summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2011-12-12 20:35:21 -0800
committerRomain Guy <romainguy@google.com>2011-12-12 20:35:21 -0800
commitf3a910b423db7ad79cf61518bdd9278c048ad0d8 (patch)
treea0ae14d597ee14202ec6ca60cedfb446ff470379
parentd71dd367af604571c7d00ca473184a1b9240eca2 (diff)
downloadframeworks_base-f3a910b423db7ad79cf61518bdd9278c048ad0d8.zip
frameworks_base-f3a910b423db7ad79cf61518bdd9278c048ad0d8.tar.gz
frameworks_base-f3a910b423db7ad79cf61518bdd9278c048ad0d8.tar.bz2
Optimize state changes
Change-Id: Iae59bc8dfd6427d0967472462cc1994987092827
-rw-r--r--libs/hwui/Caches.cpp38
-rw-r--r--libs/hwui/Caches.h45
-rw-r--r--libs/hwui/FontRenderer.cpp13
-rw-r--r--libs/hwui/FontRenderer.h13
-rw-r--r--libs/hwui/OpenGLRenderer.cpp49
-rw-r--r--libs/hwui/Patch.cpp4
-rw-r--r--libs/hwui/Program.cpp8
-rw-r--r--libs/hwui/Program.h257
-rw-r--r--libs/hwui/ProgramCache.cpp2
-rw-r--r--libs/hwui/ProgramCache.h232
10 files changed, 365 insertions, 296 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f293cba..4da576d 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -73,6 +73,9 @@ void Caches::init() {
glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
mCurrentBuffer = meshBuffer;
+ mCurrentPositionPointer = this;
+ mCurrentTexCoordsPointer = this;
+
mRegionMesh = NULL;
blend = false;
@@ -218,24 +221,51 @@ void Caches::flush(FlushMode mode) {
// VBO
///////////////////////////////////////////////////////////////////////////////
-void Caches::bindMeshBuffer() {
- bindMeshBuffer(meshBuffer);
+bool Caches::bindMeshBuffer() {
+ return bindMeshBuffer(meshBuffer);
}
-void Caches::bindMeshBuffer(const GLuint buffer) {
+bool Caches::bindMeshBuffer(const GLuint buffer) {
if (mCurrentBuffer != buffer) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
mCurrentBuffer = buffer;
+ return true;
}
+ return false;
}
-void Caches::unbindMeshBuffer() {
+bool Caches::unbindMeshBuffer() {
if (mCurrentBuffer) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
mCurrentBuffer = 0;
+ return true;
+ }
+ return false;
+}
+
+void Caches::bindPositionVertexPointer(bool force, GLuint slot, GLvoid* vertices, GLsizei stride) {
+ if (force || vertices != mCurrentPositionPointer) {
+ glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+ mCurrentPositionPointer = vertices;
}
}
+void Caches::bindTexCoordsVertexPointer(bool force, GLuint slot, GLvoid* vertices) {
+ if (force || vertices != mCurrentTexCoordsPointer) {
+ glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, gMeshStride, vertices);
+ mCurrentTexCoordsPointer = vertices;
+ }
+}
+
+void Caches::resetVertexPointers() {
+ mCurrentPositionPointer = this;
+ mCurrentTexCoordsPointer = this;
+}
+
+void Caches::resetTexCoordsVertexPointer() {
+ mCurrentTexCoordsPointer = this;
+}
+
TextureVertex* Caches::getRegionMesh() {
// Create the mesh, 2 triangles and 4 vertices per rectangle in the region
if (!mRegionMesh) {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 5e58a9e..7ca198a 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -91,15 +91,6 @@ class ANDROID_API Caches: public Singleton<Caches> {
CacheLogger mLogger;
- GLuint mCurrentBuffer;
-
- // Used to render layers
- TextureVertex* mRegionMesh;
- GLuint mRegionMeshIndices;
-
- mutable Mutex mGarbageLock;
- Vector<Layer*> mLayerGarbage;
-
public:
enum FlushMode {
kFlushMode_Layers = 0,
@@ -147,17 +138,36 @@ public:
/**
* Binds the VBO used to render simple textured quads.
*/
- void bindMeshBuffer();
+ bool bindMeshBuffer();
/**
* Binds the specified VBO if needed.
*/
- void bindMeshBuffer(const GLuint buffer);
+ bool bindMeshBuffer(const GLuint buffer);
/**
* Unbinds the VBO used to render simple textured quads.
*/
- void unbindMeshBuffer();
+ bool unbindMeshBuffer();
+
+ /**
+ * Binds an attrib to the specified float vertex pointer.
+ * Assumes a stride of gMeshStride and a size of 2.
+ */
+ void bindPositionVertexPointer(bool force, GLuint slot, GLvoid* vertices,
+ GLsizei stride = gMeshStride);
+
+ /**
+ * Binds an attrib to the specified float vertex pointer.
+ * Assumes a stride of gMeshStride and a size of 2.
+ */
+ void bindTexCoordsVertexPointer(bool force, GLuint slot, GLvoid* vertices);
+
+ /**
+ * Resets the vertex pointers.
+ */
+ void resetVertexPointers();
+ void resetTexCoordsVertexPointer();
/**
* Returns the mesh used to draw regions. Calling this method will
@@ -203,6 +213,17 @@ public:
ResourceCache resourceCache;
private:
+ GLuint mCurrentBuffer;
+ void* mCurrentPositionPointer;
+ void* mCurrentTexCoordsPointer;
+
+ // Used to render layers
+ TextureVertex* mRegionMesh;
+ GLuint mRegionMeshIndices;
+
+ mutable Mutex mGarbageLock;
+ Vector<Layer*> mLayerGarbage;
+
DebugLevel mDebugLevel;
bool mInitialized;
}; // class Caches
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 6e80d15..f04ea6f 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -325,8 +325,6 @@ FontRenderer::FontRenderer() {
mTextTexture = NULL;
mIndexBufferID = 0;
- mPositionAttrSlot = -1;
- mTexcoordAttrSlot = -1;
mCacheWidth = DEFAULT_TEXT_CACHE_WIDTH;
mCacheHeight = DEFAULT_TEXT_CACHE_HEIGHT;
@@ -599,12 +597,6 @@ void FontRenderer::checkTextureUpdate() {
void FontRenderer::issueDrawCommand() {
checkTextureUpdate();
- float* vtx = mTextMeshPtr;
- float* tex = vtx + 2;
-
- glVertexAttribPointer(mPositionAttrSlot, 2, GL_FLOAT, GL_FALSE, 16, vtx);
- glVertexAttribPointer(mTexcoordAttrSlot, 2, GL_FLOAT, GL_FALSE, 16, tex);
-
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferID);
glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, NULL);
@@ -760,11 +752,6 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text
return false;
}
- if (mPositionAttrSlot < 0 || mTexcoordAttrSlot < 0) {
- LOGE("Font renderer unable to draw, attribute slots undefined");
- return false;
- }
-
mDrawn = false;
mBounds = bounds;
mClip = clip;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 71695a8..f945873 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -178,9 +178,13 @@ public:
mGammaTable = gammaTable;
}
- void setAttributeBindingSlots(int positionSlot, int texCoordSlot) {
- mPositionAttrSlot = positionSlot;
- mTexcoordAttrSlot = texCoordSlot;
+ inline float* getMeshBuffer() {
+ checkInit();
+ return mTextMeshPtr;
+ }
+
+ inline int getMeshTexCoordsOffset() const {
+ return 2;
}
void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
@@ -309,9 +313,6 @@ protected:
uint32_t mIndexBufferID;
- int32_t mPositionAttrSlot;
- int32_t mTexcoordAttrSlot;
-
const Rect* mClip;
Rect* mBounds;
bool mDrawn;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6e2f1c3..fcac053 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -199,13 +199,13 @@ void OpenGLRenderer::interrupt() {
}
}
mCaches.unbindMeshBuffer();
+ mCaches.resetVertexPointers();
}
void OpenGLRenderer::resume() {
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
-
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_SCISSOR_TEST);
@@ -1201,16 +1201,15 @@ void OpenGLRenderer::setupDrawColorFilterUniforms() {
}
void OpenGLRenderer::setupDrawSimpleMesh() {
- mCaches.bindMeshBuffer();
- glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, 0);
+ bool force = mCaches.bindMeshBuffer();
+ mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
}
void OpenGLRenderer::setupDrawTexture(GLuint texture) {
bindTexture(texture);
glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
- mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+ mTexCoordsSlot = mCaches.currentProgram->texCoords;
glEnableVertexAttribArray(mTexCoordsSlot);
}
@@ -1218,7 +1217,7 @@ void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
bindExternalTexture(texture);
glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
- mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+ mTexCoordsSlot = mCaches.currentProgram->texCoords;
glEnableVertexAttribArray(mTexCoordsSlot);
}
@@ -1232,23 +1231,23 @@ void OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) {
}
void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
+ bool force = false;
if (!vertices) {
- mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+ force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
} else {
- mCaches.unbindMeshBuffer();
+ force = mCaches.unbindMeshBuffer();
}
- glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, vertices);
+ mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
if (mTexCoordsSlot >= 0) {
- glVertexAttribPointer(mTexCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
+ mCaches.bindTexCoordsVertexPointer(force, mTexCoordsSlot, texCoords);
}
}
void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
- mCaches.unbindMeshBuffer();
- glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gVertexStride, vertices);
+ bool force = mCaches.unbindMeshBuffer();
+ mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
+ vertices, gVertexStride);
}
/**
@@ -1264,10 +1263,10 @@ void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
*/
void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
GLvoid* lengthCoords, float boundaryWidthProportion) {
- mCaches.unbindMeshBuffer();
-
- glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gAAVertexStride, vertices);
+ bool force = mCaches.unbindMeshBuffer();
+ mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
+ vertices, gAAVertexStride);
+ mCaches.resetTexCoordsVertexPointer();
int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
glEnableVertexAttribArray(widthSlot);
@@ -2186,12 +2185,14 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
#else
bool hasActiveLayer = false;
#endif
- mCaches.unbindMeshBuffer();
- // Tell font renderer the locations of position and texture coord
- // attributes so it can bind its data properly
- int positionSlot = mCaches.currentProgram->position;
- fontRenderer.setAttributeBindingSlots(positionSlot, mTexCoordsSlot);
+ float* buffer = fontRenderer.getMeshBuffer();
+ int offset = fontRenderer.getMeshTexCoordsOffset();
+
+ bool force = mCaches.unbindMeshBuffer();
+ mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, buffer);
+ mCaches.bindTexCoordsVertexPointer(force, mTexCoordsSlot, buffer + offset);
+
if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
hasActiveLayer ? &bounds : NULL)) {
#if RENDER_LAYERS_AS_REGIONS
@@ -2205,7 +2206,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
+ glDisableVertexAttribArray(mCaches.currentProgram->texCoords);
drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
}
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 47a2c99..27f530c 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -197,7 +197,8 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
}
if (verticesCount > 0) {
- Caches::getInstance().bindMeshBuffer(meshBuffer);
+ Caches& caches = Caches::getInstance();
+ caches.bindMeshBuffer(meshBuffer);
if (!mUploaded) {
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
mVertices, GL_DYNAMIC_DRAW);
@@ -206,6 +207,7 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
glBufferSubData(GL_ARRAY_BUFFER, 0,
sizeof(TextureVertex) * verticesCount, mVertices);
}
+ caches.resetVertexPointers();
}
PATCH_LOGD(" patch: new vertices count = %d", verticesCount);
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index cb2a5fd..cbea843 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -26,7 +26,7 @@ namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// TODO: Program instance should be created from a factory method
-Program::Program(const char* vertex, const char* fragment) {
+Program::Program(const ProgramDescription& description, const char* vertex, const char* fragment) {
mInitialized = false;
mHasColorUniform = false;
mUse = false;
@@ -43,6 +43,12 @@ Program::Program(const char* vertex, const char* fragment) {
glAttachShader(mProgramId, mFragmentShader);
position = bindAttrib("position", kBindingPosition);
+ if (description.hasTexture || description.hasExternalTexture) {
+ texCoords = bindAttrib("texCoords", kBindingTexCoords);
+ } else {
+ texCoords = -1;
+ }
+
glLinkProgram(mProgramId);
GLint status;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 9e59621..559c717 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -17,16 +17,264 @@
#ifndef ANDROID_HWUI_PROGRAM_H
#define ANDROID_HWUI_PROGRAM_H
+#include <utils/KeyedVector.h>
+
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
-#include <utils/KeyedVector.h>
+#include <SkXfermode.h>
#include "Matrix.h"
+#include "Properties.h"
namespace android {
namespace uirenderer {
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Debug
+#if DEBUG_PROGRAMS
+ #define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
+#else
+ #define PROGRAM_LOGD(...)
+#endif
+
+#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
+#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
+
+#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
+#define PROGRAM_KEY_BITMAP_NPOT 0x100
+#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
+
+#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
+#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
+
+// Encode the xfermodes on 6 bits
+#define PROGRAM_MAX_XFERMODE 0x1f
+#define PROGRAM_XFERMODE_SHADER_SHIFT 26
+#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
+#define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
+
+#define PROGRAM_BITMAP_WRAPS_SHIFT 9
+#define PROGRAM_BITMAP_WRAPT_SHIFT 11
+
+#define PROGRAM_GRADIENT_TYPE_SHIFT 33
+#define PROGRAM_MODULATE_SHIFT 35
+
+#define PROGRAM_IS_POINT_SHIFT 36
+
+#define PROGRAM_HAS_AA_SHIFT 37
+
+#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
+#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
+
+///////////////////////////////////////////////////////////////////////////////
+// Types
+///////////////////////////////////////////////////////////////////////////////
+
+typedef uint64_t programid;
+
+///////////////////////////////////////////////////////////////////////////////
+// Program description
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * 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
+ };
+
+ enum Gradient {
+ kGradientLinear,
+ kGradientCircular,
+ kGradientSweep
+ };
+
+ ProgramDescription() {
+ reset();
+ }
+
+ // Texturing
+ bool hasTexture;
+ bool hasAlpha8Texture;
+ bool hasExternalTexture;
+ bool hasTextureTransform;
+
+ // Modulate, this should only be set when setColor() return true
+ bool modulate;
+
+ // Shaders
+ bool hasBitmap;
+ bool isBitmapNpot;
+
+ bool isAA;
+
+ bool hasGradient;
+ Gradient gradientType;
+
+ SkXfermode::Mode shadersMode;
+
+ bool isBitmapFirst;
+ GLenum bitmapWrapS;
+ GLenum bitmapWrapT;
+
+ // Color operations
+ ColorModifier colorOp;
+ SkXfermode::Mode colorMode;
+
+ // Framebuffer blending (requires Extensions.hasFramebufferFetch())
+ // Ignored for all values < SkXfermode::kPlus_Mode
+ SkXfermode::Mode framebufferMode;
+ bool swapSrcDst;
+
+ bool isPoint;
+ float pointSize;
+
+ /**
+ * Resets this description. All fields are reset back to the default
+ * values they hold after building a new instance.
+ */
+ void reset() {
+ hasTexture = false;
+ hasAlpha8Texture = false;
+ hasExternalTexture = false;
+ hasTextureTransform = false;
+
+ isAA = false;
+
+ modulate = false;
+
+ hasBitmap = false;
+ isBitmapNpot = false;
+
+ hasGradient = false;
+ gradientType = kGradientLinear;
+
+ shadersMode = SkXfermode::kClear_Mode;
+
+ isBitmapFirst = false;
+ bitmapWrapS = GL_CLAMP_TO_EDGE;
+ bitmapWrapT = GL_CLAMP_TO_EDGE;
+
+ colorOp = kColorNone;
+ colorMode = SkXfermode::kClear_Mode;
+
+ framebufferMode = SkXfermode::kClear_Mode;
+ swapSrcDst = false;
+
+ isPoint = false;
+ pointSize = 0.0f;
+ }
+
+ /**
+ * Indicates, for a given color, whether color modulation is required in
+ * the fragment shader. When this method returns true, the program should
+ * be provided with a modulation color.
+ */
+ bool setColor(const float r, const float g, const float b, const float a) {
+ modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
+ g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
+ return modulate;
+ }
+
+ /**
+ * Indicates, for a given color, whether color modulation is required in
+ * the fragment shader. When this method returns true, the program should
+ * be provided with a modulation color.
+ */
+ bool setAlpha8Color(const float r, const float g, const float b, const float a) {
+ modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
+ g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
+ return modulate;
+ }
+
+ /**
+ * Computes the unique key identifying this program.
+ */
+ 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 (isBitmapNpot) {
+ key |= PROGRAM_KEY_BITMAP_NPOT;
+ key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
+ key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
+ }
+ }
+ if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
+ key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
+ 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;
+ }
+ key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
+ if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
+ if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
+ if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
+ if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
+ if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
+ if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
+ return key;
+ }
+
+ /**
+ * Logs the specified message followed by the key identifying this program.
+ */
+ void log(const char* message) const {
+#if DEBUG_PROGRAMS
+ programid k = key();
+ PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
+ uint32_t(k & 0xffffffff));
+#endif
+ }
+
+private:
+ inline uint32_t getEnumForWrap(GLenum wrap) const {
+ switch (wrap) {
+ case GL_CLAMP_TO_EDGE:
+ return 0;
+ case GL_REPEAT:
+ return 1;
+ case GL_MIRRORED_REPEAT:
+ return 2;
+ }
+ return 0;
+ }
+
+}; // struct ProgramDescription
+
/**
* A program holds a vertex and a fragment shader. It offers several utility
* methods to query attributes and uniforms.
@@ -42,7 +290,7 @@ public:
* Creates a new program with the specified vertex and fragment
* shaders sources.
*/
- Program(const char* vertex, const char* fragment);
+ Program(const ProgramDescription& description, const char* vertex, const char* fragment);
virtual ~Program();
/**
@@ -99,6 +347,11 @@ public:
int position;
/**
+ * Name of the texCoords attribute if it exists, -1 otherwise.
+ */
+ int texCoords;
+
+ /**
* Name of the transform uniform.
*/
int transform;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index c2383f4..a7f1277 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -388,7 +388,7 @@ Program* ProgramCache::generateProgram(const ProgramDescription& description, pr
String8 vertexShader = generateVertexShader(description);
String8 fragmentShader = generateFragmentShader(description);
- Program* program = new Program(vertexShader.string(), fragmentShader.string());
+ Program* program = new Program(description, vertexShader.string(), fragmentShader.string());
return program;
}
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 441db8c..e3ed79e 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -23,8 +23,6 @@
#include <GLES2/gl2.h>
-#include <SkXfermode.h>
-
#include "Debug.h"
#include "Program.h"
#include "Properties.h"
@@ -43,241 +41,11 @@ namespace uirenderer {
#define PROGRAM_LOGD(...)
#endif
-#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
-#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
-
-#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
-#define PROGRAM_KEY_BITMAP_NPOT 0x100
-#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
-
-#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
-#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
-
-// Encode the xfermodes on 6 bits
-#define PROGRAM_MAX_XFERMODE 0x1f
-#define PROGRAM_XFERMODE_SHADER_SHIFT 26
-#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
-#define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
-
-#define PROGRAM_BITMAP_WRAPS_SHIFT 9
-#define PROGRAM_BITMAP_WRAPT_SHIFT 11
-
-#define PROGRAM_GRADIENT_TYPE_SHIFT 33
-#define PROGRAM_MODULATE_SHIFT 35
-
-#define PROGRAM_IS_POINT_SHIFT 36
-
-#define PROGRAM_HAS_AA_SHIFT 37
-
-#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
-#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
-
-///////////////////////////////////////////////////////////////////////////////
-// Types
-///////////////////////////////////////////////////////////////////////////////
-
-typedef uint64_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
- };
-
- enum Gradient {
- kGradientLinear,
- kGradientCircular,
- kGradientSweep
- };
-
- ProgramDescription() {
- reset();
- }
-
- // Texturing
- bool hasTexture;
- bool hasAlpha8Texture;
- bool hasExternalTexture;
- bool hasTextureTransform;
-
- // Modulate, this should only be set when setColor() return true
- bool modulate;
-
- // Shaders
- bool hasBitmap;
- bool isBitmapNpot;
-
- bool isAA;
-
- bool hasGradient;
- Gradient gradientType;
-
- SkXfermode::Mode shadersMode;
-
- bool isBitmapFirst;
- GLenum bitmapWrapS;
- GLenum bitmapWrapT;
-
- // Color operations
- ColorModifier colorOp;
- SkXfermode::Mode colorMode;
-
- // Framebuffer blending (requires Extensions.hasFramebufferFetch())
- // Ignored for all values < SkXfermode::kPlus_Mode
- SkXfermode::Mode framebufferMode;
- bool swapSrcDst;
-
- bool isPoint;
- float pointSize;
-
- /**
- * Resets this description. All fields are reset back to the default
- * values they hold after building a new instance.
- */
- void reset() {
- hasTexture = false;
- hasAlpha8Texture = false;
- hasExternalTexture = false;
- hasTextureTransform = false;
-
- isAA = false;
-
- modulate = false;
-
- hasBitmap = false;
- isBitmapNpot = false;
-
- hasGradient = false;
- gradientType = kGradientLinear;
-
- shadersMode = SkXfermode::kClear_Mode;
-
- isBitmapFirst = false;
- bitmapWrapS = GL_CLAMP_TO_EDGE;
- bitmapWrapT = GL_CLAMP_TO_EDGE;
-
- colorOp = kColorNone;
- colorMode = SkXfermode::kClear_Mode;
-
- framebufferMode = SkXfermode::kClear_Mode;
- swapSrcDst = false;
-
- isPoint = false;
- pointSize = 0.0f;
- }
-
- /**
- * Indicates, for a given color, whether color modulation is required in
- * the fragment shader. When this method returns true, the program should
- * be provided with a modulation color.
- */
- bool setColor(const float r, const float g, const float b, const float a) {
- modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
- g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
- return modulate;
- }
-
- /**
- * Indicates, for a given color, whether color modulation is required in
- * the fragment shader. When this method returns true, the program should
- * be provided with a modulation color.
- */
- bool setAlpha8Color(const float r, const float g, const float b, const float a) {
- modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
- g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
- return modulate;
- }
-
- /**
- * Computes the unique key identifying this program.
- */
- 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 (isBitmapNpot) {
- key |= PROGRAM_KEY_BITMAP_NPOT;
- key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
- key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
- }
- }
- if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
- key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
- 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;
- }
- key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
- if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
- if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
- if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
- if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
- if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
- if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
- return key;
- }
-
- /**
- * Logs the specified message followed by the key identifying this program.
- */
- void log(const char* message) const {
-#if DEBUG_PROGRAMS
- programid k = key();
- PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
- uint32_t(k & 0xffffffff));
-#endif
- }
-
-private:
- inline uint32_t getEnumForWrap(GLenum wrap) const {
- switch (wrap) {
- case GL_CLAMP_TO_EDGE:
- return 0;
- case GL_REPEAT:
- return 1;
- case GL_MIRRORED_REPEAT:
- return 2;
- }
- return 0;
- }
-
-}; // struct ProgramDescription
-
-/**
* Generates and caches program. Programs are generated based on
* ProgramDescriptions.
*/