blob: 2a2e4c765c83960a7cac74ba54fca479a271533c [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 Craik5e00c7c2016-07-06 16:10:09 -070016
17#pragma once
John Reckacb6f072014-03-12 16:11:23 -070018
Chris Craik76caecf2015-11-02 19:17:45 -080019#include "Caches.h"
20#include "DeviceInfo.h"
21#include "Rect.h"
22#include "RevealClip.h"
23#include "Outline.h"
24#include "utils/MathUtils.h"
Chris Craik5e00c7c2016-07-06 16:10:09 -070025#include "utils/PaintUtils.h"
John Reckacb6f072014-03-12 16:11:23 -070026
27#include <SkCamera.h>
28#include <SkMatrix.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070029#include <SkRegion.h>
Tom Hudson2dc236b2014-10-15 15:46:42 -040030#include <SkXfermode.h>
Chris Craikb49f4462014-03-20 12:44:20 -070031
Chris Craik76caecf2015-11-02 19:17:45 -080032#include <algorithm>
33#include <stddef.h>
34#include <vector>
35#include <cutils/compiler.h>
36#include <androidfw/ResourceTypes.h>
37#include <utils/Log.h>
John Reckacb6f072014-03-12 16:11:23 -070038
John Reckacb6f072014-03-12 16:11:23 -070039class SkBitmap;
John Reck25fbb3f2014-06-12 13:46:45 -070040class SkColorFilter;
John Reckacb6f072014-03-12 16:11:23 -070041class SkPaint;
John Reckacb6f072014-03-12 16:11:23 -070042
43namespace android {
44namespace uirenderer {
45
46class Matrix4;
47class RenderNode;
John Reck25fbb3f2014-06-12 13:46:45 -070048class RenderProperties;
John Reckacb6f072014-03-12 16:11:23 -070049
John Reck79c7de72014-05-23 10:33:31 -070050// The __VA_ARGS__ will be executed if a & b are not equal
Chih-Hung Hsiehcef190d2016-05-19 15:25:50 -070051#define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false)
John Reck79c7de72014-05-23 10:33:31 -070052#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
53
John Reck25fbb3f2014-06-12 13:46:45 -070054// Keep in sync with View.java:LAYER_TYPE_*
Chris Craik182952f2015-03-09 14:17:29 -070055enum class LayerType {
56 None = 0,
John Reck25fbb3f2014-06-12 13:46:45 -070057 // Although we cannot build the software layer directly (must be done at
58 // record time), this information is used when applying alpha.
Chris Craik182952f2015-03-09 14:17:29 -070059 Software = 1,
60 RenderLayer = 2,
John Reck25fbb3f2014-06-12 13:46:45 -070061 // TODO: LayerTypeSurfaceTexture? Maybe?
62};
63
Chris Craika753f4c2014-07-24 12:39:17 -070064enum ClippingFlags {
65 CLIP_TO_BOUNDS = 0x1 << 0,
66 CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
67};
68
John Reck25fbb3f2014-06-12 13:46:45 -070069class ANDROID_API LayerProperties {
70public:
71 bool setType(LayerType type) {
72 if (RP_SET(mType, type)) {
73 reset();
74 return true;
75 }
76 return false;
77 }
78
John Reck25fbb3f2014-06-12 13:46:45 -070079 bool setOpaque(bool opaque) {
80 return RP_SET(mOpaque, opaque);
81 }
82
83 bool opaque() const {
84 return mOpaque;
85 }
86
87 bool setAlpha(uint8_t alpha) {
88 return RP_SET(mAlpha, alpha);
89 }
90
91 uint8_t alpha() const {
92 return mAlpha;
93 }
94
95 bool setXferMode(SkXfermode::Mode mode) {
96 return RP_SET(mMode, mode);
97 }
98
99 SkXfermode::Mode xferMode() const {
100 return mMode;
101 }
102
103 bool setColorFilter(SkColorFilter* filter);
104
105 SkColorFilter* colorFilter() const {
106 return mColorFilter;
107 }
108
109 // Sets alpha, xfermode, and colorfilter from an SkPaint
110 // paint may be NULL, in which case defaults will be set
111 bool setFromPaint(const SkPaint* paint);
112
113 bool needsBlending() const {
114 return !opaque() || alpha() < 255;
115 }
116
117 LayerProperties& operator=(const LayerProperties& other);
118
119private:
120 LayerProperties();
121 ~LayerProperties();
122 void reset();
123
Chris Craik856f0cc2015-04-21 15:13:29 -0700124 // Private since external users should go through properties().effectiveLayerType()
125 LayerType type() const {
126 return mType;
127 }
128
John Reck25fbb3f2014-06-12 13:46:45 -0700129 friend class RenderProperties;
130
Chris Craik182952f2015-03-09 14:17:29 -0700131 LayerType mType = LayerType::None;
John Reck25fbb3f2014-06-12 13:46:45 -0700132 // Whether or not that Layer's content is opaque, doesn't include alpha
133 bool mOpaque;
134 uint8_t mAlpha;
135 SkXfermode::Mode mMode;
Chris Craik182952f2015-03-09 14:17:29 -0700136 SkColorFilter* mColorFilter = nullptr;
John Reck25fbb3f2014-06-12 13:46:45 -0700137};
138
John Reckacb6f072014-03-12 16:11:23 -0700139/*
140 * Data structure that holds the properties for a RenderNode
141 */
John Reck25fbb3f2014-06-12 13:46:45 -0700142class ANDROID_API RenderProperties {
John Reckacb6f072014-03-12 16:11:23 -0700143public:
144 RenderProperties();
145 virtual ~RenderProperties();
146
Chris Craika753f4c2014-07-24 12:39:17 -0700147 static bool setFlag(int flag, bool newValue, int* outFlags) {
148 if (newValue) {
149 if (!(flag & *outFlags)) {
150 *outFlags |= flag;
151 return true;
152 }
153 return false;
154 } else {
155 if (flag & *outFlags) {
156 *outFlags &= ~flag;
157 return true;
158 }
159 return false;
160 }
161 }
162
Chris Craika766cb22015-06-08 16:49:43 -0700163 /**
164 * Set internal layer state based on whether this layer
165 *
166 * Additionally, returns true if child RenderNodes with functors will need to use a layer
167 * to support clipping.
168 */
169 bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
170 // parent may have already dictated that a descendant layer is needed
171 bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
172
173 // Round rect clipping forces layer for functors
Chris Craikb60d3e72015-06-25 17:15:16 -0700174 || CC_UNLIKELY(getOutline().willRoundRectClip())
Chris Craika766cb22015-06-08 16:49:43 -0700175 || CC_UNLIKELY(getRevealClip().willClip())
176
177 // Complex matrices forces layer, due to stencil clipping
178 || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
179 || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
180 || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
181
182 mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
183
184 // If on a layer, will have consumed the need for isolating functors from stencil.
185 // Thus, it's safe to reset the flag until some descendent sets it.
186 return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
187 }
188
John Reckd0a0b2a2014-03-20 16:28:56 -0700189 RenderProperties& operator=(const RenderProperties& other);
190
John Reck79c7de72014-05-23 10:33:31 -0700191 bool setClipToBounds(bool clipToBounds) {
Chris Craika753f4c2014-07-24 12:39:17 -0700192 return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
193 }
194
195 bool setClipBounds(const Rect& clipBounds) {
196 bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
197 return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
198 }
199
200 bool setClipBoundsEmpty() {
201 return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
John Reckacb6f072014-03-12 16:11:23 -0700202 }
203
John Reck79c7de72014-05-23 10:33:31 -0700204 bool setProjectBackwards(bool shouldProject) {
205 return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
John Reckacb6f072014-03-12 16:11:23 -0700206 }
207
Chris Craik6fe991e52015-10-20 09:39:42 -0700208 bool setProjectionReceiver(bool shouldReceive) {
209 return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
John Reckacb6f072014-03-12 16:11:23 -0700210 }
211
John Reckd0a0b2a2014-03-20 16:28:56 -0700212 bool isProjectionReceiver() const {
213 return mPrimitiveFields.mProjectionReceiver;
John Reckacb6f072014-03-12 16:11:23 -0700214 }
215
John Reck79c7de72014-05-23 10:33:31 -0700216 bool setStaticMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700217 delete mStaticMatrix;
John Reckd0a0b2a2014-03-20 16:28:56 -0700218 if (matrix) {
219 mStaticMatrix = new SkMatrix(*matrix);
220 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800221 mStaticMatrix = nullptr;
John Reckd0a0b2a2014-03-20 16:28:56 -0700222 }
John Reck79c7de72014-05-23 10:33:31 -0700223 return true;
John Reckacb6f072014-03-12 16:11:23 -0700224 }
225
226 // Can return NULL
John Reckd0a0b2a2014-03-20 16:28:56 -0700227 const SkMatrix* getStaticMatrix() const {
John Reckacb6f072014-03-12 16:11:23 -0700228 return mStaticMatrix;
229 }
230
John Reck79c7de72014-05-23 10:33:31 -0700231 bool setAnimationMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700232 delete mAnimationMatrix;
233 if (matrix) {
234 mAnimationMatrix = new SkMatrix(*matrix);
235 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800236 mAnimationMatrix = nullptr;
John Reckacb6f072014-03-12 16:11:23 -0700237 }
John Reck79c7de72014-05-23 10:33:31 -0700238 return true;
John Reckacb6f072014-03-12 16:11:23 -0700239 }
240
John Reck79c7de72014-05-23 10:33:31 -0700241 bool setAlpha(float alpha) {
John Reck3b52c032014-08-06 10:19:32 -0700242 alpha = MathUtils::clampAlpha(alpha);
John Reck79c7de72014-05-23 10:33:31 -0700243 return RP_SET(mPrimitiveFields.mAlpha, alpha);
John Reckacb6f072014-03-12 16:11:23 -0700244 }
245
246 float getAlpha() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700247 return mPrimitiveFields.mAlpha;
John Reckacb6f072014-03-12 16:11:23 -0700248 }
249
John Reck79c7de72014-05-23 10:33:31 -0700250 bool setHasOverlappingRendering(bool hasOverlappingRendering) {
251 return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
John Reckacb6f072014-03-12 16:11:23 -0700252 }
253
254 bool hasOverlappingRendering() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700255 return mPrimitiveFields.mHasOverlappingRendering;
John Reckacb6f072014-03-12 16:11:23 -0700256 }
257
John Reck79c7de72014-05-23 10:33:31 -0700258 bool setElevation(float elevation) {
259 return RP_SET(mPrimitiveFields.mElevation, elevation);
260 // Don't dirty matrix/pivot, since they don't respect Z
Chris Craikcc39e162014-04-25 18:34:11 -0700261 }
262
263 float getElevation() const {
264 return mPrimitiveFields.mElevation;
265 }
266
John Reck79c7de72014-05-23 10:33:31 -0700267 bool setTranslationX(float translationX) {
268 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
John Reckacb6f072014-03-12 16:11:23 -0700269 }
270
271 float getTranslationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700272 return mPrimitiveFields.mTranslationX;
John Reckacb6f072014-03-12 16:11:23 -0700273 }
274
John Reck79c7de72014-05-23 10:33:31 -0700275 bool setTranslationY(float translationY) {
276 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
John Reckacb6f072014-03-12 16:11:23 -0700277 }
278
279 float getTranslationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700280 return mPrimitiveFields.mTranslationY;
John Reckacb6f072014-03-12 16:11:23 -0700281 }
282
John Reck79c7de72014-05-23 10:33:31 -0700283 bool setTranslationZ(float translationZ) {
284 return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
285 // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
John Reckacb6f072014-03-12 16:11:23 -0700286 }
287
288 float getTranslationZ() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700289 return mPrimitiveFields.mTranslationZ;
John Reckacb6f072014-03-12 16:11:23 -0700290 }
291
John Recke45b1fd2014-04-15 09:50:16 -0700292 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700293 bool setX(float value) {
294 return setTranslationX(value - getLeft());
John Recke45b1fd2014-04-15 09:50:16 -0700295 }
296
297 // Animation helper
298 float getX() const {
299 return getLeft() + getTranslationX();
300 }
301
302 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700303 bool setY(float value) {
304 return setTranslationY(value - getTop());
John Recke45b1fd2014-04-15 09:50:16 -0700305 }
306
307 // Animation helper
308 float getY() const {
309 return getTop() + getTranslationY();
310 }
311
312 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700313 bool setZ(float value) {
314 return setTranslationZ(value - getElevation());
John Recke45b1fd2014-04-15 09:50:16 -0700315 }
316
Chris Craikcc39e162014-04-25 18:34:11 -0700317 float getZ() const {
318 return getElevation() + getTranslationZ();
319 }
320
John Reck79c7de72014-05-23 10:33:31 -0700321 bool setRotation(float rotation) {
322 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
John Reckacb6f072014-03-12 16:11:23 -0700323 }
324
325 float getRotation() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700326 return mPrimitiveFields.mRotation;
John Reckacb6f072014-03-12 16:11:23 -0700327 }
328
John Reck79c7de72014-05-23 10:33:31 -0700329 bool setRotationX(float rotationX) {
330 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
John Reckacb6f072014-03-12 16:11:23 -0700331 }
332
333 float getRotationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700334 return mPrimitiveFields.mRotationX;
John Reckacb6f072014-03-12 16:11:23 -0700335 }
336
John Reck79c7de72014-05-23 10:33:31 -0700337 bool setRotationY(float rotationY) {
338 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
John Reckacb6f072014-03-12 16:11:23 -0700339 }
340
341 float getRotationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700342 return mPrimitiveFields.mRotationY;
John Reckacb6f072014-03-12 16:11:23 -0700343 }
344
John Reck79c7de72014-05-23 10:33:31 -0700345 bool setScaleX(float scaleX) {
346 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
John Reckacb6f072014-03-12 16:11:23 -0700347 }
348
349 float getScaleX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700350 return mPrimitiveFields.mScaleX;
John Reckacb6f072014-03-12 16:11:23 -0700351 }
352
John Reck79c7de72014-05-23 10:33:31 -0700353 bool setScaleY(float scaleY) {
354 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
John Reckacb6f072014-03-12 16:11:23 -0700355 }
356
357 float getScaleY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700358 return mPrimitiveFields.mScaleY;
John Reckacb6f072014-03-12 16:11:23 -0700359 }
360
John Reck79c7de72014-05-23 10:33:31 -0700361 bool setPivotX(float pivotX) {
362 if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
363 || !mPrimitiveFields.mPivotExplicitlySet) {
364 mPrimitiveFields.mMatrixOrPivotDirty = true;
365 mPrimitiveFields.mPivotExplicitlySet = true;
366 return true;
367 }
368 return false;
John Reckacb6f072014-03-12 16:11:23 -0700369 }
370
John Reckd0a0b2a2014-03-20 16:28:56 -0700371 /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
John Reck79c7de72014-05-23 10:33:31 -0700372 * so the value returned may be stale if the RenderProperties has been
373 * modified since the last call to updateMatrix()
John Reckd0a0b2a2014-03-20 16:28:56 -0700374 */
375 float getPivotX() const {
376 return mPrimitiveFields.mPivotX;
377 }
John Reckacb6f072014-03-12 16:11:23 -0700378
John Reck79c7de72014-05-23 10:33:31 -0700379 bool setPivotY(float pivotY) {
380 if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
381 || !mPrimitiveFields.mPivotExplicitlySet) {
382 mPrimitiveFields.mMatrixOrPivotDirty = true;
383 mPrimitiveFields.mPivotExplicitlySet = true;
384 return true;
385 }
386 return false;
John Reckacb6f072014-03-12 16:11:23 -0700387 }
388
John Reckd0a0b2a2014-03-20 16:28:56 -0700389 float getPivotY() const {
390 return mPrimitiveFields.mPivotY;
391 }
John Reckacb6f072014-03-12 16:11:23 -0700392
Chris Craik49e6c7392014-03-31 12:34:11 -0700393 bool isPivotExplicitlySet() const {
394 return mPrimitiveFields.mPivotExplicitlySet;
395 }
396
John Reck79c7de72014-05-23 10:33:31 -0700397 bool setCameraDistance(float distance) {
Chris Craik49e6c7392014-03-31 12:34:11 -0700398 if (distance != getCameraDistance()) {
John Reckf7483e32014-04-11 08:54:47 -0700399 mPrimitiveFields.mMatrixOrPivotDirty = true;
Chris Craik49e6c7392014-03-31 12:34:11 -0700400 mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
John Reck79c7de72014-05-23 10:33:31 -0700401 return true;
John Reckacb6f072014-03-12 16:11:23 -0700402 }
John Reck79c7de72014-05-23 10:33:31 -0700403 return false;
John Reckacb6f072014-03-12 16:11:23 -0700404 }
405
406 float getCameraDistance() const {
Chris Craik49e6c7392014-03-31 12:34:11 -0700407 // TODO: update getCameraLocationZ() to be const
408 return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
John Reckacb6f072014-03-12 16:11:23 -0700409 }
410
John Reck79c7de72014-05-23 10:33:31 -0700411 bool setLeft(int left) {
412 if (RP_SET(mPrimitiveFields.mLeft, left)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700413 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700414 if (!mPrimitiveFields.mPivotExplicitlySet) {
415 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700416 }
John Reck79c7de72014-05-23 10:33:31 -0700417 return true;
John Reckacb6f072014-03-12 16:11:23 -0700418 }
John Reck79c7de72014-05-23 10:33:31 -0700419 return false;
John Reckacb6f072014-03-12 16:11:23 -0700420 }
421
John Recke248bd12015-08-05 13:53:53 -0700422 int getLeft() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700423 return mPrimitiveFields.mLeft;
John Reckacb6f072014-03-12 16:11:23 -0700424 }
425
John Reck79c7de72014-05-23 10:33:31 -0700426 bool setTop(int top) {
427 if (RP_SET(mPrimitiveFields.mTop, top)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700428 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700429 if (!mPrimitiveFields.mPivotExplicitlySet) {
430 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700431 }
John Reck79c7de72014-05-23 10:33:31 -0700432 return true;
John Reckacb6f072014-03-12 16:11:23 -0700433 }
John Reck79c7de72014-05-23 10:33:31 -0700434 return false;
John Reckacb6f072014-03-12 16:11:23 -0700435 }
436
John Recke248bd12015-08-05 13:53:53 -0700437 int getTop() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700438 return mPrimitiveFields.mTop;
John Reckacb6f072014-03-12 16:11:23 -0700439 }
440
John Reck79c7de72014-05-23 10:33:31 -0700441 bool setRight(int right) {
442 if (RP_SET(mPrimitiveFields.mRight, right)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700443 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700444 if (!mPrimitiveFields.mPivotExplicitlySet) {
445 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700446 }
John Reck79c7de72014-05-23 10:33:31 -0700447 return true;
John Reckacb6f072014-03-12 16:11:23 -0700448 }
John Reck79c7de72014-05-23 10:33:31 -0700449 return false;
John Reckacb6f072014-03-12 16:11:23 -0700450 }
451
John Recke248bd12015-08-05 13:53:53 -0700452 int getRight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700453 return mPrimitiveFields.mRight;
John Reckacb6f072014-03-12 16:11:23 -0700454 }
455
John Reck79c7de72014-05-23 10:33:31 -0700456 bool setBottom(int bottom) {
457 if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700458 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700459 if (!mPrimitiveFields.mPivotExplicitlySet) {
460 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700461 }
John Reck79c7de72014-05-23 10:33:31 -0700462 return true;
John Reckacb6f072014-03-12 16:11:23 -0700463 }
John Reck79c7de72014-05-23 10:33:31 -0700464 return false;
John Reckacb6f072014-03-12 16:11:23 -0700465 }
466
John Recke248bd12015-08-05 13:53:53 -0700467 int getBottom() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700468 return mPrimitiveFields.mBottom;
John Reckacb6f072014-03-12 16:11:23 -0700469 }
470
John Reck79c7de72014-05-23 10:33:31 -0700471 bool setLeftTop(int left, int top) {
472 bool leftResult = setLeft(left);
473 bool topResult = setTop(top);
474 return leftResult || topResult;
John Reckacb6f072014-03-12 16:11:23 -0700475 }
476
John Reck79c7de72014-05-23 10:33:31 -0700477 bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
Chris Craikcc39e162014-04-25 18:34:11 -0700478 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
479 || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700480 mPrimitiveFields.mLeft = left;
481 mPrimitiveFields.mTop = top;
482 mPrimitiveFields.mRight = right;
483 mPrimitiveFields.mBottom = bottom;
484 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
485 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700486 if (!mPrimitiveFields.mPivotExplicitlySet) {
487 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700488 }
John Reck79c7de72014-05-23 10:33:31 -0700489 return true;
John Reckacb6f072014-03-12 16:11:23 -0700490 }
John Reck79c7de72014-05-23 10:33:31 -0700491 return false;
John Reckacb6f072014-03-12 16:11:23 -0700492 }
493
Chris Craika753f4c2014-07-24 12:39:17 -0700494 bool offsetLeftRight(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700495 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700496 mPrimitiveFields.mLeft += offset;
497 mPrimitiveFields.mRight += offset;
John Reck79c7de72014-05-23 10:33:31 -0700498 return true;
John Reckacb6f072014-03-12 16:11:23 -0700499 }
John Reck79c7de72014-05-23 10:33:31 -0700500 return false;
John Reckacb6f072014-03-12 16:11:23 -0700501 }
502
Chris Craika753f4c2014-07-24 12:39:17 -0700503 bool offsetTopBottom(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700504 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700505 mPrimitiveFields.mTop += offset;
506 mPrimitiveFields.mBottom += offset;
John Reck79c7de72014-05-23 10:33:31 -0700507 return true;
John Reckacb6f072014-03-12 16:11:23 -0700508 }
John Reck79c7de72014-05-23 10:33:31 -0700509 return false;
John Reckacb6f072014-03-12 16:11:23 -0700510 }
511
Chris Craikb49f4462014-03-20 12:44:20 -0700512 int getWidth() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700513 return mPrimitiveFields.mWidth;
John Reckacb6f072014-03-12 16:11:23 -0700514 }
515
Chris Craikb49f4462014-03-20 12:44:20 -0700516 int getHeight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700517 return mPrimitiveFields.mHeight;
John Reckacb6f072014-03-12 16:11:23 -0700518 }
519
John Reckd0a0b2a2014-03-20 16:28:56 -0700520 const SkMatrix* getAnimationMatrix() const {
521 return mAnimationMatrix;
522 }
523
John Reckf7483e32014-04-11 08:54:47 -0700524 bool hasTransformMatrix() const {
525 return getTransformMatrix() && !getTransformMatrix()->isIdentity();
526 }
527
528 // May only call this if hasTransformMatrix() is true
529 bool isTransformTranslateOnly() const {
530 return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
John Reckd0a0b2a2014-03-20 16:28:56 -0700531 }
532
Chris Craik49e6c7392014-03-31 12:34:11 -0700533 const SkMatrix* getTransformMatrix() const {
John Reckf7483e32014-04-11 08:54:47 -0700534 LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
John Reckd0a0b2a2014-03-20 16:28:56 -0700535 return mComputedFields.mTransformMatrix;
536 }
537
Chris Craika753f4c2014-07-24 12:39:17 -0700538 int getClippingFlags() const {
539 return mPrimitiveFields.mClippingFlags;
540 }
541
John Reckd0a0b2a2014-03-20 16:28:56 -0700542 bool getClipToBounds() const {
Chris Craika753f4c2014-07-24 12:39:17 -0700543 return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
544 }
545
John Recke248bd12015-08-05 13:53:53 -0700546 const Rect& getClipBounds() const {
547 return mPrimitiveFields.mClipBounds;
548 }
549
Chris Craika753f4c2014-07-24 12:39:17 -0700550 void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
551 if (flags & CLIP_TO_BOUNDS) {
552 outRect->set(0, 0, getWidth(), getHeight());
553 if (flags & CLIP_TO_CLIP_BOUNDS) {
Chris Craikac02eb92015-10-05 12:23:46 -0700554 outRect->doIntersect(mPrimitiveFields.mClipBounds);
Chris Craika753f4c2014-07-24 12:39:17 -0700555 }
556 } else {
557 outRect->set(mPrimitiveFields.mClipBounds);
558 }
John Reckd0a0b2a2014-03-20 16:28:56 -0700559 }
560
561 bool getHasOverlappingRendering() const {
562 return mPrimitiveFields.mHasOverlappingRendering;
563 }
564
565 const Outline& getOutline() const {
566 return mPrimitiveFields.mOutline;
567 }
568
Chris Craik8c271ca2014-03-25 10:33:01 -0700569 const RevealClip& getRevealClip() const {
570 return mPrimitiveFields.mRevealClip;
571 }
572
John Reckd0a0b2a2014-03-20 16:28:56 -0700573 bool getProjectBackwards() const {
574 return mPrimitiveFields.mProjectBackwards;
575 }
576
577 void debugOutputProperties(const int level) const;
578
John Reck25fbb3f2014-06-12 13:46:45 -0700579 void updateMatrix();
John Reckd0a0b2a2014-03-20 16:28:56 -0700580
581 Outline& mutableOutline() {
582 return mPrimitiveFields.mOutline;
Chris Craikb49f4462014-03-20 12:44:20 -0700583 }
584
Chris Craik8c271ca2014-03-25 10:33:01 -0700585 RevealClip& mutableRevealClip() {
586 return mPrimitiveFields.mRevealClip;
587 }
588
John Reck25fbb3f2014-06-12 13:46:45 -0700589 const LayerProperties& layerProperties() const {
590 return mLayerProperties;
591 }
592
593 LayerProperties& mutateLayerProperties() {
594 return mLayerProperties;
595 }
596
John Reck293e8682014-06-17 10:34:02 -0700597 // Returns true if damage calculations should be clipped to bounds
598 // TODO: Figure out something better for getZ(), as children should still be
599 // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
600 // for this RP's getZ() anyway, this can be optimized when we have a
601 // Z damage estimate instead of INT_MAX
602 bool getClipDamageToBounds() const {
603 return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
604 }
605
Chris Craik5c75c522014-09-05 14:08:08 -0700606 bool hasShadow() const {
Chris Craikb5a54352014-11-21 14:54:35 -0800607 return getZ() > 0.0f
Chris Craike84a2082014-12-22 14:28:49 -0800608 && getOutline().getPath() != nullptr
Chris Craik9fa364d2014-09-19 16:04:45 -0700609 && getOutline().getAlpha() != 0.0f;
Chris Craik5c75c522014-09-05 14:08:08 -0700610 }
611
Chris Craik9fded232015-11-11 16:42:34 -0800612 bool fitsOnLayer() const {
Chris Craik76caecf2015-11-02 19:17:45 -0800613 const DeviceInfo* deviceInfo = DeviceInfo::get();
Chris Craik9fded232015-11-11 16:42:34 -0800614 return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
Chris Craikd4fe4d32016-06-09 16:57:11 -0700615 && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize()
616 && mPrimitiveFields.mWidth > 0
617 && mPrimitiveFields.mHeight > 0;
Chris Craik9fded232015-11-11 16:42:34 -0800618 }
619
620 bool promotedToLayer() const {
Chris Craik1a0808e2015-05-13 16:33:04 -0700621 return mLayerProperties.mType == LayerType::None
Chris Craik9fded232015-11-11 16:42:34 -0800622 && fitsOnLayer()
Chris Craika766cb22015-06-08 16:49:43 -0700623 && (mComputedFields.mNeedLayerForFunctors
624 || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
625 && mPrimitiveFields.mAlpha < 1
626 && mPrimitiveFields.mHasOverlappingRendering));
Chris Craik1a0808e2015-05-13 16:33:04 -0700627 }
628
629 LayerType effectiveLayerType() const {
Chris Craika766cb22015-06-08 16:49:43 -0700630 return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
Chris Craik856f0cc2015-04-21 15:13:29 -0700631 }
632
John Reckacb6f072014-03-12 16:11:23 -0700633private:
John Reckacb6f072014-03-12 16:11:23 -0700634 // Rendering properties
John Reckd0a0b2a2014-03-20 16:28:56 -0700635 struct PrimitiveFields {
John Recke248bd12015-08-05 13:53:53 -0700636 int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
637 int mWidth = 0, mHeight = 0;
638 int mClippingFlags = CLIP_TO_BOUNDS;
639 float mAlpha = 1;
640 float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
641 float mElevation = 0;
642 float mRotation = 0, mRotationX = 0, mRotationY = 0;
643 float mScaleX = 1, mScaleY = 1;
644 float mPivotX = 0, mPivotY = 0;
645 bool mHasOverlappingRendering = false;
646 bool mPivotExplicitlySet = false;
647 bool mMatrixOrPivotDirty = false;
648 bool mProjectBackwards = false;
649 bool mProjectionReceiver = false;
650 Rect mClipBounds;
John Reckd0a0b2a2014-03-20 16:28:56 -0700651 Outline mOutline;
Chris Craik8c271ca2014-03-25 10:33:01 -0700652 RevealClip mRevealClip;
John Reckd0a0b2a2014-03-20 16:28:56 -0700653 } mPrimitiveFields;
654
John Reckacb6f072014-03-12 16:11:23 -0700655 SkMatrix* mStaticMatrix;
656 SkMatrix* mAnimationMatrix;
John Reck25fbb3f2014-06-12 13:46:45 -0700657 LayerProperties mLayerProperties;
John Reckacb6f072014-03-12 16:11:23 -0700658
John Reckd0a0b2a2014-03-20 16:28:56 -0700659 /**
660 * These fields are all generated from other properties and are not set directly.
661 */
662 struct ComputedFields {
663 ComputedFields();
664 ~ComputedFields();
665
666 /**
667 * Stores the total transformation of the DisplayList based upon its scalar
668 * translate/rotate/scale properties.
669 *
Chris Craik49e6c7392014-03-31 12:34:11 -0700670 * In the common translation-only case, the matrix isn't necessarily allocated,
671 * and the mTranslation properties are used directly.
John Reckd0a0b2a2014-03-20 16:28:56 -0700672 */
Chris Craik49e6c7392014-03-31 12:34:11 -0700673 SkMatrix* mTransformMatrix;
674
675 Sk3DView mTransformCamera;
Chris Craika766cb22015-06-08 16:49:43 -0700676
677 // Force layer on for functors to enable render features they don't yet support (clipping)
678 bool mNeedLayerForFunctors = false;
John Reckd0a0b2a2014-03-20 16:28:56 -0700679 } mComputedFields;
John Reckacb6f072014-03-12 16:11:23 -0700680};
681
682} /* namespace uirenderer */
683} /* namespace android */