Remove unused texture coordinate flags.

Currently we support 5 texture stages, each with 5 possible texture coordinate attributes.
However, we only ever use one explicit texture coordinate. This change removes all but one 
(now named just "aTexCoord") of the possible explicit texture coordinates.

Review URL: https://codereview.appspot.com/7308094/


git-svn-id: http://skia.googlecode.com/svn/trunk@7737 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
jvanverth@google.com 2013-02-14 15:25:44 +00:00
parent 682e1f9245
commit 3976825a21
13 changed files with 216 additions and 431 deletions

View File

@ -312,7 +312,7 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
static const GrVertexLayout layout = GrDrawState::StageTexCoordVertexLayoutBit(0,0);
static const GrVertexLayout layout = GrDrawState::StageTexCoordVertexLayoutBit(0);
drawState->setVertexLayout(layout);
GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
@ -853,12 +853,7 @@ void GrContext::drawRectToRect(const GrPaint& paint,
#else
GrDrawState::AutoStageDisable atr(fDrawState);
const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
const SkMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
srcRects[0] = &srcRect;
srcMatrices[0] = srcMatrix;
target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices);
target->drawRect(dstRect, dstMatrix, &srcRect, srcMatrix, 0);
#endif
}
@ -879,7 +874,7 @@ void GrContext::drawVertices(const GrPaint& paint,
GrVertexLayout layout = 0;
if (NULL != texCoords) {
layout |= GrDrawState::StageTexCoordVertexLayoutBit(0, 0);
layout |= GrDrawState::StageTexCoordVertexLayoutBit(0);
}
if (NULL != colors) {
layout |= GrDrawState::kColor_VertexLayoutBit;
@ -892,20 +887,20 @@ void GrContext::drawVertices(const GrPaint& paint,
GrPrintf("Failed to get space for vertices!\n");
return;
}
int texOffsets[GrDrawState::kMaxTexCoords];
int texOffset;
int colorOffset;
GrDrawState::VertexSizeAndOffsetsByIdx(layout,
texOffsets,
&colorOffset,
NULL,
NULL);
GrDrawState::VertexSizeAndOffsets(layout,
&texOffset,
&colorOffset,
NULL,
NULL);
void* curVertex = geo.vertices();
for (int i = 0; i < vertexCount; ++i) {
*((GrPoint*)curVertex) = positions[i];
if (texOffsets[0] > 0) {
*(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
if (texOffset > 0) {
*(GrPoint*)((intptr_t)curVertex + texOffset) = texCoords[i];
}
if (colorOffset > 0) {
*(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];

View File

@ -49,100 +49,25 @@ void GrDrawState::setFromPaint(const GrPaint& paint) {
namespace {
/**
* This function generates some masks that we like to have known at compile
* time. When the number of stages or tex coords is bumped or the way bits
* are defined in GrDrawState.h changes this function should be rerun to
* generate the new masks. (We attempted to force the compiler to generate the
* masks using recursive templates but always wound up with static initializers
* under gcc, even if they were just a series of immediate->memory moves.)
* This function generates a mask that we like to have known at compile
* time. When the number of stages is bumped or the way bits are defined in
* GrDrawState.h changes this function should be rerun to generate the new mask.
* (We attempted to force the compiler to generate the mask using recursive
* templates but always wound up with static initializers under gcc, even if
* they were just a series of immediate->memory moves.)
*
*/
void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
GrVertexLayout* texCoordMasks) {
void gen_tex_coord_mask(GrVertexLayout* texCoordMask) {
*texCoordMask = 0;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
stageTexCoordMasks[s] = 0;
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
stageTexCoordMasks[s] |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
}
}
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
texCoordMasks[t] = 0;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
texCoordMasks[t] |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
}
*texCoordMask |= GrDrawState::StageTexCoordVertexLayoutBit(s);
}
}
/**
* Uncomment and run the gen_globals function to generate
* the code that declares the global masks.
*
* #if 0'ed out to avoid unused function warning.
*/
const GrVertexLayout kTexCoordMask = (1 << GrDrawState::kNumStages)-1;
#if 0
void gen_globals() {
GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
}
GrPrintf("};\n");
GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
GrPrintf(" 0x%x,\n", texCoordMasks[t]);
}
GrPrintf("};\n");
GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
}
#endif
/* These values were generated by the above function */
const GrVertexLayout gStageTexCoordMasks[] = {
0x108421,
0x210842,
0x421084,
0x842108,
0x1084210,
};
GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
const GrVertexLayout gTexCoordMasks[] = {
0x1f,
0x3e0,
0x7c00,
0xf8000,
0x1f00000,
};
GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
#ifdef SK_DEBUG
bool check_layout(GrVertexLayout layout) {
// can only have 1 or 0 bits set for each stage.
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
int stageBits = layout & gStageTexCoordMasks[s];
if (stageBits && !GrIsPow2(stageBits)) {
return false;
}
}
return true;
}
#endif
int num_tex_coords(GrVertexLayout layout) {
int cnt = 0;
// figure out how many tex coordinates are present
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
if (gTexCoordMasks[t] & layout) {
++cnt;
}
}
return cnt;
inline int num_tex_coords(GrVertexLayout layout) {
return (kTexCoordMask & layout) ? 1 : 0;
}
} //unnamed namespace
@ -150,8 +75,6 @@ int num_tex_coords(GrVertexLayout layout) {
static const size_t kVec2Size = sizeof(GrPoint);
size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
size_t size = kVec2Size; // position
size += num_tex_coords(vertexLayout) * kVec2Size;
if (vertexLayout & kColor_VertexLayoutBit) {
@ -174,38 +97,20 @@ size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) {
*
* Order of vertex components:
* Position
* Tex Coord 0
* ...
* Tex Coord GrDrawState::kMaxTexCoords-1
* Tex Coord
* Color
* Coverage
*/
int GrDrawState::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
return 0;
}
int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
if (tcIdx >= 0) {
int offset = kVec2Size; // position
// figure out how many tex coordinates are present and precede this one.
for (int t = 0; t < tcIdx; ++t) {
if (gTexCoordMasks[t] & vertexLayout) {
offset += kVec2Size;
}
}
return offset;
}
return -1;
return kVec2Size;
}
int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
if (vertexLayout & kColor_VertexLayoutBit) {
return kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos
}
@ -213,8 +118,6 @@ int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) {
}
int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
if (vertexLayout & kCoverage_VertexLayoutBit) {
int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1);
if (vertexLayout & kColor_VertexLayoutBit) {
@ -226,8 +129,6 @@ int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) {
}
int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
// edge pts are after the pos, tex coords, and color
if (vertexLayout & kEdge_VertexLayoutBit) {
int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos
@ -242,26 +143,22 @@ int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) {
return -1;
}
int GrDrawState::VertexSizeAndOffsetsByIdx(
int GrDrawState::VertexSizeAndOffsets(
GrVertexLayout vertexLayout,
int texCoordOffsetsByIdx[kMaxTexCoords],
int* texCoordOffset,
int* colorOffset,
int* coverageOffset,
int* edgeOffset) {
GrAssert(check_layout(vertexLayout));
int size = kVec2Size; // position
for (int t = 0; t < kMaxTexCoords; ++t) {
if (gTexCoordMasks[t] & vertexLayout) {
if (NULL != texCoordOffsetsByIdx) {
texCoordOffsetsByIdx[t] = size;
}
size += kVec2Size;
} else {
if (NULL != texCoordOffsetsByIdx) {
texCoordOffsetsByIdx[t] = -1;
}
if (kTexCoordMask & vertexLayout) {
if (NULL != texCoordOffset) {
*texCoordOffset = size;
}
size += kVec2Size;
} else {
if (NULL != texCoordOffset) {
*texCoordOffset = -1;
}
}
if (kColor_VertexLayoutBit & vertexLayout) {
@ -303,21 +200,17 @@ int GrDrawState::VertexSizeAndOffsetsByStage(
int* colorOffset,
int* coverageOffset,
int* edgeOffset) {
GrAssert(check_layout(vertexLayout));
int texCoordOffsetsByIdx[kMaxTexCoords];
int size = VertexSizeAndOffsetsByIdx(vertexLayout,
(NULL == texCoordOffsetsByStage) ?
NULL :
texCoordOffsetsByIdx,
colorOffset,
coverageOffset,
edgeOffset);
int texCoordOffset;
int size = VertexSizeAndOffsets(vertexLayout,
&texCoordOffset,
colorOffset,
coverageOffset,
edgeOffset);
if (NULL != texCoordOffsetsByStage) {
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
texCoordOffsetsByStage[s] =
tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
texCoordOffsetsByStage[s] = StageUsesTexCoords(vertexLayout, s) ?
texCoordOffset : 0;
}
}
return size;
@ -325,131 +218,93 @@ int GrDrawState::VertexSizeAndOffsetsByStage(
////////////////////////////////////////////////////////////////////////////////
bool GrDrawState::VertexUsesTexCoordIdx(int coordIndex,
GrVertexLayout vertexLayout) {
GrAssert(coordIndex < kMaxTexCoords);
GrAssert(check_layout(vertexLayout));
return !!(gTexCoordMasks[coordIndex] & vertexLayout);
}
int GrDrawState::VertexTexCoordsForStage(int stageIdx,
GrVertexLayout vertexLayout) {
GrAssert(stageIdx < GrDrawState::kNumStages);
GrAssert(check_layout(vertexLayout));
int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
if (bit) {
// figure out which set of texture coordates is used
// bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
// and start at bit 0.
GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
}
return -1;
bool GrDrawState::VertexUsesTexCoords(GrVertexLayout vertexLayout) {
return SkToBool(kTexCoordMask & vertexLayout);
}
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::VertexLayoutUnitTest() {
// Ensure that our globals mask arrays are correct
GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
GrVertexLayout texCoordMasks[kMaxTexCoords];
gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
}
for (int t = 0; t < kMaxTexCoords; ++t) {
GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
}
// Ensure that our tex coord mask is correct
GrVertexLayout texCoordMask;
gen_tex_coord_mask(&texCoordMask);
GrAssert(texCoordMask == kTexCoordMask);
// not necessarily exhaustive
static bool run;
if (!run) {
run = true;
GrVertexLayout tcMask = 0;
GrAssert(!VertexUsesTexCoords(0));
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tcMask |= StageTexCoordVertexLayoutBit(s);
GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
GrAssert(VertexUsesTexCoords(tcMask));
GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
GrAssert(StageUsesTexCoords(tcMask, s));
for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
GrAssert(!StageUsesTexCoords(tcMask, s2));
GrVertexLayout stageMask = 0;
for (int t = 0; t < kMaxTexCoords; ++t) {
stageMask |= StageTexCoordVertexLayoutBit(s,t);
#if GR_DEBUG
GrVertexLayout posAsTex = tcMask;
#endif
GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
GrAssert(!StageUsesTexCoords(posAsTex, s2));
GrAssert(-1 == VertexEdgeOffset(posAsTex));
}
GrAssert(1 == kMaxTexCoords ||
!check_layout(stageMask));
GrAssert(gStageTexCoordMasks[s] == stageMask);
GrAssert(!check_layout(stageMask));
GrAssert(-1 == VertexEdgeOffset(tcMask));
GrAssert(-1 == VertexColorOffset(tcMask));
GrAssert(-1 == VertexCoverageOffset(tcMask));
#if GR_DEBUG
GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
#endif
GrAssert(-1 == VertexCoverageOffset(withColor));
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
#if GR_DEBUG
GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
#endif
GrAssert(-1 == VertexColorOffset(withEdge));
GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
#if GR_DEBUG
GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
#endif
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
#if GR_DEBUG
GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
#endif
GrAssert(-1 == VertexColorOffset(withCoverage));
GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
#if GR_DEBUG
GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
kColor_VertexLayoutBit;
#endif
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
}
for (int t = 0; t < kMaxTexCoords; ++t) {
GrVertexLayout tcMask = 0;
GrAssert(!VertexUsesTexCoordIdx(t, 0));
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tcMask |= StageTexCoordVertexLayoutBit(s,t);
GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
GrAssert(VertexUsesTexCoordIdx(t, tcMask));
GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
GrAssert(t == VertexTexCoordsForStage(s, tcMask));
for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
GrAssert(kTexCoordMask == tcMask);
#if GR_DEBUG
GrVertexLayout posAsTex = tcMask;
#endif
GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
GrAssert(-1 == VertexEdgeOffset(posAsTex));
}
GrAssert(-1 == VertexEdgeOffset(tcMask));
GrAssert(-1 == VertexColorOffset(tcMask));
GrAssert(-1 == VertexCoverageOffset(tcMask));
#if GR_DEBUG
GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
#endif
GrAssert(-1 == VertexCoverageOffset(withColor));
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
#if GR_DEBUG
GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
#endif
GrAssert(-1 == VertexColorOffset(withEdge));
GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
#if GR_DEBUG
GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
#endif
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
#if GR_DEBUG
GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
#endif
GrAssert(-1 == VertexColorOffset(withCoverage));
GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
#if GR_DEBUG
GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
kColor_VertexLayoutBit;
#endif
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
}
GrAssert(gTexCoordMasks[t] == tcMask);
GrAssert(check_layout(tcMask));
int stageOffsets[GrDrawState::kNumStages];
int colorOffset;
int edgeOffset;
int coverageOffset;
int size;
size = VertexSizeAndOffsetsByStage(tcMask,
stageOffsets, &colorOffset,
&coverageOffset, &edgeOffset);
GrAssert(2*sizeof(GrPoint) == size);
GrAssert(-1 == colorOffset);
GrAssert(-1 == coverageOffset);
GrAssert(-1 == edgeOffset);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
GrAssert(sizeof(GrPoint) == stageOffsets[s]);
GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
}
int stageOffsets[GrDrawState::kNumStages];
int colorOffset;
int edgeOffset;
int coverageOffset;
int size;
size = VertexSizeAndOffsetsByStage(tcMask,
stageOffsets, &colorOffset,
&coverageOffset, &edgeOffset);
GrAssert(2*sizeof(GrPoint) == size);
GrAssert(-1 == colorOffset);
GrAssert(-1 == coverageOffset);
GrAssert(-1 == edgeOffset);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
GrAssert(sizeof(GrPoint) == stageOffsets[s]);
GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
}
}
}
@ -457,7 +312,7 @@ void GrDrawState::VertexLayoutUnitTest() {
////////////////////////////////////////////////////////////////////////////////
bool GrDrawState::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
return SkToBool(layout & StageTexCoordVertexLayoutBit(stageIdx));
}
bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const {

View File

@ -55,7 +55,6 @@ public:
*/
enum {
kNumStages = 5,
kMaxTexCoords = kNumStages
};
GrDrawState() {
@ -114,45 +113,35 @@ public:
/**
* The format of vertices is represented as a bitfield of flags.
* Flags that indicate the layout of vertex data. Vertices always contain
* positions and may also contain up to GrDrawState::kMaxTexCoords sets
* of 2D texture coordinates, per-vertex colors, and per-vertex coverage.
* Each stage can
* use any of the texture coordinates as its input texture coordinates or it
* may use the positions as texture coordinates.
* positions and may also contain texture coordinates, per-vertex colors,
* and per-vertex coverage. Each stage can use any texture coordinates as
* its input texture coordinates or it may use the positions as texture
* coordinates.
*
* If no texture coordinates are specified for a stage then the stage is
* disabled.
*
* Only one type of texture coord can be specified per stage. For
* example StageTexCoordVertexLayoutBit(0, 2) and
* StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
*
* The order in memory is always (position, texture coord 0, ..., color,
* coverage) with any unused fields omitted. Note that this means that if
* only texture coordinates 1 is referenced then there is no texture
* coordinates 0 and the order would be (position, texture coordinate 1
* [, color][, coverage]).
* The order in memory is always (position, texture coords, color, coverage)
* with any unused fields omitted.
*/
/**
* Generates a bit indicating that a texture stage uses texture coordinates
*
* @param stageIdx the stage that will use texture coordinates.
* @param texCoordIdx the index of the texture coordinates to use
*
* @return the bit to add to a GrVertexLayout bitfield.
*/
static int StageTexCoordVertexLayoutBit(int stageIdx, int texCoordIdx) {
static int StageTexCoordVertexLayoutBit(int stageIdx) {
GrAssert(stageIdx < kNumStages);
GrAssert(texCoordIdx < kMaxTexCoords);
return 1 << (stageIdx + (texCoordIdx * kNumStages));
return (1 << stageIdx);
}
static bool StageUsesTexCoords(GrVertexLayout layout, int stageIdx);
private:
// non-stage bits start at this index.
static const int STAGE_BIT_CNT = kNumStages * kMaxTexCoords;
static const int STAGE_BIT_CNT = kNumStages;
public:
/**
@ -199,25 +188,10 @@ public:
*/
static size_t VertexSize(GrVertexLayout vertexLayout);
/**
* Helper function for determining the index of texture coordinates that
* is input for a texture stage. Note that a stage may instead use positions
* as texture coordinates, in which case the result of the function is
* indistinguishable from the case when the stage is disabled.
*
* @param stageIdx the stage to query
* @param vertexLayout layout to query
*
* @return the texture coordinate index or -1 if the stage doesn't use
* separate (non-position) texture coordinates.
*/
static int VertexTexCoordsForStage(int stageIdx, GrVertexLayout vertexLayout);
/**
* Helper function to compute the offset of texture coordinates in a vertex
* @return offset of texture coordinates in vertex layout or -1 if the
* layout has no texture coordinates. Will be 0 if positions are
* used as texture coordinates for the stage.
* @return offset of texture coordinates in vertex layout or 0 if positions
* are used as texture coordinates for the stage.
*/
static int VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout);
@ -244,27 +218,23 @@ public:
/**
* Helper function to determine if vertex layout contains explicit texture
* coordinates of some index.
* coordinates.
*
* @param coordIndex the tex coord index to query
* @param vertexLayout layout to query
*
* @return true if vertex specifies texture coordinates for the index,
* false otherwise.
* @return true if vertex specifies texture coordinates,
* false otherwise.
*/
static bool VertexUsesTexCoordIdx(int coordIndex,
GrVertexLayout vertexLayout);
static bool VertexUsesTexCoords(GrVertexLayout vertexLayout);
/**
* Helper function to compute the size of each vertex and the offsets of
* texture coordinates and color. Determines tex coord offsets by tex coord
* index rather than by stage. (Each stage can be mapped to any t.c. index
* by StageTexCoordVertexLayoutBit.)
* texture coordinates and color.
*
* @param vertexLayout the layout to query
* @param texCoordOffsetsByIdx after return it is the offset of each
* @param texCoordOffset after return it is the offset of the
* tex coord index in the vertex or -1 if
* index isn't used. (optional)
* tex coords aren't used. (optional)
* @param colorOffset after return it is the offset of the
* color field in each vertex, or -1 if
* there aren't per-vertex colors. (optional)
@ -278,8 +248,8 @@ public:
* (optional)
* @return size of a single vertex
*/
static int VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
int texCoordOffsetsByIdx[kMaxTexCoords],
static int VertexSizeAndOffsets(GrVertexLayout vertexLayout,
int *texCoordOffset,
int *colorOffset,
int *coverageOffset,
int* edgeOffset);

View File

@ -523,20 +523,15 @@ void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
void GrDrawTarget::drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* srcRects[],
const SkMatrix* srcMatrices[]) {
const GrRect* srcRect,
const SkMatrix* srcMatrix,
int stage) {
GrVertexLayout layout = 0;
uint32_t explicitCoordMask = 0;
if (NULL != srcRects) {
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
int numTC = 0;
if (NULL != srcRects[s]) {
layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
explicitCoordMask |= (1 << s);
++numTC;
}
}
if (NULL != srcRect) {
layout |= GrDrawState::StageTexCoordVertexLayoutBit(stage);
explicitCoordMask = (1 << stage);
}
GrDrawState::AutoViewMatrixRestore avmr;
@ -560,11 +555,11 @@ void GrDrawTarget::drawRect(const GrRect& rect,
GrAssert(0 != stageOffsets[i]);
GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
stageOffsets[i]);
coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
srcRects[i]->fRight, srcRects[i]->fBottom,
coords->setRectFan(srcRect->fLeft, srcRect->fTop,
srcRect->fRight, srcRect->fBottom,
vsize);
if (NULL != srcMatrices && NULL != srcMatrices[i]) {
srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
if (NULL != srcMatrix) {
srcMatrix->mapPointsWithStride(coords, vsize, 4);
}
} else {
GrAssert(0 == stageOffsets[i]);

View File

@ -385,39 +385,40 @@ public:
* have changed. They should be reestablished before the next drawIndexed
* or drawNonIndexed. This cannot be called between reserving and releasing
* geometry.
*
*
* A subclass may override this to perform more optimal rect rendering. Its
* draws should be funneled through one of the public GrDrawTarget draw methods
* (e.g. drawNonIndexed, drawIndexedInstances, ...). The base class draws a two
* triangle fan using drawNonIndexed from reserved vertex space.
*
*
* @param rect the rect to draw
* @param matrix optional matrix applied to rect (before viewMatrix)
* @param srcRects specifies rects for stages enabled by stageEnableMask.
* if stageEnableMask bit i is 1, srcRects is not NULL,
* and srcRects[i] is not NULL, then srcRects[i] will be
* used as coordinates for stage i. Otherwise, if stage i
* is enabled then rect is used as the coordinates.
* @param srcMatrices optional matrices applied to srcRects. If
* srcRect[i] is non-NULL and srcMatrices[i] is
* non-NULL then srcRect[i] will be transformed by
* srcMatrix[i]. srcMatrices can be NULL when no
* srcMatrices are desired.
* @param srcRects specifies rect for explicit texture coordinates.
* if srcRect is non-NULL then that rect will be used
* as the coordinates for the given stage.
* @param srcMatrix optional matrix applied to srcRect. If
* srcRect is non-NULL and srcMatrix is non-NULL
* then srcRect will be transformed by srcMatrix.
* srcMatrix can be NULL when no srcMatrix is desired.
* @param stage the stage to be given explicit texture coordinates.
* Ignored if srcRect is NULL.
*/
virtual void drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* srcRects[],
const SkMatrix* srcMatrices[]);
const GrRect* srcRect,
const SkMatrix* srcMatrix,
int stage);
/**
* Helper for drawRect when the caller doesn't need separate src rects or
* matrices.
*/
void drawSimpleRect(const GrRect& rect, const SkMatrix* matrix = NULL) {
drawRect(rect, matrix, NULL, NULL);
drawRect(rect, matrix, NULL, NULL, 0);
}
void drawSimpleRect(const GrIRect& irect, const SkMatrix* matrix = NULL) {
SkRect rect = SkRect::MakeFromIRect(irect);
this->drawRect(rect, matrix, NULL, NULL);
this->drawRect(rect, matrix, NULL, NULL, 0);
}
/**

View File

@ -72,8 +72,9 @@ void get_vertex_bounds(const void* vertices,
void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* srcRects[],
const SkMatrix* srcMatrices[]) {
const GrRect* srcRect,
const SkMatrix* srcMatrix,
int stage) {
GrVertexLayout layout = 0;
GrDrawState::AutoColorRestore acr;
@ -96,15 +97,9 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
}
uint32_t explicitCoordMask = 0;
if (NULL != srcRects) {
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
int numTC = 0;
if (NULL != srcRects[s]) {
layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
++numTC;
explicitCoordMask |= (1 << s);
}
}
if (NULL != srcRect) {
layout |= GrDrawState::StageTexCoordVertexLayoutBit(stage);
explicitCoordMask = (1 << stage);
}
this->drawState()->setVertexLayout(layout);
@ -122,7 +117,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
combinedMatrix.reset();
}
combinedMatrix.postConcat(this->drawState()->getViewMatrix());
// When the caller has provided an explicit source rects for a stage then we don't want to
// When the caller has provided an explicit source rect for a stage then we don't want to
// modify that stage's matrix. Otherwise if the effect is generating its source rect from
// the vertex positions then we have to account for the view matrix change.
GrDrawState::AutoDeviceCoordDraw adcd(this->drawState(), explicitCoordMask);
@ -147,11 +142,11 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
GrAssert(0 != stageOffsets[i]);
GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
stageOffsets[i]);
coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
srcRects[i]->fRight, srcRects[i]->fBottom,
coords->setRectFan(srcRect->fLeft, srcRect->fTop,
srcRect->fRight, srcRect->fBottom,
vsize);
if (NULL != srcMatrices && NULL != srcMatrices[i]) {
srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
if (NULL != srcMatrix) {
srcMatrix->mapPointsWithStride(coords, vsize, 4);
}
} else {
GrAssert(0 == stageOffsets[i]);

View File

@ -89,8 +89,9 @@ public:
GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
virtual void drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* srcRects[],
const SkMatrix* srcMatrices[]) SK_OVERRIDE;
const GrRect* srcRect,
const SkMatrix* srcMatrix,
int stage) SK_OVERRIDE;
protected:
virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;

View File

@ -203,13 +203,11 @@ void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
GrRect maskRect = GrRect::MakeWH(w / texture->width(),
h / texture->height());
const GrRect* srcRects[GrDrawState::kNumStages] = { NULL };
srcRects[kPathMaskStage] = &maskRect;
GrRect dstRect = GrRect::MakeLTRB(
SK_Scalar1 * rect.fLeft,
SK_Scalar1 * rect.fTop,
SK_Scalar1 * rect.fRight,
SK_Scalar1 * rect.fBottom);
target->drawRect(dstRect, NULL, srcRects, NULL);
target->drawRect(dstRect, NULL, &maskRect, NULL, kPathMaskStage);
drawState->disableStage(kPathMaskStage);
}

View File

@ -93,7 +93,7 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint(
fVertices = NULL;
fMaxVertices = 0;
fVertexLayout = GrDrawState::StageTexCoordVertexLayoutBit(kGlyphMaskStage, 0);
fVertexLayout = GrDrawState::StageTexCoordVertexLayoutBit(kGlyphMaskStage);
}
GrTextContext::~GrTextContext() {

View File

@ -25,19 +25,14 @@ SK_DEFINE_INST_COUNT(GrGLProgram)
SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, "Print the source code for all shaders generated.");
#define TEX_ATTR_NAME "aTexCoord"
#define COL_ATTR_NAME "aColor"
#define COV_ATTR_NAME "aCoverage"
#define EDGE_ATTR_NAME "aEdge"
namespace {
inline void tex_attr_name(int coordIdx, SkString* s) {
*s = "aTexCoord";
s->appendS32(coordIdx);
}
inline const char* declared_color_output_name() { return "fsColorOut"; }
inline const char* dual_source_output_name() { return "dualSourceOut"; }
}
void GrGLProgram::BuildDesc(const GrDrawState& drawState,
@ -731,14 +726,10 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
}
// add texture coordinates that are used to the list of vertex attr decls
SkString texCoordAttrs[GrDrawState::kMaxTexCoords];
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
if (GrDrawState::VertexUsesTexCoordIdx(t, layout)) {
tex_attr_name(t, texCoordAttrs + t);
builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
texCoordAttrs[t].c_str());
}
if (GrDrawState::VertexUsesTexCoords(layout)) {
builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
TEX_ATTR_NAME);
}
///////////////////////////////////////////////////////////////////////////
@ -757,13 +748,11 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
const char* inCoords;
// figure out what our input coords are
int tcIdx = GrDrawState::VertexTexCoordsForStage(s, layout);
if (tcIdx < 0) {
if (!GrDrawState::StageUsesTexCoords(layout, s)) {
inCoords = builder.positionAttribute().c_str();
} else {
// must have input tex coordinates if stage is enabled.
GrAssert(texCoordAttrs[tcIdx].size());
inCoords = texCoordAttrs[tcIdx].c_str();
inCoords = TEX_ATTR_NAME;
}
builder.setCurrentStage(s);
@ -853,15 +842,12 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
const char* inCoords;
// figure out what our input coords are
int tcIdx =
GrDrawState::VertexTexCoordsForStage(s, layout);
if (tcIdx < 0) {
if (!GrDrawState::StageUsesTexCoords(layout, s)) {
inCoords = builder.positionAttribute().c_str();
} else {
// must have input tex coordinates if stage is
// enabled.
GrAssert(texCoordAttrs[tcIdx].size());
inCoords = texCoordAttrs[tcIdx].c_str();
inCoords = TEX_ATTR_NAME;
}
// stages don't know how to deal with a scalar input. (Maybe they should. We
@ -945,7 +931,6 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
}
if (!this->bindOutputsAttribsAndLinkProgram(builder,
texCoordAttrs,
isColorDeclared,
dualSourceOutputWritten)) {
return false;
@ -959,7 +944,6 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
}
bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
SkString texCoordAttrNames[],
bool bindColorOut,
bool bindDualSrcOut) {
GL_CALL_RET(fProgramID, CreateProgram());
@ -984,14 +968,7 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
GL_CALL(BindAttribLocation(fProgramID,
PositionAttributeIdx(),
builder.positionAttribute().c_str()));
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
if (texCoordAttrNames[t].size()) {
GL_CALL(BindAttribLocation(fProgramID,
TexCoordAttributeIdx(t),
texCoordAttrNames[t].c_str()));
}
}
GL_CALL(BindAttribLocation(fProgramID, TexCoordAttributeIdx(), TEX_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));

View File

@ -85,7 +85,7 @@ public:
static int ColorAttributeIdx() { return 1; }
static int CoverageAttributeIdx() { return 2; }
static int EdgeAttributeIdx() { return 3; }
static int TexCoordAttributeIdx(int tcIdx) { return 4 + tcIdx; }
static int TexCoordAttributeIdx() { return 4; }
/**
* Some GL state that is relevant to programs is not stored per-program. In particular vertex
@ -227,7 +227,6 @@ private:
// Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
bool bindColorOut,
bool bindDualSrcOut);

View File

@ -217,26 +217,26 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
int newColorOffset;
int newCoverageOffset;
int newTexCoordOffsets[GrDrawState::kMaxTexCoords];
int newTexCoordOffset;
int newEdgeOffset;
GrVertexLayout currLayout = this->getDrawState().getVertexLayout();
GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout,
newTexCoordOffsets,
&newColorOffset,
&newCoverageOffset,
&newEdgeOffset);
GrGLsizei newStride = GrDrawState::VertexSizeAndOffsets(currLayout,
&newTexCoordOffset,
&newColorOffset,
&newCoverageOffset,
&newEdgeOffset);
int oldColorOffset;
int oldCoverageOffset;
int oldTexCoordOffsets[GrDrawState::kMaxTexCoords];
int oldTexCoordOffset;
int oldEdgeOffset;
GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
oldTexCoordOffsets,
&oldColorOffset,
&oldCoverageOffset,
&oldEdgeOffset);
GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
&oldTexCoordOffset,
&oldColorOffset,
&oldCoverageOffset,
&oldEdgeOffset);
int extraVertexOffset;
this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset);
@ -254,19 +254,17 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
fHWGeometryState.fVertexOffset = vertexOffset;
}
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
if (newTexCoordOffsets[t] > 0) {
GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
int idx = GrGLProgram::TexCoordAttributeIdx(t);
if (oldTexCoordOffsets[t] <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
} else if (allOffsetsChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
}
} else if (oldTexCoordOffsets[t] > 0) {
GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
if (newTexCoordOffset > 0) {
GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffset);
int idx = GrGLProgram::TexCoordAttributeIdx();
if (oldTexCoordOffset <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
} else if (allOffsetsChange || newTexCoordOffset != oldTexCoordOffset) {
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
}
} else if (oldTexCoordOffset > 0) {
GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx()));
}
if (newColorOffset > 0) {

View File

@ -57,14 +57,15 @@ void GrGLProgram::Desc::setRandom(SkMWCRandom* random,
fDualSrcOutput = kNone_DualSrcOutput;
}
bool useOnce = false;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (NULL != stages[s].getEffect()) {
const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory();
fEffectKeys[s] = factory.glEffectKey(stages[s], gpu->glCaps());
// use separate tex coords?
if (random->nextBool()) {
int t = random->nextULessThan(GrDrawState::kMaxTexCoords);
fVertexLayout |= GrDrawState::StageTexCoordVertexLayoutBit(s, t);
if (!useOnce && random->nextBool()) {
fVertexLayout |= GrDrawState::StageTexCoordVertexLayoutBit(s);
useOnce = true;
}
}
}