Loading libs/hwui/BakedOpRenderer.cpp +82 −4 Original line number Diff line number Diff line Loading @@ -25,6 +25,15 @@ namespace android { namespace uirenderer { void BakedOpRenderer::Info::setViewport(uint32_t width, uint32_t height) { viewportWidth = width; viewportHeight = height; orthoMatrix.loadOrtho(viewportWidth, viewportHeight); renderState.setViewport(width, height); renderState.blend().syncEnabled(); } Texture* BakedOpRenderer::Info::getTexture(const SkBitmap* bitmap) { Texture* texture = renderState.assetAtlas().getEntryTexture(bitmap); if (!texture) { Loading @@ -45,9 +54,54 @@ void BakedOpRenderer::Info::renderGlop(const BakedOpState& state, const Glop& gl didDraw = true; } void BakedOpRenderer::startFrame(Info& info) { info.renderState.setViewport(info.viewportWidth, info.viewportHeight); info.renderState.blend().syncEnabled(); Layer* BakedOpRenderer::startLayer(Info& info, uint32_t width, uint32_t height) { info.caches.textureState().activateTexture(0); Layer* layer = info.caches.layerCache.get(info.renderState, width, height); LOG_ALWAYS_FATAL_IF(!layer, "need layer..."); info.layer = layer; layer->texCoords.set(0.0f, width / float(layer->getHeight()), height / float(layer->getWidth()), 0.0f); layer->setFbo(info.renderState.genFramebuffer()); info.renderState.bindFramebuffer(layer->getFbo()); layer->bindTexture(); // Initialize the texture if needed if (layer->isEmpty()) { layer->allocateTexture(); layer->setEmpty(false); } // attach the texture to the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->getTextureId(), 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED"); LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "framebuffer incomplete!"); // Clear the FBO info.renderState.scissor().setEnabled(false); glClear(GL_COLOR_BUFFER_BIT); // Change the viewport & ortho projection info.setViewport(width, height); return layer; } void BakedOpRenderer::endLayer(Info& info) { Layer* layer = info.layer; info.layer = nullptr; // Detach the texture from the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED"); layer->removeFbo(false); } void BakedOpRenderer::startFrame(Info& info, uint32_t width, uint32_t height) { info.renderState.bindFramebuffer(0); info.setViewport(width, height); Caches::getInstance().clearGarbage(); if (!info.opaque) { Loading Loading @@ -130,7 +184,31 @@ void BakedOpRenderer::onEndLayerOp(Info& info, const EndLayerOp& op, const Baked } void BakedOpRenderer::onLayerOp(Info& info, const LayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); Layer* layer = *op.layerHandle; // TODO: make this work for HW layers layer->setPaint(op.paint); layer->setBlend(true); float layerAlpha = (layer->getAlpha() / 255.0f) * state.alpha; const bool tryToSnap = state.computedState.transform.isPureTranslate(); Glop glop; GlopBuilder(info.renderState, info.caches, &glop) .setRoundRectClipState(state.roundRectClipState) .setMeshTexturedUvQuad(nullptr, layer->texCoords) .setFillLayer(layer->getTexture(), layer->getColorFilter(), layerAlpha, layer->getMode(), Blend::ModeOrderSwap::NoSwap) .setTransform(state.computedState.transform, TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds) .build(); info.renderGlop(state, glop); // return layer to cache, since each clipped savelayer is only drawn once. layer->setConvexMask(nullptr); if (!info.caches.layerCache.put(layer)) { // Failing to add the layer to the cache should happen only if the layer is too large LAYER_LOGD("Deleting layer"); layer->decStrong(nullptr); } } } // namespace uirenderer Loading libs/hwui/BakedOpRenderer.h +12 −9 Original line number Diff line number Diff line Loading @@ -25,21 +25,21 @@ namespace uirenderer { class Caches; struct Glop; class Layer; class RenderState; class BakedOpRenderer { public: class Info { public: Info(Caches& caches, RenderState& renderState, int viewportWidth, int viewportHeight, bool opaque) Info(Caches& caches, RenderState& renderState, bool opaque) : renderState(renderState) , caches(caches) , opaque(opaque) , viewportWidth(viewportWidth) , viewportHeight(viewportHeight) { orthoMatrix.loadOrtho(viewportWidth, viewportHeight); , opaque(opaque) { } void setViewport(uint32_t width, uint32_t height); Texture* getTexture(const SkBitmap* bitmap); void renderGlop(const BakedOpState& state, const Glop& glop); Loading @@ -47,16 +47,19 @@ public: Caches& caches; bool didDraw = false; bool opaque; Layer* layer = nullptr; // where should these live? layer state object? int viewportWidth; int viewportHeight; bool opaque; uint32_t viewportWidth = 0; uint32_t viewportHeight = 0; Matrix4 orthoMatrix; }; static void startFrame(Info& info); static Layer* startLayer(Info& info, uint32_t width, uint32_t height); static void endLayer(Info& info); static void startFrame(Info& info, uint32_t width, uint32_t height); static void endFrame(Info& info); /** Loading libs/hwui/Layer.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -155,8 +155,7 @@ void Layer::removeFbo(bool flush) { if (fbo) { if (flush) LayerRenderer::flushLayer(renderState, this); // If put fails the cache will delete the FBO caches.fboCache.put(fbo); renderState.deleteFramebuffer(fbo); fbo = 0; } } Loading libs/hwui/LayerRenderer.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -189,7 +189,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height); Caches& caches = Caches::getInstance(); GLuint fbo = caches.fboCache.get(); GLuint fbo = renderState.genFramebuffer(); if (!fbo) { ALOGW("Could not obtain an FBO"); return nullptr; Loading @@ -204,7 +204,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width // We first obtain a layer before comparing against the max texture size // because layers are not allocated at the exact desired size. They are // always created slighly larger to improve recycling // always created slightly larger to improve recycling const uint32_t maxTextureSize = caches.maxTextureSize; if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) { ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", Loading Loading @@ -357,7 +357,7 @@ bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { GLuint fbo = caches.fboCache.get(); GLuint fbo = renderState.getFramebuffer(); if (!fbo) { ALOGW("Could not obtain an FBO"); return false; Loading Loading @@ -465,7 +465,7 @@ error: layer->setAlpha(alpha, mode); layer->setFbo(previousLayerFbo); caches.textureState().deleteTexture(texture); caches.fboCache.put(fbo); renderState.deleteFramebuffer(fbo); renderState.setViewport(previousViewportWidth, previousViewportHeight); return status; Loading libs/hwui/OpReorderer.cpp +23 −20 Original line number Diff line number Diff line Loading @@ -203,7 +203,7 @@ private: }; // iterate back toward target to see if anything drawn since should overlap the new op // if no target, merging ops still interate to find similar batch to insert after // if no target, merging ops still iterate to find similar batch to insert after void OpReorderer::LayerReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds, BatchBase** targetBatch, size_t* insertBatchIndex) const { for (int i = mBatches.size() - 1; i >= 0; i--) { Loading Loading @@ -292,18 +292,14 @@ void OpReorderer::LayerReorderer::dump() const { } } OpReorderer::OpReorderer() OpReorderer::OpReorderer(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight, const std::vector< sp<RenderNode> >& nodes) : mCanvasState(*this) { mLayerReorderers.emplace_back(); mLayerStack.push_back(0); } void OpReorderer::onViewportInitialized() {} ATRACE_NAME("prepare drawing commands"); void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {} mLayerReorderers.emplace_back(viewportWidth, viewportHeight); mLayerStack.push_back(0); void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeight, const std::vector< sp<RenderNode> >& nodes) { mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, clip.fLeft, clip.fTop, clip.fRight, clip.fBottom, Vector3()); Loading @@ -321,13 +317,22 @@ void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeigh } } void OpReorderer::defer(int viewportWidth, int viewportHeight, const DisplayList& displayList) { 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); mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, 0, 0, viewportWidth, viewportHeight, Vector3()); deferImpl(displayList); } void OpReorderer::onViewportInitialized() {} void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {} /** * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods. * Loading @@ -350,11 +355,6 @@ void OpReorderer::deferImpl(const DisplayList& displayList) { void OpReorderer::replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers) { ATRACE_NAME("flush drawing commands"); // Relay through layers in reverse order, since layers // later in the list will be drawn by earlier ones for (int i = mLayerReorderers.size() - 1; i >= 0; i--) { mLayerReorderers[i].replayBakedOpsImpl(arg, receivers); } } void OpReorderer::onRenderNodeOp(const RenderNodeOp& op) { Loading Loading @@ -405,15 +405,17 @@ void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) { // TODO: test rejection at defer time, where the bounds become empty void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) { const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth(); const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight(); mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag); mCanvasState.writableSnapshot()->transform->loadIdentity(); mCanvasState.writableSnapshot()->initializeViewport( (int) op.unmappedBounds.getWidth(), (int) op.unmappedBounds.getHeight()); mCanvasState.writableSnapshot()->initializeViewport(layerWidth, layerHeight); mCanvasState.writableSnapshot()->roundRectClipState = nullptr; // create a new layer, and push its index on the stack mLayerStack.push_back(mLayerReorderers.size()); mLayerReorderers.emplace_back(); mLayerReorderers.emplace_back(layerWidth, layerHeight); mLayerReorderers.back().beginLayerOp = &op; } Loading @@ -432,7 +434,8 @@ void OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) { beginLayerOp.unmappedBounds, beginLayerOp.localMatrix, beginLayerOp.localClipRect, beginLayerOp.paint); beginLayerOp.paint, &mLayerReorderers[finishedLayerIndex].layer); BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp); if (bakedOpState) { Loading Loading
libs/hwui/BakedOpRenderer.cpp +82 −4 Original line number Diff line number Diff line Loading @@ -25,6 +25,15 @@ namespace android { namespace uirenderer { void BakedOpRenderer::Info::setViewport(uint32_t width, uint32_t height) { viewportWidth = width; viewportHeight = height; orthoMatrix.loadOrtho(viewportWidth, viewportHeight); renderState.setViewport(width, height); renderState.blend().syncEnabled(); } Texture* BakedOpRenderer::Info::getTexture(const SkBitmap* bitmap) { Texture* texture = renderState.assetAtlas().getEntryTexture(bitmap); if (!texture) { Loading @@ -45,9 +54,54 @@ void BakedOpRenderer::Info::renderGlop(const BakedOpState& state, const Glop& gl didDraw = true; } void BakedOpRenderer::startFrame(Info& info) { info.renderState.setViewport(info.viewportWidth, info.viewportHeight); info.renderState.blend().syncEnabled(); Layer* BakedOpRenderer::startLayer(Info& info, uint32_t width, uint32_t height) { info.caches.textureState().activateTexture(0); Layer* layer = info.caches.layerCache.get(info.renderState, width, height); LOG_ALWAYS_FATAL_IF(!layer, "need layer..."); info.layer = layer; layer->texCoords.set(0.0f, width / float(layer->getHeight()), height / float(layer->getWidth()), 0.0f); layer->setFbo(info.renderState.genFramebuffer()); info.renderState.bindFramebuffer(layer->getFbo()); layer->bindTexture(); // Initialize the texture if needed if (layer->isEmpty()) { layer->allocateTexture(); layer->setEmpty(false); } // attach the texture to the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->getTextureId(), 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED"); LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "framebuffer incomplete!"); // Clear the FBO info.renderState.scissor().setEnabled(false); glClear(GL_COLOR_BUFFER_BIT); // Change the viewport & ortho projection info.setViewport(width, height); return layer; } void BakedOpRenderer::endLayer(Info& info) { Layer* layer = info.layer; info.layer = nullptr; // Detach the texture from the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED"); layer->removeFbo(false); } void BakedOpRenderer::startFrame(Info& info, uint32_t width, uint32_t height) { info.renderState.bindFramebuffer(0); info.setViewport(width, height); Caches::getInstance().clearGarbage(); if (!info.opaque) { Loading Loading @@ -130,7 +184,31 @@ void BakedOpRenderer::onEndLayerOp(Info& info, const EndLayerOp& op, const Baked } void BakedOpRenderer::onLayerOp(Info& info, const LayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); Layer* layer = *op.layerHandle; // TODO: make this work for HW layers layer->setPaint(op.paint); layer->setBlend(true); float layerAlpha = (layer->getAlpha() / 255.0f) * state.alpha; const bool tryToSnap = state.computedState.transform.isPureTranslate(); Glop glop; GlopBuilder(info.renderState, info.caches, &glop) .setRoundRectClipState(state.roundRectClipState) .setMeshTexturedUvQuad(nullptr, layer->texCoords) .setFillLayer(layer->getTexture(), layer->getColorFilter(), layerAlpha, layer->getMode(), Blend::ModeOrderSwap::NoSwap) .setTransform(state.computedState.transform, TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds) .build(); info.renderGlop(state, glop); // return layer to cache, since each clipped savelayer is only drawn once. layer->setConvexMask(nullptr); if (!info.caches.layerCache.put(layer)) { // Failing to add the layer to the cache should happen only if the layer is too large LAYER_LOGD("Deleting layer"); layer->decStrong(nullptr); } } } // namespace uirenderer Loading
libs/hwui/BakedOpRenderer.h +12 −9 Original line number Diff line number Diff line Loading @@ -25,21 +25,21 @@ namespace uirenderer { class Caches; struct Glop; class Layer; class RenderState; class BakedOpRenderer { public: class Info { public: Info(Caches& caches, RenderState& renderState, int viewportWidth, int viewportHeight, bool opaque) Info(Caches& caches, RenderState& renderState, bool opaque) : renderState(renderState) , caches(caches) , opaque(opaque) , viewportWidth(viewportWidth) , viewportHeight(viewportHeight) { orthoMatrix.loadOrtho(viewportWidth, viewportHeight); , opaque(opaque) { } void setViewport(uint32_t width, uint32_t height); Texture* getTexture(const SkBitmap* bitmap); void renderGlop(const BakedOpState& state, const Glop& glop); Loading @@ -47,16 +47,19 @@ public: Caches& caches; bool didDraw = false; bool opaque; Layer* layer = nullptr; // where should these live? layer state object? int viewportWidth; int viewportHeight; bool opaque; uint32_t viewportWidth = 0; uint32_t viewportHeight = 0; Matrix4 orthoMatrix; }; static void startFrame(Info& info); static Layer* startLayer(Info& info, uint32_t width, uint32_t height); static void endLayer(Info& info); static void startFrame(Info& info, uint32_t width, uint32_t height); static void endFrame(Info& info); /** Loading
libs/hwui/Layer.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -155,8 +155,7 @@ void Layer::removeFbo(bool flush) { if (fbo) { if (flush) LayerRenderer::flushLayer(renderState, this); // If put fails the cache will delete the FBO caches.fboCache.put(fbo); renderState.deleteFramebuffer(fbo); fbo = 0; } } Loading
libs/hwui/LayerRenderer.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -189,7 +189,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height); Caches& caches = Caches::getInstance(); GLuint fbo = caches.fboCache.get(); GLuint fbo = renderState.genFramebuffer(); if (!fbo) { ALOGW("Could not obtain an FBO"); return nullptr; Loading @@ -204,7 +204,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width // We first obtain a layer before comparing against the max texture size // because layers are not allocated at the exact desired size. They are // always created slighly larger to improve recycling // always created slightly larger to improve recycling const uint32_t maxTextureSize = caches.maxTextureSize; if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) { ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", Loading Loading @@ -357,7 +357,7 @@ bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { GLuint fbo = caches.fboCache.get(); GLuint fbo = renderState.getFramebuffer(); if (!fbo) { ALOGW("Could not obtain an FBO"); return false; Loading Loading @@ -465,7 +465,7 @@ error: layer->setAlpha(alpha, mode); layer->setFbo(previousLayerFbo); caches.textureState().deleteTexture(texture); caches.fboCache.put(fbo); renderState.deleteFramebuffer(fbo); renderState.setViewport(previousViewportWidth, previousViewportHeight); return status; Loading
libs/hwui/OpReorderer.cpp +23 −20 Original line number Diff line number Diff line Loading @@ -203,7 +203,7 @@ private: }; // iterate back toward target to see if anything drawn since should overlap the new op // if no target, merging ops still interate to find similar batch to insert after // if no target, merging ops still iterate to find similar batch to insert after void OpReorderer::LayerReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds, BatchBase** targetBatch, size_t* insertBatchIndex) const { for (int i = mBatches.size() - 1; i >= 0; i--) { Loading Loading @@ -292,18 +292,14 @@ void OpReorderer::LayerReorderer::dump() const { } } OpReorderer::OpReorderer() OpReorderer::OpReorderer(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight, const std::vector< sp<RenderNode> >& nodes) : mCanvasState(*this) { mLayerReorderers.emplace_back(); mLayerStack.push_back(0); } void OpReorderer::onViewportInitialized() {} ATRACE_NAME("prepare drawing commands"); void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {} mLayerReorderers.emplace_back(viewportWidth, viewportHeight); mLayerStack.push_back(0); void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeight, const std::vector< sp<RenderNode> >& nodes) { mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, clip.fLeft, clip.fTop, clip.fRight, clip.fBottom, Vector3()); Loading @@ -321,13 +317,22 @@ void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeigh } } void OpReorderer::defer(int viewportWidth, int viewportHeight, const DisplayList& displayList) { 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); mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, 0, 0, viewportWidth, viewportHeight, Vector3()); deferImpl(displayList); } void OpReorderer::onViewportInitialized() {} void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {} /** * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods. * Loading @@ -350,11 +355,6 @@ void OpReorderer::deferImpl(const DisplayList& displayList) { void OpReorderer::replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers) { ATRACE_NAME("flush drawing commands"); // Relay through layers in reverse order, since layers // later in the list will be drawn by earlier ones for (int i = mLayerReorderers.size() - 1; i >= 0; i--) { mLayerReorderers[i].replayBakedOpsImpl(arg, receivers); } } void OpReorderer::onRenderNodeOp(const RenderNodeOp& op) { Loading Loading @@ -405,15 +405,17 @@ void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) { // TODO: test rejection at defer time, where the bounds become empty void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) { const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth(); const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight(); mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag); mCanvasState.writableSnapshot()->transform->loadIdentity(); mCanvasState.writableSnapshot()->initializeViewport( (int) op.unmappedBounds.getWidth(), (int) op.unmappedBounds.getHeight()); mCanvasState.writableSnapshot()->initializeViewport(layerWidth, layerHeight); mCanvasState.writableSnapshot()->roundRectClipState = nullptr; // create a new layer, and push its index on the stack mLayerStack.push_back(mLayerReorderers.size()); mLayerReorderers.emplace_back(); mLayerReorderers.emplace_back(layerWidth, layerHeight); mLayerReorderers.back().beginLayerOp = &op; } Loading @@ -432,7 +434,8 @@ void OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) { beginLayerOp.unmappedBounds, beginLayerOp.localMatrix, beginLayerOp.localClipRect, beginLayerOp.paint); beginLayerOp.paint, &mLayerReorderers[finishedLayerIndex].layer); BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp); if (bakedOpState) { Loading