diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Canvas.h | 4 | ||||
-rw-r--r-- | libs/hwui/DisplayListCanvas.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 19 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 8 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 6 |
5 files changed, 34 insertions, 11 deletions
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h index aa24673..562bb80 100644 --- a/libs/hwui/Canvas.h +++ b/libs/hwui/Canvas.h @@ -47,6 +47,10 @@ public: * It is useful for testing and clients (e.g. Picture/Movie) that expect to * draw their contents into an SkCanvas. * + * The SkCanvas returned is *only* valid until another Canvas call is made + * that would change state (e.g. matrix or clip). Clients of asSkCanvas() + * are responsible for *not* persisting this pointer. + * * Further, the returned SkCanvas should NOT be unref'd and is valid until * this canvas is destroyed or a new bitmap is set. */ diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index 02a4877..b08187b 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -99,6 +99,14 @@ SkCanvas* DisplayListCanvas::asSkCanvas() { if (!mSkiaCanvasProxy) { mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this)); } + + // SkCanvas instances default to identity transform, but should inherit + // the state of this Canvas; if this code was in the SkiaCanvasProxy + // constructor, we couldn't cache mSkiaCanvasProxy. + SkMatrix parentTransform; + getMatrix(&parentTransform); + mSkiaCanvasProxy.get()->setMatrix(parentTransform); + return mSkiaCanvasProxy.get(); } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 433e178..3d48fa6 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1097,7 +1097,7 @@ void OpenGLRenderer::dirtyLayer(const float left, const float top, } void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { - if (bounds.intersect(mState.currentClipRect())) { + if (CC_LIKELY(!bounds.isEmpty() && bounds.intersect(mState.currentClipRect()))) { bounds.snapToPixelBoundaries(); android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom); if (!dirty.isEmpty()) { @@ -1146,7 +1146,7 @@ void OpenGLRenderer::clearLayerRegions() { .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect())) .build(); - renderGlop(glop, false); + renderGlop(glop, GlopRenderType::LayerClear); if (scissorChanged) mRenderState.scissor().setEnabled(true); } else { @@ -1454,10 +1454,15 @@ void OpenGLRenderer::debugClip() { #endif } -void OpenGLRenderer::renderGlop(const Glop& glop, bool clearLayer) { +void OpenGLRenderer::renderGlop(const Glop& glop, GlopRenderType type) { // TODO: It would be best if we could do this before quickRejectSetupScissor() // changes the scissor test state - if (clearLayer) clearLayerRegions(); + if (type != GlopRenderType::LayerClear) { + // Regular draws need to clear the dirty area on the layer before they start drawing on top + // of it. If this draw *is* a layer clear, it skips the clear step (since it would + // infinitely recurse) + clearLayerRegions(); + } if (mState.getDirtyClip()) { if (mRenderState.scissor().isEnabled()) { @@ -1467,7 +1472,7 @@ void OpenGLRenderer::renderGlop(const Glop& glop, bool clearLayer) { setStencilFromClip(); } mRenderState.render(glop); - if (!mRenderState.stencil().isWriteEnabled()) { + if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) { // TODO: specify more clearly when a draw should dirty the layer. // is writing to the stencil the only time we should ignore this? dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom); @@ -1540,7 +1545,7 @@ void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entr .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight())) .build(); - renderGlop(glop); + renderGlop(glop, GlopRenderType::Multi); } void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { @@ -1738,7 +1743,7 @@ void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entr .setTransform(*currentSnapshot(), transformFlags) .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0)) .build(); - renderGlop(glop); + renderGlop(glop, GlopRenderType::Multi); } void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 5850dc6..800a9f9 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -535,7 +535,13 @@ protected: RenderState& mRenderState; private: - void renderGlop(const Glop& glop, bool clearLayer = true); + enum class GlopRenderType { + Standard, + Multi, + LayerClear + }; + + void renderGlop(const Glop& glop, GlopRenderType type = GlopRenderType::Standard); /** * Discards the content of the framebuffer if supported by the driver. diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index a323065..6cf66cd 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -419,12 +419,12 @@ bool SkiaCanvas::quickRejectPath(const SkPath& path) const { bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); mCanvas->clipRect(rect, op); - return mCanvas->isClipEmpty(); + return !mCanvas->isClipEmpty(); } bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) { mCanvas->clipPath(*path, op); - return mCanvas->isClipEmpty(); + return !mCanvas->isClipEmpty(); } bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) { @@ -438,7 +438,7 @@ bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) { } else { mCanvas->clipRect(SkRect::MakeEmpty(), op); } - return mCanvas->isClipEmpty(); + return !mCanvas->isClipEmpty(); } // ---------------------------------------------------------------------------- |