diff options
author | 2016-02-25 16:54:08 -0800 | |
---|---|---|
committer | 2016-02-25 16:59:19 -0800 | |
commit | 4876de16e34622634266d09522c9153c78c7c2fb (patch) | |
tree | 08a054ece3cb68203113b899a60bd891ab299b07 /libs/hwui/FrameBuilder.cpp | |
parent | 1b7db4000eabb570697f4c5097588acbfa4df62b (diff) |
Properly reject empty unclipped savelayers
bug:27225580
bug:27281241
Empty unclipped savelayers (clipped at defer time, often by dirty rect)
were resulting in invalid layer clear rectangles. Simplify by just
rejecting these unclipped savelayers entirely at defer.
Also, use repaint rect as base clip for constructed ops within
LayerBuilder.
Change-Id: I5c466199e85201a2f68f5cdc60b29187c849961b
Diffstat (limited to 'libs/hwui/FrameBuilder.cpp')
-rw-r--r-- | libs/hwui/FrameBuilder.cpp | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index 4f51036b336e..04de98afe85c 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -782,39 +782,46 @@ void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) { boundsTransform.mapRect(dstRect); dstRect.doIntersect(mCanvasState.currentSnapshot()->getRenderTargetClip()); - // Allocate a holding position for the layer object (copyTo will produce, copyFrom will consume) - OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>(nullptr); - - /** - * First, defer an operation to copy out the content from the rendertarget into a layer. - */ - auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle); - BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator, - &(currentLayer().viewportClip), dstRect, *copyToOp); - currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer); - - /** - * Defer a clear rect, so that clears from multiple unclipped layers can be drawn - * both 1) simultaneously, and 2) as long after the copyToLayer executes as possible - */ - currentLayer().deferLayerClear(dstRect); - - /** - * And stash an operation to copy that layer back under the rendertarget until - * a balanced EndUnclippedLayerOp is seen - */ - auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle); - bakedState = BakedOpState::directConstruct(mAllocator, - &(currentLayer().viewportClip), dstRect, *copyFromOp); - currentLayer().activeUnclippedSaveLayers.push_back(bakedState); + if (dstRect.isEmpty()) { + // Unclipped layer rejected - push a null op, so next EndUnclippedLayerOp is ignored + currentLayer().activeUnclippedSaveLayers.push_back(nullptr); + } else { + // Allocate a holding position for the layer object (copyTo will produce, copyFrom will consume) + OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>(nullptr); + + /** + * First, defer an operation to copy out the content from the rendertarget into a layer. + */ + auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle); + BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator, + &(currentLayer().repaintClip), dstRect, *copyToOp); + currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer); + + /** + * Defer a clear rect, so that clears from multiple unclipped layers can be drawn + * both 1) simultaneously, and 2) as long after the copyToLayer executes as possible + */ + currentLayer().deferLayerClear(dstRect); + + /** + * And stash an operation to copy that layer back under the rendertarget until + * a balanced EndUnclippedLayerOp is seen + */ + auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle); + bakedState = BakedOpState::directConstruct(mAllocator, + &(currentLayer().repaintClip), dstRect, *copyFromOp); + currentLayer().activeUnclippedSaveLayers.push_back(bakedState); + } } void FrameBuilder::deferEndUnclippedLayerOp(const EndUnclippedLayerOp& /* ignored */) { LOG_ALWAYS_FATAL_IF(currentLayer().activeUnclippedSaveLayers.empty(), "no layer to end!"); BakedOpState* copyFromLayerOp = currentLayer().activeUnclippedSaveLayers.back(); - currentLayer().deferUnmergeableOp(mAllocator, copyFromLayerOp, OpBatchType::CopyFromLayer); currentLayer().activeUnclippedSaveLayers.pop_back(); + if (copyFromLayerOp) { + currentLayer().deferUnmergeableOp(mAllocator, copyFromLayerOp, OpBatchType::CopyFromLayer); + } } } // namespace uirenderer |