typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
#else
/*
* Include stdint.h with defines that trigger declaration of C99 limit/const
kHighVertexLayoutBit = kDummyVertexLayoutBit - 1
};
// make sure we haven't exceeded the number of bits in GrVertexLayout.
- GR_STATIC_ASSERT(kHighVertexLayoutBit < (1 << 8*sizeof(GrVertexLayout)));
+ GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout)));
/**
* There are three paths for specifying geometry (vertices and optionally
*
* GR_GL_CHECK_ERROR_START: controls the initial value of gCheckErrorGL
* when GR_GL_CHECK_ERROR is 1. Defaults to 1.
+ *
+ * GR_GL_NO_CONSTANT_ATTRIBUTES: if this evaluates to true then the GL backend
+ * will use uniforms instead of attributes in all cases when there is not
+ * per-vertex data. This is important when the underlying GL implementation
+ * doesn't actually support immediate style attribute values (e.g. when
+ * the GL stream is converted to DX as in ANGLE on Chrome). Defaults to 0.
+ *
+ * GR_GL_ATTRIBUTE_MATRICES: If changing uniforms is very expensive it may be
+ * faster to use vertex attributes for matrices (set via glVertexAttrib3fv).
+ * Setting this build flag enables this behavior. GR_GL_NO_CONSTANT_ATTRIBUTES
+ * must not be set since this uses constant attributes for the matrices.
+ * Defaults to 0.
*/
-
#if !defined(GR_GL_LOG_CALLS)
- #define GR_GL_LOG_CALLS 0
+ #define GR_GL_LOG_CALLS 0
#endif
#if !defined(GR_GL_LOG_CALLS_START)
- #define GR_GL_LOG_CALLS_START 0
+ #define GR_GL_LOG_CALLS_START 0
#endif
#if !defined(GR_GL_CHECK_ERROR)
- #define GR_GL_CHECK_ERROR GR_DEBUG
+ #define GR_GL_CHECK_ERROR GR_DEBUG
#endif
#if !defined(GR_GL_CHECK_ERROR_START)
- #define GR_GL_CHECK_ERROR_START 1
+ #define GR_GL_CHECK_ERROR_START 1
+#endif
+
+#if !defined(GR_GL_NO_CONSTANT_ATTRIBUTES)
+ #define GR_GL_NO_CONSTANT_ATTRIBUTES 0
+#endif
+
+#if !defined(GR_GL_ATTRIBUTE_MATRICES)
+ #define GR_GL_ATTRIBUTE_MATRICES 0
+#endif
+
+#if(GR_GL_NO_CONSTANT_ATTRIBUTES) && (GR_GL_ATTRIBUTE_MATRICES)
+ #error "Cannot combine GR_GL_NO_CONSTANT_ATTRIBUTES and GR_GL_ATTRIBUTE_MATRICES"
#endif
////////////////////////////////////////////////////////////////////////////////
#define GrGLConfig_chrome_DEFINED
// chrome always assumes BGRA
-#define GR_GL_32BPP_COLOR_FORMAT GR_GL_BGRA
+#define GR_GL_32BPP_COLOR_FORMAT GR_GL_BGRA
// glGetError() forces a sync with gpu process on chrome
-#define GR_GL_CHECK_ERROR_START 0
+#define GR_GL_CHECK_ERROR_START 0
+
+// ANGLE creates a temp VB for vertex attributes not specified per-vertex.
+#define GR_GL_NO_CONSTANT_ATTRIBUTES GR_WIN32_BUILD
#endif
* Type used to describe format of vertices in arrays
* Values are defined in GrDrawTarget
*/
-typedef uint16_t GrVertexLayout;
+typedef int GrVertexLayout;
/**
* Geometric primitives used for drawing.
} // namespace
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
#define VIEW_MATRIX_NAME "aViewM"
#else
#define VIEW_MATRIX_NAME "uViewM"
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
+#define COL_UNI_NAME "uColor"
// for variable names etc
typedef GrSStringBuilder<16> GrTokenString;
}
static void tex_matrix_name(int stage, GrStringBuilder* s) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
*s = "aTexM";
#else
*s = "uTexM";
memset(&programData->fUniLocations, 0, sizeof(UniLocations));
- bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
- fProgramDesc.fOptFlags);
-
-#if ATTRIBUTE_MATRIX
- segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n";
+#if GR_GL_ATTRIBUTE_MATRICES
+ segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
#else
- segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
- segments.fVSAttrs = "";
+ segments.fVSUnis += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
#endif
segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
- if (haveColor) {
- segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
- segments.fVaryings = "varying vec4 vColor;\n";
- } else {
- segments.fVaryings = "";
- }
segments.fVSCode = "void main() {\n"
"\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
"\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
- if (haveColor) {
+
+ // incoming color to current stage being processed.
+ GrTokenString inColor;
+
+ switch (fProgramDesc.fColorType) {
+ case ProgramDesc::kAttribute_ColorType:
+ segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
+ segments.fVaryings += "varying vec4 vColor;\n";
segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
+ inColor = "vColor";
+ break;
+ case ProgramDesc::kUniform_ColorType:
+ segments.fFSUnis += "uniform vec4 " COL_UNI_NAME ";\n";
+ inColor = COL_UNI_NAME;
+ break;
+ case ProgramDesc::kNone_ColorType:
+ inColor = "";
+ break;
}
- if (!(fProgramDesc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)) {
+ if (fProgramDesc.fEmitsPointSize){
segments.fVSCode += "\tgl_PointSize = 1.0;\n";
}
+
segments.fFSCode = "void main() {\n";
// add texture coordinates that are used to the list of vertex attr decls
}
}
- GrTokenString inColor = "vColor";
-
// if we have active stages string them together, feeding the output color
// of each to the next and generating code for each stage.
if (numActiveStages) {
genStageCode(s,
fProgramDesc.fStages[s],
- haveColor ? inColor.cstr() : NULL,
+ inColor.length() ? inColor.cstr() : NULL,
outColor.cstr(),
stageInCoords[s],
&segments,
&programData->fUniLocations.fStages[s]);
++currActiveStage;
inColor = outColor;
- haveColor = true;
}
}
} else {
segments.fFSCode += "\tgl_FragColor = ";
- if (haveColor) {
+ if (inColor.length()) {
segments.fFSCode += inColor;
} else {
segments.fFSCode += "vec4(1,1,1,1)";
}
}
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
// set unis to a bogus value so that checks against -1 before
// flushing will pass.
GR_GL(BindAttribLocation(progID,
}
// Get uniform locations
-#if !ATTRIBUTE_MATRIX
+#if !GR_GL_ATTRIBUTE_MATRICES
programData->fUniLocations.fViewMatrixUni =
GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
GrAssert(-1 != programData->fUniLocations.fViewMatrixUni);
#endif
+ if (ProgramDesc::kUniform_ColorType == fProgramDesc.fColorType) {
+ programData->fUniLocations.fColorUni =
+ GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
+ GrAssert(-1 != programData->fUniLocations.fColorUni);
+ } else {
+ programData->fUniLocations.fColorUni = -1;
+ }
+
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
StageUniLocations& locations = programData->fUniLocations.fStages[s];
if (fProgramDesc.fStages[s].fEnabled) {
-#if !ATTRIBUTE_MATRIX
+#if !GR_GL_ATTRIBUTE_MATRICES
if (locations.fTextureMatrixUni) {
GrTokenString texMName;
tex_matrix_name(s, &texMName);
if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
varyingDims = coordDims;
} else {
- #if ATTRIBUTE_MATRIX
+ #if GR_GL_ATTRIBUTE_MATRICES
segments->fVSAttrs += "attribute mat3 ";
segments->fVSAttrs += texMName;
segments->fVSAttrs += ";\n";
//Parameters that affect code generation
struct ProgramDesc {
+ ProgramDesc() {
+ // since we use this as part of a key we can't have any unitialized
+ // padding
+ memset(this, 0, sizeof(ProgramDesc));
+ }
+
+ // stripped of bits that don't affect prog generation
GrVertexLayout fVertexLayout;
enum {
- kNotPoints_OptFlagBit = 0x1,
- kVertexColorAllOnes_OptFlagBit = 0x2,
- };
- // we're assuming optflags and layout pack into 32 bits
- // VS 2010 seems to require short rather than just unsigned
- // for this to pack
- unsigned short fOptFlags : 16;
+ kNone_ColorType = 0,
+ kAttribute_ColorType = 1,
+ kUniform_ColorType = 2,
+ } fColorType;
+
+ bool fEmitsPointSize;
struct StageDesc {
enum OptFlagBits {
} fStages[GrDrawTarget::kNumStages];
} fProgramDesc;
+ const ProgramDesc& getDesc() { return fProgramDesc; }
+
public:
struct StageUniLocations {
GrGLint fTextureMatrixUni;
struct UniLocations {
GrGLint fViewMatrixUni;
+ GrGLint fColorUni;
StageUniLocations fStages[GrDrawTarget::kNumStages];
};
// these reflect the current values of uniforms
// (GL uniform values travel with program)
+ GrColor fColor;
GrMatrix fTextureMatrices[GrDrawTarget::kNumStages];
GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages];
GrScalar fRadial2Radius0[GrDrawTarget::kNumStages];
#include "GrNoncopyable.h"
#include "GrStringBuilder.h"
-#define ATTRIBUTE_MATRIX 0
#define PRINT_SHADERS 0
#define SKIP_CACHE_CHECK true
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
-#if ATTRIBUTE_MATRIX
-#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
-#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
-#define BOGUS_MATRIX_UNI_LOCATION 1000
+#if GR_GL_ATTRIBUTE_MATRICES
+ #define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
+ #define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
+ #define BOGUS_MATRIX_UNI_LOCATION 1000
#endif
#include "GrTHashCache.h"
}
const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
return fHWDrawState.fSamplerStates[stage].getMatrix();
#else
GrAssert(fProgramData);
}
void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
#else
GrAssert(fProgramData);
m[GrMatrix::kTransY],
m[GrMatrix::kPersp2]
};
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
m[GrMatrix::kTransY],
m[GrMatrix::kPersp2]
};
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
unis));
}
+void GrGpuGLShaders::flushColor() {
+ const GrGLProgram::ProgramDesc& desc = fCurrentProgram.getDesc();
+ if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
+ // color will be specified per-vertex as an attribute
+ // invalidate the const vertex attrib color
+ fHWDrawState.fColor = GrColor_ILLEGAL;
+ } else {
+ switch (desc.fColorType) {
+ case GrGLProgram::ProgramDesc::kAttribute_ColorType:
+ if (fHWDrawState.fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColor) / 255.f
+ };
+ GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
+ fHWDrawState.fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case GrGLProgram::ProgramDesc::kUniform_ColorType:
+ if (fProgramData->fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColor) / 255.f
+ };
+ GrAssert(-1 != fProgramData->fUniLocations.fColorUni);
+ GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 1, c));
+ fProgramData->fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case GrGLProgram::ProgramDesc::kNone_ColorType:
+ GrAssert(0xffffffff == fCurrDrawState.fColor);
+ break;
+ default:
+ GrCrash("Unknown color type.");
+ }
+ }
+}
+
+
bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
if (!flushGLStateCommon(type)) {
return false;
if (fDirtyFlags.fRenderTargetChanged) {
// our coords are in pixel space and the GL matrices map to NDC
// so if the viewport changed, our matrix is now wrong.
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
#else
// we assume all shader matrices may be wrong after viewport changes
#endif
}
- if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
- // invalidate the immediate mode color
- fHWDrawState.fColor = GrColor_ILLEGAL;
- } else {
- if (fHWDrawState.fColor != fCurrDrawState.fColor) {
- // OpenGL ES only supports the float varities of glVertexAttrib
- float c[] = {
- GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackA(fCurrDrawState.fColor) / 255.f
- };
- GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
- fHWDrawState.fColor = fCurrDrawState.fColor;
- }
- }
-
buildProgram(type);
fProgramData = fProgramCache->getProgramData(fCurrentProgram, this);
return false;
}
-#if ATTRIBUTE_MATRIX
+ flushColor();
+
+#if GR_GL_ATTRIBUTE_MATRICES
GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
#else
GrMatrix& currViewMatrix = fProgramData->fViewMatrix;
}
void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
+ GrGLProgram::ProgramDesc& desc = fCurrentProgram.fProgramDesc;
+
// Must initialize all fields or cache will have false negatives!
- fCurrentProgram.fProgramDesc.fVertexLayout = fGeometrySrc.fVertexLayout;
+ desc.fVertexLayout = fGeometrySrc.fVertexLayout;
+
+ desc.fEmitsPointSize = kPoints_PrimitiveType == type;
+
+ bool requiresAttributeColors = desc.fVertexLayout & kColor_VertexLayoutBit;
+ // fColorType records how colors are specified for the program. Strip
+ // the bit from the layout to avoid false negatives when searching for an
+ // existing program in the cache.
+ desc.fVertexLayout &= ~(kColor_VertexLayoutBit);
- fCurrentProgram.fProgramDesc.fOptFlags = 0;
- if (kPoints_PrimitiveType != type) {
- fCurrentProgram.fProgramDesc.fOptFlags |= GrGLProgram::ProgramDesc::kNotPoints_OptFlagBit;
- }
#if GR_AGGRESSIVE_SHADER_OPTS
- if (!(fCurrentProgram.fProgramDesc.fVertexLayout & kColor_VertexLayoutBit) &&
- (0xffffffff == fCurrDrawState.fColor)) {
- fCurrentProgram.fProgramDesc.fOptFlags |= GrGLProgram::ProgramDesc::kVertexColorAllOnes_OptFlagBit;
- }
+ if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
+ desc.fColorType = ProgramDesc::kNone_ColorType;
+ } else
+#endif
+#if GR_GL_NO_CONSTANT_ATTRIBUTES
+ if (!requiresAttributeColors) {
+ desc.fColorType = GrGLProgram::ProgramDesc::kUniform_ColorType;
+ } else
#endif
+ {
+ desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
+ }
for (int s = 0; s < kNumStages; ++s) {
- GrGLProgram::ProgramDesc::StageDesc& stage = fCurrentProgram.fProgramDesc.fStages[s];
+ GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
// sets the texture matrix uniform for currently bound program
void flushTextureMatrix(int stage);
+ // sets the color specified by GrDrawTarget::setColor()
+ void flushColor();
+
// sets the MVP matrix uniform for currently bound program
void flushViewMatrix();
#include "GrMemory.h"
#include "GrStringBuilder.h"
-
-#define ATTRIBUTE_MATRIX 0
-
#define PRINT_SHADERS 0
-#define SKIP_CACHE_CHECK true
+#define SKIP_CACHE_CHECK true
#define POS_ATTR_LOCATION 0
#define TEX_ATTR_LOCATION(X) (1 + X)
#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords)
-#if ATTRIBUTE_MATRIX
-#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
-#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
-#define BOGUS_MATRIX_UNI_LOCATION 1000
+#if GR_GL_ATTRIBUTE_MATRICES
+ #define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
+ #define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
+ #define BOGUS_MATRIX_UNI_LOCATION 1000
#endif
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
struct GrGpuGLShaders2::UniLocations {
GrGLint fViewMatrixUni;
+ GrGLint fColorUni;
StageUniLocations fStages[kNumStages];
};
// these reflect the current values of uniforms
// (GL uniform values travel with program)
GrMatrix fViewMatrix;
+ GrColor fColor;
GrMatrix fTextureMatrices[kNumStages];
GrScalar fRadial2CenterX1[kNumStages];
GrScalar fRadial2Radius0[kNumStages];
// must be tightly packed
struct GrGpuGLShaders2::ProgramDesc {
- GrVertexLayout fVertexLayout;
- GR_STATIC_ASSERT(2 == sizeof(GrVertexLayout)); // pack with next field
+ ProgramDesc() {
+ // since we use this as a key we can't have any unitialized padding
+ memset(this, 0, sizeof(ProgramDesc));
+ }
+ GrVertexLayout fVertexLayout; // stripped of bits that don't affect
+ // program generation.
enum {
- kNotPoints_OptFlagBit = 0x1,
- kVertexColorAllOnes_OptFlagBit = 0x2,
- };
- // we're assuming optflags and layout pack into 32 bits
- // VS 2010 seems to require short rather than just unsigned
- // for this to pack
- unsigned short fOptFlags : 16;
+ kNone_ColorType = 0,
+ kAttribute_ColorType = 1,
+ kUniform_ColorType = 2,
+ } fColorType;
+ bool fEmitsPointSize;
StageDesc fStages[kNumStages];
bool operator == (const ProgramDesc& desc) const {
- // keep 4-byte aligned and tightly packed
- GR_STATIC_ASSERT(4 == sizeof(StageDesc));
- GR_STATIC_ASSERT(2 + 2 + 4 * kNumStages == sizeof(ProgramDesc));
return 0 == memcmp(this, &desc, sizeof(ProgramDesc));
}
};
GrGpuGLShaders2::ProgramCache::HashKey::HashKey() {
}
-static uint32_t ror(uint32_t x) {
+static inline uint32_t ror(uint32_t x) {
return (x >> 8) | (x << 24);
}
-static uint32_t rol(uint32_t x) {
+static inline uint32_t rol(uint32_t x) {
return (x << 8) | (x >> 24);
}
+static inline uint32_t roh(uint32_t x) {
+ return (x << 16) | (x >> 16);
+}
+
+static inline uint32_t swapouter(uint32_t x) {
+ return (x & 0x00ff00) | (x << 24) | (x >> 24);
+}
+
GrGpuGLShaders2::ProgramCache::HashKey::HashKey(const ProgramDesc& desc) {
fDesc = desc;
// if you change the size of the desc, need to update the hash function
- GR_STATIC_ASSERT(12 == sizeof(ProgramDesc));
+ GR_STATIC_ASSERT(20 == sizeof(ProgramDesc));
uint32_t* d = GrTCast<uint32_t*>(&fDesc);
- fHash = d[0] ^ ror(d[1]) ^ rol(d[2]);
+ fHash = d[0] ^ ror(d[1]) ^ rol(d[2]) ^ roh(d[3]) ^ swapouter(d[4]);
}
bool GrGpuGLShaders2::ProgramCache::HashKey::EQ(const Entry& entry,
// for variable names etc
typedef GrSStringBuilder<16> GrTokenString;
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
#define VIEW_MATRIX_NAME "aViewM"
#else
#define VIEW_MATRIX_NAME "uViewM"
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
+#define COL_UNI_NAME "uColor"
static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
*s = "aTexCoord";
}
static void tex_matrix_name(int stage, GrStringBuilder* s) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
*s = "aTexM";
#else
*s = "uTexM";
#include "GrRandom.h"
void GrGpuGLShaders2::ProgramUnitTest() {
- static const int PROG_OPTS[] = {
- 0,
- ProgramDesc::kNotPoints_OptFlagBit,
- ProgramDesc::kVertexColorAllOnes_OptFlagBit,
- ProgramDesc::kNotPoints_OptFlagBit | ProgramDesc::kVertexColorAllOnes_OptFlagBit
- };
+
static const int STAGE_OPTS[] = {
0,
StageDesc::kNoPerspective_OptFlagBit,
for (int t = 0; t < NUM_TESTS; ++t) {
pdesc.fVertexLayout = 0;
+ pdesc.fEmitsPointSize = random.nextF() > .5f;
+ float colorType = random.nextF();
+ if (colorType < 1.f / 3.f) {
+ pdesc.fColorType = ProgramDesc::kAttribute_ColorType;
+ } else if (colorType < 2.f / 3.f) {
+ pdesc.fColorType = ProgramDesc::kUniform_ColorType;
+ } else {
+ pdesc.fColorType = ProgramDesc::kNone_ColorType;
+ }
for (int s = 0; s < kNumStages; ++s) {
// enable the stage?
if (random.nextF() > .5f) {
}
}
- int x = (int)(random.nextF() * GR_ARRAY_COUNT(PROG_OPTS));
- pdesc.fOptFlags = PROG_OPTS[x];
for (int s = 0; s < kNumStages; ++s) {
+ int x;
pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
varyingDims = coordDims;
} else {
- #if ATTRIBUTE_MATRIX
+ #if GR_GL_ATTRIBUTE_MATRICES
segments->fVSAttrs += "attribute mat3 ";
segments->fVSAttrs += texMName;
segments->fVSAttrs += ";\n";
memset(&program->fUniLocations, 0, sizeof(UniLocations));
- bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
- desc.fOptFlags);
-
-#if ATTRIBUTE_MATRIX
- segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n";
+#if GR_GL_ATTRIBUTE_MATRICES
+ segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
#else
- segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
- segments.fVSAttrs = "";
+ segments.fVSUnis += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
#endif
segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
- if (haveColor) {
- segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
- segments.fVaryings = "varying vec4 vColor;\n";
- } else {
- segments.fVaryings = "";
- }
- segments.fVSCode = "void main() {\n"
- "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
- if (haveColor) {
+ segments.fVSCode += "void main() {\n"
+ "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
+ "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
+
+ // incoming color to current stage being processed.
+ GrTokenString inColor;
+
+ switch (desc.fColorType) {
+ case ProgramDesc::kAttribute_ColorType:
+ segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
+ segments.fVaryings += "varying vec4 vColor;\n";
segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
+ inColor = "vColor";
+ break;
+ case ProgramDesc::kUniform_ColorType:
+ segments.fFSUnis += "uniform vec4 " COL_UNI_NAME ";\n";
+ inColor = COL_UNI_NAME;
+ break;
+ case ProgramDesc::kNone_ColorType:
+ inColor = "";
+ break;
}
- if (!(desc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)){
+ if (desc.fEmitsPointSize){
segments.fVSCode += "\tgl_PointSize = 1.0;\n";
}
- segments.fFSCode = "void main() {\n";
+ segments.fFSCode += "void main() {\n";
// add texture coordinates that are used to the list of vertex attr decls
GrTokenString texCoordAttrs[kMaxTexCoords];
}
}
- GrTokenString inColor = "vColor";
-
// if we have active stages string them together, feeding the output color
// of each to the next and generating code for each stage.
if (numActiveStages) {
}
GenStageCode(s,
desc.fStages[s],
- haveColor ? inColor.cstr() : NULL,
+ inColor.length() ? inColor.cstr() : NULL,
outColor.cstr(),
stageInCoords[s],
&segments,
&program->fUniLocations.fStages[s]);
++currActiveStage;
inColor = outColor;
- haveColor = true;
}
}
} else {
segments.fFSCode += "\tgl_FragColor = ";
- if (haveColor) {
+ if (inColor.length()) {
segments.fFSCode += inColor;
} else {
segments.fFSCode += "vec4(1,1,1,1)";
}
}
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
// set unis to a bogus value so that checks against -1 before
// flushing will pass.
GR_GL(BindAttribLocation(progID,
}
// Get uniform locations
-#if !ATTRIBUTE_MATRIX
+#if !GR_GL_ATTRIBUTE_MATRICES
program->fUniLocations.fViewMatrixUni =
GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
GrAssert(-1 != program->fUniLocations.fViewMatrixUni);
#endif
+ if (ProgramDesc::kUniform_ColorType == desc.fColorType) {
+ program->fUniLocations.fColorUni =
+ GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
+ GrAssert(-1 != program->fUniLocations.fColorUni);
+ } else {
+ program->fUniLocations.fColorUni = -1;
+ }
+
for (int s = 0; s < kNumStages; ++s) {
StageUniLocations& locations = program->fUniLocations.fStages[s];
if (desc.fStages[s].fEnabled) {
-#if !ATTRIBUTE_MATRIX
+#if !GR_GL_ATTRIBUTE_MATRICES
if (locations.fTextureMatrixUni) {
GrTokenString texMName;
tex_matrix_name(s, &texMName);
program->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
program->fRadial2CenterX1[s] = GR_ScalarMax;
program->fRadial2Radius0[s] = -GR_ScalarMax;
+ program->fColor = GrColor_ILLEGAL;
}
program->fViewMatrix = GrMatrix::InvalidMatrix();
}
// Must initialize all fields or cache will have false negatives!
desc->fVertexLayout = fGeometrySrc.fVertexLayout;
- desc->fOptFlags = 0;
- if (kPoints_PrimitiveType != primType) {
- desc->fOptFlags |= ProgramDesc::kNotPoints_OptFlagBit;
- }
+ desc->fEmitsPointSize = kPoints_PrimitiveType == primType;
+
+ bool requiresAttributeColors = desc->fVertexLayout & kColor_VertexLayoutBit;
+ // fColorType records how colors are specified for the program. Strip
+ // the bit from the layout to avoid false negatives when searching for an
+ // existing program in the cache.
+ desc->fVertexLayout &= ~(kColor_VertexLayoutBit);
+
#if GR_AGGRESSIVE_SHADER_OPTS
- if (!(desc->fVertexLayout & kColor_VertexLayoutBit) &&
- (0xffffffff == fCurrDrawState.fColor)) {
- desc->fOptFlags |= ProgramDesc::kVertexColorAllOnes_OptFlagBit;
- }
+ if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
+ desc->fColorType = ProgramDesc::kNone_ColorType;
+ } else
#endif
+#if GR_GL_NO_CONSTANT_ATTRIBUTES
+ if (!requiresAttributeColors) {
+ desc->fColorType = ProgramDesc::kUniform_ColorType;
+ } else
+#endif
+ {
+ desc->fColorType = ProgramDesc::kAttribute_ColorType;
+ }
for (int s = 0; s < kNumStages; ++s) {
StageDesc& stage = desc->fStages[s];
}
const GrMatrix& GrGpuGLShaders2::getHWSamplerMatrix(int stage) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
return fHWDrawState.fSamplerStates[stage].getMatrix();
#else
return fProgram->fTextureMatrices[stage];
}
void GrGpuGLShaders2::recordHWSamplerMatrix(int stage, const GrMatrix& matrix){
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
#else
fProgram->fTextureMatrices[stage] = matrix;
m[GrMatrix::kTransY],
m[GrMatrix::kPersp2]
};
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
m[GrMatrix::kTransY],
m[GrMatrix::kPersp2]
};
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
unis));
}
-void GrGpuGLShaders2::flushProgram(GrPrimitiveType type) {
- ProgramDesc desc;
- getProgramDesc(type, &desc);
- fProgram = fProgramCache->getProgram(desc);
+void GrGpuGLShaders2::flushProgram(GrPrimitiveType type, ProgramDesc* desc) {
+ getProgramDesc(type, desc);
+ fProgram = fProgramCache->getProgram(*desc);
if (fHWProgramID != fProgram->fProgramID) {
GR_GL(UseProgram(fProgram->fProgramID));
}
}
+void GrGpuGLShaders2::flushColor(const ProgramDesc& desc) {
+ if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
+ // color will be specified per-vertex as an attribute
+ // invalidate the const vertex attrib color
+ fHWDrawState.fColor = GrColor_ILLEGAL;
+ } else {
+ switch (desc.fColorType) {
+ case ProgramDesc::kAttribute_ColorType:
+ if (fHWDrawState.fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColor) / 255.f
+ };
+ GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
+ fHWDrawState.fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case ProgramDesc::kUniform_ColorType:
+ if (fProgram->fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColor) / 255.f
+ };
+ GrAssert(-1 != fProgram->fUniLocations.fColorUni);
+ GR_GL(Uniform4fv(fProgram->fUniLocations.fColorUni, 1, c));
+ fProgram->fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case ProgramDesc::kNone_ColorType:
+ GrAssert(0xffffffff == fCurrDrawState.fColor);
+ break;
+ default:
+ GrCrash("Unknown color type.");
+ }
+ }
+}
+
bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
if (!flushGLStateCommon(type)) {
if (fDirtyFlags.fRenderTargetChanged) {
// our coords are in pixel space and the GL matrices map to NDC
// so if the viewport changed, our matrix is now wrong.
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
#else
// we assume all shader matrices may be wrong after viewport changes
#endif
}
- flushProgram(type);
+ ProgramDesc desc;
+ flushProgram(type, &desc);
- if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
- // invalidate the immediate mode color
- fHWDrawState.fColor = GrColor_ILLEGAL;
- } else {
- if (fHWDrawState.fColor != fCurrDrawState.fColor &&
- (!GR_AGGRESSIVE_SHADER_OPTS || 0xffffffff != fCurrDrawState.fColor)) {
- // avoid pushing the color attrib if the shader will optimize it out
-
- // OpenGL ES only supports the float varities of glVertexAttrib
- float c[] = {
- GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackA(fCurrDrawState.fColor) / 255.f
- };
- GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
- fHWDrawState.fColor = fCurrDrawState.fColor;
- }
- }
+ flushColor(desc);
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
#else
GrMatrix& currViewMatrix = fProgram->fViewMatrix;
private:
+ struct Program;
+
+ struct StageDesc;
+ struct ProgramDesc;
+
+ struct UniLocations;
+ struct StageUniLocations;
+
+ struct ShaderCodeSegments;
+
+ class ProgramCache;
+
+ // GrGpu override
virtual void resetContext();
// Helpers to make code more readable
// flushes the parameters to two point radial gradient
void flushRadial2(int stage);
- // called at flush time to setup the appropriate program
- void flushProgram(GrPrimitiveType type);
+ // called at flush time to setup the appropriate program, also returns
+ // the program description.
+ void flushProgram(GrPrimitiveType type, ProgramDesc* desc);
- struct Program;
-
- struct StageDesc;
- struct ProgramDesc;
-
- struct UniLocations;
- struct StageUniLocations;
-
- struct ShaderCodeSegments;
-
- class ProgramCache;
+ // called at flush time to handle the color specified by setColor()
+ void flushColor(const ProgramDesc& desc);
// gets a description of needed shader
void getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc);
ProgramCache* fProgramCache;
Program* fProgram;
- GrGLuint fHWProgramID;
+ GrGLuint fHWProgramID;
typedef GrGpuGL INHERITED;
};