Merge "Generate shaders to cover all possible cases."

This commit is contained in:
Romain Guy
2010-07-27 19:53:33 -07:00
committed by Android (Google) Code Review
12 changed files with 543 additions and 76 deletions

View File

@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \
Patch.cpp \
PatchCache.cpp \
Program.cpp \
ProgramCache.cpp \
TextureCache.cpp
LOCAL_C_INCLUDES += \

View File

@ -45,32 +45,22 @@ namespace uirenderer {
#define MB(s) s * 1024 * 1024
// Generates simple and textured vertices
#define SV(x, y) { { x, y } }
#define FV(x, y, u, v) { { x, y }, { u, v } }
///////////////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////////////
static const SimpleVertex gDrawColorVertices[] = {
SV(0.0f, 0.0f),
SV(1.0f, 0.0f),
SV(0.0f, 1.0f),
SV(1.0f, 1.0f)
};
static const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
static const GLsizei gDrawColorVertexCount = 4;
// This array is never used directly but used as a memcpy source in the
// OpenGLRenderer constructor
static const TextureVertex gDrawTextureVertices[] = {
static const TextureVertex gMeshVertices[] = {
FV(0.0f, 0.0f, 0.0f, 0.0f),
FV(1.0f, 0.0f, 1.0f, 0.0f),
FV(0.0f, 1.0f, 0.0f, 1.0f),
FV(1.0f, 1.0f, 1.0f, 1.0f)
};
static const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
static const GLsizei gDrawTextureVertexCount = 4;
static const GLsizei gMeshStride = sizeof(TextureVertex);
static const GLsizei gMeshCount = 4;
// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
@ -143,7 +133,18 @@ OpenGLRenderer::OpenGLRenderer():
mLastTexture = 0;
memcpy(mDrawTextureVertices, gDrawTextureVertices, sizeof(gDrawTextureVertices));
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
ProgramDescription d;
mProgramCache.get(d);
d.hasTexture = true;
mProgramCache.get(d);
d.hasAlpha8Texture = true;
d.hasGradient = true;
d.hasBitmap = true;
d.shadersMode = SkXfermode::kDstOut_Mode;
d.colorOp = ProgramDescription::kColorMatrix;
mProgramCache.get(d);
}
OpenGLRenderer::~OpenGLRenderer() {
@ -650,9 +651,13 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
mModelView.scale(right - left, bottom - top, 1.0f);
if (!useProgram(mDrawColorProgram)) {
const GLvoid* p = &gDrawColorVertices[0].position[0];
const GLvoid* vertices = &mMeshVertices[0].position[0];
const GLvoid* texCoords = &mMeshVertices[0].texture[0];
glVertexAttribPointer(mDrawColorProgram->position, 2, GL_FLOAT, GL_FALSE,
gDrawColorVertexStride, p);
gMeshStride, vertices);
glVertexAttribPointer(mDrawColorProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
gMeshStride, texCoords);
}
if (!ignoreTransform) {
@ -664,7 +669,7 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
glUniform4f(mDrawColorProgram->color, r, g, b, a);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}
void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right, float bottom,
@ -717,9 +722,9 @@ void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right
&screenSpace.data[0]);
glVertexAttribPointer(mDrawLinearGradientProgram->position, 2, GL_FLOAT, GL_FALSE,
gDrawTextureVertexStride, &mDrawTextureVertices[0].position[0]);
gMeshStride, &mMeshVertices[0].position[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}
void OpenGLRenderer::drawBitmapShader(float left, float top, float right, float bottom,
@ -757,7 +762,7 @@ void OpenGLRenderer::drawBitmapShader(float left, float top, float right, float
resetDrawTextureTexCoords(u1, v1, u2, v2);
drawTextureMesh(left, top, right, bottom, texture->id, alpha, mode, texture->blend,
&mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@ -769,13 +774,13 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
getAlphaAndMode(paint, &alpha, &mode);
drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend,
&mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
&mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
}
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
@ -794,12 +799,12 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha);
glVertexAttribPointer(mDrawTextureProgram->position, 2, GL_FLOAT, GL_FALSE,
gDrawTextureVertexStride, vertices);
gMeshStride, vertices);
glVertexAttribPointer(mDrawTextureProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
gDrawTextureVertexStride, texCoords);
gMeshStride, texCoords);
if (!indices) {
glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
} else {
glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices);
}
@ -842,7 +847,7 @@ bool OpenGLRenderer::useProgram(const sp<Program>& program) {
}
void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
TextureVertex* v = &mDrawTextureVertices[0];
TextureVertex* v = &mMeshVertices[0];
TextureVertex::setUV(v++, u1, v1);
TextureVertex::setUV(v++, u2, v1);
TextureVertex::setUV(v++, u1, v2);

View File

@ -41,6 +41,7 @@
#include "PatchCache.h"
#include "Vertex.h"
#include "FontRenderer.h"
#include "ProgramCache.h"
namespace android {
namespace uirenderer {
@ -268,7 +269,7 @@ private:
SkXfermode::Mode mode);
/**
* Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
* Resets the texture coordinates stored in mMeshVertices. Setting the values
* back to default is achieved by calling:
*
* resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
@ -337,7 +338,7 @@ private:
sp<DrawLinearGradientProgram> mDrawLinearGradientProgram;
// Used to draw textured quads
TextureVertex mDrawTextureVertices[4];
TextureVertex mMeshVertices[4];
// Current texture state
GLuint mLastTexture;
@ -372,6 +373,7 @@ private:
TextureCache mTextureCache;
LayerCache mLayerCache;
GradientCache mGradientCache;
ProgramCache mProgramCache;
PatchCache mPatchCache;
}; // class OpenGLRenderer

View File

@ -27,7 +27,6 @@ namespace uirenderer {
#define SHADER_SOURCE(name, source) const char* name = #source
#include "shaders/drawColor.vert"
#include "shaders/drawColor.frag"
#include "shaders/drawTexture.vert"
@ -127,7 +126,7 @@ GLuint Program::buildShader(const char* source, GLenum type) {
///////////////////////////////////////////////////////////////////////////////
DrawColorProgram::DrawColorProgram():
Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
Program(gDrawTextureVertexShader, gDrawColorFragmentShader) {
getAttribsAndUniforms();
}
@ -138,6 +137,7 @@ DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment):
void DrawColorProgram::getAttribsAndUniforms() {
position = addAttrib("position");
texCoords = addAttrib("texCoords");
color = addUniform("color");
transform = addUniform("transform");
}
@ -154,11 +154,13 @@ void DrawColorProgram::set(const mat4& projectionMatrix, const mat4& modelViewMa
void DrawColorProgram::use() {
Program::use();
glEnableVertexAttribArray(position);
glEnableVertexAttribArray(texCoords);
}
void DrawColorProgram::remove() {
Program::remove();
glDisableVertexAttribArray(position);
glDisableVertexAttribArray(texCoords);
}
///////////////////////////////////////////////////////////////////////////////
@ -167,26 +169,21 @@ void DrawColorProgram::remove() {
DrawTextureProgram::DrawTextureProgram():
DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) {
texCoords = addAttrib("texCoords");
sampler = addUniform("sampler");
}
DrawTextureProgram::DrawTextureProgram(const char* vertex, const char* fragment):
DrawColorProgram(vertex, fragment) {
texCoords = addAttrib("texCoords");
sampler = addUniform("sampler");
}
void DrawTextureProgram::use() {
DrawColorProgram::use();
glActiveTexture(GL_TEXTURE0);
glUniform1i(sampler, 0);
glEnableVertexAttribArray(texCoords);
}
void DrawTextureProgram::remove() {
DrawColorProgram::remove();
glDisableVertexAttribArray(texCoords);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -52,6 +52,16 @@ public:
*/
virtual void remove();
/**
* Returns the OpenGL name of the specified attribute.
*/
int getAttrib(const char* name);
/**
* Returns the OpenGL name of the specified uniform.
*/
int getUniform(const char* name);
/**
* Indicates whether this program is currently in use with
* the GL context.
@ -67,10 +77,6 @@ protected:
* @return The OpenGL name of the attribute.
*/
int addAttrib(const char* name);
/**
* Returns the OpenGL name of the specified attribute.
*/
int getAttrib(const char* name);
/**
* Adds a uniform with the specified name.
@ -78,10 +84,6 @@ protected:
* @return The OpenGL name of the uniform.
*/
int addUniform(const char* name);
/**
* Returns the OpenGL name of the specified uniform.
*/
int getUniform(const char* name);
private:
/**
@ -144,6 +146,11 @@ public:
*/
int position;
/**
* Name of the texture coordinates attribute.
*/
int texCoords;
/**
* Name of the color uniform.
*/
@ -184,11 +191,6 @@ public:
* Name of the texture sampler uniform.
*/
int sampler;
/**
* Name of the texture coordinates attribute.
*/
int texCoords;
};
class DrawTextProgram: public DrawTextureProgram {

332
libs/hwui/ProgramCache.cpp Normal file
View File

@ -0,0 +1,332 @@
/*
* 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.
*/
#define LOG_TAG "OpenGLRenderer"
#include <utils/String8.h>
#include "ProgramCache.h"
namespace android {
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 =
"attribute vec2 texCoords;\n";
const char* gVS_Header_Uniforms =
"uniform mat4 transform;\n";
const char* gVS_Header_Uniforms_HasGradient =
"uniform float gradientLength;\n"
"uniform vec2 gradient;\n"
"uniform vec2 gradientStart;\n"
"uniform mat4 screenSpace;\n";
const char* gVS_Header_Varyings_HasTexture =
"varying vec2 outTexCoords;\n";
const char* gVS_Header_Varyings_HasBitmap =
"varying vec2 outBitmapTexCoords;\n";
const char* gVS_Header_Varyings_HasGradient =
"varying float index;\n";
const char* gVS_Main =
"\nvoid main(void) {\n";
const char* gVS_Main_OutTexCoords =
" outTexCoords = texCoords;\n";
const char* gVS_Main_OutGradientIndex =
" vec4 location = screenSpace * position;\n"
" index = dot(location.xy - gradientStart, gradient) * gradientLength;\n";
const char* gVS_Main_Position =
" gl_Position = transform * position;\n";
const char* gVS_Footer =
"}\n\n";
///////////////////////////////////////////////////////////////////////////////
// Fragment shaders snippets
///////////////////////////////////////////////////////////////////////////////
const char* gFS_Header =
"precision mediump float;\n\n";
const char* gFS_Uniforms_Color =
"uniform vec4 color;\n";
const char* gFS_Uniforms_TextureSampler =
"uniform sampler2D sampler;\n";
const char* gFS_Uniforms_GradientSampler =
"uniform sampler2D gradientSampler;\n";
const char* gFS_Uniforms_BitmapSampler =
"uniform sampler2D bitmapSampler;\n";
const char* gFS_Uniforms_ColorOp[4] = {
// None
"",
// Matrix
"uniform mat4 colorMatrix;\n"
"uniform vec4 colorMatrixVector;\n",
// Lighting
"uniform float lightingMul;\n"
"uniform float lightingAdd;\n",
// PorterDuff
"uniform vec4 colorBLend;\n"
};
const char* gFS_Main =
"\nvoid main(void) {\n"
" vec4 fragColor;\n";
const char* gFS_Main_FetchColor =
" fragColor = color;\n";
const char* gFS_Main_FetchTexture =
" fragColor = color * texture2D(sampler, outTexCoords);\n";
const char* gFS_Main_FetchA8Texture =
" fragColor = color * texture2D(sampler, outTexCoords).a;\n";
const char* gFS_Main_FetchGradient =
" vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n";
const char* gFS_Main_FetchBitmap =
" vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
const char* gFS_Main_BlendShadersBG =
" fragColor = blendShaders(bitmapColor, gradientColor)";
const char* gFS_Main_BlendShadersGB =
" fragColor = blendShaders(gradientColor, bitmapColor)";
const char* gFS_Main_BlendShaders_Modulate =
" * fragColor.a;\n";
const char* gFS_Main_FragColor =
" gl_FragColor = fragColor;\n";
const char* gFS_Main_ApplyColorOp[4] = {
// None
"",
// Matrix
" fragColor *= colorMatrix;\n"
" fragColor += colorMatrixVector;\n",
// Lighting
" fragColor *= lightingMul;\n"
" fragColor += lightingAdd;\n",
// PorterDuff
" fragColor = blendColors(colorBlend, fragColor);\n"
};
const char* gFS_Footer =
"}\n\n";
///////////////////////////////////////////////////////////////////////////////
// PorterDuff snippets
///////////////////////////////////////////////////////////////////////////////
const char* gPorterDuff[12] = {
// Clear
"return vec4(0.0, 0.0, 0.0, 0.0);\n",
// Src
"return src;\n",
// Dst
"return dst;\n",
// SrcOver
"return vec4(src.rgb + (1.0 - src.a) * dst.rgb, src.a + dst.a - src.a * dst.a);\n",
// DstOver
"return vec4(dst.rgb + (1.0 - dst.a) * src.rgb, src.a + dst.a - src.a * dst.a);\n",
// SrcIn
"return vec4(src.rgb * dst.a, src.a * dst.a);\n",
// DstIn
"return vec4(dst.rgb * src.a, src.a * dst.a);\n",
// SrcOut
"return vec4(src.rgb * (1.0 - dst.a), src.a * (1.0 - dst.a));\n",
// DstOut
"return vec4(dst.rgb * (1.0 - src.a), dst.a * (1.0 - src.a));\n",
// SrcAtop
"return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n",
// DstAtop
"return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n",
// Xor
"return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, "
"src.a + dst.a - 2.0 * src.a * dst.a);\n",
};
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructors
///////////////////////////////////////////////////////////////////////////////
ProgramCache::ProgramCache() {
}
ProgramCache::~ProgramCache() {
clear();
}
///////////////////////////////////////////////////////////////////////////////
// Cache management
///////////////////////////////////////////////////////////////////////////////
void ProgramCache::clear() {
size_t count = mCache.size();
for (size_t i = 0; i < count; i++) {
delete mCache.valueAt(i);
}
mCache.clear();
}
Program* ProgramCache::get(const ProgramDescription& description) {
programid key = description.key();
ssize_t index = mCache.indexOfKey(key);
Program* program = NULL;
if (index < 0) {
PROGRAM_LOGD("Could not find program with key 0x%x", key);
program = generateProgram(description, key);
mCache.add(key, program);
} else {
program = mCache.valueAt(index);
}
return program;
}
///////////////////////////////////////////////////////////////////////////////
// Program generation
///////////////////////////////////////////////////////////////////////////////
Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) {
String8 vertexShader = generateVertexShader(description);
String8 fragmentShader = generateFragmentShader(description);
Program* program = new Program(vertexShader.string(), fragmentShader.string());
return program;
}
String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
// Add attributes
String8 shader(gVS_Header_Attributes);
if (description.hasTexture || description.hasBitmap) {
shader.append(gVS_Header_Attributes_TexCoords);
}
// Uniforms
shader.append(gVS_Header_Uniforms);
if (description.hasGradient) {
shader.append(gVS_Header_Uniforms_HasGradient);
}
// Varyings
if (description.hasTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Varyings_HasBitmap);
}
// Begin the shader
shader.append(gVS_Main); {
if (description.hasTexture) {
shader.append(gVS_Main_OutTexCoords);
}
if (description.hasGradient) {
shader.append(gVS_Main_OutGradientIndex);
}
// Output transformed position
shader.append(gVS_Main_Position);
}
// End the shader
shader.append(gVS_Footer);
PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string());
return shader;
}
String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
// Set the default precision
String8 shader(gFS_Header);
// Varyings
if (description.hasTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Varyings_HasBitmap);
}
// Uniforms
shader.append(gFS_Uniforms_Color);
if (description.hasTexture) {
shader.append(gFS_Uniforms_TextureSampler);
}
if (description.hasGradient) {
shader.append(gFS_Uniforms_GradientSampler);
}
if (description.hasBitmap) {
shader.append(gFS_Uniforms_BitmapSampler);
}
shader.append(gFS_Uniforms_ColorOp[description.colorOp]);
// Generate required functions
if (description.hasGradient && description.hasBitmap) {
generatePorterDuffBlend(shader, "blendShaders", description.shadersMode);
}
if (description.colorOp == ProgramDescription::kColorBlend) {
generatePorterDuffBlend(shader, "blendColors", description.colorMode);
}
// Begin the shader
shader.append(gFS_Main); {
// Stores the result in fragColor directly
if (description.hasTexture) {
if (description.hasAlpha8Texture) {
shader.append(gFS_Main_FetchA8Texture);
} else {
shader.append(gFS_Main_FetchTexture);
}
} else {
shader.append(gFS_Main_FetchColor);
}
if (description.hasGradient) {
shader.append(gFS_Main_FetchGradient);
}
if (description.hasBitmap) {
shader.append(gFS_Main_FetchBitmap);
}
// Case when we have two shaders set
if (description.hasGradient && description.hasBitmap) {
if (description.isBitmapFirst) {
shader.append(gFS_Main_BlendShadersBG);
} else {
shader.append(gFS_Main_BlendShadersGB);
}
shader.append(gFS_Main_BlendShaders_Modulate);
}
// Apply the color op if needed
shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
// Output the fragment
shader.append(gFS_Main_FragColor);
}
// End the shader
shader.append(gFS_Footer);
PROGRAM_LOGD("*** Generated fragment shader:\n\n%s", shader.string());
return shader;
}
void ProgramCache::generatePorterDuffBlend(String8& shader, const char* name,
SkXfermode::Mode mode) {
shader.append("\nvec4 ");
shader.append(name);
shader.append("(vec4 src, vec4 dst) {\n");
shader.append(" ");
shader.append(gPorterDuff[mode]);
shader.append("}\n");
}
}; // namespace uirenderer
}; // namespace android

155
libs/hwui/ProgramCache.h Normal file
View File

@ -0,0 +1,155 @@
/*
* 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_PROGRAM_CACHE_H
#define ANDROID_UI_PROGRAM_CACHE_H
#include <utils/KeyedVector.h>
#include <utils/Log.h>
#include <SkXfermode.h>
#include "Program.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
// Debug
#define DEBUG_PROGRAM_CACHE 0
// Debug
#if DEBUG_PROGRAM_CACHE
#define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
#else
#define PROGRAM_LOGD(...)
#endif
#define PROGRAM_KEY_TEXTURE 0x1
#define PROGRAM_KEY_A8_TEXTURE 0x2
#define PROGRAM_KEY_BITMAP 0x4
#define PROGRAM_KEY_GRADIENT 0x8
#define PROGRAM_KEY_BITMAP_FIRST 0x10
#define PROGRAM_KEY_COLOR_MATRIX 0x20
#define PROGRAM_KEY_COLOR_LIGHTING 0x40
#define PROGRAM_KEY_COLOR_BLEND 0x80
// Support only the 12 Porter-Duff modes for now
#define PROGRAM_MAX_XFERMODE 0xC
#define PROGRAM_XFERMODE_SHADER_SHIFT 24
#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////
typedef uint32_t programid;
///////////////////////////////////////////////////////////////////////////////
// Cache
///////////////////////////////////////////////////////////////////////////////
/**
* Describe the features required for a given program. The features
* determine the generation of both the vertex and fragment shaders.
* A ProgramDescription must be used in conjunction with a ProgramCache.
*/
struct ProgramDescription {
enum ColorModifier {
kColorNone,
kColorMatrix,
kColorLighting,
kColorBlend
};
ProgramDescription():
hasTexture(false), hasAlpha8Texture(false),
hasBitmap(false), hasGradient(false), shadersMode(SkXfermode::kClear_Mode),
colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode) {
}
// Texturing
bool hasTexture;
bool hasAlpha8Texture;
// Shaders
bool hasBitmap;
bool hasGradient;
SkXfermode::Mode shadersMode;
bool isBitmapFirst;
// Color operations
int colorOp;
SkXfermode::Mode colorMode;
programid key() const {
programid key = 0;
if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
if (hasBitmap) key |= PROGRAM_KEY_BITMAP;
if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
if (hasBitmap && hasGradient) {
key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
}
switch (colorOp) {
case kColorMatrix:
key |= PROGRAM_KEY_COLOR_MATRIX;
break;
case kColorLighting:
key |= PROGRAM_KEY_COLOR_LIGHTING;
break;
case kColorBlend:
key |= PROGRAM_KEY_COLOR_BLEND;
key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
break;
case kColorNone:
break;
}
return key;
}
}; // struct ProgramDescription
/**
* Generates and caches program. Programs are generated based on
* ProgramDescriptions.
*/
class ProgramCache {
public:
ProgramCache();
~ProgramCache();
Program* get(const ProgramDescription& description);
void clear();
private:
Program* generateProgram(const ProgramDescription& description, programid key);
String8 generateVertexShader(const ProgramDescription& description);
String8 generateFragmentShader(const ProgramDescription& description);
void generatePorterDuffBlend(String8& shader, const char* name, SkXfermode::Mode mode);
KeyedVector<programid, Program*> mCache;
}; // class ProgramCache
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_UI_PROGRAM_CACHE_H

View File

@ -20,14 +20,6 @@
namespace android {
namespace uirenderer {
/**
* Simple structure to describe a vertex with a position.
* This is used to draw filled rectangles without a texture.
*/
struct SimpleVertex {
float position[2];
}; // struct SimpleVertex
/**
* Simple structure to describe a vertex with a position and a texture.
*/

View File

@ -1,11 +0,0 @@
SHADER_SOURCE(gDrawColorVertexShader,
attribute vec4 position;
uniform mat4 transform;
void main(void) {
gl_Position = transform * position;
}
);

View File

@ -2,10 +2,10 @@ SHADER_SOURCE(gDrawLinearGradientVertexShader,
attribute vec4 position;
uniform mat4 transform;
uniform float gradientLength;
uniform vec2 gradient;
uniform vec2 start;
uniform mat4 transform;
uniform mat4 screenSpace;
varying float index;