Loading libs/hwui/BakedOpRenderer.cpp +73 −7 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "Caches.h" #include "Glop.h" #include "GlopBuilder.h" #include "VertexBuffer.h" #include "renderstate/RenderState.h" #include "utils/FatVector.h" #include "utils/GLUtils.h" Loading @@ -45,7 +46,7 @@ OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, caches.textureState().bindTexture(GL_TEXTURE_2D, texture.id); texture.setWrap(GL_CLAMP_TO_EDGE, false, false, GL_TEXTURE_2D); // not setting filter on texture, since it's set when drawing, based on transform // not setting filter on texture, since it's set when rendering, based on transform glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, Loading @@ -55,7 +56,7 @@ OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, void OffscreenBuffer::updateMeshFromRegion() { // avoid T-junctions as they cause artifacts in between the resultant // geometry when complex transforms occur. // TODO: generate the safeRegion only if necessary based on drawing transform // TODO: generate the safeRegion only if necessary based on rendering transform Region safeRegion = Region::createTJunctionFreeRegion(region); size_t count; Loading Loading @@ -108,15 +109,15 @@ void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) { delete offscreenBuffer; } OffscreenBuffer* BakedOpRenderer::createLayer(uint32_t width, uint32_t height) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) { OffscreenBuffer* buffer = createOffscreenBuffer(mRenderState, width, height); startLayer(buffer); startRepaintLayer(buffer); return buffer; } void BakedOpRenderer::startLayer(OffscreenBuffer* offscreenBuffer) { void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); mRenderTarget.offscreenBuffer = offscreenBuffer; // create and bind framebuffer Loading Loading @@ -261,6 +262,71 @@ void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, co renderer.renderGlop(state, glop); } namespace VertexBufferRenderFlags { enum { Offset = 0x1, ShadowInterp = 0x2, }; } static void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state, const VertexBuffer& vertexBuffer, float translateX, float translateY, SkPaint& paint, int vertexBufferRenderFlags) { if (CC_LIKELY(vertexBuffer.getVertexCount())) { bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp; const int transformFlags = TransformFlags::OffsetByFudgeFactor; Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) .setRoundRectClipState(state.roundRectClipState) .setMeshVertexBuffer(vertexBuffer, shadowInterp) .setFillPaint(paint, state.alpha) .setTransform(state.computedState.transform, transformFlags) .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) .build(); renderer.renderGlop(state, glop); } } static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha, const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) { SkPaint paint; paint.setAntiAlias(true); // want to use AlphaVertex // The caller has made sure casterAlpha > 0. uint8_t ambientShadowAlpha = 128u; //TODO: mAmbientShadowAlpha; if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) { ambientShadowAlpha = Properties::overrideAmbientShadowStrength; } if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) { paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha)); renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, paint, VertexBufferRenderFlags::ShadowInterp); } uint8_t spotShadowAlpha = 128u; //TODO: mSpotShadowAlpha; if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) { spotShadowAlpha = Properties::overrideSpotShadowStrength; } if (spotShadowVertexBuffer && spotShadowAlpha > 0) { paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha)); renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, paint, VertexBufferRenderFlags::ShadowInterp); } } void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) { TessellationCache::vertexBuffer_pair_t buffers; Vector3 lightCenter = { 300, 300, 300 }; // TODO! float lightRadius = 150; // TODO! renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform, op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath, &op.shadowMatrixXY, &op.shadowMatrixZ, lightCenter, lightRadius, buffers); renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second); } void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, const BakedOpState& state) { Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) Loading libs/hwui/BakedOpRenderer.h +2 −2 Original line number Diff line number Diff line Loading @@ -81,8 +81,8 @@ public: void startFrame(uint32_t width, uint32_t height); void endFrame(); OffscreenBuffer* createLayer(uint32_t width, uint32_t height); void startLayer(OffscreenBuffer* offscreenBuffer); OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height); void startRepaintLayer(OffscreenBuffer* offscreenBuffer); void endLayer(); Texture* getTexture(const SkBitmap* bitmap); Loading libs/hwui/BakedOpState.h +31 −2 Original line number Diff line number Diff line Loading @@ -89,6 +89,21 @@ public: * and early return null in one place. */ } /** * Constructor for unbounded ops without transform/clip (namely shadows) * * Since the op doesn't have known bounds, we conservatively set the mapped bounds * to the current clipRect, and clipSideFlags to Full. */ ResolvedRenderState(const Snapshot& snapshot) { transform = *snapshot.transform; clipRect = snapshot.getRenderTargetClip(); clippedBounds = clipRect; transform.mapRect(clippedBounds); clipSideFlags = OpClipSideFlags::Full; } Matrix4 transform; Rect clipRect; int clipSideFlags = 0; Loading @@ -104,8 +119,7 @@ class BakedOpState { public: static BakedOpState* tryConstruct(LinearAllocator& allocator, const Snapshot& snapshot, const RecordedOp& recordedOp) { BakedOpState* bakedOp = new (allocator) BakedOpState( snapshot, recordedOp); BakedOpState* bakedOp = new (allocator) BakedOpState(snapshot, recordedOp); if (bakedOp->computedState.clippedBounds.isEmpty()) { // bounds are empty, so op is rejected allocator.rewindIfLastAlloc(bakedOp); Loading @@ -114,6 +128,14 @@ public: return bakedOp; } static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator, const Snapshot& snapshot, const ShadowOp* shadowOpPtr) { if (snapshot.getRenderTargetClip().isEmpty()) return nullptr; // clip isn't empty, so construct the op return new (allocator) BakedOpState(snapshot, shadowOpPtr); } static void* operator new(size_t size, LinearAllocator& allocator) { return allocator.alloc(size); } Loading @@ -134,6 +156,13 @@ private: , roundRectClipState(snapshot.roundRectClipState) , projectionPathMask(snapshot.projectionPathMask) , op(&recordedOp) {} BakedOpState(const Snapshot& snapshot, const ShadowOp* shadowOpPtr) : computedState(snapshot) , alpha(snapshot.alpha) , roundRectClipState(snapshot.roundRectClipState) , projectionPathMask(snapshot.projectionPathMask) , op(shadowOpPtr) {} }; }; // namespace uirenderer Loading libs/hwui/OpReorderer.cpp +59 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "utils/PaintUtils.h" #include <SkCanvas.h> #include <SkPathOps.h> #include <utils/Trace.h> #include <utils/TypeHelpers.h> Loading Loading @@ -347,7 +348,6 @@ OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip, OpReorderer::OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList) : mCanvasState(*this) { ATRACE_NAME("prepare drawing commands"); mLayerReorderers.emplace_back(viewportWidth, viewportHeight); mLayerStack.push_back(0); Loading Loading @@ -462,8 +462,60 @@ void OpReorderer::defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedN } void OpReorderer::deferShadow(const RenderNodeOp& casterNodeOp) { // TODO auto& node = *casterNodeOp.renderNode; auto& properties = node.properties(); if (properties.getAlpha() <= 0.0f || properties.getOutline().getAlpha() <= 0.0f || !properties.getOutline().getPath() || properties.getScaleX() == 0 || properties.getScaleY() == 0) { // no shadow to draw return; } 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* casterPath = casterOutlinePath; // intersect the shadow-casting path with the reveal, if present if (revealClipPath) { frameAllocatedPath = createFrameAllocatedPath(); Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, frameAllocatedPath); casterPath = frameAllocatedPath; } // intersect the shadow-casting path with the clipBounds, if present if (properties.getClippingFlags() & CLIP_TO_CLIP_BOUNDS) { if (!frameAllocatedPath) { frameAllocatedPath = createFrameAllocatedPath(); } Rect clipBounds; properties.getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds); SkPath clipBoundsPath; clipBoundsPath.addRect(clipBounds.left, clipBounds.top, clipBounds.right, clipBounds.bottom); Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, frameAllocatedPath); casterPath = frameAllocatedPath; } ShadowOp* shadowOp = new (mAllocator) ShadowOp(casterNodeOp, casterAlpha, casterPath, mCanvasState.getLocalClipBounds()); BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct( mAllocator, *mCanvasState.currentSnapshot(), shadowOp); if (CC_LIKELY(bakedOpState)) { currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow); } } /** * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods. * Loading Loading @@ -593,5 +645,9 @@ void OpReorderer::onLayerOp(const LayerOp& op) { LOG_ALWAYS_FATAL("unsupported"); } void OpReorderer::onShadowOp(const ShadowOp& op) { LOG_ALWAYS_FATAL("unsupported"); } } // namespace uirenderer } // namespace android libs/hwui/OpReorderer.h +9 −2 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ namespace OpBatchType { AlphaMaskTexture, Text, ColorText, Shadow, Count // must be last }; Loading Loading @@ -152,11 +153,11 @@ public: LayerReorderer& layer = mLayerReorderers[i]; if (layer.renderNode) { // cached HW layer - can't skip layer if empty renderer.startLayer(layer.offscreenBuffer); renderer.startRepaintLayer(layer.offscreenBuffer); layer.replayBakedOpsImpl((void*)&renderer, receivers); renderer.endLayer(); } else if (!layer.empty()) { // save layer - skip entire layer if empty layer.offscreenBuffer = renderer.createLayer(layer.width, layer.height); layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height); layer.replayBakedOpsImpl((void*)&renderer, receivers); renderer.endLayer(); } Loading Loading @@ -210,6 +211,10 @@ private: void replayBakedOpsImpl(void* arg, BakedOpDispatcher* receivers); SkPath* createFrameAllocatedPath() { mFrameAllocatedPaths.emplace_back(new SkPath); return mFrameAllocatedPaths.back().get(); } /** * Declares all OpReorderer::onXXXXOp() methods for every RecordedOp type. * Loading @@ -220,6 +225,8 @@ private: void on##Type(const Type& op); MAP_OPS(INTERNAL_OP_HANDLER) std::vector<std::unique_ptr<SkPath> > mFrameAllocatedPaths; // List of every deferred layer's render state. Replayed in reverse order to render a frame. std::vector<LayerReorderer> mLayerReorderers; Loading Loading
libs/hwui/BakedOpRenderer.cpp +73 −7 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "Caches.h" #include "Glop.h" #include "GlopBuilder.h" #include "VertexBuffer.h" #include "renderstate/RenderState.h" #include "utils/FatVector.h" #include "utils/GLUtils.h" Loading @@ -45,7 +46,7 @@ OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, caches.textureState().bindTexture(GL_TEXTURE_2D, texture.id); texture.setWrap(GL_CLAMP_TO_EDGE, false, false, GL_TEXTURE_2D); // not setting filter on texture, since it's set when drawing, based on transform // not setting filter on texture, since it's set when rendering, based on transform glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, Loading @@ -55,7 +56,7 @@ OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, void OffscreenBuffer::updateMeshFromRegion() { // avoid T-junctions as they cause artifacts in between the resultant // geometry when complex transforms occur. // TODO: generate the safeRegion only if necessary based on drawing transform // TODO: generate the safeRegion only if necessary based on rendering transform Region safeRegion = Region::createTJunctionFreeRegion(region); size_t count; Loading Loading @@ -108,15 +109,15 @@ void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) { delete offscreenBuffer; } OffscreenBuffer* BakedOpRenderer::createLayer(uint32_t width, uint32_t height) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) { OffscreenBuffer* buffer = createOffscreenBuffer(mRenderState, width, height); startLayer(buffer); startRepaintLayer(buffer); return buffer; } void BakedOpRenderer::startLayer(OffscreenBuffer* offscreenBuffer) { void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); mRenderTarget.offscreenBuffer = offscreenBuffer; // create and bind framebuffer Loading Loading @@ -261,6 +262,71 @@ void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, co renderer.renderGlop(state, glop); } namespace VertexBufferRenderFlags { enum { Offset = 0x1, ShadowInterp = 0x2, }; } static void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state, const VertexBuffer& vertexBuffer, float translateX, float translateY, SkPaint& paint, int vertexBufferRenderFlags) { if (CC_LIKELY(vertexBuffer.getVertexCount())) { bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp; const int transformFlags = TransformFlags::OffsetByFudgeFactor; Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) .setRoundRectClipState(state.roundRectClipState) .setMeshVertexBuffer(vertexBuffer, shadowInterp) .setFillPaint(paint, state.alpha) .setTransform(state.computedState.transform, transformFlags) .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) .build(); renderer.renderGlop(state, glop); } } static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha, const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) { SkPaint paint; paint.setAntiAlias(true); // want to use AlphaVertex // The caller has made sure casterAlpha > 0. uint8_t ambientShadowAlpha = 128u; //TODO: mAmbientShadowAlpha; if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) { ambientShadowAlpha = Properties::overrideAmbientShadowStrength; } if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) { paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha)); renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, paint, VertexBufferRenderFlags::ShadowInterp); } uint8_t spotShadowAlpha = 128u; //TODO: mSpotShadowAlpha; if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) { spotShadowAlpha = Properties::overrideSpotShadowStrength; } if (spotShadowVertexBuffer && spotShadowAlpha > 0) { paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha)); renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, paint, VertexBufferRenderFlags::ShadowInterp); } } void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) { TessellationCache::vertexBuffer_pair_t buffers; Vector3 lightCenter = { 300, 300, 300 }; // TODO! float lightRadius = 150; // TODO! renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform, op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath, &op.shadowMatrixXY, &op.shadowMatrixZ, lightCenter, lightRadius, buffers); renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second); } void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, const BakedOpState& state) { Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) Loading
libs/hwui/BakedOpRenderer.h +2 −2 Original line number Diff line number Diff line Loading @@ -81,8 +81,8 @@ public: void startFrame(uint32_t width, uint32_t height); void endFrame(); OffscreenBuffer* createLayer(uint32_t width, uint32_t height); void startLayer(OffscreenBuffer* offscreenBuffer); OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height); void startRepaintLayer(OffscreenBuffer* offscreenBuffer); void endLayer(); Texture* getTexture(const SkBitmap* bitmap); Loading
libs/hwui/BakedOpState.h +31 −2 Original line number Diff line number Diff line Loading @@ -89,6 +89,21 @@ public: * and early return null in one place. */ } /** * Constructor for unbounded ops without transform/clip (namely shadows) * * Since the op doesn't have known bounds, we conservatively set the mapped bounds * to the current clipRect, and clipSideFlags to Full. */ ResolvedRenderState(const Snapshot& snapshot) { transform = *snapshot.transform; clipRect = snapshot.getRenderTargetClip(); clippedBounds = clipRect; transform.mapRect(clippedBounds); clipSideFlags = OpClipSideFlags::Full; } Matrix4 transform; Rect clipRect; int clipSideFlags = 0; Loading @@ -104,8 +119,7 @@ class BakedOpState { public: static BakedOpState* tryConstruct(LinearAllocator& allocator, const Snapshot& snapshot, const RecordedOp& recordedOp) { BakedOpState* bakedOp = new (allocator) BakedOpState( snapshot, recordedOp); BakedOpState* bakedOp = new (allocator) BakedOpState(snapshot, recordedOp); if (bakedOp->computedState.clippedBounds.isEmpty()) { // bounds are empty, so op is rejected allocator.rewindIfLastAlloc(bakedOp); Loading @@ -114,6 +128,14 @@ public: return bakedOp; } static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator, const Snapshot& snapshot, const ShadowOp* shadowOpPtr) { if (snapshot.getRenderTargetClip().isEmpty()) return nullptr; // clip isn't empty, so construct the op return new (allocator) BakedOpState(snapshot, shadowOpPtr); } static void* operator new(size_t size, LinearAllocator& allocator) { return allocator.alloc(size); } Loading @@ -134,6 +156,13 @@ private: , roundRectClipState(snapshot.roundRectClipState) , projectionPathMask(snapshot.projectionPathMask) , op(&recordedOp) {} BakedOpState(const Snapshot& snapshot, const ShadowOp* shadowOpPtr) : computedState(snapshot) , alpha(snapshot.alpha) , roundRectClipState(snapshot.roundRectClipState) , projectionPathMask(snapshot.projectionPathMask) , op(shadowOpPtr) {} }; }; // namespace uirenderer Loading
libs/hwui/OpReorderer.cpp +59 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "utils/PaintUtils.h" #include <SkCanvas.h> #include <SkPathOps.h> #include <utils/Trace.h> #include <utils/TypeHelpers.h> Loading Loading @@ -347,7 +348,6 @@ OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip, OpReorderer::OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList) : mCanvasState(*this) { ATRACE_NAME("prepare drawing commands"); mLayerReorderers.emplace_back(viewportWidth, viewportHeight); mLayerStack.push_back(0); Loading Loading @@ -462,8 +462,60 @@ void OpReorderer::defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedN } void OpReorderer::deferShadow(const RenderNodeOp& casterNodeOp) { // TODO auto& node = *casterNodeOp.renderNode; auto& properties = node.properties(); if (properties.getAlpha() <= 0.0f || properties.getOutline().getAlpha() <= 0.0f || !properties.getOutline().getPath() || properties.getScaleX() == 0 || properties.getScaleY() == 0) { // no shadow to draw return; } 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* casterPath = casterOutlinePath; // intersect the shadow-casting path with the reveal, if present if (revealClipPath) { frameAllocatedPath = createFrameAllocatedPath(); Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, frameAllocatedPath); casterPath = frameAllocatedPath; } // intersect the shadow-casting path with the clipBounds, if present if (properties.getClippingFlags() & CLIP_TO_CLIP_BOUNDS) { if (!frameAllocatedPath) { frameAllocatedPath = createFrameAllocatedPath(); } Rect clipBounds; properties.getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds); SkPath clipBoundsPath; clipBoundsPath.addRect(clipBounds.left, clipBounds.top, clipBounds.right, clipBounds.bottom); Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, frameAllocatedPath); casterPath = frameAllocatedPath; } ShadowOp* shadowOp = new (mAllocator) ShadowOp(casterNodeOp, casterAlpha, casterPath, mCanvasState.getLocalClipBounds()); BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct( mAllocator, *mCanvasState.currentSnapshot(), shadowOp); if (CC_LIKELY(bakedOpState)) { currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow); } } /** * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods. * Loading Loading @@ -593,5 +645,9 @@ void OpReorderer::onLayerOp(const LayerOp& op) { LOG_ALWAYS_FATAL("unsupported"); } void OpReorderer::onShadowOp(const ShadowOp& op) { LOG_ALWAYS_FATAL("unsupported"); } } // namespace uirenderer } // namespace android
libs/hwui/OpReorderer.h +9 −2 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ namespace OpBatchType { AlphaMaskTexture, Text, ColorText, Shadow, Count // must be last }; Loading Loading @@ -152,11 +153,11 @@ public: LayerReorderer& layer = mLayerReorderers[i]; if (layer.renderNode) { // cached HW layer - can't skip layer if empty renderer.startLayer(layer.offscreenBuffer); renderer.startRepaintLayer(layer.offscreenBuffer); layer.replayBakedOpsImpl((void*)&renderer, receivers); renderer.endLayer(); } else if (!layer.empty()) { // save layer - skip entire layer if empty layer.offscreenBuffer = renderer.createLayer(layer.width, layer.height); layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height); layer.replayBakedOpsImpl((void*)&renderer, receivers); renderer.endLayer(); } Loading Loading @@ -210,6 +211,10 @@ private: void replayBakedOpsImpl(void* arg, BakedOpDispatcher* receivers); SkPath* createFrameAllocatedPath() { mFrameAllocatedPaths.emplace_back(new SkPath); return mFrameAllocatedPaths.back().get(); } /** * Declares all OpReorderer::onXXXXOp() methods for every RecordedOp type. * Loading @@ -220,6 +225,8 @@ private: void on##Type(const Type& op); MAP_OPS(INTERNAL_OP_HANDLER) std::vector<std::unique_ptr<SkPath> > mFrameAllocatedPaths; // List of every deferred layer's render state. Replayed in reverse order to render a frame. std::vector<LayerReorderer> mLayerReorderers; Loading