diff options
author | Romain Guy <romainguy@google.com> | 2010-07-19 18:43:02 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2010-07-19 18:44:05 -0700 |
commit | c0ac193b9415680f0a69e20a3f5f22d16f8053be (patch) | |
tree | 9a1d680ad20ba3f6ec0924c6b445290696d63b8c | |
parent | 9d339c13aaa30ddfd51d0f13f8ab22af05e40ea0 (diff) | |
download | frameworks_base-c0ac193b9415680f0a69e20a3f5f22d16f8053be.zip frameworks_base-c0ac193b9415680f0a69e20a3f5f22d16f8053be.tar.gz frameworks_base-c0ac193b9415680f0a69e20a3f5f22d16f8053be.tar.bz2 |
Add support for linear gradients.
Change-Id: Id15329da065045b3f06fdaed615f33cd57608496
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 4 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
-rw-r--r-- | libs/hwui/GradientCache.cpp | 160 | ||||
-rw-r--r-- | libs/hwui/GradientCache.h | 89 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 93 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 19 | ||||
-rw-r--r-- | libs/hwui/Program.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Program.h | 11 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/shaders/drawLinearGradient.vert | 6 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/google/android/test/hwui/ShadersActivity.java | 2 |
12 files changed, 374 insertions, 22 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index ef9709e..b811b7b 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -633,7 +633,7 @@ class GLES20Canvas extends Canvas { } else if (shader instanceof LinearGradient) { final LinearGradient ls = (LinearGradient) shader; nSetupLinearShader(mRenderer, ls.native_instance, ls.bounds, ls.colors, - ls.positions, ls.tileMode, ls.mLocalMatrix); + ls.positions, ls.count, ls.tileMode, ls.mLocalMatrix); return true; } else if (shader instanceof RadialGradient) { // TODO: Implement @@ -645,7 +645,7 @@ class GLES20Canvas extends Canvas { } private native void nSetupLinearShader(int renderer, int shader, int bounds, - int colors, int positions, int tileMode, int localMatrix); + int colors, int positions, int count, int tileMode, int localMatrix); private native void nSetupBitmapShader(int renderer, int shader, int bitmap, int tileX, int tileY, int matrix); private native void nResetShader(int renderer); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index e419ec8..d177e1a 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -240,9 +240,9 @@ static void android_view_GLES20Canvas_setupBitmapShader(JNIEnv* env, jobject can static void android_view_GLES20Canvas_setupLinearShader(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, SkShader* shader, float* bounds, uint32_t* colors, - float* positions, SkShader::TileMode tileMode, SkMatrix* matrix) { - renderer->setupLinearGradientShader(shader, bounds, colors, positions, tileMode, - matrix, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); + float* positions, int count, SkShader::TileMode tileMode, SkMatrix* matrix) { + renderer->setupLinearGradientShader(shader, bounds, colors, positions, count, + tileMode, matrix, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0); } // ---------------------------------------------------------------------------- @@ -286,7 +286,7 @@ static JNINativeMethod gMethods[] = { { "nResetShader", "(I)V", (void*) android_view_GLES20Canvas_resetShader }, { "nSetupBitmapShader", "(IIIIII)V", (void*) android_view_GLES20Canvas_setupBitmapShader }, - { "nSetupLinearShader", "(IIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader }, + { "nSetupLinearShader", "(IIIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader }, { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds }, diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 809f74d6..1bdb9d3 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -2,6 +2,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ + GradientCache.cpp \ LayerCache.cpp \ Matrix.cpp \ OpenGLRenderer.cpp \ diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp new file mode 100644 index 0000000..aeda416 --- /dev/null +++ b/libs/hwui/GradientCache.cpp @@ -0,0 +1,160 @@ +/* + * 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 <GLES2/gl2.h> + +#include <SkCanvas.h> +#include <SkGradientShader.h> + +#include "GradientCache.h" + +namespace android { +namespace uirenderer { + +/////////////////////////////////////////////////////////////////////////////// +// Constructors/destructor +/////////////////////////////////////////////////////////////////////////////// + +GradientCache::GradientCache(uint32_t maxByteSize): + mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity), + mSize(0), mMaxSize(maxByteSize) { + mCache.setOnEntryRemovedListener(this); +} + +GradientCache::~GradientCache() { + mCache.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Size management +/////////////////////////////////////////////////////////////////////////////// + +uint32_t GradientCache::getSize() { + return mSize; +} + +uint32_t GradientCache::getMaxSize() { + return mMaxSize; +} + +void GradientCache::setMaxSize(uint32_t maxSize) { + mMaxSize = maxSize; + while (mSize > mMaxSize) { + mCache.removeOldest(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Callbacks +/////////////////////////////////////////////////////////////////////////////// + +void GradientCache::operator()(SkShader*& shader, Texture*& texture) { + if (shader) { + const uint32_t size = texture->width * texture->height * 4; + mSize -= size; + } + + if (texture) { + glDeleteTextures(1, &texture->id); + delete texture; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Caching +/////////////////////////////////////////////////////////////////////////////// + +Texture* GradientCache::get(SkShader* shader) { + Texture* texture = mCache.get(shader); + return texture; +} + +void GradientCache::remove(SkShader* shader) { + mCache.remove(shader); +} + +void GradientCache::clear() { + mCache.clear(); +} + +Texture* GradientCache::addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, + float* positions, int count, SkShader::TileMode tileMode) { + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1); + bitmap.allocPixels(); + bitmap.eraseColor(0); + + SkCanvas canvas(bitmap); + + SkPoint points[2]; + points[0].set(0.0f, 0.0f); + points[1].set(bitmap.width(), 0.0f); + + SkShader* localShader = SkGradientShader::CreateLinear(points, + reinterpret_cast<const SkColor*>(colors), positions, count, tileMode); + + SkPaint p; + p.setStyle(SkPaint::kStrokeAndFill_Style); + p.setShader(localShader)->unref(); + + canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p); + + // Asume the cache is always big enough + const uint32_t size = bitmap.rowBytes() * bitmap.height(); + while (mSize + size > mMaxSize) { + mCache.removeOldest(); + } + + Texture* texture = new Texture; + generateTexture(&bitmap, texture); + + mSize += size; + mCache.put(shader, texture); + + return texture; +} + +void GradientCache::generateTexture(SkBitmap* bitmap, Texture* texture) { + SkAutoLockPixels autoLock(*bitmap); + if (!bitmap->readyToDraw()) { + LOGE("Cannot generate texture from shader"); + return; + } + + texture->generation = bitmap->getGenerationID(); + texture->width = bitmap->width(); + texture->height = bitmap->height(); + + glGenTextures(1, &texture->id); + + glBindTexture(GL_TEXTURE_2D, texture->id); + glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); + + texture->blend = !bitmap->isOpaque(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h new file mode 100644 index 0000000..12c8a23 --- /dev/null +++ b/libs/hwui/GradientCache.h @@ -0,0 +1,89 @@ +/* + * 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. + */ + +#ifndef ANDROID_UI_GRADIENT_CACHE_H +#define ANDROID_UI_GRADIENT_CACHE_H + +#include <SkShader.h> + +#include "Texture.h" +#include "GenerationCache.h" + +namespace android { +namespace uirenderer { + +/** + * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. + * Any texture added to the cache causing the cache to grow beyond the maximum + * allowed size will also cause the oldest texture to be kicked out. + */ +class GradientCache: public OnEntryRemoved<SkShader*, Texture*> { +public: + GradientCache(uint32_t maxByteSize); + ~GradientCache(); + + /** + * Used as a callback when an entry is removed from the cache. + * Do not invoke directly. + */ + void operator()(SkShader*& shader, Texture*& texture); + + /** + * Adds a new linear gradient to the cache. The generated texture is + * returned. + */ + Texture* addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors, + float* positions, int count, SkShader::TileMode tileMode); + /** + * Returns the texture associated with the specified shader. + */ + Texture* get(SkShader* shader); + /** + * Removes the texture associated with the specified shader. Returns NULL + * if the texture cannot be found. Upon remove the texture is freed. + */ + void remove(SkShader* shader); + /** + * Clears the cache. This causes all textures to be deleted. + */ + void clear(); + + /** + * Sets the maximum size of the cache in bytes. + */ + void setMaxSize(uint32_t maxSize); + /** + * Returns the maximum size of the cache in bytes. + */ + uint32_t getMaxSize(); + /** + * Returns the current size of the cache in bytes. + */ + uint32_t getSize(); + +private: + void generateTexture(SkBitmap* bitmap, Texture* texture); + + GenerationCache<SkShader*, Texture*> mCache; + + uint32_t mSize; + uint32_t mMaxSize; +}; // class GradientCache + +}; // namespace uirenderer +}; // namespace android + +#endif // ANDROID_UI_GRADIENT_CACHE_H diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 731862b..e39385a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -37,10 +37,12 @@ namespace uirenderer { // These properties are defined in mega-bytes #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size" #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size" +#define PROPERTY_GRADIENT_CACHE_SIZE "ro.hwui.gradient_cache_size" -#define DEFAULT_TEXTURE_CACHE_SIZE 20 -#define DEFAULT_LAYER_CACHE_SIZE 10 +#define DEFAULT_TEXTURE_CACHE_SIZE 20.0f +#define DEFAULT_LAYER_CACHE_SIZE 10.0f #define DEFAULT_PATCH_CACHE_SIZE 100 +#define DEFAULT_GRADIENT_CACHE_SIZE 0.5f // Converts a number of mega-bytes into bytes #define MB(s) s * 1024 * 1024 @@ -104,22 +106,30 @@ OpenGLRenderer::OpenGLRenderer(): mBlend(false), mLastSrcMode(GL_ZERO), mLastDstMode(GL_ZERO), mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)), mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)), + mGradientCache(MB(DEFAULT_GRADIENT_CACHE_SIZE)), mPatchCache(DEFAULT_PATCH_CACHE_SIZE) { LOGD("Create OpenGLRenderer"); char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { LOGD(" Setting texture cache size to %sMB", property); - mTextureCache.setMaxSize(MB(atoi(property))); + mTextureCache.setMaxSize(MB(atof(property))); } else { - LOGD(" Using default texture cache size of %dMB", DEFAULT_TEXTURE_CACHE_SIZE); + LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); } if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) { LOGD(" Setting layer cache size to %sMB", property); - mLayerCache.setMaxSize(MB(atoi(property))); + mLayerCache.setMaxSize(MB(atof(property))); } else { - LOGD(" Using default layer cache size of %dMB", DEFAULT_LAYER_CACHE_SIZE); + LOGD(" Using default layer cache size of %.2fMB", DEFAULT_LAYER_CACHE_SIZE); + } + + if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) { + LOGD(" Setting gradient cache size to %sMB", property); + mLayerCache.setMaxSize(MB(atof(property))); + } else { + LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE); } mDrawColorProgram = new DrawColorProgram; @@ -143,6 +153,7 @@ OpenGLRenderer::~OpenGLRenderer() { mTextureCache.clear(); mLayerCache.clear(); + mGradientCache.clear(); mPatchCache.clear(); } @@ -538,8 +549,9 @@ void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tile mShaderMatrix = matrix; } -void OpenGLRenderer::setupLinearGradientShader(SkShader* shader, float* bounds,uint32_t* colors, - float* positions, SkShader::TileMode tileMode, SkMatrix* matrix, bool hasAlpha) { +void OpenGLRenderer::setupLinearGradientShader(SkShader* shader, float* bounds, uint32_t* colors, + float* positions, int count, SkShader::TileMode tileMode, SkMatrix* matrix, + bool hasAlpha) { // TODO: We should use a struct to describe each shader mShader = OpenGLRenderer::kShaderLinearGradient; mShaderKey = shader; @@ -550,6 +562,7 @@ void OpenGLRenderer::setupLinearGradientShader(SkShader* shader, float* bounds,u mShaderBounds = bounds; mShaderColors = colors; mShaderPositions = positions; + mShaderCount = count; } /////////////////////////////////////////////////////////////////////////////// @@ -566,21 +579,22 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot // Render using pre-multiplied alpha const int alpha = (color >> 24) & 0xFF; const GLfloat a = alpha / 255.0f; - const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; - const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; - const GLfloat b = a * ((color ) & 0xFF) / 255.0f; switch (mShader) { case OpenGLRenderer::kShaderBitmap: drawBitmapShader(left, top, right, bottom, a, mode); return; case OpenGLRenderer::kShaderLinearGradient: - // TODO: Generate gradient texture, set appropriate shader - break; + drawLinearGradientShader(left, top, right, bottom, a, mode); + return; default: break; } + const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; + const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; + const GLfloat b = a * ((color ) & 0xFF) / 255.0f; + // Pre-multiplication happens when setting the shader color chooseBlending(alpha < 255 || mShaderBlend, mode); @@ -605,6 +619,58 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount); } +void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right, float bottom, + float alpha, SkXfermode::Mode mode) { + Texture* texture = mGradientCache.get(mShaderKey); + if (!texture) { + texture = mGradientCache.addLinearGradient(mShaderKey, mShaderBounds, mShaderColors, + mShaderPositions, mShaderCount, mShaderTileX); + } + + mModelView.loadTranslate(left, top, 0.0f); + mModelView.scale(right - left, bottom - top, 1.0f); + + useProgram(mDrawLinearGradientProgram); + mDrawLinearGradientProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); + + chooseBlending(mShaderBlend || alpha < 1.0f, mode); + + if (texture->id != mLastTexture) { + glBindTexture(GL_TEXTURE_2D, texture->id); + mLastTexture = texture->id; + } + // TODO: Don't set the texture parameters every time + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gTileModes[mShaderTileX]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gTileModes[mShaderTileX]); + + Rect start(mShaderBounds[0], mShaderBounds[1], mShaderBounds[2], mShaderBounds[3]); + if (mShaderMatrix) { + mat4 shaderMatrix(*mShaderMatrix); + shaderMatrix.mapRect(start); + } + mSnapshot->transform.mapRect(start); + + const float gradientX = start.right - start.left; + const float gradientY = start.bottom - start.top; + + mat4 screenSpace(mSnapshot->transform); + screenSpace.multiply(mModelView); + + // Always premultiplied + glUniform4f(mDrawLinearGradientProgram->color, alpha, alpha, alpha, alpha); + glUniform2f(mDrawLinearGradientProgram->start, start.left, start.top); + glUniform2f(mDrawLinearGradientProgram->gradient, gradientX, gradientY); + glUniform1f(mDrawLinearGradientProgram->gradientLength, + 1.0f / (gradientX * gradientX + gradientY * gradientY)); + glUniformMatrix4fv(mDrawLinearGradientProgram->screenSpace, 1, GL_FALSE, + &screenSpace.data[0]); + + glVertexAttribPointer(mDrawLinearGradientProgram->position, 2, GL_FLOAT, GL_FALSE, + gDrawTextureVertexStride, &mDrawTextureVertices[0].position[0]); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount); +} + void OpenGLRenderer::drawBitmapShader(float left, float top, float right, float bottom, float alpha, SkXfermode::Mode mode) { const Texture* texture = mTextureCache.get(mShaderBitmap); @@ -680,6 +746,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gTileModes[mShaderTileY]); // Always premultiplied + //glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha); glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha); glVertexAttribPointer(mDrawTextureProgram->position, 2, GL_FLOAT, GL_FALSE, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 5a530eb..dd7999d 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -36,6 +36,7 @@ #include "Snapshot.h" #include "TextureCache.h" #include "LayerCache.h" +#include "GradientCache.h" #include "PatchCache.h" #include "Vertex.h" @@ -104,7 +105,8 @@ public: void setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix, bool hasAlpha); void setupLinearGradientShader(SkShader* shader, float* bounds, uint32_t* colors, - float* positions, SkShader::TileMode tileMode, SkMatrix* matrix, bool hasAlpha); + float* positions, int count, SkShader::TileMode tileMode, + SkMatrix* matrix, bool hasAlpha); private: /** @@ -249,6 +251,19 @@ private: SkXfermode::Mode mode); /** + * Fills the specified rectangle with the currently set linear gradient shader. + * + * @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 alpha An additional translucency parameter, between 0.0f and 1.0f + * @param mode The blending mode + */ + void drawLinearGradientShader(float left, float top, float right, float bottom, float alpha, + SkXfermode::Mode mode); + + /** * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values * back to default is achieved by calling: * @@ -335,10 +350,12 @@ private: float* mShaderBounds; uint32_t* mShaderColors; float* mShaderPositions; + int mShaderCount; // Various caches TextureCache mTextureCache; LayerCache mLayerCache; + GradientCache mGradientCache; PatchCache mPatchCache; }; // class OpenGLRenderer diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp index 6202ba3..841b6c8 100644 --- a/libs/hwui/Program.cpp +++ b/libs/hwui/Program.cpp @@ -190,6 +190,8 @@ DrawLinearGradientProgram::DrawLinearGradientProgram(): gradient = addUniform("gradient"); gradientLength = addUniform("gradientLength"); sampler = addUniform("sampler"); + start = addUniform("start"); + screenSpace = addUniform("screenSpace"); } void DrawLinearGradientProgram::use() { diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index d7970d9..18a8e92 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -213,6 +213,17 @@ public: virtual void remove(); /** + * Name of the matrix used to compute the screen space coordinates + * of the vertices. + */ + int screenSpace; + + /** + * Name of the linear gradient start point. + */ + int start; + + /** * Name of the linear gradient vector. */ int gradient; diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index ff7d7c9..ff9e2af 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -97,6 +97,7 @@ Texture* TextureCache::get(SkBitmap* bitmap) { } else if (bitmap->getGenerationID() != texture->generation) { generateTexture(bitmap, texture, true); } + // TODO: Do something to destroy the texture object if it's too big for the cache return texture; } diff --git a/libs/hwui/shaders/drawLinearGradient.vert b/libs/hwui/shaders/drawLinearGradient.vert index 963dc87..f5c669b 100644 --- a/libs/hwui/shaders/drawLinearGradient.vert +++ b/libs/hwui/shaders/drawLinearGradient.vert @@ -4,13 +4,17 @@ attribute vec4 position; uniform float gradientLength; uniform vec2 gradient; +uniform vec2 start; uniform mat4 transform; +uniform mat4 screenSpace; varying float index; void main(void) { + vec4 location = screenSpace * position; + index = dot(location.xy - start, gradient) * gradientLength; + gl_Position = transform * position; - index = dot(gl_Position.xy, gradient) * gradientLength; } ); diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/ShadersActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/ShadersActivity.java index 851a06c..1912245 100644 --- a/tests/HwAccelerationTest/src/com/google/android/test/hwui/ShadersActivity.java +++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/ShadersActivity.java @@ -91,7 +91,7 @@ public class ShadersActivity extends Activity { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - canvas.drawRGB(255, 255, 255); + //canvas.drawRGB(255, 255, 255); // Bitmap shaders canvas.save(); |