diff options
author | Chris Craik <ccraik@google.com> | 2013-03-19 15:03:48 -0700 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2013-03-20 16:32:53 -0700 |
commit | d90144db52c7297879b950cbbc85137ed123ab5b (patch) | |
tree | 7c2bc1e65081419297a59f1b3fdfc2e4ca1a1c55 /libs | |
parent | afd10322f598abfda973ad78117dd297e09de212 (diff) | |
download | frameworks_base-d90144db52c7297879b950cbbc85137ed123ab5b.zip frameworks_base-d90144db52c7297879b950cbbc85137ed123ab5b.tar.gz frameworks_base-d90144db52c7297879b950cbbc85137ed123ab5b.tar.bz2 |
Update snapshot upon saveLayer deferral
bug:8409891
In order to defer fbo-targetting saveLayer operations, it's necessary
to update the snapshot at defer time so that deferred display state
(namely, clip and transform) are fbo relative.
Re-enables deferring, as the issues with saveLayer are fixed.
Change-Id: I74b0779bc732675c747208f0757c3ea85f6dfbed
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/DeferredDisplayList.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/DeferredDisplayList.h | 9 | ||||
-rw-r--r-- | libs/hwui/DisplayList.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 7 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 103 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 12 |
6 files changed, 90 insertions, 49 deletions
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index 1ace42f..7907224 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -78,7 +78,7 @@ public: renderer.restoreDisplayState(op->state, kStateDeferFlag_Draw); #if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS - renderer.eventMark(strlen(op->name()), op->name()); + renderer.eventMark(op->name()); #endif status |= op->applyDraw(renderer, dirty, 0); logBuffer.writeCommand(0, op->name()); @@ -134,7 +134,6 @@ public: virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) { DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount); renderer.restoreToCount(mRestoreCount); - return DrawGlInfo::kStatusDone; } @@ -373,9 +372,10 @@ status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) { DEFER_LOGD("--flushing"); renderer.eventMark("Flush"); + DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers(); renderer.restoreToCount(1); status |= replayBatchList(mBatches, renderer, dirty); - renderer.resetDrawModifiers(); + renderer.setDrawModifiers(restoreDrawModifiers); DEFER_LOGD("--flush complete, returning %x", status); diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h index 8e908fa..cb9da8f 100644 --- a/libs/hwui/DeferredDisplayList.h +++ b/libs/hwui/DeferredDisplayList.h @@ -72,7 +72,7 @@ public: void addDrawOp(OpenGLRenderer& renderer, DrawOp* op); private: - /* + /** * Resets the batching back-pointers, creating a barrier in the operation stream so that no ops * added in the future will be inserted into a batch that already exist. */ @@ -88,9 +88,10 @@ private: int getStateOpDeferFlags() const; int getDrawOpDeferFlags() const; - /* - * - * at defer time, stores the savecount of save/saveLayer ops that were + /** + * At defer time, stores the *defer time* savecount of save/saveLayer ops that were deferred, so + * that when an associated restoreToCount is deferred, it can be recorded as a + * RestoreToCountBatch */ Vector<int> mSaveStack; int mComplexClipStackStart; diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 257c875..55ddd17 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -443,7 +443,7 @@ public: : mReplayStruct(replayStruct), mLevel(level) {} inline void operator()(DisplayListOp* operation, int saveCount) { #if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS - replayStruct.mRenderer.eventMark(operation->name()); + mReplayStruct.mRenderer.eventMark(operation->name()); #endif operation->replay(mReplayStruct, saveCount, mLevel); } diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 4561c61..4f2db69 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -284,8 +284,13 @@ public: virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) { // NOTE: don't bother with actual saveLayer, instead issuing it at flush time - int newSaveCount = deferStruct.mRenderer.save(mFlags); + int newSaveCount = deferStruct.mRenderer.getSaveCount(); deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount); + + // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just + // setup the snapshot for deferral, and re-issue the op at flush time + deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom, + mAlpha, mMode, mFlags); } virtual void applyState(OpenGLRenderer& renderer, int saveCount) { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8030d66..0a299d3 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -112,7 +112,10 @@ static const Blender gBlendsSwap[] = { OpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) { - resetDrawModifiers(); + mDrawModifiers.mShader = NULL; + mDrawModifiers.mColorFilter = NULL; + mDrawModifiers.mHasShadow = false; + mDrawModifiers.mHasDrawFilter = false; memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); @@ -643,6 +646,63 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, return count; } +void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) { + const Rect untransformedBounds(bounds); + + currentTransform().mapRect(bounds); + + // Layers only make sense if they are in the framebuffer's bounds + if (bounds.intersect(*mSnapshot->clipRect)) { + // We cannot work with sub-pixels in this case + bounds.snapToPixelBoundaries(); + + // When the layer is not an FBO, we may use glCopyTexImage so we + // need to make sure the layer does not extend outside the bounds + // of the framebuffer + if (!bounds.intersect(mSnapshot->previous->viewport)) { + bounds.setEmpty(); + } else if (fboLayer) { + clip.set(bounds); + mat4 inverse; + inverse.loadInverse(currentTransform()); + inverse.mapRect(clip); + clip.snapToPixelBoundaries(); + if (clip.intersect(untransformedBounds)) { + clip.translate(-untransformedBounds.left, -untransformedBounds.top); + bounds.set(untransformedBounds); + } else { + clip.setEmpty(); + } + } + } else { + bounds.setEmpty(); + } +} + +int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom, + int alpha, SkXfermode::Mode mode, int flags) { + const GLuint previousFbo = mSnapshot->fbo; + const int count = saveSnapshot(flags); + + if (!mSnapshot->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) { + // initialize the snapshot as though it almost represents an FBO layer so deferred draw + // operations will be able to store and restore the current clip and transform info, and + // quick rejection will be correct (for display lists) + + Rect bounds(left, top, right, bottom); + Rect clip; + calculateLayerBoundsAndClip(bounds, clip, true); + + if (!bounds.isEmpty() && !clip.isEmpty()) { + mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); + mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); + } + } + + return count; +} + + /** * Layers are viewed by Skia are slightly different than layers in image editing * programs (for instance.) When a layer is created, previously created layers @@ -704,35 +764,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto // Window coordinates of the layer Rect clip; Rect bounds(left, top, right, bottom); - Rect untransformedBounds(bounds); - currentTransform().mapRect(bounds); - - // Layers only make sense if they are in the framebuffer's bounds - if (bounds.intersect(*mSnapshot->clipRect)) { - // We cannot work with sub-pixels in this case - bounds.snapToPixelBoundaries(); - - // When the layer is not an FBO, we may use glCopyTexImage so we - // need to make sure the layer does not extend outside the bounds - // of the framebuffer - if (!bounds.intersect(mSnapshot->previous->viewport)) { - bounds.setEmpty(); - } else if (fboLayer) { - clip.set(bounds); - mat4 inverse; - inverse.loadInverse(currentTransform()); - inverse.mapRect(clip); - clip.snapToPixelBoundaries(); - if (clip.intersect(untransformedBounds)) { - clip.translate(-left, -top); - bounds.set(untransformedBounds); - } else { - clip.setEmpty(); - } - } - } else { - bounds.setEmpty(); - } + calculateLayerBoundsAndClip(bounds, clip, fboLayer); if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize || bounds.getHeight() > mCaches.maxTextureSize || @@ -1201,13 +1233,6 @@ void OpenGLRenderer::clearLayerRegions() { // State Deferral /////////////////////////////////////////////////////////////////////////////// -void OpenGLRenderer::resetDrawModifiers() { - mDrawModifiers.mShader = NULL; - mDrawModifiers.mColorFilter = NULL; - mDrawModifiers.mHasShadow = false; - mDrawModifiers.mHasDrawFilter = false; -} - bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) { const Rect& currentClip = *(mSnapshot->clipRect); const mat4& currentMatrix = *(mSnapshot->transform); @@ -1246,7 +1271,7 @@ void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, int mSnapshot->alpha = state.mAlpha; } - if (!state.mClip.isEmpty()) { //stateDeferFlags & kStateDeferFlag_Clip) { + if (!state.mClip.isEmpty()) { mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom); dirtyClip(); } @@ -1805,7 +1830,7 @@ status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, // All the usual checks and setup operations (quickReject, setupDraw, etc.) // will be performed by the display list itself if (displayList && displayList->isRenderable()) { - if (true || CC_UNLIKELY(mCaches.drawDeferDisabled)) { // NOTE: temporary workaround + if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { ReplayStateStruct replayStruct(*this, dirty, replayFlags); displayList->replay(replayStruct, 0); return replayStruct.mDrawGlStatus; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index fc7c597..01fcfc6 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -205,6 +205,9 @@ public: virtual int saveLayer(float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode, int flags); + int saveLayerDeferred(float left, float top, float right, float bottom, + int alpha, SkXfermode::Mode mode, int flags); + virtual void translate(float dx, float dy); virtual void rotate(float degrees); virtual void scale(float sx, float sy); @@ -273,10 +276,12 @@ public: SkPaint* filterPaint(SkPaint* paint); - void resetDrawModifiers(); bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags); void restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags); + const DrawModifiers& getDrawModifiers() { return mDrawModifiers; } + void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; } + // TODO: what does this mean? no perspective? no rotate? ANDROID_API bool isCurrentTransformSimple() { return mSnapshot->transform->isSimple(); @@ -538,6 +543,11 @@ private: bool quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint); /** + * given the local bounds of the layer, calculates ... + */ + void calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer); + + /** * Creates a new layer stored in the specified snapshot. * * @param snapshot The snapshot associated with the new layer |