diff options
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 161 |
1 files changed, 151 insertions, 10 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 830e0c36ff83..786b927d35eb 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -27,6 +27,7 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#include <SkCanvas.h> #include <SkPaint.h> #include <SkXfermode.h> @@ -40,21 +41,31 @@ namespace uirenderer { // Defines /////////////////////////////////////////////////////////////////////////////// -#define V(x, y) { { x, y } } +#define SV(x, y) { { x, y } } +#define FV(x, y, u, v) { { x, y }, { u, v } } /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// const SimpleVertex gDrawColorVertices[] = { - V(0.0f, 0.0f), - V(1.0f, 0.0f), - V(0.0f, 1.0f), - V(1.0f, 1.0f) + SV(0.0f, 0.0f), + SV(1.0f, 0.0f), + SV(0.0f, 1.0f), + SV(1.0f, 1.0f) }; const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); const GLsizei gDrawColorVertexCount = 4; +const 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), + FV(1.0f, 1.0f, 1.0f, 0.0f) +}; +const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex); +const GLsizei gDrawTextureVertexCount = 4; + /////////////////////////////////////////////////////////////////////////////// // Shaders /////////////////////////////////////////////////////////////////////////////// @@ -64,6 +75,9 @@ const GLsizei gDrawColorVertexCount = 4; #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); @@ -139,6 +153,15 @@ GLuint Program::buildShader(const char* source, GLenum type) { 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"); @@ -154,6 +177,12 @@ void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* model glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix); } +DrawTextureProgram::DrawTextureProgram(): + DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) { + texCoords = addAttrib("texCoords"); + sampler = addUniform("sampler"); +} + /////////////////////////////////////////////////////////////////////////////// // Support /////////////////////////////////////////////////////////////////////////////// @@ -175,6 +204,7 @@ OpenGLRenderer::OpenGLRenderer() { LOGD("Create OpenGLRenderer"); mDrawColorShader = new DrawColorProgram; + mDrawTextureShader = new DrawTextureProgram; } OpenGLRenderer::~OpenGLRenderer() { @@ -252,17 +282,90 @@ int OpenGLRenderer::saveSnapshot() { bool OpenGLRenderer::restoreSnapshot() { bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; + bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer; - mSaveCount--; - - // Do not merge these two lines! + sp<Snapshot> current = mSnapshot; sp<Snapshot> previous = mSnapshot->previous; + + if (restoreLayer) { + // Unbind current FBO and restore previous one + // Most of the time, previous->fbo will be 0 to bind the default buffer + glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); + + const Rect& layer = current->layer; + clipRect(layer.left, layer.top, layer.right, layer.bottom); + mSnapshot->transform.loadIdentity(); + + drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha); + + glDeleteFramebuffers(1, ¤t->fbo); + glDeleteTextures(1, ¤t->texture); + } + mSnapshot = previous; + mSaveCount--; return restoreClip; } /////////////////////////////////////////////////////////////////////////////// +// Layers +/////////////////////////////////////////////////////////////////////////////// + +int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, + const SkPaint* p, int flags) { + // TODO Implement + return saveSnapshot(); +} + +int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, + int alpha, int flags) { + int count = saveSnapshot(); + + mSnapshot->flags |= Snapshot::kFlagIsLayer; + mSnapshot->alpha = alpha / 255.0f; + mSnapshot->layer.set(left, top, right, bottom); + + // Generate the FBO and attach the texture + glGenFramebuffers(1, &mSnapshot->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, mSnapshot->fbo); + + // Generate the texture in which the FBO will draw + glGenTextures(1, &mSnapshot->texture); + glBindTexture(GL_TEXTURE_2D, mSnapshot->texture); + + // 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); + + // 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. + + const GLsizei width = mWidth; //right - left; + const GLsizei height = mHeight; //bottom - right; + + const GLint format = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) ? GL_RGBA : GL_RGB; + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + // Bind texture to FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + mSnapshot->texture, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LOGD("Framebuffer incomplete %d", status); + + glDeleteFramebuffers(1, &mSnapshot->fbo); + glDeleteTextures(1, &mSnapshot->texture); + } + + return count; +} + +/////////////////////////////////////////////////////////////////////////////// // Transforms /////////////////////////////////////////////////////////////////////////////// @@ -346,10 +449,10 @@ void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color); } -void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* paint) { +void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { // TODO Support more than just color // TODO: Set the transfer mode - drawColorRect(left, top, right, bottom, paint->getColor()); + drawColorRect(left, top, right, bottom, p->getColor()); } void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) { @@ -375,5 +478,43 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot glDisableVertexAttribArray(mDrawColorShader->position); } +void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, + GLuint texture, float alpha) { + mModelView.loadTranslate(left, top, 0.0f); + mModelView.scale(right - left, bottom - top, 1.0f); + + mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]); + + // TODO Correctly set the blend function + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + glBindTexture(GL_TEXTURE_2D, texture); + + glActiveTexture(GL_TEXTURE0); + glUniform1i(mDrawTextureShader->sampler, 0); + + const GLvoid* p = &gDrawTextureVertices[0].position[0]; + const GLvoid* t = &gDrawTextureVertices[0].texture[0]; + + glEnableVertexAttribArray(mDrawTextureShader->position); + glVertexAttribPointer(mDrawTextureShader->position, 2, GL_FLOAT, GL_FALSE, + gDrawTextureVertexStride, p); + + glEnableVertexAttribArray(mDrawTextureShader->texCoords); + glVertexAttribPointer(mDrawTextureShader->texCoords, 2, GL_FLOAT, GL_FALSE, + gDrawTextureVertexStride, t); + + glVertexAttrib4f(mDrawTextureShader->color, 1.0f, 1.0f, 1.0f, alpha); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount); + + glDisableVertexAttribArray(mDrawTextureShader->position); + glDisableVertexAttribArray(mDrawTextureShader->texCoords); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_BLEND); +} + }; // namespace uirenderer }; // namespace android |