diff options
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 147 |
1 files changed, 101 insertions, 46 deletions
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 4211da97e2..6f059124cb 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -17,46 +17,88 @@ namespace { -// recursive helper for creating mask with all the tex coord bits set for -// one stage -template <int N> -int stage_mask_recur(int stage) { - return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) | - stage_mask_recur<N+1>(stage); -} -template<> -int stage_mask_recur<GrDrawState::kNumStages>(int) { return 0; } - -// mask of all tex coord indices for one stage -int stage_tex_coord_mask(int stage) { - return stage_mask_recur<0>(stage); -} - -// mask of all bits relevant to one stage -int stage_mask(int stage) { - return stage_tex_coord_mask(stage) | - GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(stage); -} - -// recursive helper for creating mask of with all bits set relevant to one -// texture coordinate index -template <int N> -int tex_coord_mask_recur(int texCoordIdx) { - return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) | - tex_coord_mask_recur<N+1>(texCoordIdx); +/** + * 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 GrDrawTarget.h changes this funcion 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.) + * + */ +void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks, + GrVertexLayout* stageMasks, + GrVertexLayout* texCoordMasks) { + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + stageTexCoordMasks[s] = 0; + for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { + stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t); + } + stageMasks[s] = stageTexCoordMasks[s] | GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); + } + for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { + texCoordMasks[t] = 0; + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t); + } + } } -template<> -int tex_coord_mask_recur<GrDrawState::kMaxTexCoords>(int) { return 0; } -// mask of all bits relevant to one texture coordinate index -int tex_coord_idx_mask(int texCoordIdx) { - return tex_coord_mask_recur<0>(texCoordIdx); -} +/** + * Run this function to generate the code that declares the global masks. + */ +void gen_globals() { + GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages]; + GrVertexLayout stageMasks[GrDrawState::kNumStages]; + GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords]; + gen_mask_arrays(stageTexCoordMasks, stageMasks, 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 gStageMasks[] = {\n"); + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + GrPrintf(" 0x%x,\n", stageMasks[s]); + } + GrPrintf("};\n"); + GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));\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"); +} + +/* These values were generated by the above function */ +const GrVertexLayout gStageTexCoordMasks[] = { + 0x49, + 0x92, + 0x124 +}; + +GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks)); +const GrVertexLayout gStageMasks[] = { + 0x249, + 0x492, + 0x924 +}; + +GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks)); +const GrVertexLayout gTexCoordMasks[] = { + 0x7, + 0x38, + 0x1c0, +}; +GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks)); 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 & stage_mask(s); + int stageBits = layout & gStageMasks[s]; if (stageBits && !GrIsPow2(stageBits)) { return false; } @@ -68,7 +110,7 @@ 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 (tex_coord_idx_mask(t) & layout) { + if (gTexCoordMasks[t] & layout) { ++cnt; } } @@ -127,7 +169,7 @@ int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) int offset = vecSize; // position // figure out how many tex coordinates are present and precede this one. for (int t = 0; t < tcIdx; ++t) { - if (tex_coord_idx_mask(t) & vertexLayout) { + if (gTexCoordMasks[t] & vertexLayout) { offset += vecSize; } } @@ -137,7 +179,7 @@ int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) return -1; } -int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) { +int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) { GrAssert(check_layout(vertexLayout)); if (vertexLayout & kColor_VertexLayoutBit) { @@ -149,7 +191,7 @@ int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) { return -1; } -int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) { +int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) { GrAssert(check_layout(vertexLayout)); if (vertexLayout & kCoverage_VertexLayoutBit) { @@ -166,7 +208,7 @@ int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) { return -1; } -int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) { +int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) { GrAssert(check_layout(vertexLayout)); // edge pts are after the pos, tex coords, and color @@ -200,7 +242,7 @@ int GrDrawTarget::VertexSizeAndOffsetsByIdx( int size = vecSize; // position for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { - if (tex_coord_idx_mask(t) & vertexLayout) { + if (gTexCoordMasks[t] & vertexLayout) { if (NULL != texCoordOffsetsByIdx) { texCoordOffsetsByIdx[t] = size; } @@ -280,21 +322,21 @@ int GrDrawTarget::VertexSizeAndOffsetsByStage( bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) { GrAssert(stage < GrDrawState::kNumStages); GrAssert(check_layout(vertexLayout)); - return !!(stage_mask(stage) & vertexLayout); + return !!(gStageMasks[stage] & vertexLayout); } bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex, GrVertexLayout vertexLayout) { GrAssert(coordIndex < GrDrawState::kMaxTexCoords); GrAssert(check_layout(vertexLayout)); - return !!(tex_coord_idx_mask(coordIndex) & vertexLayout); + return !!(gTexCoordMasks[coordIndex] & vertexLayout); } int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) { GrAssert(stage < GrDrawState::kNumStages); GrAssert(check_layout(vertexLayout)); - int bit = vertexLayout & stage_tex_coord_mask(stage); + int bit = vertexLayout & gStageTexCoordMasks[stage]; if (bit) { // figure out which set of texture coordates is used // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ... @@ -308,6 +350,19 @@ int GrDrawTarget::VertexTexCoordsForStage(int stage, //////////////////////////////////////////////////////////////////////////////// void GrDrawTarget::VertexLayoutUnitTest() { + // Ensure that our globals mask arrays are correct + GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages]; + GrVertexLayout stageMasks[GrDrawState::kNumStages]; + GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords]; + gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks); + for (int s = 0; s < GrDrawState::kNumStages; ++s) { + GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]); + GrAssert(stageMasks[s] == gStageMasks[s]); + } + for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { + GrAssert(texCoordMasks[t] == gTexCoordMasks[t]); + } + // not necessarily exhaustive static bool run; if (!run) { @@ -322,9 +377,9 @@ void GrDrawTarget::VertexLayoutUnitTest() { } GrAssert(1 == GrDrawState::kMaxTexCoords || !check_layout(stageMask)); - GrAssert(stage_tex_coord_mask(s) == stageMask); + GrAssert(gStageTexCoordMasks[s] == stageMask); stageMask |= StagePosAsTexCoordVertexLayoutBit(s); - GrAssert(stage_mask(s) == stageMask); + GrAssert(gStageMasks[s] == stageMask); GrAssert(!check_layout(stageMask)); } for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { @@ -386,7 +441,7 @@ void GrDrawTarget::VertexLayoutUnitTest() { GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor)); GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor)); } - GrAssert(tex_coord_idx_mask(t) == tcMask); + GrAssert(gTexCoordMasks[t] == tcMask); GrAssert(check_layout(tcMask)); int stageOffsets[GrDrawState::kNumStages]; |