blob: abef806a69750fcb7a2b004a3ccbcdaf89a155fe [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
49#define RP_SET(a, b, ...) (a != b ? (a = b, ##__VA_ARGS__, true) : false)
50#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
Chris Craik6fe991e52015-10-20 09:39:42 -0700206 bool setProjectionReceiver(bool shouldReceive) {
207 return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
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
John Recke248bd12015-08-05 13:53:53 -0700420 int 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
John Recke248bd12015-08-05 13:53:53 -0700435 int 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
John Recke248bd12015-08-05 13:53:53 -0700450 int 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
John Recke248bd12015-08-05 13:53:53 -0700465 int 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
John Recke248bd12015-08-05 13:53:53 -0700544 const Rect& getClipBounds() const {
545 return mPrimitiveFields.mClipBounds;
546 }
547
Chris Craika753f4c2014-07-24 12:39:17 -0700548 void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
549 if (flags & CLIP_TO_BOUNDS) {
550 outRect->set(0, 0, getWidth(), getHeight());
551 if (flags & CLIP_TO_CLIP_BOUNDS) {
Chris Craikac02eb92015-10-05 12:23:46 -0700552 outRect->doIntersect(mPrimitiveFields.mClipBounds);
Chris Craika753f4c2014-07-24 12:39:17 -0700553 }
554 } else {
555 outRect->set(mPrimitiveFields.mClipBounds);
556 }
John Reckd0a0b2a2014-03-20 16:28:56 -0700557 }
558
559 bool getHasOverlappingRendering() const {
560 return mPrimitiveFields.mHasOverlappingRendering;
561 }
562
563 const Outline& getOutline() const {
564 return mPrimitiveFields.mOutline;
565 }
566
Chris Craik8c271ca2014-03-25 10:33:01 -0700567 const RevealClip& getRevealClip() const {
568 return mPrimitiveFields.mRevealClip;
569 }
570
John Reckd0a0b2a2014-03-20 16:28:56 -0700571 bool getProjectBackwards() const {
572 return mPrimitiveFields.mProjectBackwards;
573 }
574
575 void debugOutputProperties(const int level) const;
576
John Reck25fbb3f2014-06-12 13:46:45 -0700577 void updateMatrix();
John Reckd0a0b2a2014-03-20 16:28:56 -0700578
579 Outline& mutableOutline() {
580 return mPrimitiveFields.mOutline;
Chris Craikb49f4462014-03-20 12:44:20 -0700581 }
582
Chris Craik8c271ca2014-03-25 10:33:01 -0700583 RevealClip& mutableRevealClip() {
584 return mPrimitiveFields.mRevealClip;
585 }
586
John Reck25fbb3f2014-06-12 13:46:45 -0700587 const LayerProperties& layerProperties() const {
588 return mLayerProperties;
589 }
590
591 LayerProperties& mutateLayerProperties() {
592 return mLayerProperties;
593 }
594
John Reck293e8682014-06-17 10:34:02 -0700595 // Returns true if damage calculations should be clipped to bounds
596 // TODO: Figure out something better for getZ(), as children should still be
597 // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
598 // for this RP's getZ() anyway, this can be optimized when we have a
599 // Z damage estimate instead of INT_MAX
600 bool getClipDamageToBounds() const {
601 return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
602 }
603
Chris Craik5c75c522014-09-05 14:08:08 -0700604 bool hasShadow() const {
Chris Craikb5a54352014-11-21 14:54:35 -0800605 return getZ() > 0.0f
Chris Craike84a2082014-12-22 14:28:49 -0800606 && getOutline().getPath() != nullptr
Chris Craik9fa364d2014-09-19 16:04:45 -0700607 && getOutline().getAlpha() != 0.0f;
Chris Craik5c75c522014-09-05 14:08:08 -0700608 }
609
Chris Craik1a0808e2015-05-13 16:33:04 -0700610 bool promotedToLayer() const {
Chris Craik4e9d9b22015-06-12 11:07:23 -0700611 const int maxTextureSize = Caches::getInstance().maxTextureSize;
Chris Craik1a0808e2015-05-13 16:33:04 -0700612 return mLayerProperties.mType == LayerType::None
Chris Craik4e9d9b22015-06-12 11:07:23 -0700613 && mPrimitiveFields.mWidth <= maxTextureSize
Chris Craika766cb22015-06-08 16:49:43 -0700614 && mPrimitiveFields.mHeight <= maxTextureSize
615 && (mComputedFields.mNeedLayerForFunctors
616 || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
617 && mPrimitiveFields.mAlpha < 1
618 && mPrimitiveFields.mHasOverlappingRendering));
Chris Craik1a0808e2015-05-13 16:33:04 -0700619 }
620
621 LayerType effectiveLayerType() const {
Chris Craika766cb22015-06-08 16:49:43 -0700622 return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
Chris Craik856f0cc2015-04-21 15:13:29 -0700623 }
624
John Reckacb6f072014-03-12 16:11:23 -0700625private:
John Reckacb6f072014-03-12 16:11:23 -0700626 // Rendering properties
John Reckd0a0b2a2014-03-20 16:28:56 -0700627 struct PrimitiveFields {
John Recke248bd12015-08-05 13:53:53 -0700628 int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
629 int mWidth = 0, mHeight = 0;
630 int mClippingFlags = CLIP_TO_BOUNDS;
631 float mAlpha = 1;
632 float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
633 float mElevation = 0;
634 float mRotation = 0, mRotationX = 0, mRotationY = 0;
635 float mScaleX = 1, mScaleY = 1;
636 float mPivotX = 0, mPivotY = 0;
637 bool mHasOverlappingRendering = false;
638 bool mPivotExplicitlySet = false;
639 bool mMatrixOrPivotDirty = false;
640 bool mProjectBackwards = false;
641 bool mProjectionReceiver = false;
642 Rect mClipBounds;
John Reckd0a0b2a2014-03-20 16:28:56 -0700643 Outline mOutline;
Chris Craik8c271ca2014-03-25 10:33:01 -0700644 RevealClip mRevealClip;
John Reckd0a0b2a2014-03-20 16:28:56 -0700645 } mPrimitiveFields;
646
John Reckacb6f072014-03-12 16:11:23 -0700647 SkMatrix* mStaticMatrix;
648 SkMatrix* mAnimationMatrix;
John Reck25fbb3f2014-06-12 13:46:45 -0700649 LayerProperties mLayerProperties;
John Reckacb6f072014-03-12 16:11:23 -0700650
John Reckd0a0b2a2014-03-20 16:28:56 -0700651 /**
652 * These fields are all generated from other properties and are not set directly.
653 */
654 struct ComputedFields {
655 ComputedFields();
656 ~ComputedFields();
657
658 /**
659 * Stores the total transformation of the DisplayList based upon its scalar
660 * translate/rotate/scale properties.
661 *
Chris Craik49e6c732014-03-31 12:34:11 -0700662 * In the common translation-only case, the matrix isn't necessarily allocated,
663 * and the mTranslation properties are used directly.
John Reckd0a0b2a2014-03-20 16:28:56 -0700664 */
Chris Craik49e6c732014-03-31 12:34:11 -0700665 SkMatrix* mTransformMatrix;
666
667 Sk3DView mTransformCamera;
Chris Craika766cb22015-06-08 16:49:43 -0700668
669 // Force layer on for functors to enable render features they don't yet support (clipping)
670 bool mNeedLayerForFunctors = false;
John Reckd0a0b2a2014-03-20 16:28:56 -0700671 } mComputedFields;
John Reckacb6f072014-03-12 16:11:23 -0700672};
673
674} /* namespace uirenderer */
675} /* namespace android */
676
Chris Craikb49f4462014-03-20 12:44:20 -0700677#endif /* RENDERNODEPROPERTIES_H */