Merge "Generate shaders to cover all possible cases."
This commit is contained in:
@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \
|
||||
Patch.cpp \
|
||||
PatchCache.cpp \
|
||||
Program.cpp \
|
||||
ProgramCache.cpp \
|
||||
TextureCache.cpp
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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
332
libs/hwui/ProgramCache.cpp
Normal 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
155
libs/hwui/ProgramCache.h
Normal 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
|
@ -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.
|
||||
*/
|
||||
|
@ -1,11 +0,0 @@
|
||||
SHADER_SOURCE(gDrawColorVertexShader,
|
||||
|
||||
attribute vec4 position;
|
||||
|
||||
uniform mat4 transform;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = transform * position;
|
||||
}
|
||||
|
||||
);
|
@ -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;
|
||||
|
Reference in New Issue
Block a user