diff options
author | Romain Guy <romainguy@google.com> | 2010-08-02 18:50:22 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2010-08-02 18:50:56 -0700 |
commit | db1938e0e6ef816e228c815adccebd5cb05f2aa8 (patch) | |
tree | d40e91a873bca6750083fdb1713a12b469ebad4d /libs/hwui | |
parent | 16f8c620abd0ea07e704b6997a66a45ad3590dea (diff) | |
download | frameworks_base-db1938e0e6ef816e228c815adccebd5cb05f2aa8.zip frameworks_base-db1938e0e6ef816e228c815adccebd5cb05f2aa8.tar.gz frameworks_base-db1938e0e6ef816e228c815adccebd5cb05f2aa8.tar.bz2 |
Add support for ColorFilters.
Color filters are fully supported and can be used with shaders.
Change-Id: Id90ccf1c81cb462f2431f366f3f8f710d7971e04
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
-rw-r--r-- | libs/hwui/Extensions.h | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 39 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 7 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 37 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.h | 4 | ||||
-rw-r--r-- | libs/hwui/SkiaColorFilter.cpp | 102 | ||||
-rw-r--r-- | libs/hwui/SkiaColorFilter.h | 118 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.h | 6 |
9 files changed, 298 insertions, 18 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index fe1b524..8f28612 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -11,6 +11,7 @@ LOCAL_SRC_FILES:= \ PatchCache.cpp \ Program.cpp \ ProgramCache.cpp \ + SkiaColorFilter.cpp \ SkiaShader.cpp \ TextureCache.cpp diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index 99b34dd..7778290 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "OpenGLRenderer" - #ifndef ANDROID_UI_EXTENSIONS_H #define ANDROID_UI_EXTENSIONS_H diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 187e9d8..d694039 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -132,6 +132,7 @@ OpenGLRenderer::OpenGLRenderer(): mCurrentProgram = NULL; mShader = NULL; + mColorFilter = NULL; memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); @@ -460,7 +461,6 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const float u2 = srcRight / width; const float v2 = srcBottom / height; - // TODO: Do this in the shader resetDrawTextureTexCoords(u1, v1, u2, v2); drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint); @@ -552,6 +552,8 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, mModelView.loadIdentity(); GLuint textureUnit = 0; + // Needs to be set prior to calling FontRenderer::getTexture() + glActiveTexture(gTextureUnits[textureUnit]); ProgramDescription description; description.hasTexture = true; @@ -559,10 +561,14 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, if (mShader) { mShader->describe(description, mExtensions); } + if (mColorFilter) { + mColorFilter->describe(description, mExtensions); + } useProgram(mProgramCache.get(description)); mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); + // Text is always blended, no need to check the shader chooseBlending(true, mode); bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); @@ -578,6 +584,9 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } + if (mColorFilter) { + mColorFilter->setupProgram(mCurrentProgram); + } // TODO: Implement scale properly const Rect& clip = mSnapshot->getLocalClip(); @@ -604,6 +613,18 @@ void OpenGLRenderer::setupShader(SkiaShader* shader) { } /////////////////////////////////////////////////////////////////////////////// +// Color filters +/////////////////////////////////////////////////////////////////////////////// + +void OpenGLRenderer::resetColorFilter() { + mColorFilter = NULL; +} + +void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) { + mColorFilter = filter; +} + +/////////////////////////////////////////////////////////////////////////////// // Drawing implementation /////////////////////////////////////////////////////////////////////////////// @@ -631,6 +652,9 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot if (mShader) { mShader->describe(description, mExtensions); } + if (mColorFilter) { + mColorFilter->describe(description, mExtensions); + } // Build and use the appropriate shader useProgram(mProgramCache.get(description)); @@ -654,6 +678,9 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } + if (mColorFilter) { + mColorFilter->setupProgram(mCurrentProgram); + } // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); @@ -680,6 +707,9 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) { ProgramDescription description; description.hasTexture = true; + if (mColorFilter) { + mColorFilter->describe(description, mExtensions); + } mModelView.loadTranslate(left, top, 0.0f); mModelView.scale(right - left, bottom - top, 1.0f); @@ -703,6 +733,11 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b gMeshStride, vertices); glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); + // Color filter + if (mColorFilter) { + mColorFilter->setupProgram(mCurrentProgram); + } + if (!indices) { glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); } else { @@ -712,8 +747,6 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b } void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) { - // In theory we should not blend if the mode is Src, but it's rare enough - // that it's not worth it blend = blend || mode != SkXfermode::kSrcOver_Mode; if (blend) { if (!mBlend) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index dc0f50f..d2a291f 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -43,6 +43,7 @@ #include "FontRenderer.h" #include "ProgramCache.h" #include "SkiaShader.h" +#include "SkiaColorFilter.h" namespace android { namespace uirenderer { @@ -95,6 +96,9 @@ public: void resetShader(); void setupShader(SkiaShader* shader); + void resetColorFilter(); + void setupColorFilter(SkiaColorFilter* filter); + void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint); private: @@ -281,6 +285,9 @@ private: Program* mCurrentProgram; SkiaShader* mShader; + // Color filters + SkiaColorFilter* mColorFilter; + // Used to draw textured quads TextureVertex mMeshVertices[4]; diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 23923f6..3205258 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -27,8 +27,6 @@ namespace uirenderer { // Vertex shaders snippets /////////////////////////////////////////////////////////////////////////////// -// TODO: Implement BitmapShader, implement repeat/mirror for npot - const char* gVS_Header_Attributes = "attribute vec4 position;\n"; const char* gVS_Header_Attributes_TexCoords = @@ -85,10 +83,10 @@ const char* gFS_Uniforms_ColorOp[4] = { "uniform mat4 colorMatrix;\n" "uniform vec4 colorMatrixVector;\n", // Lighting - "uniform float lightingMul;\n" - "uniform float lightingAdd;\n", + "uniform vec4 lightingMul;\n" + "uniform vec4 lightingAdd;\n", // PorterDuff - "uniform vec4 colorBLend;\n" + "uniform vec4 colorBlend;\n" }; const char* gFS_Main = "\nvoid main(void) {\n" @@ -121,11 +119,14 @@ const char* gFS_Main_ApplyColorOp[4] = { // None "", // Matrix + // TODO: Fix premultiplied alpha computations for color matrix " fragColor *= colorMatrix;\n" - " fragColor += colorMatrixVector;\n", + " fragColor += colorMatrixVector;\n" + " fragColor.rgb *= fragColor.a;\n", // Lighting - " fragColor *= lightingMul;\n" - " fragColor += lightingAdd;\n", + " float lightingAlpha = fragColor.a;\n" + " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n" + " fragColor.a = lightingAlpha;\n", // PorterDuff " fragColor = blendColors(colorBlend, fragColor);\n" }; @@ -345,7 +346,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // End the shader shader.append(gFS_Footer); - PROGRAM_LOGD("*** Generated fragment shader:\n\n%s", shader.string()); + if (DEBUG_PROGRAM_CACHE) { + PROGRAM_LOGD("*** Generated fragment shader:\n\n"); + printLongString(shader); + } + return shader; } @@ -391,5 +396,19 @@ void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wra shader.append("}\n"); } +void ProgramCache::printLongString(const String8& shader) const { + ssize_t index = 0; + ssize_t lastIndex = 0; + const char* str = shader.string(); + while ((index = shader.find("\n", index)) > -1) { + String8 line(str, index - lastIndex); + if (line.length() == 0) line.append("\n"); + PROGRAM_LOGD("%s", line.string()); + index++; + str += (index - lastIndex); + lastIndex = index; + } +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index d60f6ce..a1a4a0e 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -35,7 +35,7 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Debug -#define DEBUG_PROGRAM_CACHE 1 +#define DEBUG_PROGRAM_CACHE 0 // Debug #if DEBUG_PROGRAM_CACHE @@ -180,6 +180,8 @@ private: void generatePorterDuffBlend(String8& shader, const char* name, SkXfermode::Mode mode); void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT); + void printLongString(const String8& shader) const; + KeyedVector<programid, Program*> mCache; }; // class ProgramCache diff --git a/libs/hwui/SkiaColorFilter.cpp b/libs/hwui/SkiaColorFilter.cpp new file mode 100644 index 0000000..fe57ae7 --- /dev/null +++ b/libs/hwui/SkiaColorFilter.cpp @@ -0,0 +1,102 @@ +/* + * 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. + */ + +#include "SkiaColorFilter.h" + +namespace android { +namespace uirenderer { + +/////////////////////////////////////////////////////////////////////////////// +// Base color filter +/////////////////////////////////////////////////////////////////////////////// + +SkiaColorFilter::SkiaColorFilter(Type type, bool blend): mType(type), mBlend(blend) { +} + +SkiaColorFilter::~SkiaColorFilter() { +} + +/////////////////////////////////////////////////////////////////////////////// +// Color matrix filter +/////////////////////////////////////////////////////////////////////////////// + +SkiaColorMatrixFilter::SkiaColorMatrixFilter(float* matrix, float* vector): + SkiaColorFilter(kColorMatrix, true), mMatrix(matrix), mVector(vector) { +} + +SkiaColorMatrixFilter::~SkiaColorMatrixFilter() { + delete[] mMatrix; + delete[] mVector; +} + +void SkiaColorMatrixFilter::describe(ProgramDescription& description, + const Extensions& extensions) { + description.colorOp = ProgramDescription::kColorMatrix; +} + +void SkiaColorMatrixFilter::setupProgram(Program* program) { + glUniformMatrix4fv(program->getUniform("colorMatrix"), 1, GL_FALSE, &mMatrix[0]); + glUniform4fv(program->getUniform("colorMatrixVector"), 1, mVector); +} + +/////////////////////////////////////////////////////////////////////////////// +// Lighting color filter +/////////////////////////////////////////////////////////////////////////////// + +SkiaLightingFilter::SkiaLightingFilter(int multiply, int add): + SkiaColorFilter(kLighting, true) { + mMulR = ((multiply >> 16) & 0xFF) / 255.0f; + mMulG = ((multiply >> 8) & 0xFF) / 255.0f; + mMulB = ((multiply ) & 0xFF) / 255.0f; + + mAddR = ((add >> 16) & 0xFF) / 255.0f; + mAddG = ((add >> 8) & 0xFF) / 255.0f; + mAddB = ((add ) & 0xFF) / 255.0f; +} + +void SkiaLightingFilter::describe(ProgramDescription& description, const Extensions& extensions) { + description.colorOp = ProgramDescription::kColorLighting; +} + +void SkiaLightingFilter::setupProgram(Program* program) { + glUniform4f(program->getUniform("lightingMul"), mMulR, mMulG, mMulB, 1.0f); + glUniform4f(program->getUniform("lightingAdd"), mAddR, mAddG, mAddB, 0.0f); +} + +/////////////////////////////////////////////////////////////////////////////// +// Blend color filter +/////////////////////////////////////////////////////////////////////////////// + +SkiaBlendFilter::SkiaBlendFilter(int color, SkXfermode::Mode mode): + SkiaColorFilter(kBlend, true), mMode(mode) { + const int alpha = (color >> 24) & 0xFF; + mA = alpha / 255.0f; + mR = mA * ((color >> 16) & 0xFF) / 255.0f; + mG = mA * ((color >> 8) & 0xFF) / 255.0f; + mB = mA * ((color ) & 0xFF) / 255.0f; +} + +void SkiaBlendFilter::describe(ProgramDescription& description, const Extensions& extensions) { + description.colorOp = ProgramDescription::kColorBlend; + description.colorMode = mMode; +} + +void SkiaBlendFilter::setupProgram(Program* program) { + glUniform4f(program->getUniform("colorBlend"), mR, mG, mB, mA); +} + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h new file mode 100644 index 0000000..865b6f0 --- /dev/null +++ b/libs/hwui/SkiaColorFilter.h @@ -0,0 +1,118 @@ +/* + * 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_SKIA_COLOR_FILTER_H +#define ANDROID_UI_SKIA_COLOR_FILTER_H + +#include <GLES2/gl2.h> + +#include "ProgramCache.h" +#include "Extensions.h" + +namespace android { +namespace uirenderer { + +/////////////////////////////////////////////////////////////////////////////// +// Base color filter +/////////////////////////////////////////////////////////////////////////////// + +/** + * Represents a Skia color filter. A color filter modifies a ProgramDescription + * and sets uniforms on the resulting shaders. + */ +struct SkiaColorFilter { + /** + * Type of Skia color filter in use. + */ + enum Type { + kNone, + kColorMatrix, + kLighting, + kBlend, + }; + + SkiaColorFilter(Type type, bool blend); + virtual ~SkiaColorFilter(); + + virtual void describe(ProgramDescription& description, const Extensions& extensions) = 0; + virtual void setupProgram(Program* program) = 0; + + inline bool blend() const { + return mBlend; + } + + Type type() const { + return mType; + } + +protected: + Type mType; + bool mBlend; +}; // struct SkiaColorFilter + +/////////////////////////////////////////////////////////////////////////////// +// Implementations +/////////////////////////////////////////////////////////////////////////////// + +/** + * A color filter that multiplies the source color with a matrix and adds a vector. + */ +struct SkiaColorMatrixFilter: public SkiaColorFilter { + SkiaColorMatrixFilter(float* matrix, float* vector); + ~SkiaColorMatrixFilter(); + + void describe(ProgramDescription& description, const Extensions& extensions); + void setupProgram(Program* program); + +private: + float* mMatrix; + float* mVector; +}; // struct SkiaColorMatrixFilter + +/** + * A color filters that multiplies the source color with a fixed value and adds + * another fixed value. Ignores the alpha channel of both arguments. + */ +struct SkiaLightingFilter: public SkiaColorFilter { + SkiaLightingFilter(int multiply, int add); + + void describe(ProgramDescription& description, const Extensions& extensions); + void setupProgram(Program* program); + +private: + GLfloat mMulR, mMulG, mMulB; + GLfloat mAddR, mAddG, mAddB; +}; // struct SkiaLightingFilter + +/** + * A color filters that blends the source color with a specified destination color + * and PorterDuff blending mode. + */ +struct SkiaBlendFilter: public SkiaColorFilter { + SkiaBlendFilter(int color, SkXfermode::Mode mode); + + void describe(ProgramDescription& description, const Extensions& extensions); + void setupProgram(Program* program); + +private: + SkXfermode::Mode mMode; + GLfloat mR, mG, mB, mA; +}; // struct SkiaBlendFilter + +}; // namespace uirenderer +}; // namespace android + +#endif // ANDROID_UI_SKIA_COLOR_FILTER_H diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index b5e6aeb..c19eac3 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef SKIA_SHADER_H -#define SKIA_SHADER_H +#ifndef ANDROID_UI_SKIA_SHADER_H +#define ANDROID_UI_SKIA_SHADER_H #include <SkShader.h> #include <SkXfermode.h> @@ -160,4 +160,4 @@ private: }; // namespace uirenderer }; // namespace android -#endif // SKIA_SHADER_H +#endif // ANDROID_UI_SKIA_SHADER_H |