blob: 9ee2f9c69343889b2f011a06ffb41a58cae9188c [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
Mike Reed260ab722016-10-07 15:59:20 -040027#include <SkBlendMode.h>
John Reckacb6f072014-03-12 16:11:23 -070028#include <SkCamera.h>
29#include <SkMatrix.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070030#include <SkRegion.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>
sergeyvc3849aa2016-08-08 13:22:06 -070038#include <ostream>
John Reckacb6f072014-03-12 16:11:23 -070039
John Reckacb6f072014-03-12 16:11:23 -070040class SkBitmap;
John Reck25fbb3f2014-06-12 13:46:45 -070041class SkColorFilter;
John Reckacb6f072014-03-12 16:11:23 -070042class SkPaint;
John Reckacb6f072014-03-12 16:11:23 -070043
44namespace android {
45namespace uirenderer {
46
47class Matrix4;
48class RenderNode;
John Reck25fbb3f2014-06-12 13:46:45 -070049class RenderProperties;
John Reckacb6f072014-03-12 16:11:23 -070050
John Reck79c7de72014-05-23 10:33:31 -070051// The __VA_ARGS__ will be executed if a & b are not equal
Chih-Hung Hsiehcef190d2016-05-19 15:25:50 -070052#define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false)
John Reck79c7de72014-05-23 10:33:31 -070053#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
54
John Reck25fbb3f2014-06-12 13:46:45 -070055// Keep in sync with View.java:LAYER_TYPE_*
Chris Craik182952f2015-03-09 14:17:29 -070056enum class LayerType {
57 None = 0,
John Reck25fbb3f2014-06-12 13:46:45 -070058 // Although we cannot build the software layer directly (must be done at
59 // record time), this information is used when applying alpha.
Chris Craik182952f2015-03-09 14:17:29 -070060 Software = 1,
61 RenderLayer = 2,
John Reck25fbb3f2014-06-12 13:46:45 -070062 // TODO: LayerTypeSurfaceTexture? Maybe?
63};
64
Chris Craika753f4c2014-07-24 12:39:17 -070065enum ClippingFlags {
66 CLIP_TO_BOUNDS = 0x1 << 0,
67 CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
68};
69
John Reck25fbb3f2014-06-12 13:46:45 -070070class ANDROID_API LayerProperties {
71public:
72 bool setType(LayerType type) {
73 if (RP_SET(mType, type)) {
74 reset();
75 return true;
76 }
77 return false;
78 }
79
John Reck25fbb3f2014-06-12 13:46:45 -070080 bool setOpaque(bool opaque) {
81 return RP_SET(mOpaque, opaque);
82 }
83
84 bool opaque() const {
85 return mOpaque;
86 }
87
88 bool setAlpha(uint8_t alpha) {
89 return RP_SET(mAlpha, alpha);
90 }
91
92 uint8_t alpha() const {
93 return mAlpha;
94 }
95
Mike Reed260ab722016-10-07 15:59:20 -040096 bool setXferMode(SkBlendMode mode) {
John Reck25fbb3f2014-06-12 13:46:45 -070097 return RP_SET(mMode, mode);
98 }
99
Mike Reed260ab722016-10-07 15:59:20 -0400100 SkBlendMode xferMode() const {
John Reck25fbb3f2014-06-12 13:46:45 -0700101 return mMode;
102 }
103
104 bool setColorFilter(SkColorFilter* filter);
105
106 SkColorFilter* colorFilter() const {
107 return mColorFilter;
108 }
109
110 // Sets alpha, xfermode, and colorfilter from an SkPaint
111 // paint may be NULL, in which case defaults will be set
112 bool setFromPaint(const SkPaint* paint);
113
114 bool needsBlending() const {
115 return !opaque() || alpha() < 255;
116 }
117
118 LayerProperties& operator=(const LayerProperties& other);
119
120private:
121 LayerProperties();
122 ~LayerProperties();
123 void reset();
124
Chris Craik856f0cc2015-04-21 15:13:29 -0700125 // Private since external users should go through properties().effectiveLayerType()
126 LayerType type() const {
127 return mType;
128 }
129
John Reck25fbb3f2014-06-12 13:46:45 -0700130 friend class RenderProperties;
131
Chris Craik182952f2015-03-09 14:17:29 -0700132 LayerType mType = LayerType::None;
John Reck25fbb3f2014-06-12 13:46:45 -0700133 // Whether or not that Layer's content is opaque, doesn't include alpha
134 bool mOpaque;
135 uint8_t mAlpha;
Mike Reed260ab722016-10-07 15:59:20 -0400136 SkBlendMode mMode;
Chris Craik182952f2015-03-09 14:17:29 -0700137 SkColorFilter* mColorFilter = nullptr;
John Reck25fbb3f2014-06-12 13:46:45 -0700138};
139
John Reckacb6f072014-03-12 16:11:23 -0700140/*
141 * Data structure that holds the properties for a RenderNode
142 */
John Reck25fbb3f2014-06-12 13:46:45 -0700143class ANDROID_API RenderProperties {
John Reckacb6f072014-03-12 16:11:23 -0700144public:
145 RenderProperties();
146 virtual ~RenderProperties();
147
Chris Craika753f4c2014-07-24 12:39:17 -0700148 static bool setFlag(int flag, bool newValue, int* outFlags) {
149 if (newValue) {
150 if (!(flag & *outFlags)) {
151 *outFlags |= flag;
152 return true;
153 }
154 return false;
155 } else {
156 if (flag & *outFlags) {
157 *outFlags &= ~flag;
158 return true;
159 }
160 return false;
161 }
162 }
163
Chris Craika766cb22015-06-08 16:49:43 -0700164 /**
165 * Set internal layer state based on whether this layer
166 *
167 * Additionally, returns true if child RenderNodes with functors will need to use a layer
168 * to support clipping.
169 */
170 bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
171 // parent may have already dictated that a descendant layer is needed
172 bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
173
174 // Round rect clipping forces layer for functors
Chris Craikb60d3e72015-06-25 17:15:16 -0700175 || CC_UNLIKELY(getOutline().willRoundRectClip())
Chris Craika766cb22015-06-08 16:49:43 -0700176 || CC_UNLIKELY(getRevealClip().willClip())
177
178 // Complex matrices forces layer, due to stencil clipping
179 || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
180 || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
181 || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
182
183 mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
184
185 // If on a layer, will have consumed the need for isolating functors from stencil.
186 // Thus, it's safe to reset the flag until some descendent sets it.
187 return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
188 }
189
John Reckd0a0b2a2014-03-20 16:28:56 -0700190 RenderProperties& operator=(const RenderProperties& other);
191
John Reck79c7de72014-05-23 10:33:31 -0700192 bool setClipToBounds(bool clipToBounds) {
Chris Craika753f4c2014-07-24 12:39:17 -0700193 return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
194 }
195
196 bool setClipBounds(const Rect& clipBounds) {
197 bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
198 return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
199 }
200
201 bool setClipBoundsEmpty() {
202 return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
John Reckacb6f072014-03-12 16:11:23 -0700203 }
204
John Reck79c7de72014-05-23 10:33:31 -0700205 bool setProjectBackwards(bool shouldProject) {
206 return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
John Reckacb6f072014-03-12 16:11:23 -0700207 }
208
Chris Craik6fe991e52015-10-20 09:39:42 -0700209 bool setProjectionReceiver(bool shouldReceive) {
210 return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
John Reckacb6f072014-03-12 16:11:23 -0700211 }
212
John Reckd0a0b2a2014-03-20 16:28:56 -0700213 bool isProjectionReceiver() const {
214 return mPrimitiveFields.mProjectionReceiver;
John Reckacb6f072014-03-12 16:11:23 -0700215 }
216
John Reck79c7de72014-05-23 10:33:31 -0700217 bool setStaticMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700218 delete mStaticMatrix;
John Reckd0a0b2a2014-03-20 16:28:56 -0700219 if (matrix) {
220 mStaticMatrix = new SkMatrix(*matrix);
221 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800222 mStaticMatrix = nullptr;
John Reckd0a0b2a2014-03-20 16:28:56 -0700223 }
John Reck79c7de72014-05-23 10:33:31 -0700224 return true;
John Reckacb6f072014-03-12 16:11:23 -0700225 }
226
227 // Can return NULL
John Reckd0a0b2a2014-03-20 16:28:56 -0700228 const SkMatrix* getStaticMatrix() const {
John Reckacb6f072014-03-12 16:11:23 -0700229 return mStaticMatrix;
230 }
231
John Reck79c7de72014-05-23 10:33:31 -0700232 bool setAnimationMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700233 delete mAnimationMatrix;
234 if (matrix) {
235 mAnimationMatrix = new SkMatrix(*matrix);
236 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800237 mAnimationMatrix = nullptr;
John Reckacb6f072014-03-12 16:11:23 -0700238 }
John Reck79c7de72014-05-23 10:33:31 -0700239 return true;
John Reckacb6f072014-03-12 16:11:23 -0700240 }
241
John Reck79c7de72014-05-23 10:33:31 -0700242 bool setAlpha(float alpha) {
John Reck3b52c032014-08-06 10:19:32 -0700243 alpha = MathUtils::clampAlpha(alpha);
John Reck79c7de72014-05-23 10:33:31 -0700244 return RP_SET(mPrimitiveFields.mAlpha, alpha);
John Reckacb6f072014-03-12 16:11:23 -0700245 }
246
247 float getAlpha() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700248 return mPrimitiveFields.mAlpha;
John Reckacb6f072014-03-12 16:11:23 -0700249 }
250
John Reck79c7de72014-05-23 10:33:31 -0700251 bool setHasOverlappingRendering(bool hasOverlappingRendering) {
252 return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
John Reckacb6f072014-03-12 16:11:23 -0700253 }
254
255 bool hasOverlappingRendering() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700256 return mPrimitiveFields.mHasOverlappingRendering;
John Reckacb6f072014-03-12 16:11:23 -0700257 }
258
John Reck79c7de72014-05-23 10:33:31 -0700259 bool setElevation(float elevation) {
260 return RP_SET(mPrimitiveFields.mElevation, elevation);
261 // Don't dirty matrix/pivot, since they don't respect Z
Chris Craikcc39e162014-04-25 18:34:11 -0700262 }
263
264 float getElevation() const {
265 return mPrimitiveFields.mElevation;
266 }
267
John Reck79c7de72014-05-23 10:33:31 -0700268 bool setTranslationX(float translationX) {
269 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
John Reckacb6f072014-03-12 16:11:23 -0700270 }
271
272 float getTranslationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700273 return mPrimitiveFields.mTranslationX;
John Reckacb6f072014-03-12 16:11:23 -0700274 }
275
John Reck79c7de72014-05-23 10:33:31 -0700276 bool setTranslationY(float translationY) {
277 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
John Reckacb6f072014-03-12 16:11:23 -0700278 }
279
280 float getTranslationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700281 return mPrimitiveFields.mTranslationY;
John Reckacb6f072014-03-12 16:11:23 -0700282 }
283
John Reck79c7de72014-05-23 10:33:31 -0700284 bool setTranslationZ(float translationZ) {
285 return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
286 // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
John Reckacb6f072014-03-12 16:11:23 -0700287 }
288
289 float getTranslationZ() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700290 return mPrimitiveFields.mTranslationZ;
John Reckacb6f072014-03-12 16:11:23 -0700291 }
292
John Recke45b1fd2014-04-15 09:50:16 -0700293 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700294 bool setX(float value) {
295 return setTranslationX(value - getLeft());
John Recke45b1fd2014-04-15 09:50:16 -0700296 }
297
298 // Animation helper
299 float getX() const {
300 return getLeft() + getTranslationX();
301 }
302
303 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700304 bool setY(float value) {
305 return setTranslationY(value - getTop());
John Recke45b1fd2014-04-15 09:50:16 -0700306 }
307
308 // Animation helper
309 float getY() const {
310 return getTop() + getTranslationY();
311 }
312
313 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700314 bool setZ(float value) {
315 return setTranslationZ(value - getElevation());
John Recke45b1fd2014-04-15 09:50:16 -0700316 }
317
Chris Craikcc39e162014-04-25 18:34:11 -0700318 float getZ() const {
319 return getElevation() + getTranslationZ();
320 }
321
John Reck79c7de72014-05-23 10:33:31 -0700322 bool setRotation(float rotation) {
323 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
John Reckacb6f072014-03-12 16:11:23 -0700324 }
325
326 float getRotation() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700327 return mPrimitiveFields.mRotation;
John Reckacb6f072014-03-12 16:11:23 -0700328 }
329
John Reck79c7de72014-05-23 10:33:31 -0700330 bool setRotationX(float rotationX) {
331 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
John Reckacb6f072014-03-12 16:11:23 -0700332 }
333
334 float getRotationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700335 return mPrimitiveFields.mRotationX;
John Reckacb6f072014-03-12 16:11:23 -0700336 }
337
John Reck79c7de72014-05-23 10:33:31 -0700338 bool setRotationY(float rotationY) {
339 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
John Reckacb6f072014-03-12 16:11:23 -0700340 }
341
342 float getRotationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700343 return mPrimitiveFields.mRotationY;
John Reckacb6f072014-03-12 16:11:23 -0700344 }
345
John Reck79c7de72014-05-23 10:33:31 -0700346 bool setScaleX(float scaleX) {
347 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
John Reckacb6f072014-03-12 16:11:23 -0700348 }
349
350 float getScaleX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700351 return mPrimitiveFields.mScaleX;
John Reckacb6f072014-03-12 16:11:23 -0700352 }
353
John Reck79c7de72014-05-23 10:33:31 -0700354 bool setScaleY(float scaleY) {
355 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
John Reckacb6f072014-03-12 16:11:23 -0700356 }
357
358 float getScaleY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700359 return mPrimitiveFields.mScaleY;
John Reckacb6f072014-03-12 16:11:23 -0700360 }
361
John Reck79c7de72014-05-23 10:33:31 -0700362 bool setPivotX(float pivotX) {
363 if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
364 || !mPrimitiveFields.mPivotExplicitlySet) {
365 mPrimitiveFields.mMatrixOrPivotDirty = true;
366 mPrimitiveFields.mPivotExplicitlySet = true;
367 return true;
368 }
369 return false;
John Reckacb6f072014-03-12 16:11:23 -0700370 }
371
John Reckd0a0b2a2014-03-20 16:28:56 -0700372 /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
John Reck79c7de72014-05-23 10:33:31 -0700373 * so the value returned may be stale if the RenderProperties has been
374 * modified since the last call to updateMatrix()
John Reckd0a0b2a2014-03-20 16:28:56 -0700375 */
376 float getPivotX() const {
377 return mPrimitiveFields.mPivotX;
378 }
John Reckacb6f072014-03-12 16:11:23 -0700379
John Reck79c7de72014-05-23 10:33:31 -0700380 bool setPivotY(float pivotY) {
381 if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
382 || !mPrimitiveFields.mPivotExplicitlySet) {
383 mPrimitiveFields.mMatrixOrPivotDirty = true;
384 mPrimitiveFields.mPivotExplicitlySet = true;
385 return true;
386 }
387 return false;
John Reckacb6f072014-03-12 16:11:23 -0700388 }
389
John Reckd0a0b2a2014-03-20 16:28:56 -0700390 float getPivotY() const {
391 return mPrimitiveFields.mPivotY;
392 }
John Reckacb6f072014-03-12 16:11:23 -0700393
Chris Craik49e6c732014-03-31 12:34:11 -0700394 bool isPivotExplicitlySet() const {
395 return mPrimitiveFields.mPivotExplicitlySet;
396 }
397
John Reck79c7de72014-05-23 10:33:31 -0700398 bool setCameraDistance(float distance) {
Chris Craik49e6c732014-03-31 12:34:11 -0700399 if (distance != getCameraDistance()) {
John Reckf7483e32014-04-11 08:54:47 -0700400 mPrimitiveFields.mMatrixOrPivotDirty = true;
Chris Craik49e6c732014-03-31 12:34:11 -0700401 mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
John Reck79c7de72014-05-23 10:33:31 -0700402 return true;
John Reckacb6f072014-03-12 16:11:23 -0700403 }
John Reck79c7de72014-05-23 10:33:31 -0700404 return false;
John Reckacb6f072014-03-12 16:11:23 -0700405 }
406
407 float getCameraDistance() const {
Chris Craik49e6c732014-03-31 12:34:11 -0700408 // TODO: update getCameraLocationZ() to be const
409 return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
John Reckacb6f072014-03-12 16:11:23 -0700410 }
411
John Reck79c7de72014-05-23 10:33:31 -0700412 bool setLeft(int left) {
413 if (RP_SET(mPrimitiveFields.mLeft, left)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700414 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700415 if (!mPrimitiveFields.mPivotExplicitlySet) {
416 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700417 }
John Reck79c7de72014-05-23 10:33:31 -0700418 return true;
John Reckacb6f072014-03-12 16:11:23 -0700419 }
John Reck79c7de72014-05-23 10:33:31 -0700420 return false;
John Reckacb6f072014-03-12 16:11:23 -0700421 }
422
John Recke248bd12015-08-05 13:53:53 -0700423 int getLeft() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700424 return mPrimitiveFields.mLeft;
John Reckacb6f072014-03-12 16:11:23 -0700425 }
426
John Reck79c7de72014-05-23 10:33:31 -0700427 bool setTop(int top) {
428 if (RP_SET(mPrimitiveFields.mTop, top)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700429 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700430 if (!mPrimitiveFields.mPivotExplicitlySet) {
431 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700432 }
John Reck79c7de72014-05-23 10:33:31 -0700433 return true;
John Reckacb6f072014-03-12 16:11:23 -0700434 }
John Reck79c7de72014-05-23 10:33:31 -0700435 return false;
John Reckacb6f072014-03-12 16:11:23 -0700436 }
437
John Recke248bd12015-08-05 13:53:53 -0700438 int getTop() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700439 return mPrimitiveFields.mTop;
John Reckacb6f072014-03-12 16:11:23 -0700440 }
441
John Reck79c7de72014-05-23 10:33:31 -0700442 bool setRight(int right) {
443 if (RP_SET(mPrimitiveFields.mRight, right)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700444 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700445 if (!mPrimitiveFields.mPivotExplicitlySet) {
446 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700447 }
John Reck79c7de72014-05-23 10:33:31 -0700448 return true;
John Reckacb6f072014-03-12 16:11:23 -0700449 }
John Reck79c7de72014-05-23 10:33:31 -0700450 return false;
John Reckacb6f072014-03-12 16:11:23 -0700451 }
452
John Recke248bd12015-08-05 13:53:53 -0700453 int getRight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700454 return mPrimitiveFields.mRight;
John Reckacb6f072014-03-12 16:11:23 -0700455 }
456
John Reck79c7de72014-05-23 10:33:31 -0700457 bool setBottom(int bottom) {
458 if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700459 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700460 if (!mPrimitiveFields.mPivotExplicitlySet) {
461 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700462 }
John Reck79c7de72014-05-23 10:33:31 -0700463 return true;
John Reckacb6f072014-03-12 16:11:23 -0700464 }
John Reck79c7de72014-05-23 10:33:31 -0700465 return false;
John Reckacb6f072014-03-12 16:11:23 -0700466 }
467
John Recke248bd12015-08-05 13:53:53 -0700468 int getBottom() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700469 return mPrimitiveFields.mBottom;
John Reckacb6f072014-03-12 16:11:23 -0700470 }
471
John Reck79c7de72014-05-23 10:33:31 -0700472 bool setLeftTop(int left, int top) {
473 bool leftResult = setLeft(left);
474 bool topResult = setTop(top);
475 return leftResult || topResult;
John Reckacb6f072014-03-12 16:11:23 -0700476 }
477
John Reck79c7de72014-05-23 10:33:31 -0700478 bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
Chris Craikcc39e162014-04-25 18:34:11 -0700479 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
480 || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700481 mPrimitiveFields.mLeft = left;
482 mPrimitiveFields.mTop = top;
483 mPrimitiveFields.mRight = right;
484 mPrimitiveFields.mBottom = bottom;
485 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
486 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700487 if (!mPrimitiveFields.mPivotExplicitlySet) {
488 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700489 }
John Reck79c7de72014-05-23 10:33:31 -0700490 return true;
John Reckacb6f072014-03-12 16:11:23 -0700491 }
John Reck79c7de72014-05-23 10:33:31 -0700492 return false;
John Reckacb6f072014-03-12 16:11:23 -0700493 }
494
Chris Craika753f4c2014-07-24 12:39:17 -0700495 bool offsetLeftRight(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700496 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700497 mPrimitiveFields.mLeft += offset;
498 mPrimitiveFields.mRight += offset;
John Reck79c7de72014-05-23 10:33:31 -0700499 return true;
John Reckacb6f072014-03-12 16:11:23 -0700500 }
John Reck79c7de72014-05-23 10:33:31 -0700501 return false;
John Reckacb6f072014-03-12 16:11:23 -0700502 }
503
Chris Craika753f4c2014-07-24 12:39:17 -0700504 bool offsetTopBottom(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700505 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700506 mPrimitiveFields.mTop += offset;
507 mPrimitiveFields.mBottom += offset;
John Reck79c7de72014-05-23 10:33:31 -0700508 return true;
John Reckacb6f072014-03-12 16:11:23 -0700509 }
John Reck79c7de72014-05-23 10:33:31 -0700510 return false;
John Reckacb6f072014-03-12 16:11:23 -0700511 }
512
Chris Craikb49f4462014-03-20 12:44:20 -0700513 int getWidth() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700514 return mPrimitiveFields.mWidth;
John Reckacb6f072014-03-12 16:11:23 -0700515 }
516
Chris Craikb49f4462014-03-20 12:44:20 -0700517 int getHeight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700518 return mPrimitiveFields.mHeight;
John Reckacb6f072014-03-12 16:11:23 -0700519 }
520
John Reckd0a0b2a2014-03-20 16:28:56 -0700521 const SkMatrix* getAnimationMatrix() const {
522 return mAnimationMatrix;
523 }
524
John Reckf7483e32014-04-11 08:54:47 -0700525 bool hasTransformMatrix() const {
526 return getTransformMatrix() && !getTransformMatrix()->isIdentity();
527 }
528
529 // May only call this if hasTransformMatrix() is true
530 bool isTransformTranslateOnly() const {
531 return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
John Reckd0a0b2a2014-03-20 16:28:56 -0700532 }
533
Chris Craik49e6c732014-03-31 12:34:11 -0700534 const SkMatrix* getTransformMatrix() const {
John Reckf7483e32014-04-11 08:54:47 -0700535 LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
John Reckd0a0b2a2014-03-20 16:28:56 -0700536 return mComputedFields.mTransformMatrix;
537 }
538
Chris Craika753f4c2014-07-24 12:39:17 -0700539 int getClippingFlags() const {
540 return mPrimitiveFields.mClippingFlags;
541 }
542
John Reckd0a0b2a2014-03-20 16:28:56 -0700543 bool getClipToBounds() const {
Chris Craika753f4c2014-07-24 12:39:17 -0700544 return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
545 }
546
John Recke248bd12015-08-05 13:53:53 -0700547 const Rect& getClipBounds() const {
548 return mPrimitiveFields.mClipBounds;
549 }
550
Chris Craika753f4c2014-07-24 12:39:17 -0700551 void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
552 if (flags & CLIP_TO_BOUNDS) {
553 outRect->set(0, 0, getWidth(), getHeight());
554 if (flags & CLIP_TO_CLIP_BOUNDS) {
Chris Craikac02eb92015-10-05 12:23:46 -0700555 outRect->doIntersect(mPrimitiveFields.mClipBounds);
Chris Craika753f4c2014-07-24 12:39:17 -0700556 }
557 } else {
558 outRect->set(mPrimitiveFields.mClipBounds);
559 }
John Reckd0a0b2a2014-03-20 16:28:56 -0700560 }
561
562 bool getHasOverlappingRendering() const {
563 return mPrimitiveFields.mHasOverlappingRendering;
564 }
565
566 const Outline& getOutline() const {
567 return mPrimitiveFields.mOutline;
568 }
569
Chris Craik8c271ca2014-03-25 10:33:01 -0700570 const RevealClip& getRevealClip() const {
571 return mPrimitiveFields.mRevealClip;
572 }
573
John Reckd0a0b2a2014-03-20 16:28:56 -0700574 bool getProjectBackwards() const {
575 return mPrimitiveFields.mProjectBackwards;
576 }
577
sergeyvc3849aa2016-08-08 13:22:06 -0700578 void debugOutputProperties(std::ostream& output, const int level) const;
John Reckd0a0b2a2014-03-20 16:28:56 -0700579
John Reck25fbb3f2014-06-12 13:46:45 -0700580 void updateMatrix();
John Reckd0a0b2a2014-03-20 16:28:56 -0700581
582 Outline& mutableOutline() {
583 return mPrimitiveFields.mOutline;
Chris Craikb49f4462014-03-20 12:44:20 -0700584 }
585
Chris Craik8c271ca2014-03-25 10:33:01 -0700586 RevealClip& mutableRevealClip() {
587 return mPrimitiveFields.mRevealClip;
588 }
589
John Reck25fbb3f2014-06-12 13:46:45 -0700590 const LayerProperties& layerProperties() const {
591 return mLayerProperties;
592 }
593
594 LayerProperties& mutateLayerProperties() {
595 return mLayerProperties;
596 }
597
John Reck293e8682014-06-17 10:34:02 -0700598 // Returns true if damage calculations should be clipped to bounds
599 // TODO: Figure out something better for getZ(), as children should still be
600 // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
601 // for this RP's getZ() anyway, this can be optimized when we have a
602 // Z damage estimate instead of INT_MAX
603 bool getClipDamageToBounds() const {
604 return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
605 }
606
Chris Craik5c75c522014-09-05 14:08:08 -0700607 bool hasShadow() const {
Chris Craikb5a54352014-11-21 14:54:35 -0800608 return getZ() > 0.0f
Chris Craike84a2082014-12-22 14:28:49 -0800609 && getOutline().getPath() != nullptr
Chris Craik9fa364d2014-09-19 16:04:45 -0700610 && getOutline().getAlpha() != 0.0f;
Chris Craik5c75c522014-09-05 14:08:08 -0700611 }
612
Chris Craik9fded232015-11-11 16:42:34 -0800613 bool fitsOnLayer() const {
Chris Craik76caecf2015-11-02 19:17:45 -0800614 const DeviceInfo* deviceInfo = DeviceInfo::get();
Chris Craik9fded232015-11-11 16:42:34 -0800615 return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
Chris Craike3e481d2016-07-11 12:20:51 -0700616 && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
Chris Craik9fded232015-11-11 16:42:34 -0800617 }
618
619 bool promotedToLayer() const {
Chris Craik1a0808e2015-05-13 16:33:04 -0700620 return mLayerProperties.mType == LayerType::None
Chris Craik9fded232015-11-11 16:42:34 -0800621 && fitsOnLayer()
Chris Craika766cb22015-06-08 16:49:43 -0700622 && (mComputedFields.mNeedLayerForFunctors
623 || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
624 && mPrimitiveFields.mAlpha < 1
625 && mPrimitiveFields.mHasOverlappingRendering));
Chris Craik1a0808e2015-05-13 16:33:04 -0700626 }
627
628 LayerType effectiveLayerType() const {
Chris Craika766cb22015-06-08 16:49:43 -0700629 return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
Chris Craik856f0cc2015-04-21 15:13:29 -0700630 }
631
John Reckacb6f072014-03-12 16:11:23 -0700632private:
John Reckacb6f072014-03-12 16:11:23 -0700633 // Rendering properties
John Reckd0a0b2a2014-03-20 16:28:56 -0700634 struct PrimitiveFields {
John Recke248bd12015-08-05 13:53:53 -0700635 int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
636 int mWidth = 0, mHeight = 0;
637 int mClippingFlags = CLIP_TO_BOUNDS;
638 float mAlpha = 1;
639 float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
640 float mElevation = 0;
641 float mRotation = 0, mRotationX = 0, mRotationY = 0;
642 float mScaleX = 1, mScaleY = 1;
643 float mPivotX = 0, mPivotY = 0;
644 bool mHasOverlappingRendering = false;
645 bool mPivotExplicitlySet = false;
646 bool mMatrixOrPivotDirty = false;
647 bool mProjectBackwards = false;
648 bool mProjectionReceiver = false;
649 Rect mClipBounds;
John Reckd0a0b2a2014-03-20 16:28:56 -0700650 Outline mOutline;
Chris Craik8c271ca2014-03-25 10:33:01 -0700651 RevealClip mRevealClip;
John Reckd0a0b2a2014-03-20 16:28:56 -0700652 } mPrimitiveFields;
653
John Reckacb6f072014-03-12 16:11:23 -0700654 SkMatrix* mStaticMatrix;
655 SkMatrix* mAnimationMatrix;
John Reck25fbb3f2014-06-12 13:46:45 -0700656 LayerProperties mLayerProperties;
John Reckacb6f072014-03-12 16:11:23 -0700657
John Reckd0a0b2a2014-03-20 16:28:56 -0700658 /**
659 * These fields are all generated from other properties and are not set directly.
660 */
661 struct ComputedFields {
662 ComputedFields();
663 ~ComputedFields();
664
665 /**
666 * Stores the total transformation of the DisplayList based upon its scalar
667 * translate/rotate/scale properties.
668 *
Chris Craik49e6c732014-03-31 12:34:11 -0700669 * In the common translation-only case, the matrix isn't necessarily allocated,
670 * and the mTranslation properties are used directly.
John Reckd0a0b2a2014-03-20 16:28:56 -0700671 */
Chris Craik49e6c732014-03-31 12:34:11 -0700672 SkMatrix* mTransformMatrix;
673
674 Sk3DView mTransformCamera;
Chris Craika766cb22015-06-08 16:49:43 -0700675
676 // Force layer on for functors to enable render features they don't yet support (clipping)
677 bool mNeedLayerForFunctors = false;
John Reckd0a0b2a2014-03-20 16:28:56 -0700678 } mComputedFields;
John Reckacb6f072014-03-12 16:11:23 -0700679};
680
681} /* namespace uirenderer */
682} /* namespace android */