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);
|
||||
|
||||
mCurrentBuffer = meshBuffer;
|
||||
mCurrentPositionPointer = this;
|
||||
mCurrentTexCoordsPointer = this;
|
||||
|
||||
mRegionMesh = NULL;
|
||||
|
||||
blend = false;
|
||||
@@ -218,22 +221,49 @@ 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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
@@ -98,6 +346,11 @@ public:
|
||||
*/
|
||||
int position;
|
||||
|
||||
/**
|
||||
* Name of the texCoords attribute if it exists, -1 otherwise.
|
||||
*/
|
||||
int texCoords;
|
||||
|
||||
/**
|
||||
* Name of the transform uniform.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include <SkXfermode.h>
|
||||
|
||||
#include "Debug.h"
|
||||
#include "Program.h"
|
||||
#include "Properties.h"
|
||||
@@ -43,240 +41,10 @@ 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.
|
||||
|
||||
Reference in New Issue
Block a user