aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'gpu')
-rw-r--r--gpu/include/GrContext.h6
-rw-r--r--gpu/include/GrDrawTarget.h232
-rw-r--r--gpu/include/GrGLConfig.h16
-rw-r--r--gpu/include/GrSamplerState.h1
-rw-r--r--gpu/src/GrContext.cpp30
-rw-r--r--gpu/src/GrDrawTarget.cpp322
-rw-r--r--gpu/src/GrGLTexture.cpp4
-rw-r--r--gpu/src/GrGpu.cpp28
-rw-r--r--gpu/src/GrGpuGL.cpp287
-rw-r--r--gpu/src/GrGpuGL.h13
-rw-r--r--gpu/src/GrGpuGLFixed.cpp211
-rw-r--r--gpu/src/GrGpuGLFixed.h10
-rw-r--r--gpu/src/GrGpuGLShaders.cpp166
-rw-r--r--gpu/src/GrGpuGLShaders.h3
-rw-r--r--gpu/src/GrGpuGLShaders2.cpp412
-rw-r--r--gpu/src/GrGpuGLShaders2.h6
-rw-r--r--gpu/src/GrInOrderDrawBuffer.cpp14
-rw-r--r--gpu/src/GrTextContext.cpp11
18 files changed, 1091 insertions, 681 deletions
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 68f8f7eac0..a9316957cb 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -129,9 +129,9 @@ public:
void setDefaultRenderTargetSize(uint32_t width, uint32_t height);
GrRenderTarget* defaultRenderTarget() { return fGpu->defaultRenderTarget(); }
- void setTexture(GrTexture* texture);
- void setSamplerState(const GrSamplerState&);
- void setTextureMatrix(const GrMatrix& m);
+ void setTexture(int stage, GrTexture* texture);
+ void setSamplerState(int stage, const GrSamplerState&);
+ void setTextureMatrix(int stage, const GrMatrix& m);
void setAntiAlias(bool);
void setDither(bool);
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 2823da70c6..3405bb50c5 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -34,6 +34,27 @@ class GrIndexBuffer;
class GrDrawTarget : public GrRefCnt {
public:
/**
+ * Number of texture stages. Each stage takes as input a color and
+ * 2D texture coordinates. The color input to the first enabled stage is the
+ * per-vertex color or the constant color (setColor/setAlpha) if there are no
+ * per-vertex colors. For subsequent stages the input color is the output
+ * color from the previous enabled stage. The output color of each stage is
+ * the input color modulated with the result of a texture lookup. Texture
+ * lookups are specified by a texture (setTexture), a texture matrix
+ * (setTextureMatrix), and a sampler (setSamplerState). Texture coordinates
+ * for each stage come from the vertices based on a GrVertexLayout bitfield.
+ * The output fragment color is the output color of the last enabled stage.
+ * The presence or absence of texture coordinates for each stage in the
+ * vertex layout indicates whether a stage is enabled or not.
+ */
+
+ // Currently there is just one stage but this will be changed soon.
+ enum {
+ kNumStages = 1,
+ kMaxTexCoords = kNumStages
+ };
+
+ /**
* Geometric primitives used for drawing.
*/
enum PrimitiveType {
@@ -124,25 +145,20 @@ public:
};
protected:
- enum MatrixMode {
- kModelView_MatrixMode = 0,
- kTexture_MatrixMode,
-
- kMatrixModeCount
- };
struct DrState {
uint32_t fFlagBits;
BlendCoeff fSrcBlend;
BlendCoeff fDstBlend;
- GrTexture* fTexture;
- GrSamplerState fSamplerState;
+ GrTexture* fTextures[kNumStages];
+ GrSamplerState fSamplerStates[kNumStages];
GrRenderTarget* fRenderTarget;
GrColor fColor;
float fPointSize;
StencilPass fStencilPass;
bool fReverseFill;
- GrMatrix fMatrixModeCache[kMatrixModeCount];
+ GrMatrix fViewMatrix;
+ GrMatrix fTextureMatrices[kNumStages];
bool operator ==(const DrState& s) const {
return 0 == memcmp(this, &s, sizeof(DrState));
}
@@ -172,10 +188,12 @@ public:
/**
* Sets the texture used at the next drawing call
*
+ * @param stage The texture stage for which the texture will be set
+ *
* @param texture The texture to set. Can be NULL though there is no advantage
* to settings a NULL texture if doing non-textured drawing
*/
- void setTexture(GrTexture* texture);
+ void setTexture(int stage, GrTexture* texture);
/**
* Retrieves the currently set texture.
@@ -184,7 +202,7 @@ public:
* texture has been set, NULL was most recently passed to
* setTexture, or the last setTexture was destroyed.
*/
- GrTexture* currentTexture() const;
+ GrTexture* currentTexture(int stage) const;
/**
* Sets the rendertarget used at the next drawing call
@@ -210,10 +228,10 @@ public:
*
* @param samplerState Specifies the sampler state.
*/
- void setSamplerState(const GrSamplerState& samplerState);
+ void setSamplerState(int stage, const GrSamplerState& samplerState);
/**
- * Sets the matrix applied to texture coordinates.
+ * Sets the matrix applied to texture coordinates for a stage.
*
* The post-matrix texture coordinates in the square [0,1]^2 cover the
* entire area of the texture. This means the full POT width when a NPOT
@@ -223,11 +241,10 @@ public:
* coordinates. In the latter case the texture matrix is applied to the
* pre-modelview position values.
*
- * @param m the matrix used to transform the texture coordinates.
+ * @param stage the stage for which to set a matrix.
+ * @param m the matrix used to transform the texture coordinates.
*/
- void setTextureMatrix(const GrMatrix& m) {
- this->loadMatrix(m, kTexture_MatrixMode);
- }
+ void setTextureMatrix(int stage, const GrMatrix& m);
/**
* Sets the matrix applied to veretx positions.
@@ -238,9 +255,7 @@ public:
*
* @param m the matrix used to transform the vertex positions.
*/
- void setViewMatrix(const GrMatrix& m) {
- this->loadMatrix(m, kModelView_MatrixMode);
- }
+ void setViewMatrix(const GrMatrix& m);
/**
* Multiplies the current view matrix by a matrix
@@ -379,38 +394,77 @@ public:
void copyDrawState(const GrDrawTarget& srcTarget);
/**
- * Flags that indicate the layout of vertex data.
+ * The format of vertices is represented as a bitfield of flags.
+ * Flags that indicate the layout of vertex data. Vertices always contain
+ * positions and may also contain up to kMaxTexCoords sets of 2D texture
+ * coordinates and per-vertex colors. Each stage can use any of the texture
+ * coordinates as its input texture coordinates or it may use the positions.
+ *
+ * If no texture coordinates are specified for a stage then the stage is
+ * disabled.
*
- * kSeparateTexCoord_VertexLayoutBit is incompatible with
- * kPositionAsTexCoord_VertexLayoutBit. kTextFormat_VertexLayoutBit is
- * incompatible with any other flags.
+ * Only one type of texture coord can be specified per stage. For
+ * example StageTexCoordVertexLayoutBit(0, 2) and
+ * StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
*
- * When kTextFormat_VertexLayoutBit is set:
- * Texture coordinates are separate.
- * Positions and Texture coordinates are SkGpuTextVertex.
- * For non-text vertices:
- * Position and texture coordinates are GrPoints.
- * Colors are GrColors.
+ * The order in memory is always (position, texture coord 0, ..., color)
+ * with any unused fields omitted. Note that this means that if only texture
+ * coordinates 1 is referenced then there is no texture coordinates 0 and
+ * the order would be (position, texture coordinate 1[, color]).
+ */
+
+ /**
+ * Generates a bit indicating that a texture stage uses texture coordinates
+ *
+ * @param stage the stage that will use texture coordinates.
+ * @param texCoordIdx the index of the texture coordinates to use
*
- * The order is always positions, texture coords, colors.
+ * @return the bit to add to a GrVertexLayout bitfield.
+ */
+ static int StageTexCoordVertexLayoutBit(int stage, int texCoordIdx) {
+ GrAssert(stage < kNumStages);
+ GrAssert(texCoordIdx < kMaxTexCoords);
+ return 1 << (stage + (texCoordIdx * kNumStages));
+ }
+private:
+ static const int TEX_COORD_BIT_CNT = kNumStages*kMaxTexCoords;
+public:
+ /**
+ * Generates a bit indicating that a texture stage uses the position
+ * as its texture coordinate.
+ *
+ * @param stage the stage that will use position as texture
+ * coordinates.
+ *
+ * @return the bit to add to a GrVertexLayout bitfield.
+ */
+ static int StagePosAsTexCoordVertexLayoutBit(int stage) {
+ GrAssert(stage < kNumStages);
+ return (1 << (TEX_COORD_BIT_CNT + stage));
+ }
+private:
+ static const int STAGE_BIT_CNT = TEX_COORD_BIT_CNT + kNumStages;
+
+public:
+
+ /**
+ * Additional Bits that can be specified in GrVertexLayout.
*/
enum VertexLayoutBits {
- kSeparateTexCoord_VertexLayoutBit = 0x1, //<! vertices have texture
- // coords that are not
- // inferred from the
- // positions
- kPositionAsTexCoord_VertexLayoutBit = 0x2, //<! vertices use positions
- // as texture coords.
- kColor_VertexLayoutBit = 0x4, //<! vertices have colors
- kTextFormat_VertexLayoutBit = 0x8, //<! vertices represent glyphs
- // and therefore contain
- // two GrGpuTextVertexs.
- // One for pos and one for
- // text coords.
+
+ kColor_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 0),
+ //<! vertices have colors
+ kTextFormat_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1),
+ //<! use text vertices. (Pos
+ // and tex coords may be
+ // a different type for
+ // text [GrGpuTextVertex vs
+ // GrPoint].)
// for below assert
kDummy,
kHighVertexLayoutBit = kDummy - 1
};
+ // make sure we haven't exceeded the number of bits in GrVertexLayout.
GR_STATIC_ASSERT(kHighVertexLayoutBit < (1 << 8*sizeof(GrVertexLayout)));
/**
@@ -619,19 +673,35 @@ public:
};
////////////////////////////////////////////////////////////////////////////
-
+ // Helpers for picking apart vertex layouts
+
/**
* Helper function to compute the size of a vertex from a vertex layout
* @return size of a single vertex.
*/
static size_t VertexSize(GrVertexLayout vertexLayout);
+
+ /**
+ * Helper function for determining the index of texture coordinates that
+ * is input for a texture stage. Note that a stage may instead use positions
+ * as texture coordinates, in which case the result of the function is
+ * indistinguishable from the case when the stage is disabled.
+ *
+ * @param stage the stage to query
+ * @param vertexLayout layout to query
+ *
+ * @return the texture coordinate index or -1 if the stage doesn't use
+ * separate (non-position) texture coordinates.
+ */
+ static int VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout);
/**
* Helper function to compute the offset of texture coordinates in a vertex
* @return offset of texture coordinates in vertex layout or -1 if the
- * layout has no texture coordinates.
+ * layout has no texture coordinates. Will be 0 if positions are
+ * used as texture coordinates for the stage.
*/
- static int VertexTexCoordOffset(GrVertexLayout vertexLayout);
+ static int VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout);
/**
* Helper function to compute the offset of the color in a vertex
@@ -641,27 +711,64 @@ public:
static int VertexColorOffset(GrVertexLayout vertexLayout);
/**
- * Helper function to compute vertex size and component offsets.
- * @param texCoordOffset after return it is the offset of texture coords
- * in vertex layout or -1 if the layout has no
- * texture coords.
- * @param colorOffset after return it is the offset of color in vertex
- * layout or -1 if the layout has no color.
- * @return size of a single vertex.
+ * Helper function to determine if vertex layout contains explicit texture
+ * coordinates of some index.
+ *
+ * @param coordIndex the tex coord index to query
+ * @param vertexLayout layout to query
+ *
+ * @return true if vertex specifies texture coordinates for the index,
+ * false otherwise.
*/
- static int VertexSizeAndOffsets(GrVertexLayout vertexLayout,
- int* texCoordOffset,
- int* colorOffset);
+ static bool VertexUsesTexCoordIdx(int coordIndex,
+ GrVertexLayout vertexLayout);
+
/**
* Helper function to determine if vertex layout contains either explicit or
- * implicit texture coordinates.
+ * implicit texture coordinates for a stage.
*
- * @return true if vertex specifies texture coordinates, false otherwise.
+ * @param stage the stage to query
+ * @param vertexLayout layout to query
+ *
+ * @return true if vertex specifies texture coordinates for the stage,
+ * false otherwise.
*/
- static bool VertexHasTexCoords(GrVertexLayout vertexLayout);
+ static bool VertexUsesStage(int stage, GrVertexLayout vertexLayout);
+ /**
+ * Helper function to compute the size of each vertex and the offsets of
+ * texture coordinates and color. Determines tex coord offsets by tex coord
+ * index rather than by stage. (Each stage can be mapped to any t.c. index
+ * by StageTexCoordVertexLayoutBit.)
+ *
+ * @param vertexLayout the layout to query
+ * @param texCoordOffsetsByIdx after return it is the offset of each
+ * tex coord index in the vertex or -1 if
+ * index isn't used.
+ * @return size of a single vertex
+ */
+ static int VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
+ int texCoordOffsetsByIdx[kMaxTexCoords],
+ int *colorOffset);
+
+ /**
+ * Helper function to compute the size of each vertex and the offsets of
+ * texture coordinates and color. Determines tex coord offsets by stage
+ * rather than by index. (Each stage can be mapped to any t.c. index
+ * by StageTexCoordVertexLayoutBit.) If a stage uses positions for
+ * tex coords then that stage's offset will be 0 (positions are always at 0).
+ *
+ * @param vertexLayout the layout to query
+ * @param texCoordOffsetsByStage after return it is the offset of each
+ * tex coord index in the vertex or -1 if
+ * index isn't used.
+ * @return size of a single vertex
+ */
+ static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
+ int texCoordOffsetsByStage[kNumStages],
+ int *colorOffset);
protected:
-
+
// Helpers for GrDrawTarget subclasses that won't have private access to
// SavedDrawState but need to peek at the state values.
static DrState& accessSavedDrawState(SavedDrawState& sds)
@@ -708,9 +815,6 @@ protected:
DrState fCurrDrawState;
- // set texture or modelview matrix
- void loadMatrix(const GrMatrix&, MatrixMode);
-
// not meant for outside usage. Could cause problems if calls between
// the save and restore mess with reserved geometry state.
class AutoGeometrySrcRestore {
@@ -731,6 +835,8 @@ protected:
AutoGeometrySrcRestore& operator =(AutoGeometrySrcRestore&);
};
+private:
+ void VertexLayoutUnitTest();
};
#endif
diff --git a/gpu/include/GrGLConfig.h b/gpu/include/GrGLConfig.h
index b183892472..2bc535d709 100644
--- a/gpu/include/GrGLConfig.h
+++ b/gpu/include/GrGLConfig.h
@@ -90,6 +90,8 @@
#endif
#endif
+#define GR_SUPPORT_GLES (GR_SUPPORT_GLES1 || GR_SUPPORT_GLES2)
+
#ifndef GR_SUPPORT_GLDESKTOP
#if defined(GR_INCLUDE_GLDESKTOP)
#define GR_SUPPORT_GLDESKTOP 1
@@ -155,20 +157,6 @@
//
// End including GL headers
-#if GL_VERSION_1_1
- #define GR_GL_DESKTOP 1
- #define GR_GL_ES 0
-#else
- #ifndef GL_ES_VERSION_2_0
- GR_STATIC_ASSERT(GL_VERSION_ES_CM_1_0 ||
- GL_VERSION_ES_CL_1_0 ||
- GL_VERSION_ES_CM_1_1 ||
- GL_VERSION_ES_CL_1_1);
- #endif
- #define GR_GL_DESKTOP 0
- #define GR_GL_ES 1
-#endif
-
#if GR_SCALAR_IS_FIXED
#define GrGLType GL_FIXED
#elif GR_SCALAR_IS_FLOAT
diff --git a/gpu/include/GrSamplerState.h b/gpu/include/GrSamplerState.h
index 06c2346d93..5fb10b9441 100644
--- a/gpu/include/GrSamplerState.h
+++ b/gpu/include/GrSamplerState.h
@@ -24,7 +24,6 @@ class GrSamplerState {
public:
enum SampleMode {
kNormal_SampleMode, //!< sample color directly
- kAlphaMod_SampleMode, //!< modulate with alpha only
kRadial_SampleMode, //!< treat as radial gradient
kRadial2_SampleMode, //!< treat as 2-point radial gradient
kSweep_SampleMode, //!< treat as sweep gradient
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 942afa3021..e5e378f4de 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -138,9 +138,9 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
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 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
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 @@ static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,
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 @@ void GrContext::drawPath(GrPathIter* path, PathFills fill,
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 @@ void GrContext::writePixels(int left, int top, int width, int height,
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 @@ GrIndexBuffer* GrContext::createIndexBuffer(uint32_t size, bool dynamic) {
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 @@ void GrContext::setDefaultRenderTargetSize(uint32_t width, uint32_t height) {
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 82f94a35df..7ea9ff2ca7 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);
+// mask of all tex coord indices for one stage
+static int stage_tex_coord_mask(int stage) {
+ return stage_mask_recur<0>(stage);
+}
+
+// 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;
}
- if (vertexLayout & kColor_VertexLayoutBit) {
- size += sizeof(GrColor);
+ }
+ 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;
}
- return size;
}
+ if (vertexLayout & kColor_VertexLayoutBit) {
+ size += sizeof(GrColor);
+ }
+ return size;
}
-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) {
+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);
+ }
+ if (kColor_VertexLayoutBit & vertexLayout) {
+ *colorOffset = size;
+ size += sizeof(GrColor);
+ } else {
+ *colorOffset = -1;
+ }
+ return size;
+}
+
+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 {
- *colorOffset = -1;
+ texCoordOffsetsByStage[s] = -1;
}
- return size;
}
+ 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;
}
-bool GrDrawTarget::VertexHasTexCoords(GrVertexLayout vertexLayout) {
- return !!(vertexLayout & (kSeparateTexCoord_VertexLayoutBit |
- kPositionAsTexCoord_VertexLayoutBit |
- kTextFormat_VertexLayoutBit));
+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 @@ const GrClip& GrDrawTarget::getClip() const {
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 @@ GrRenderTarget* GrDrawTarget::currentRenderTarget() const {
return fCurrDrawState.fRenderTarget;
}
+void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
+ fCurrDrawState.fViewMatrix = m;
+}
+
void GrDrawTarget::concatViewMatrix(const GrMatrix& matrix) {
- GrMatrix mv;
- mv.setConcat(fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode], matrix);
- this->loadMatrix(mv, kModelView_MatrixMode);
+ 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 @@ bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
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 @@ void GrDrawTarget::disableState(uint32_t bits) {
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 4e9d9223de..9460086fe2 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -144,6 +144,9 @@ void GrGLTexture::uploadTextureData(uint32_t x,
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 @@ void GrGLTexture::uploadTextureData(uint32_t x,
// 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 f9ee217426..fe6d0c37f7 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -92,20 +92,32 @@ bool GrGpu::canDisableBlend() const {
}
// 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 4d539d217b..6de6db38c1 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 @@ void gl_version(int* major, int* minor) {
*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 @@ void gl_version(int* major, int* minor) {
///////////////////////////////////////////////////////////////////////////////
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 @@ bool fbo_test(GrGLExts exts, int w, int h) {
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 @@ GrGpuGL::GrGpuGL() {
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 @@ GrGpuGL::GrGpuGL() {
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 @@ GrGpuGL::GrGpuGL() {
}
}
-#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 @@ GrGpuGL::GrGpuGL() {
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 @@ GrGpuGL::GrGpuGL() {
}
-#if GR_GL_DESKTOP
+#if GR_SUPPORT_GLDESKTOP
fRGBA8Renderbuffer = true;
#else
fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
@@ -271,7 +300,7 @@ GrGpuGL::GrGpuGL() {
}
-#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 @@ GrGpuGL::GrGpuGL() {
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 @@ void GrGpuGL::resetContextHelper() {
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 @@ void GrGpuGL::resetContextHelper() {
// 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 @@ void GrGpuGL::resetContextHelper() {
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 @@ void GrGpuGL::resetContext() {
// 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 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
++fStats.fTextureCreateCnt;
#endif
+ setSpareTextureUnit();
+
static const GrGLTexture::TexParams DEFAULT_PARAMS = {
GL_NEAREST,
GL_CLAMP_TO_EDGE,
@@ -585,7 +618,7 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
* 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 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
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 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
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 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
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 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
}
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 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
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::flushStencil() {
void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
- bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
-
- // bind texture and set sampler state
- if (usingTexture) {
- GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTexture;
-
- 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) {
-
- 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;
+ 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.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 (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()];
+
+ 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 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
}
}
-#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 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
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::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
}
}
-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::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
}
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 @@ bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
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 @@ bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
} 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 @@ extern void GrGLInitExtensions(GrGLExts* exts) {
#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 @@ extern void GrGLInitExtensions(GrGLExts* exts) {
// 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 @@ extern void GrGLInitExtensions(GrGLExts* exts) {
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 728a5d343b..8c2cd80997 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -87,6 +87,8 @@ protected:
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 @@ protected:
// last scissor / viewport scissor state seen by the GL.
BoundsState fHWBounds;
-private:
GrGLExts fExts;
+private:
GrGLRenderTarget* fDefaultRenderTarget;
void resetContextHelper();
@@ -122,10 +124,11 @@ private:
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 @@ private:
// ES requires an extension to support RGBA8 in RenderBufferStorage
bool fRGBA8Renderbuffer;
-
+
+ int fActiveTextureUnitIdx;
+
typedef GrGpu INHERITED;
};
@@ -168,7 +173,7 @@ void gl_version(int* major, int* minor);
* 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 77bec40979..d142b66a0b 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -72,25 +72,27 @@ void GrGpuGLFixed::resetContext() {
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));
-
- 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));
+ 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+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 @@ void GrGpuGLFixed::flushProjectionMatrix() {
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 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
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 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
}
// 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;
+ }
+
+ 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();
}
- GR_GL(MatrixMode(gMatrixMode2Enum[kTexture_MatrixMode]));
- GR_GL(LoadMatrixf(glm.fMat));
- fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] =
- fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
- 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 @@ void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
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 @@ void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
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 @@ void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
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));
- }
- if (posChange || newTexCoordOffset != oldTexCoordOffset) {
- GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
+ 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));
}
- } 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 f3a033234c..85db830e33 100644
--- a/gpu/src/GrGpuGLFixed.h
+++ b/gpu/src/GrGpuGLFixed.h
@@ -40,15 +40,15 @@ private:
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 b9db90c657..2ace2ad240 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -512,8 +512,9 @@ GrGpuGLShaders::GrGpuGLShaders() {
&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 @@ void GrGpuGLShaders::flushMatrix(GLint location) {
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 @@ void GrGpuGLShaders::flushTexMatrix(GLint location,
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 @@ void GrGpuGLShaders::flushProgram(PrimitiveType type) {
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 @@ HAVE_NEXT_PROGRAM:
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 @@ bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) {
}
#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 @@ void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
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 @@ void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
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 cba387bcce..e5a5665868 100644
--- a/gpu/src/GrGpuGLShaders.h
+++ b/gpu/src/GrGpuGLShaders.h
@@ -134,7 +134,8 @@ private:
// 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 c7b3cb982b..92df809b3a 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::StageUniLocations {
struct GrGpuGLShaders2::UniLocations {
GLint fViewMatrixUni;
- StageUniLocations fStages[NUM_STAGES];
+ StageUniLocations fStages[kNumStages];
};
// Records per-program information
@@ -82,11 +81,11 @@ struct GrGpuGLShaders2::Program {
// 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 @@ struct GrGpuGLShaders2::ProgramDesc {
// 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 @@ static uint32_t ror(uint32_t x) {
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 @@ typedef GrSStringBuilder<16> GrTokenString;
#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 @@ static void radial2_varying_name(int stage, GrStringBuilder* s) {
#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 @@ void GrGpuGLShaders2::ProgramUnitTest() {
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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
}
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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
} 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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
// 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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
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 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
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 @@ void GrGpuGLShaders2::getProgramDesc(PrimitiveType primType, ProgramDesc* desc)
// 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;
+ }
+ #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;
}
- } else {
- stage.fOptFlags = 0;
- stage.fCoordMapping = (StageDesc::CoordMapping)0;
- stage.fModulation = (StageDesc::Modulation)0;
}
}
@@ -1088,7 +1111,9 @@ void GrGpuGLShaders2::resetContextHelper() {
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 @@ void GrGpuGLShaders2::flushViewMatrix() {
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 @@ void GrGpuGLShaders2::flushViewMatrix() {
#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 @@ void GrGpuGLShaders2::flushTextureMatrix() {
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 @@ void GrGpuGLShaders2::flushTextureMatrix() {
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 @@ void GrGpuGLShaders2::flushRadial2() {
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 @@ bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) {
// 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 @@ bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) {
}
#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 @@ bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) {
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) {
-
- int newColorOffset, newTexCoordOffset;
-
- GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
- &newTexCoordOffset,
- &newColorOffset);
- int oldColorOffset, oldTexCoordOffset;
- GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
- &oldTexCoordOffset,
- &oldColorOffset);
+ uint32_t startIndex,
+ uint32_t vertexCount,
+ uint32_t indexCount) {
+
+ int newColorOffset;
+ int newTexCoordOffsets[kMaxTexCoords];
+
+ 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 @@ void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
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 @@ void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
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 @@ void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
fHWGeometryState.fPositionPtr = posPtr;
}
- if (newTexCoordOffset > 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
- if (oldTexCoordOffset <= 0) {
- GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION));
- }
- if (posChange || newTexCoordOffset != oldTexCoordOffset) {
- GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION, 2, scalarType,
- texCoordNorm, newStride, texCoordPtr));
+ 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)));
}
- } 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 c484544293..bba63f6f12 100644
--- a/gpu/src/GrGpuGLShaders2.h
+++ b/gpu/src/GrGpuGLShaders2.h
@@ -37,17 +37,17 @@ protected:
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 952ba836ae..494f227383 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -156,9 +156,11 @@ void GrInOrderDrawBuffer::reset() {
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 @@ bool GrInOrderDrawBuffer::grabState() {
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 02648567ff..0a777d6cd8 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 @@ void GrTextContext::flushGlyphs() {
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,