Loading libs/hwui/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ Matrix.cpp \ OpenGLRenderer.cpp OpenGLRenderer.cpp \ Program.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ Loading libs/hwui/Matrix.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ #define LOG_TAG "Matrix" #define LOG_TAG "OpenGLRenderer" #include <math.h> #include <stdlib.h> Loading libs/hwui/OpenGLRenderer.cpp +36 −144 Original line number Diff line number Diff line Loading @@ -20,19 +20,11 @@ #include <stdint.h> #include <sys/types.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> #include <utils/Log.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <SkCanvas.h> #include <SkPaint.h> #include <SkXfermode.h> #include <utils/Log.h> #include "OpenGLRenderer.h" #include "Matrix.h" namespace android { namespace uirenderer { Loading @@ -57,7 +49,7 @@ const SimpleVertex gDrawColorVertices[] = { const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); const GLsizei gDrawColorVertexCount = 4; const TextureVertex gDrawTextureVertices[] = { TextureVertex gDrawTextureVertices[] = { FV(0.0f, 0.0f, 0.0f, 1.0f), FV(1.0f, 0.0f, 1.0f, 1.0f), FV(0.0f, 1.0f, 0.0f, 0.0f), Loading @@ -66,134 +58,15 @@ const TextureVertex gDrawTextureVertices[] = { const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex); const GLsizei gDrawTextureVertexCount = 4; /////////////////////////////////////////////////////////////////////////////// // Shaders /////////////////////////////////////////////////////////////////////////////// #define SHADER_SOURCE(name, source) const char* name = #source #include "shaders/drawColor.vert" #include "shaders/drawColor.frag" #include "shaders/drawTexture.vert" #include "shaders/drawTexture.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) { getAttribsAndUniforms(); } DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment): Program(vertex, fragment) { getAttribsAndUniforms(); } void DrawColorProgram::getAttribsAndUniforms() { position = addAttrib("position"); color = addAttrib("color"); projection = addUniform("projection"); modelView = addUniform("modelView"); transform = addUniform("transform"); } void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix) { Program::use(); glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix); glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix); glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); } DrawTextureProgram::DrawTextureProgram(): DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) { texCoords = addAttrib("texCoords"); sampler = addUniform("sampler"); } /////////////////////////////////////////////////////////////////////////////// // Support /////////////////////////////////////////////////////////////////////////////// const Rect& Snapshot::getMappedClip() { if (flags & kFlagDirtyTransform) { flags &= ~kFlagDirtyTransform; mappedClip.set(clipRect); transform.mapRect(mappedClip); } return mappedClip; static inline void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { gDrawTextureVertices[0].texture[0] = u1; gDrawTextureVertices[0].texture[1] = v2; gDrawTextureVertices[1].texture[0] = u2; gDrawTextureVertices[1].texture[1] = v2; gDrawTextureVertices[2].texture[0] = u1; gDrawTextureVertices[2].texture[1] = v1; gDrawTextureVertices[3].texture[0] = u2; gDrawTextureVertices[3].texture[1] = v1; } /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -292,11 +165,28 @@ bool OpenGLRenderer::restoreSnapshot() { // Most of the time, previous->fbo will be 0 to bind the default buffer glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot const Rect& clip = previous->getMappedClip(); glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); // Compute the correct texture coordinates for the FBO texture // The texture is currently as big as the window but drawn with // a quad of the appropriate size const Rect& layer = current->layer; clipRect(layer.left, layer.top, layer.right, layer.bottom); mSnapshot->transform.loadIdentity(); Rect texCoords(current->layer); mSnapshot->transform.mapRect(texCoords); const float u1 = texCoords.left / float(mWidth); const float v1 = (mHeight - texCoords.top) / float(mHeight); const float u2 = texCoords.right / float(mWidth); const float v2 = (mHeight - texCoords.bottom) / float(mHeight); drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha); resetDrawTextureTexCoords(u1, v1, u2, v1); drawTextureRect(layer.left, layer.top, layer.right, layer.bottom, current->texture, current->alpha); resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); glDeleteFramebuffers(1, ¤t->fbo); glDeleteTextures(1, ¤t->texture); Loading Loading @@ -337,11 +227,14 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // TODO ***** IMPORTANT ***** // Creating a texture-backed FBO works only if the texture is the same size // as the original rendering buffer (in this case, mWidth and mHeight.) // This is expensive and wasteful and must be fixed. // TODO Additionally we should use an FBO cache const GLsizei width = mWidth; //right - left; const GLsizei height = mHeight; //bottom - right; Loading Loading @@ -425,7 +318,6 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto * const Rect& clip = mSnapshot->getMappedClip(); * return !clip.intersects(r); */ Rect r(left, top, right, bottom); return !mSnapshot->clipRect.intersects(r); } Loading Loading @@ -485,7 +377,7 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]); // TODO Correctly set the blend function // TODO Correctly set the blend function, based on texture format and xfermode glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); Loading libs/hwui/OpenGLRenderer.h +53 −104 Original line number Diff line number Diff line Loading @@ -23,11 +23,12 @@ #include <SkMatrix.h> #include <SkXfermode.h> #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include "Matrix.h" #include "Program.h" #include "Rect.h" #include "Snapshot.h" namespace android { namespace uirenderer { Loading @@ -36,122 +37,30 @@ namespace uirenderer { // Support /////////////////////////////////////////////////////////////////////////////// class Snapshot: public LightRefBase<Snapshot> { public: Snapshot() { } Snapshot(const sp<Snapshot> s): transform(s->transform), clipRect(s->clipRect), flags(kFlagDirtyTransform), previous(s), layer(0.0f, 0.0f, 0.0f, 0.0f), texture(0), fbo(0), alpha(255) { } enum Flags { kFlagClipSet = 0x1, kFlagDirtyTransform = 0x2, kFlagIsLayer = 0x4, }; const Rect& getMappedClip(); // Local transformations mat4 transform; // Clipping rectangle at the time of this snapshot Rect clipRect; // Dirty flags int flags; // Previous snapshot in the frames stack sp<Snapshot> previous; // Layer, only set if kFlagIsLayer is set Rect layer; GLuint texture; GLuint fbo; float alpha; private: // Clipping rectangle mapped with the transform Rect mappedClip; }; // class Snapshot /** * Simple structure to describe a vertex with a position. * This is used to draw filled rectangles without a texture. */ struct SimpleVertex { float position[2]; }; // struct SimpleVertex /** * Simple structure to describe a vertex with a position and a texture. */ struct TextureVertex { float position[2]; float texture[2]; }; // struct TextureVertex 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(); DrawColorProgram(const char* vertex, const char* fragment); void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix); int position; int color; int projection; int modelView; int transform; protected: void getAttribsAndUniforms(); }; class DrawTextureProgram: public DrawColorProgram { public: DrawTextureProgram(); int sampler; int texCoords; }; /////////////////////////////////////////////////////////////////////////////// // Renderer /////////////////////////////////////////////////////////////////////////////// /** * OpenGL renderer used to draw accelerated 2D graphics. The API is a * simplified version of Skia's Canvas API. */ class OpenGLRenderer { public: OpenGLRenderer(); Loading Loading @@ -184,12 +93,52 @@ public: void drawRect(float left, float top, float right, float bottom, const SkPaint* paint); private: /** * Saves the current state of the renderer as a new snapshot. * The new snapshot is saved in mSnapshot and the previous snapshot * is linked from mSnapshot->previous. * * @return The new save count. This value can be passed to #restoreToCount() */ int saveSnapshot(); /** * Restores the current snapshot; mSnapshot becomes mSnapshot->previous. * * @return True if the clip should be also reapplied by calling * #setScissorFromClip(). */ bool restoreSnapshot(); /** * Sets the clipping rectangle using glScissor. The clip is defined by * the current snapshot's clipRect member. */ void setScissorFromClip(); /** * Draws a colored rectangle with the specified color. The specified coordinates * are transformed by the current snapshot's transform matrix. * * @param left The left coordinate of the rectangle * @param top The top coordinate of the rectangle * @param right The right coordinate of the rectangle * @param bottom The bottom coordinate of the rectangle * @param color The rectangle's ARGB color, defined as a packed 32 bits word */ void drawColorRect(float left, float top, float right, float bottom, int color); /** * Draws a textured rectangle with the specified texture. The specified coordinates * are transformed by the current snapshot's transform matrix. * * @param left The left coordinate of the rectangle * @param top The top coordinate of the rectangle * @param right The right coordinate of the rectangle * @param bottom The bottom coordinate of the rectangle * @param texture The texture name to map onto the rectangle * @param alpha An additional translucency parameter, between 0.0f and 1.0f */ void drawTextureRect(float left, float top, float right, float bottom, GLuint texture, float alpha); Loading libs/hwui/Program.cpp 0 → 100644 +154 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "OpenGLRenderer" #include "Program.h" namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Shaders /////////////////////////////////////////////////////////////////////////////// #define SHADER_SOURCE(name, source) const char* name = #source #include "shaders/drawColor.vert" #include "shaders/drawColor.frag" #include "shaders/drawTexture.vert" #include "shaders/drawTexture.frag" /////////////////////////////////////////////////////////////////////////////// // Base program /////////////////////////////////////////////////////////////////////////////// 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; } /////////////////////////////////////////////////////////////////////////////// // Draw color /////////////////////////////////////////////////////////////////////////////// DrawColorProgram::DrawColorProgram(): Program(gDrawColorVertexShader, gDrawColorFragmentShader) { getAttribsAndUniforms(); } DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment): Program(vertex, fragment) { getAttribsAndUniforms(); } void DrawColorProgram::getAttribsAndUniforms() { position = addAttrib("position"); color = addAttrib("color"); projection = addUniform("projection"); modelView = addUniform("modelView"); transform = addUniform("transform"); } void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix) { Program::use(); glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix); glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix); glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); } /////////////////////////////////////////////////////////////////////////////// // Draw texture /////////////////////////////////////////////////////////////////////////////// DrawTextureProgram::DrawTextureProgram(): DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) { texCoords = addAttrib("texCoords"); sampler = addUniform("sampler"); } }; // namespace uirenderer }; // namespace android Loading
libs/hwui/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ Matrix.cpp \ OpenGLRenderer.cpp OpenGLRenderer.cpp \ Program.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ Loading
libs/hwui/Matrix.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ #define LOG_TAG "Matrix" #define LOG_TAG "OpenGLRenderer" #include <math.h> #include <stdlib.h> Loading
libs/hwui/OpenGLRenderer.cpp +36 −144 Original line number Diff line number Diff line Loading @@ -20,19 +20,11 @@ #include <stdint.h> #include <sys/types.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> #include <utils/Log.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <SkCanvas.h> #include <SkPaint.h> #include <SkXfermode.h> #include <utils/Log.h> #include "OpenGLRenderer.h" #include "Matrix.h" namespace android { namespace uirenderer { Loading @@ -57,7 +49,7 @@ const SimpleVertex gDrawColorVertices[] = { const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); const GLsizei gDrawColorVertexCount = 4; const TextureVertex gDrawTextureVertices[] = { TextureVertex gDrawTextureVertices[] = { FV(0.0f, 0.0f, 0.0f, 1.0f), FV(1.0f, 0.0f, 1.0f, 1.0f), FV(0.0f, 1.0f, 0.0f, 0.0f), Loading @@ -66,134 +58,15 @@ const TextureVertex gDrawTextureVertices[] = { const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex); const GLsizei gDrawTextureVertexCount = 4; /////////////////////////////////////////////////////////////////////////////// // Shaders /////////////////////////////////////////////////////////////////////////////// #define SHADER_SOURCE(name, source) const char* name = #source #include "shaders/drawColor.vert" #include "shaders/drawColor.frag" #include "shaders/drawTexture.vert" #include "shaders/drawTexture.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) { getAttribsAndUniforms(); } DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment): Program(vertex, fragment) { getAttribsAndUniforms(); } void DrawColorProgram::getAttribsAndUniforms() { position = addAttrib("position"); color = addAttrib("color"); projection = addUniform("projection"); modelView = addUniform("modelView"); transform = addUniform("transform"); } void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix) { Program::use(); glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix); glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix); glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); } DrawTextureProgram::DrawTextureProgram(): DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) { texCoords = addAttrib("texCoords"); sampler = addUniform("sampler"); } /////////////////////////////////////////////////////////////////////////////// // Support /////////////////////////////////////////////////////////////////////////////// const Rect& Snapshot::getMappedClip() { if (flags & kFlagDirtyTransform) { flags &= ~kFlagDirtyTransform; mappedClip.set(clipRect); transform.mapRect(mappedClip); } return mappedClip; static inline void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { gDrawTextureVertices[0].texture[0] = u1; gDrawTextureVertices[0].texture[1] = v2; gDrawTextureVertices[1].texture[0] = u2; gDrawTextureVertices[1].texture[1] = v2; gDrawTextureVertices[2].texture[0] = u1; gDrawTextureVertices[2].texture[1] = v1; gDrawTextureVertices[3].texture[0] = u2; gDrawTextureVertices[3].texture[1] = v1; } /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -292,11 +165,28 @@ bool OpenGLRenderer::restoreSnapshot() { // Most of the time, previous->fbo will be 0 to bind the default buffer glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot const Rect& clip = previous->getMappedClip(); glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); // Compute the correct texture coordinates for the FBO texture // The texture is currently as big as the window but drawn with // a quad of the appropriate size const Rect& layer = current->layer; clipRect(layer.left, layer.top, layer.right, layer.bottom); mSnapshot->transform.loadIdentity(); Rect texCoords(current->layer); mSnapshot->transform.mapRect(texCoords); const float u1 = texCoords.left / float(mWidth); const float v1 = (mHeight - texCoords.top) / float(mHeight); const float u2 = texCoords.right / float(mWidth); const float v2 = (mHeight - texCoords.bottom) / float(mHeight); drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha); resetDrawTextureTexCoords(u1, v1, u2, v1); drawTextureRect(layer.left, layer.top, layer.right, layer.bottom, current->texture, current->alpha); resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); glDeleteFramebuffers(1, ¤t->fbo); glDeleteTextures(1, ¤t->texture); Loading Loading @@ -337,11 +227,14 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // TODO ***** IMPORTANT ***** // Creating a texture-backed FBO works only if the texture is the same size // as the original rendering buffer (in this case, mWidth and mHeight.) // This is expensive and wasteful and must be fixed. // TODO Additionally we should use an FBO cache const GLsizei width = mWidth; //right - left; const GLsizei height = mHeight; //bottom - right; Loading Loading @@ -425,7 +318,6 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto * const Rect& clip = mSnapshot->getMappedClip(); * return !clip.intersects(r); */ Rect r(left, top, right, bottom); return !mSnapshot->clipRect.intersects(r); } Loading Loading @@ -485,7 +377,7 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]); // TODO Correctly set the blend function // TODO Correctly set the blend function, based on texture format and xfermode glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); Loading
libs/hwui/OpenGLRenderer.h +53 −104 Original line number Diff line number Diff line Loading @@ -23,11 +23,12 @@ #include <SkMatrix.h> #include <SkXfermode.h> #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include "Matrix.h" #include "Program.h" #include "Rect.h" #include "Snapshot.h" namespace android { namespace uirenderer { Loading @@ -36,122 +37,30 @@ namespace uirenderer { // Support /////////////////////////////////////////////////////////////////////////////// class Snapshot: public LightRefBase<Snapshot> { public: Snapshot() { } Snapshot(const sp<Snapshot> s): transform(s->transform), clipRect(s->clipRect), flags(kFlagDirtyTransform), previous(s), layer(0.0f, 0.0f, 0.0f, 0.0f), texture(0), fbo(0), alpha(255) { } enum Flags { kFlagClipSet = 0x1, kFlagDirtyTransform = 0x2, kFlagIsLayer = 0x4, }; const Rect& getMappedClip(); // Local transformations mat4 transform; // Clipping rectangle at the time of this snapshot Rect clipRect; // Dirty flags int flags; // Previous snapshot in the frames stack sp<Snapshot> previous; // Layer, only set if kFlagIsLayer is set Rect layer; GLuint texture; GLuint fbo; float alpha; private: // Clipping rectangle mapped with the transform Rect mappedClip; }; // class Snapshot /** * Simple structure to describe a vertex with a position. * This is used to draw filled rectangles without a texture. */ struct SimpleVertex { float position[2]; }; // struct SimpleVertex /** * Simple structure to describe a vertex with a position and a texture. */ struct TextureVertex { float position[2]; float texture[2]; }; // struct TextureVertex 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(); DrawColorProgram(const char* vertex, const char* fragment); void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix); int position; int color; int projection; int modelView; int transform; protected: void getAttribsAndUniforms(); }; class DrawTextureProgram: public DrawColorProgram { public: DrawTextureProgram(); int sampler; int texCoords; }; /////////////////////////////////////////////////////////////////////////////// // Renderer /////////////////////////////////////////////////////////////////////////////// /** * OpenGL renderer used to draw accelerated 2D graphics. The API is a * simplified version of Skia's Canvas API. */ class OpenGLRenderer { public: OpenGLRenderer(); Loading Loading @@ -184,12 +93,52 @@ public: void drawRect(float left, float top, float right, float bottom, const SkPaint* paint); private: /** * Saves the current state of the renderer as a new snapshot. * The new snapshot is saved in mSnapshot and the previous snapshot * is linked from mSnapshot->previous. * * @return The new save count. This value can be passed to #restoreToCount() */ int saveSnapshot(); /** * Restores the current snapshot; mSnapshot becomes mSnapshot->previous. * * @return True if the clip should be also reapplied by calling * #setScissorFromClip(). */ bool restoreSnapshot(); /** * Sets the clipping rectangle using glScissor. The clip is defined by * the current snapshot's clipRect member. */ void setScissorFromClip(); /** * Draws a colored rectangle with the specified color. The specified coordinates * are transformed by the current snapshot's transform matrix. * * @param left The left coordinate of the rectangle * @param top The top coordinate of the rectangle * @param right The right coordinate of the rectangle * @param bottom The bottom coordinate of the rectangle * @param color The rectangle's ARGB color, defined as a packed 32 bits word */ void drawColorRect(float left, float top, float right, float bottom, int color); /** * Draws a textured rectangle with the specified texture. The specified coordinates * are transformed by the current snapshot's transform matrix. * * @param left The left coordinate of the rectangle * @param top The top coordinate of the rectangle * @param right The right coordinate of the rectangle * @param bottom The bottom coordinate of the rectangle * @param texture The texture name to map onto the rectangle * @param alpha An additional translucency parameter, between 0.0f and 1.0f */ void drawTextureRect(float left, float top, float right, float bottom, GLuint texture, float alpha); Loading
libs/hwui/Program.cpp 0 → 100644 +154 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "OpenGLRenderer" #include "Program.h" namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Shaders /////////////////////////////////////////////////////////////////////////////// #define SHADER_SOURCE(name, source) const char* name = #source #include "shaders/drawColor.vert" #include "shaders/drawColor.frag" #include "shaders/drawTexture.vert" #include "shaders/drawTexture.frag" /////////////////////////////////////////////////////////////////////////////// // Base program /////////////////////////////////////////////////////////////////////////////// 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; } /////////////////////////////////////////////////////////////////////////////// // Draw color /////////////////////////////////////////////////////////////////////////////// DrawColorProgram::DrawColorProgram(): Program(gDrawColorVertexShader, gDrawColorFragmentShader) { getAttribsAndUniforms(); } DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment): Program(vertex, fragment) { getAttribsAndUniforms(); } void DrawColorProgram::getAttribsAndUniforms() { position = addAttrib("position"); color = addAttrib("color"); projection = addUniform("projection"); modelView = addUniform("modelView"); transform = addUniform("transform"); } void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix, const GLfloat* transformMatrix) { Program::use(); glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix); glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix); glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); } /////////////////////////////////////////////////////////////////////////////// // Draw texture /////////////////////////////////////////////////////////////////////////////// DrawTextureProgram::DrawTextureProgram(): DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) { texCoords = addAttrib("texCoords"); sampler = addUniform("sampler"); } }; // namespace uirenderer }; // namespace android