diff options
Diffstat (limited to 'libs/hwui/RenderProperties.h')
-rw-r--r-- | libs/hwui/RenderProperties.h | 317 |
1 files changed, 199 insertions, 118 deletions
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index c0e3ce7..227d56e 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -21,6 +21,7 @@ #include <vector> #include <cutils/compiler.h> #include <androidfw/ResourceTypes.h> +#include <utils/Log.h> #include <SkCamera.h> #include <SkMatrix.h> @@ -30,8 +31,10 @@ #include "Rect.h" #include "RevealClip.h" #include "Outline.h" +#include "utils/MathUtils.h" class SkBitmap; +class SkColorFilter; class SkPaint; namespace android { @@ -39,40 +42,125 @@ namespace uirenderer { class Matrix4; class RenderNode; +class RenderProperties; + +// The __VA_ARGS__ will be executed if a & b are not equal +#define RP_SET(a, b, ...) (a != b ? (a = b, ##__VA_ARGS__, true) : false) +#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true) + +// Keep in sync with View.java:LAYER_TYPE_* +enum LayerType { + kLayerTypeNone = 0, + // Although we cannot build the software layer directly (must be done at + // record time), this information is used when applying alpha. + kLayerTypeSoftware = 1, + kLayerTypeRenderLayer = 2, + // TODO: LayerTypeSurfaceTexture? Maybe? +}; + +class ANDROID_API LayerProperties { +public: + bool setType(LayerType type) { + if (RP_SET(mType, type)) { + reset(); + return true; + } + return false; + } + + LayerType type() const { + return mType; + } + + bool setOpaque(bool opaque) { + return RP_SET(mOpaque, opaque); + } + + bool opaque() const { + return mOpaque; + } + + bool setAlpha(uint8_t alpha) { + return RP_SET(mAlpha, alpha); + } + + uint8_t alpha() const { + return mAlpha; + } + + bool setXferMode(SkXfermode::Mode mode) { + return RP_SET(mMode, mode); + } + + SkXfermode::Mode xferMode() const { + return mMode; + } + + bool setColorFilter(SkColorFilter* filter); + + SkColorFilter* colorFilter() const { + return mColorFilter; + } + + // Sets alpha, xfermode, and colorfilter from an SkPaint + // paint may be NULL, in which case defaults will be set + bool setFromPaint(const SkPaint* paint); + + bool needsBlending() const { + return !opaque() || alpha() < 255; + } + + LayerProperties& operator=(const LayerProperties& other); + +private: + LayerProperties(); + ~LayerProperties(); + void reset(); + + friend class RenderProperties; + + LayerType mType; + // Whether or not that Layer's content is opaque, doesn't include alpha + bool mOpaque; + uint8_t mAlpha; + SkXfermode::Mode mMode; + SkColorFilter* mColorFilter; +}; /* * Data structure that holds the properties for a RenderNode */ -class RenderProperties { +class ANDROID_API RenderProperties { public: RenderProperties(); virtual ~RenderProperties(); RenderProperties& operator=(const RenderProperties& other); - void setClipToBounds(bool clipToBounds) { - mPrimitiveFields.mClipToBounds = clipToBounds; + bool setClipToBounds(bool clipToBounds) { + return RP_SET(mPrimitiveFields.mClipToBounds, clipToBounds); } - void setProjectBackwards(bool shouldProject) { - mPrimitiveFields.mProjectBackwards = shouldProject; + bool setProjectBackwards(bool shouldProject) { + return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject); } - void setProjectionReceiver(bool shouldRecieve) { - mPrimitiveFields.mProjectionReceiver = shouldRecieve; + bool setProjectionReceiver(bool shouldRecieve) { + return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldRecieve); } bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; } - void setStaticMatrix(const SkMatrix* matrix) { + bool setStaticMatrix(const SkMatrix* matrix) { delete mStaticMatrix; if (matrix) { mStaticMatrix = new SkMatrix(*matrix); } else { mStaticMatrix = NULL; } + return true; } // Can return NULL @@ -80,72 +168,61 @@ public: return mStaticMatrix; } - void setAnimationMatrix(const SkMatrix* matrix) { + bool setAnimationMatrix(const SkMatrix* matrix) { delete mAnimationMatrix; if (matrix) { mAnimationMatrix = new SkMatrix(*matrix); } else { mAnimationMatrix = NULL; } + return true; } - void setAlpha(float alpha) { + bool setAlpha(float alpha) { alpha = fminf(1.0f, fmaxf(0.0f, alpha)); - if (alpha != mPrimitiveFields.mAlpha) { - mPrimitiveFields.mAlpha = alpha; - } + return RP_SET(mPrimitiveFields.mAlpha, alpha); } float getAlpha() const { return mPrimitiveFields.mAlpha; } - void setHasOverlappingRendering(bool hasOverlappingRendering) { - mPrimitiveFields.mHasOverlappingRendering = hasOverlappingRendering; + bool setHasOverlappingRendering(bool hasOverlappingRendering) { + return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering); } bool hasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; } - void setElevation(float elevation) { - if (elevation != mPrimitiveFields.mElevation) { - mPrimitiveFields.mElevation = elevation; - // mMatrixOrPivotDirty not set, since matrix doesn't respect Z - } + bool setElevation(float elevation) { + return RP_SET(mPrimitiveFields.mElevation, elevation); + // Don't dirty matrix/pivot, since they don't respect Z } float getElevation() const { return mPrimitiveFields.mElevation; } - void setTranslationX(float translationX) { - if (translationX != mPrimitiveFields.mTranslationX) { - mPrimitiveFields.mTranslationX = translationX; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setTranslationX(float translationX) { + return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX); } float getTranslationX() const { return mPrimitiveFields.mTranslationX; } - void setTranslationY(float translationY) { - if (translationY != mPrimitiveFields.mTranslationY) { - mPrimitiveFields.mTranslationY = translationY; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setTranslationY(float translationY) { + return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY); } float getTranslationY() const { return mPrimitiveFields.mTranslationY; } - void setTranslationZ(float translationZ) { - if (translationZ != mPrimitiveFields.mTranslationZ) { - mPrimitiveFields.mTranslationZ = translationZ; - // mMatrixOrPivotDirty not set, since matrix doesn't respect Z - } + bool setTranslationZ(float translationZ) { + return RP_SET(mPrimitiveFields.mTranslationZ, translationZ); + // mMatrixOrPivotDirty not set, since matrix doesn't respect Z } float getTranslationZ() const { @@ -153,8 +230,8 @@ public: } // Animation helper - void setX(float value) { - setTranslationX(value - getLeft()); + bool setX(float value) { + return setTranslationX(value - getLeft()); } // Animation helper @@ -163,8 +240,8 @@ public: } // Animation helper - void setY(float value) { - setTranslationY(value - getTop()); + bool setY(float value) { + return setTranslationY(value - getTop()); } // Animation helper @@ -173,87 +250,82 @@ public: } // Animation helper - void setZ(float value) { - setTranslationZ(value - getElevation()); + bool setZ(float value) { + return setTranslationZ(value - getElevation()); } float getZ() const { return getElevation() + getTranslationZ(); } - void setRotation(float rotation) { - if (rotation != mPrimitiveFields.mRotation) { - mPrimitiveFields.mRotation = rotation; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setRotation(float rotation) { + return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation); } float getRotation() const { return mPrimitiveFields.mRotation; } - void setRotationX(float rotationX) { - if (rotationX != mPrimitiveFields.mRotationX) { - mPrimitiveFields.mRotationX = rotationX; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setRotationX(float rotationX) { + return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX); } float getRotationX() const { return mPrimitiveFields.mRotationX; } - void setRotationY(float rotationY) { - if (rotationY != mPrimitiveFields.mRotationY) { - mPrimitiveFields.mRotationY = rotationY; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setRotationY(float rotationY) { + return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY); } float getRotationY() const { return mPrimitiveFields.mRotationY; } - void setScaleX(float scaleX) { - if (scaleX != mPrimitiveFields.mScaleX) { - mPrimitiveFields.mScaleX = scaleX; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setScaleX(float scaleX) { + LOG_ALWAYS_FATAL_IF(scaleX > 1000000, "invalid scaleX %e", scaleX); + return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX); } float getScaleX() const { return mPrimitiveFields.mScaleX; } - void setScaleY(float scaleY) { - if (scaleY != mPrimitiveFields.mScaleY) { - mPrimitiveFields.mScaleY = scaleY; - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + bool setScaleY(float scaleY) { + LOG_ALWAYS_FATAL_IF(scaleY > 1000000, "invalid scaleY %e", scaleY); + return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY); } float getScaleY() const { return mPrimitiveFields.mScaleY; } - void setPivotX(float pivotX) { - mPrimitiveFields.mPivotX = pivotX; - mPrimitiveFields.mMatrixOrPivotDirty = true; - mPrimitiveFields.mPivotExplicitlySet = true; + bool setPivotX(float pivotX) { + if (RP_SET(mPrimitiveFields.mPivotX, pivotX) + || !mPrimitiveFields.mPivotExplicitlySet) { + mPrimitiveFields.mMatrixOrPivotDirty = true; + mPrimitiveFields.mPivotExplicitlySet = true; + return true; + } + return false; } /* Note that getPivotX and getPivotY are adjusted by updateMatrix(), - * so the value returned mPrimitiveFields.may be stale if the RenderProperties has been - * mPrimitiveFields.modified since the last call to updateMatrix() + * so the value returned may be stale if the RenderProperties has been + * modified since the last call to updateMatrix() */ float getPivotX() const { return mPrimitiveFields.mPivotX; } - void setPivotY(float pivotY) { - mPrimitiveFields.mPivotY = pivotY; - mPrimitiveFields.mMatrixOrPivotDirty = true; - mPrimitiveFields.mPivotExplicitlySet = true; + bool setPivotY(float pivotY) { + if (RP_SET(mPrimitiveFields.mPivotY, pivotY) + || !mPrimitiveFields.mPivotExplicitlySet) { + mPrimitiveFields.mMatrixOrPivotDirty = true; + mPrimitiveFields.mPivotExplicitlySet = true; + return true; + } + return false; } float getPivotY() const { @@ -264,11 +336,13 @@ public: return mPrimitiveFields.mPivotExplicitlySet; } - void setCameraDistance(float distance) { + bool setCameraDistance(float distance) { if (distance != getCameraDistance()) { mPrimitiveFields.mMatrixOrPivotDirty = true; mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance); + return true; } + return false; } float getCameraDistance() const { @@ -276,75 +350,73 @@ public: return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ(); } - void setLeft(int left) { - if (left != mPrimitiveFields.mLeft) { - mPrimitiveFields.mLeft = left; + bool setLeft(int left) { + if (RP_SET(mPrimitiveFields.mLeft, left)) { mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; if (!mPrimitiveFields.mPivotExplicitlySet) { mPrimitiveFields.mMatrixOrPivotDirty = true; } + return true; } + return false; } float getLeft() const { return mPrimitiveFields.mLeft; } - void setTop(int top) { - if (top != mPrimitiveFields.mTop) { - mPrimitiveFields.mTop = top; + bool setTop(int top) { + if (RP_SET(mPrimitiveFields.mTop, top)) { mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; if (!mPrimitiveFields.mPivotExplicitlySet) { mPrimitiveFields.mMatrixOrPivotDirty = true; } + return true; } + return false; } float getTop() const { return mPrimitiveFields.mTop; } - void setRight(int right) { - if (right != mPrimitiveFields.mRight) { - mPrimitiveFields.mRight = right; + bool setRight(int right) { + if (RP_SET(mPrimitiveFields.mRight, right)) { mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; if (!mPrimitiveFields.mPivotExplicitlySet) { mPrimitiveFields.mMatrixOrPivotDirty = true; } + return true; } + return false; } float getRight() const { return mPrimitiveFields.mRight; } - void setBottom(int bottom) { - if (bottom != mPrimitiveFields.mBottom) { - mPrimitiveFields.mBottom = bottom; + bool setBottom(int bottom) { + if (RP_SET(mPrimitiveFields.mBottom, bottom)) { mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; if (!mPrimitiveFields.mPivotExplicitlySet) { mPrimitiveFields.mMatrixOrPivotDirty = true; } + return true; } + return false; } float getBottom() const { return mPrimitiveFields.mBottom; } - void setLeftTop(int left, int top) { - if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop) { - mPrimitiveFields.mLeft = left; - mPrimitiveFields.mTop = top; - mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; - mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; - if (!mPrimitiveFields.mPivotExplicitlySet) { - mPrimitiveFields.mMatrixOrPivotDirty = true; - } - } + bool setLeftTop(int left, int top) { + bool leftResult = setLeft(left); + bool topResult = setTop(top); + return leftResult || topResult; } - void setLeftTopRightBottom(int left, int top, int right, int bottom) { + bool setLeftTopRightBottom(int left, int top, int right, int bottom) { if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) { mPrimitiveFields.mLeft = left; @@ -356,31 +428,27 @@ public: if (!mPrimitiveFields.mPivotExplicitlySet) { mPrimitiveFields.mMatrixOrPivotDirty = true; } + return true; } + return false; } - void offsetLeftRight(float offset) { + bool offsetLeftRight(float offset) { if (offset != 0) { mPrimitiveFields.mLeft += offset; mPrimitiveFields.mRight += offset; - if (!mPrimitiveFields.mPivotExplicitlySet) { - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + return true; } + return false; } - void offsetTopBottom(float offset) { + bool offsetTopBottom(float offset) { if (offset != 0) { mPrimitiveFields.mTop += offset; mPrimitiveFields.mBottom += offset; - if (!mPrimitiveFields.mPivotExplicitlySet) { - mPrimitiveFields.mMatrixOrPivotDirty = true; - } + return true; } - } - - void setCaching(bool caching) { - mPrimitiveFields.mCaching = caching; + return false; } int getWidth() const { @@ -409,10 +477,6 @@ public: return mComputedFields.mTransformMatrix; } - bool getCaching() const { - return mPrimitiveFields.mCaching; - } - bool getClipToBounds() const { return mPrimitiveFields.mClipToBounds; } @@ -435,7 +499,7 @@ public: void debugOutputProperties(const int level) const; - ANDROID_API void updateMatrix(); + void updateMatrix(); bool hasClippingPath() const { return mPrimitiveFields.mRevealClip.willClip(); @@ -458,6 +522,23 @@ public: return mPrimitiveFields.mRevealClip; } + const LayerProperties& layerProperties() const { + return mLayerProperties; + } + + LayerProperties& mutateLayerProperties() { + return mLayerProperties; + } + + // Returns true if damage calculations should be clipped to bounds + // TODO: Figure out something better for getZ(), as children should still be + // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX + // for this RP's getZ() anyway, this can be optimized when we have a + // Z damage estimate instead of INT_MAX + bool getClipDamageToBounds() const { + return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty()); + } + private: // Rendering properties @@ -480,11 +561,11 @@ private: int mWidth, mHeight; bool mPivotExplicitlySet; bool mMatrixOrPivotDirty; - bool mCaching; } mPrimitiveFields; SkMatrix* mStaticMatrix; SkMatrix* mAnimationMatrix; + LayerProperties mLayerProperties; /** * These fields are all generated from other properties and are not set directly. |