Skip to content

Commit ceb5a98

Browse files
Romain GuyAndroid (Google) Code Review
authored andcommitted
Merge "Minimize state changes when updating layers" into jb-mr1-dev
2 parents 9ffc604 + 35643dd commit ceb5a98

File tree

5 files changed

+75
-11
lines changed

5 files changed

+75
-11
lines changed

libs/hwui/Caches.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
378378
if (scissorEnabled && (x != mScissorX || y != mScissorY ||
379379
width != mScissorWidth || height != mScissorHeight)) {
380380

381+
if (x < 0) x = 0;
382+
if (y < 0) y = 0;
383+
381384
glScissor(x, y, width, height);
382385

383386
mScissorX = x;

libs/hwui/LayerRenderer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) {
3737
LayerRenderer::~LayerRenderer() {
3838
}
3939

40+
void LayerRenderer::setViewport(int width, int height) {
41+
initViewport(width, height);
42+
}
43+
4044
int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
4145
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
4246

libs/hwui/LayerRenderer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class LayerRenderer: public OpenGLRenderer {
4747
ANDROID_API LayerRenderer(Layer* layer);
4848
virtual ~LayerRenderer();
4949

50+
virtual void setViewport(int width, int height);
5051
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
5152
virtual void finish();
5253

libs/hwui/OpenGLRenderer.cpp

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,22 @@ bool OpenGLRenderer::isDeferred() {
144144
}
145145

146146
void OpenGLRenderer::setViewport(int width, int height) {
147+
initViewport(width, height);
148+
149+
glDisable(GL_DITHER);
150+
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
151+
152+
glEnableVertexAttribArray(Program::kBindingPosition);
153+
}
154+
155+
void OpenGLRenderer::initViewport(int width, int height) {
147156
mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
148157

149158
mWidth = width;
150159
mHeight = height;
151160

152161
mFirstSnapshot->height = height;
153162
mFirstSnapshot->viewport.set(0, 0, width, height);
154-
155-
glDisable(GL_DITHER);
156-
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
157-
158-
glEnableVertexAttribArray(Program::kBindingPosition);
159163
}
160164

161165
int OpenGLRenderer::prepare(bool opaque) {
@@ -251,8 +255,9 @@ void OpenGLRenderer::interrupt() {
251255

252256
void OpenGLRenderer::resume() {
253257
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
254-
255258
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
259+
glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
260+
256261
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
257262

258263
mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
@@ -261,14 +266,22 @@ void OpenGLRenderer::resume() {
261266
dirtyClip();
262267

263268
mCaches.activeTexture(0);
264-
glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
265269

266270
mCaches.blend = true;
267271
glEnable(GL_BLEND);
268272
glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
269273
glBlendEquation(GL_FUNC_ADD);
270274
}
271275

276+
void OpenGLRenderer::resumeAfterLayer() {
277+
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
278+
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
279+
glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
280+
281+
mCaches.resetScissor();
282+
dirtyClip();
283+
}
284+
272285
void OpenGLRenderer::detachFunctor(Functor* functor) {
273286
mFunctors.remove(functor);
274287
}
@@ -1081,6 +1094,22 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl
10811094
return !clipRect.intersects(r);
10821095
}
10831096

1097+
bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom,
1098+
Rect& transformed, Rect& clip) {
1099+
if (mSnapshot->isIgnored()) {
1100+
return true;
1101+
}
1102+
1103+
transformed.set(left, top, right, bottom);
1104+
mSnapshot->transform->mapRect(transformed);
1105+
transformed.snapToPixelBoundaries();
1106+
1107+
clip.set(*mSnapshot->clipRect);
1108+
clip.snapToPixelBoundaries();
1109+
1110+
return !clip.intersects(transformed);
1111+
}
1112+
10841113
bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
10851114
if (mSnapshot->isIgnored()) {
10861115
return true;
@@ -2574,22 +2603,30 @@ status_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
25742603
}
25752604

25762605
status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
2577-
if (!layer || quickReject(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight())) {
2606+
if (!layer) {
25782607
return DrawGlInfo::kStatusDone;
25792608
}
25802609

2581-
bool debugLayerUpdate = false;
2610+
Rect transformed;
2611+
Rect clip;
2612+
const bool rejected = quickRejectNoScissor(x, y,
2613+
x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip);
25822614

2615+
if (rejected) {
2616+
return DrawGlInfo::kStatusDone;
2617+
}
2618+
2619+
bool debugLayerUpdate = false;
25832620
if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
25842621
OpenGLRenderer* renderer = layer->renderer;
25852622
Rect& dirty = layer->dirtyRect;
25862623

2587-
interrupt();
25882624
renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
25892625
renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
25902626
renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
25912627
renderer->finish();
2592-
resume();
2628+
2629+
resumeAfterLayer();
25932630

25942631
dirty.setEmpty();
25952632
layer->deferredUpdateScheduled = false;
@@ -2599,6 +2636,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
25992636
debugLayerUpdate = mCaches.debugLayersUpdates;
26002637
}
26012638

2639+
mCaches.setScissorEnabled(!clip.contains(transformed));
26022640
mCaches.activeTexture(0);
26032641

26042642
if (CC_LIKELY(!layer->region.isEmpty())) {

libs/hwui/OpenGLRenderer.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ class OpenGLRenderer {
254254
}
255255

256256
protected:
257+
/**
258+
* Computes the projection matrix, initialize the first snapshot
259+
* and stores the dimensions of the render target.
260+
*/
261+
void initViewport(int width, int height);
262+
263+
/**
264+
* Call this method after updating a layer during a drawing pass.
265+
*/
266+
void resumeAfterLayer();
267+
257268
/**
258269
* Compose the layer defined in the current snapshot with the layer
259270
* defined by the previous snapshot.
@@ -359,6 +370,13 @@ class OpenGLRenderer {
359370
*/
360371
void setScissorFromClip();
361372

373+
/**
374+
* Performs a quick reject but does not affect the scissor. Returns
375+
* the transformed rect to test and the current clip.
376+
*/
377+
bool quickRejectNoScissor(float left, float top, float right, float bottom,
378+
Rect& transformed, Rect& clip);
379+
362380
/**
363381
* Creates a new layer stored in the specified snapshot.
364382
*

0 commit comments

Comments
 (0)