diff options
author | John Reck <jreck@google.com> | 2014-06-12 13:46:45 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2014-06-12 19:25:33 -0700 |
commit | 25fbb3fa1138675379102a44405852555cefccbd (patch) | |
tree | 510d62715f870f85fc4eea8a781c0265e7eebae5 /libs/hwui | |
parent | a447d29c65fb811cd184775a3476101a1cede929 (diff) | |
download | frameworks_base-25fbb3fa1138675379102a44405852555cefccbd.zip frameworks_base-25fbb3fa1138675379102a44405852555cefccbd.tar.gz frameworks_base-25fbb3fa1138675379102a44405852555cefccbd.tar.bz2 |
Move LayerType to RenderNode
Change-Id: Icb79a5015cb0362b1f3a66d09007450730135a97
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/DamageAccumulator.cpp | 20 | ||||
-rw-r--r-- | libs/hwui/DamageAccumulator.h | 10 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 30 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 8 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 148 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 10 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.cpp | 51 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.h | 103 | ||||
-rw-r--r-- | libs/hwui/TreeInfo.h | 5 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 3 |
11 files changed, 301 insertions, 88 deletions
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp index 898e81a..1cb87f2 100644 --- a/libs/hwui/DamageAccumulator.cpp +++ b/libs/hwui/DamageAccumulator.cpp @@ -35,6 +35,7 @@ NullDamageAccumulator* NullDamageAccumulator::instance() { enum TransformType { TransformRenderNode, TransformMatrix4, + TransformNone, }; struct DirtyStack { @@ -80,14 +81,25 @@ void DamageAccumulator::pushTransform(const Matrix4* transform) { mHead->matrix4 = transform; } +void DamageAccumulator::pushNullTransform() { + pushCommon(); + mHead->type = TransformNone; +} + void DamageAccumulator::popTransform() { LOG_ALWAYS_FATAL_IF(mHead->prev == mHead, "Cannot pop the root frame!"); DirtyStack* dirtyFrame = mHead; mHead = mHead->prev; - if (dirtyFrame->type == TransformRenderNode) { + switch (dirtyFrame->type) { + case TransformRenderNode: applyRenderNodeTransform(dirtyFrame); - } else { + break; + case TransformMatrix4: applyMatrix4Transform(dirtyFrame); + break; + case TransformNone: + mHead->pendingDirty.join(dirtyFrame->pendingDirty); + break; } } @@ -186,6 +198,10 @@ void DamageAccumulator::dirty(float left, float top, float right, float bottom) mHead->pendingDirty.join(left, top, right, bottom); } +void DamageAccumulator::peekAtDirty(SkRect* dest) { + *dest = mHead->pendingDirty; +} + void DamageAccumulator::finish(SkRect* totalDirty) { LOG_ALWAYS_FATAL_IF(mHead->prev != mHead, "Cannot finish, mismatched push/pop calls! %p vs. %p", mHead->prev, mHead); // Root node never has a transform, so this is the fully mapped dirty rect diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h index 2ca30d4..fc9b41b 100644 --- a/libs/hwui/DamageAccumulator.h +++ b/libs/hwui/DamageAccumulator.h @@ -35,8 +35,10 @@ class IDamageAccumulator { public: virtual void pushTransform(const RenderNode* transform) = 0; virtual void pushTransform(const Matrix4* transform) = 0; + virtual void pushNullTransform() = 0; virtual void popTransform() = 0; virtual void dirty(float left, float top, float right, float bottom) = 0; + virtual void peekAtDirty(SkRect* dest) = 0; protected: virtual ~IDamageAccumulator() {} }; @@ -52,6 +54,9 @@ public: // will be affected by the transform when popTransform() is called. virtual void pushTransform(const RenderNode* transform); virtual void pushTransform(const Matrix4* transform); + // This is used in combination with peekAtDirty to inspect the damage + // area of a subtree + virtual void pushNullTransform(); // Pops a transform node from the stack, propagating the dirty rect // up to the parent node. Returns the IDamageTransform that was just applied @@ -59,6 +64,9 @@ public: virtual void dirty(float left, float top, float right, float bottom); + // Returns the current dirty area, *NOT* transformed by pushed transforms + virtual void peekAtDirty(SkRect* dest); + void finish(SkRect* totalDirty); private: @@ -75,8 +83,10 @@ class NullDamageAccumulator : public IDamageAccumulator { public: virtual void pushTransform(const RenderNode* transform) { } virtual void pushTransform(const Matrix4* transform) { } + virtual void pushNullTransform() { } virtual void popTransform() { } virtual void dirty(float left, float top, float right, float bottom) { } + virtual void peekAtDirty(SkRect* dest) { dest->setEmpty(); } ANDROID_API static NullDamageAccumulator* instance(); diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index d494c4c..8e99b9a 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -27,8 +27,7 @@ static void defaultLayerDestroyer(Layer* layer) { } DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, LayerDestroyer destroyer) - : mDisplayList(0) - , mSurfaceTexture(0) + : mSurfaceTexture(0) , mTransform(0) , mNeedsGLContextAttach(false) , mUpdateTexImage(false) @@ -41,7 +40,6 @@ DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, LayerDestroyer destroye mColorFilter = SkSafeRef(mLayer->getColorFilter()); mAlpha = mLayer->getAlpha(); mMode = mLayer->getMode(); - mDirtyRect.setEmpty(); if (!mDestroyer) { mDestroyer = defaultLayerDestroyer; @@ -60,37 +58,13 @@ void DeferredLayerUpdater::setPaint(const SkPaint* paint) { SkRefCnt_SafeAssign(mColorFilter, colorFilter); } -void DeferredLayerUpdater::setDisplayList(RenderNode* displayList, - int left, int top, int right, int bottom) { - mDisplayList = displayList; - if (mDirtyRect.isEmpty()) { - mDirtyRect.set(left, top, right, bottom); - } else { - mDirtyRect.unionWith(Rect(left, top, right, bottom)); - } -} - bool DeferredLayerUpdater::apply(TreeInfo& info) { bool success = true; // These properties are applied the same to both layer types mLayer->setColorFilter(mColorFilter); mLayer->setAlpha(mAlpha, mMode); - if (mDisplayList.get()) { - if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) { - success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight); - } - mLayer->setBlend(mBlend); - // TODO: Use DamageAccumulator to get the damage area for the layer's - // subtree to only update that part of the layer. Do this as part of - // reworking layers to be a RenderProperty instead of a View-managed object - mDirtyRect.set(0, 0, mWidth, mHeight); - mDisplayList->prepareTree(info); - mLayer->updateDeferred(mDisplayList.get(), - mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom); - mDirtyRect.setEmpty(); - mDisplayList = 0; - } else if (mSurfaceTexture.get()) { + if (mSurfaceTexture.get()) { if (mNeedsGLContextAttach) { mNeedsGLContextAttach = false; mSurfaceTexture->attachToContext(mLayer->getTexture()); diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index b7cfe80..5082271 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -74,9 +74,6 @@ public: mTransform = matrix ? new SkMatrix(*matrix) : 0; } - ANDROID_API void setDisplayList(RenderNode* displayList, - int left, int top, int right, int bottom); - ANDROID_API void setPaint(const SkPaint* paint); ANDROID_API bool apply(TreeInfo& info); @@ -94,11 +91,6 @@ private: int mAlpha; SkXfermode::Mode mMode; - // Layer type specific properties - // displayList and surfaceTexture are mutually exclusive, only 1 may be set - // dirtyRect is only valid if displayList is set - sp<RenderNode> mDisplayList; - Rect mDirtyRect; sp<GLConsumer> mSurfaceTexture; SkMatrix* mTransform; bool mNeedsGLContextAttach; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 83ad76f..378183a 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -30,6 +30,8 @@ #include "Debug.h" #include "DisplayListOp.h" #include "DisplayListLogBuffer.h" +#include "LayerRenderer.h" +#include "OpenGLRenderer.h" #include "utils/MathUtils.h" namespace android { @@ -59,12 +61,14 @@ RenderNode::RenderNode() , mNeedsDisplayListDataSync(false) , mDisplayListData(0) , mStagingDisplayListData(0) - , mNeedsAnimatorsSync(false) { + , mNeedsAnimatorsSync(false) + , mLayer(0) { } RenderNode::~RenderNode() { delete mDisplayListData; delete mStagingDisplayListData; + LayerRenderer::destroyLayerDeferred(mLayer); } void RenderNode::setStagingDisplayList(DisplayListData* data) { @@ -124,17 +128,72 @@ void RenderNode::damageSelf(TreeInfo& info) { } } +void RenderNode::prepareLayer(TreeInfo& info) { + LayerType layerType = properties().layerProperties().type(); + if (CC_UNLIKELY(layerType == kLayerTypeRenderLayer)) { + // We push a null transform here as we don't care what the existing dirty + // area is, only what our display list dirty is as well as our children's + // dirty area + info.damageAccumulator->pushNullTransform(); + } +} + +void RenderNode::pushLayerUpdate(TreeInfo& info) { + LayerType layerType = properties().layerProperties().type(); + // If we are not a layer OR we cannot be rendered (eg, view was detached) + // we need to destroy any Layers we may have had previously + if (CC_LIKELY(layerType != kLayerTypeRenderLayer) || CC_UNLIKELY(!isRenderable())) { + if (layerType == kLayerTypeRenderLayer) { + info.damageAccumulator->popTransform(); + } + if (CC_UNLIKELY(mLayer)) { + LayerRenderer::destroyLayer(mLayer); + mLayer = NULL; + } + return; + } + + if (!mLayer) { + mLayer = LayerRenderer::createRenderLayer(getWidth(), getHeight()); + applyLayerPropertiesToLayer(info); + damageSelf(info); + } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) { + LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight()); + damageSelf(info); + } + + SkRect dirty; + info.damageAccumulator->peekAtDirty(&dirty); + info.damageAccumulator->popTransform(); + + if (!dirty.isEmpty()) { + mLayer->updateDeferred(this, dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom); + } + // This is not inside the above if because we may have called + // updateDeferred on a previous prepare pass that didn't have a renderer + if (info.renderer && mLayer->deferredUpdateScheduled) { + info.renderer->pushLayerUpdate(mLayer); + } +} + void RenderNode::prepareTreeImpl(TreeInfo& info) { info.damageAccumulator->pushTransform(this); if (info.mode == TreeInfo::MODE_FULL) { - pushStagingChanges(info); + pushStagingPropertiesChanges(info); evaluateAnimations(info); } else if (info.mode == TreeInfo::MODE_MAYBE_DETACHING) { - pushStagingChanges(info); + pushStagingPropertiesChanges(info); } else if (info.mode == TreeInfo::MODE_RT_ONLY) { evaluateAnimations(info); } + + prepareLayer(info); + if (info.mode == TreeInfo::MODE_FULL) { + pushStagingDisplayListChanges(info); + } prepareSubTree(info, mDisplayListData); + pushLayerUpdate(info); + info.damageAccumulator->popTransform(); } @@ -152,7 +211,7 @@ private: TreeInfo& mInfo; }; -void RenderNode::pushStagingChanges(TreeInfo& info) { +void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { // Push the animators first so that setupStartValueIfNecessary() is called // before properties() is trampled by stagingProperties(), as they are // required by some animators. @@ -170,6 +229,7 @@ void RenderNode::pushStagingChanges(TreeInfo& info) { damageSelf(info); info.damageAccumulator->popTransform(); mProperties = mStagingProperties; + applyLayerPropertiesToLayer(info); // We could try to be clever and only re-damage if the matrix changed. // However, we don't need to worry about that. The cost of over-damaging // here is only going to be a single additional map rect of this node @@ -178,6 +238,18 @@ void RenderNode::pushStagingChanges(TreeInfo& info) { info.damageAccumulator->pushTransform(this); damageSelf(info); } +} + +void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) { + if (CC_LIKELY(!mLayer)) return; + + const LayerProperties& props = properties().layerProperties(); + mLayer->setAlpha(props.alpha(), props.xferMode()); + mLayer->setColorFilter(props.colorFilter()); + mLayer->setBlend(props.needsBlending()); +} + +void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { if (mNeedsDisplayListDataSync) { mNeedsDisplayListDataSync = false; // Do a push pass on the old tree to handle freeing DisplayListData @@ -274,9 +346,10 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) { renderer.concatMatrix(*properties().getTransformMatrix()); } } - bool clipToBoundsNeeded = properties().getCaching() ? false : properties().getClipToBounds(); + const bool isLayer = properties().layerProperties().type() != kLayerTypeNone; + bool clipToBoundsNeeded = isLayer ? false : properties().getClipToBounds(); if (properties().getAlpha() < 1) { - if (properties().getCaching()) { + if (isLayer) { renderer.setOverrideLayerAlpha(properties().getAlpha()); } else if (!properties().getHasOverlappingRendering()) { renderer.scaleAlpha(properties().getAlpha()); @@ -691,8 +764,14 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& */ template <class T> void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { + const bool drawLayer = (mLayer && (&renderer != mLayer->renderer)); + // If we are updating the contents of mLayer, we don't want to apply any of + // the RenderNode's properties to this issueOperations pass. Those will all + // be applied when the layer is drawn, aka when this is true. + const bool useViewProperties = (!mLayer || drawLayer); + const int level = handler.level(); - if (mDisplayListData->isEmpty() || properties().getAlpha() <= 0) { + if (mDisplayListData->isEmpty() || (useViewProperties && properties().getAlpha() <= 0)) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName()); return; } @@ -714,7 +793,9 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); - setViewProperties<T>(renderer, handler); + if (useViewProperties) { + setViewProperties<T>(renderer, handler); + } bool quickRejected = properties().getClipToBounds() && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight()); @@ -723,31 +804,36 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { renderer.setClippingOutline(alloc, &(mProperties.getOutline())); } - Vector<ZDrawDisplayListOpPair> zTranslatedNodes; - buildZSortedChildList(zTranslatedNodes); - - // for 3d root, draw children with negative z values - issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler); - - DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); - const int saveCountOffset = renderer.getSaveCount() - 1; - const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex; - for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { - DisplayListOp *op = mDisplayListData->displayListOps[i]; - -#if DEBUG_DISPLAY_LIST - op->output(level + 1); -#endif - logBuffer.writeCommand(level, op->name()); - handler(op, saveCountOffset, properties().getClipToBounds()); - - if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) { - issueOperationsOfProjectedChildren(renderer, handler); + if (drawLayer) { + handler(new (alloc) DrawLayerOp(mLayer, 0, 0), + renderer.getSaveCount() - 1, properties().getClipToBounds()); + } else { + Vector<ZDrawDisplayListOpPair> zTranslatedNodes; + buildZSortedChildList(zTranslatedNodes); + + // for 3d root, draw children with negative z values + issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler); + + DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); + const int saveCountOffset = renderer.getSaveCount() - 1; + const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex; + for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { + DisplayListOp *op = mDisplayListData->displayListOps[i]; + + #if DEBUG_DISPLAY_LIST + op->output(level + 1); + #endif + logBuffer.writeCommand(level, op->name()); + handler(op, saveCountOffset, properties().getClipToBounds()); + + if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) { + issueOperationsOfProjectedChildren(renderer, handler); + } } - } - // for 3d root, draw children with positive z values - issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler); + // for 3d root, draw children with positive z values + issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler); + } } DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index f0f6e7c..b2fe849 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -254,9 +254,13 @@ private: }; void prepareTreeImpl(TreeInfo& info); - void pushStagingChanges(TreeInfo& info); + void pushStagingPropertiesChanges(TreeInfo& info); + void pushStagingDisplayListChanges(TreeInfo& info); void evaluateAnimations(TreeInfo& info); void prepareSubTree(TreeInfo& info, DisplayListData* subtree); + void applyLayerPropertiesToLayer(TreeInfo& info); + void prepareLayer(TreeInfo& info); + void pushLayerUpdate(TreeInfo& info); String8 mName; @@ -272,6 +276,10 @@ private: std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators; std::vector< sp<BaseRenderNodeAnimator> > mAnimators; + // Owned by RT. Lifecycle is managed by prepareTree(), with the exception + // being in ~RenderNode() which may happen on any thread. + Layer* mLayer; + /** * Draw time state - these properties are only set and used during rendering */ diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 5f7d4e3..8848b2f 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -21,16 +21,59 @@ #include <utils/Trace.h> #include <SkCanvas.h> +#include <SkColorFilter.h> #include <SkMatrix.h> #include <SkPath.h> #include <SkPathOps.h> #include "Matrix.h" +#include "OpenGLRenderer.h" #include "utils/MathUtils.h" namespace android { namespace uirenderer { +LayerProperties::LayerProperties() + : mType(kLayerTypeNone) + , mColorFilter(NULL) { + reset(); +} + +LayerProperties::~LayerProperties() { + setType(kLayerTypeNone); +} + +void LayerProperties::reset() { + mOpaque = false; + setFromPaint(NULL); +} + +bool LayerProperties::setColorFilter(SkColorFilter* filter) { + if (mColorFilter == filter) return false; + SkRefCnt_SafeAssign(mColorFilter, filter); + return true; +} + +bool LayerProperties::setFromPaint(const SkPaint* paint) { + bool changed = false; + SkXfermode::Mode mode; + int alpha; + OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); + changed |= setAlpha(static_cast<uint8_t>(alpha)); + changed |= setXferMode(mode); + changed |= setColorFilter(paint ? paint->getColorFilter() : NULL); + return changed; +} + +LayerProperties& LayerProperties::operator=(const LayerProperties& other) { + setType(other.type()); + setOpaque(other.opaque()); + setAlpha(other.alpha()); + setXferMode(other.xferMode()); + setColorFilter(other.colorFilter()); + return *this; +} + RenderProperties::PrimitiveFields::PrimitiveFields() : mClipToBounds(true) , mProjectBackwards(false) @@ -45,8 +88,7 @@ RenderProperties::PrimitiveFields::PrimitiveFields() , mLeft(0), mTop(0), mRight(0), mBottom(0) , mWidth(0), mHeight(0) , mPivotExplicitlySet(false) - , mMatrixOrPivotDirty(false) - , mCaching(false) { + , mMatrixOrPivotDirty(false) { } RenderProperties::ComputedFields::ComputedFields() @@ -73,6 +115,7 @@ RenderProperties& RenderProperties::operator=(const RenderProperties& other) { setStaticMatrix(other.getStaticMatrix()); setAnimationMatrix(other.getAnimationMatrix()); setCameraDistance(other.getCameraDistance()); + mLayerProperties = other.layerProperties(); // Force recalculation of the matrix, since other's dirty bit may be clear mPrimitiveFields.mMatrixOrPivotDirty = true; @@ -103,9 +146,9 @@ void RenderProperties::debugOutputProperties(const int level) const { } } - bool clipToBoundsNeeded = mPrimitiveFields.mCaching ? false : mPrimitiveFields.mClipToBounds; + bool clipToBoundsNeeded = layerProperties().type() != kLayerTypeNone ? false : mPrimitiveFields.mClipToBounds; if (mPrimitiveFields.mAlpha < 1) { - if (mPrimitiveFields.mCaching) { + if (layerProperties().type() != kLayerTypeNone) { ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); } else if (!mPrimitiveFields.mHasOverlappingRendering) { ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index b012fc5..8c6cc9e 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -32,6 +32,7 @@ #include "Outline.h" class SkBitmap; +class SkColorFilter; class SkPaint; namespace android { @@ -39,15 +40,95 @@ 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(); @@ -366,10 +447,6 @@ public: return false; } - bool setCaching(bool caching) { - return RP_SET(mPrimitiveFields.mCaching, caching); - } - int getWidth() const { return mPrimitiveFields.mWidth; } @@ -396,10 +473,6 @@ public: return mComputedFields.mTransformMatrix; } - bool getCaching() const { - return mPrimitiveFields.mCaching; - } - bool getClipToBounds() const { return mPrimitiveFields.mClipToBounds; } @@ -422,7 +495,7 @@ public: void debugOutputProperties(const int level) const; - ANDROID_API void updateMatrix(); + void updateMatrix(); bool hasClippingPath() const { return mPrimitiveFields.mRevealClip.willClip(); @@ -445,6 +518,14 @@ public: return mPrimitiveFields.mRevealClip; } + const LayerProperties& layerProperties() const { + return mLayerProperties; + } + + LayerProperties& mutateLayerProperties() { + return mLayerProperties; + } + private: // Rendering properties @@ -467,11 +548,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. diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index fd78f8e..0fc0cef 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -26,6 +26,7 @@ namespace uirenderer { class BaseRenderNodeAnimator; class AnimationListener; +class OpenGLRenderer; class AnimationHook { public: @@ -63,6 +64,7 @@ public: , animationHook(NULL) , prepareTextures(mode == MODE_FULL) , damageAccumulator(NullDamageAccumulator::instance()) + , renderer(0) {} const TraversalMode mode; @@ -73,6 +75,9 @@ public: bool prepareTextures; // Must not be null IDamageAccumulator* damageAccumulator; + // The renderer that will be drawing the next frame. Use this to push any + // layer updates or similar. May be NULL. + OpenGLRenderer* renderer; struct Out { Out() diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 8a5c857..440f965 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -440,6 +440,7 @@ void CanvasContext::prepareTree(TreeInfo& info) { info.frameTimeMs = mRenderThread.timeLord().frameTimeMs(); info.damageAccumulator = &mDamageAccumulator; + info.renderer = mCanvas; mRootRenderNode->prepareTree(info); int runningBehind = 0; diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index bdfdd21..797566f 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -130,9 +130,6 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) { mContext->processLayerUpdate(mLayers[i].get(), info); } mLayers.clear(); - if (info.out.hasAnimations) { - // TODO: Uh... crap? - } mContext->prepareTree(info); if (info.out.hasAnimations) { |