Skip to content

Commit 7c25aab

Browse files
author
Romain Guy
committed
Defer layer rendering to avoid stalls
Bug #7326824 When a layer is taken out of the cache and initialized it gets cleared to prepare it for future rendering. This triggers the following sequence of operations: glBindFramebuffer(layer.fbo) attach texture storage to FBO glClear() glBindFramebuffer(defaultFbo) The clear forces a resolve on tilers which stalls the CPU for a little while, thus producing jank during animations. This change moves the clear to the next frame when we know we will have to execute a resolve anyway. Change-Id: Ic1939c25df20ed65a4c48dc81ee549b2cd8b6ec3
1 parent b2e2f24 commit 7c25aab

File tree

9 files changed

+64
-14
lines changed

9 files changed

+64
-14
lines changed

core/java/android/view/HardwareRenderer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1200,7 +1200,12 @@ boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callba
12001200
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
12011201
}
12021202

1203-
status = onPreDraw(dirty);
1203+
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
1204+
try {
1205+
status = onPreDraw(dirty);
1206+
} finally {
1207+
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
1208+
}
12041209
saveCount = canvas.save();
12051210
callbacks.onHardwarePreDraw(canvas);
12061211

libs/hwui/DisplayListRenderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,7 @@ void DisplayListRenderer::setViewport(int width, int height) {
14341434
mHeight = height;
14351435
}
14361436

1437-
int DisplayListRenderer::prepareDirty(float left, float top,
1437+
status_t DisplayListRenderer::prepareDirty(float left, float top,
14381438
float right, float bottom, bool opaque) {
14391439
mSnapshot = new Snapshot(mFirstSnapshot,
14401440
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);

libs/hwui/DisplayListRenderer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ class DisplayListRenderer: public OpenGLRenderer {
550550
virtual bool isDeferred();
551551

552552
virtual void setViewport(int width, int height);
553-
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
553+
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
554554
virtual void finish();
555555

556556
virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);

libs/hwui/Layer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
3131
meshIndices = NULL;
3232
meshElementCount = 0;
3333
cacheable = true;
34+
dirty = false;
3435
textureLayer = false;
3536
renderTarget = GL_TEXTURE_2D;
3637
texture.width = layerWidth;

libs/hwui/Layer.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ struct Layer {
162162
this->cacheable = cacheable;
163163
}
164164

165+
inline bool isDirty() {
166+
return dirty;
167+
}
168+
169+
inline void setDirty(bool dirty) {
170+
this->dirty = dirty;
171+
}
172+
165173
inline bool isTextureLayer() {
166174
return textureLayer;
167175
}
@@ -286,6 +294,12 @@ struct Layer {
286294
*/
287295
bool textureLayer;
288296

297+
/**
298+
* When set to true, this layer is dirty and should be cleared
299+
* before any rendering occurs.
300+
*/
301+
bool dirty;
302+
289303
/**
290304
* Indicates the render target.
291305
*/

libs/hwui/LayerRenderer.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#include <ui/Rect.h>
2020

21+
#include <private/hwui/DrawGlInfo.h>
22+
2123
#include "LayerCache.h"
2224
#include "LayerRenderer.h"
2325
#include "Matrix.h"
@@ -41,7 +43,8 @@ void LayerRenderer::setViewport(int width, int height) {
4143
initViewport(width, height);
4244
}
4345

44-
int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
46+
status_t LayerRenderer::prepareDirty(float left, float top, float right, float bottom,
47+
bool opaque) {
4548
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
4649

4750
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
@@ -63,6 +66,20 @@ int LayerRenderer::prepareDirty(float left, float top, float right, float bottom
6366
return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
6467
}
6568

69+
status_t LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
70+
if (mLayer->isDirty()) {
71+
getCaches().disableScissor();
72+
glClear(GL_COLOR_BUFFER_BIT);
73+
74+
getCaches().resetScissor();
75+
mLayer->setDirty(false);
76+
77+
return DrawGlInfo::kStatusDone;
78+
}
79+
80+
return OpenGLRenderer::clear(left, top, right, bottom, opaque);
81+
}
82+
6683
void LayerRenderer::finish() {
6784
OpenGLRenderer::finish();
6885

@@ -201,6 +218,7 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
201218
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
202219
layer->setBlend(!isOpaque);
203220
layer->setColorFilter(NULL);
221+
layer->setDirty(true);
204222
layer->region.clear();
205223

206224
GLuint previousFbo;
@@ -229,9 +247,6 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
229247
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
230248
layer->getTexture(), 0);
231249

232-
caches.disableScissor();
233-
glClear(GL_COLOR_BUFFER_BIT);
234-
235250
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
236251

237252
return layer;

libs/hwui/LayerRenderer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class LayerRenderer: public OpenGLRenderer {
4848
virtual ~LayerRenderer();
4949

5050
virtual void setViewport(int width, int height);
51-
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
51+
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
52+
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
5253
virtual void finish();
5354

5455
ANDROID_API static Layer* createTextureLayer(bool isOpaque);

libs/hwui/OpenGLRenderer.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,12 @@ void OpenGLRenderer::initViewport(int width, int height) {
165165
mFirstSnapshot->viewport.set(0, 0, width, height);
166166
}
167167

168-
int OpenGLRenderer::prepare(bool opaque) {
168+
status_t OpenGLRenderer::prepare(bool opaque) {
169169
return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
170170
}
171171

172-
int OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
172+
status_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
173+
bool opaque) {
173174
mCaches.clearGarbage();
174175

175176
mSnapshot = new Snapshot(mFirstSnapshot,
@@ -203,15 +204,18 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
203204

204205
debugOverdraw(true, true);
205206

207+
return clear(left, top, right, bottom, opaque);
208+
}
209+
210+
status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
206211
if (!opaque) {
207212
mCaches.enableScissor();
208213
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
209214
glClear(GL_COLOR_BUFFER_BIT);
210215
return DrawGlInfo::kStatusDrew;
211-
} else {
212-
mCaches.resetScissor();
213216
}
214217

218+
mCaches.resetScissor();
215219
return DrawGlInfo::kStatusDone;
216220
}
217221

@@ -743,6 +747,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
743747
bounds.getWidth() / float(layer->getWidth()), 0.0f);
744748
layer->setColorFilter(mColorFilter);
745749
layer->setBlend(true);
750+
layer->setDirty(false);
746751

747752
// Save the layer in the snapshot
748753
mSnapshot->flags |= Snapshot::kFlagIsLayer;

libs/hwui/OpenGLRenderer.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class OpenGLRenderer {
9494
* and will not be cleared. If false, the target surface
9595
* will be cleared
9696
*/
97-
ANDROID_API int prepare(bool opaque);
97+
ANDROID_API status_t prepare(bool opaque);
9898

9999
/**
100100
* Prepares the renderer to draw a frame. This method must be invoked
@@ -110,7 +110,7 @@ class OpenGLRenderer {
110110
* and will not be cleared. If false, the target surface
111111
* will be cleared in the specified dirty rectangle
112112
*/
113-
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
113+
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
114114

115115
/**
116116
* Indicates the end of a frame. This method must be invoked whenever
@@ -269,6 +269,11 @@ class OpenGLRenderer {
269269
*/
270270
void initViewport(int width, int height);
271271

272+
/**
273+
* Clears the underlying surface if needed.
274+
*/
275+
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
276+
272277
/**
273278
* Call this method after updating a layer during a drawing pass.
274279
*/
@@ -355,6 +360,10 @@ class OpenGLRenderer {
355360
return false;
356361
}
357362

363+
Caches& getCaches() {
364+
return mCaches;
365+
}
366+
358367
private:
359368
/**
360369
* Ensures the state of the renderer is the same as the state of

0 commit comments

Comments
 (0)