xref: /aosp_15_r20/frameworks/base/libs/hwui/RenderProperties.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #pragma once
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include <SkBlendMode.h>
20*d57664e9SAndroid Build Coastguard Worker #include <SkCamera.h>
21*d57664e9SAndroid Build Coastguard Worker #include <SkColor.h>
22*d57664e9SAndroid Build Coastguard Worker #include <SkImageFilter.h>
23*d57664e9SAndroid Build Coastguard Worker #include <SkMatrix.h>
24*d57664e9SAndroid Build Coastguard Worker #include <SkRegion.h>
25*d57664e9SAndroid Build Coastguard Worker #include <androidfw/ResourceTypes.h>
26*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h>
27*d57664e9SAndroid Build Coastguard Worker #include <stddef.h>
28*d57664e9SAndroid Build Coastguard Worker #include <utils/Log.h>
29*d57664e9SAndroid Build Coastguard Worker 
30*d57664e9SAndroid Build Coastguard Worker #include <algorithm>
31*d57664e9SAndroid Build Coastguard Worker #include <ostream>
32*d57664e9SAndroid Build Coastguard Worker #include <vector>
33*d57664e9SAndroid Build Coastguard Worker 
34*d57664e9SAndroid Build Coastguard Worker #include "DeviceInfo.h"
35*d57664e9SAndroid Build Coastguard Worker #include "Outline.h"
36*d57664e9SAndroid Build Coastguard Worker #include "Rect.h"
37*d57664e9SAndroid Build Coastguard Worker #include "RevealClip.h"
38*d57664e9SAndroid Build Coastguard Worker #include "effects/StretchEffect.h"
39*d57664e9SAndroid Build Coastguard Worker #include "utils/MathUtils.h"
40*d57664e9SAndroid Build Coastguard Worker #include "utils/PaintUtils.h"
41*d57664e9SAndroid Build Coastguard Worker 
42*d57664e9SAndroid Build Coastguard Worker class SkBitmap;
43*d57664e9SAndroid Build Coastguard Worker class SkColorFilter;
44*d57664e9SAndroid Build Coastguard Worker class SkPaint;
45*d57664e9SAndroid Build Coastguard Worker 
46*d57664e9SAndroid Build Coastguard Worker namespace android {
47*d57664e9SAndroid Build Coastguard Worker namespace uirenderer {
48*d57664e9SAndroid Build Coastguard Worker 
49*d57664e9SAndroid Build Coastguard Worker class Matrix4;
50*d57664e9SAndroid Build Coastguard Worker class RenderNode;
51*d57664e9SAndroid Build Coastguard Worker class RenderProperties;
52*d57664e9SAndroid Build Coastguard Worker 
53*d57664e9SAndroid Build Coastguard Worker // The __VA_ARGS__ will be executed if a & b are not equal
54*d57664e9SAndroid Build Coastguard Worker #define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false)
55*d57664e9SAndroid Build Coastguard Worker #define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
56*d57664e9SAndroid Build Coastguard Worker 
57*d57664e9SAndroid Build Coastguard Worker // Keep in sync with View.java:LAYER_TYPE_*
58*d57664e9SAndroid Build Coastguard Worker enum class LayerType {
59*d57664e9SAndroid Build Coastguard Worker     None = 0,
60*d57664e9SAndroid Build Coastguard Worker     // We cannot build the software layer directly (must be done at record time) and all management
61*d57664e9SAndroid Build Coastguard Worker     // of software layers is handled in Java.
62*d57664e9SAndroid Build Coastguard Worker     Software = 1,
63*d57664e9SAndroid Build Coastguard Worker     RenderLayer = 2,
64*d57664e9SAndroid Build Coastguard Worker };
65*d57664e9SAndroid Build Coastguard Worker 
66*d57664e9SAndroid Build Coastguard Worker enum ClippingFlags {
67*d57664e9SAndroid Build Coastguard Worker     CLIP_TO_BOUNDS = 0x1 << 0,
68*d57664e9SAndroid Build Coastguard Worker     CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
69*d57664e9SAndroid Build Coastguard Worker };
70*d57664e9SAndroid Build Coastguard Worker 
71*d57664e9SAndroid Build Coastguard Worker class LayerProperties {
72*d57664e9SAndroid Build Coastguard Worker public:
setType(LayerType type)73*d57664e9SAndroid Build Coastguard Worker     bool setType(LayerType type) {
74*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mType, type)) {
75*d57664e9SAndroid Build Coastguard Worker             reset();
76*d57664e9SAndroid Build Coastguard Worker             return true;
77*d57664e9SAndroid Build Coastguard Worker         }
78*d57664e9SAndroid Build Coastguard Worker         return false;
79*d57664e9SAndroid Build Coastguard Worker     }
80*d57664e9SAndroid Build Coastguard Worker 
setOpaque(bool opaque)81*d57664e9SAndroid Build Coastguard Worker     bool setOpaque(bool opaque) { return RP_SET(mOpaque, opaque); }
82*d57664e9SAndroid Build Coastguard Worker 
opaque()83*d57664e9SAndroid Build Coastguard Worker     bool opaque() const { return mOpaque; }
84*d57664e9SAndroid Build Coastguard Worker 
setAlpha(uint8_t alpha)85*d57664e9SAndroid Build Coastguard Worker     bool setAlpha(uint8_t alpha) { return RP_SET(mAlpha, alpha); }
86*d57664e9SAndroid Build Coastguard Worker 
alpha()87*d57664e9SAndroid Build Coastguard Worker     uint8_t alpha() const { return mAlpha; }
88*d57664e9SAndroid Build Coastguard Worker 
setXferMode(SkBlendMode mode)89*d57664e9SAndroid Build Coastguard Worker     bool setXferMode(SkBlendMode mode) { return RP_SET(mMode, mode); }
90*d57664e9SAndroid Build Coastguard Worker 
xferMode()91*d57664e9SAndroid Build Coastguard Worker     SkBlendMode xferMode() const { return mMode; }
92*d57664e9SAndroid Build Coastguard Worker 
getColorFilter()93*d57664e9SAndroid Build Coastguard Worker     SkColorFilter* getColorFilter() const { return mColorFilter.get(); }
94*d57664e9SAndroid Build Coastguard Worker 
95*d57664e9SAndroid Build Coastguard Worker     bool setImageFilter(SkImageFilter* imageFilter);
96*d57664e9SAndroid Build Coastguard Worker 
97*d57664e9SAndroid Build Coastguard Worker     bool setBackdropImageFilter(SkImageFilter* imageFilter);
98*d57664e9SAndroid Build Coastguard Worker 
getImageFilter()99*d57664e9SAndroid Build Coastguard Worker     SkImageFilter* getImageFilter() const { return mImageFilter.get(); }
100*d57664e9SAndroid Build Coastguard Worker 
getBackdropImageFilter()101*d57664e9SAndroid Build Coastguard Worker     SkImageFilter* getBackdropImageFilter() const { return mBackdropImageFilter.get(); }
102*d57664e9SAndroid Build Coastguard Worker 
getStretchEffect()103*d57664e9SAndroid Build Coastguard Worker     const StretchEffect& getStretchEffect() const { return mStretchEffect; }
104*d57664e9SAndroid Build Coastguard Worker 
mutableStretchEffect()105*d57664e9SAndroid Build Coastguard Worker     StretchEffect& mutableStretchEffect() { return mStretchEffect; }
106*d57664e9SAndroid Build Coastguard Worker 
107*d57664e9SAndroid Build Coastguard Worker     // Sets alpha, xfermode, and colorfilter from an SkPaint
108*d57664e9SAndroid Build Coastguard Worker     // paint may be NULL, in which case defaults will be set
109*d57664e9SAndroid Build Coastguard Worker     bool setFromPaint(const SkPaint* paint);
110*d57664e9SAndroid Build Coastguard Worker 
needsBlending()111*d57664e9SAndroid Build Coastguard Worker     bool needsBlending() const { return !opaque() || alpha() < 255; }
112*d57664e9SAndroid Build Coastguard Worker 
113*d57664e9SAndroid Build Coastguard Worker     LayerProperties& operator=(const LayerProperties& other);
114*d57664e9SAndroid Build Coastguard Worker 
115*d57664e9SAndroid Build Coastguard Worker     // Strongly recommend using effectiveLayerType instead
type()116*d57664e9SAndroid Build Coastguard Worker     LayerType type() const { return mType; }
117*d57664e9SAndroid Build Coastguard Worker 
118*d57664e9SAndroid Build Coastguard Worker private:
119*d57664e9SAndroid Build Coastguard Worker     LayerProperties();
120*d57664e9SAndroid Build Coastguard Worker     ~LayerProperties();
121*d57664e9SAndroid Build Coastguard Worker     void reset();
122*d57664e9SAndroid Build Coastguard Worker     bool setColorFilter(SkColorFilter* filter);
123*d57664e9SAndroid Build Coastguard Worker 
124*d57664e9SAndroid Build Coastguard Worker     friend class RenderProperties;
125*d57664e9SAndroid Build Coastguard Worker 
126*d57664e9SAndroid Build Coastguard Worker     LayerType mType = LayerType::None;
127*d57664e9SAndroid Build Coastguard Worker     // Whether or not that Layer's content is opaque, doesn't include alpha
128*d57664e9SAndroid Build Coastguard Worker     bool mOpaque;
129*d57664e9SAndroid Build Coastguard Worker     uint8_t mAlpha;
130*d57664e9SAndroid Build Coastguard Worker     SkBlendMode mMode;
131*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkColorFilter> mColorFilter;
132*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkImageFilter> mImageFilter;
133*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkImageFilter> mBackdropImageFilter;
134*d57664e9SAndroid Build Coastguard Worker     StretchEffect mStretchEffect;
135*d57664e9SAndroid Build Coastguard Worker };
136*d57664e9SAndroid Build Coastguard Worker 
137*d57664e9SAndroid Build Coastguard Worker /*
138*d57664e9SAndroid Build Coastguard Worker  * Data structure that holds the properties for a RenderNode
139*d57664e9SAndroid Build Coastguard Worker  */
140*d57664e9SAndroid Build Coastguard Worker class RenderProperties {
141*d57664e9SAndroid Build Coastguard Worker public:
142*d57664e9SAndroid Build Coastguard Worker     RenderProperties();
143*d57664e9SAndroid Build Coastguard Worker     virtual ~RenderProperties();
144*d57664e9SAndroid Build Coastguard Worker 
setFlag(int flag,bool newValue,int * outFlags)145*d57664e9SAndroid Build Coastguard Worker     static bool setFlag(int flag, bool newValue, int* outFlags) {
146*d57664e9SAndroid Build Coastguard Worker         if (newValue) {
147*d57664e9SAndroid Build Coastguard Worker             if (!(flag & *outFlags)) {
148*d57664e9SAndroid Build Coastguard Worker                 *outFlags |= flag;
149*d57664e9SAndroid Build Coastguard Worker                 return true;
150*d57664e9SAndroid Build Coastguard Worker             }
151*d57664e9SAndroid Build Coastguard Worker             return false;
152*d57664e9SAndroid Build Coastguard Worker         } else {
153*d57664e9SAndroid Build Coastguard Worker             if (flag & *outFlags) {
154*d57664e9SAndroid Build Coastguard Worker                 *outFlags &= ~flag;
155*d57664e9SAndroid Build Coastguard Worker                 return true;
156*d57664e9SAndroid Build Coastguard Worker             }
157*d57664e9SAndroid Build Coastguard Worker             return false;
158*d57664e9SAndroid Build Coastguard Worker         }
159*d57664e9SAndroid Build Coastguard Worker     }
160*d57664e9SAndroid Build Coastguard Worker 
161*d57664e9SAndroid Build Coastguard Worker     /**
162*d57664e9SAndroid Build Coastguard Worker      * Set internal layer state based on whether this layer
163*d57664e9SAndroid Build Coastguard Worker      *
164*d57664e9SAndroid Build Coastguard Worker      * Additionally, returns true if child RenderNodes with functors will need to use a layer
165*d57664e9SAndroid Build Coastguard Worker      * to support clipping.
166*d57664e9SAndroid Build Coastguard Worker      */
prepareForFunctorPresence(bool willHaveFunctor,bool ancestorDictatesFunctorsNeedLayer)167*d57664e9SAndroid Build Coastguard Worker     bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
168*d57664e9SAndroid Build Coastguard Worker         // parent may have already dictated that a descendant layer is needed
169*d57664e9SAndroid Build Coastguard Worker         bool functorsNeedLayer =
170*d57664e9SAndroid Build Coastguard Worker                 ancestorDictatesFunctorsNeedLayer ||
171*d57664e9SAndroid Build Coastguard Worker                 CC_UNLIKELY(isClipMayBeComplex())
172*d57664e9SAndroid Build Coastguard Worker 
173*d57664e9SAndroid Build Coastguard Worker                 // Round rect clipping forces layer for functors
174*d57664e9SAndroid Build Coastguard Worker                 || CC_UNLIKELY(getOutline().willComplexClip()) ||
175*d57664e9SAndroid Build Coastguard Worker                 CC_UNLIKELY(getRevealClip().willClip())
176*d57664e9SAndroid Build Coastguard Worker 
177*d57664e9SAndroid Build Coastguard Worker                 // Complex matrices forces layer, due to stencil clipping
178*d57664e9SAndroid Build Coastguard Worker                 || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate()) ||
179*d57664e9SAndroid Build Coastguard Worker                 CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate()) ||
180*d57664e9SAndroid Build Coastguard Worker                 CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
181*d57664e9SAndroid Build Coastguard Worker 
182*d57664e9SAndroid Build Coastguard Worker         mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
183*d57664e9SAndroid Build Coastguard Worker 
184*d57664e9SAndroid Build Coastguard Worker         // If on a layer, will have consumed the need for isolating functors from stencil.
185*d57664e9SAndroid Build Coastguard Worker         // Thus, it's safe to reset the flag until some descendent sets it.
186*d57664e9SAndroid Build Coastguard Worker         return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
187*d57664e9SAndroid Build Coastguard Worker     }
188*d57664e9SAndroid Build Coastguard Worker 
189*d57664e9SAndroid Build Coastguard Worker     RenderProperties& operator=(const RenderProperties& other);
190*d57664e9SAndroid Build Coastguard Worker 
setClipToBounds(bool clipToBounds)191*d57664e9SAndroid Build Coastguard Worker     bool setClipToBounds(bool clipToBounds) {
192*d57664e9SAndroid Build Coastguard Worker         return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
193*d57664e9SAndroid Build Coastguard Worker     }
194*d57664e9SAndroid Build Coastguard Worker 
setClipBounds(const Rect & clipBounds)195*d57664e9SAndroid Build Coastguard Worker     bool setClipBounds(const Rect& clipBounds) {
196*d57664e9SAndroid Build Coastguard Worker         bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
197*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
198*d57664e9SAndroid Build Coastguard Worker     }
199*d57664e9SAndroid Build Coastguard Worker 
setClipBoundsEmpty()200*d57664e9SAndroid Build Coastguard Worker     bool setClipBoundsEmpty() {
201*d57664e9SAndroid Build Coastguard Worker         return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
202*d57664e9SAndroid Build Coastguard Worker     }
203*d57664e9SAndroid Build Coastguard Worker 
setProjectBackwards(bool shouldProject)204*d57664e9SAndroid Build Coastguard Worker     bool setProjectBackwards(bool shouldProject) {
205*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
206*d57664e9SAndroid Build Coastguard Worker     }
207*d57664e9SAndroid Build Coastguard Worker 
setProjectionReceiver(bool shouldReceive)208*d57664e9SAndroid Build Coastguard Worker     bool setProjectionReceiver(bool shouldReceive) {
209*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
210*d57664e9SAndroid Build Coastguard Worker     }
211*d57664e9SAndroid Build Coastguard Worker 
isProjectionReceiver()212*d57664e9SAndroid Build Coastguard Worker     bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; }
213*d57664e9SAndroid Build Coastguard Worker 
setClipMayBeComplex(bool isClipMayBeComplex)214*d57664e9SAndroid Build Coastguard Worker     bool setClipMayBeComplex(bool isClipMayBeComplex) {
215*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mClipMayBeComplex, isClipMayBeComplex);
216*d57664e9SAndroid Build Coastguard Worker     }
217*d57664e9SAndroid Build Coastguard Worker 
isClipMayBeComplex()218*d57664e9SAndroid Build Coastguard Worker     bool isClipMayBeComplex() const { return mPrimitiveFields.mClipMayBeComplex; }
219*d57664e9SAndroid Build Coastguard Worker 
setStaticMatrix(const SkMatrix * matrix)220*d57664e9SAndroid Build Coastguard Worker     bool setStaticMatrix(const SkMatrix* matrix) {
221*d57664e9SAndroid Build Coastguard Worker         delete mStaticMatrix;
222*d57664e9SAndroid Build Coastguard Worker         if (matrix) {
223*d57664e9SAndroid Build Coastguard Worker             mStaticMatrix = new SkMatrix(*matrix);
224*d57664e9SAndroid Build Coastguard Worker         } else {
225*d57664e9SAndroid Build Coastguard Worker             mStaticMatrix = nullptr;
226*d57664e9SAndroid Build Coastguard Worker         }
227*d57664e9SAndroid Build Coastguard Worker         return true;
228*d57664e9SAndroid Build Coastguard Worker     }
229*d57664e9SAndroid Build Coastguard Worker 
230*d57664e9SAndroid Build Coastguard Worker     // Can return NULL
getStaticMatrix()231*d57664e9SAndroid Build Coastguard Worker     const SkMatrix* getStaticMatrix() const { return mStaticMatrix; }
232*d57664e9SAndroid Build Coastguard Worker 
setAnimationMatrix(const SkMatrix * matrix)233*d57664e9SAndroid Build Coastguard Worker     bool setAnimationMatrix(const SkMatrix* matrix) {
234*d57664e9SAndroid Build Coastguard Worker         delete mAnimationMatrix;
235*d57664e9SAndroid Build Coastguard Worker         if (matrix) {
236*d57664e9SAndroid Build Coastguard Worker             mAnimationMatrix = new SkMatrix(*matrix);
237*d57664e9SAndroid Build Coastguard Worker         } else {
238*d57664e9SAndroid Build Coastguard Worker             mAnimationMatrix = nullptr;
239*d57664e9SAndroid Build Coastguard Worker         }
240*d57664e9SAndroid Build Coastguard Worker         return true;
241*d57664e9SAndroid Build Coastguard Worker     }
242*d57664e9SAndroid Build Coastguard Worker 
setAlpha(float alpha)243*d57664e9SAndroid Build Coastguard Worker     bool setAlpha(float alpha) {
244*d57664e9SAndroid Build Coastguard Worker         alpha = MathUtils::clampAlpha(alpha);
245*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mAlpha, alpha);
246*d57664e9SAndroid Build Coastguard Worker     }
247*d57664e9SAndroid Build Coastguard Worker 
getAlpha()248*d57664e9SAndroid Build Coastguard Worker     float getAlpha() const { return mPrimitiveFields.mAlpha; }
249*d57664e9SAndroid Build Coastguard Worker 
setHasOverlappingRendering(bool hasOverlappingRendering)250*d57664e9SAndroid Build Coastguard Worker     bool setHasOverlappingRendering(bool hasOverlappingRendering) {
251*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
252*d57664e9SAndroid Build Coastguard Worker     }
253*d57664e9SAndroid Build Coastguard Worker 
hasOverlappingRendering()254*d57664e9SAndroid Build Coastguard Worker     bool hasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; }
255*d57664e9SAndroid Build Coastguard Worker 
setElevation(float elevation)256*d57664e9SAndroid Build Coastguard Worker     bool setElevation(float elevation) {
257*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mElevation, elevation);
258*d57664e9SAndroid Build Coastguard Worker         // Don't dirty matrix/pivot, since they don't respect Z
259*d57664e9SAndroid Build Coastguard Worker     }
260*d57664e9SAndroid Build Coastguard Worker 
getElevation()261*d57664e9SAndroid Build Coastguard Worker     float getElevation() const { return mPrimitiveFields.mElevation; }
262*d57664e9SAndroid Build Coastguard Worker 
setTranslationX(float translationX)263*d57664e9SAndroid Build Coastguard Worker     bool setTranslationX(float translationX) {
264*d57664e9SAndroid Build Coastguard Worker         return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
265*d57664e9SAndroid Build Coastguard Worker     }
266*d57664e9SAndroid Build Coastguard Worker 
getTranslationX()267*d57664e9SAndroid Build Coastguard Worker     float getTranslationX() const { return mPrimitiveFields.mTranslationX; }
268*d57664e9SAndroid Build Coastguard Worker 
setTranslationY(float translationY)269*d57664e9SAndroid Build Coastguard Worker     bool setTranslationY(float translationY) {
270*d57664e9SAndroid Build Coastguard Worker         return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
271*d57664e9SAndroid Build Coastguard Worker     }
272*d57664e9SAndroid Build Coastguard Worker 
getTranslationY()273*d57664e9SAndroid Build Coastguard Worker     float getTranslationY() const { return mPrimitiveFields.mTranslationY; }
274*d57664e9SAndroid Build Coastguard Worker 
setTranslationZ(float translationZ)275*d57664e9SAndroid Build Coastguard Worker     bool setTranslationZ(float translationZ) {
276*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
277*d57664e9SAndroid Build Coastguard Worker         // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
278*d57664e9SAndroid Build Coastguard Worker     }
279*d57664e9SAndroid Build Coastguard Worker 
getTranslationZ()280*d57664e9SAndroid Build Coastguard Worker     float getTranslationZ() const { return mPrimitiveFields.mTranslationZ; }
281*d57664e9SAndroid Build Coastguard Worker 
282*d57664e9SAndroid Build Coastguard Worker     // Animation helper
setX(float value)283*d57664e9SAndroid Build Coastguard Worker     bool setX(float value) { return setTranslationX(value - getLeft()); }
284*d57664e9SAndroid Build Coastguard Worker 
285*d57664e9SAndroid Build Coastguard Worker     // Animation helper
getX()286*d57664e9SAndroid Build Coastguard Worker     float getX() const { return getLeft() + getTranslationX(); }
287*d57664e9SAndroid Build Coastguard Worker 
288*d57664e9SAndroid Build Coastguard Worker     // Animation helper
setY(float value)289*d57664e9SAndroid Build Coastguard Worker     bool setY(float value) { return setTranslationY(value - getTop()); }
290*d57664e9SAndroid Build Coastguard Worker 
291*d57664e9SAndroid Build Coastguard Worker     // Animation helper
getY()292*d57664e9SAndroid Build Coastguard Worker     float getY() const { return getTop() + getTranslationY(); }
293*d57664e9SAndroid Build Coastguard Worker 
294*d57664e9SAndroid Build Coastguard Worker     // Animation helper
setZ(float value)295*d57664e9SAndroid Build Coastguard Worker     bool setZ(float value) { return setTranslationZ(value - getElevation()); }
296*d57664e9SAndroid Build Coastguard Worker 
getZ()297*d57664e9SAndroid Build Coastguard Worker     float getZ() const { return getElevation() + getTranslationZ(); }
298*d57664e9SAndroid Build Coastguard Worker 
setRotation(float rotation)299*d57664e9SAndroid Build Coastguard Worker     bool setRotation(float rotation) {
300*d57664e9SAndroid Build Coastguard Worker         return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
301*d57664e9SAndroid Build Coastguard Worker     }
302*d57664e9SAndroid Build Coastguard Worker 
getRotation()303*d57664e9SAndroid Build Coastguard Worker     float getRotation() const { return mPrimitiveFields.mRotation; }
304*d57664e9SAndroid Build Coastguard Worker 
setRotationX(float rotationX)305*d57664e9SAndroid Build Coastguard Worker     bool setRotationX(float rotationX) {
306*d57664e9SAndroid Build Coastguard Worker         return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
307*d57664e9SAndroid Build Coastguard Worker     }
308*d57664e9SAndroid Build Coastguard Worker 
getRotationX()309*d57664e9SAndroid Build Coastguard Worker     float getRotationX() const { return mPrimitiveFields.mRotationX; }
310*d57664e9SAndroid Build Coastguard Worker 
setRotationY(float rotationY)311*d57664e9SAndroid Build Coastguard Worker     bool setRotationY(float rotationY) {
312*d57664e9SAndroid Build Coastguard Worker         return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
313*d57664e9SAndroid Build Coastguard Worker     }
314*d57664e9SAndroid Build Coastguard Worker 
getRotationY()315*d57664e9SAndroid Build Coastguard Worker     float getRotationY() const { return mPrimitiveFields.mRotationY; }
316*d57664e9SAndroid Build Coastguard Worker 
setScaleX(float scaleX)317*d57664e9SAndroid Build Coastguard Worker     bool setScaleX(float scaleX) { return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX); }
318*d57664e9SAndroid Build Coastguard Worker 
getScaleX()319*d57664e9SAndroid Build Coastguard Worker     float getScaleX() const { return mPrimitiveFields.mScaleX; }
320*d57664e9SAndroid Build Coastguard Worker 
setScaleY(float scaleY)321*d57664e9SAndroid Build Coastguard Worker     bool setScaleY(float scaleY) { return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY); }
322*d57664e9SAndroid Build Coastguard Worker 
getScaleY()323*d57664e9SAndroid Build Coastguard Worker     float getScaleY() const { return mPrimitiveFields.mScaleY; }
324*d57664e9SAndroid Build Coastguard Worker 
setPivotX(float pivotX)325*d57664e9SAndroid Build Coastguard Worker     bool setPivotX(float pivotX) {
326*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mPrimitiveFields.mPivotX, pivotX) || !mPrimitiveFields.mPivotExplicitlySet) {
327*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mMatrixOrPivotDirty = true;
328*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mPivotExplicitlySet = true;
329*d57664e9SAndroid Build Coastguard Worker             return true;
330*d57664e9SAndroid Build Coastguard Worker         }
331*d57664e9SAndroid Build Coastguard Worker         return false;
332*d57664e9SAndroid Build Coastguard Worker     }
333*d57664e9SAndroid Build Coastguard Worker 
334*d57664e9SAndroid Build Coastguard Worker     /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
335*d57664e9SAndroid Build Coastguard Worker      * so the value returned may be stale if the RenderProperties has been
336*d57664e9SAndroid Build Coastguard Worker      * modified since the last call to updateMatrix()
337*d57664e9SAndroid Build Coastguard Worker      */
getPivotX()338*d57664e9SAndroid Build Coastguard Worker     float getPivotX() const { return mPrimitiveFields.mPivotX; }
339*d57664e9SAndroid Build Coastguard Worker 
setPivotY(float pivotY)340*d57664e9SAndroid Build Coastguard Worker     bool setPivotY(float pivotY) {
341*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mPrimitiveFields.mPivotY, pivotY) || !mPrimitiveFields.mPivotExplicitlySet) {
342*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mMatrixOrPivotDirty = true;
343*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mPivotExplicitlySet = true;
344*d57664e9SAndroid Build Coastguard Worker             return true;
345*d57664e9SAndroid Build Coastguard Worker         }
346*d57664e9SAndroid Build Coastguard Worker         return false;
347*d57664e9SAndroid Build Coastguard Worker     }
348*d57664e9SAndroid Build Coastguard Worker 
getPivotY()349*d57664e9SAndroid Build Coastguard Worker     float getPivotY() const { return mPrimitiveFields.mPivotY; }
350*d57664e9SAndroid Build Coastguard Worker 
isPivotExplicitlySet()351*d57664e9SAndroid Build Coastguard Worker     bool isPivotExplicitlySet() const { return mPrimitiveFields.mPivotExplicitlySet; }
352*d57664e9SAndroid Build Coastguard Worker 
resetPivot()353*d57664e9SAndroid Build Coastguard Worker     bool resetPivot() { return RP_SET_AND_DIRTY(mPrimitiveFields.mPivotExplicitlySet, false); }
354*d57664e9SAndroid Build Coastguard Worker 
setCameraDistance(float distance)355*d57664e9SAndroid Build Coastguard Worker     bool setCameraDistance(float distance) {
356*d57664e9SAndroid Build Coastguard Worker         if (distance != getCameraDistance()) {
357*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mMatrixOrPivotDirty = true;
358*d57664e9SAndroid Build Coastguard Worker             mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
359*d57664e9SAndroid Build Coastguard Worker             return true;
360*d57664e9SAndroid Build Coastguard Worker         }
361*d57664e9SAndroid Build Coastguard Worker         return false;
362*d57664e9SAndroid Build Coastguard Worker     }
363*d57664e9SAndroid Build Coastguard Worker 
getCameraDistance()364*d57664e9SAndroid Build Coastguard Worker     float getCameraDistance() const {
365*d57664e9SAndroid Build Coastguard Worker         // TODO: update getCameraLocationZ() to be const
366*d57664e9SAndroid Build Coastguard Worker         return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
367*d57664e9SAndroid Build Coastguard Worker     }
368*d57664e9SAndroid Build Coastguard Worker 
setLeft(int left)369*d57664e9SAndroid Build Coastguard Worker     bool setLeft(int left) {
370*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mPrimitiveFields.mLeft, left)) {
371*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
372*d57664e9SAndroid Build Coastguard Worker             if (!mPrimitiveFields.mPivotExplicitlySet) {
373*d57664e9SAndroid Build Coastguard Worker                 mPrimitiveFields.mMatrixOrPivotDirty = true;
374*d57664e9SAndroid Build Coastguard Worker             }
375*d57664e9SAndroid Build Coastguard Worker             return true;
376*d57664e9SAndroid Build Coastguard Worker         }
377*d57664e9SAndroid Build Coastguard Worker         return false;
378*d57664e9SAndroid Build Coastguard Worker     }
379*d57664e9SAndroid Build Coastguard Worker 
getLeft()380*d57664e9SAndroid Build Coastguard Worker     int getLeft() const { return mPrimitiveFields.mLeft; }
381*d57664e9SAndroid Build Coastguard Worker 
setTop(int top)382*d57664e9SAndroid Build Coastguard Worker     bool setTop(int top) {
383*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mPrimitiveFields.mTop, top)) {
384*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
385*d57664e9SAndroid Build Coastguard Worker             if (!mPrimitiveFields.mPivotExplicitlySet) {
386*d57664e9SAndroid Build Coastguard Worker                 mPrimitiveFields.mMatrixOrPivotDirty = true;
387*d57664e9SAndroid Build Coastguard Worker             }
388*d57664e9SAndroid Build Coastguard Worker             return true;
389*d57664e9SAndroid Build Coastguard Worker         }
390*d57664e9SAndroid Build Coastguard Worker         return false;
391*d57664e9SAndroid Build Coastguard Worker     }
392*d57664e9SAndroid Build Coastguard Worker 
getTop()393*d57664e9SAndroid Build Coastguard Worker     int getTop() const { return mPrimitiveFields.mTop; }
394*d57664e9SAndroid Build Coastguard Worker 
setRight(int right)395*d57664e9SAndroid Build Coastguard Worker     bool setRight(int right) {
396*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mPrimitiveFields.mRight, right)) {
397*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
398*d57664e9SAndroid Build Coastguard Worker             if (!mPrimitiveFields.mPivotExplicitlySet) {
399*d57664e9SAndroid Build Coastguard Worker                 mPrimitiveFields.mMatrixOrPivotDirty = true;
400*d57664e9SAndroid Build Coastguard Worker             }
401*d57664e9SAndroid Build Coastguard Worker             return true;
402*d57664e9SAndroid Build Coastguard Worker         }
403*d57664e9SAndroid Build Coastguard Worker         return false;
404*d57664e9SAndroid Build Coastguard Worker     }
405*d57664e9SAndroid Build Coastguard Worker 
getRight()406*d57664e9SAndroid Build Coastguard Worker     int getRight() const { return mPrimitiveFields.mRight; }
407*d57664e9SAndroid Build Coastguard Worker 
setBottom(int bottom)408*d57664e9SAndroid Build Coastguard Worker     bool setBottom(int bottom) {
409*d57664e9SAndroid Build Coastguard Worker         if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
410*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
411*d57664e9SAndroid Build Coastguard Worker             if (!mPrimitiveFields.mPivotExplicitlySet) {
412*d57664e9SAndroid Build Coastguard Worker                 mPrimitiveFields.mMatrixOrPivotDirty = true;
413*d57664e9SAndroid Build Coastguard Worker             }
414*d57664e9SAndroid Build Coastguard Worker             return true;
415*d57664e9SAndroid Build Coastguard Worker         }
416*d57664e9SAndroid Build Coastguard Worker         return false;
417*d57664e9SAndroid Build Coastguard Worker     }
418*d57664e9SAndroid Build Coastguard Worker 
getBottom()419*d57664e9SAndroid Build Coastguard Worker     int getBottom() const { return mPrimitiveFields.mBottom; }
420*d57664e9SAndroid Build Coastguard Worker 
setLeftTop(int left,int top)421*d57664e9SAndroid Build Coastguard Worker     bool setLeftTop(int left, int top) {
422*d57664e9SAndroid Build Coastguard Worker         bool leftResult = setLeft(left);
423*d57664e9SAndroid Build Coastguard Worker         bool topResult = setTop(top);
424*d57664e9SAndroid Build Coastguard Worker         return leftResult || topResult;
425*d57664e9SAndroid Build Coastguard Worker     }
426*d57664e9SAndroid Build Coastguard Worker 
setLeftTopRightBottom(int left,int top,int right,int bottom)427*d57664e9SAndroid Build Coastguard Worker     bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
428*d57664e9SAndroid Build Coastguard Worker         if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop ||
429*d57664e9SAndroid Build Coastguard Worker             right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
430*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mLeft = left;
431*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mTop = top;
432*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mRight = right;
433*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mBottom = bottom;
434*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
435*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
436*d57664e9SAndroid Build Coastguard Worker             if (!mPrimitiveFields.mPivotExplicitlySet) {
437*d57664e9SAndroid Build Coastguard Worker                 mPrimitiveFields.mMatrixOrPivotDirty = true;
438*d57664e9SAndroid Build Coastguard Worker             }
439*d57664e9SAndroid Build Coastguard Worker             return true;
440*d57664e9SAndroid Build Coastguard Worker         }
441*d57664e9SAndroid Build Coastguard Worker         return false;
442*d57664e9SAndroid Build Coastguard Worker     }
443*d57664e9SAndroid Build Coastguard Worker 
offsetLeftRight(int offset)444*d57664e9SAndroid Build Coastguard Worker     bool offsetLeftRight(int offset) {
445*d57664e9SAndroid Build Coastguard Worker         if (offset != 0) {
446*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mLeft += offset;
447*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mRight += offset;
448*d57664e9SAndroid Build Coastguard Worker             return true;
449*d57664e9SAndroid Build Coastguard Worker         }
450*d57664e9SAndroid Build Coastguard Worker         return false;
451*d57664e9SAndroid Build Coastguard Worker     }
452*d57664e9SAndroid Build Coastguard Worker 
offsetTopBottom(int offset)453*d57664e9SAndroid Build Coastguard Worker     bool offsetTopBottom(int offset) {
454*d57664e9SAndroid Build Coastguard Worker         if (offset != 0) {
455*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mTop += offset;
456*d57664e9SAndroid Build Coastguard Worker             mPrimitiveFields.mBottom += offset;
457*d57664e9SAndroid Build Coastguard Worker             return true;
458*d57664e9SAndroid Build Coastguard Worker         }
459*d57664e9SAndroid Build Coastguard Worker         return false;
460*d57664e9SAndroid Build Coastguard Worker     }
461*d57664e9SAndroid Build Coastguard Worker 
getWidth()462*d57664e9SAndroid Build Coastguard Worker     int getWidth() const { return mPrimitiveFields.mWidth; }
463*d57664e9SAndroid Build Coastguard Worker 
getHeight()464*d57664e9SAndroid Build Coastguard Worker     int getHeight() const { return mPrimitiveFields.mHeight; }
465*d57664e9SAndroid Build Coastguard Worker 
getAnimationMatrix()466*d57664e9SAndroid Build Coastguard Worker     const SkMatrix* getAnimationMatrix() const { return mAnimationMatrix; }
467*d57664e9SAndroid Build Coastguard Worker 
hasTransformMatrix()468*d57664e9SAndroid Build Coastguard Worker     bool hasTransformMatrix() const {
469*d57664e9SAndroid Build Coastguard Worker         return getTransformMatrix() && !getTransformMatrix()->isIdentity();
470*d57664e9SAndroid Build Coastguard Worker     }
471*d57664e9SAndroid Build Coastguard Worker 
472*d57664e9SAndroid Build Coastguard Worker     // May only call this if hasTransformMatrix() is true
isTransformTranslateOnly()473*d57664e9SAndroid Build Coastguard Worker     bool isTransformTranslateOnly() const {
474*d57664e9SAndroid Build Coastguard Worker         return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
475*d57664e9SAndroid Build Coastguard Worker     }
476*d57664e9SAndroid Build Coastguard Worker 
getTransformMatrix()477*d57664e9SAndroid Build Coastguard Worker     const SkMatrix* getTransformMatrix() const {
478*d57664e9SAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
479*d57664e9SAndroid Build Coastguard Worker         return mComputedFields.mTransformMatrix;
480*d57664e9SAndroid Build Coastguard Worker     }
481*d57664e9SAndroid Build Coastguard Worker 
getClippingFlags()482*d57664e9SAndroid Build Coastguard Worker     int getClippingFlags() const { return mPrimitiveFields.mClippingFlags; }
483*d57664e9SAndroid Build Coastguard Worker 
getClipToBounds()484*d57664e9SAndroid Build Coastguard Worker     bool getClipToBounds() const { return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS; }
485*d57664e9SAndroid Build Coastguard Worker 
getClipBounds()486*d57664e9SAndroid Build Coastguard Worker     const Rect& getClipBounds() const { return mPrimitiveFields.mClipBounds; }
487*d57664e9SAndroid Build Coastguard Worker 
getClippingRectForFlags(uint32_t flags,Rect * outRect)488*d57664e9SAndroid Build Coastguard Worker     void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
489*d57664e9SAndroid Build Coastguard Worker         if (flags & CLIP_TO_BOUNDS) {
490*d57664e9SAndroid Build Coastguard Worker             outRect->set(0, 0, getWidth(), getHeight());
491*d57664e9SAndroid Build Coastguard Worker             if (flags & CLIP_TO_CLIP_BOUNDS) {
492*d57664e9SAndroid Build Coastguard Worker                 outRect->doIntersect(mPrimitiveFields.mClipBounds);
493*d57664e9SAndroid Build Coastguard Worker             }
494*d57664e9SAndroid Build Coastguard Worker         } else {
495*d57664e9SAndroid Build Coastguard Worker             outRect->set(mPrimitiveFields.mClipBounds);
496*d57664e9SAndroid Build Coastguard Worker         }
497*d57664e9SAndroid Build Coastguard Worker     }
498*d57664e9SAndroid Build Coastguard Worker 
getHasOverlappingRendering()499*d57664e9SAndroid Build Coastguard Worker     bool getHasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; }
500*d57664e9SAndroid Build Coastguard Worker 
getOutline()501*d57664e9SAndroid Build Coastguard Worker     const Outline& getOutline() const { return mPrimitiveFields.mOutline; }
502*d57664e9SAndroid Build Coastguard Worker 
getRevealClip()503*d57664e9SAndroid Build Coastguard Worker     const RevealClip& getRevealClip() const { return mPrimitiveFields.mRevealClip; }
504*d57664e9SAndroid Build Coastguard Worker 
getProjectBackwards()505*d57664e9SAndroid Build Coastguard Worker     bool getProjectBackwards() const { return mPrimitiveFields.mProjectBackwards; }
506*d57664e9SAndroid Build Coastguard Worker 
507*d57664e9SAndroid Build Coastguard Worker     void debugOutputProperties(std::ostream& output, const int level) const;
508*d57664e9SAndroid Build Coastguard Worker 
509*d57664e9SAndroid Build Coastguard Worker     void updateMatrix();
510*d57664e9SAndroid Build Coastguard Worker 
mutableOutline()511*d57664e9SAndroid Build Coastguard Worker     Outline& mutableOutline() { return mPrimitiveFields.mOutline; }
512*d57664e9SAndroid Build Coastguard Worker 
mutableRevealClip()513*d57664e9SAndroid Build Coastguard Worker     RevealClip& mutableRevealClip() { return mPrimitiveFields.mRevealClip; }
514*d57664e9SAndroid Build Coastguard Worker 
layerProperties()515*d57664e9SAndroid Build Coastguard Worker     const LayerProperties& layerProperties() const { return mLayerProperties; }
516*d57664e9SAndroid Build Coastguard Worker 
mutateLayerProperties()517*d57664e9SAndroid Build Coastguard Worker     LayerProperties& mutateLayerProperties() { return mLayerProperties; }
518*d57664e9SAndroid Build Coastguard Worker 
519*d57664e9SAndroid Build Coastguard Worker     // Returns true if damage calculations should be clipped to bounds
520*d57664e9SAndroid Build Coastguard Worker     // TODO: Figure out something better for getZ(), as children should still be
521*d57664e9SAndroid Build Coastguard Worker     // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
522*d57664e9SAndroid Build Coastguard Worker     // for this RP's getZ() anyway, this can be optimized when we have a
523*d57664e9SAndroid Build Coastguard Worker     // Z damage estimate instead of INT_MAX
getClipDamageToBounds()524*d57664e9SAndroid Build Coastguard Worker     bool getClipDamageToBounds() const {
525*d57664e9SAndroid Build Coastguard Worker         return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
526*d57664e9SAndroid Build Coastguard Worker     }
527*d57664e9SAndroid Build Coastguard Worker 
hasShadow()528*d57664e9SAndroid Build Coastguard Worker     bool hasShadow() const {
529*d57664e9SAndroid Build Coastguard Worker         return getZ() > 0.0f && getOutline().getPath() != nullptr &&
530*d57664e9SAndroid Build Coastguard Worker                getOutline().getAlpha() != 0.0f;
531*d57664e9SAndroid Build Coastguard Worker     }
532*d57664e9SAndroid Build Coastguard Worker 
getSpotShadowColor()533*d57664e9SAndroid Build Coastguard Worker     SkColor getSpotShadowColor() const { return mPrimitiveFields.mSpotShadowColor; }
534*d57664e9SAndroid Build Coastguard Worker 
setSpotShadowColor(SkColor shadowColor)535*d57664e9SAndroid Build Coastguard Worker     bool setSpotShadowColor(SkColor shadowColor) {
536*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor);
537*d57664e9SAndroid Build Coastguard Worker     }
538*d57664e9SAndroid Build Coastguard Worker 
getAmbientShadowColor()539*d57664e9SAndroid Build Coastguard Worker     SkColor getAmbientShadowColor() const { return mPrimitiveFields.mAmbientShadowColor; }
540*d57664e9SAndroid Build Coastguard Worker 
setAmbientShadowColor(SkColor shadowColor)541*d57664e9SAndroid Build Coastguard Worker     bool setAmbientShadowColor(SkColor shadowColor) {
542*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor);
543*d57664e9SAndroid Build Coastguard Worker     }
544*d57664e9SAndroid Build Coastguard Worker 
fitsOnLayer()545*d57664e9SAndroid Build Coastguard Worker     bool fitsOnLayer() const {
546*d57664e9SAndroid Build Coastguard Worker         const DeviceInfo* deviceInfo = DeviceInfo::get();
547*d57664e9SAndroid Build Coastguard Worker         return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize() &&
548*d57664e9SAndroid Build Coastguard Worker                mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize() &&
549*d57664e9SAndroid Build Coastguard Worker                mPrimitiveFields.mWidth > 0 && mPrimitiveFields.mHeight > 0;
550*d57664e9SAndroid Build Coastguard Worker     }
551*d57664e9SAndroid Build Coastguard Worker 
promotedToLayer()552*d57664e9SAndroid Build Coastguard Worker     bool promotedToLayer() const {
553*d57664e9SAndroid Build Coastguard Worker         return mLayerProperties.mType == LayerType::None && fitsOnLayer() &&
554*d57664e9SAndroid Build Coastguard Worker                (mComputedFields.mNeedLayerForFunctors || mLayerProperties.mImageFilter != nullptr ||
555*d57664e9SAndroid Build Coastguard Worker                 mLayerProperties.getStretchEffect().requiresLayer() ||
556*d57664e9SAndroid Build Coastguard Worker                 (!MathUtils::isZero(mPrimitiveFields.mAlpha) && mPrimitiveFields.mAlpha < 1 &&
557*d57664e9SAndroid Build Coastguard Worker                  mPrimitiveFields.mHasOverlappingRendering));
558*d57664e9SAndroid Build Coastguard Worker     }
559*d57664e9SAndroid Build Coastguard Worker 
effectiveLayerType()560*d57664e9SAndroid Build Coastguard Worker     LayerType effectiveLayerType() const {
561*d57664e9SAndroid Build Coastguard Worker         return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
562*d57664e9SAndroid Build Coastguard Worker     }
563*d57664e9SAndroid Build Coastguard Worker 
setAllowForceDark(bool allow)564*d57664e9SAndroid Build Coastguard Worker     bool setAllowForceDark(bool allow) {
565*d57664e9SAndroid Build Coastguard Worker         return RP_SET(mPrimitiveFields.mAllowForceDark, allow);
566*d57664e9SAndroid Build Coastguard Worker     }
567*d57664e9SAndroid Build Coastguard Worker 
getAllowForceDark()568*d57664e9SAndroid Build Coastguard Worker     bool getAllowForceDark() const {
569*d57664e9SAndroid Build Coastguard Worker         return mPrimitiveFields.mAllowForceDark;
570*d57664e9SAndroid Build Coastguard Worker     }
571*d57664e9SAndroid Build Coastguard Worker 
572*d57664e9SAndroid Build Coastguard Worker private:
573*d57664e9SAndroid Build Coastguard Worker     // Rendering properties
574*d57664e9SAndroid Build Coastguard Worker     struct PrimitiveFields {
575*d57664e9SAndroid Build Coastguard Worker         int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
576*d57664e9SAndroid Build Coastguard Worker         int mWidth = 0, mHeight = 0;
577*d57664e9SAndroid Build Coastguard Worker         int mClippingFlags = CLIP_TO_BOUNDS;
578*d57664e9SAndroid Build Coastguard Worker         SkColor mSpotShadowColor = SK_ColorBLACK;
579*d57664e9SAndroid Build Coastguard Worker         SkColor mAmbientShadowColor = SK_ColorBLACK;
580*d57664e9SAndroid Build Coastguard Worker         float mAlpha = 1;
581*d57664e9SAndroid Build Coastguard Worker         float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
582*d57664e9SAndroid Build Coastguard Worker         float mElevation = 0;
583*d57664e9SAndroid Build Coastguard Worker         float mRotation = 0, mRotationX = 0, mRotationY = 0;
584*d57664e9SAndroid Build Coastguard Worker         float mScaleX = 1, mScaleY = 1;
585*d57664e9SAndroid Build Coastguard Worker         float mPivotX = 0, mPivotY = 0;
586*d57664e9SAndroid Build Coastguard Worker         bool mHasOverlappingRendering = false;
587*d57664e9SAndroid Build Coastguard Worker         bool mPivotExplicitlySet = false;
588*d57664e9SAndroid Build Coastguard Worker         bool mMatrixOrPivotDirty = false;
589*d57664e9SAndroid Build Coastguard Worker         bool mProjectBackwards = false;
590*d57664e9SAndroid Build Coastguard Worker         bool mProjectionReceiver = false;
591*d57664e9SAndroid Build Coastguard Worker         bool mAllowForceDark = true;
592*d57664e9SAndroid Build Coastguard Worker         bool mClipMayBeComplex = false;
593*d57664e9SAndroid Build Coastguard Worker         Rect mClipBounds;
594*d57664e9SAndroid Build Coastguard Worker         Outline mOutline;
595*d57664e9SAndroid Build Coastguard Worker         RevealClip mRevealClip;
596*d57664e9SAndroid Build Coastguard Worker     } mPrimitiveFields;
597*d57664e9SAndroid Build Coastguard Worker 
598*d57664e9SAndroid Build Coastguard Worker     SkMatrix* mStaticMatrix;
599*d57664e9SAndroid Build Coastguard Worker     SkMatrix* mAnimationMatrix;
600*d57664e9SAndroid Build Coastguard Worker     LayerProperties mLayerProperties;
601*d57664e9SAndroid Build Coastguard Worker 
602*d57664e9SAndroid Build Coastguard Worker     /**
603*d57664e9SAndroid Build Coastguard Worker      * These fields are all generated from other properties and are not set directly.
604*d57664e9SAndroid Build Coastguard Worker      */
605*d57664e9SAndroid Build Coastguard Worker     struct ComputedFields {
606*d57664e9SAndroid Build Coastguard Worker         ComputedFields();
607*d57664e9SAndroid Build Coastguard Worker         ~ComputedFields();
608*d57664e9SAndroid Build Coastguard Worker 
609*d57664e9SAndroid Build Coastguard Worker         /**
610*d57664e9SAndroid Build Coastguard Worker          * Stores the total transformation of the DisplayList based upon its scalar
611*d57664e9SAndroid Build Coastguard Worker          * translate/rotate/scale properties.
612*d57664e9SAndroid Build Coastguard Worker          *
613*d57664e9SAndroid Build Coastguard Worker          * In the common translation-only case, the matrix isn't necessarily allocated,
614*d57664e9SAndroid Build Coastguard Worker          * and the mTranslation properties are used directly.
615*d57664e9SAndroid Build Coastguard Worker          */
616*d57664e9SAndroid Build Coastguard Worker         SkMatrix* mTransformMatrix;
617*d57664e9SAndroid Build Coastguard Worker 
618*d57664e9SAndroid Build Coastguard Worker         Sk3DView mTransformCamera;
619*d57664e9SAndroid Build Coastguard Worker 
620*d57664e9SAndroid Build Coastguard Worker         // Force layer on for functors to enable render features they don't yet support (clipping)
621*d57664e9SAndroid Build Coastguard Worker         bool mNeedLayerForFunctors = false;
622*d57664e9SAndroid Build Coastguard Worker     } mComputedFields;
623*d57664e9SAndroid Build Coastguard Worker };
624*d57664e9SAndroid Build Coastguard Worker 
625*d57664e9SAndroid Build Coastguard Worker } /* namespace uirenderer */
626*d57664e9SAndroid Build Coastguard Worker } /* namespace android */
627