summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Romain Guy <romainguy@google.com> 2012-07-13 15:28:31 -0700
committer Romain Guy <romainguy@google.com> 2012-07-13 15:28:31 -0700
commit586cae3ac69c0c667fbf8a954edbd399f620a717 (patch)
tree400d845a02c1ff3e36db59835072bf23efa789e7
parent9c0b188e4231bcb967234f3646c178d22d8a9f50 (diff)
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
-rw-r--r--libs/hwui/Caches.cpp27
-rw-r--r--libs/hwui/Caches.h5
-rw-r--r--libs/hwui/LayerRenderer.cpp7
-rw-r--r--libs/hwui/OpenGLRenderer.cpp16
-rw-r--r--libs/hwui/Rect.h4
5 files changed, 45 insertions, 14 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f2108203b9ba..214cc9255d0f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -74,6 +74,7 @@ void Caches::init() {
mTexCoordsArrayEnabled = false;
+ scissorEnabled = false;
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
glActiveTexture(gTextureUnits[0]);
@@ -352,7 +353,9 @@ void Caches::activeTexture(GLuint textureUnit) {
}
void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
- if (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight) {
+ if (scissorEnabled && (x != mScissorX || y != mScissorY ||
+ width != mScissorWidth || height != mScissorHeight)) {
+
glScissor(x, y, width, height);
mScissorX = x;
@@ -362,6 +365,28 @@ void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
}
}
+void Caches::enableScissor() {
+ if (!scissorEnabled) {
+ glEnable(GL_SCISSOR_TEST);
+ scissorEnabled = true;
+ }
+}
+
+void Caches::disableScissor() {
+ if (scissorEnabled) {
+ glDisable(GL_SCISSOR_TEST);
+ scissorEnabled = false;
+ }
+}
+
+void Caches::setScissorEnabled(bool enabled) {
+ if (scissorEnabled != enabled) {
+ if (enabled) glEnable(GL_SCISSOR_TEST);
+ else glDisable(GL_SCISSOR_TEST);
+ scissorEnabled = enabled;
+ }
+}
+
void Caches::resetScissor() {
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 58361c9568f1..f83e291d4f58 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -204,6 +204,10 @@ public:
*/
void resetScissor();
+ void enableScissor();
+ void disableScissor();
+ void setScissorEnabled(bool enabled);
+
/**
* Returns the mesh used to draw regions. Calling this method will
* bind a VBO of type GL_ELEMENT_ARRAY_BUFFER that contains the
@@ -221,6 +225,7 @@ public:
GLenum lastSrcMode;
GLenum lastDstMode;
Program* currentProgram;
+ bool scissorEnabled;
// VBO to draw with
GLuint meshBuffer;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 65f8c7c8b67c..41a5f0d4ba84 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -233,9 +233,8 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->getTexture(), 0);
- glDisable(GL_SCISSOR_TEST);
+ caches.disableScissor();
glClear(GL_COLOR_BUFFER_BIT);
- glEnable(GL_SCISSOR_TEST);
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
@@ -431,7 +430,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
bitmap->width(), bitmap->height(), !layer->isBlend());
- glDisable(GL_SCISSOR_TEST);
+ caches.disableScissor();
renderer.translate(0.0f, bitmap->height());
renderer.scale(1.0f, -1.0f);
@@ -460,8 +459,6 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
}
error:
- glEnable(GL_SCISSOR_TEST);
-
#if DEBUG_OPENGL
if (error != GL_NO_ERROR) {
ALOGD("GL error while copying layer into bitmap = 0x%x", error);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 933d01232271..cbf7b02dcddf 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -157,7 +157,6 @@ void OpenGLRenderer::setViewport(int width, int height) {
mFirstSnapshot->viewport.set(0, 0, width, height);
glDisable(GL_DITHER);
- glEnable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnableVertexAttribArray(Program::kBindingPosition);
@@ -181,6 +180,7 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
syncState();
if (!opaque) {
+ mCaches.enableScissor();
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
glClear(GL_COLOR_BUFFER_BIT);
return DrawGlInfo::kStatusDrew;
@@ -250,7 +250,7 @@ void OpenGLRenderer::resume() {
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glEnable(GL_SCISSOR_TEST);
+ mCaches.enableScissor();
mCaches.resetScissor();
dirtyClip();
@@ -651,6 +651,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna
#endif
// Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
+ mCaches.enableScissor();
mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -981,7 +982,7 @@ void OpenGLRenderer::clearLayerRegions() {
// The list contains bounds that have already been clipped
// against their initial clip rect, and the current clip
// is likely different so we need to disable clipping here
- glDisable(GL_SCISSOR_TEST);
+ mCaches.disableScissor();
Vertex mesh[count * 6];
Vertex* vertex = mesh;
@@ -1008,8 +1009,6 @@ void OpenGLRenderer::clearLayerRegions() {
setupDrawVertices(&mesh[0].position[0]);
glDrawArrays(GL_TRIANGLES, 0, count * 6);
-
- glEnable(GL_SCISSOR_TEST);
} else {
for (uint32_t i = 0; i < count; i++) {
delete mLayers.itemAt(i);
@@ -1088,7 +1087,12 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto
Rect clipRect(*mSnapshot->clipRect);
clipRect.snapToPixelBoundaries();
- return !clipRect.intersects(r);
+ bool rejected = !clipRect.intersects(r);
+ if (!isDeferred() && !rejected) {
+ mCaches.setScissorEnabled(!clipRect.contains(r));
+ }
+
+ return rejected;
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 2ca4f50bb176..80f39ff90d1e 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -125,11 +125,11 @@ public:
return intersect(r.left, r.top, r.right, r.bottom);
}
- bool contains(float l, float t, float r, float b) {
+ inline bool contains(float l, float t, float r, float b) {
return l >= left && t >= top && r <= right && b <= bottom;
}
- bool contains(const Rect& r) {
+ inline bool contains(const Rect& r) {
return contains(r.left, r.top, r.right, r.bottom);
}