Merge "Optimize state changes"
This commit is contained in:
@@ -73,6 +73,9 @@ void Caches::init() {
|
|||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
mCurrentBuffer = meshBuffer;
|
mCurrentBuffer = meshBuffer;
|
||||||
|
mCurrentPositionPointer = this;
|
||||||
|
mCurrentTexCoordsPointer = this;
|
||||||
|
|
||||||
mRegionMesh = NULL;
|
mRegionMesh = NULL;
|
||||||
|
|
||||||
blend = false;
|
blend = false;
|
||||||
@@ -218,22 +221,49 @@ void Caches::flush(FlushMode mode) {
|
|||||||
// VBO
|
// VBO
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void Caches::bindMeshBuffer() {
|
bool Caches::bindMeshBuffer() {
|
||||||
bindMeshBuffer(meshBuffer);
|
return bindMeshBuffer(meshBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Caches::bindMeshBuffer(const GLuint buffer) {
|
bool Caches::bindMeshBuffer(const GLuint buffer) {
|
||||||
if (mCurrentBuffer != buffer) {
|
if (mCurrentBuffer != buffer) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||||
mCurrentBuffer = buffer;
|
mCurrentBuffer = buffer;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Caches::unbindMeshBuffer() {
|
bool Caches::unbindMeshBuffer() {
|
||||||
if (mCurrentBuffer) {
|
if (mCurrentBuffer) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
mCurrentBuffer = 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() {
|
TextureVertex* Caches::getRegionMesh() {
|
||||||
|
|||||||
@@ -91,15 +91,6 @@ class ANDROID_API Caches: public Singleton<Caches> {
|
|||||||
|
|
||||||
CacheLogger mLogger;
|
CacheLogger mLogger;
|
||||||
|
|
||||||
GLuint mCurrentBuffer;
|
|
||||||
|
|
||||||
// Used to render layers
|
|
||||||
TextureVertex* mRegionMesh;
|
|
||||||
GLuint mRegionMeshIndices;
|
|
||||||
|
|
||||||
mutable Mutex mGarbageLock;
|
|
||||||
Vector<Layer*> mLayerGarbage;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum FlushMode {
|
enum FlushMode {
|
||||||
kFlushMode_Layers = 0,
|
kFlushMode_Layers = 0,
|
||||||
@@ -147,17 +138,36 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Binds the VBO used to render simple textured quads.
|
* Binds the VBO used to render simple textured quads.
|
||||||
*/
|
*/
|
||||||
void bindMeshBuffer();
|
bool bindMeshBuffer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds the specified VBO if needed.
|
* 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.
|
* 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
|
* Returns the mesh used to draw regions. Calling this method will
|
||||||
@@ -203,6 +213,17 @@ public:
|
|||||||
ResourceCache resourceCache;
|
ResourceCache resourceCache;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GLuint mCurrentBuffer;
|
||||||
|
void* mCurrentPositionPointer;
|
||||||
|
void* mCurrentTexCoordsPointer;
|
||||||
|
|
||||||
|
// Used to render layers
|
||||||
|
TextureVertex* mRegionMesh;
|
||||||
|
GLuint mRegionMeshIndices;
|
||||||
|
|
||||||
|
mutable Mutex mGarbageLock;
|
||||||
|
Vector<Layer*> mLayerGarbage;
|
||||||
|
|
||||||
DebugLevel mDebugLevel;
|
DebugLevel mDebugLevel;
|
||||||
bool mInitialized;
|
bool mInitialized;
|
||||||
}; // class Caches
|
}; // class Caches
|
||||||
|
|||||||
@@ -325,8 +325,6 @@ FontRenderer::FontRenderer() {
|
|||||||
mTextTexture = NULL;
|
mTextTexture = NULL;
|
||||||
|
|
||||||
mIndexBufferID = 0;
|
mIndexBufferID = 0;
|
||||||
mPositionAttrSlot = -1;
|
|
||||||
mTexcoordAttrSlot = -1;
|
|
||||||
|
|
||||||
mCacheWidth = DEFAULT_TEXT_CACHE_WIDTH;
|
mCacheWidth = DEFAULT_TEXT_CACHE_WIDTH;
|
||||||
mCacheHeight = DEFAULT_TEXT_CACHE_HEIGHT;
|
mCacheHeight = DEFAULT_TEXT_CACHE_HEIGHT;
|
||||||
@@ -599,12 +597,6 @@ void FontRenderer::checkTextureUpdate() {
|
|||||||
void FontRenderer::issueDrawCommand() {
|
void FontRenderer::issueDrawCommand() {
|
||||||
checkTextureUpdate();
|
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);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferID);
|
||||||
glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, NULL);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPositionAttrSlot < 0 || mTexcoordAttrSlot < 0) {
|
|
||||||
LOGE("Font renderer unable to draw, attribute slots undefined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDrawn = false;
|
mDrawn = false;
|
||||||
mBounds = bounds;
|
mBounds = bounds;
|
||||||
mClip = clip;
|
mClip = clip;
|
||||||
|
|||||||
@@ -178,9 +178,13 @@ public:
|
|||||||
mGammaTable = gammaTable;
|
mGammaTable = gammaTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAttributeBindingSlots(int positionSlot, int texCoordSlot) {
|
inline float* getMeshBuffer() {
|
||||||
mPositionAttrSlot = positionSlot;
|
checkInit();
|
||||||
mTexcoordAttrSlot = texCoordSlot;
|
return mTextMeshPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getMeshTexCoordsOffset() const {
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
|
void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
|
||||||
@@ -309,9 +313,6 @@ protected:
|
|||||||
|
|
||||||
uint32_t mIndexBufferID;
|
uint32_t mIndexBufferID;
|
||||||
|
|
||||||
int32_t mPositionAttrSlot;
|
|
||||||
int32_t mTexcoordAttrSlot;
|
|
||||||
|
|
||||||
const Rect* mClip;
|
const Rect* mClip;
|
||||||
Rect* mBounds;
|
Rect* mBounds;
|
||||||
bool mDrawn;
|
bool mDrawn;
|
||||||
|
|||||||
@@ -199,13 +199,13 @@ void OpenGLRenderer::interrupt() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCaches.unbindMeshBuffer();
|
mCaches.unbindMeshBuffer();
|
||||||
|
mCaches.resetVertexPointers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::resume() {
|
void OpenGLRenderer::resume() {
|
||||||
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
|
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
|
||||||
|
|
||||||
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
|
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
@@ -1201,16 +1201,15 @@ void OpenGLRenderer::setupDrawColorFilterUniforms() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::setupDrawSimpleMesh() {
|
void OpenGLRenderer::setupDrawSimpleMesh() {
|
||||||
mCaches.bindMeshBuffer();
|
bool force = mCaches.bindMeshBuffer();
|
||||||
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
|
mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
|
||||||
gMeshStride, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::setupDrawTexture(GLuint texture) {
|
void OpenGLRenderer::setupDrawTexture(GLuint texture) {
|
||||||
bindTexture(texture);
|
bindTexture(texture);
|
||||||
glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
|
glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
|
||||||
|
|
||||||
mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
|
mTexCoordsSlot = mCaches.currentProgram->texCoords;
|
||||||
glEnableVertexAttribArray(mTexCoordsSlot);
|
glEnableVertexAttribArray(mTexCoordsSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1218,7 +1217,7 @@ void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
|
|||||||
bindExternalTexture(texture);
|
bindExternalTexture(texture);
|
||||||
glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
|
glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
|
||||||
|
|
||||||
mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
|
mTexCoordsSlot = mCaches.currentProgram->texCoords;
|
||||||
glEnableVertexAttribArray(mTexCoordsSlot);
|
glEnableVertexAttribArray(mTexCoordsSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1232,23 +1231,23 @@ void OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
|
void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
|
||||||
|
bool force = false;
|
||||||
if (!vertices) {
|
if (!vertices) {
|
||||||
mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
|
force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
|
||||||
} else {
|
} else {
|
||||||
mCaches.unbindMeshBuffer();
|
force = mCaches.unbindMeshBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
|
mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, vertices);
|
||||||
gMeshStride, vertices);
|
|
||||||
if (mTexCoordsSlot >= 0) {
|
if (mTexCoordsSlot >= 0) {
|
||||||
glVertexAttribPointer(mTexCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
|
mCaches.bindTexCoordsVertexPointer(force, mTexCoordsSlot, texCoords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
|
void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
|
||||||
mCaches.unbindMeshBuffer();
|
bool force = mCaches.unbindMeshBuffer();
|
||||||
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
|
mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
|
||||||
gVertexStride, vertices);
|
vertices, gVertexStride);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1264,10 +1263,10 @@ void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
|
|||||||
*/
|
*/
|
||||||
void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
|
void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
|
||||||
GLvoid* lengthCoords, float boundaryWidthProportion) {
|
GLvoid* lengthCoords, float boundaryWidthProportion) {
|
||||||
mCaches.unbindMeshBuffer();
|
bool force = mCaches.unbindMeshBuffer();
|
||||||
|
mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
|
||||||
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
|
vertices, gAAVertexStride);
|
||||||
gAAVertexStride, vertices);
|
mCaches.resetTexCoordsVertexPointer();
|
||||||
|
|
||||||
int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
|
int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
|
||||||
glEnableVertexAttribArray(widthSlot);
|
glEnableVertexAttribArray(widthSlot);
|
||||||
@@ -2186,12 +2185,14 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
|||||||
#else
|
#else
|
||||||
bool hasActiveLayer = false;
|
bool hasActiveLayer = false;
|
||||||
#endif
|
#endif
|
||||||
mCaches.unbindMeshBuffer();
|
|
||||||
|
|
||||||
// Tell font renderer the locations of position and texture coord
|
float* buffer = fontRenderer.getMeshBuffer();
|
||||||
// attributes so it can bind its data properly
|
int offset = fontRenderer.getMeshTexCoordsOffset();
|
||||||
int positionSlot = mCaches.currentProgram->position;
|
|
||||||
fontRenderer.setAttributeBindingSlots(positionSlot, mTexCoordsSlot);
|
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,
|
if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
|
||||||
hasActiveLayer ? &bounds : NULL)) {
|
hasActiveLayer ? &bounds : NULL)) {
|
||||||
#if RENDER_LAYERS_AS_REGIONS
|
#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);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
|
glDisableVertexAttribArray(mCaches.currentProgram->texCoords);
|
||||||
|
|
||||||
drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
|
drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,8 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (verticesCount > 0) {
|
if (verticesCount > 0) {
|
||||||
Caches::getInstance().bindMeshBuffer(meshBuffer);
|
Caches& caches = Caches::getInstance();
|
||||||
|
caches.bindMeshBuffer(meshBuffer);
|
||||||
if (!mUploaded) {
|
if (!mUploaded) {
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
|
glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
|
||||||
mVertices, GL_DYNAMIC_DRAW);
|
mVertices, GL_DYNAMIC_DRAW);
|
||||||
@@ -206,6 +207,7 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
|
|||||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||||
sizeof(TextureVertex) * verticesCount, mVertices);
|
sizeof(TextureVertex) * verticesCount, mVertices);
|
||||||
}
|
}
|
||||||
|
caches.resetVertexPointers();
|
||||||
}
|
}
|
||||||
|
|
||||||
PATCH_LOGD(" patch: new vertices count = %d", verticesCount);
|
PATCH_LOGD(" patch: new vertices count = %d", verticesCount);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace uirenderer {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO: Program instance should be created from a factory method
|
// 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;
|
mInitialized = false;
|
||||||
mHasColorUniform = false;
|
mHasColorUniform = false;
|
||||||
mUse = false;
|
mUse = false;
|
||||||
@@ -43,6 +43,12 @@ Program::Program(const char* vertex, const char* fragment) {
|
|||||||
glAttachShader(mProgramId, mFragmentShader);
|
glAttachShader(mProgramId, mFragmentShader);
|
||||||
|
|
||||||
position = bindAttrib("position", kBindingPosition);
|
position = bindAttrib("position", kBindingPosition);
|
||||||
|
if (description.hasTexture || description.hasExternalTexture) {
|
||||||
|
texCoords = bindAttrib("texCoords", kBindingTexCoords);
|
||||||
|
} else {
|
||||||
|
texCoords = -1;
|
||||||
|
}
|
||||||
|
|
||||||
glLinkProgram(mProgramId);
|
glLinkProgram(mProgramId);
|
||||||
|
|
||||||
GLint status;
|
GLint status;
|
||||||
|
|||||||
@@ -17,16 +17,264 @@
|
|||||||
#ifndef ANDROID_HWUI_PROGRAM_H
|
#ifndef ANDROID_HWUI_PROGRAM_H
|
||||||
#define ANDROID_HWUI_PROGRAM_H
|
#define ANDROID_HWUI_PROGRAM_H
|
||||||
|
|
||||||
|
#include <utils/KeyedVector.h>
|
||||||
|
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
|
|
||||||
#include <utils/KeyedVector.h>
|
#include <SkXfermode.h>
|
||||||
|
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
|
#include "Properties.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace uirenderer {
|
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
|
* A program holds a vertex and a fragment shader. It offers several utility
|
||||||
* methods to query attributes and uniforms.
|
* methods to query attributes and uniforms.
|
||||||
@@ -42,7 +290,7 @@ public:
|
|||||||
* Creates a new program with the specified vertex and fragment
|
* Creates a new program with the specified vertex and fragment
|
||||||
* shaders sources.
|
* shaders sources.
|
||||||
*/
|
*/
|
||||||
Program(const char* vertex, const char* fragment);
|
Program(const ProgramDescription& description, const char* vertex, const char* fragment);
|
||||||
virtual ~Program();
|
virtual ~Program();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +346,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
int position;
|
int position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the texCoords attribute if it exists, -1 otherwise.
|
||||||
|
*/
|
||||||
|
int texCoords;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the transform uniform.
|
* Name of the transform uniform.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ Program* ProgramCache::generateProgram(const ProgramDescription& description, pr
|
|||||||
String8 vertexShader = generateVertexShader(description);
|
String8 vertexShader = generateVertexShader(description);
|
||||||
String8 fragmentShader = generateFragmentShader(description);
|
String8 fragmentShader = generateFragmentShader(description);
|
||||||
|
|
||||||
Program* program = new Program(vertexShader.string(), fragmentShader.string());
|
Program* program = new Program(description, vertexShader.string(), fragmentShader.string());
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,6 @@
|
|||||||
|
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
|
|
||||||
#include <SkXfermode.h>
|
|
||||||
|
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "Program.h"
|
#include "Program.h"
|
||||||
#include "Properties.h"
|
#include "Properties.h"
|
||||||
@@ -43,240 +41,10 @@ namespace uirenderer {
|
|||||||
#define PROGRAM_LOGD(...)
|
#define PROGRAM_LOGD(...)
|
||||||
#endif
|
#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
|
// 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
|
* Generates and caches program. Programs are generated based on
|
||||||
* ProgramDescriptions.
|
* ProgramDescriptions.
|
||||||
|
|||||||
Reference in New Issue
Block a user