Skip to content

Commit 586cae3

Browse files
author
Romain Guy
committed
Improve rendering speed by disabling scissor tests
This change improves execution of display lists, particularly on tiled renderers. The goal is to disable the scissor test as often as possible. Drawing commands are rarely clipped by View bounds so most of them can be drawn without doing a scissor test. The speed improvements scale with the number of views and drawing commands. Change-Id: Ibd9b5e051a3e4300562463805acc4fd744ba6266
1 parent 9c0b188 commit 586cae3

File tree

5 files changed

+45
-14
lines changed

5 files changed

+45
-14
lines changed

libs/hwui/Caches.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ void Caches::init() {
7474

7575
mTexCoordsArrayEnabled = false;
7676

77+
scissorEnabled = false;
7778
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
7879

7980
glActiveTexture(gTextureUnits[0]);
@@ -352,7 +353,9 @@ void Caches::activeTexture(GLuint textureUnit) {
352353
}
353354

354355
void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
355-
if (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight) {
356+
if (scissorEnabled && (x != mScissorX || y != mScissorY ||
357+
width != mScissorWidth || height != mScissorHeight)) {
358+
356359
glScissor(x, y, width, height);
357360

358361
mScissorX = x;
@@ -362,6 +365,28 @@ void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
362365
}
363366
}
364367

368+
void Caches::enableScissor() {
369+
if (!scissorEnabled) {
370+
glEnable(GL_SCISSOR_TEST);
371+
scissorEnabled = true;
372+
}
373+
}
374+
375+
void Caches::disableScissor() {
376+
if (scissorEnabled) {
377+
glDisable(GL_SCISSOR_TEST);
378+
scissorEnabled = false;
379+
}
380+
}
381+
382+
void Caches::setScissorEnabled(bool enabled) {
383+
if (scissorEnabled != enabled) {
384+
if (enabled) glEnable(GL_SCISSOR_TEST);
385+
else glDisable(GL_SCISSOR_TEST);
386+
scissorEnabled = enabled;
387+
}
388+
}
389+
365390
void Caches::resetScissor() {
366391
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
367392
}

libs/hwui/Caches.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ class ANDROID_API Caches: public Singleton<Caches> {
204204
*/
205205
void resetScissor();
206206

207+
void enableScissor();
208+
void disableScissor();
209+
void setScissorEnabled(bool enabled);
210+
207211
/**
208212
* Returns the mesh used to draw regions. Calling this method will
209213
* bind a VBO of type GL_ELEMENT_ARRAY_BUFFER that contains the
@@ -221,6 +225,7 @@ class ANDROID_API Caches: public Singleton<Caches> {
221225
GLenum lastSrcMode;
222226
GLenum lastDstMode;
223227
Program* currentProgram;
228+
bool scissorEnabled;
224229

225230
// VBO to draw with
226231
GLuint meshBuffer;

libs/hwui/LayerRenderer.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,8 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
233233
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
234234
layer->getTexture(), 0);
235235

236-
glDisable(GL_SCISSOR_TEST);
236+
caches.disableScissor();
237237
glClear(GL_COLOR_BUFFER_BIT);
238-
glEnable(GL_SCISSOR_TEST);
239238

240239
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
241240

@@ -431,7 +430,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
431430
renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
432431
bitmap->width(), bitmap->height(), !layer->isBlend());
433432

434-
glDisable(GL_SCISSOR_TEST);
433+
caches.disableScissor();
435434
renderer.translate(0.0f, bitmap->height());
436435
renderer.scale(1.0f, -1.0f);
437436

@@ -460,8 +459,6 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
460459
}
461460

462461
error:
463-
glEnable(GL_SCISSOR_TEST);
464-
465462
#if DEBUG_OPENGL
466463
if (error != GL_NO_ERROR) {
467464
ALOGD("GL error while copying layer into bitmap = 0x%x", error);

libs/hwui/OpenGLRenderer.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ void OpenGLRenderer::setViewport(int width, int height) {
157157
mFirstSnapshot->viewport.set(0, 0, width, height);
158158

159159
glDisable(GL_DITHER);
160-
glEnable(GL_SCISSOR_TEST);
161160
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
162161

163162
glEnableVertexAttribArray(Program::kBindingPosition);
@@ -181,6 +180,7 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
181180
syncState();
182181

183182
if (!opaque) {
183+
mCaches.enableScissor();
184184
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
185185
glClear(GL_COLOR_BUFFER_BIT);
186186
return DrawGlInfo::kStatusDrew;
@@ -250,7 +250,7 @@ void OpenGLRenderer::resume() {
250250
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
251251
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
252252

253-
glEnable(GL_SCISSOR_TEST);
253+
mCaches.enableScissor();
254254
mCaches.resetScissor();
255255
dirtyClip();
256256

@@ -651,6 +651,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna
651651
#endif
652652

653653
// Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
654+
mCaches.enableScissor();
654655
mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
655656
clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
656657
glClear(GL_COLOR_BUFFER_BIT);
@@ -981,7 +982,7 @@ void OpenGLRenderer::clearLayerRegions() {
981982
// The list contains bounds that have already been clipped
982983
// against their initial clip rect, and the current clip
983984
// is likely different so we need to disable clipping here
984-
glDisable(GL_SCISSOR_TEST);
985+
mCaches.disableScissor();
985986

986987
Vertex mesh[count * 6];
987988
Vertex* vertex = mesh;
@@ -1008,8 +1009,6 @@ void OpenGLRenderer::clearLayerRegions() {
10081009
setupDrawVertices(&mesh[0].position[0]);
10091010

10101011
glDrawArrays(GL_TRIANGLES, 0, count * 6);
1011-
1012-
glEnable(GL_SCISSOR_TEST);
10131012
} else {
10141013
for (uint32_t i = 0; i < count; i++) {
10151014
delete mLayers.itemAt(i);
@@ -1088,7 +1087,12 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto
10881087
Rect clipRect(*mSnapshot->clipRect);
10891088
clipRect.snapToPixelBoundaries();
10901089

1091-
return !clipRect.intersects(r);
1090+
bool rejected = !clipRect.intersects(r);
1091+
if (!isDeferred() && !rejected) {
1092+
mCaches.setScissorEnabled(!clipRect.contains(r));
1093+
}
1094+
1095+
return rejected;
10921096
}
10931097

10941098
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {

libs/hwui/Rect.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,11 @@ class Rect {
125125
return intersect(r.left, r.top, r.right, r.bottom);
126126
}
127127

128-
bool contains(float l, float t, float r, float b) {
128+
inline bool contains(float l, float t, float r, float b) {
129129
return l >= left && t >= top && r <= right && b <= bottom;
130130
}
131131

132-
bool contains(const Rect& r) {
132+
inline bool contains(const Rect& r) {
133133
return contains(r.left, r.top, r.right, r.bottom);
134134
}
135135

0 commit comments

Comments
 (0)