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;
}
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;
}
}
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;
}
}
return -1;
}
-int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
+int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
if (vertexLayout & kColor_VertexLayoutBit) {
return -1;
}
-int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
+int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
GrAssert(check_layout(vertexLayout));
if (vertexLayout & kCoverage_VertexLayoutBit) {
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
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;
}
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, ...
////////////////////////////////////////////////////////////////////////////////
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) {
}
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) {
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];