Add colored rectangles implementation in OpenGLRenderer.
Drawing two rectangles one after the other discards the second one because of
Z buffering issues. This will be fixed in another changelist.
Change-Id: Ida1b3cde8a78e60cacc07e477abc44def527ff67
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index cbbce382f2..c097d7f 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "UIMatrix"
+#define LOG_TAG "Matrix"
#include <math.h>
#include <stdlib.h>
@@ -27,6 +27,7 @@
#include "Matrix.h"
namespace android {
+namespace uirenderer {
void Matrix4::loadIdentity() {
mMat[0] = 1.0f;
@@ -175,6 +176,21 @@
mMat[14] = -(far + near) / (far - near);
}
+#define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
+
+void Matrix4::mapRect(Rect& r) const {
+ const float sx = mMat[0];
+ const float sy = mMat[5];
+
+ const float tx = mMat[12];
+ const float ty = mMat[13];
+
+ MUL_ADD_STORE(r.left, sx, tx);
+ MUL_ADD_STORE(r.right, sx, tx);
+ MUL_ADD_STORE(r.top, sy, ty);
+ MUL_ADD_STORE(r.bottom, sy, ty);
+}
+
void Matrix4::dump() const {
LOGD("Matrix4[");
LOGD(" %f %f %f %f", mMat[0], mMat[4], mMat[ 8], mMat[12]);
@@ -184,4 +200,5 @@
LOGD("]");
}
-};
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 80f3fd6..9bd289f 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_MATRIX_H
-#define ANDROID_MATRIX_H
+#ifndef ANDROID_UI_MATRIX_H
+#define ANDROID_UI_MATRIX_H
#include <SkMatrix.h>
+#include "Rect.h"
+
namespace android {
+namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Classes
@@ -83,6 +86,8 @@
void copyTo(float* v) const;
void copyTo(SkMatrix& v) const;
+ void mapRect(Rect& r) const;
+
void dump() const;
private:
@@ -103,6 +108,7 @@
typedef Matrix4 mat4;
+}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_MATRIX_H
+#endif // ANDROID_UI_MATRIX_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e19795e7..575bc20 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
#include <utils/Log.h>
#include <GLES2/gl2.h>
@@ -32,6 +33,129 @@
#include "Matrix.h"
namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#define SOLID_WHITE { 1.0f, 1.0f, 1.0f, 1.0f }
+
+#define P(x, y) { x, y }
+
+///////////////////////////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////////////////////////
+
+const Vertex gDrawColorVertices[] = {
+ { P(0.0f, 0.0f), SOLID_WHITE },
+ { P(1.0f, 0.0f), SOLID_WHITE },
+ { P(0.0f, 1.0f), SOLID_WHITE },
+ { P(1.0f, 1.0f), SOLID_WHITE }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Shaders
+///////////////////////////////////////////////////////////////////////////////
+
+#define SHADER_SOURCE(name, source) const char* name = #source
+
+#include "shaders/drawColor.vert"
+#include "shaders/drawColor.frag"
+
+Program::Program(const char* vertex, const char* fragment) {
+ vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+ fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+
+ id = glCreateProgram();
+ glAttachShader(id, vertexShader);
+ glAttachShader(id, fragmentShader);
+ glLinkProgram(id);
+
+ GLint status;
+ glGetProgramiv(id, GL_LINK_STATUS, &status);
+ if (status != GL_TRUE) {
+ GLint infoLen = 0;
+ glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1) {
+ char* log = (char*) malloc(sizeof(char) * infoLen);
+ glGetProgramInfoLog(id, infoLen, 0, log);
+ LOGE("Error while linking shaders: %s", log);
+ delete log;
+ }
+ glDeleteProgram(id);
+ }
+}
+
+Program::~Program() {
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ glDeleteProgram(id);
+}
+
+void Program::use() {
+ glUseProgram(id);
+}
+
+int Program::addAttrib(const char* name) {
+ int slot = glGetAttribLocation(id, name);
+ attributes.add(name, slot);
+ return slot;
+}
+
+int Program::getAttrib(const char* name) {
+ return attributes.valueFor(name);
+}
+
+int Program::addUniform(const char* name) {
+ int slot = glGetUniformLocation(id, name);
+ uniforms.add(name, slot);
+ return slot;
+}
+
+int Program::getUniform(const char* name) {
+ return uniforms.valueFor(name);
+}
+
+GLuint Program::buildShader(const char* source, GLenum type) {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &source, 0);
+ glCompileShader(shader);
+
+ GLint status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status != GL_TRUE) {
+ // Some drivers return wrong values for GL_INFO_LOG_LENGTH
+ // use a fixed size instead
+ GLchar log[512];
+ glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
+ LOGE("Error while compiling shader: %s", log);
+ glDeleteShader(shader);
+ }
+
+ return shader;
+}
+
+DrawColorProgram::DrawColorProgram():
+ Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
+ position = addAttrib("position");
+ color = addAttrib("color");
+ projection = addUniform("projection");
+ modelView = addUniform("modelView");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Support
+///////////////////////////////////////////////////////////////////////////////
+
+const Rect& Snapshot::getMappedClip() {
+ if (flags & kFlagDirtyTransform) {
+ flags &= ~kFlagDirtyTransform;
+ mappedClip.set(clipRect);
+ transform.mapRect(mappedClip);
+ }
+ return mappedClip;
+}
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
@@ -39,6 +163,8 @@
OpenGLRenderer::OpenGLRenderer() {
LOGD("Create OpenGLRenderer");
+
+ mDrawColorShader = new DrawColorProgram;
}
OpenGLRenderer::~OpenGLRenderer() {
@@ -114,7 +240,6 @@
}
bool OpenGLRenderer::restoreSnapshot() {
- // TODO: handle local transformations
bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
mSaveCount--;
@@ -132,18 +257,22 @@
void OpenGLRenderer::translate(float dx, float dy) {
mSnapshot->transform.translate(dx, dy, 0.0f);
+ mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::rotate(float degrees) {
mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
+ mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::scale(float sx, float sy) {
mSnapshot->transform.scale(sx, sy, 1.0f);
+ mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
mSnapshot->transform.load(*matrix);
+ mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
@@ -153,6 +282,7 @@
void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
mat4 m(*matrix);
mSnapshot->transform.multiply(m);
+ mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
///////////////////////////////////////////////////////////////////////////////
@@ -160,12 +290,15 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setScissorFromClip() {
- Rect* clip = &(mSnapshot->clipRect);
- glScissor(clip->left, clip->top, clip->getWidth(), clip->getHeight());
+ const Rect& clip = mSnapshot->getMappedClip();
+ glScissor(clip.left, clip.top, clip.getWidth(), clip.getHeight());
+}
+
+const Rect& OpenGLRenderer::getClipBounds() {
+ return mSnapshot->clipRect;
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
- // TODO: take local translate transform into account
bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
if (clipped) {
mSnapshot->flags |= Snapshot::kFlagClipSet;
@@ -179,7 +312,41 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
- LOGD("Drawing color");
+ GLfloat a = ((color >> 24) & 0xFF) / 255.0f;
+ GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
+ GLfloat g = ((color >> 8) & 0xFF) / 255.0f;
+ GLfloat b = ((color ) & 0xFF) / 255.0f;
+
+ // TODO Optimize this section
+ const Rect& clip = mSnapshot->getMappedClip();
+
+ mat4 modelView;
+ modelView.loadScale(clip.getWidth(), clip.getHeight(), 1.0f);
+ modelView.translate(clip.left, clip.top, 0.0f);
+
+ float matrix[16];
+ modelView.copyTo(matrix);
+ // TODO Optimize this section
+
+ mDrawColorShader->use();
+
+ glUniformMatrix4fv(mDrawColorShader->projection, 1, GL_FALSE, &mOrthoMatrix[0]);
+ glUniformMatrix4fv(mDrawColorShader->modelView, 1, GL_FALSE, &matrix[0]);
+
+ glEnableVertexAttribArray(mDrawColorShader->position);
+
+ GLsizei stride = sizeof(Vertex);
+ const GLvoid* p = &gDrawColorVertices[0].position[0];
+
+ glVertexAttribPointer(mDrawColorShader->position, 2, GL_FLOAT, GL_FALSE, stride, p);
+ glVertexAttrib4f(mDrawColorShader->color, r, g, b, a);
+
+ GLsizei vertexCount = sizeof(gDrawColorVertices) / sizeof(Vertex);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
+
+ glDisableVertexAttribArray(mDrawColorShader->position);
+ glDisableVertexAttribArray(mDrawColorShader->color);
}
+}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 595768c..88cbc1c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -14,18 +14,23 @@
* limitations under the License.
*/
-#ifndef ANDROID_OPENGL_RENDERER_H
-#define ANDROID_OPENGL_RENDERER_H
+#ifndef ANDROID_UI_OPENGL_RENDERER_H
+#define ANDROID_UI_OPENGL_RENDERER_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
#include <SkMatrix.h>
#include <SkXfermode.h>
+#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include "Matrix.h"
#include "Rect.h"
namespace android {
+namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Support
@@ -36,14 +41,20 @@
Snapshot() {
}
- Snapshot(const sp<Snapshot> s): transform(s->transform), clipRect(s->clipRect),
- flags(0), previous(s) {
+ Snapshot(const sp<Snapshot> s):
+ transform(s->transform),
+ clipRect(s->clipRect),
+ flags(kFlagDirtyTransform),
+ previous(s) {
}
enum Flags {
kFlagClipSet = 0x1,
+ kFlagDirtyTransform = 0x2,
};
+ const Rect& getMappedClip();
+
// Local transformations
mat4 transform;
@@ -55,7 +66,58 @@
// Previous snapshot in the frames stack
sp<Snapshot> previous;
-}; // struct Snapshot
+
+private:
+ // Clipping rectangle mapped with the transform
+ Rect mappedClip;
+}; // class Snapshot
+
+struct Vertex {
+ float position[2];
+ float color[4];
+}; // struct Vertex
+
+typedef char* shader;
+
+class Program: public LightRefBase<Program> {
+public:
+ Program(const char* vertex, const char* fragment);
+ ~Program();
+
+ void use();
+
+protected:
+ int addAttrib(const char* name);
+ int getAttrib(const char* name);
+
+ int addUniform(const char* name);
+ int getUniform(const char* name);
+
+private:
+ GLuint buildShader(const char* source, GLenum type);
+
+ // Handle of the OpenGL program
+ GLuint id;
+
+ // Handles of the shaders
+ GLuint vertexShader;
+ GLuint fragmentShader;
+
+ // Keeps track of attributes and uniforms slots
+ KeyedVector<const char*, int> attributes;
+ KeyedVector<const char*, int> uniforms;
+}; // class Program
+
+class DrawColorProgram: public Program {
+public:
+ DrawColorProgram();
+
+ int position;
+ int color;
+
+ int projection;
+ int modelView;
+};
///////////////////////////////////////////////////////////////////////////////
// Renderer
@@ -82,6 +144,7 @@
void getMatrix(SkMatrix* matrix);
void concatMatrix(SkMatrix* matrix);
+ const Rect& getClipBounds();
bool clipRect(float left, float top, float right, float bottom);
void drawColor(int color, SkXfermode::Mode mode);
@@ -104,8 +167,12 @@
Snapshot mFirstSnapshot;
// Current state
sp<Snapshot> mSnapshot;
+
+ // Shaders
+ sp<DrawColorProgram> mDrawColorShader;
}; // class OpenGLRenderer
+}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_OPENGL_RENDERER_H
+#endif // ANDROID_UI_OPENGL_RENDERER_H
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 724bd1a..fcf11e9 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#ifndef ANDROID_RECT_H
-#define ANDROID_RECT_H
+#ifndef ANDROID_UI_RECT_H
+#define ANDROID_UI_RECT_H
namespace android {
+namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Structs
@@ -29,7 +30,19 @@
float right;
float bottom;
- Rect(): left(0), top(0), right(0), bottom(0) { }
+ Rect():
+ left(0),
+ top(0),
+ right(0),
+ bottom(0) {
+ }
+
+ Rect(float left, float top, float right, float bottom):
+ left(left),
+ top(top),
+ right(right),
+ bottom(bottom) {
+ }
Rect(const Rect& r) {
set(r);
@@ -120,6 +133,7 @@
}; // struct Rect
+}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_RECT_H
diff --git a/libs/hwui/shaders/drawColor.frag b/libs/hwui/shaders/drawColor.frag
new file mode 100644
index 0000000..f753abb
--- /dev/null
+++ b/libs/hwui/shaders/drawColor.frag
@@ -0,0 +1,11 @@
+SHADER_SOURCE(gDrawColorFragmentShader,
+
+precision mediump float;
+
+varying vec4 outColor;
+
+void main(void) {
+ gl_FragColor = outColor;
+}
+
+);
diff --git a/libs/hwui/shaders/drawColor.vert b/libs/hwui/shaders/drawColor.vert
new file mode 100644
index 0000000..fd3cb45
--- /dev/null
+++ b/libs/hwui/shaders/drawColor.vert
@@ -0,0 +1,16 @@
+SHADER_SOURCE(gDrawColorVertexShader,
+
+attribute vec4 position;
+attribute vec4 color;
+
+uniform mat4 projection;
+uniform mat4 modelView;
+
+varying vec4 outColor;
+
+void main(void) {
+ outColor = color;
+ gl_Position = projection * modelView * position;
+}
+
+);