summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@android.com>2010-06-26 00:13:53 -0700
committerRomain Guy <romainguy@android.com>2010-06-26 00:13:53 -0700
commitbd6b79b40247aea7bfe13d0831c6c0472df6c636 (patch)
tree71c913ec50df87a9463e30c8a28e5cb29e734c79
parent7ae7ac48aa2b53453c9805075171ecd5bcafd7de (diff)
downloadframeworks_base-bd6b79b40247aea7bfe13d0831c6c0472df6c636.zip
frameworks_base-bd6b79b40247aea7bfe13d0831c6c0472df6c636.tar.gz
frameworks_base-bd6b79b40247aea7bfe13d0831c6c0472df6c636.tar.bz2
Add implementations for saveLayerAlpha() and textured rects.
Even though there's an implementation for textured rects, drawBitmap() is not hooked up yet as it will require a good texture cache. This method is implemented using FBOs. There's currently an issue either in the driver or in the Canvas renderer that forces the FBO to be fullscreen, which is extremely expensive and yields terrible performance. Change-Id: I148419195e12d45653c60186938aa78c23a68e2c
-rw-r--r--core/java/android/view/GLES20Canvas.java20
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp67
-rw-r--r--libs/hwui/Matrix.cpp8
-rw-r--r--libs/hwui/Matrix.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp161
-rw-r--r--libs/hwui/OpenGLRenderer.h38
-rw-r--r--libs/hwui/shaders/drawColor.frag4
-rw-r--r--libs/hwui/shaders/drawTexture.frag12
-rw-r--r--libs/hwui/shaders/drawTexture.vert20
-rw-r--r--tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java52
10 files changed, 332 insertions, 53 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 5c24058..aafd3ff 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -278,30 +278,34 @@ class GLES20Canvas extends Canvas {
@Override
public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
- // TODO: Implement
- return 0;
+ return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
}
@Override
public int saveLayer(float left, float top, float right, float bottom, Paint paint,
int saveFlags) {
- // TODO: Implement
- return 0;
+ int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
}
+ private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
+ int paint, int saveFlags);
+
@Override
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
- // TODO: Implement
- return 0;
+ return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+ alpha, saveFlags);
}
@Override
public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
int saveFlags) {
- // TODO: Implement
- return 0;
+ return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
}
+ private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
+ float bottom, int alpha, int saveFlags);
+
@Override
public void restore() {
nRestore(mRenderer);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index d3b6558..fd9ce44 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -92,6 +92,22 @@ static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canv
}
// ----------------------------------------------------------------------------
+// Layers
+// ----------------------------------------------------------------------------
+
+static jint android_view_GLES20Renderer_saveLayer(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
+ SkPaint* paint, jint saveFlags) {
+ return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
+}
+
+static jint android_view_GLES20Renderer_saveLayerAlpha(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
+ jint alpha, jint saveFlags) {
+ return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
+}
+
+// ----------------------------------------------------------------------------
// Clipping
// ----------------------------------------------------------------------------
@@ -178,30 +194,33 @@ static void android_view_GLES20Renderer_drawRect(JNIEnv* env, jobject canvas,
const char* const kClassPathName = "android/view/GLES20Canvas";
static JNINativeMethod gMethods[] = {
- { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer },
- { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer },
- { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport },
- { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare },
-
- { "nSave", "(II)I", (void*) android_view_GLES20Renderer_save },
- { "nRestore", "(I)V", (void*) android_view_GLES20Renderer_restore },
- { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Renderer_restoreToCount },
- { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Renderer_getSaveCount },
-
- { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Renderer_quickReject },
- { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF },
- { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect },
-
- { "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate },
- { "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate },
- { "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale },
-
- { "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix },
- { "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix },
- { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix },
-
- { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor },
- { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Renderer_drawRect },
+ { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer },
+ { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer },
+ { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport },
+ { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare },
+
+ { "nSave", "(II)I", (void*) android_view_GLES20Renderer_save },
+ { "nRestore", "(I)V", (void*) android_view_GLES20Renderer_restore },
+ { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Renderer_restoreToCount },
+ { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Renderer_getSaveCount },
+
+ { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Renderer_saveLayer },
+ { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Renderer_saveLayerAlpha },
+
+ { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Renderer_quickReject },
+ { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF },
+ { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect },
+
+ { "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate },
+ { "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate },
+ { "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale },
+
+ { "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix },
+ { "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix },
+ { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix },
+
+ { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor },
+ { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Renderer_drawRect },
{ "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
(void*) android_view_GLES20Renderer_getClipBounds },
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index c772f00..e9c7791 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -97,6 +97,14 @@ void Matrix4::copyTo(float* v) const {
memcpy(v, data, sizeof(data));
}
+float Matrix4::getTranslateX() {
+ return data[12];
+}
+
+float Matrix4::getTranslateY() {
+ return data[13];
+}
+
void Matrix4::loadTranslate(float x, float y, float z) {
loadIdentity();
data[12] = x;
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index fa9638b..40c80fa 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -90,6 +90,9 @@ public:
void mapRect(Rect& r) const;
+ float getTranslateX();
+ float getTranslateY();
+
void dump() const;
private:
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 830e0c3..786b927 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, &current->fbo);
+ glDeleteTextures(1, &current->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
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 6f6b997..527bf3e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -45,12 +45,17 @@ public:
transform(s->transform),
clipRect(s->clipRect),
flags(kFlagDirtyTransform),
- previous(s) {
+ 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();
@@ -67,6 +72,12 @@ public:
// 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;
@@ -76,7 +87,10 @@ struct SimpleVertex {
float position[2];
}; // struct SimpleVertex
-typedef char* shader;
+struct TextureVertex {
+ float position[2];
+ float texture[2];
+}; // struct TextureVertex
class Program: public LightRefBase<Program> {
public:
@@ -110,6 +124,7 @@ private:
class DrawColorProgram: public Program {
public:
DrawColorProgram();
+ DrawColorProgram(const char* vertex, const char* fragment);
void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
const GLfloat* transformMatrix);
@@ -120,6 +135,17 @@ public:
int projection;
int modelView;
int transform;
+
+protected:
+ void getAttribsAndUniforms();
+};
+
+class DrawTextureProgram: public DrawColorProgram {
+public:
+ DrawTextureProgram();
+
+ int sampler;
+ int texCoords;
};
///////////////////////////////////////////////////////////////////////////////
@@ -139,6 +165,9 @@ public:
void restore();
void restoreToCount(int saveCount);
+ int saveLayer(float left, float top, float right, float bottom, const SkPaint* p, int flags);
+ int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags);
+
void translate(float dx, float dy);
void rotate(float degrees);
void scale(float sx, float sy);
@@ -152,7 +181,7 @@ public:
bool clipRect(float left, float top, float right, float bottom);
void drawColor(int color, SkXfermode::Mode mode);
- void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
+ void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
private:
int saveSnapshot();
@@ -161,6 +190,8 @@ private:
void setScissorFromClip();
void drawColorRect(float left, float top, float right, float bottom, int color);
+ void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
+ float alpha);
// Dimensions of the drawing surface
int mWidth, mHeight;
@@ -180,6 +211,7 @@ private:
// Shaders
sp<DrawColorProgram> mDrawColorShader;
+ sp<DrawTextureProgram> mDrawTextureShader;
}; // class OpenGLRenderer
}; // namespace uirenderer
diff --git a/libs/hwui/shaders/drawColor.frag b/libs/hwui/shaders/drawColor.frag
index f753abb..e84c47b 100644
--- a/libs/hwui/shaders/drawColor.frag
+++ b/libs/hwui/shaders/drawColor.frag
@@ -1,8 +1,6 @@
SHADER_SOURCE(gDrawColorFragmentShader,
-precision mediump float;
-
-varying vec4 outColor;
+varying lowp vec4 outColor;
void main(void) {
gl_FragColor = outColor;
diff --git a/libs/hwui/shaders/drawTexture.frag b/libs/hwui/shaders/drawTexture.frag
new file mode 100644
index 0000000..5bd420e
--- /dev/null
+++ b/libs/hwui/shaders/drawTexture.frag
@@ -0,0 +1,12 @@
+SHADER_SOURCE(gDrawTextureFragmentShader,
+
+varying lowp vec4 outColor;
+varying mediump vec2 outTexCoords;
+
+uniform sampler2D sampler;
+
+void main(void) {
+ gl_FragColor = texture2D(sampler, outTexCoords) * outColor;
+}
+
+);
diff --git a/libs/hwui/shaders/drawTexture.vert b/libs/hwui/shaders/drawTexture.vert
new file mode 100644
index 0000000..310a812
--- /dev/null
+++ b/libs/hwui/shaders/drawTexture.vert
@@ -0,0 +1,20 @@
+SHADER_SOURCE(gDrawTextureVertexShader,
+
+attribute vec4 position;
+attribute vec2 texCoords;
+attribute vec4 color;
+
+uniform mat4 projection;
+uniform mat4 modelView;
+uniform mat4 transform;
+
+varying vec4 outColor;
+varying vec2 outTexCoords;
+
+void main(void) {
+ outColor = color;
+ outTexCoords = texCoords;
+ gl_Position = projection * transform * modelView * position;
+}
+
+);
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java
index 14154a8..85e3997 100644
--- a/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/HwUiActivity.java
@@ -22,7 +22,11 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
+import android.view.Gravity;
import android.view.View;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.widget.FrameLayout;
@SuppressWarnings({"UnusedDeclaration"})
public class HwUiActivity extends Activity {
@@ -32,7 +36,19 @@ public class HwUiActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(new DirtyBitmapView(this));
+ DirtyBitmapView container = new DirtyBitmapView(this);
+
+ ColorView color = new ColorView(this);
+ container.addView(color, new DirtyBitmapView.LayoutParams(
+ dipToPx(this, 100), dipToPx(this, 100), Gravity.CENTER));
+
+ AlphaAnimation a = new AlphaAnimation(1.0f, 0.0f);
+ a.setDuration(2000);
+ a.setRepeatCount(Animation.INFINITE);
+ a.setRepeatMode(Animation.REVERSE);
+ color.startAnimation(a);
+
+ setContentView(container);
}
@SuppressWarnings({"UnusedDeclaration"})
@@ -40,7 +56,19 @@ public class HwUiActivity extends Activity {
return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f);
}
- static class DirtyBitmapView extends View {
+ static class ColorView extends View {
+ ColorView(Context c) {
+ super(c);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawRGB(0, 255, 0);
+ }
+ }
+
+ static class DirtyBitmapView extends FrameLayout {
private final Paint mPaint;
DirtyBitmapView(Context c) {
@@ -49,9 +77,7 @@ public class HwUiActivity extends Activity {
}
@Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
+ public void dispatchDraw(Canvas canvas) {
canvas.drawRGB(255, 255, 255);
mPaint.setColor(0xffff0000);
@@ -86,6 +112,7 @@ public class HwUiActivity extends Activity {
Canvas.EdgeType.BW));
canvas.restore();
+ canvas.save();
canvas.scale(2.0f, 2.0f);
canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
@@ -94,6 +121,21 @@ public class HwUiActivity extends Activity {
mPaint.setColor(0xff0000ff);
canvas.drawRect(20.0f, 0.0f, 40.0f, 20.0f, mPaint);
+
+ canvas.restore();
+
+ final int restoreTo = canvas.save();
+ canvas.saveLayerAlpha(0.0f, 100.0f, getWidth(), 150.0f, 127,
+ Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ mPaint.setColor(0xff0000ff);
+ canvas.drawRect(0.0f, 100.0f, 40.0f, 150.0f, mPaint);
+ mPaint.setColor(0xff00ffff);
+ canvas.drawRect(40.0f, 100.0f, 140.0f, 150.0f, mPaint);
+ mPaint.setColor(0xffff00ff);
+ canvas.drawRect(140.0f, 100.0f, 240.0f, 150.0f, mPaint);
+ canvas.restoreToCount(restoreTo);
+
+ super.dispatchDraw(canvas);
}
}
}