diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-01-13 19:52:45 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-01-13 19:52:45 +0000 |
commit | 8531c1cea2a9cf7702ef314ccd0a6cd1dd33c76c (patch) | |
tree | c760b89996fbc0c43eee1e100dcfee1a66ec4418 /gpu | |
parent | a76de3d1a92134c3e95ad7fce99234f92fa48268 (diff) |
Towards issue #106
Adds notion of texture multiple stages but currently just uses 1.
git-svn-id: http://skia.googlecode.com/svn/trunk@694 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/include/GrContext.h | 6 | ||||
-rw-r--r-- | gpu/include/GrDrawTarget.h | 232 | ||||
-rw-r--r-- | gpu/include/GrGLConfig.h | 16 | ||||
-rw-r--r-- | gpu/include/GrSamplerState.h | 1 | ||||
-rw-r--r-- | gpu/src/GrContext.cpp | 30 | ||||
-rw-r--r-- | gpu/src/GrDrawTarget.cpp | 322 | ||||
-rw-r--r-- | gpu/src/GrGLTexture.cpp | 4 | ||||
-rw-r--r-- | gpu/src/GrGpu.cpp | 28 | ||||
-rw-r--r-- | gpu/src/GrGpuGL.cpp | 287 | ||||
-rw-r--r-- | gpu/src/GrGpuGL.h | 13 | ||||
-rw-r--r-- | gpu/src/GrGpuGLFixed.cpp | 211 | ||||
-rw-r--r-- | gpu/src/GrGpuGLFixed.h | 10 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders.cpp | 166 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders.h | 3 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders2.cpp | 412 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders2.h | 6 | ||||
-rw-r--r-- | gpu/src/GrInOrderDrawBuffer.cpp | 14 | ||||
-rw-r--r-- | gpu/src/GrTextContext.cpp | 11 |
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, |