diff options
author | Romain Guy <romainguy@google.com> | 2012-09-18 15:40:58 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2012-09-18 15:41:16 -0700 |
commit | 35643ddc689913f5b5f80ceed864470d987bd6cd (patch) | |
tree | db2ac0933bc52d1c71aa7d0edfd94c06dcc2cf2a /libs/hwui | |
parent | 29d0aa73a099fde05c506857b5d215cde87b78d6 (diff) | |
download | frameworks_base-35643ddc689913f5b5f80ceed864470d987bd6cd.zip frameworks_base-35643ddc689913f5b5f80ceed864470d987bd6cd.tar.gz frameworks_base-35643ddc689913f5b5f80ceed864470d987bd6cd.tar.bz2 |
Minimize state changes when updating layers
Change-Id: I407fcc80bd3178f9f09a3b379ceb7f7ce0749e08
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/Caches.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.h | 1 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 18 |
5 files changed, 75 insertions, 11 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 1de0f9d..edb4c10 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -378,6 +378,9 @@ bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) { if (scissorEnabled && (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight)) { + if (x < 0) x = 0; + if (y < 0) y = 0; + glScissor(x, y, width, height); mScissorX = x; diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index b57d806..5d59a4c 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -37,6 +37,10 @@ LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) { LayerRenderer::~LayerRenderer() { } +void LayerRenderer::setViewport(int width, int height) { + initViewport(width, height); +} + int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo()); diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index 531aa5b..8d42f7f 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -47,6 +47,7 @@ public: ANDROID_API LayerRenderer(Layer* layer); virtual ~LayerRenderer(); + virtual void setViewport(int width, int height); virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 4aefcba..11eb7a1 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -144,6 +144,15 @@ bool OpenGLRenderer::isDeferred() { } void OpenGLRenderer::setViewport(int width, int height) { + initViewport(width, height); + + glDisable(GL_DITHER); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glEnableVertexAttribArray(Program::kBindingPosition); +} + +void OpenGLRenderer::initViewport(int width, int height) { mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); mWidth = width; @@ -151,11 +160,6 @@ void OpenGLRenderer::setViewport(int width, int height) { mFirstSnapshot->height = height; mFirstSnapshot->viewport.set(0, 0, width, height); - - glDisable(GL_DITHER); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - glEnableVertexAttribArray(Program::kBindingPosition); } int OpenGLRenderer::prepare(bool opaque) { @@ -251,8 +255,9 @@ void OpenGLRenderer::interrupt() { void OpenGLRenderer::resume() { sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot; - glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); + glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST); @@ -261,7 +266,6 @@ void OpenGLRenderer::resume() { dirtyClip(); mCaches.activeTexture(0); - glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); mCaches.blend = true; glEnable(GL_BLEND); @@ -269,6 +273,15 @@ void OpenGLRenderer::resume() { glBlendEquation(GL_FUNC_ADD); } +void OpenGLRenderer::resumeAfterLayer() { + sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot; + glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); + glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); + + mCaches.resetScissor(); + dirtyClip(); +} + void OpenGLRenderer::detachFunctor(Functor* functor) { mFunctors.remove(functor); } @@ -1081,6 +1094,22 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl return !clipRect.intersects(r); } +bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom, + Rect& transformed, Rect& clip) { + if (mSnapshot->isIgnored()) { + return true; + } + + transformed.set(left, top, right, bottom); + mSnapshot->transform->mapRect(transformed); + transformed.snapToPixelBoundaries(); + + clip.set(*mSnapshot->clipRect); + clip.snapToPixelBoundaries(); + + return !clip.intersects(transformed); +} + bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { if (mSnapshot->isIgnored()) { return true; @@ -2574,22 +2603,30 @@ status_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { } status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { - if (!layer || quickReject(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight())) { + if (!layer) { return DrawGlInfo::kStatusDone; } - bool debugLayerUpdate = false; + Rect transformed; + Rect clip; + const bool rejected = quickRejectNoScissor(x, y, + x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip); + if (rejected) { + return DrawGlInfo::kStatusDone; + } + + bool debugLayerUpdate = false; if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) { OpenGLRenderer* renderer = layer->renderer; Rect& dirty = layer->dirtyRect; - interrupt(); renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight()); renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend()); renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren); renderer->finish(); - resume(); + + resumeAfterLayer(); dirty.setEmpty(); layer->deferredUpdateScheduled = false; @@ -2599,6 +2636,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain debugLayerUpdate = mCaches.debugLayersUpdates; } + mCaches.setScissorEnabled(!clip.contains(transformed)); mCaches.activeTexture(0); if (CC_LIKELY(!layer->region.isEmpty())) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 7f9405f..8dcd33f 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -255,6 +255,17 @@ public: protected: /** + * Computes the projection matrix, initialize the first snapshot + * and stores the dimensions of the render target. + */ + void initViewport(int width, int height); + + /** + * Call this method after updating a layer during a drawing pass. + */ + void resumeAfterLayer(); + + /** * Compose the layer defined in the current snapshot with the layer * defined by the previous snapshot. * @@ -360,6 +371,13 @@ private: void setScissorFromClip(); /** + * Performs a quick reject but does not affect the scissor. Returns + * the transformed rect to test and the current clip. + */ + bool quickRejectNoScissor(float left, float top, float right, float bottom, + Rect& transformed, Rect& clip); + + /** * Creates a new layer stored in the specified snapshot. * * @param snapshot The snapshot associated with the new layer |