summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/Caches.cpp1
-rw-r--r--libs/hwui/Caches.h2
-rwxr-xr-xlibs/hwui/Dither.cpp84
-rwxr-xr-xlibs/hwui/Dither.h47
-rw-r--r--libs/hwui/ProgramCache.cpp58
-rw-r--r--libs/hwui/SkiaShader.cpp4
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java9
8 files changed, 187 insertions, 19 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index a54c188..1947c32 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -11,6 +11,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
Caches.cpp \
DisplayListLogBuffer.cpp \
DisplayListRenderer.cpp \
+ Dither.cpp \
FboCache.cpp \
GradientCache.cpp \
LayerCache.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 258ced0..aa2bc3f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -252,6 +252,7 @@ void Caches::flush(FlushMode mode) {
dropShadowCache.clear();
gradientCache.clear();
fontRenderer->clear();
+ dither.clear();
// fall through
case kFlushMode_Moderate:
fontRenderer->flush();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 4cbac41..ad1098c 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -38,6 +38,7 @@
#include "TextDropShadowCache.h"
#include "FboCache.h"
#include "ResourceCache.h"
+#include "Dither.h"
namespace android {
namespace uirenderer {
@@ -250,6 +251,7 @@ public:
TextDropShadowCache dropShadowCache;
FboCache fboCache;
ResourceCache resourceCache;
+ Dither dither;
GammaFontRenderer* fontRenderer;
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
new file mode 100755
index 0000000..5817977
--- /dev/null
+++ b/libs/hwui/Dither.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 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 "Caches.h"
+#include "Dither.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Must be a power of two
+#define DITHER_KERNEL_SIZE 4
+
+///////////////////////////////////////////////////////////////////////////////
+// Lifecycle
+///////////////////////////////////////////////////////////////////////////////
+
+void Dither::bindDitherTexture() {
+ if (!mInitialized) {
+ const uint8_t pattern[] = {
+ 0, 8, 2, 10,
+ 12, 4, 14, 6,
+ 3, 11, 1, 9,
+ 15, 7, 13, 5
+ };
+
+ glGenTextures(1, &mDitherTexture);
+ glBindTexture(GL_TEXTURE_2D, mDitherTexture);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+
+ mInitialized = true;
+ } else {
+ glBindTexture(GL_TEXTURE_2D, mDitherTexture);
+ }
+}
+
+void Dither::clear() {
+ if (mInitialized) {
+ glDeleteTextures(1, &mDitherTexture);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Program management
+///////////////////////////////////////////////////////////////////////////////
+
+void Dither::setupProgram(Program* program, GLuint* textureUnit) {
+ GLuint textureSlot = (*textureUnit)++;
+ Caches::getInstance().activeTexture(textureSlot);
+
+ bindDitherTexture();
+
+ glUniform1i(program->getUniform("ditherSampler"), textureSlot);
+ glUniform1f(program->getUniform("ditherSize"), 1.0f / DITHER_KERNEL_SIZE);
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
new file mode 100755
index 0000000..34cf9bf
--- /dev/null
+++ b/libs/hwui/Dither.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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_HWUI_DITHER_H
+#define ANDROID_HWUI_DITHER_H
+
+#include <GLES2/gl2.h>
+
+#include "Program.h"
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * Handles dithering for programs.
+ */
+class Dither {
+public:
+ Dither(): mInitialized(false), mDitherTexture(0) { }
+
+ void clear();
+ void setupProgram(Program* program, GLuint* textureUnit);
+
+private:
+ void bindDitherTexture();
+
+ bool mInitialized;
+ GLuint mDitherTexture;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_DITHER_H
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index d601f01..0e77cb2 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -75,9 +75,11 @@ const char* gVS_Header_Varyings_HasGradient[6] = {
// Linear
"varying highp vec2 linear;\n",
"varying highp float linear;\n",
+
// Circular
"varying highp vec2 circular;\n",
"varying highp vec2 circular;\n",
+
// Sweep
"varying highp vec2 sweep;\n",
"varying highp vec2 sweep;\n",
@@ -92,9 +94,11 @@ const char* gVS_Main_OutGradient[6] = {
// Linear
" linear = vec2((screenSpace * position).x, 0.5);\n",
" linear = (screenSpace * position).x;\n",
+
// Circular
" circular = (screenSpace * position).xy;\n",
" circular = (screenSpace * position).xy;\n",
+
// Sweep
" sweep = (screenSpace * position).xy;\n",
" sweep = (screenSpace * position).xy;\n",
@@ -137,19 +141,24 @@ const char* gFS_Uniforms_TextureSampler =
"uniform sampler2D sampler;\n";
const char* gFS_Uniforms_ExternalTextureSampler =
"uniform samplerExternalOES sampler;\n";
+#define FS_UNIFORMS_DITHER \
+ "uniform float ditherSize;\n" \
+ "uniform sampler2D ditherSampler;\n"
+#define FS_UNIFORMS_GRADIENT \
+ "uniform vec4 startColor;\n" \
+ "uniform vec4 endColor;\n"
const char* gFS_Uniforms_GradientSampler[6] = {
// Linear
- "uniform sampler2D gradientSampler;\n",
- "uniform vec4 startColor;\n"
- "uniform vec4 endColor;\n",
+ FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
+ FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
+
// Circular
- "uniform sampler2D gradientSampler;\n",
- "uniform vec4 startColor;\n"
- "uniform vec4 endColor;\n",
+ FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
+ FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
+
// Sweep
- "uniform sampler2D gradientSampler;\n",
- "uniform vec4 startColor;\n"
- "uniform vec4 endColor;\n",
+ FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
+ FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT
};
const char* gFS_Uniforms_BitmapSampler =
"uniform sampler2D bitmapSampler;\n";
@@ -176,6 +185,11 @@ const char* gFS_Main_PointBitmapTexCoords =
" highp vec2 outBitmapTexCoords = outPointBitmapTexCoords + "
"((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n";
+#define FS_MAIN_DITHER \
+ "texture2D(ditherSampler, gl_FragCoord.xy * ditherSize).a * ditherSize * ditherSize"
+const char* gFS_Main_AddDitherToGradient =
+ " gradientColor += " FS_MAIN_DITHER ";\n";
+
// Fast cases
const char* gFS_Fast_SingleColor =
"\nvoid main(void) {\n"
@@ -207,18 +221,18 @@ const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
"}\n\n";
const char* gFS_Fast_SingleGradient[2] = {
"\nvoid main(void) {\n"
- " gl_FragColor = texture2D(gradientSampler, linear);\n"
+ " gl_FragColor = " FS_MAIN_DITHER " + texture2D(gradientSampler, linear);\n"
"}\n\n",
"\nvoid main(void) {\n"
- " gl_FragColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+ " gl_FragColor = " FS_MAIN_DITHER " + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
"}\n\n"
};
const char* gFS_Fast_SingleModulateGradient[2] = {
"\nvoid main(void) {\n"
- " gl_FragColor = color.a * texture2D(gradientSampler, linear);\n"
+ " gl_FragColor " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
"}\n\n",
"\nvoid main(void) {\n"
- " gl_FragColor = color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+ " gl_FragColor " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
"}\n\n"
};
@@ -254,16 +268,21 @@ const char* gFS_Main_FetchA8Texture[2] = {
};
const char* gFS_Main_FetchGradient[6] = {
// Linear
- " vec4 gradientColor = texture2D(gradientSampler, linear);\n",
- " vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+ " highp vec4 gradientColor = texture2D(gradientSampler, linear);\n",
+
+ " highp vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+
// Circular
- " vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
- " vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+ " highp vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
+
+ " highp vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+
// Sweep
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
+ " highp vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
+
" highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
- " vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
+ " highp vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
};
const char* gFS_Main_FetchBitmap =
" vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
@@ -651,6 +670,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
if (description.hasGradient) {
shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
+ shader.append(gFS_Main_AddDitherToGradient);
}
if (description.hasBitmap) {
if (description.isPoint) {
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 71e1739..8916efd 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -250,6 +250,8 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV
bindUniformColor(program->getUniform("endColor"), mColors[1]);
}
+ Caches::getInstance().dither.setupProgram(program, textureUnit);
+
mat4 screenSpace;
computeScreenSpaceMatrix(screenSpace, modelView);
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
@@ -375,6 +377,8 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi
bindUniformColor(program->getUniform("endColor"), mColors[1]);
}
+ Caches::getInstance().dither.setupProgram(program, textureUnit);
+
mat4 screenSpace;
computeScreenSpaceMatrix(screenSpace, modelView);
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java
index ed00ecd..a73eab5 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java
@@ -19,6 +19,7 @@ package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
@@ -111,6 +112,14 @@ public class GradientStopsActivity extends Activity {
canvas.translate(0.0f, 75.0f);
canvas.drawRect(0.0f, 0.0f, 768.0f, 50.0f, paint);
+
+ gradient = new LinearGradient(0.0f, 0.0f, 512.0f, 0.0f,
+ colors, null, Shader.TileMode.CLAMP);
+
+ paint.setShader(gradient);
+
+ canvas.translate(0.0f, 75.0f);
+ canvas.drawRect(0.0f, 0.0f, 512.0f, 50.0f, paint);
}
}
}