Towards issue #106
Adds notion of texture multiple stages but currently just uses 1.
git-svn-id: http://skia.googlecode.com/svn/trunk@694 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 82f94a3..7ea9ff2 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -18,93 +18,265 @@
#include "GrDrawTarget.h"
#include "GrGpuVertex.h"
-#define VERTEX_LAYOUT_ASSERTS \
- GrAssert(!(vertexLayout & kTextFormat_VertexLayoutBit) || \
- vertexLayout == kTextFormat_VertexLayoutBit); \
- GrAssert(!(vertexLayout & kSeparateTexCoord_VertexLayoutBit) || \
- !(vertexLayout & kPositionAsTexCoord_VertexLayoutBit));
+// recursive helper for creating mask with all the tex coord bits set for
+// one stage
+template <int N>
+static int stage_mask_recur(int stage) {
+ return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) |
+ stage_mask_recur<N+1>(stage);
+}
+template<>
+static int stage_mask_recur<GrDrawTarget::kNumStages>(int) { return 0; }
-size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
- VERTEX_LAYOUT_ASSERTS
- if ((vertexLayout & kTextFormat_VertexLayoutBit)) {
- return 2 * sizeof(GrGpuTextVertex);
- } else {
- size_t size = sizeof(GrPoint);
- if (vertexLayout & kSeparateTexCoord_VertexLayoutBit) {
- size += sizeof(GrPoint);
- }
- if (vertexLayout & kColor_VertexLayoutBit) {
- size += sizeof(GrColor);
- }
- return size;
- }
+// mask of all tex coord indices for one stage
+static int stage_tex_coord_mask(int stage) {
+ return stage_mask_recur<0>(stage);
}
-int GrDrawTarget::VertexTexCoordOffset(GrVertexLayout vertexLayout) {
- VERTEX_LAYOUT_ASSERTS
- if ((vertexLayout & kTextFormat_VertexLayoutBit)) {
- return sizeof(GrGpuTextVertex);
- } else if (vertexLayout & kSeparateTexCoord_VertexLayoutBit) {
- return sizeof(GrPoint);
- } else if (vertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
+// mask of all bits relevant to one stage
+static 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>
+static int tex_coord_mask_recur(int texCoordIdx) {
+ return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) |
+ tex_coord_mask_recur<N+1>(texCoordIdx);
+}
+template<>
+static int tex_coord_mask_recur<GrDrawTarget::kMaxTexCoords>(int) { return 0; }
+
+// mask of all bits relevant to one texture coordinate index
+static int tex_coord_idx_mask(int texCoordIdx) {
+ return tex_coord_mask_recur<0>(texCoordIdx);
+}
+
+bool check_layout(GrVertexLayout layout) {
+ // can only have 1 or 0 bits set for each stage.
+ for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
+ int stageBits = layout & stage_mask(s);
+ if (stageBits && !GrIsPow2(stageBits)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
+ GrAssert(check_layout(vertexLayout));
+
+ size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
+ sizeof(GrGpuTextVertex) :
+ sizeof(GrPoint);
+
+ size_t size = vecSize; // position
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ if (tex_coord_idx_mask(t) & vertexLayout) {
+ size += vecSize;
+ }
+ }
+ if (vertexLayout & kColor_VertexLayoutBit) {
+ size += sizeof(GrColor);
+ }
+ return size;
+}
+
+int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
+ GrAssert(check_layout(vertexLayout));
+ if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
return 0;
}
+ int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
+ if (tcIdx >= 0) {
+
+ int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
+ sizeof(GrGpuTextVertex) :
+ sizeof(GrPoint);
+ 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) {
+ offset += vecSize;
+ }
+ }
+ return offset;
+ }
+
return -1;
}
int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
- VERTEX_LAYOUT_ASSERTS
+ GrAssert(check_layout(vertexLayout));
+
if (vertexLayout & kColor_VertexLayoutBit) {
- if (vertexLayout & kSeparateTexCoord_VertexLayoutBit) {
- return 2 * sizeof(GrPoint);
- } else {
- return sizeof(GrPoint);
+ int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
+ sizeof(GrGpuTextVertex) :
+ sizeof(GrPoint);
+ int offset = vecSize; // position
+ // figure out how many tex coordinates are present and precede this one.
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ if (tex_coord_idx_mask(t) & vertexLayout) {
+ offset += vecSize;
+ }
}
+ return offset;
}
return -1;
}
-int GrDrawTarget::VertexSizeAndOffsets(GrVertexLayout vertexLayout,
- int* texCoordOffset,
- int* colorOffset) {
- VERTEX_LAYOUT_ASSERTS
-
- GrAssert(NULL != texCoordOffset);
+int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
+ int texCoordOffsetsByIdx[kMaxTexCoords],
+ int* colorOffset) {
+ GrAssert(check_layout(vertexLayout));
+
+ GrAssert(NULL != texCoordOffsetsByIdx);
GrAssert(NULL != colorOffset);
- if ((vertexLayout & kTextFormat_VertexLayoutBit)) {
- *texCoordOffset = sizeof(GrGpuTextVertex);
- *colorOffset = 0;
- return 2 * sizeof(GrGpuTextVertex);
- } else {
- size_t size = sizeof(GrPoint);
- if (vertexLayout & kSeparateTexCoord_VertexLayoutBit) {
- *texCoordOffset = sizeof(GrPoint);
- size += sizeof(GrPoint);
- } else if (vertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
- *texCoordOffset = 0;
+ int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
+ sizeof(GrGpuTextVertex) :
+ sizeof(GrPoint);
+ int size = vecSize; // position
+
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ if (tex_coord_idx_mask(t) & vertexLayout) {
+ texCoordOffsetsByIdx[t] = size;
+ size += vecSize;
} else {
- *texCoordOffset = -1;
+ texCoordOffsetsByIdx[t] = -1;
}
- if (vertexLayout & kColor_VertexLayoutBit) {
- *colorOffset = size;
- size += sizeof(GrColor);
- } else {
- *colorOffset = -1;
- }
- return size;
}
+ if (kColor_VertexLayoutBit & vertexLayout) {
+ *colorOffset = size;
+ size += sizeof(GrColor);
+ } else {
+ *colorOffset = -1;
+ }
+ return size;
}
-bool GrDrawTarget::VertexHasTexCoords(GrVertexLayout vertexLayout) {
- return !!(vertexLayout & (kSeparateTexCoord_VertexLayoutBit |
- kPositionAsTexCoord_VertexLayoutBit |
- kTextFormat_VertexLayoutBit));
+int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
+ int texCoordOffsetsByStage[kNumStages],
+ int* colorOffset) {
+ GrAssert(check_layout(vertexLayout));
+
+ GrAssert(NULL != texCoordOffsetsByStage);
+ GrAssert(NULL != colorOffset);
+
+ int texCoordOffsetsByIdx[kMaxTexCoords];
+ int size = VertexSizeAndOffsetsByIdx(vertexLayout,
+ texCoordOffsetsByIdx,
+ colorOffset);
+ for (int s = 0; s < kNumStages; ++s) {
+ int tcIdx;
+ if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
+ texCoordOffsetsByStage[s] = 0;
+ } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
+ texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
+ } else {
+ texCoordOffsetsByStage[s] = -1;
+ }
+ }
+ return size;
+}
+
+bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
+ GrAssert(stage < kNumStages);
+ GrAssert(check_layout(vertexLayout));
+ return !!(stage_mask(stage) & vertexLayout);
+}
+
+bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
+ GrVertexLayout vertexLayout) {
+ GrAssert(coordIndex < kMaxTexCoords);
+ GrAssert(check_layout(vertexLayout));
+ return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
+}
+
+int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) {
+ GrAssert(stage < kNumStages);
+ GrAssert(check_layout(vertexLayout));
+ int bit = vertexLayout & stage_tex_coord_mask(stage);
+ 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 - Gr_clz(bit) - 1) / kNumStages;
+ }
+ return -1;
+}
+
+void GrDrawTarget::VertexLayoutUnitTest() {
+ // not necessarily exhaustive
+ static bool run;
+ if (!run) {
+ run = true;
+ for (int s = 0; s < kNumStages; ++s) {
+
+ GrAssert(!VertexUsesStage(s, 0));
+ GrAssert(-1 == VertexStageCoordOffset(s, 0));
+ GrVertexLayout stageMask = 0;
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ stageMask |= StageTexCoordVertexLayoutBit(s,t);
+ }
+ GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
+ GrAssert(stage_tex_coord_mask(s) == stageMask);
+ stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
+ GrAssert(stage_mask(s) == stageMask);
+ GrAssert(!check_layout(stageMask));
+ }
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ GrVertexLayout tcMask = 0;
+ GrAssert(!VertexUsesTexCoordIdx(t, 0));
+ for (int s = 0; s < kNumStages; ++s) {
+ tcMask |= StageTexCoordVertexLayoutBit(s,t);
+ GrAssert(VertexUsesStage(s, tcMask));
+ 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 < kNumStages; ++s2) {
+ GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
+ GrAssert(!VertexUsesStage(s2, tcMask));
+ GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
+
+ GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
+ GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
+ GrAssert(VertexUsesStage(s2, posAsTex));
+ GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
+ GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
+ }
+ GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
+ GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
+ GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
+ }
+ GrAssert(tex_coord_idx_mask(t) == tcMask);
+ GrAssert(check_layout(tcMask));
+
+ int stageOffsets[kNumStages];
+ int colorOffset;
+ int size;
+ size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset);
+ GrAssert(2*sizeof(GrPoint) == size);
+ GrAssert(-1 == colorOffset);
+ for (int s = 0; s < kNumStages; ++s) {
+ GrAssert(VertexUsesStage(s, tcMask));
+ GrAssert(sizeof(GrPoint) == stageOffsets[s]);
+ GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
+ }
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
GrDrawTarget::GrDrawTarget() {
+#if GR_DEBUG
+ VertexLayoutUnitTest();
+#endif
fReservedGeometry.fLocked = false;
#if GR_DEBUG
fReservedGeometry.fVertexCount = ~0;
@@ -123,12 +295,14 @@
return fClip;
}
-void GrDrawTarget::setTexture(GrTexture* tex) {
- fCurrDrawState.fTexture = tex;
+void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
+ GrAssert(stage >= 0 && stage < kNumStages);
+ fCurrDrawState.fTextures[stage] = tex;
}
-GrTexture* GrDrawTarget::currentTexture() const {
- return fCurrDrawState.fTexture;
+GrTexture* GrDrawTarget::currentTexture(int stage) const {
+ GrAssert(stage >= 0 && stage < kNumStages);
+ return fCurrDrawState.fTextures[stage];
}
void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
@@ -139,21 +313,25 @@
return fCurrDrawState.fRenderTarget;
}
-void GrDrawTarget::concatViewMatrix(const GrMatrix& matrix) {
- GrMatrix mv;
- mv.setConcat(fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode], matrix);
- this->loadMatrix(mv, kModelView_MatrixMode);
+void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
+ fCurrDrawState.fViewMatrix = m;
}
+void GrDrawTarget::concatViewMatrix(const GrMatrix& matrix) {
+ fCurrDrawState.fViewMatrix.preConcat(matrix);
+}
+
+// Can't this just return a const&
void GrDrawTarget::getViewMatrix(GrMatrix* matrix) const {
- *matrix = fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
+ *matrix = fCurrDrawState.fViewMatrix;
}
bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
- // Can we cache this somewhere?
+ // Mike: Can we cache this somewhere?
+ // Brian: Sure, do we use it often?
GrMatrix inverse;
- if (fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode].invert(&inverse)) {
+ if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
if (matrix) {
*matrix = inverse;
}
@@ -162,8 +340,14 @@
return false;
}
-void GrDrawTarget::setSamplerState(const GrSamplerState& state) {
- fCurrDrawState.fSamplerState = state;
+void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
+ GrAssert(stage >= 0 && stage < kNumStages);
+ fCurrDrawState.fSamplerStates[stage] = state;
+}
+
+void GrDrawTarget::setTextureMatrix(int stage, const GrMatrix& m) {
+ GrAssert(stage >= 0 && stage < kNumStages);
+ fCurrDrawState.fTextureMatrices[stage] = m;
}
void GrDrawTarget::setStencilPass(StencilPass pass) {
@@ -182,10 +366,6 @@
fCurrDrawState.fFlagBits &= ~(bits);
}
-void GrDrawTarget::loadMatrix(const GrMatrix& matrix, MatrixMode m) {
- fCurrDrawState.fMatrixModeCache[m] = matrix;
-}
-
void GrDrawTarget::setPointSize(float size) {
fCurrDrawState.fPointSize = size;
}