summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2013-03-19 15:03:48 -0700
committerChris Craik <ccraik@google.com>2013-03-20 16:32:53 -0700
commitd90144db52c7297879b950cbbc85137ed123ab5b (patch)
tree7c2bc1e65081419297a59f1b3fdfc2e4ca1a1c55 /libs
parentafd10322f598abfda973ad78117dd297e09de212 (diff)
downloadframeworks_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.cpp6
-rw-r--r--libs/hwui/DeferredDisplayList.h9
-rw-r--r--libs/hwui/DisplayList.cpp2
-rw-r--r--libs/hwui/DisplayListOp.h7
-rw-r--r--libs/hwui/OpenGLRenderer.cpp103
-rw-r--r--libs/hwui/OpenGLRenderer.h12
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