Loading libs/hwui/OpenGLRenderer.cpp +77 −44 Original line number Diff line number Diff line Loading @@ -171,6 +171,16 @@ bool OpenGLRenderer::restoreSnapshot() { sp<Snapshot> previous = mSnapshot->previous; if (restoreLayer) { composeLayer(current, previous); } mSnapshot = previous; mSaveCount--; return restoreClip; } 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); Loading @@ -194,7 +204,7 @@ bool OpenGLRenderer::restoreSnapshot() { resetDrawTextureTexCoords(u1, v1, u2, v1); drawTextureRect(layer.left, layer.top, layer.right, layer.bottom, current->texture, current->alpha); current->texture, current->alpha, current->mode, true); resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); Loading @@ -202,37 +212,49 @@ bool OpenGLRenderer::restoreSnapshot() { 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 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); Loading @@ -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; } /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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); Loading libs/hwui/OpenGLRenderer.h +31 −1 Original line number Diff line number Diff line Loading @@ -125,6 +125,34 @@ private: */ void setScissorFromClip(); /** * Compose the layer defined in the current snapshot with the layer * defined by the previous snapshot. * * The current snapshot *must* be a layer (flag kFlagIsLayer set.) * * @param curent The current snapshot containing the layer to compose * @param previous The previous snapshot to compose the current layer with */ void composeLayer(sp<Snapshot> current, sp<Snapshot> previous); /** * Creates a new layer stored in the specified snapshot. * * @param snapshot The snapshot associated with the new layer * @param left The left coordinate of the layer * @param top The top coordinate of the layer * @param right The right coordinate of the layer * @param bottom The bottom coordinate of the layer * @param alpha The translucency of the layer * @param mode The blending mode of the layer * @param flags The layer save flags * * @return True if the layer was successfully created, false otherwise */ bool createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode, int flags); /** * Draws a colored rectangle with the specified color. The specified coordinates * are transformed by the current snapshot's transform matrix. Loading @@ -149,9 +177,11 @@ private: * @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 * @param mode The blending mode * @param isPremultiplied Indicates whether the texture has premultiplied alpha */ void drawTextureRect(float left, float top, float right, float bottom, GLuint texture, float alpha); float alpha, SkXfermode::Mode mode, bool isPremultiplied = false); /** * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values Loading libs/hwui/Snapshot.h +7 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <SkXfermode.h> #include <utils/RefBase.h> #include "Matrix.h" Loading Loading @@ -133,6 +135,11 @@ public: * Only set when the flag kFlagIsLayer is set. */ float alpha; /** * Blending mode of the layer. * Only set when the flag kFlagIsLayer is set. */ SkXfermode::Mode mode; private: // Clipping rectangle mapped with the transform Loading tests/HwAccelerationTest/AndroidManifest.xml +12 −2 Original line number Diff line number Diff line Loading @@ -22,8 +22,18 @@ android:hardwareAccelerated="true"> <activity android:name="HwUiActivity" android:label="_Layers"> android:name="AlphaLayersActivity" android:label="_αLayers"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="LayersActivity" android:label="_Layers" android:theme="@android:style/Theme.Translucent"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> Loading tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java→tests/HwAccelerationTest/src/com/google/android/test/hwui/AlphaLayersActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ import android.view.animation.Animation; import android.widget.FrameLayout; @SuppressWarnings({"UnusedDeclaration"}) public class HwUiActivity extends Activity { public class AlphaLayersActivity extends Activity { private static final String LOG_TAG = "HwUi"; @Override Loading Loading
libs/hwui/OpenGLRenderer.cpp +77 −44 Original line number Diff line number Diff line Loading @@ -171,6 +171,16 @@ bool OpenGLRenderer::restoreSnapshot() { sp<Snapshot> previous = mSnapshot->previous; if (restoreLayer) { composeLayer(current, previous); } mSnapshot = previous; mSaveCount--; return restoreClip; } 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); Loading @@ -194,7 +204,7 @@ bool OpenGLRenderer::restoreSnapshot() { resetDrawTextureTexCoords(u1, v1, u2, v1); drawTextureRect(layer.left, layer.top, layer.right, layer.bottom, current->texture, current->alpha); current->texture, current->alpha, current->mode, true); resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); Loading @@ -202,37 +212,49 @@ bool OpenGLRenderer::restoreSnapshot() { 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 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); Loading @@ -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; } /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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); Loading
libs/hwui/OpenGLRenderer.h +31 −1 Original line number Diff line number Diff line Loading @@ -125,6 +125,34 @@ private: */ void setScissorFromClip(); /** * Compose the layer defined in the current snapshot with the layer * defined by the previous snapshot. * * The current snapshot *must* be a layer (flag kFlagIsLayer set.) * * @param curent The current snapshot containing the layer to compose * @param previous The previous snapshot to compose the current layer with */ void composeLayer(sp<Snapshot> current, sp<Snapshot> previous); /** * Creates a new layer stored in the specified snapshot. * * @param snapshot The snapshot associated with the new layer * @param left The left coordinate of the layer * @param top The top coordinate of the layer * @param right The right coordinate of the layer * @param bottom The bottom coordinate of the layer * @param alpha The translucency of the layer * @param mode The blending mode of the layer * @param flags The layer save flags * * @return True if the layer was successfully created, false otherwise */ bool createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode, int flags); /** * Draws a colored rectangle with the specified color. The specified coordinates * are transformed by the current snapshot's transform matrix. Loading @@ -149,9 +177,11 @@ private: * @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 * @param mode The blending mode * @param isPremultiplied Indicates whether the texture has premultiplied alpha */ void drawTextureRect(float left, float top, float right, float bottom, GLuint texture, float alpha); float alpha, SkXfermode::Mode mode, bool isPremultiplied = false); /** * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values Loading
libs/hwui/Snapshot.h +7 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <SkXfermode.h> #include <utils/RefBase.h> #include "Matrix.h" Loading Loading @@ -133,6 +135,11 @@ public: * Only set when the flag kFlagIsLayer is set. */ float alpha; /** * Blending mode of the layer. * Only set when the flag kFlagIsLayer is set. */ SkXfermode::Mode mode; private: // Clipping rectangle mapped with the transform Loading
tests/HwAccelerationTest/AndroidManifest.xml +12 −2 Original line number Diff line number Diff line Loading @@ -22,8 +22,18 @@ android:hardwareAccelerated="true"> <activity android:name="HwUiActivity" android:label="_Layers"> android:name="AlphaLayersActivity" android:label="_αLayers"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="LayersActivity" android:label="_Layers" android:theme="@android:style/Theme.Translucent"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> Loading
tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java→tests/HwAccelerationTest/src/com/google/android/test/hwui/AlphaLayersActivity.java +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ import android.view.animation.Animation; import android.widget.FrameLayout; @SuppressWarnings({"UnusedDeclaration"}) public class HwUiActivity extends Activity { public class AlphaLayersActivity extends Activity { private static final String LOG_TAG = "HwUi"; @Override Loading