Optimize shader binding changes.
This change also cleans up the internal API a little bit by using mat4
everywhere instead of float[16] (for the ortho matrix for instance.)
Change-Id: I35924c7dc17bad17f30307118d5ed437c2ed37e0
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b783d3f..117fccd 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -118,6 +118,7 @@
mDrawColorShader = new DrawColorProgram;
mDrawTextureShader = new DrawTextureProgram;
+ mCurrentShader = mDrawTextureShader;
memcpy(mDrawTextureVertices, gDrawTextureVertices, sizeof(gDrawTextureVertices));
}
@@ -136,9 +137,7 @@
void OpenGLRenderer::setViewport(int width, int height) {
glViewport(0, 0, width, height);
- mat4 ortho;
- ortho.loadOrtho(0, width, height, 0, -1, 1);
- ortho.copyTo(mOrthoMatrix);
+ mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
mWidth = width;
mHeight = height;
@@ -208,7 +207,7 @@
sp<Snapshot> previous = mSnapshot->previous;
if (restoreOrtho) {
- memcpy(mOrthoMatrix, current->orthoMatrix, sizeof(mOrthoMatrix));
+ mOrthoMatrix.load(current->orthoMatrix);
}
if (restoreLayer) {
@@ -333,12 +332,10 @@
mSnapshot->flags = Snapshot::kFlagDirtyTransform | Snapshot::kFlagDirtyOrtho |
Snapshot::kFlagClipSet;
- memcpy(mSnapshot->orthoMatrix, mOrthoMatrix, sizeof(mOrthoMatrix));
+ mSnapshot->orthoMatrix.load(mOrthoMatrix);
// Change the ortho projection
- mat4 ortho;
- ortho.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f);
- ortho.copyTo(mOrthoMatrix);
+ mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f);
return true;
}
@@ -511,7 +508,8 @@
mModelView.loadTranslate(left, top, 0.0f);
mModelView.scale(right - left, bottom - top, 1.0f);
- mDrawColorShader->use(&mOrthoMatrix[0], mModelView, mSnapshot->transform);
+ useShader(mDrawColorShader);
+ mDrawColorShader->set(mOrthoMatrix, mModelView, mSnapshot->transform);
const GLvoid* p = &gDrawColorVertices[0].position[0];
@@ -548,7 +546,8 @@
mModelView.loadTranslate(left, top, 0.0f);
mModelView.scale(right - left, bottom - top, 1.0f);
- mDrawTextureShader->use(&mOrthoMatrix[0], mModelView, mSnapshot->transform);
+ useShader(mDrawTextureShader);
+ mDrawTextureShader->set(mOrthoMatrix, mModelView, mSnapshot->transform);
chooseBlending(blend || alpha < 1.0f, mode, isPremultiplied);
@@ -606,6 +605,14 @@
mBlend = blend;
}
+void OpenGLRenderer::useShader(const sp<Program>& shader) {
+ if (!shader->isInUse()) {
+ mCurrentShader->remove();
+ shader->use();
+ mCurrentShader = shader;
+ }
+}
+
void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
TextureVertex* v = &mDrawTextureVertices[0];
TextureVertex::setUV(v++, u1, v1);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 76d6e06..afb747f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -247,11 +247,19 @@
*/
inline void chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied);
+ /**
+ * Use the specified shader with the current GL context. If the shader is already
+ * in use, it will not be bound again. If it is not in use, the current shader is
+ * marked unused and the specified shader becomes used and becomes the new
+ * current shader.
+ */
+ inline void useShader(const sp<Program>& shader);
+
// Dimensions of the drawing surface
int mWidth, mHeight;
// Matrix used for ortho projection in shaders
- float mOrthoMatrix[16];
+ mat4 mOrthoMatrix;
// Model-view matrix used to position/size objects
mat4 mModelView;
@@ -264,6 +272,7 @@
sp<Snapshot> mSnapshot;
// Shaders
+ sp<Program> mCurrentShader;
sp<DrawColorProgram> mDrawColorShader;
sp<DrawTextureProgram> mDrawTextureShader;
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 98d254c..3b5e5da 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -59,6 +59,8 @@
}
glDeleteProgram(id);
}
+
+ mUse = false;
}
Program::~Program() {
@@ -69,6 +71,11 @@
void Program::use() {
glUseProgram(id);
+ mUse = true;
+}
+
+void Program::remove() {
+ mUse = false;
}
int Program::addAttrib(const char* name) {
@@ -130,13 +137,12 @@
transform = addUniform("transform");
}
-void DrawColorProgram::use(const float* projectionMatrix, const mat4& modelViewMatrix,
+void DrawColorProgram::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
const mat4& transformMatrix) {
mat4 t(projectionMatrix);
t.multiply(transformMatrix);
t.multiply(modelViewMatrix);
- Program::use();
glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]);
}
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 61d55a9..652befe1 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -46,6 +46,20 @@
*/
void use();
+ /**
+ * Marks this program as unused. This will not unbind
+ * the program from the GL context.
+ */
+ void remove();
+
+ /**
+ * Indicates whether this program is currently in use with
+ * the GL context.
+ */
+ inline bool isInUse() const {
+ return mUse;
+ }
+
protected:
/**
* Adds an attribute with the specified name.
@@ -87,6 +101,8 @@
// Keeps track of attributes and uniforms slots
KeyedVector<const char*, int> attributes;
KeyedVector<const char*, int> uniforms;
+
+ bool mUse;
}; // class Program
/**
@@ -109,7 +125,7 @@
* Binds the program with the specified projection, modelView and
* transform matrices.
*/
- void use(const float* projectionMatrix, const mat4& modelViewMatrix,
+ void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
const mat4& transformMatrix);
/**
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 17ca440..ef9269f 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -130,7 +130,7 @@
/**
* Contains the previous ortho matrix.
*/
- float orthoMatrix[16];
+ mat4 orthoMatrix;
private:
// Clipping rectangle mapped with the transform