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
This commit is contained in:
Romain Guy
2013-04-05 11:17:55 -07:00
parent 80fdc9624e
commit b488004289
6 changed files with 194 additions and 124 deletions

View File

@ -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) {