summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/Extensions.h2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp39
-rw-r--r--libs/hwui/OpenGLRenderer.h7
-rw-r--r--libs/hwui/ProgramCache.cpp37
-rw-r--r--libs/hwui/ProgramCache.h4
-rw-r--r--libs/hwui/SkiaColorFilter.cpp102
-rw-r--r--libs/hwui/SkiaColorFilter.h118
-rw-r--r--libs/hwui/SkiaShader.h6
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