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/GrContext.cpp b/gpu/src/GrContext.cpp
index 942afa3..e5e378f 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -138,9 +138,9 @@
if (NULL != texture) {
GrGpu::AutoStateRestore asr(fGpu);
fGpu->setRenderTarget(texture->asRenderTarget());
- fGpu->setTexture(clampEntry->texture());
+ fGpu->setTexture(0, clampEntry->texture());
fGpu->setStencilPass(GrGpu::kNone_StencilPass);
- fGpu->setTextureMatrix(GrMatrix::I());
+ fGpu->setTextureMatrix(0, GrMatrix::I());
fGpu->setViewMatrix(GrMatrix::I());
fGpu->setAlpha(0xff);
fGpu->setBlendFunc(GrGpu::kOne_BlendCoeff, GrGpu::kZero_BlendCoeff);
@@ -150,10 +150,10 @@
GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kClamp_WrapMode,
sampler.isFilter());
- fGpu->setSamplerState(stretchSampler);
+ fGpu->setSamplerState(0, stretchSampler);
static const GrVertexLayout layout =
- GrDrawTarget::kSeparateTexCoord_VertexLayoutBit;
+ GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
if (arg.succeeded()) {
@@ -303,7 +303,7 @@
void GrContext::drawRect(const GrRect& rect, bool useTexture, GrScalar width) {
GrVertexLayout layout = useTexture ?
- GrDrawTarget::kPositionAsTexCoord_VertexLayoutBit :
+ GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
0;
static const int worstCaseVertCount = 10;
@@ -582,7 +582,7 @@
tol);
GrVertexLayout layout = 0;
if (useTexture) {
- layout = GrDrawTarget::kPositionAsTexCoord_VertexLayoutBit;
+ layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
}
// add 4 to hold the bounding rect
GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, maxPts + 4, 0);
@@ -808,14 +808,14 @@
fGpu->setViewMatrix(matrix);
matrix.setScale(GR_Scalar1 / texture->allocWidth(),
GR_Scalar1 / texture->allocHeight());
- fGpu->setTextureMatrix(matrix);
+ fGpu->setTextureMatrix(0, matrix);
fGpu->disableState(GrDrawTarget::kClip_StateBit);
fGpu->setAlpha(0xFF);
fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff,
GrDrawTarget::kZero_BlendCoeff);
- fGpu->setTexture(texture);
- fGpu->setSamplerState(GrSamplerState::ClampNoFilter());
+ fGpu->setTexture(0, texture);
+ fGpu->setSamplerState(0, GrSamplerState::ClampNoFilter());
this->fillRect(GrRect(0, 0, GrIntToScalar(width), GrIntToScalar(height)),
true);
@@ -841,8 +841,8 @@
return fGpu->createIndexBuffer(size, dynamic);
}
-void GrContext::setTexture(GrTexture* texture) {
- fGpu->setTexture(texture);
+void GrContext::setTexture(int stage, GrTexture* texture) {
+ fGpu->setTexture(stage, texture);
}
void GrContext::setRenderTarget(GrRenderTarget* target) {
@@ -858,12 +858,12 @@
fGpu->setDefaultRenderTargetSize(width, height);
}
-void GrContext::setSamplerState(const GrSamplerState& samplerState) {
- fGpu->setSamplerState(samplerState);
+void GrContext::setSamplerState(int stage, const GrSamplerState& samplerState) {
+ fGpu->setSamplerState(stage, samplerState);
}
-void GrContext::setTextureMatrix(const GrMatrix& m) {
- fGpu->setTextureMatrix(m);
+void GrContext::setTextureMatrix(int stage, const GrMatrix& m) {
+ fGpu->setTextureMatrix(stage, m);
}
void GrContext::getViewMatrix(GrMatrix* m) const {
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;
}
diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp
index 4e9d922..9460086 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -144,6 +144,9 @@
uint32_t width,
uint32_t height,
const void* srcData) {
+
+ fGpuGL->setSpareTextureUnit();
+
// glCompressedTexSubImage2D doesn't support any formats
// (at least without extensions)
GrAssert(fUploadFormat != GR_PALETTE8_RGBA8);
@@ -152,7 +155,6 @@
// then we have to modify this code to flip the srcData
GrAssert(kTopDown_Orientation == fOrientation);
GR_GL(BindTexture(GL_TEXTURE_2D, fTextureID));
- fGpuGL->notifyTextureBind(this);
GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, fUploadByteCount));
GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
fUploadFormat, fUploadType, srcData));
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index f9ee217..fe6d0c3 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -92,20 +92,32 @@
}
// If the src coef will always be 1...
- bool fullSrc = kSA_BlendCoeff == fCurrDrawState.fSrcBlend ||
- kOne_BlendCoeff == fCurrDrawState.fSrcBlend;
+ if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
+ kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
+ return false;
+ }
// ...and the dst coef is always 0...
- bool noDst = kISA_BlendCoeff == fCurrDrawState.fDstBlend ||
- kZero_BlendCoeff == fCurrDrawState.fDstBlend;
+ if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
+ kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
+ return false;
+ }
// ...and there isn't a texture with an alpha channel...
- bool noTexAlpha = !VertexHasTexCoords(fGeometrySrc.fVertexLayout) ||
- fCurrDrawState.fTexture->config() == GrTexture::kRGB_565_PixelConfig ||
- fCurrDrawState.fTexture->config() == GrTexture::kRGBX_8888_PixelConfig;
+ for (int s = 0; s < kNumStages; ++s) {
+ if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
+ GrAssert(NULL != fCurrDrawState.fTextures[s]);
+ GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config();
+
+ if (GrTexture::kRGB_565_PixelConfig != config &&
+ GrTexture::kRGBX_8888_PixelConfig != config) {
+ return false;
+ }
+ }
+ }
// ...then we disable blend.
- return fullSrc && noDst && noTexAlpha;
+ return true;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 4d539d2..6de6db3 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -29,6 +29,10 @@
static const GLuint GR_MAX_GLUINT = ~0;
static const GLint GR_INVAL_GLINT = ~0;
+// we use a spare texture unit to avoid
+// mucking with the state of any of the stages.
+static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
+
#define SKIP_CACHE_CHECK true
static const GLenum gXfermodeCoeff2Blend[] = {
@@ -69,7 +73,7 @@
*minor = 0;
return;
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
int n = sscanf(v, "%d.%d", major, minor);
if (n != 2) {
GrAssert(0);
@@ -96,6 +100,14 @@
///////////////////////////////////////////////////////////////////////////////
bool fbo_test(GrGLExts exts, int w, int h) {
+
+ GLint savedFBO;
+ GLint savedTexUnit;
+ GR_GL(GetIntegerv(GL_ACTIVE_TEXTURE, &savedTexUnit));
+ GR_GL(GetIntegerv(GR_FRAMEBUFFER_BINDING, &savedFBO));
+
+ GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
+
GLuint testFBO;
GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
@@ -113,6 +125,10 @@
GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
GR_GL(DeleteTextures(1, &testRTTex));
+
+ GR_GL(ActiveTexture(savedTexUnit));
+ GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
+
return status == GR_FRAMEBUFFER_COMPLETE;
}
@@ -155,7 +171,20 @@
this);
fHWDrawState.fRenderTarget = fDefaultRenderTarget;
fRenderTargetChanged = true;
-
+
+ GLint maxTextureUnits;
+ // check FS and fixed-function texture unit limits
+ // we only use textures in the fragment stage currently.
+ // checks are > to make sure we have a spare unit.
+#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES2
+ GR_GL(GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits));
+ GrAssert(maxTextureUnits > kNumStages);
+#endif
+#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
+ GR_GL(GetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits));
+ GrAssert(maxTextureUnits > kNumStages);
+#endif
+
fCurrDrawState = fHWDrawState;
////////////////////////////////////////////////////////////////////////////
@@ -198,7 +227,7 @@
GrPrintf("MSAA Support: APPLE ES EXT.\n");
}
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
else if ((major >= 3) ||
has_gl_extension("GL_ARB_framebuffer_object") ||
(has_gl_extension("GL_EXT_framebuffer_multisample") &&
@@ -236,7 +265,7 @@
}
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
has_gl_extension("GL_EXT_stencil_wrap");
#else
@@ -246,7 +275,7 @@
GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
// we could also look for GL_ATI_separate_stencil extension or
// GL_EXT_stencil_two_side but they use different function signatures
// than GL2.0+ (and than each other).
@@ -261,7 +290,7 @@
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
fRGBA8Renderbuffer = true;
#else
fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
@@ -271,7 +300,7 @@
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
fBufferLockSupport = true; // we require VBO support and the desktop VBO
// extension includes glMapBuffer.
#else
@@ -281,7 +310,7 @@
GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
fNPOTTextureSupport =
(major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) ?
kFull_NPOTTextureType :
@@ -433,7 +462,7 @@
GR_GL(Disable(GL_CULL_FACE));
GR_GL(Disable(GL_DITHER));
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
GR_GL(Disable(GL_LINE_SMOOTH));
GR_GL(Disable(GL_POINT_SMOOTH));
GR_GL(Disable(GL_MULTISAMPLE));
@@ -442,7 +471,8 @@
// we only ever use lines in hairline mode
GR_GL(LineWidth(1));
- GR_GL(ActiveTexture(GL_TEXTURE0));
+ // invalid
+ fActiveTextureUnitIdx = -1;
fHWDrawState.fFlagBits = 0;
@@ -451,21 +481,22 @@
fHWDrawState.fDstBlend = (BlendCoeff)-1;
fHWDrawState.fColor = GrColor_ILLEGAL;
fHWDrawState.fPointSize = -1;
- fHWDrawState.fTexture = NULL;
-
+
+ fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax); // illegal
+
+ for (int s = 0; s < kNumStages; ++s) {
+ fHWDrawState.fTextures[s] = NULL;
+ fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
+ -GR_ScalarMax,
+ true);
+ fHWDrawState.fTextureMatrices[s].setScale(GR_ScalarMax, GR_ScalarMax);
+ }
+
GR_GL(Scissor(0,0,0,0));
fHWBounds.fScissorRect.setLTRB(0,0,0,0);
fHWBounds.fScissorEnabled = false;
GR_GL(Disable(GL_SCISSOR_TEST));
- fHWDrawState.fSamplerState.setRadial2Params(-GR_ScalarMax,
- -GR_ScalarMax,
- true);
-
- for (int i = 0; i < kMatrixModeCount; i++) {
- fHWDrawState.fMatrixModeCache[i].setScale(GR_ScalarMax, GR_ScalarMax); // illegal
- }
-
// disabling the stencil test also disables
// stencil buffer writes
GR_GL(Disable(GL_STENCIL_TEST));
@@ -490,7 +521,7 @@
// defines stencil formats from more to less preferred
-#if GR_GL_ES
+#if GR_SUPPORT_GLES
GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
GR_STENCIL_INDEX8,
};
@@ -544,6 +575,8 @@
++fStats.fTextureCreateCnt;
#endif
+ setSpareTextureUnit();
+
static const GrGLTexture::TexParams DEFAULT_PARAMS = {
GL_NEAREST,
GL_CLAMP_TO_EDGE,
@@ -585,7 +618,7 @@
* to trim those off here, since GL doesn't let us pass the rowBytes as
* a parameter to glTexImage2D
*/
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
if (srcData) {
GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
rowBytes / glDesc.fUploadByteCount));
@@ -636,10 +669,6 @@
GR_GL(TexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T,
DEFAULT_PARAMS.fWrapT));
-#if GR_COLLECT_STATS
- ++fStats.fTextureChngCnt;
-#endif
- fHWDrawState.fTexture = NULL;
GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
@@ -763,7 +792,6 @@
GR_GL(DeleteTextures(1, &glDesc.fTextureID));
GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
- fHWDrawState.fTexture = NULL;
return return_null_texture();
}
} else {
@@ -776,12 +804,10 @@
attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
}
- // need to unbind the texture before we call FramebufferTexture2D
+ // someone suggested that some systems might require
+ // unbinding the texture before we call FramebufferTexture2D
+ // (seems unlikely)
GR_GL(BindTexture(GL_TEXTURE_2D, 0));
-#if GR_COLLECT_STATS
- ++fStats.fTextureChngCnt;
-#endif
- GrAssert(NULL == fHWDrawState.fTexture);
err = ~GL_NO_ERROR;
for (int i = 0; i < attempts; ++i) {
@@ -869,7 +895,7 @@
}
status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
// On some implementations you have to be bound as DEPTH_STENCIL.
// (Even binding to DEPTH and STENCIL separately with the same
// buffer doesn't work.)
@@ -890,7 +916,7 @@
if (status != GR_FRAMEBUFFER_COMPLETE) {
GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
status, desc.fWidth, desc.fHeight);
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
if (rtIDs.fStencilRenderbufferID) {
GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
GR_DEPTH_STENCIL_ATTACHMENT,
@@ -1428,65 +1454,75 @@
void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
- bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
+ for (int s = 0; s < kNumStages; ++s) {
+ bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
- // bind texture and set sampler state
- if (usingTexture) {
- GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTexture;
+ // bind texture and set sampler state
+ if (usingTexture) {
+ GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
- if (NULL != nextTexture) {
- // if we created a rt/tex and rendered to it without using a texture
- // and now we're texuring from the rt it will still be the last bound
- // texture, but it needs resolving. So keep this out of the last
- // != next check.
- resolveTextureRenderTarget(nextTexture);
+ if (NULL != nextTexture) {
+ // if we created a rt/tex and rendered to it without using a
+ // texture and now we're texuring from the rt it will still be
+ // the last bound texture, but it needs resolving. So keep this
+ // out of the "last != next" check.
+ resolveTextureRenderTarget(nextTexture);
- if (fHWDrawState.fTexture != nextTexture) {
+ if (fHWDrawState.fTextures[s] != nextTexture) {
+ setTextureUnit(s);
+ GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
+ #if GR_COLLECT_STATS
+ ++fStats.fTextureChngCnt;
+ #endif
+ //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
+ fHWDrawState.fTextures[s] = nextTexture;
+ }
+
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+ const GrGLTexture::TexParams& oldTexParams =
+ nextTexture->getTexParams();
+ GrGLTexture::TexParams newTexParams;
+
+ newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
+ GL_NEAREST;
+ newTexParams.fWrapS =
+ GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
+ newTexParams.fWrapT =
+ GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
- GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
- #if GR_COLLECT_STATS
- ++fStats.fTextureChngCnt;
- #endif
- //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
- fHWDrawState.fTexture = nextTexture;
- }
-
- const GrGLTexture::TexParams& oldTexParams = nextTexture->getTexParams();
- GrGLTexture::TexParams newTexParams;
- newTexParams.fFilter = fCurrDrawState.fSamplerState.isFilter() ?
- GL_LINEAR :
- GL_NEAREST;
- newTexParams.fWrapS = GrGLTexture::gWrapMode2GLWrap[fCurrDrawState.fSamplerState.getWrapX()];
- newTexParams.fWrapT = GrGLTexture::gWrapMode2GLWrap[fCurrDrawState.fSamplerState.getWrapY()];
-
- if (newTexParams.fFilter != oldTexParams.fFilter) {
- GR_GL(TexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_MAG_FILTER,
- newTexParams.fFilter));
- GR_GL(TexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_MIN_FILTER,
- newTexParams.fFilter));
- }
- if (newTexParams.fWrapS != oldTexParams.fWrapS) {
- GR_GL(TexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_WRAP_S,
- newTexParams.fWrapS));
- }
- if (newTexParams.fWrapT != oldTexParams.fWrapT) {
- GR_GL(TexParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_WRAP_T,
- newTexParams.fWrapT));
- }
- nextTexture->setTexParams(newTexParams);
- } else {
- GrAssert(!"Rendering with texture vert flag set but no texture");
- if (NULL != fHWDrawState.fTexture) {
- GR_GL(BindTexture(GL_TEXTURE_2D, 0));
- // GrPrintf("---- bindtexture 0\n");
- #if GR_COLLECT_STATS
- ++fStats.fTextureChngCnt;
- #endif
- fHWDrawState.fTexture = NULL;
+ if (newTexParams.fFilter != oldTexParams.fFilter) {
+ setTextureUnit(s);
+ GR_GL(TexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER,
+ newTexParams.fFilter));
+ GR_GL(TexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER,
+ newTexParams.fFilter));
+ }
+ if (newTexParams.fWrapS != oldTexParams.fWrapS) {
+ setTextureUnit(s);
+ GR_GL(TexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_S,
+ newTexParams.fWrapS));
+ }
+ if (newTexParams.fWrapT != oldTexParams.fWrapT) {
+ setTextureUnit(s);
+ GR_GL(TexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_T,
+ newTexParams.fWrapT));
+ }
+ nextTexture->setTexParams(newTexParams);
+ } else {
+ GrAssert(!"Rendering with texture vert flag set but no texture");
+ if (NULL != fHWDrawState.fTextures[s]) {
+ setTextureUnit(s);
+ GR_GL(BindTexture(GL_TEXTURE_2D, 0));
+ // GrPrintf("---- bindtexture 0\n");
+ #if GR_COLLECT_STATS
+ ++fStats.fTextureChngCnt;
+ #endif
+ fHWDrawState.fTextures[s] = NULL;
+ }
}
}
}
@@ -1502,7 +1538,7 @@
}
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
// ES doesn't support toggling GL_MULTISAMPLE and doesn't have
// smooth lines.
if (fRenderTargetChanged ||
@@ -1549,13 +1585,18 @@
fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
}
}
-
+
+#if GR_DEBUG
// check for circular rendering
- GrAssert(!usingTexture ||
- NULL == fCurrDrawState.fRenderTarget ||
- NULL == fCurrDrawState.fTexture ||
- fCurrDrawState.fTexture->asRenderTarget() != fCurrDrawState.fRenderTarget);
-
+ for (int s = 0; s < kNumStages; ++s) {
+ GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
+ NULL == fCurrDrawState.fRenderTarget ||
+ NULL == fCurrDrawState.fTextures[s] ||
+ fCurrDrawState.fTextures[s]->asRenderTarget() !=
+ fCurrDrawState.fRenderTarget);
+ }
+#endif
+
flushStencil();
fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
@@ -1589,13 +1630,6 @@
}
}
-void GrGpuGL::notifyTextureBind(GrGLTexture* texture) {
- fHWDrawState.fTexture = texture;
-#if GR_COLLECT_STATS
- ++fStats.fTextureChngCnt;
-#endif
-}
-
void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
GrAssert(NULL != renderTarget);
@@ -1615,13 +1649,15 @@
}
void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
- if (fCurrDrawState.fTexture == texture) {
- fCurrDrawState.fTexture = NULL;
+ for (int s = 0; s < kNumStages; ++s) {
+ if (fCurrDrawState.fTextures[s] == texture) {
+ fCurrDrawState.fTextures[s] = NULL;
+ }
+ if (fHWDrawState.fTextures[s] == texture) {
+ // deleting bound texture does implied bind to 0
+ fHWDrawState.fTextures[s] = NULL;
+ }
}
- if (fHWDrawState.fTexture == texture) {
- // deleting bound texture does implied bind to 0
- fHWDrawState.fTexture = NULL;
- }
}
void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
@@ -1672,6 +1708,21 @@
return true;
}
+void GrGpuGL::setTextureUnit(int unit) {
+ GrAssert(unit >= 0 && unit < kNumStages);
+ if (fActiveTextureUnitIdx != unit) {
+ GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
+ fActiveTextureUnitIdx = unit;
+ }
+}
+
+void GrGpuGL::setSpareTextureUnit() {
+ if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
+ GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
+ fActiveTextureUnitIdx = SPARE_TEX_UNIT;
+ }
+}
+
/* On ES the internalFormat and format must match for TexImage and we use
GL_RGB, GL_RGBA for color formats. We also generally like having the driver
decide the internalFormat. However, on ES internalFormat for
@@ -1688,8 +1739,8 @@
} else {
return false;
}
-#if GR_GL_ES // ES2 supports 565. ES1 supports it with FBO extension
- // desktop GL has no such internal format
+#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
+ // desktop GL has no such internal format
case GrTexture::kRGB_565_PixelConfig:
*format = GR_RGB565;
return true;
@@ -1799,7 +1850,7 @@
#else
GLint major, minor;
gl_version(&major, &minor);
- #if GR_GL_DESKTOP
+ #if GR_SUPPORT_GLDESKTOP
if (major >= 3) {// FBO, FBOMS, and FBOBLIT part of 3.0
exts->GenFramebuffers = glGenFramebuffers;
exts->BindFramebuffer = glBindFramebuffer;
@@ -1849,7 +1900,7 @@
// we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
exts->MapBuffer = glMapBuffer;
exts->UnmapBuffer = glUnmapBuffer;
- #else // !GR_GL_DESKTOP
+ #else // !GR_SUPPORT_GLDESKTOP
if (major >= 2) {// ES 2.0 supports FBO
exts->GenFramebuffers = glGenFramebuffers;
exts->BindFramebuffer = glBindFramebuffer;
@@ -1886,7 +1937,7 @@
GET_PROC(exts, MapBuffer, OES);
GET_PROC(exts, UnmapBuffer, OES);
}
- #endif // !GR_GL_DESKTOP
+ #endif // !GR_SUPPORT_GLDESKTOP
#endif // BUILD
}
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 728a5d3..8c2cd80 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -87,6 +87,8 @@
void eraseStencil(uint32_t value, uint32_t mask);
virtual void eraseStencilClip();
+
+ void setTextureUnit(int unitIdx);
// flushes state that is common to fixed and programmable GL
// dither
@@ -109,9 +111,9 @@
// last scissor / viewport scissor state seen by the GL.
BoundsState fHWBounds;
-private:
GrGLExts fExts;
+private:
GrGLRenderTarget* fDefaultRenderTarget;
void resetContextHelper();
@@ -122,10 +124,11 @@
void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer);
void notifyIndexBufferBind(const GrGLIndexBuffer* buffer);
void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer);
- void notifyTextureBind(GrGLTexture* texture);
void notifyTextureDelete(GrGLTexture* texture);
void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
void notifyTextureRemoveRenderTarget(GrGLTexture* texture);
+
+ void setSpareTextureUnit();
void flushRenderTarget();
void flushStencil();
@@ -157,7 +160,9 @@
// ES requires an extension to support RGBA8 in RenderBufferStorage
bool fRGBA8Renderbuffer;
-
+
+ int fActiveTextureUnitIdx;
+
typedef GrGpu INHERITED;
};
@@ -168,7 +173,7 @@
* GrGL_RestoreResetRowLength() will reset GL_UNPACK_ROW_LENGTH to 0. We write
* this wrapper, since GL_UNPACK_ROW_LENGTH is not available on all GL versions
*/
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
static inline void GrGL_RestoreResetRowLength() {
GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH, 0));
}
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index 77bec40..d142b66 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -72,25 +72,27 @@
void GrGpuGLFixed::resetContextHelper() {
GR_GL(Disable(GL_TEXTURE_2D));
- GR_GL(EnableClientState(GL_VERTEX_ARRAY));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR));
+ for (int s = 0; s < kNumStages; ++s) {
+ setTextureUnit(s);
+ GR_GL(EnableClientState(GL_VERTEX_ARRAY));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0+s));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR));
- GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA));
-
- // this changes between GL_SRC_COLR and GL_SRC_ALPHA depending upon
- // whether we have a (premultiplied) RGBA texture or just an ALPHA texture
- //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- fHWRGBOperand0 = (TextureEnvRGBOperands) -1;
-
- GR_GL(ClientActiveTexture(GL_TEXTURE0));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0+s));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS));
+ GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA));
+
+ // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending
+ // upon whether we have a (premultiplied) RGBA texture or just an ALPHA
+ // texture, e.g.:
+ //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
+ }
fHWGeometryState.fVertexLayout = 0;
fHWGeometryState.fPositionPtr = (void*) ~0;
@@ -127,11 +129,15 @@
bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
- bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
+ bool usingTextures[kNumStages];
+
+ for (int s = 0; s < kNumStages; ++s) {
+ usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
- if (usingTexture && fCurrDrawState.fSamplerState.isGradient()) {
- unimpl("Fixed pipe doesn't support radial/sweep gradients");
- return false;
+ if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
+ unimpl("Fixed pipe doesn't support radial/sweep gradients");
+ return false;
+ }
}
flushGLStateCommon(type);
@@ -140,24 +146,25 @@
flushProjectionMatrix();
fRenderTargetChanged = false;
}
-
- bool wasUsingTexture = VertexHasTexCoords(fHWGeometryState.fVertexLayout);
- if (usingTexture != wasUsingTexture) {
- if (usingTexture) {
- GR_GL(Enable(GL_TEXTURE_2D));
- } else {
- GR_GL(Disable(GL_TEXTURE_2D));
+
+ for (int s = 0; s < kNumStages; ++s) {
+ bool wasUsingTexture = VertexUsesStage(s, fHWGeometryState.fVertexLayout);
+ if (usingTextures[s] != wasUsingTexture) {
+ setTextureUnit(s);
+ if (usingTextures[s]) {
+ GR_GL(Enable(GL_TEXTURE_2D));
+ } else {
+ GR_GL(Disable(GL_TEXTURE_2D));
+ }
}
}
-
+
uint32_t vertColor = (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit);
uint32_t prevVertColor = (fHWGeometryState.fVertexLayout &
kColor_VertexLayoutBit);
if (vertColor != prevVertColor) {
if (vertColor) {
- GrAssert(fCurrDrawState.fSamplerState.getSampleMode() !=
- GrSamplerState::kAlphaMod_SampleMode);
GR_GL(ShadeModel(GL_SMOOTH));
// invalidate the immediate mode color
fHWDrawState.fColor = GrColor_ILLEGAL;
@@ -181,57 +188,61 @@
}
// set texture environment, decide whether we are modulating by RGB or A.
- if (usingTexture) {
- GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTexture;
- if (NULL != texture) {
- TextureEnvRGBOperands nextRGBOperand0 =
- (texture->uploadFormat() == GL_ALPHA) ?
- kAlpha_TextureEnvRGBOperand :
- kColor_TextureEnvRGBOperand;
- if (fHWRGBOperand0 != nextRGBOperand0) {
- GR_GL(TexEnvi(GL_TEXTURE_ENV,
- GL_OPERAND0_RGB,
- (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
- GL_SRC_ALPHA :
- GL_SRC_COLOR));
- fHWRGBOperand0 = nextRGBOperand0;
- }
-
- if (fHWTextureOrientation != texture->orientation() ||
- fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] !=
- fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]) {
- GrGpuMatrix glm;
- if (GrGLTexture::kBottomUp_Orientation == texture->orientation()) {
- GrMatrix m(
- GR_Scalar1, 0, 0,
- 0, -GR_Scalar1, GR_Scalar1,
- 0, 0, GrMatrix::I()[8]
- );
- m.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
- glm.set(m);
- } else {
- glm.set(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
+ for (int s = 0; s < kNumStages; ++s) {
+ if (usingTextures[s]) {
+ GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
+ if (NULL != texture) {
+ TextureEnvRGBOperands nextRGBOperand0 =
+ (texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
+ kAlpha_TextureEnvRGBOperand :
+ kColor_TextureEnvRGBOperand;
+ if (fHWRGBOperand0[s] != nextRGBOperand0) {
+ setTextureUnit(s);
+ GR_GL(TexEnvi(GL_TEXTURE_ENV,
+ GL_OPERAND0_RGB,
+ (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ?
+ GL_SRC_ALPHA :
+ GL_SRC_COLOR));
+ fHWRGBOperand0[s] = nextRGBOperand0;
}
- GR_GL(MatrixMode(gMatrixMode2Enum[kTexture_MatrixMode]));
- GR_GL(LoadMatrixf(glm.fMat));
- fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] =
- fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
- fHWTextureOrientation = texture->orientation();
+
+ if (fHWTextureOrientation != texture->orientation() ||
+ fHWDrawState.fTextureMatrices[s] !=
+ fCurrDrawState.fTextureMatrices[s]) {
+ GrGpuMatrix glm;
+ if (GrGLTexture::kBottomUp_Orientation ==
+ texture->orientation()) {
+ GrMatrix m(
+ GR_Scalar1, 0, 0,
+ 0, -GR_Scalar1, GR_Scalar1,
+ 0, 0, GrMatrix::I()[8]
+ );
+ m.preConcat(fCurrDrawState.fTextureMatrices[s]);
+ glm.set(m);
+ } else {
+ glm.set(fCurrDrawState.fTextureMatrices[s]);
+ }
+ setTextureUnit(s);
+ GR_GL(MatrixMode(GL_TEXTURE));
+ GR_GL(LoadMatrixf(glm.fMat));
+ fHWDrawState.fTextureMatrices[s] =
+ fCurrDrawState.fTextureMatrices[s];
+ fHWTextureOrientation = texture->orientation();
+ }
+ } else {
+ GrAssert(!"Rendering with texture vert flag set but no bound texture");
+ return false;
}
- } else {
- GrAssert(!"Rendering with texture vert flag set but no bound texture");
- return false;
}
}
- if (fHWDrawState.fMatrixModeCache[kModelView_MatrixMode] !=
- fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
+ if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) {
GrGpuMatrix glm;
- glm.set(fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
- GR_GL(MatrixMode(gMatrixMode2Enum[kModelView_MatrixMode]));
+ glm.set(fCurrDrawState.fViewMatrix);
+ GR_GL(MatrixMode(GL_MODELVIEW));
GR_GL(LoadMatrixf(glm.fMat));
- fHWDrawState.fMatrixModeCache[kModelView_MatrixMode] =
- fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
+ fHWDrawState.fViewMatrix =
+ fCurrDrawState.fViewMatrix;
}
return true;
}
@@ -241,15 +252,17 @@
uint32_t vertexCount,
uint32_t indexCount) {
- int newColorOffset, newTexCoordOffset;
+ int newColorOffset;
+ int newTexCoordOffsets[kNumStages];
- GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
- &newTexCoordOffset,
- &newColorOffset);
- int oldColorOffset, oldTexCoordOffset;
- GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
- &oldTexCoordOffset,
- &oldColorOffset);
+ GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
+ newTexCoordOffsets,
+ &newColorOffset);
+ int oldColorOffset;
+ int oldTexCoordOffsets[kNumStages];
+ GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
+ oldTexCoordOffsets,
+ &oldColorOffset);
const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
@@ -258,7 +271,7 @@
GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
GrGLVertexBuffer* buf =
- (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
+ (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
}
@@ -310,17 +323,23 @@
fHWGeometryState.fPositionPtr = posPtr;
}
- // need to enable array if tex coord offset is 0 (using positions as coords)
- if (newTexCoordOffset >= 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
- if (oldTexCoordOffset < 0) {
- GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
+ for (int s = 0; s < kNumStages; ++s) {
+ // need to enable array if tex coord offset is 0
+ // (using positions as coords)
+ if (newTexCoordOffsets[s] >= 0) {
+ GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[s];
+ if (oldTexCoordOffsets[s] < 0) {
+ GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
+ GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
+ }
+ if (posChange || newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
+ GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
+ GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
+ }
+ } else if (oldTexCoordOffsets[s] >= 0) {
+ GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
+ GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
}
- if (posChange || newTexCoordOffset != oldTexCoordOffset) {
- GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
- }
- } else if (oldTexCoordOffset >= 0) {
- GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
}
if (newColorOffset > 0) {
diff --git a/gpu/src/GrGpuGLFixed.h b/gpu/src/GrGpuGLFixed.h
index f3a0332..85db830 100644
--- a/gpu/src/GrGpuGLFixed.h
+++ b/gpu/src/GrGpuGLFixed.h
@@ -40,15 +40,15 @@
void resetContextHelper();
// when the texture is GL_RGBA we set the GL_COMBINE texture
- // environment rgb operand 0 to be GL_COLOR to modulate each incoming frag's
- // RGB by the texture's RGB. When the texture is GL_ALPHA we set
- // the operand to GL_ALPHA so that the incoming frag's RGB is modulated
- // by the texture's alpha.
+ // environment rgb operand 0 to be GL_COLOR to modulate each incoming
+ // R,G, & B by the texture's R, G, & B. When the texture is alpha-only we
+ // set the operand to GL_ALPHA so that the incoming frag's R, G, &B are all
+ // modulated by the texture's A.
enum TextureEnvRGBOperands {
kAlpha_TextureEnvRGBOperand,
kColor_TextureEnvRGBOperand,
};
- TextureEnvRGBOperands fHWRGBOperand0;
+ TextureEnvRGBOperands fHWRGBOperand0[kNumStages];
void flushProjectionMatrix();
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index b9db90c..2ace2ad 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -512,8 +512,9 @@
&fPrograms[p]);
GR_DEBUGASSERT(result);
- for (int m = 0; m < kMatrixModeCount; ++m) {
- fPrograms[p].fMatrixModeCache[m].setScale(GR_ScalarMax,
+ fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
+ for (int s = 0; s < kNumStages; ++s) {
+ fPrograms[p].fTextureMatrices[s].setScale(GR_ScalarMax,
GR_ScalarMax); // illegal
};
fPrograms[p].fColor = GrColor_ILLEGAL;
@@ -559,7 +560,7 @@
GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
0, 0, GrMatrix::I()[8]);
- m.setConcat(m, fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
+ m.setConcat(m, fCurrDrawState.fViewMatrix);
// ES doesn't allow you to pass true to the transpose param,
// so do our own transpose
@@ -593,11 +594,11 @@
0, -GR_Scalar1, GR_Scalar1,
0, 0, GrMatrix::I()[8]
);
- temp.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
+ temp.preConcat(fCurrDrawState.fTextureMatrices[0]);
m = &temp;
} else {
GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
- m = &fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
+ m = &fCurrDrawState.fTextureMatrices[0];
}
// ES doesn't allow you to pass true to the transpose param,
@@ -644,74 +645,77 @@
Programs nextProgram = kNoTexture_Program;
- if (!VertexHasTexCoords(fGeometrySrc.fVertexLayout)) {
+ GrTexture* texture = fCurrDrawState.fTextures[0];
+ bool posAsTex =
+ StagePosAsTexCoordVertexLayoutBit(0) & fGeometrySrc.fVertexLayout;
+
+ if (!VertexUsesStage(0, fGeometrySrc.fVertexLayout)) {
goto HAVE_NEXT_PROGRAM;
}
- GrAssert(fCurrDrawState.fTexture);
+ GrAssert(NULL != texture);
- switch (fCurrDrawState.fSamplerState.getSampleMode()) {
+ switch (fCurrDrawState.fSamplerStates[0].getSampleMode()) {
case GrSamplerState::kRadial_SampleMode:
- GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
- if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
+ GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
+ GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
+ if (posAsTex) {
nextProgram = kRadialTextureVertCoords_Program;
} else {
nextProgram = kRadialTextureTexCoords_Program;
}
break;
case GrSamplerState::kSweep_SampleMode:
- GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
- if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
+ GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
+ GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
+ if (posAsTex) {
nextProgram = kSweepTextureVertCoords_Program;
} else {
nextProgram = kSweepTextureTexCoords_Program;
}
break;
case GrSamplerState::kRadial2_SampleMode:
- GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
- if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
+ GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
+ GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
+ if (posAsTex) {
nextProgram = kTwoPointRadialTextureVertCoords_Program;
} else {
nextProgram = kTwoPointRadialTextureTexCoords_Program;
}
break;
- case GrSamplerState::kAlphaMod_SampleMode:
- GrAssert(((GrGLTexture*)fCurrDrawState.fTexture)->orientation() ==
- GrGLTexture::kTopDown_Orientation);
- (((GrGLTexture*)fCurrDrawState.fTexture)->uploadFormat() == GL_ALPHA);
-
- nextProgram = kText_Program;
- break;
- case GrSamplerState::kNormal_SampleMode: {
- GR_DEBUGCODE(GrGLTexture* tex = (GrGLTexture*)fCurrDrawState.fTexture;)
- GrAssert(tex);
-
- bool persp = fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective();
-
- if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
- nextProgram = persp ? kTextureVertCoordsProj_Program :
- kTextureVertCoords_Program;
+ case GrSamplerState::kNormal_SampleMode:
+ if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
+ GrAssert(((GrGLTexture*)texture)->orientation() ==
+ GrGLTexture::kTopDown_Orientation);
+ GrAssert(!posAsTex);
+ nextProgram = kText_Program;
} else {
- nextProgram = persp ? kTextureTexCoordsProj_Program :
- kTextureTexCoords_Program;
- }
- // check for case when frag shader can skip the color modulation
- if (!persp && !(fGeometrySrc.fVertexLayout
- & kColor_VertexLayoutBit) &&
- 0xffffffff == fCurrDrawState.fColor) {
- switch (nextProgram) {
- case kTextureVertCoords_Program:
- nextProgram = kTextureVertCoordsNoColor_Program;
- break;
- case kTextureTexCoords_Program:
- nextProgram = kTextureTexCoordsNoColor_Program;
- break;
- default:
- GrAssert("Unexpected");
- break;
+ bool persp = fCurrDrawState.fTextureMatrices[0].hasPerspective();
+ if (posAsTex) {
+ nextProgram = persp ? kTextureVertCoordsProj_Program :
+ kTextureVertCoords_Program;
+ } else {
+ nextProgram = persp ? kTextureTexCoordsProj_Program :
+ kTextureTexCoords_Program;
+ }
+ // check for case when frag shader can skip the color modulation
+ if (!persp && !(fGeometrySrc.fVertexLayout
+ & kColor_VertexLayoutBit) &&
+ 0xffffffff == fCurrDrawState.fColor) {
+ switch (nextProgram) {
+ case kTextureVertCoords_Program:
+ nextProgram = kTextureVertCoordsNoColor_Program;
+ break;
+ case kTextureTexCoords_Program:
+ nextProgram = kTextureTexCoordsNoColor_Program;
+ break;
+ default:
+ GrAssert("Unexpected");
+ break;
+ }
}
}
- } break;
+ break;
default:
GrAssert(!"Unknown samplemode");
break;
@@ -729,20 +733,26 @@
bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) {
+ for (int s = 1; s < kNumStages; ++s) {
+ if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
+ unimpl("the hard-coded shaders used by this "
+ "class only support 1 stage");
+ return false;
+ }
+ }
+
flushGLStateCommon(type);
if (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
- fHWDrawState.fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
- GR_ScalarMax);
+ fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
#else
// we assume all shader matrices may be wrong after viewport changes
for (int p = 0; p < kProgramCount; ++p) {
// set to illegal matrix
- fPrograms[p].fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
- GR_ScalarMax);
+ fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
}
#endif
fRenderTargetChanged = false;
@@ -783,36 +793,35 @@
}
#if ATTRIBUTE_MATRIX
- GrMatrix* currentMats = fHWDrawState.fMatrixModeCache;
+ GrMatrix& currentViewMatrix = fHWDrawState.fViewMatrix;
+ GrMatrix& currentTexMatrix = fHWDrawState.fTextureMatrices[0];
GrGLTexture::Orientation& orientation = fTextureOrientation;
#else
- GrMatrix* currentMats = fPrograms[fHWProgram].fMatrixModeCache;
+ GrMatrix& currentViewMatrix = fPrograms[fHWProgram].fViewMatrix;
+ GrMatrix& currentTexMatrix = fPrograms[fHWProgram].fTextureMatrices[0];
GrGLTexture::Orientation& orientation =
fPrograms[fHWProgram].fTextureOrientation;
#endif
- if (currentMats[kModelView_MatrixMode] !=
- fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
+ if (currentViewMatrix !=
+ fCurrDrawState.fViewMatrix) {
flushMatrix(fPrograms[fHWProgram].fMatrixLocation);
- currentMats[kModelView_MatrixMode] =
- fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
+ currentViewMatrix = fCurrDrawState.fViewMatrix;
}
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
+ GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[0];
if (NULL != texture) {
if (-1 != fPrograms[fHWProgram].fTexMatrixLocation &&
- (currentMats[kTexture_MatrixMode] !=
- fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode] ||
+ (currentTexMatrix != fCurrDrawState.fTextureMatrices[0] ||
orientation != texture->orientation())) {
flushTexMatrix(fPrograms[fHWProgram].fTexMatrixLocation,
texture->orientation());
- currentMats[kTexture_MatrixMode] =
- fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
+ currentTexMatrix = fCurrDrawState.fTextureMatrices[0];
orientation = texture->orientation();
}
}
- const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[0];
if (-1 != fPrograms[fHWProgram].fTwoPointParamsLocation &&
(fPrograms[fHWProgram].fRadial2CenterX1 != sampler.getRadial2CenterX1() ||
fPrograms[fHWProgram].fRadial2Radius0 != sampler.getRadial2Radius0() ||
@@ -833,15 +842,17 @@
uint32_t vertexCount,
uint32_t indexCount) {
- int newColorOffset, newTexCoordOffset;
+ int newColorOffset;
+ int newTexCoordOffsets[kNumStages];
- GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
- &newTexCoordOffset,
- &newColorOffset);
- int oldColorOffset, oldTexCoordOffset;
- GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
- &oldTexCoordOffset,
- &oldColorOffset);
+ GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
+ newTexCoordOffsets,
+ &newColorOffset);
+ int oldColorOffset;
+ int oldTexCoordOffsets[kNumStages];
+ GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
+ oldTexCoordOffsets,
+ &oldColorOffset);
const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
@@ -906,16 +917,17 @@
fHWGeometryState.fPositionPtr = posPtr;
}
- if (newTexCoordOffset > 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
- if (oldTexCoordOffset <= 0) {
+ // this class only supports one stage.
+ if (newTexCoordOffsets[0] > 0) {
+ GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[0];
+ if (oldTexCoordOffsets[0] <= 0) {
GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
}
- if (posChange || newTexCoordOffset != oldTexCoordOffset) {
+ if (posChange || newTexCoordOffsets[0] != oldTexCoordOffsets[0]) {
GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
texCoordNorm, newStride, texCoordPtr));
}
- } else if (oldTexCoordOffset > 0) {
+ } else if (oldTexCoordOffsets[0] > 0) {
GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
}
diff --git a/gpu/src/GrGpuGLShaders.h b/gpu/src/GrGpuGLShaders.h
index cba387b..e5a5665 100644
--- a/gpu/src/GrGpuGLShaders.h
+++ b/gpu/src/GrGpuGLShaders.h
@@ -134,7 +134,8 @@
// these reflect the current values of uniforms
// (GL uniform values travel with program)
- GrMatrix fMatrixModeCache[kMatrixModeCount];
+ GrMatrix fViewMatrix;
+ GrMatrix fTextureMatrices[kNumStages];
GrColor fColor;
GrGLTexture::Orientation fTextureOrientation;
GrScalar fRadial2CenterX1;
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
index c7b3cb9..92df809 100644
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ b/gpu/src/GrGpuGLShaders2.cpp
@@ -41,17 +41,16 @@
const char GR_SHADER_PRECISION[] = "";
#endif
+
#define POS_ATTR_LOCATION 0
-#define TEX_ATTR_LOCATION 1
-#define COL_ATTR_LOCATION 2
+#define TEX_ATTR_LOCATION(X) (1 + X)
+#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords)
#if ATTRIBUTE_MATRIX
-#define VIEWMAT_ATTR_LOCATION 3
-#define TEXMAT_ATTR_LOCATION(X) (6 + 3 * (X))
+#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
+#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
#define BOGUS_MATRIX_UNI_LOCATION 1000
#endif
-const int GrGpuGLShaders2::NUM_STAGES = 1;
-
struct GrGpuGLShaders2::StageUniLocations {
GLint fTextureMatrixUni;
GLint fSamplerUni;
@@ -60,7 +59,7 @@
struct GrGpuGLShaders2::UniLocations {
GLint fViewMatrixUni;
- StageUniLocations fStages[NUM_STAGES];
+ StageUniLocations fStages[kNumStages];
};
// Records per-program information
@@ -82,11 +81,11 @@
// these reflect the current values of uniforms
// (GL uniform values travel with program)
GrMatrix fViewMatrix;
- GrMatrix fTextureMatrix[NUM_STAGES];
- GrGLTexture::Orientation fTextureOrientation[NUM_STAGES];
- GrScalar fRadial2CenterX1[NUM_STAGES];
- GrScalar fRadial2Radius0[NUM_STAGES];
- bool fRadial2PosRoot[NUM_STAGES];
+ GrMatrix fTextureMatrix[kNumStages];
+ GrGLTexture::Orientation fTextureOrientation[kNumStages];
+ GrScalar fRadial2CenterX1[kNumStages];
+ GrScalar fRadial2Radius0[kNumStages];
+ bool fRadial2PosRoot[kNumStages];
};
@@ -127,12 +126,12 @@
// for this to pack
unsigned short fOptFlags : 16;
- StageDesc fStages[NUM_STAGES];
+ 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 * NUM_STAGES == sizeof(ProgramDesc));
+ GR_STATIC_ASSERT(2 + 2 + 4 * kNumStages == sizeof(ProgramDesc));
return 0 == memcmp(this, &desc, sizeof(ProgramDesc));
}
};
@@ -237,7 +236,6 @@
return (x >> 8) | (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
@@ -289,7 +287,11 @@
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
-#define TEX_ATTR_NAME "aTexture"
+
+static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
+ *s = "aTexCoord";
+ s->appendInt(coordIdx);
+}
static inline const char* float_vector_type(int count) {
static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
@@ -347,14 +349,6 @@
#include "GrRandom.h"
void GrGpuGLShaders2::ProgramUnitTest() {
- static const uint16_t VFORMATS[] = {
- 0,
- kSeparateTexCoord_VertexLayoutBit,
- kPositionAsTexCoord_VertexLayoutBit,
- kSeparateTexCoord_VertexLayoutBit | kColor_VertexLayoutBit,
- kPositionAsTexCoord_VertexLayoutBit | kColor_VertexLayoutBit,
- kTextFormat_VertexLayoutBit
- };
static const int PROG_OPTS[] = {
0,
ProgramDesc::kNotPoints_OptFlagBit,
@@ -379,19 +373,35 @@
ProgramDesc pdesc;
memset(&pdesc, 0, sizeof(pdesc));
- static const int NUM_TESTS = 1024;
+ static const int NUM_TESTS = 512;
// GrRandoms nextU() values have patterns in the low bits
// So using nextU() % array_count might never take some values.
GrRandom random;
for (int t = 0; t < NUM_TESTS; ++t) {
- int x = (int)(random.nextF() * GR_ARRAY_COUNT(VFORMATS));
- pdesc.fVertexLayout = VFORMATS[x];
- x = (int)(random.nextF() * GR_ARRAY_COUNT(PROG_OPTS));
+
+ pdesc.fVertexLayout = 0;
+ for (int s = 0; s < kNumStages; ++s) {
+ // enable the stage?
+ if (random.nextF() > .5f) {
+ // use separate tex coords?
+ if (random.nextF() > .5f) {
+ int t = (int)(random.nextF() * kMaxTexCoords);
+ pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
+ } else {
+ pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
+ }
+ }
+ // use text-formatted verts?
+ if (random.nextF() > .5f) {
+ pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
+ }
+ }
+
+ int x = (int)(random.nextF() * GR_ARRAY_COUNT(PROG_OPTS));
pdesc.fOptFlags = PROG_OPTS[x];
- for (int s = 0; s < NUM_STAGES; ++s) {
- x = (int)(random.nextF() * 2.f);
- pdesc.fStages[s].fEnabled = x;
+ for (int s = 0; s < kNumStages; ++s) {
+ pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
@@ -696,30 +706,46 @@
}
segments.fFSCode = "void main() {\n";
- bool textureCoordAttr = false;
- static const char* IN_COORDS[] = {POS_ATTR_NAME, TEX_ATTR_NAME};
- const char* inCoords = NULL;
- if ((kSeparateTexCoord_VertexLayoutBit | kTextFormat_VertexLayoutBit) &
- layout) {
- segments.fVSAttrs += "attribute vec2 " TEX_ATTR_NAME ";\n";
- inCoords = IN_COORDS[1];
- textureCoordAttr = true;
- } else if (kPositionAsTexCoord_VertexLayoutBit & layout) {
- inCoords = IN_COORDS[0];
+ // add texture coordinates that are used to the list of vertex attr decls
+ GrTokenString texCoordAttrs[kMaxTexCoords];
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ if (VertexUsesTexCoordIdx(t, layout)) {
+ tex_attr_name(t, texCoordAttrs + t);
+
+ segments.fVSAttrs += "attribute vec2 ";
+ segments.fVSAttrs += texCoordAttrs[t];
+ segments.fVSAttrs += ";\n";
+ }
}
- GrTokenString inColor = "vColor";
- GR_STATIC_ASSERT(NUM_STAGES <= 9);
+ // for each enabled stage figure out what the input coordinates are
+ // and count the number of stages in use.
+ const char* stageInCoords[kNumStages];
int numActiveStages = 0;
- for (int i = 0; i < NUM_STAGES; ++i) {
- if (desc.fStages[i].fEnabled) {
+
+ for (int s = 0; s < kNumStages; ++s) {
+ if (desc.fStages[s].fEnabled) {
+ if (StagePosAsTexCoordVertexLayoutBit(s) & layout) {
+ stageInCoords[s] = POS_ATTR_NAME;
+ } else {
+ int tcIdx = VertexTexCoordsForStage(s, layout);
+ // we better have input tex coordinates if stage is enabled.
+ GrAssert(tcIdx >= 0);
+ GrAssert(texCoordAttrs[tcIdx].length());
+ stageInCoords[s] = texCoordAttrs[tcIdx].cstr();
+ }
++numActiveStages;
}
}
- if (NULL != inCoords && numActiveStages) {
+
+ 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) {
int currActiveStage = 0;
- for (int i = 0; i < NUM_STAGES; ++i) {
- if (desc.fStages[i].fEnabled) {
+ for (int s = 0; s < kNumStages; ++s) {
+ if (desc.fStages[s].fEnabled) {
GrTokenString outColor;
if (currActiveStage < (numActiveStages - 1)) {
outColor = "color";
@@ -730,13 +756,13 @@
} else {
outColor = "gl_FragColor";
}
- GenStageCode(i,
- desc.fStages[i],
+ GenStageCode(s,
+ desc.fStages[s],
haveColor ? inColor.cstr() : NULL,
outColor.cstr(),
- inCoords,
+ stageInCoords[s],
&segments,
- &program->fUniLocations.fStages[i]);
+ &program->fUniLocations.fStages[s]);
++currActiveStage;
inColor = outColor;
haveColor = true;
@@ -835,8 +861,12 @@
// Bind the attrib locations to same values for all shaders
GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME));
- if (textureCoordAttr) {
- GR_GL(BindAttribLocation(progID, TEX_ATTR_LOCATION, TEX_ATTR_NAME));
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ if (texCoordAttrs[t].length()) {
+ GR_GL(BindAttribLocation(progID,
+ TEX_ATTR_LOCATION(t),
+ texCoordAttrs[t].cstr()));
+ }
}
#if ATTRIBUTE_MATRIX
@@ -848,12 +878,12 @@
program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION;
- for (int i = 0; i < NUM_STAGES; ++i) {
- if (desc.fStages[i].fEnabled) {
+ for (int s = 0; s < kNumStages; ++s) {
+ if (desc.fStages[s].fEnabled) {
GR_GL(BindAttribLocation(progID,
- TEXMAT_ATTR_LOCATION(i),
+ TEXMAT_ATTR_LOCATION(s),
tex_matrix_name(i).cstr()));
- program->fUniLocations.fStages[i].fTextureMatrixUni =
+ program->fUniLocations.fStages[s].fTextureMatrixUni =
BOGUS_MATRIX_UNI_LOCATION;
}
}
@@ -888,13 +918,13 @@
GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
GrAssert(-1 != program->fUniLocations.fViewMatrixUni);
#endif
- for (int i = 0; i < NUM_STAGES; ++i) {
- StageUniLocations& locations = program->fUniLocations.fStages[i];
- if (desc.fStages[i].fEnabled) {
+ for (int s = 0; s < kNumStages; ++s) {
+ StageUniLocations& locations = program->fUniLocations.fStages[s];
+ if (desc.fStages[s].fEnabled) {
#if !ATTRIBUTE_MATRIX
if (locations.fTextureMatrixUni) {
GrTokenString texMName;
- tex_matrix_name(i, &texMName);
+ tex_matrix_name(s, &texMName);
locations.fTextureMatrixUni = GR_GL(GetUniformLocation(
progID,
texMName.cstr()));
@@ -907,7 +937,7 @@
if (locations.fSamplerUni) {
GrTokenString samplerName;
- sampler_name(i, &samplerName);
+ sampler_name(s, &samplerName);
locations.fSamplerUni = GR_GL(GetUniformLocation(
progID,
samplerName.cstr()));
@@ -918,7 +948,7 @@
if (locations.fRadial2Uni) {
GrTokenString radial2ParamName;
- radial2_param_name(i, &radial2ParamName);
+ radial2_param_name(s, &radial2ParamName);
locations.fRadial2Uni = GR_GL(GetUniformLocation(
progID,
radial2ParamName.cstr()));
@@ -935,13 +965,13 @@
GR_GL(UseProgram(progID));
// init sampler unis and set bogus values for state tracking
- for (int i = 0; i < NUM_STAGES; ++i) {
- if (-1 != program->fUniLocations.fStages[i].fSamplerUni) {
- GR_GL(Uniform1i(program->fUniLocations.fStages[i].fSamplerUni, i));
+ for (int s = 0; s < kNumStages; ++s) {
+ if (-1 != program->fUniLocations.fStages[s].fSamplerUni) {
+ GR_GL(Uniform1i(program->fUniLocations.fStages[s].fSamplerUni, s));
}
- program->fTextureMatrix[i].setScale(GR_ScalarMax, GR_ScalarMax);
- program->fRadial2CenterX1[i] = GR_ScalarMax;
- program->fRadial2Radius0[i] = -GR_ScalarMax;
+ program->fTextureMatrix[s].setScale(GR_ScalarMax, GR_ScalarMax);
+ program->fRadial2CenterX1[s] = GR_ScalarMax;
+ program->fRadial2Radius0[s] = -GR_ScalarMax;
}
program->fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
}
@@ -950,70 +980,63 @@
// Must initialize all fields or cache will have false negatives!
desc->fVertexLayout = fGeometrySrc.fVertexLayout;
- desc->fStages[0].fEnabled = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
- for (int i = 1; i < NUM_STAGES; ++i) {
- desc->fStages[i].fEnabled = false;
- desc->fStages[i].fOptFlags = 0;
- desc->fStages[i].fCoordMapping = (StageDesc::CoordMapping)0;
- desc->fStages[i].fModulation = (StageDesc::Modulation)0;
- }
+ for (int s = 0; s < kNumStages; ++s) {
+ StageDesc& stage = desc->fStages[s];
+
+ stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
- if (primType != kPoints_PrimitiveType) {
- desc->fOptFlags = ProgramDesc::kNotPoints_OptFlagBit;
- } else {
- desc->fOptFlags = 0;
- }
-#if SKIP_COLOR_MODULATE_OPT
- if (!(desc->fVertexLayout & kColor_VertexLayoutBit) &&
- (0xffffffff == fCurrDrawState.fColor)) {
- desc->fOptFlags |= ProgramDesc::kVertexColorAllOnes_OptFlagBit;
- }
-#endif
-
- StageDesc& stage = desc->fStages[0];
-
- if (stage.fEnabled) {
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
- GrAssert(NULL != texture);
- // we matrix to invert when orientation is TopDown, so make sure
- // we aren't in that case before flagging as identity.
- if (fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].isIdentity() &&
- GrGLTexture::kTopDown_Orientation == texture->orientation()) {
- stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
- } else if (!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective()) {
- stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
+ if (primType != kPoints_PrimitiveType) {
+ desc->fOptFlags = ProgramDesc::kNotPoints_OptFlagBit;
} else {
- stage.fOptFlags = 0;
+ desc->fOptFlags = 0;
}
- switch (fCurrDrawState.fSamplerState.getSampleMode()) {
- case GrSamplerState::kNormal_SampleMode:
- stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
- stage.fModulation = StageDesc::kColor_Modulation;
- break;
- case GrSamplerState::kAlphaMod_SampleMode:
- stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
- stage.fModulation = StageDesc::kAlpha_Modulation;
- break;
- case GrSamplerState::kRadial_SampleMode:
- stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
- stage.fModulation = StageDesc::kColor_Modulation;
- break;
- case GrSamplerState::kRadial2_SampleMode:
- stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
- stage.fModulation = StageDesc::kColor_Modulation;
- break;
- case GrSamplerState::kSweep_SampleMode:
- stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
- stage.fModulation = StageDesc::kColor_Modulation;
- break;
- default:
- GrAssert(!"Unexpected sample mode!");
- break;
+ #if SKIP_COLOR_MODULATE_OPT
+ if (!(desc->fVertexLayout & kColor_VertexLayoutBit) &&
+ (0xffffffff == fCurrDrawState.fColor)) {
+ desc->fOptFlags |= ProgramDesc::kVertexColorAllOnes_OptFlagBit;
}
- } else {
- stage.fOptFlags = 0;
- stage.fCoordMapping = (StageDesc::CoordMapping)0;
- stage.fModulation = (StageDesc::Modulation)0;
+ #endif
+
+ if (stage.fEnabled) {
+ GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+ GrAssert(NULL != texture);
+ // we matrix to invert when orientation is TopDown, so make sure
+ // we aren't in that case before flagging as identity.
+ if (fCurrDrawState.fTextureMatrices[s].isIdentity() &&
+ GrGLTexture::kTopDown_Orientation == texture->orientation()) {
+ stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
+ } else if (!fCurrDrawState.fTextureMatrices[s].hasPerspective()) {
+ stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
+ } else {
+ stage.fOptFlags = 0;
+ }
+ switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
+ case GrSamplerState::kNormal_SampleMode:
+ stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
+ break;
+ case GrSamplerState::kRadial_SampleMode:
+ stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
+ break;
+ case GrSamplerState::kRadial2_SampleMode:
+ stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
+ break;
+ case GrSamplerState::kSweep_SampleMode:
+ stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
+ break;
+ default:
+ GrAssert(!"Unexpected sample mode!");
+ break;
+ }
+ if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
+ stage.fModulation = StageDesc::kAlpha_Modulation;
+ } else {
+ stage.fModulation = StageDesc::kColor_Modulation;
+ }
+ } else {
+ stage.fOptFlags = 0;
+ stage.fCoordMapping = (StageDesc::CoordMapping)0;
+ stage.fModulation = (StageDesc::Modulation)0;
+ }
}
}
@@ -1088,7 +1111,9 @@
fHWGeometryState.fVertexLayout = 0;
fHWGeometryState.fPositionPtr = (void*) ~0;
GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
- GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION));
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
+ }
GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION));
fHWProgramID = 0;
@@ -1100,7 +1125,7 @@
GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
0, 0, GrMatrix::I()[8]);
- m.setConcat(m, fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
+ m.setConcat(m, fCurrDrawState.fViewMatrix);
// ES doesn't allow you to pass true to the transpose param,
// so do our own transpose
@@ -1124,11 +1149,11 @@
#endif
}
-void GrGpuGLShaders2::flushTextureMatrix() {
+void GrGpuGLShaders2::flushTextureMatrix(int stage) {
- GrAssert(NULL != fCurrDrawState.fTexture);
+ GrAssert(NULL != fCurrDrawState.fTextures[stage]);
GrGLTexture::Orientation orientation =
- ((GrGLTexture*)fCurrDrawState.fTexture)->orientation();
+ ((GrGLTexture*)fCurrDrawState.fTextures[stage])->orientation();
GrMatrix* m;
GrMatrix temp;
@@ -1138,11 +1163,11 @@
0, -GR_Scalar1, GR_Scalar1,
0, 0, GrMatrix::I()[8]
);
- temp.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
+ temp.preConcat(fCurrDrawState.fTextureMatrices[stage]);
m = &temp;
} else {
GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
- m = &fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
+ m = &fCurrDrawState.fTextureMatrices[stage];
}
// ES doesn't allow you to pass true to the transpose param,
@@ -1163,16 +1188,16 @@
glVertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3);
glVertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6);
#else
- GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fStages[0].fTextureMatrixUni,
+ GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fStages[stage].fTextureMatrixUni,
1,
false,
mt));
#endif
}
-void GrGpuGLShaders2::flushRadial2() {
+void GrGpuGLShaders2::flushRadial2(int stage) {
- const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[stage];
GrScalar centerX1 = sampler.getRadial2CenterX1();
GrScalar radius0 = sampler.getRadial2Radius0();
@@ -1187,7 +1212,9 @@
GrScalarToFloat(GrMul(radius0, radius0)),
sampler.isRadial2PosRoot() ? 1.f : -1.f
};
- GR_GL(Uniform1fv(fProgram->fUniLocations.fStages[0].fRadial2Uni, 6, unis));
+ GR_GL(Uniform1fv(fProgram->fUniLocations.fStages[stage].fRadial2Uni,
+ 6,
+ unis));
}
void GrGpuGLShaders2::flushProgram(PrimitiveType type) {
@@ -1212,8 +1239,7 @@
// 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
- fHWDrawState.fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
- GR_ScalarMax);
+ fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
#else
// we assume all shader matrices may be wrong after viewport changes
fProgramCache->invalidateViewMatrices();
@@ -1241,7 +1267,7 @@
}
#if ATTRIBUTE_MATRIX
- GrMatrix& currViewMatrix = fHWDrawState.fMatrixModeCache[kModelView_MatrixMode];
+ GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
GrMatrix& currTextureMatrix = fHWDrawState.fMatrixModeCache[kTexture_MatrixMode];
GrGLTexture::Orientation& orientation = fTextureOrientation;
#else
@@ -1250,53 +1276,56 @@
GrGLTexture::Orientation& orientation = fProgram->fTextureOrientation[0];
#endif
- if (currViewMatrix != fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
+ if (currViewMatrix != fCurrDrawState.fViewMatrix) {
flushViewMatrix();
- currViewMatrix = fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
+ currViewMatrix = fCurrDrawState.fViewMatrix;
}
- GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
- if (NULL != texture) {
- if (-1 != fProgram->fUniLocations.fStages[0].fTextureMatrixUni &&
- (currTextureMatrix !=
- fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode] ||
- orientation != texture->orientation())) {
- flushTextureMatrix();
- currTextureMatrix = fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
- orientation = texture->orientation();
+ for (int s = 0; s < kNumStages; ++s) {
+ GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+ if (NULL != texture) {
+ if (-1 != fProgram->fUniLocations.fStages[s].fTextureMatrixUni &&
+ (currTextureMatrix != fCurrDrawState.fTextureMatrices[s] ||
+ orientation != texture->orientation())) {
+ flushTextureMatrix(s);
+ currTextureMatrix = fCurrDrawState.fTextureMatrices[s];
+ orientation = texture->orientation();
+ }
}
- }
- const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
- if (-1 != fProgram->fUniLocations.fStages[0].fRadial2Uni &&
- (fProgram->fRadial2CenterX1[0] != sampler.getRadial2CenterX1() ||
- fProgram->fRadial2Radius0[0] != sampler.getRadial2Radius0() ||
- fProgram->fRadial2PosRoot[0] != sampler.isRadial2PosRoot())) {
+ const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+ if (-1 != fProgram->fUniLocations.fStages[s].fRadial2Uni &&
+ (fProgram->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
+ fProgram->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
+ fProgram->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
- flushRadial2();
+ flushRadial2(s);
- fProgram->fRadial2CenterX1[0] = sampler.getRadial2CenterX1();
- fProgram->fRadial2Radius0[0] = sampler.getRadial2Radius0();
- fProgram->fRadial2PosRoot[0] = sampler.isRadial2PosRoot();
+ fProgram->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
+ fProgram->fRadial2Radius0[s] = sampler.getRadial2Radius0();
+ fProgram->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
+ }
}
return true;
}
void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
+ uint32_t startIndex,
+ uint32_t vertexCount,
+ uint32_t indexCount) {
- int newColorOffset, newTexCoordOffset;
+ int newColorOffset;
+ int newTexCoordOffsets[kMaxTexCoords];
- GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
- &newTexCoordOffset,
- &newColorOffset);
- int oldColorOffset, oldTexCoordOffset;
- GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
- &oldTexCoordOffset,
- &oldColorOffset);
+ GLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
+ newTexCoordOffsets,
+ &newColorOffset);
+ int oldColorOffset;
+ int oldTexCoordOffsets[kMaxTexCoords];
+ GLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
+ oldTexCoordOffsets,
+ &oldColorOffset);
const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
@@ -1305,7 +1334,7 @@
GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
GrGLVertexBuffer* buf =
- (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
+ (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
}
@@ -1327,8 +1356,7 @@
GrAssert(NULL != fGeometrySrc.fIndexBuffer);
GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
- GrGLIndexBuffer* buf =
- (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
+ GrGLIndexBuffer* buf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
}
@@ -1361,17 +1389,19 @@
fHWGeometryState.fPositionPtr = posPtr;
}
- if (newTexCoordOffset > 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
- if (oldTexCoordOffset <= 0) {
- GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION));
+ for (int t = 0; t < kMaxTexCoords; ++t) {
+ if (newTexCoordOffsets[t] > 0) {
+ GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[t];
+ if (oldTexCoordOffsets[t] <= 0) {
+ GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t)));
+ }
+ if (posChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
+ GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
+ texCoordNorm, newStride, texCoordPtr));
+ }
+ } else if (oldTexCoordOffsets[t] > 0) {
+ GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
}
- if (posChange || newTexCoordOffset != oldTexCoordOffset) {
- GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION, 2, scalarType,
- texCoordNorm, newStride, texCoordPtr));
- }
- } else if (oldTexCoordOffset > 0) {
- GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION));
}
if (newColorOffset > 0) {
diff --git a/gpu/src/GrGpuGLShaders2.h b/gpu/src/GrGpuGLShaders2.h
index c484544..bba63f6 100644
--- a/gpu/src/GrGpuGLShaders2.h
+++ b/gpu/src/GrGpuGLShaders2.h
@@ -37,17 +37,17 @@
uint32_t indexCount);
private:
- static const int NUM_STAGES;
void resetContextHelper();
// sets the texture matrix uniform for currently bound program
- void flushTextureMatrix();
+ void flushTextureMatrix(int stage);
+
// sets the MVP matrix uniform for currently bound program
void flushViewMatrix();
// flushes the parameters to two point radial gradient
- void flushRadial2();
+ void flushRadial2(int stage);
// called at flush time to setup the appropriate program
void flushProgram(PrimitiveType type);
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 952ba83..494f227 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -156,9 +156,11 @@
GrAssert(!fReservedGeometry.fLocked);
uint32_t numStates = fStates.count();
for (uint32_t i = 0; i < numStates; ++i) {
- GrTexture* tex = accessSavedDrawState(fStates[i]).fTexture;
- if (NULL != tex) {
- tex->unref();
+ for (int s = 0; s < kNumStages; ++s) {
+ GrTexture* tex = accessSavedDrawState(fStates[i]).fTextures[s];
+ if (NULL != tex) {
+ tex->unref();
+ }
}
}
fDraws.reset();
@@ -320,8 +322,10 @@
newState = old != fCurrDrawState;
}
if (newState) {
- if (NULL != fCurrDrawState.fTexture) {
- fCurrDrawState.fTexture->ref();
+ for (int s = 0; s < kNumStages; ++s) {
+ if (NULL != fCurrDrawState.fTextures[s]) {
+ fCurrDrawState.fTextures[s]->ref();
+ }
}
saveCurrentDrawState(&fStates.push_back());
}
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 0264856..0a777d6 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -23,7 +23,9 @@
#include "GrTextStrike_impl.h"
#include "GrFontScaler.h"
-static const GrVertexLayout VLAYOUT = GrDrawTarget::kTextFormat_VertexLayoutBit;
+static const GrVertexLayout VLAYOUT =
+ GrDrawTarget::kTextFormat_VertexLayoutBit |
+ GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
void GrTextContext::flushGlyphs() {
if (fCurrVertex > 0) {
@@ -33,15 +35,14 @@
GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode,
GrSamplerState::kRepeat_WrapMode,
- GrSamplerState::kAlphaMod_SampleMode,
!fExtMatrix.isIdentity());
- fDrawTarget->setSamplerState(sampler);
+ fDrawTarget->setSamplerState(0, sampler);
GrAssert(GrIsALIGN4(fCurrVertex));
int nIndices = fCurrVertex + (fCurrVertex >> 1);
GrAssert(fCurrTexture);
- fDrawTarget->setTexture(fCurrTexture);
- fDrawTarget->setTextureMatrix(GrMatrix::I());
+ fDrawTarget->setTexture(0, fCurrTexture);
+ fDrawTarget->setTextureMatrix(0, GrMatrix::I());
fDrawTarget->setIndexSourceToBuffer(fContext->quadIndexBuffer());
fDrawTarget->drawIndexed(GrDrawTarget::kTriangles_PrimitiveType,