blob: 56a7886f930ffbb066a3d53a2fa603f32bcf8b4c [file] [log] [blame]
John Reckacb6f072014-03-12 16:11:23 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Chris Craikb49f4462014-03-20 12:44:20 -070016#ifndef RENDERNODEPROPERTIES_H
17#define RENDERNODEPROPERTIES_H
John Reckacb6f072014-03-12 16:11:23 -070018
John Recke45b1fd2014-04-15 09:50:16 -070019#include <algorithm>
John Reckacb6f072014-03-12 16:11:23 -070020#include <stddef.h>
John Recke45b1fd2014-04-15 09:50:16 -070021#include <vector>
John Reckacb6f072014-03-12 16:11:23 -070022#include <cutils/compiler.h>
23#include <androidfw/ResourceTypes.h>
Chris Craikfe02b4b2014-06-16 16:34:29 -070024#include <utils/Log.h>
John Reckacb6f072014-03-12 16:11:23 -070025
26#include <SkCamera.h>
27#include <SkMatrix.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070028#include <SkRegion.h>
Tom Hudson2dc236b2014-10-15 15:46:42 -040029#include <SkXfermode.h>
Chris Craikb49f4462014-03-20 12:44:20 -070030
Chris Craik4e9d9b22015-06-12 11:07:23 -070031#include "Caches.h"
Chris Craikb49f4462014-03-20 12:44:20 -070032#include "Rect.h"
Chris Craik8c271ca2014-03-25 10:33:01 -070033#include "RevealClip.h"
Chris Craikb49f4462014-03-20 12:44:20 -070034#include "Outline.h"
John Reck293e8682014-06-17 10:34:02 -070035#include "utils/MathUtils.h"
John Reckacb6f072014-03-12 16:11:23 -070036
John Reckacb6f072014-03-12 16:11:23 -070037class SkBitmap;
John Reck25fbb3f2014-06-12 13:46:45 -070038class SkColorFilter;
John Reckacb6f072014-03-12 16:11:23 -070039class SkPaint;
John Reckacb6f072014-03-12 16:11:23 -070040
41namespace android {
42namespace uirenderer {
43
44class Matrix4;
45class RenderNode;
John Reck25fbb3f2014-06-12 13:46:45 -070046class RenderProperties;
John Reckacb6f072014-03-12 16:11:23 -070047
John Reck79c7de72014-05-23 10:33:31 -070048// The __VA_ARGS__ will be executed if a & b are not equal
Chih-Hung Hsiehcef190d2016-05-19 15:25:50 -070049#define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false)
John Reck79c7de72014-05-23 10:33:31 -070050#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
51
John Reck25fbb3f2014-06-12 13:46:45 -070052// Keep in sync with View.java:LAYER_TYPE_*
Chris Craik182952f2015-03-09 14:17:29 -070053enum class LayerType {
54 None = 0,
John Reck25fbb3f2014-06-12 13:46:45 -070055 // Although we cannot build the software layer directly (must be done at
56 // record time), this information is used when applying alpha.
Chris Craik182952f2015-03-09 14:17:29 -070057 Software = 1,
58 RenderLayer = 2,
John Reck25fbb3f2014-06-12 13:46:45 -070059 // TODO: LayerTypeSurfaceTexture? Maybe?
60};
61
Chris Craika753f4c2014-07-24 12:39:17 -070062enum ClippingFlags {
63 CLIP_TO_BOUNDS = 0x1 << 0,
64 CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
65};
66
John Reck25fbb3f2014-06-12 13:46:45 -070067class ANDROID_API LayerProperties {
68public:
69 bool setType(LayerType type) {
70 if (RP_SET(mType, type)) {
71 reset();
72 return true;
73 }
74 return false;
75 }
76
John Reck25fbb3f2014-06-12 13:46:45 -070077 bool setOpaque(bool opaque) {
78 return RP_SET(mOpaque, opaque);
79 }
80
81 bool opaque() const {
82 return mOpaque;
83 }
84
85 bool setAlpha(uint8_t alpha) {
86 return RP_SET(mAlpha, alpha);
87 }
88
89 uint8_t alpha() const {
90 return mAlpha;
91 }
92
93 bool setXferMode(SkXfermode::Mode mode) {
94 return RP_SET(mMode, mode);
95 }
96
97 SkXfermode::Mode xferMode() const {
98 return mMode;
99 }
100
101 bool setColorFilter(SkColorFilter* filter);
102
103 SkColorFilter* colorFilter() const {
104 return mColorFilter;
105 }
106
107 // Sets alpha, xfermode, and colorfilter from an SkPaint
108 // paint may be NULL, in which case defaults will be set
109 bool setFromPaint(const SkPaint* paint);
110
111 bool needsBlending() const {
112 return !opaque() || alpha() < 255;
113 }
114
115 LayerProperties& operator=(const LayerProperties& other);
116
117private:
118 LayerProperties();
119 ~LayerProperties();
120 void reset();
121
Chris Craik856f0cc2015-04-21 15:13:29 -0700122 // Private since external users should go through properties().effectiveLayerType()
123 LayerType type() const {
124 return mType;
125 }
126
John Reck25fbb3f2014-06-12 13:46:45 -0700127 friend class RenderProperties;
128
Chris Craik182952f2015-03-09 14:17:29 -0700129 LayerType mType = LayerType::None;
John Reck25fbb3f2014-06-12 13:46:45 -0700130 // Whether or not that Layer's content is opaque, doesn't include alpha
131 bool mOpaque;
132 uint8_t mAlpha;
133 SkXfermode::Mode mMode;
Chris Craik182952f2015-03-09 14:17:29 -0700134 SkColorFilter* mColorFilter = nullptr;
John Reck25fbb3f2014-06-12 13:46:45 -0700135};
136
John Reckacb6f072014-03-12 16:11:23 -0700137/*
138 * Data structure that holds the properties for a RenderNode
139 */
John Reck25fbb3f2014-06-12 13:46:45 -0700140class ANDROID_API RenderProperties {
John Reckacb6f072014-03-12 16:11:23 -0700141public:
142 RenderProperties();
143 virtual ~RenderProperties();
144
Chris Craika753f4c2014-07-24 12:39:17 -0700145 static bool setFlag(int flag, bool newValue, int* outFlags) {
146 if (newValue) {
147 if (!(flag & *outFlags)) {
148 *outFlags |= flag;
149 return true;
150 }
151 return false;
152 } else {
153 if (flag & *outFlags) {
154 *outFlags &= ~flag;
155 return true;
156 }
157 return false;
158 }
159 }
160
Chris Craika766cb22015-06-08 16:49:43 -0700161 /**
162 * Set internal layer state based on whether this layer
163 *
164 * Additionally, returns true if child RenderNodes with functors will need to use a layer
165 * to support clipping.
166 */
167 bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
168 // parent may have already dictated that a descendant layer is needed
169 bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
170
171 // Round rect clipping forces layer for functors
Chris Craikb60d3e72015-06-25 17:15:16 -0700172 || CC_UNLIKELY(getOutline().willRoundRectClip())
Chris Craika766cb22015-06-08 16:49:43 -0700173 || CC_UNLIKELY(getRevealClip().willClip())
174
175 // Complex matrices forces layer, due to stencil clipping
176 || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
177 || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
178 || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
179
180 mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
181
182 // If on a layer, will have consumed the need for isolating functors from stencil.
183 // Thus, it's safe to reset the flag until some descendent sets it.
184 return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
185 }
186
John Reckd0a0b2a2014-03-20 16:28:56 -0700187 RenderProperties& operator=(const RenderProperties& other);
188
John Reck79c7de72014-05-23 10:33:31 -0700189 bool setClipToBounds(bool clipToBounds) {
Chris Craika753f4c2014-07-24 12:39:17 -0700190 return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
191 }
192
193 bool setClipBounds(const Rect& clipBounds) {
194 bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
195 return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
196 }
197
198 bool setClipBoundsEmpty() {
199 return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
John Reckacb6f072014-03-12 16:11:23 -0700200 }
201
John Reck79c7de72014-05-23 10:33:31 -0700202 bool setProjectBackwards(bool shouldProject) {
203 return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
John Reckacb6f072014-03-12 16:11:23 -0700204 }
205
John Reck79c7de72014-05-23 10:33:31 -0700206 bool setProjectionReceiver(bool shouldRecieve) {
207 return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldRecieve);
John Reckacb6f072014-03-12 16:11:23 -0700208 }
209
John Reckd0a0b2a2014-03-20 16:28:56 -0700210 bool isProjectionReceiver() const {
211 return mPrimitiveFields.mProjectionReceiver;
John Reckacb6f072014-03-12 16:11:23 -0700212 }
213
John Reck79c7de72014-05-23 10:33:31 -0700214 bool setStaticMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700215 delete mStaticMatrix;
John Reckd0a0b2a2014-03-20 16:28:56 -0700216 if (matrix) {
217 mStaticMatrix = new SkMatrix(*matrix);
218 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800219 mStaticMatrix = nullptr;
John Reckd0a0b2a2014-03-20 16:28:56 -0700220 }
John Reck79c7de72014-05-23 10:33:31 -0700221 return true;
John Reckacb6f072014-03-12 16:11:23 -0700222 }
223
224 // Can return NULL
John Reckd0a0b2a2014-03-20 16:28:56 -0700225 const SkMatrix* getStaticMatrix() const {
John Reckacb6f072014-03-12 16:11:23 -0700226 return mStaticMatrix;
227 }
228
John Reck79c7de72014-05-23 10:33:31 -0700229 bool setAnimationMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700230 delete mAnimationMatrix;
231 if (matrix) {
232 mAnimationMatrix = new SkMatrix(*matrix);
233 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800234 mAnimationMatrix = nullptr;
John Reckacb6f072014-03-12 16:11:23 -0700235 }
John Reck79c7de72014-05-23 10:33:31 -0700236 return true;
John Reckacb6f072014-03-12 16:11:23 -0700237 }
238
John Reck79c7de72014-05-23 10:33:31 -0700239 bool setAlpha(float alpha) {
John Reck3b52c032014-08-06 10:19:32 -0700240 alpha = MathUtils::clampAlpha(alpha);
John Reck79c7de72014-05-23 10:33:31 -0700241 return RP_SET(mPrimitiveFields.mAlpha, alpha);
John Reckacb6f072014-03-12 16:11:23 -0700242 }
243
244 float getAlpha() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700245 return mPrimitiveFields.mAlpha;
John Reckacb6f072014-03-12 16:11:23 -0700246 }
247
John Reck79c7de72014-05-23 10:33:31 -0700248 bool setHasOverlappingRendering(bool hasOverlappingRendering) {
249 return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
John Reckacb6f072014-03-12 16:11:23 -0700250 }
251
252 bool hasOverlappingRendering() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700253 return mPrimitiveFields.mHasOverlappingRendering;
John Reckacb6f072014-03-12 16:11:23 -0700254 }
255
John Reck79c7de72014-05-23 10:33:31 -0700256 bool setElevation(float elevation) {
257 return RP_SET(mPrimitiveFields.mElevation, elevation);
258 // Don't dirty matrix/pivot, since they don't respect Z
Chris Craikcc39e162014-04-25 18:34:11 -0700259 }
260
261 float getElevation() const {
262 return mPrimitiveFields.mElevation;
263 }
264
John Reck79c7de72014-05-23 10:33:31 -0700265 bool setTranslationX(float translationX) {
266 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
John Reckacb6f072014-03-12 16:11:23 -0700267 }
268
269 float getTranslationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700270 return mPrimitiveFields.mTranslationX;
John Reckacb6f072014-03-12 16:11:23 -0700271 }
272
John Reck79c7de72014-05-23 10:33:31 -0700273 bool setTranslationY(float translationY) {
274 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
John Reckacb6f072014-03-12 16:11:23 -0700275 }
276
277 float getTranslationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700278 return mPrimitiveFields.mTranslationY;
John Reckacb6f072014-03-12 16:11:23 -0700279 }
280
John Reck79c7de72014-05-23 10:33:31 -0700281 bool setTranslationZ(float translationZ) {
282 return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
283 // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
John Reckacb6f072014-03-12 16:11:23 -0700284 }
285
286 float getTranslationZ() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700287 return mPrimitiveFields.mTranslationZ;
John Reckacb6f072014-03-12 16:11:23 -0700288 }
289
John Recke45b1fd2014-04-15 09:50:16 -0700290 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700291 bool setX(float value) {
292 return setTranslationX(value - getLeft());
John Recke45b1fd2014-04-15 09:50:16 -0700293 }
294
295 // Animation helper
296 float getX() const {
297 return getLeft() + getTranslationX();
298 }
299
300 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700301 bool setY(float value) {
302 return setTranslationY(value - getTop());
John Recke45b1fd2014-04-15 09:50:16 -0700303 }
304
305 // Animation helper
306 float getY() const {
307 return getTop() + getTranslationY();
308 }
309
310 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700311 bool setZ(float value) {
312 return setTranslationZ(value - getElevation());
John Recke45b1fd2014-04-15 09:50:16 -0700313 }
314
Chris Craikcc39e162014-04-25 18:34:11 -0700315 float getZ() const {
316 return getElevation() + getTranslationZ();
317 }
318
John Reck79c7de72014-05-23 10:33:31 -0700319 bool setRotation(float rotation) {
320 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
John Reckacb6f072014-03-12 16:11:23 -0700321 }
322
323 float getRotation() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700324 return mPrimitiveFields.mRotation;
John Reckacb6f072014-03-12 16:11:23 -0700325 }
326
John Reck79c7de72014-05-23 10:33:31 -0700327 bool setRotationX(float rotationX) {
328 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
John Reckacb6f072014-03-12 16:11:23 -0700329 }
330
331 float getRotationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700332 return mPrimitiveFields.mRotationX;
John Reckacb6f072014-03-12 16:11:23 -0700333 }
334
John Reck79c7de72014-05-23 10:33:31 -0700335 bool setRotationY(float rotationY) {
336 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
John Reckacb6f072014-03-12 16:11:23 -0700337 }
338
339 float getRotationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700340 return mPrimitiveFields.mRotationY;
John Reckacb6f072014-03-12 16:11:23 -0700341 }
342
John Reck79c7de72014-05-23 10:33:31 -0700343 bool setScaleX(float scaleX) {
344 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
John Reckacb6f072014-03-12 16:11:23 -0700345 }
346
347 float getScaleX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700348 return mPrimitiveFields.mScaleX;
John Reckacb6f072014-03-12 16:11:23 -0700349 }
350
John Reck79c7de72014-05-23 10:33:31 -0700351 bool setScaleY(float scaleY) {
352 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
John Reckacb6f072014-03-12 16:11:23 -0700353 }
354
355 float getScaleY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700356 return mPrimitiveFields.mScaleY;
John Reckacb6f072014-03-12 16:11:23 -0700357 }
358
John Reck79c7de72014-05-23 10:33:31 -0700359 bool setPivotX(float pivotX) {
360 if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
361 || !mPrimitiveFields.mPivotExplicitlySet) {
362 mPrimitiveFields.mMatrixOrPivotDirty = true;
363 mPrimitiveFields.mPivotExplicitlySet = true;
364 return true;
365 }
366 return false;
John Reckacb6f072014-03-12 16:11:23 -0700367 }
368
John Reckd0a0b2a2014-03-20 16:28:56 -0700369 /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
John Reck79c7de72014-05-23 10:33:31 -0700370 * so the value returned may be stale if the RenderProperties has been
371 * modified since the last call to updateMatrix()
John Reckd0a0b2a2014-03-20 16:28:56 -0700372 */
373 float getPivotX() const {
374 return mPrimitiveFields.mPivotX;
375 }
John Reckacb6f072014-03-12 16:11:23 -0700376
John Reck79c7de72014-05-23 10:33:31 -0700377 bool setPivotY(float pivotY) {
378 if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
379 || !mPrimitiveFields.mPivotExplicitlySet) {
380 mPrimitiveFields.mMatrixOrPivotDirty = true;
381 mPrimitiveFields.mPivotExplicitlySet = true;
382 return true;
383 }
384 return false;
John Reckacb6f072014-03-12 16:11:23 -0700385 }
386
John Reckd0a0b2a2014-03-20 16:28:56 -0700387 float getPivotY() const {
388 return mPrimitiveFields.mPivotY;
389 }
John Reckacb6f072014-03-12 16:11:23 -0700390
Chris Craik49e6c732014-03-31 12:34:11 -0700391 bool isPivotExplicitlySet() const {
392 return mPrimitiveFields.mPivotExplicitlySet;
393 }
394
John Reck79c7de72014-05-23 10:33:31 -0700395 bool setCameraDistance(float distance) {
Chris Craik49e6c732014-03-31 12:34:11 -0700396 if (distance != getCameraDistance()) {
John Reckf7483e32014-04-11 08:54:47 -0700397 mPrimitiveFields.mMatrixOrPivotDirty = true;
Chris Craik49e6c732014-03-31 12:34:11 -0700398 mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
John Reck79c7de72014-05-23 10:33:31 -0700399 return true;
John Reckacb6f072014-03-12 16:11:23 -0700400 }
John Reck79c7de72014-05-23 10:33:31 -0700401 return false;
John Reckacb6f072014-03-12 16:11:23 -0700402 }
403
404 float getCameraDistance() const {
Chris Craik49e6c732014-03-31 12:34:11 -0700405 // TODO: update getCameraLocationZ() to be const
406 return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
John Reckacb6f072014-03-12 16:11:23 -0700407 }
408
John Reck79c7de72014-05-23 10:33:31 -0700409 bool setLeft(int left) {
410 if (RP_SET(mPrimitiveFields.mLeft, left)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700411 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700412 if (!mPrimitiveFields.mPivotExplicitlySet) {
413 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700414 }
John Reck79c7de72014-05-23 10:33:31 -0700415 return true;
John Reckacb6f072014-03-12 16:11:23 -0700416 }
John Reck79c7de72014-05-23 10:33:31 -0700417 return false;
John Reckacb6f072014-03-12 16:11:23 -0700418 }
419
420 float getLeft() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700421 return mPrimitiveFields.mLeft;
John Reckacb6f072014-03-12 16:11:23 -0700422 }
423
John Reck79c7de72014-05-23 10:33:31 -0700424 bool setTop(int top) {
425 if (RP_SET(mPrimitiveFields.mTop, top)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700426 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700427 if (!mPrimitiveFields.mPivotExplicitlySet) {
428 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700429 }
John Reck79c7de72014-05-23 10:33:31 -0700430 return true;
John Reckacb6f072014-03-12 16:11:23 -0700431 }
John Reck79c7de72014-05-23 10:33:31 -0700432 return false;
John Reckacb6f072014-03-12 16:11:23 -0700433 }
434
435 float getTop() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700436 return mPrimitiveFields.mTop;
John Reckacb6f072014-03-12 16:11:23 -0700437 }
438
John Reck79c7de72014-05-23 10:33:31 -0700439 bool setRight(int right) {
440 if (RP_SET(mPrimitiveFields.mRight, right)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700441 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700442 if (!mPrimitiveFields.mPivotExplicitlySet) {
443 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700444 }
John Reck79c7de72014-05-23 10:33:31 -0700445 return true;
John Reckacb6f072014-03-12 16:11:23 -0700446 }
John Reck79c7de72014-05-23 10:33:31 -0700447 return false;
John Reckacb6f072014-03-12 16:11:23 -0700448 }
449
450 float getRight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700451 return mPrimitiveFields.mRight;
John Reckacb6f072014-03-12 16:11:23 -0700452 }
453
John Reck79c7de72014-05-23 10:33:31 -0700454 bool setBottom(int bottom) {
455 if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700456 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700457 if (!mPrimitiveFields.mPivotExplicitlySet) {
458 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700459 }
John Reck79c7de72014-05-23 10:33:31 -0700460 return true;
John Reckacb6f072014-03-12 16:11:23 -0700461 }
John Reck79c7de72014-05-23 10:33:31 -0700462 return false;
John Reckacb6f072014-03-12 16:11:23 -0700463 }
464
465 float getBottom() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700466 return mPrimitiveFields.mBottom;
John Reckacb6f072014-03-12 16:11:23 -0700467 }
468
John Reck79c7de72014-05-23 10:33:31 -0700469 bool setLeftTop(int left, int top) {
470 bool leftResult = setLeft(left);
471 bool topResult = setTop(top);
472 return leftResult || topResult;
John Reckacb6f072014-03-12 16:11:23 -0700473 }
474
John Reck79c7de72014-05-23 10:33:31 -0700475 bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
Chris Craikcc39e162014-04-25 18:34:11 -0700476 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
477 || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700478 mPrimitiveFields.mLeft = left;
479 mPrimitiveFields.mTop = top;
480 mPrimitiveFields.mRight = right;
481 mPrimitiveFields.mBottom = bottom;
482 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
483 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700484 if (!mPrimitiveFields.mPivotExplicitlySet) {
485 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700486 }
John Reck79c7de72014-05-23 10:33:31 -0700487 return true;
John Reckacb6f072014-03-12 16:11:23 -0700488 }
John Reck79c7de72014-05-23 10:33:31 -0700489 return false;
John Reckacb6f072014-03-12 16:11:23 -0700490 }
491
Chris Craika753f4c2014-07-24 12:39:17 -0700492 bool offsetLeftRight(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700493 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700494 mPrimitiveFields.mLeft += offset;
495 mPrimitiveFields.mRight += offset;
John Reck79c7de72014-05-23 10:33:31 -0700496 return true;
John Reckacb6f072014-03-12 16:11:23 -0700497 }
John Reck79c7de72014-05-23 10:33:31 -0700498 return false;
John Reckacb6f072014-03-12 16:11:23 -0700499 }
500
Chris Craika753f4c2014-07-24 12:39:17 -0700501 bool offsetTopBottom(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700502 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700503 mPrimitiveFields.mTop += offset;
504 mPrimitiveFields.mBottom += offset;
John Reck79c7de72014-05-23 10:33:31 -0700505 return true;
John Reckacb6f072014-03-12 16:11:23 -0700506 }
John Reck79c7de72014-05-23 10:33:31 -0700507 return false;
John Reckacb6f072014-03-12 16:11:23 -0700508 }
509
Chris Craikb49f4462014-03-20 12:44:20 -0700510 int getWidth() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700511 return mPrimitiveFields.mWidth;
John Reckacb6f072014-03-12 16:11:23 -0700512 }
513
Chris Craikb49f4462014-03-20 12:44:20 -0700514 int getHeight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700515 return mPrimitiveFields.mHeight;
John Reckacb6f072014-03-12 16:11:23 -0700516 }
517
John Reckd0a0b2a2014-03-20 16:28:56 -0700518 const SkMatrix* getAnimationMatrix() const {
519 return mAnimationMatrix;
520 }
521
John Reckf7483e32014-04-11 08:54:47 -0700522 bool hasTransformMatrix() const {
523 return getTransformMatrix() && !getTransformMatrix()->isIdentity();
524 }
525
526 // May only call this if hasTransformMatrix() is true
527 bool isTransformTranslateOnly() const {
528 return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
John Reckd0a0b2a2014-03-20 16:28:56 -0700529 }
530
Chris Craik49e6c732014-03-31 12:34:11 -0700531 const SkMatrix* getTransformMatrix() const {
John Reckf7483e32014-04-11 08:54:47 -0700532 LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
John Reckd0a0b2a2014-03-20 16:28:56 -0700533 return mComputedFields.mTransformMatrix;
534 }
535
Chris Craika753f4c2014-07-24 12:39:17 -0700536 int getClippingFlags() const {
537 return mPrimitiveFields.mClippingFlags;
538 }
539
John Reckd0a0b2a2014-03-20 16:28:56 -0700540 bool getClipToBounds() const {
Chris Craika753f4c2014-07-24 12:39:17 -0700541 return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
542 }
543
544 void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
545 if (flags & CLIP_TO_BOUNDS) {
546 outRect->set(0, 0, getWidth(), getHeight());
547 if (flags & CLIP_TO_CLIP_BOUNDS) {
548 outRect->intersect(mPrimitiveFields.mClipBounds);
549 }
550 } else {
551 outRect->set(mPrimitiveFields.mClipBounds);
552 }
John Reckd0a0b2a2014-03-20 16:28:56 -0700553 }
554
555 bool getHasOverlappingRendering() const {
556 return mPrimitiveFields.mHasOverlappingRendering;
557 }
558
559 const Outline& getOutline() const {
560 return mPrimitiveFields.mOutline;
561 }
562
Chris Craik8c271ca2014-03-25 10:33:01 -0700563 const RevealClip& getRevealClip() const {
564 return mPrimitiveFields.mRevealClip;
565 }
566
John Reckd0a0b2a2014-03-20 16:28:56 -0700567 bool getProjectBackwards() const {
568 return mPrimitiveFields.mProjectBackwards;
569 }
570
571 void debugOutputProperties(const int level) const;
572
John Reck25fbb3f2014-06-12 13:46:45 -0700573 void updateMatrix();
John Reckd0a0b2a2014-03-20 16:28:56 -0700574
575 Outline& mutableOutline() {
576 return mPrimitiveFields.mOutline;
Chris Craikb49f4462014-03-20 12:44:20 -0700577 }
578
Chris Craik8c271ca2014-03-25 10:33:01 -0700579 RevealClip& mutableRevealClip() {
580 return mPrimitiveFields.mRevealClip;
581 }
582
John Reck25fbb3f2014-06-12 13:46:45 -0700583 const LayerProperties& layerProperties() const {
584 return mLayerProperties;
585 }
586
587 LayerProperties& mutateLayerProperties() {
588 return mLayerProperties;
589 }
590
John Reck293e8682014-06-17 10:34:02 -0700591 // Returns true if damage calculations should be clipped to bounds
592 // TODO: Figure out something better for getZ(), as children should still be
593 // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
594 // for this RP's getZ() anyway, this can be optimized when we have a
595 // Z damage estimate instead of INT_MAX
596 bool getClipDamageToBounds() const {
597 return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
598 }
599
Chris Craik5c75c522014-09-05 14:08:08 -0700600 bool hasShadow() const {
Chris Craikb5a54352014-11-21 14:54:35 -0800601 return getZ() > 0.0f
Chris Craike84a2082014-12-22 14:28:49 -0800602 && getOutline().getPath() != nullptr
Chris Craik9fa364d2014-09-19 16:04:45 -0700603 && getOutline().getAlpha() != 0.0f;
Chris Craik5c75c522014-09-05 14:08:08 -0700604 }
605
Chris Craik1a0808e2015-05-13 16:33:04 -0700606 bool promotedToLayer() const {
Chris Craik4e9d9b22015-06-12 11:07:23 -0700607 const int maxTextureSize = Caches::getInstance().maxTextureSize;
Chris Craik1a0808e2015-05-13 16:33:04 -0700608 return mLayerProperties.mType == LayerType::None
Chris Craik4e9d9b22015-06-12 11:07:23 -0700609 && mPrimitiveFields.mWidth <= maxTextureSize
Chris Craika766cb22015-06-08 16:49:43 -0700610 && mPrimitiveFields.mHeight <= maxTextureSize
611 && (mComputedFields.mNeedLayerForFunctors
612 || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
613 && mPrimitiveFields.mAlpha < 1
614 && mPrimitiveFields.mHasOverlappingRendering));
Chris Craik1a0808e2015-05-13 16:33:04 -0700615 }
616
617 LayerType effectiveLayerType() const {
Chris Craika766cb22015-06-08 16:49:43 -0700618 return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
Chris Craik856f0cc2015-04-21 15:13:29 -0700619 }
620
John Reckacb6f072014-03-12 16:11:23 -0700621private:
John Reckacb6f072014-03-12 16:11:23 -0700622 // Rendering properties
John Reckd0a0b2a2014-03-20 16:28:56 -0700623 struct PrimitiveFields {
624 PrimitiveFields();
John Reckacb6f072014-03-12 16:11:23 -0700625
John Reckd0a0b2a2014-03-20 16:28:56 -0700626 Outline mOutline;
Chris Craik8c271ca2014-03-25 10:33:01 -0700627 RevealClip mRevealClip;
Chris Craika753f4c2014-07-24 12:39:17 -0700628 int mClippingFlags;
John Reckd0a0b2a2014-03-20 16:28:56 -0700629 bool mProjectBackwards;
630 bool mProjectionReceiver;
631 float mAlpha;
632 bool mHasOverlappingRendering;
Chris Craikcc39e162014-04-25 18:34:11 -0700633 float mElevation;
John Reckd0a0b2a2014-03-20 16:28:56 -0700634 float mTranslationX, mTranslationY, mTranslationZ;
635 float mRotation, mRotationX, mRotationY;
636 float mScaleX, mScaleY;
637 float mPivotX, mPivotY;
638 int mLeft, mTop, mRight, mBottom;
639 int mWidth, mHeight;
John Reckd0a0b2a2014-03-20 16:28:56 -0700640 bool mPivotExplicitlySet;
John Reckf7483e32014-04-11 08:54:47 -0700641 bool mMatrixOrPivotDirty;
Chris Craika753f4c2014-07-24 12:39:17 -0700642 Rect mClipBounds;
John Reckd0a0b2a2014-03-20 16:28:56 -0700643 } mPrimitiveFields;
644
John Reckacb6f072014-03-12 16:11:23 -0700645 SkMatrix* mStaticMatrix;
646 SkMatrix* mAnimationMatrix;
John Reck25fbb3f2014-06-12 13:46:45 -0700647 LayerProperties mLayerProperties;
John Reckacb6f072014-03-12 16:11:23 -0700648
John Reckd0a0b2a2014-03-20 16:28:56 -0700649 /**
650 * These fields are all generated from other properties and are not set directly.
651 */
652 struct ComputedFields {
653 ComputedFields();
654 ~ComputedFields();
655
656 /**
657 * Stores the total transformation of the DisplayList based upon its scalar
658 * translate/rotate/scale properties.
659 *
Chris Craik49e6c732014-03-31 12:34:11 -0700660 * In the common translation-only case, the matrix isn't necessarily allocated,
661 * and the mTranslation properties are used directly.
John Reckd0a0b2a2014-03-20 16:28:56 -0700662 */
Chris Craik49e6c732014-03-31 12:34:11 -0700663 SkMatrix* mTransformMatrix;
664
665 Sk3DView mTransformCamera;
Chris Craika766cb22015-06-08 16:49:43 -0700666
667 // Force layer on for functors to enable render features they don't yet support (clipping)
668 bool mNeedLayerForFunctors = false;
John Reckd0a0b2a2014-03-20 16:28:56 -0700669 } mComputedFields;
John Reckacb6f072014-03-12 16:11:23 -0700670};
671
672} /* namespace uirenderer */
673} /* namespace android */
674
Chris Craikb49f4462014-03-20 12:44:20 -0700675#endif /* RENDERNODEPROPERTIES_H */