diff options
| author | Romain Guy <romainguy@google.com> | 2010-06-28 17:42:46 -0700 |
|---|---|---|
| committer | Romain Guy <romainguy@google.com> | 2010-06-28 18:52:24 -0700 |
| commit | d55a86120dd1e8ebcc6906c9ffd463f7460348da (patch) | |
| tree | 11ee1cc35750ba27df4fdb80540c3a5752cdd500 /libs/hwui/OpenGLRenderer.cpp | |
| parent | 8f704d89dc38c6e25b23721f6a784956521f283a (diff) | |
| download | frameworks_base-d55a86120dd1e8ebcc6906c9ffd463f7460348da.zip frameworks_base-d55a86120dd1e8ebcc6906c9ffd463f7460348da.tar.gz frameworks_base-d55a86120dd1e8ebcc6906c9ffd463f7460348da.tar.bz2 | |
Add support for saveLayer().
saveLayer() is affected by the paint's alpha and xfermode.
Change-Id: I28693a9337052643adccdb4889a8f228d4e17903
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 121 |
1 files changed, 77 insertions, 44 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 305c8c5..aa992c4 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -171,41 +171,45 @@ bool OpenGLRenderer::restoreSnapshot() { 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); + composeLayer(current, previous); + } - // Restore the clip from the previous snapshot - const Rect& clip = previous->getMappedClip(); - glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); + mSnapshot = previous; + mSaveCount--; - // 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; - Rect texCoords(current->layer); - mSnapshot->transform.mapRect(texCoords); + return restoreClip; +} - 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); +void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { + // 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); - resetDrawTextureTexCoords(u1, v1, u2, v1); + // Restore the clip from the previous snapshot + const Rect& clip = previous->getMappedClip(); + glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); - drawTextureRect(layer.left, layer.top, layer.right, layer.bottom, - current->texture, current->alpha); + // 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; + Rect texCoords(current->layer); + mSnapshot->transform.mapRect(texCoords); - resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); + 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); - glDeleteFramebuffers(1, ¤t->fbo); - glDeleteTextures(1, ¤t->texture); - } + resetDrawTextureTexCoords(u1, v1, u2, v1); - mSnapshot = previous; - mSaveCount--; + drawTextureRect(layer.left, layer.top, layer.right, layer.bottom, + current->texture, current->alpha, current->mode, true); - return restoreClip; + resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); + + glDeleteFramebuffers(1, ¤t->fbo); + glDeleteTextures(1, ¤t->texture); } /////////////////////////////////////////////////////////////////////////////// @@ -214,25 +218,43 @@ bool OpenGLRenderer::restoreSnapshot() { int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, const SkPaint* p, int flags) { - // TODO Implement - return saveSnapshot(); + int count = saveSnapshot(); + + int alpha = 255; + SkXfermode::Mode mode; + + if (p) { + alpha = p->getAlpha(); + const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); + if (!isMode) { + // Assume SRC_OVER + mode = SkXfermode::kSrcOver_Mode; + } + } else { + mode = SkXfermode::kSrcOver_Mode; + } + + createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags); + + return count; } int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags) { int count = saveSnapshot(); + createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags); + return count; +} - mSnapshot->flags |= Snapshot::kFlagIsLayer; - mSnapshot->alpha = alpha / 255.0f; - mSnapshot->layer.set(left, top, right, bottom); - +bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, + float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) { // Generate the FBO and attach the texture - glGenFramebuffers(1, &mSnapshot->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, mSnapshot->fbo); + glGenFramebuffers(1, &snapshot->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); // Generate the texture in which the FBO will draw - glGenTextures(1, &mSnapshot->texture); - glBindTexture(GL_TEXTURE_2D, mSnapshot->texture); + glGenTextures(1, &snapshot->texture); + glBindTexture(GL_TEXTURE_2D, snapshot->texture); // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -255,17 +277,24 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot // Bind texture to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - mSnapshot->texture, 0); + snapshot->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); + glDeleteFramebuffers(1, &snapshot->fbo); + glDeleteTextures(1, &snapshot->texture); + + return false; } - return count; + snapshot->flags |= Snapshot::kFlagIsLayer; + snapshot->mode = mode; + snapshot->alpha = alpha / 255.0f; + snapshot->layer.set(left, top, right, bottom); + + return true; } /////////////////////////////////////////////////////////////////////////////// @@ -406,16 +435,20 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot } void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, - GLuint texture, float alpha) { + GLuint texture, float alpha, SkXfermode::Mode mode, bool isPremultiplied) { 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, based on texture format and xfermode + GLenum sourceMode = gBlends[mode].src; + if (!isPremultiplied && sourceMode == GL_ONE) { + sourceMode = GL_SRC_ALPHA; + } + + // TODO: Try to disable blending when the texture is opaque and alpha == 1.0f glEnable(GL_BLEND); - // For not pre-multiplied sources - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(sourceMode, gBlends[mode].dst); glBindTexture(GL_TEXTURE_2D, texture); |
