diff options
author | Chris Craik <ccraik@google.com> | 2016-07-06 16:10:09 -0700 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2016-07-07 15:53:50 -0700 |
commit | 5e00c7ce063116c11315639f0035aca8ad73e8cc (patch) | |
tree | 6ca43728a401d92762fb5fd65cfd39afe9438571 /libs/hwui/RenderNode.cpp | |
parent | 32d9ae186733115802eafe241c2029a63794efc2 (diff) |
Delete old rendering pipeline
fixes: 30002246
Change-Id: I45df0e924708526cee045b14c291bd23aa1a92db
Diffstat (limited to 'libs/hwui/RenderNode.cpp')
-rw-r--r-- | libs/hwui/RenderNode.cpp | 571 |
1 files changed, 13 insertions, 558 deletions
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index f8797bf63442..5330e2365d66 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -16,19 +16,17 @@ #include "RenderNode.h" +#include "BakedOpRenderer.h" #include "DamageAccumulator.h" #include "Debug.h" -#if HWUI_NEW_OPS -#include "BakedOpRenderer.h" -#include "RecordedOp.h" -#include "OpDumper.h" -#endif -#include "DisplayListOp.h" #include "LayerRenderer.h" -#include "OpenGLRenderer.h" +#include "OpDumper.h" +#include "RecordedOp.h" #include "TreeInfo.h" #include "utils/MathUtils.h" #include "utils/TraceUtils.h" +#include "VectorDrawable.h" +#include "renderstate/RenderState.h" #include "renderthread/CanvasContext.h" #include "protos/hwui.pb.h" @@ -41,23 +39,6 @@ namespace android { namespace uirenderer { -void RenderNode::debugDumpLayers(const char* prefix) { -#if HWUI_NEW_OPS - LOG_ALWAYS_FATAL("TODO: dump layer"); -#else - if (mLayer) { - ALOGD("%sNode %p (%s) has layer %p (fbo = %u, wasBuildLayered = %s)", - prefix, this, getName(), mLayer, mLayer->getFbo(), - mLayer->wasBuildLayered ? "true" : "false"); - } -#endif - if (mDisplayList) { - for (auto&& child : mDisplayList->getChildren()) { - child->renderNode->debugDumpLayers(prefix); - } - } -} - RenderNode::RenderNode() : mDirtyPropertyFields(0) , mNeedsDisplayListSync(false) @@ -70,15 +51,7 @@ RenderNode::RenderNode() RenderNode::~RenderNode() { deleteDisplayList(nullptr); delete mStagingDisplayList; -#if HWUI_NEW_OPS LOG_ALWAYS_FATAL_IF(mLayer, "layer missed detachment!"); -#else - if (mLayer) { - ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer); - mLayer->postDecStrong(); - mLayer = nullptr; - } -#endif } void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) { @@ -96,7 +69,6 @@ void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* o * This function is a simplified version of replay(), where we simply retrieve and log the * display list. This function should remain in sync with the replay() function. */ -#if HWUI_NEW_OPS void RenderNode::output(uint32_t level, const char* label) { ALOGD("%s (%s %p%s%s%s%s%s)", label, @@ -123,26 +95,6 @@ void RenderNode::output(uint32_t level, const char* label) { } ALOGD("%*s/RenderNode(%s %p)", level * 2, "", getName(), this); } -#else -void RenderNode::output(uint32_t level) { - ALOGD("%*sStart display list (%p, %s%s%s%s%s%s)", (level - 1) * 2, "", this, - getName(), - (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""), - (properties().hasShadow() ? ", casting shadow" : ""), - (isRenderable() ? "" : ", empty"), - (properties().getProjectBackwards() ? ", projected" : ""), - (mLayer != nullptr ? ", on HW Layer" : "")); - ALOGD("%*s%s %d", level * 2, "", "Save", SaveFlags::MatrixClip); - properties().debugOutputProperties(level); - if (mDisplayList) { - // TODO: consider printing the chunk boundaries here - for (auto&& op : mDisplayList->getOps()) { - op->output(level, DisplayListOp::kOpLogFlag_Recurse); - } - } - ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName()); - } -#endif void RenderNode::copyTo(proto::RenderNode *pnode) { pnode->set_id(static_cast<uint64_t>( @@ -272,29 +224,17 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) { } } -static layer_t* createLayer(RenderState& renderState, uint32_t width, uint32_t height) { -#if HWUI_NEW_OPS +static OffscreenBuffer* createLayer(RenderState& renderState, uint32_t width, uint32_t height) { return renderState.layerPool().get(renderState, width, height); -#else - return LayerRenderer::createRenderLayer(renderState, width, height); -#endif } -static void destroyLayer(layer_t* layer) { -#if HWUI_NEW_OPS +static void destroyLayer(OffscreenBuffer* layer) { RenderState& renderState = layer->renderState; renderState.layerPool().putOrDelete(layer); -#else - LayerRenderer::destroyLayer(layer); -#endif } -static bool layerMatchesWidthAndHeight(layer_t* layer, int width, int height) { -#if HWUI_NEW_OPS +static bool layerMatchesWidthAndHeight(OffscreenBuffer* layer, int width, int height) { return layer->viewportWidth == (uint32_t) width && layer->viewportHeight == (uint32_t)height; -#else - return layer->layer.getWidth() == width && layer->layer.getHeight() == height; -#endif } void RenderNode::pushLayerUpdate(TreeInfo& info) { @@ -312,22 +252,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { bool transformUpdateNeeded = false; if (!mLayer) { mLayer = createLayer(info.canvasContext.getRenderState(), getWidth(), getHeight()); -#if !HWUI_NEW_OPS - applyLayerPropertiesToLayer(info); -#endif damageSelf(info); transformUpdateNeeded = true; } else if (!layerMatchesWidthAndHeight(mLayer, getWidth(), getHeight())) { -#if HWUI_NEW_OPS // TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering) // Or, ideally, maintain damage between frames on node/layer so ordering is always correct RenderState& renderState = mLayer->renderState; if (properties().fitsOnLayer()) { mLayer = renderState.layerPool().resize(mLayer, getWidth(), getHeight()); } else { -#else - if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) { -#endif destroyLayer(mLayer); mLayer = nullptr; } @@ -362,19 +295,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { mLayer->setWindowTransform(windowTransform); } -#if HWUI_NEW_OPS info.layerUpdateQueue->enqueueLayerWithDamage(this, dirty); -#else - if (dirty.intersect(0, 0, getWidth(), getHeight())) { - dirty.roundOut(&dirty); - 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); - } -#endif // There might be prefetched layers that need to be accounted for. // That might be us, so tell CanvasContext that this layer is in the @@ -450,9 +371,6 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { damageSelf(info); info.damageAccumulator->popTransform(); syncProperties(); -#if !HWUI_NEW_OPS - applyLayerPropertiesToLayer(info); -#endif // 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 @@ -463,17 +381,6 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { } } -#if !HWUI_NEW_OPS -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()); -} -#endif - void RenderNode::syncDisplayList(TreeInfo* info) { // Make sure we inc first so that we don't fluctuate between 0 and 1, // which would thrash the layer cache @@ -526,15 +433,8 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL } for (auto&& op : subtree->getChildren()) { RenderNode* childNode = op->renderNode; -#if HWUI_NEW_OPS info.damageAccumulator->pushTransform(&op->localMatrix); bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip; -#else - info.damageAccumulator->pushTransform(&op->localMatrix); - bool childFunctorsNeedLayer = functorsNeedLayer - // Recorded with non-rect clip, or canvas-rotated by parent - || op->mRecordedWithPotentialStencilClip; -#endif childNode->prepareTreeImpl(info, childFunctorsNeedLayer); info.damageAccumulator->popTransform(); } @@ -576,84 +476,6 @@ void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) { } } -/* - * For property operations, we pass a savecount of 0, since the operations aren't part of the - * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in - * base saveCount (i.e., how RestoreToCount uses saveCount + properties().getCount()) - */ -#define PROPERTY_SAVECOUNT 0 - -template <class T> -void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) { -#if DEBUG_DISPLAY_LIST - properties().debugOutputProperties(handler.level() + 1); -#endif - if (properties().getLeft() != 0 || properties().getTop() != 0) { - renderer.translate(properties().getLeft(), properties().getTop()); - } - if (properties().getStaticMatrix()) { - renderer.concatMatrix(*properties().getStaticMatrix()); - } else if (properties().getAnimationMatrix()) { - renderer.concatMatrix(*properties().getAnimationMatrix()); - } - if (properties().hasTransformMatrix()) { - if (properties().isTransformTranslateOnly()) { - renderer.translate(properties().getTranslationX(), properties().getTranslationY()); - } else { - renderer.concatMatrix(*properties().getTransformMatrix()); - } - } - const bool isLayer = properties().effectiveLayerType() != LayerType::None; - int clipFlags = properties().getClippingFlags(); - if (properties().getAlpha() < 1) { - if (isLayer) { - clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer - } - if (CC_LIKELY(isLayer || !properties().getHasOverlappingRendering())) { - // simply scale rendering content's alpha - renderer.scaleAlpha(properties().getAlpha()); - } else { - // savelayer needed to create an offscreen buffer - Rect layerBounds(0, 0, getWidth(), getHeight()); - if (clipFlags) { - properties().getClippingRectForFlags(clipFlags, &layerBounds); - clipFlags = 0; // all clipping done by savelayer - } - SaveLayerOp* op = new (handler.allocator()) SaveLayerOp( - layerBounds.left, layerBounds.top, - layerBounds.right, layerBounds.bottom, - (int) (properties().getAlpha() * 255), - SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer); - handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); - } - - if (CC_UNLIKELY(ATRACE_ENABLED() && properties().promotedToLayer())) { - // pretend alpha always causes savelayer to warn about - // performance problem affecting old versions - ATRACE_FORMAT("%s alpha caused saveLayer %dx%d", getName(), - static_cast<int>(getWidth()), - static_cast<int>(getHeight())); - } - } - if (clipFlags) { - Rect clipRect; - properties().getClippingRectForFlags(clipFlags, &clipRect); - ClipRectOp* op = new (handler.allocator()) ClipRectOp( - clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, - SkRegion::kIntersect_Op); - handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); - } - - // TODO: support nesting round rect clips - if (mProperties.getRevealClip().willClip()) { - Rect bounds; - mProperties.getRevealClip().getBounds(&bounds); - renderer.setClippingRoundRect(handler.allocator(), bounds, mProperties.getRevealClip().getRadius()); - } else if (mProperties.getOutline().willClip()) { - renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline())); - } -} - /** * Apply property-based transformations to input matrix * @@ -714,14 +536,14 @@ void RenderNode::computeOrdering() { // transform properties are applied correctly to top level children if (mDisplayList == nullptr) return; for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) { - renderNodeOp_t* childOp = mDisplayList->getChildren()[i]; + RenderNodeOp* childOp = mDisplayList->getChildren()[i]; childOp->renderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity()); } } void RenderNode::computeOrderingImpl( - renderNodeOp_t* opState, - std::vector<renderNodeOp_t*>* compositedChildrenOfProjectionSurface, + RenderNodeOp* opState, + std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface) { mProjectedNodes.clear(); if (mDisplayList == nullptr || mDisplayList->isEmpty()) return; @@ -745,10 +567,10 @@ void RenderNode::computeOrderingImpl( const bool isProjectionReceiver = mDisplayList->projectionReceiveIndex >= 0; bool haveAppliedPropertiesToProjection = false; for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) { - renderNodeOp_t* childOp = mDisplayList->getChildren()[i]; + RenderNodeOp* childOp = mDisplayList->getChildren()[i]; RenderNode* child = childOp->renderNode; - std::vector<renderNodeOp_t*>* projectionChildren = nullptr; + std::vector<RenderNodeOp*>* projectionChildren = nullptr; const mat4* projectionTransform = nullptr; if (isProjectionReceiver && !child->properties().getProjectBackwards()) { // if receiving projections, collect projecting descendant @@ -771,372 +593,5 @@ void RenderNode::computeOrderingImpl( } } -class DeferOperationHandler { -public: - DeferOperationHandler(DeferStateStruct& deferStruct, int level) - : mDeferStruct(deferStruct), mLevel(level) {} - inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) { - operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds); - } - inline LinearAllocator& allocator() { return *(mDeferStruct.mAllocator); } - inline void startMark(const char* name) {} // do nothing - inline void endMark() {} - inline int level() { return mLevel; } - inline int replayFlags() { return mDeferStruct.mReplayFlags; } - inline SkPath* allocPathForFrame() { return mDeferStruct.allocPathForFrame(); } - -private: - DeferStateStruct& mDeferStruct; - const int mLevel; -}; - -void RenderNode::defer(DeferStateStruct& deferStruct, const int level) { - DeferOperationHandler handler(deferStruct, level); - issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler); -} - -class ReplayOperationHandler { -public: - ReplayOperationHandler(ReplayStateStruct& replayStruct, int level) - : mReplayStruct(replayStruct), mLevel(level) {} - inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) { -#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS - mReplayStruct.mRenderer.eventMark(operation->name()); -#endif - operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds); - } - inline LinearAllocator& allocator() { return *(mReplayStruct.mAllocator); } - inline void startMark(const char* name) { - mReplayStruct.mRenderer.startMark(name); - } - inline void endMark() { - mReplayStruct.mRenderer.endMark(); - } - inline int level() { return mLevel; } - inline int replayFlags() { return mReplayStruct.mReplayFlags; } - inline SkPath* allocPathForFrame() { return mReplayStruct.allocPathForFrame(); } - -private: - ReplayStateStruct& mReplayStruct; - const int mLevel; -}; - -void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) { - ReplayOperationHandler handler(replayStruct, level); - issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler); -} - -void RenderNode::buildZSortedChildList(const DisplayList::Chunk& chunk, - std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) { -#if !HWUI_NEW_OPS - if (chunk.beginChildIndex == chunk.endChildIndex) return; - - for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) { - DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i]; - RenderNode* child = childOp->renderNode; - float childZ = child->properties().getZ(); - - if (!MathUtils::isZero(childZ) && chunk.reorderChildren) { - zTranslatedNodes.push_back(ZDrawRenderNodeOpPair(childZ, childOp)); - childOp->skipInOrderDraw = true; - } else if (!child->properties().getProjectBackwards()) { - // regular, in order drawing DisplayList - childOp->skipInOrderDraw = false; - } - } - - // Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order) - std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end()); -#endif -} - -template <class T> -void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) { - if (properties().getAlpha() <= 0.0f - || properties().getOutline().getAlpha() <= 0.0f - || !properties().getOutline().getPath() - || properties().getScaleX() == 0 - || properties().getScaleY() == 0) { - // no shadow to draw - return; - } - - mat4 shadowMatrixXY(transformFromParent); - applyViewPropertyTransforms(shadowMatrixXY); - - // Z matrix needs actual 3d transformation, so mapped z values will be correct - mat4 shadowMatrixZ(transformFromParent); - applyViewPropertyTransforms(shadowMatrixZ, true); - - const SkPath* casterOutlinePath = properties().getOutline().getPath(); - const SkPath* revealClipPath = properties().getRevealClip().getPath(); - if (revealClipPath && revealClipPath->isEmpty()) return; - - float casterAlpha = properties().getAlpha() * properties().getOutline().getAlpha(); - - - // holds temporary SkPath to store the result of intersections - SkPath* frameAllocatedPath = nullptr; - const SkPath* outlinePath = casterOutlinePath; - - // intersect the outline with the reveal clip, if present - if (revealClipPath) { - frameAllocatedPath = handler.allocPathForFrame(); - - Op(*outlinePath, *revealClipPath, kIntersect_SkPathOp, frameAllocatedPath); - outlinePath = frameAllocatedPath; - } - - // intersect the outline with the clipBounds, if present - if (properties().getClippingFlags() & CLIP_TO_CLIP_BOUNDS) { - if (!frameAllocatedPath) { - frameAllocatedPath = handler.allocPathForFrame(); - } - - Rect clipBounds; - properties().getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds); - SkPath clipBoundsPath; - clipBoundsPath.addRect(clipBounds.left, clipBounds.top, - clipBounds.right, clipBounds.bottom); - - Op(*outlinePath, clipBoundsPath, kIntersect_SkPathOp, frameAllocatedPath); - outlinePath = frameAllocatedPath; - } - - DisplayListOp* shadowOp = new (handler.allocator()) DrawShadowOp( - shadowMatrixXY, shadowMatrixZ, casterAlpha, outlinePath); - handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds()); -} - -#define SHADOW_DELTA 0.1f - -template <class T> -void RenderNode::issueOperationsOf3dChildren(ChildrenSelectMode mode, - const Matrix4& initialTransform, const std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes, - OpenGLRenderer& renderer, T& handler) { - const int size = zTranslatedNodes.size(); - if (size == 0 - || (mode == ChildrenSelectMode::NegativeZChildren && zTranslatedNodes[0].key > 0.0f) - || (mode == ChildrenSelectMode::PositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) { - // no 3d children to draw - return; - } - - // Apply the base transform of the parent of the 3d children. This isolates - // 3d children of the current chunk from transformations made in previous chunks. - int rootRestoreTo = renderer.save(SaveFlags::Matrix); - renderer.setGlobalMatrix(initialTransform); - - /** - * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters - * with very similar Z heights to draw together. - * - * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are - * underneath both, and neither's shadow is drawn on top of the other. - */ - const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes); - size_t drawIndex, shadowIndex, endIndex; - if (mode == ChildrenSelectMode::NegativeZChildren) { - drawIndex = 0; - endIndex = nonNegativeIndex; - shadowIndex = endIndex; // draw no shadows - } else { - drawIndex = nonNegativeIndex; - endIndex = size; - shadowIndex = drawIndex; // potentially draw shadow for each pos Z child - } - - DISPLAY_LIST_LOGD("%*s%d %s 3d children:", (handler.level() + 1) * 2, "", - endIndex - drawIndex, mode == kNegativeZChildren ? "negative" : "positive"); - - float lastCasterZ = 0.0f; - while (shadowIndex < endIndex || drawIndex < endIndex) { - if (shadowIndex < endIndex) { - DrawRenderNodeOp* casterOp = zTranslatedNodes[shadowIndex].value; - RenderNode* caster = casterOp->renderNode; - const float casterZ = zTranslatedNodes[shadowIndex].key; - // attempt to render the shadow if the caster about to be drawn is its caster, - // OR if its caster's Z value is similar to the previous potential caster - if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) { - caster->issueDrawShadowOperation(casterOp->localMatrix, handler); - - lastCasterZ = casterZ; // must do this even if current caster not casting a shadow - shadowIndex++; - continue; - } - } - - // only the actual child DL draw needs to be in save/restore, - // since it modifies the renderer's matrix - int restoreTo = renderer.save(SaveFlags::Matrix); - - DrawRenderNodeOp* childOp = zTranslatedNodes[drawIndex].value; - - renderer.concatMatrix(childOp->localMatrix); - childOp->skipInOrderDraw = false; // this is horrible, I'm so sorry everyone - handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds()); - childOp->skipInOrderDraw = true; - - renderer.restoreToCount(restoreTo); - drawIndex++; - } - renderer.restoreToCount(rootRestoreTo); -} - -template <class T> -void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) { - DISPLAY_LIST_LOGD("%*s%d projected children:", (handler.level() + 1) * 2, "", mProjectedNodes.size()); - const SkPath* projectionReceiverOutline = properties().getOutline().getPath(); - int restoreTo = renderer.getSaveCount(); - - LinearAllocator& alloc = handler.allocator(); - handler(new (alloc) SaveOp(SaveFlags::MatrixClip), - PROPERTY_SAVECOUNT, properties().getClipToBounds()); - - // Transform renderer to match background we're projecting onto - // (by offsetting canvas by translationX/Y of background rendernode, since only those are set) - const DisplayListOp* op = -#if HWUI_NEW_OPS - nullptr; - LOG_ALWAYS_FATAL("unsupported"); -#else - (mDisplayList->getOps()[mDisplayList->projectionReceiveIndex]); -#endif - const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op); - const RenderProperties& backgroundProps = backgroundOp->renderNode->properties(); - renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY()); - - // If the projection receiver has an outline, we mask projected content to it - // (which we know, apriori, are all tessellated paths) - renderer.setProjectionPathMask(alloc, projectionReceiverOutline); - - // draw projected nodes - for (size_t i = 0; i < mProjectedNodes.size(); i++) { - renderNodeOp_t* childOp = mProjectedNodes[i]; - - // matrix save, concat, and restore can be done safely without allocating operations - int restoreTo = renderer.save(SaveFlags::Matrix); - renderer.concatMatrix(childOp->transformFromCompositingAncestor); - childOp->skipInOrderDraw = false; // this is horrible, I'm so sorry everyone - handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds()); - childOp->skipInOrderDraw = true; - renderer.restoreToCount(restoreTo); - } - - handler(new (alloc) RestoreToCountOp(restoreTo), - PROPERTY_SAVECOUNT, properties().getClipToBounds()); -} - -/** - * This function serves both defer and replay modes, and will organize the displayList's component - * operations for a single frame: - * - * Every 'simple' state operation that affects just the matrix and alpha (or other factors of - * DeferredDisplayState) may be issued directly to the renderer, but complex operations (with custom - * defer logic) and operations in displayListOps are issued through the 'handler' which handles the - * defer vs replay logic, per operation - */ -template <class T> -void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { - if (mDisplayList->isEmpty()) { - DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", handler.level() * 2, "", - this, getName()); - return; - } - -#if HWUI_NEW_OPS - const bool drawLayer = false; -#else - const bool drawLayer = (mLayer && (&renderer != mLayer->renderer.get())); -#endif - // 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); - if (useViewProperties) { - const Outline& outline = properties().getOutline(); - if (properties().getAlpha() <= 0 - || (outline.getShouldClip() && outline.isEmpty()) - || properties().getScaleX() == 0 - || properties().getScaleY() == 0) { - DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", handler.level() * 2, "", - this, getName()); - return; - } - } - - handler.startMark(getName()); - -#if DEBUG_DISPLAY_LIST - const Rect& clipRect = renderer.getLocalClipBounds(); - DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), localClipBounds: %.0f, %.0f, %.0f, %.0f", - handler.level() * 2, "", this, getName(), - clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); -#endif - - LinearAllocator& alloc = handler.allocator(); - int restoreTo = renderer.getSaveCount(); - handler(new (alloc) SaveOp(SaveFlags::MatrixClip), - PROPERTY_SAVECOUNT, properties().getClipToBounds()); - - DISPLAY_LIST_LOGD("%*sSave %d %d", (handler.level() + 1) * 2, "", - SaveFlags::MatrixClip, restoreTo); - - if (useViewProperties) { - setViewProperties<T>(renderer, handler); - } - -#if HWUI_NEW_OPS - LOG_ALWAYS_FATAL("legacy op traversal not supported"); -#else - bool quickRejected = properties().getClipToBounds() - && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight()); - if (!quickRejected) { - Matrix4 initialTransform(*(renderer.currentTransform())); - renderer.setBaseTransform(initialTransform); - - if (drawLayer) { - handler(new (alloc) DrawLayerOp(mLayer), - renderer.getSaveCount() - 1, properties().getClipToBounds()); - } else { - const int saveCountOffset = renderer.getSaveCount() - 1; - const int projectionReceiveIndex = mDisplayList->projectionReceiveIndex; - for (size_t chunkIndex = 0; chunkIndex < mDisplayList->getChunks().size(); chunkIndex++) { - const DisplayList::Chunk& chunk = mDisplayList->getChunks()[chunkIndex]; - - std::vector<ZDrawRenderNodeOpPair> zTranslatedNodes; - buildZSortedChildList(chunk, zTranslatedNodes); - - issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren, - initialTransform, zTranslatedNodes, renderer, handler); - - for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) { - DisplayListOp *op = mDisplayList->getOps()[opIndex]; -#if DEBUG_DISPLAY_LIST - op->output(handler.level() + 1); -#endif - handler(op, saveCountOffset, properties().getClipToBounds()); - - if (CC_UNLIKELY(!mProjectedNodes.empty() && projectionReceiveIndex >= 0 && - opIndex == static_cast<size_t>(projectionReceiveIndex))) { - issueOperationsOfProjectedChildren(renderer, handler); - } - } - - issueOperationsOf3dChildren(ChildrenSelectMode::PositiveZChildren, - initialTransform, zTranslatedNodes, renderer, handler); - } - } - } -#endif - - DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (handler.level() + 1) * 2, "", restoreTo); - handler(new (alloc) RestoreToCountOp(restoreTo), - PROPERTY_SAVECOUNT, properties().getClipToBounds()); - - DISPLAY_LIST_LOGD("%*sDone (%p, %s)", handler.level() * 2, "", this, getName()); - handler.endMark(); -} - } /* namespace uirenderer */ } /* namespace android */ |