summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2013-04-05 11:17:55 -0700
committerRomain Guy <romainguy@google.com>2013-04-05 14:17:17 -0700
commitb48800428906ae455c2b63acacd44e390e1fee49 (patch)
treebc0de8c6f51eb5c9cac2d5fe1d5a41fede6d727a /libs
parent80fdc9624e6d53a78031bf99d34e7c01d53ad66e (diff)
downloadframeworks_base-b48800428906ae455c2b63acacd44e390e1fee49.zip
frameworks_base-b48800428906ae455c2b63acacd44e390e1fee49.tar.gz
frameworks_base-b48800428906ae455c2b63acacd44e390e1fee49.tar.bz2
Use float textures to render gradients when possible
Float textures offer better precision for dithering. In addition this change removes two uniforms from gradient shaders. These uniforms were used to dither gradients but their value is a build time constant. Instead we hardcode the value directly in the shader source at compile time. Change-Id: I05e9fd3eef93771843bbd91b453274452dfaefee
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Dither.cpp45
-rw-r--r--libs/hwui/Dither.h12
-rw-r--r--libs/hwui/GradientCache.cpp142
-rw-r--r--libs/hwui/GradientCache.h25
-rw-r--r--libs/hwui/ProgramCache.cpp88
-rw-r--r--libs/hwui/ProgramCache.h2
6 files changed, 192 insertions, 122 deletions
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index e80b325..9bc5c14 100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
@@ -21,38 +21,46 @@ 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
- };
+ bool useFloatTexture = Extensions::getInstance().getMajorGlVersion() >= 3;
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);
+ if (useFloatTexture) {
+ float dither = 1.0f / (255.0f * DITHER_KERNEL_SIZE * DITHER_KERNEL_SIZE);
+ const GLfloat pattern[] = {
+ 0 * dither, 8 * dither, 2 * dither, 10 * dither,
+ 12 * dither, 4 * dither, 14 * dither, 6 * dither,
+ 3 * dither, 11 * dither, 1 * dither, 9 * dither,
+ 15 * dither, 7 * dither, 13 * dither, 5 * dither
+ };
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, sizeof(GLfloat));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+ GL_RED, GL_FLOAT, &pattern);
+ } else {
+ const uint8_t pattern[] = {
+ 0, 8, 2, 10,
+ 12, 4, 14, 6,
+ 3, 11, 1, 9,
+ 15, 7, 13, 5
+ };
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+ }
mInitialized = true;
} else {
@@ -76,10 +84,7 @@ void Dither::setupProgram(Program* program, GLuint* textureUnit) {
bindDitherTexture();
- float ditherSize = 1.0f / DITHER_KERNEL_SIZE;
glUniform1i(program->getUniform("ditherSampler"), textureSlot);
- glUniform1f(program->getUniform("ditherSize"), ditherSize);
- glUniform1f(program->getUniform("ditherSizeSquared"), ditherSize * ditherSize);
}
}; // namespace uirenderer
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
index 34cf9bf..4d1f921 100644
--- a/libs/hwui/Dither.h
+++ b/libs/hwui/Dither.h
@@ -17,13 +17,23 @@
#ifndef ANDROID_HWUI_DITHER_H
#define ANDROID_HWUI_DITHER_H
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
#include "Program.h"
namespace android {
namespace uirenderer {
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Must be a power of two
+#define DITHER_KERNEL_SIZE 4
+// These must not use the .0f notation as they are used from GLSL
+#define DITHER_KERNEL_SIZE_INV (1.0 / 4.0)
+#define DITHER_KERNEL_SIZE_INV_SQUARE (1.0 / 16.0)
+
/**
* Handles dithering for programs.
*/
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index d681609..eef366c 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -27,13 +27,6 @@ namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#define GRADIENT_TEXTURE_HEIGHT 2
-#define GRADIENT_BYTES_PER_PIXEL 4
-
-///////////////////////////////////////////////////////////////////////////////
// Functions
///////////////////////////////////////////////////////////////////////////////
@@ -83,6 +76,10 @@ GradientCache::GradientCache():
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
mCache.setOnEntryRemovedListener(this);
+
+ const Extensions& extensions = Extensions::getInstance();
+ mUseFloatTexture = extensions.getMajorGlVersion() >= 3;
+ mHasNpot = extensions.hasNPot();
}
GradientCache::GradientCache(uint32_t maxByteSize):
@@ -120,7 +117,7 @@ void GradientCache::setMaxSize(uint32_t maxSize) {
void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
if (texture) {
- const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
+ const uint32_t size = texture->width * texture->height * bytesPerPixel();
mSize -= size;
glDeleteTextures(1, &texture->id);
@@ -151,7 +148,7 @@ void GradientCache::getGradientInfo(const uint32_t* colors, const int count,
GradientInfo& info) {
uint32_t width = 256 * (count - 1);
- if (!Extensions::getInstance().hasNPot()) {
+ if (!mHasNpot) {
width = 1 << (31 - __builtin_clz(width));
}
@@ -175,12 +172,12 @@ Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
Texture* texture = new Texture;
texture->width = info.width;
- texture->height = GRADIENT_TEXTURE_HEIGHT;
+ texture->height = 2;
texture->blend = info.hasAlpha;
texture->generation = 1;
// Asume the cache is always big enough
- const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL;
+ const uint32_t size = texture->width * texture->height * bytesPerPixel();
while (getSize() + size > mMaxSize) {
mCache.removeOldest();
}
@@ -193,69 +190,110 @@ Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient,
return texture;
}
+size_t GradientCache::bytesPerPixel() const {
+ // We use 4 channels (RGBA)
+ return 4 * (mUseFloatTexture ? sizeof(float) : sizeof(uint8_t));
+}
+
+void GradientCache::splitToBytes(uint32_t inColor, GradientColor& outColor) const {
+ outColor.r = (inColor >> 16) & 0xff;
+ outColor.g = (inColor >> 8) & 0xff;
+ outColor.b = (inColor >> 0) & 0xff;
+ outColor.a = (inColor >> 24) & 0xff;
+}
+
+void GradientCache::splitToFloats(uint32_t inColor, GradientColor& outColor) const {
+ outColor.r = ((inColor >> 16) & 0xff) / 255.0f;
+ outColor.g = ((inColor >> 8) & 0xff) / 255.0f;
+ outColor.b = ((inColor >> 0) & 0xff) / 255.0f;
+ outColor.a = ((inColor >> 24) & 0xff) / 255.0f;
+}
+
+void GradientCache::mixBytes(GradientColor& start, GradientColor& end, float amount,
+ uint8_t*& dst) const {
+ float oppAmount = 1.0f - amount;
+ const float alpha = start.a * oppAmount + end.a * amount;
+ const float a = alpha / 255.0f;
+
+ *dst++ = uint8_t(a * (start.r * oppAmount + end.r * amount));
+ *dst++ = uint8_t(a * (start.g * oppAmount + end.g * amount));
+ *dst++ = uint8_t(a * (start.b * oppAmount + end.b * amount));
+ *dst++ = uint8_t(alpha);
+}
+
+void GradientCache::mixFloats(GradientColor& start, GradientColor& end, float amount,
+ uint8_t*& dst) const {
+ float oppAmount = 1.0f - amount;
+ const float a = start.a * oppAmount + end.a * amount;
+
+ float* d = (float*) dst;
+ *d++ = a * (start.r * oppAmount + end.r * amount);
+ *d++ = a * (start.g * oppAmount + end.g * amount);
+ *d++ = a * (start.b * oppAmount + end.b * amount);
+ *d++ = a;
+
+ dst += 4 * sizeof(float);
+}
+
void GradientCache::generateTexture(uint32_t* colors, float* positions,
int count, Texture* texture) {
-
const uint32_t width = texture->width;
- const GLsizei rowBytes = width * GRADIENT_BYTES_PER_PIXEL;
- uint32_t pixels[width * texture->height];
+ const GLsizei rowBytes = width * bytesPerPixel();
+ uint8_t pixels[rowBytes * texture->height];
- int currentPos = 1;
+ static ChannelSplitter gSplitters[] = {
+ &android::uirenderer::GradientCache::splitToBytes,
+ &android::uirenderer::GradientCache::splitToFloats,
+ };
+ ChannelSplitter split = gSplitters[mUseFloatTexture];
- float startA = (colors[0] >> 24) & 0xff;
- float startR = (colors[0] >> 16) & 0xff;
- float startG = (colors[0] >> 8) & 0xff;
- float startB = (colors[0] >> 0) & 0xff;
+ static ChannelMixer gMixers[] = {
+ &android::uirenderer::GradientCache::mixBytes,
+ &android::uirenderer::GradientCache::mixFloats,
+ };
+ ChannelMixer mix = gMixers[mUseFloatTexture];
- float endA = (colors[1] >> 24) & 0xff;
- float endR = (colors[1] >> 16) & 0xff;
- float endG = (colors[1] >> 8) & 0xff;
- float endB = (colors[1] >> 0) & 0xff;
+ GradientColor start;
+ (this->*split)(colors[0], start);
- float start = positions[0];
- float distance = positions[1] - start;
+ GradientColor end;
+ (this->*split)(colors[1], end);
- uint8_t* p = (uint8_t*) pixels;
+ int currentPos = 1;
+ float startPos = positions[0];
+ float distance = positions[1] - startPos;
+
+ uint8_t* dst = pixels;
for (uint32_t x = 0; x < width; x++) {
float pos = x / float(width - 1);
if (pos > positions[currentPos]) {
- startA = endA;
- startR = endR;
- startG = endG;
- startB = endB;
- start = positions[currentPos];
+ start = end;
+ startPos = positions[currentPos];
currentPos++;
- endA = (colors[currentPos] >> 24) & 0xff;
- endR = (colors[currentPos] >> 16) & 0xff;
- endG = (colors[currentPos] >> 8) & 0xff;
- endB = (colors[currentPos] >> 0) & 0xff;
- distance = positions[currentPos] - start;
+ (this->*split)(colors[currentPos], end);
+ distance = positions[currentPos] - startPos;
}
- float amount = (pos - start) / distance;
- float oppAmount = 1.0f - amount;
-
- const float alpha = startA * oppAmount + endA * amount;
- const float a = alpha / 255.0f;
- *p++ = uint8_t(a * (startR * oppAmount + endR * amount));
- *p++ = uint8_t(a * (startG * oppAmount + endG * amount));
- *p++ = uint8_t(a * (startB * oppAmount + endB * amount));
- *p++ = uint8_t(alpha);
+ float amount = (pos - startPos) / distance;
+ (this->*mix)(start, end, amount, dst);
}
- for (int i = 1; i < GRADIENT_TEXTURE_HEIGHT; i++) {
- memcpy(pixels + width * i, pixels, rowBytes);
- }
+ memcpy(pixels + rowBytes, pixels, rowBytes);
glGenTextures(1, &texture->id);
-
glBindTexture(GL_TEXTURE_2D, texture->id);
- glPixelStorei(GL_UNPACK_ALIGNMENT, GRADIENT_BYTES_PER_PIXEL);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ if (mUseFloatTexture) {
+ // We have to use GL_RGBA16F because GL_RGBA32F does not support filtering
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, texture->height, 0,
+ GL_RGBA, GL_FLOAT, pixels);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ }
texture->setFilter(GL_LINEAR);
texture->setWrap(GL_CLAMP_TO_EDGE);
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 7dc5b8a..43934d9 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_HWUI_GRADIENT_CACHE_H
#define ANDROID_HWUI_GRADIENT_CACHE_H
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
#include <SkShader.h>
@@ -160,12 +160,35 @@ private:
void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
+ size_t bytesPerPixel() const;
+
+ struct GradientColor {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+
+ typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor,
+ GradientColor& outColor) const;
+
+ void splitToBytes(uint32_t inColor, GradientColor& outColor) const;
+ void splitToFloats(uint32_t inColor, GradientColor& outColor) const;
+
+ typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end,
+ float amount, uint8_t*& dst) const;
+
+ void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
+ void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
+
LruCache<GradientCacheEntry, Texture*> mCache;
uint32_t mSize;
uint32_t mMaxSize;
GLint mMaxTextureSize;
+ bool mUseFloatTexture;
+ bool mHasNpot;
Vector<SkShader*> mGarbage;
mutable Mutex mLock;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index f78fb2d..2479630 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -19,6 +19,7 @@
#include <utils/String8.h>
#include "Caches.h"
+#include "Dither.h"
#include "ProgramCache.h"
namespace android {
@@ -32,6 +33,9 @@ namespace uirenderer {
#define MODULATE_OP_MODULATE 1
#define MODULATE_OP_MODULATE_A8 2
+#define STR(x) STR1(x)
+#define STR1(x) #x
+
///////////////////////////////////////////////////////////////////////////////
// Vertex shaders snippets
///////////////////////////////////////////////////////////////////////////////
@@ -51,17 +55,8 @@ const char* gVS_Header_Uniforms =
"uniform mat4 transform;\n";
const char* gVS_Header_Uniforms_IsPoint =
"uniform mediump float pointSize;\n";
-const char* gVS_Header_Uniforms_HasGradient[3] = {
- // Linear
- "uniform mat4 screenSpace;\n"
- "uniform float ditherSize;\n",
- // Circular
- "uniform mat4 screenSpace;\n"
- "uniform float ditherSize;\n",
- // Sweep
- "uniform mat4 screenSpace;\n"
- "uniform float ditherSize;\n"
-};
+const char* gVS_Header_Uniforms_HasGradient =
+ "uniform mat4 screenSpace;\n";
const char* gVS_Header_Uniforms_HasBitmap =
"uniform mat4 textureTransform;\n"
"uniform mediump vec2 textureDimension;\n";
@@ -105,21 +100,21 @@ const char* gVS_Main_OutTransformedTexCoords =
const char* gVS_Main_OutGradient[6] = {
// Linear
" linear = vec2((screenSpace * position).x, 0.5);\n"
- " ditherTexCoords = (transform * position).xy * ditherSize;\n",
+ " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
" linear = (screenSpace * position).x;\n"
- " ditherTexCoords = (transform * position).xy * ditherSize;\n",
+ " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
// Circular
" circular = (screenSpace * position).xy;\n"
- " ditherTexCoords = (transform * position).xy * ditherSize;\n",
+ " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
" circular = (screenSpace * position).xy;\n"
- " ditherTexCoords = (transform * position).xy * ditherSize;\n",
+ " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
// Sweep
" sweep = (screenSpace * position).xy;\n"
- " ditherTexCoords = (transform * position).xy * ditherSize;\n",
+ " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
" sweep = (screenSpace * position).xy;\n"
- " ditherTexCoords = (transform * position).xy * ditherSize;\n",
+ " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
};
const char* gVS_Main_OutBitmapTexCoords =
" outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
@@ -153,24 +148,14 @@ const char* gFS_Uniforms_TextureSampler =
"uniform sampler2D baseSampler;\n";
const char* gFS_Uniforms_ExternalTextureSampler =
"uniform samplerExternalOES baseSampler;\n";
-#define FS_UNIFORMS_DITHER \
- "uniform float ditherSizeSquared;\n" \
- "uniform sampler2D ditherSampler;\n"
-#define FS_UNIFORMS_GRADIENT \
- "uniform vec4 startColor;\n" \
+const char* gFS_Uniforms_Dither =
+ "uniform sampler2D ditherSampler;";
+const char* gFS_Uniforms_GradientSampler[2] = {
+ "%s\n"
+ "uniform sampler2D gradientSampler;\n",
+ "%s\n"
+ "uniform vec4 startColor;\n"
"uniform vec4 endColor;\n"
-const char* gFS_Uniforms_GradientSampler[6] = {
- // Linear
- FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
- FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
-
- // Circular
- FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
- FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT,
-
- // Sweep
- FS_UNIFORMS_DITHER "uniform sampler2D gradientSampler;\n",
- FS_UNIFORMS_DITHER FS_UNIFORMS_GRADIENT
};
const char* gFS_Uniforms_BitmapSampler =
"uniform sampler2D bitmapSampler;\n";
@@ -197,10 +182,14 @@ 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, ditherTexCoords).a * ditherSizeSquared"
+const char* gFS_Main_Dither[2] = {
+ // ES 2.0
+ "texture2D(ditherSampler, ditherTexCoords).a * " STR(DITHER_KERNEL_SIZE_INV_SQUARE),
+ // ES 3.0
+ "texture2D(ditherSampler, ditherTexCoords).r"
+};
const char* gFS_Main_AddDitherToGradient =
- " gradientColor += " FS_MAIN_DITHER ";\n";
+ " gradientColor += %s;\n";
// Fast cases
const char* gFS_Fast_SingleColor =
@@ -233,18 +222,18 @@ const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
"}\n\n";
const char* gFS_Fast_SingleGradient[2] = {
"\nvoid main(void) {\n"
- " gl_FragColor = " FS_MAIN_DITHER " + texture2D(gradientSampler, linear);\n"
+ " gl_FragColor = %s + texture2D(gradientSampler, linear);\n"
"}\n\n",
"\nvoid main(void) {\n"
- " gl_FragColor = " FS_MAIN_DITHER " + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
- "}\n\n"
+ " gl_FragColor = %s + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+ "}\n\n",
};
const char* gFS_Fast_SingleModulateGradient[2] = {
"\nvoid main(void) {\n"
- " gl_FragColor = " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
+ " gl_FragColor = %s + color.a * texture2D(gradientSampler, linear);\n"
"}\n\n",
"\nvoid main(void) {\n"
- " gl_FragColor = " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+ " gl_FragColor = %s + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
"}\n\n"
};
@@ -410,7 +399,7 @@ const char* gBlendOps[18] = {
// Constructors/destructors
///////////////////////////////////////////////////////////////////////////////
-ProgramCache::ProgramCache() {
+ProgramCache::ProgramCache(): mHasES3(Extensions::getInstance().getMajorGlVersion() >= 3) {
}
ProgramCache::~ProgramCache() {
@@ -484,7 +473,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
shader.append(gVS_Header_Uniforms_TextureTransform);
}
if (description.hasGradient) {
- shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
+ shader.append(gVS_Header_Uniforms_HasGradient);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Uniforms_HasBitmap);
@@ -601,7 +590,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Uniforms_ExternalTextureSampler);
}
if (description.hasGradient) {
- shader.append(gFS_Uniforms_GradientSampler[gradientIndex(description)]);
+ shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient],
+ gFS_Uniforms_Dither);
}
if (description.hasBitmap && description.isPoint) {
shader.append(gFS_Header_Uniforms_PointHasBitmap);
@@ -652,9 +642,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
fast = true;
} else if (singleGradient) {
if (!description.modulate) {
- shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]);
+ shader.appendFormat(gFS_Fast_SingleGradient[description.isSimpleGradient],
+ gFS_Main_Dither[mHasES3]);
} else {
- shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]);
+ shader.appendFormat(gFS_Fast_SingleModulateGradient[description.isSimpleGradient],
+ gFS_Main_Dither[mHasES3]);
}
fast = true;
}
@@ -708,7 +700,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
if (description.hasGradient) {
shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
- shader.append(gFS_Main_AddDitherToGradient);
+ shader.appendFormat(gFS_Main_AddDitherToGradient, gFS_Main_Dither[mHasES3]);
}
if (description.hasBitmap) {
if (description.isPoint) {
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 1ca148d..38f6f99 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -57,6 +57,8 @@ private:
void printLongString(const String8& shader) const;
KeyedVector<programid, Program*> mCache;
+
+ const bool mHasES3;
}; // class ProgramCache
}; // namespace uirenderer