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
This commit is contained in:
bsalomon@google.com 2011-01-13 19:52:45 +00:00
parent a76de3d1a9
commit 8531c1cea2
20 changed files with 1111 additions and 700 deletions

View File

@ -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);

View File

@ -33,6 +33,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.
*/
@ -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 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.
*
* kSeparateTexCoord_VertexLayoutBit is incompatible with
* kPositionAsTexCoord_VertexLayoutBit. kTextFormat_VertexLayoutBit is
* incompatible with any other flags.
* If no texture coordinates are specified for a stage then the stage is
* disabled.
*
* 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.
* Only one type of texture coord can be specified per stage. For
* example StageTexCoordVertexLayoutBit(0, 2) and
* StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
*
* The order is always positions, texture coords, colors.
* 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
*
* @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,6 +673,7 @@ public:
};
////////////////////////////////////////////////////////////////////////////
// Helpers for picking apart vertex layouts
/**
* Helper function to compute the size of a vertex from a vertex layout
@ -626,12 +681,27 @@ public:
*/
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,25 +711,62 @@ 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
@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -18,75 +18,137 @@
#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; }
// 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;
}
}
return true;
}
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);
GrAssert(check_layout(vertexLayout));
size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
sizeof(GrGpuTextVertex) :
sizeof(GrPoint);
size_t size = vecSize; // position
for (int t = 0; t < kMaxTexCoords; ++t) {
if (tex_coord_idx_mask(t) & vertexLayout) {
size += vecSize;
}
}
if (vertexLayout & kColor_VertexLayoutBit) {
size += sizeof(GrColor);
}
return size;
}
}
int GrDrawTarget::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 GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
int texCoordOffsetsByIdx[kMaxTexCoords],
int* colorOffset) {
VERTEX_LAYOUT_ASSERTS
GrAssert(check_layout(vertexLayout));
GrAssert(NULL != texCoordOffset);
GrAssert(NULL != texCoordOffsetsByIdx);
GrAssert(NULL != colorOffset);
if ((vertexLayout & kTextFormat_VertexLayoutBit)) {
*texCoordOffset = sizeof(GrGpuTextVertex);
*colorOffset = 0;
return 2 * sizeof(GrGpuTextVertex);
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 {
size_t size = sizeof(GrPoint);
if (vertexLayout & kSeparateTexCoord_VertexLayoutBit) {
*texCoordOffset = sizeof(GrPoint);
size += sizeof(GrPoint);
} else if (vertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
*texCoordOffset = 0;
} else {
*texCoordOffset = -1;
texCoordOffsetsByIdx[t] = -1;
}
if (vertexLayout & kColor_VertexLayoutBit) {
}
if (kColor_VertexLayoutBit & vertexLayout) {
*colorOffset = size;
size += sizeof(GrColor);
} else {
@ -94,17 +156,127 @@ int GrDrawTarget::VertexSizeAndOffsets(GrVertexLayout vertexLayout,
}
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 {
texCoordOffsetsByStage[s] = -1;
}
}
return size;
}
bool GrDrawTarget::VertexHasTexCoords(GrVertexLayout vertexLayout) {
return !!(vertexLayout & (kSeparateTexCoord_VertexLayoutBit |
kPositionAsTexCoord_VertexLayoutBit |
kTextFormat_VertexLayoutBit));
bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
GrAssert(stage < kNumStages);
GrAssert(check_layout(vertexLayout));
return !!(stage_mask(stage) & vertexLayout);
}
bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
GrVertexLayout vertexLayout) {
GrAssert(coordIndex < kMaxTexCoords);
GrAssert(check_layout(vertexLayout));
return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
}
int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) {
GrAssert(stage < kNumStages);
GrAssert(check_layout(vertexLayout));
int bit = vertexLayout & stage_tex_coord_mask(stage);
if (bit) {
// figure out which set of texture coordates is used
// bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
// and start at bit 0.
GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
return (32 - Gr_clz(bit) - 1) / kNumStages;
}
return -1;
}
void GrDrawTarget::VertexLayoutUnitTest() {
// not necessarily exhaustive
static bool run;
if (!run) {
run = true;
for (int s = 0; s < kNumStages; ++s) {
GrAssert(!VertexUsesStage(s, 0));
GrAssert(-1 == VertexStageCoordOffset(s, 0));
GrVertexLayout stageMask = 0;
for (int t = 0; t < kMaxTexCoords; ++t) {
stageMask |= StageTexCoordVertexLayoutBit(s,t);
}
GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
GrAssert(stage_tex_coord_mask(s) == stageMask);
stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
GrAssert(stage_mask(s) == stageMask);
GrAssert(!check_layout(stageMask));
}
for (int t = 0; t < kMaxTexCoords; ++t) {
GrVertexLayout tcMask = 0;
GrAssert(!VertexUsesTexCoordIdx(t, 0));
for (int s = 0; s < kNumStages; ++s) {
tcMask |= StageTexCoordVertexLayoutBit(s,t);
GrAssert(VertexUsesStage(s, tcMask));
GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
GrAssert(VertexUsesTexCoordIdx(t, tcMask));
GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
GrAssert(t == VertexTexCoordsForStage(s, tcMask));
for (int s2 = s + 1; s2 < kNumStages; ++s2) {
GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
GrAssert(!VertexUsesStage(s2, tcMask));
GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
GrAssert(VertexUsesStage(s2, posAsTex));
GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
}
GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
}
GrAssert(tex_coord_idx_mask(t) == tcMask);
GrAssert(check_layout(tcMask));
int stageOffsets[kNumStages];
int colorOffset;
int size;
size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset);
GrAssert(2*sizeof(GrPoint) == size);
GrAssert(-1 == colorOffset);
for (int s = 0; s < kNumStages; ++s) {
GrAssert(VertexUsesStage(s, tcMask));
GrAssert(sizeof(GrPoint) == stageOffsets[s]);
GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
GrDrawTarget::GrDrawTarget() {
#if GR_DEBUG
VertexLayoutUnitTest();
#endif
fReservedGeometry.fLocked = false;
#if GR_DEBUG
fReservedGeometry.fVertexCount = ~0;
@ -123,12 +295,14 @@ 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::concatViewMatrix(const GrMatrix& matrix) {
GrMatrix mv;
mv.setConcat(fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode], matrix);
this->loadMatrix(mv, kModelView_MatrixMode);
void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
fCurrDrawState.fViewMatrix = m;
}
void GrDrawTarget::concatViewMatrix(const GrMatrix& matrix) {
fCurrDrawState.fViewMatrix.preConcat(matrix);
}
// Can't this just return a const&
void GrDrawTarget::getViewMatrix(GrMatrix* matrix) const {
*matrix = fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
*matrix = fCurrDrawState.fViewMatrix;
}
bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
// Can we cache this somewhere?
// Mike: Can we cache this somewhere?
// Brian: Sure, do we use it often?
GrMatrix inverse;
if (fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode].invert(&inverse)) {
if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
if (matrix) {
*matrix = inverse;
}
@ -162,8 +340,14 @@ 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;
}

View File

@ -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));

View File

@ -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;
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -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;
}
@ -156,6 +172,19 @@ GrGpuGL::GrGpuGL() {
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,38 +1454,44 @@ void GrGpuGL::flushStencil() {
void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
for (int s = 0; s < kNumStages; ++s) {
bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
// bind texture and set sampler state
if (usingTexture) {
GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTexture;
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.
// if we created a rt/tex and rendered to it without using a
// texture and now we're texuring from the rt it will still be
// the last bound texture, but it needs resolving. So keep this
// out of the "last != next" check.
resolveTextureRenderTarget(nextTexture);
if (fHWDrawState.fTexture != nextTexture) {
if (fHWDrawState.fTextures[s] != nextTexture) {
setTextureUnit(s);
GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
#if GR_COLLECT_STATS
++fStats.fTextureChngCnt;
#endif
//GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
fHWDrawState.fTexture = nextTexture;
fHWDrawState.fTextures[s] = nextTexture;
}
const GrGLTexture::TexParams& oldTexParams = nextTexture->getTexParams();
const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
const GrGLTexture::TexParams& oldTexParams =
nextTexture->getTexParams();
GrGLTexture::TexParams newTexParams;
newTexParams.fFilter = fCurrDrawState.fSamplerState.isFilter() ?
GL_LINEAR :
newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
GL_NEAREST;
newTexParams.fWrapS = GrGLTexture::gWrapMode2GLWrap[fCurrDrawState.fSamplerState.getWrapX()];
newTexParams.fWrapT = GrGLTexture::gWrapMode2GLWrap[fCurrDrawState.fSamplerState.getWrapY()];
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));
@ -1468,11 +1500,13 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
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));
@ -1480,13 +1514,15 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
nextTexture->setTexParams(newTexParams);
} else {
GrAssert(!"Rendering with texture vert flag set but no texture");
if (NULL != fHWDrawState.fTexture) {
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.fTexture = NULL;
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 ||
@ -1550,11 +1586,16 @@ void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
}
}
#if GR_DEBUG
// check for circular rendering
GrAssert(!usingTexture ||
for (int s = 0; s < kNumStages; ++s) {
GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
NULL == fCurrDrawState.fRenderTarget ||
NULL == fCurrDrawState.fTexture ||
fCurrDrawState.fTexture->asRenderTarget() != fCurrDrawState.fRenderTarget);
NULL == fCurrDrawState.fTextures[s] ||
fCurrDrawState.fTextures[s]->asRenderTarget() !=
fCurrDrawState.fRenderTarget);
}
#endif
flushStencil();
@ -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,12 +1649,14 @@ 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.fTexture == texture) {
if (fHWDrawState.fTextures[s] == texture) {
// deleting bound texture does implied bind to 0
fHWDrawState.fTexture = NULL;
fHWDrawState.fTextures[s] = NULL;
}
}
}
@ -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,7 +1739,7 @@ bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
} else {
return false;
}
#if GR_GL_ES // ES2 supports 565. ES1 supports it with FBO extension
#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;
@ -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
}

View File

@ -88,6 +88,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
// line smoothing
@ -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,11 +124,12 @@ 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();
void resolveTextureRenderTarget(GrGLTexture* texture);
@ -158,6 +161,8 @@ 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));
}

View File

@ -72,25 +72,27 @@ void GrGpuGLFixed::resetContext() {
void GrGpuGLFixed::resetContextHelper() {
GR_GL(Disable(GL_TEXTURE_2D));
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));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0+s));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_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_PRIMARY_COLOR));
GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS));
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
// 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 = (TextureEnvRGBOperands) -1;
GR_GL(ClientActiveTexture(GL_TEXTURE0));
fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1;
}
fHWGeometryState.fVertexLayout = 0;
fHWGeometryState.fPositionPtr = (void*) ~0;
@ -127,12 +129,16 @@ void GrGpuGLFixed::flushProjectionMatrix() {
bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
bool usingTextures[kNumStages];
if (usingTexture && fCurrDrawState.fSamplerState.isGradient()) {
for (int s = 0; s < kNumStages; ++s) {
usingTextures[s] = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
if (usingTextures[s] && fCurrDrawState.fSamplerStates[s].isGradient()) {
unimpl("Fixed pipe doesn't support radial/sweep gradients");
return false;
}
}
flushGLStateCommon(type);
@ -141,14 +147,17 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
fRenderTargetChanged = false;
}
bool wasUsingTexture = VertexHasTexCoords(fHWGeometryState.fVertexLayout);
if (usingTexture != wasUsingTexture) {
if (usingTexture) {
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 &
@ -156,8 +165,6 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
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,41 +188,45 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
}
// set texture environment, decide whether we are modulating by RGB or A.
if (usingTexture) {
GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTexture;
for (int s = 0; s < kNumStages; ++s) {
if (usingTextures[s]) {
GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s];
if (NULL != texture) {
TextureEnvRGBOperands nextRGBOperand0 =
(texture->uploadFormat() == GL_ALPHA) ?
(texture->config() == GrTexture::kAlpha_8_PixelConfig) ?
kAlpha_TextureEnvRGBOperand :
kColor_TextureEnvRGBOperand;
if (fHWRGBOperand0 != nextRGBOperand0) {
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 = nextRGBOperand0;
fHWRGBOperand0[s] = nextRGBOperand0;
}
if (fHWTextureOrientation != texture->orientation() ||
fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] !=
fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]) {
fHWDrawState.fTextureMatrices[s] !=
fCurrDrawState.fTextureMatrices[s]) {
GrGpuMatrix glm;
if (GrGLTexture::kBottomUp_Orientation == texture->orientation()) {
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]);
m.preConcat(fCurrDrawState.fTextureMatrices[s]);
glm.set(m);
} else {
glm.set(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
glm.set(fCurrDrawState.fTextureMatrices[s]);
}
GR_GL(MatrixMode(gMatrixMode2Enum[kTexture_MatrixMode]));
setTextureUnit(s);
GR_GL(MatrixMode(GL_TEXTURE));
GR_GL(LoadMatrixf(glm.fMat));
fHWDrawState.fMatrixModeCache[kTexture_MatrixMode] =
fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
fHWDrawState.fTextureMatrices[s] =
fCurrDrawState.fTextureMatrices[s];
fHWTextureOrientation = texture->orientation();
}
} else {
@ -223,15 +234,15 @@ bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
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,14 +252,16 @@ 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,
GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
newTexCoordOffsets,
&newColorOffset);
int oldColorOffset, oldTexCoordOffset;
GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
&oldTexCoordOffset,
int oldColorOffset;
int oldTexCoordOffsets[kNumStages];
GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
oldTexCoordOffsets,
&oldColorOffset);
const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
@ -310,18 +323,24 @@ 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) {
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 || newTexCoordOffset != oldTexCoordOffset) {
if (posChange || newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
}
} else if (oldTexCoordOffset >= 0) {
} else if (oldTexCoordOffsets[s] >= 0) {
GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
}
}
if (newColorOffset > 0) {
GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;

View File

@ -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();

View File

@ -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,51 +645,53 @@ 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() ==
case GrSamplerState::kNormal_SampleMode:
if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
GrAssert(((GrGLTexture*)texture)->orientation() ==
GrGLTexture::kTopDown_Orientation);
(((GrGLTexture*)fCurrDrawState.fTexture)->uploadFormat() == GL_ALPHA);
GrAssert(!posAsTex);
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) {
} else {
bool persp = fCurrDrawState.fTextureMatrices[0].hasPerspective();
if (posAsTex) {
nextProgram = persp ? kTextureVertCoordsProj_Program :
kTextureVertCoords_Program;
} else {
@ -711,7 +714,8 @@ void GrGpuGLShaders::flushProgram(PrimitiveType type) {
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,14 +842,16 @@ 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,
GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
newTexCoordOffsets,
&newColorOffset);
int oldColorOffset, oldTexCoordOffset;
GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
&oldTexCoordOffset,
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));
}

View File

@ -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;

View File

@ -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,13 +980,10 @@ 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;
@ -970,52 +997,48 @@ void GrGpuGLShaders2::getProgramDesc(PrimitiveType primType, ProgramDesc* desc)
}
#endif
StageDesc& stage = desc->fStages[0];
if (stage.fEnabled) {
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
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.fMatrixModeCache[kTexture_MatrixMode].isIdentity() &&
if (fCurrDrawState.fTextureMatrices[s].isIdentity() &&
GrGLTexture::kTopDown_Orientation == texture->orientation()) {
stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
} else if (!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective()) {
} else if (!fCurrDrawState.fTextureMatrices[s].hasPerspective()) {
stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
} else {
stage.fOptFlags = 0;
}
switch (fCurrDrawState.fSamplerState.getSampleMode()) {
switch (fCurrDrawState.fSamplerStates[s].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 (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;
}
}
}
GLuint GrGpuGLShaders2::CompileShader(GLenum type,
int stringCnt,
@ -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,34 +1276,35 @@ 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;
for (int s = 0; s < kNumStages; ++s) {
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
if (NULL != texture) {
if (-1 != fProgram->fUniLocations.fStages[0].fTextureMatrixUni &&
(currTextureMatrix !=
fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode] ||
if (-1 != fProgram->fUniLocations.fStages[s].fTextureMatrixUni &&
(currTextureMatrix != fCurrDrawState.fTextureMatrices[s] ||
orientation != texture->orientation())) {
flushTextureMatrix();
currTextureMatrix = fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
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;
@ -1288,14 +1315,16 @@ void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
uint32_t vertexCount,
uint32_t indexCount) {
int newColorOffset, newTexCoordOffset;
int newColorOffset;
int newTexCoordOffsets[kMaxTexCoords];
GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
&newTexCoordOffset,
GLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
newTexCoordOffsets,
&newColorOffset);
int oldColorOffset, oldTexCoordOffset;
GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
&oldTexCoordOffset,
int oldColorOffset;
int oldTexCoordOffsets[kMaxTexCoords];
GLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
oldTexCoordOffsets,
&oldColorOffset);
const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
@ -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));
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 || newTexCoordOffset != oldTexCoordOffset) {
GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION, 2, scalarType,
if (posChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
texCoordNorm, newStride, texCoordPtr));
}
} else if (oldTexCoordOffset > 0) {
GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION));
} else if (oldTexCoordOffsets[t] > 0) {
GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
}
}
if (newColorOffset > 0) {

View File

@ -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);

View File

@ -156,11 +156,13 @@ 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;
for (int s = 0; s < kNumStages; ++s) {
GrTexture* tex = accessSavedDrawState(fStates[i]).fTextures[s];
if (NULL != tex) {
tex->unref();
}
}
}
fDraws.reset();
fStates.reset();
if (NULL == fBufferVertices) {
@ -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());
}

View File

@ -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,

View File

@ -82,7 +82,7 @@ GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
if (texture) {
// return the native texture
fTex = NULL;
device->context()->setTexture(texture);
device->context()->setTexture(0, texture);
} else {
// look it up in our cache
fTex = device->lockCachedTexture(bitmap, sampler, &texture, false);
@ -333,7 +333,7 @@ void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
bool SkGpuDevice::bindDeviceAsTexture(SkPoint* max) {
if (NULL != fTexture) {
fContext->setTexture(fTexture);
fContext->setTexture(0, fTexture);
if (NULL != max) {
max->set(SkFixedToScalar((width() << 16) /
fTexture->allocWidth()),
@ -431,7 +431,7 @@ void SkGpuDevice::AutoPaintShader::init(SkGpuDevice* device,
}
// the lock has already called setTexture for us
ctx->setSamplerState(samplerState);
ctx->setSamplerState(0, samplerState);
// since our texture coords will be in local space, we wack the texture
// matrix to map them back into 0...1 before we load it
@ -456,7 +456,7 @@ void SkGpuDevice::AutoPaintShader::init(SkGpuDevice* device,
}
GrMatrix grmat;
SkGr::SkMatrix2GrMatrix(matrix, &grmat);
ctx->setTextureMatrix(grmat);
ctx->setTextureMatrix(0, grmat);
// since we're going to use a shader/texture, we don't want the color,
// just its alpha
@ -507,7 +507,7 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
}
GrVertexLayout layout = shader.useTex() ?
GrDrawTarget::kPositionAsTexCoord_VertexLayoutBit :
GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
0;
#if SK_SCALAR_IS_GR_SCALAR
fContext->setVertexSourceToArray(pts, layout);
@ -700,7 +700,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
GrSamplerState sampler(paint.isFilterBitmap()); // defaults to clamp
// the lock has already called setTexture for us
fContext->setSamplerState(sampler);
fContext->setSamplerState(0, sampler);
GrTexture* texture;
SkAutoCachedTexture act(this, bitmap, sampler, &texture);
@ -708,7 +708,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
return;
}
GrVertexLayout layout = GrDrawTarget::kSeparateTexCoord_VertexLayoutBit;
GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0, 0);
GrPoint* vertex;
if (!fContext->reserveAndLockGeometry(layout, 4,
@ -734,7 +734,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
texture->allocHeight());
vertex[1].setRectFan(left, top, right, bottom, 2*sizeof(GrPoint));
fContext->setTextureMatrix(GrMatrix::I());
fContext->setTextureMatrix(0, GrMatrix::I());
// now draw the mesh
sk_gr_set_paint(fContext, paint, true);
fContext->drawNonIndexed(GrGpu::kTriangleFan_PrimitiveType, 0, 4);
@ -746,11 +746,11 @@ static void gl_drawSprite(GrContext* ctx,
const SkPaint& paint) {
GrAutoViewMatrix avm(ctx, GrMatrix::I());
ctx->setSamplerState(GrSamplerState::ClampNoFilter());
ctx->setTextureMatrix(GrMatrix::I());
ctx->setSamplerState(0, GrSamplerState::ClampNoFilter());
ctx->setTextureMatrix(0, GrMatrix::I());
GrPoint* vertex;
GrVertexLayout layout = GrGpu::kSeparateTexCoord_VertexLayoutBit;
GrVertexLayout layout = GrGpu::StageTexCoordVertexLayoutBit(0, 0);
if (!ctx->reserveAndLockGeometry(layout, 4, 0,
GrTCast<void**>(&vertex), NULL)) {
return;
@ -837,7 +837,7 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
bool releaseVerts = false;
GrVertexLayout layout = 0;
if (useTexture) {
layout |= GrDrawTarget::kSeparateTexCoord_VertexLayoutBit;
layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0, 0);
}
if (NULL != colors) {
layout |= GrDrawTarget::kColor_VertexLayoutBit;
@ -855,16 +855,17 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
&verts, NULL)) {
return;
}
int texOffset, colorOffset;
uint32_t stride = GrDrawTarget::VertexSizeAndOffsets(layout,
&texOffset,
int texOffsets[GrDrawTarget::kNumStages];
int colorOffset;
uint32_t stride = GrDrawTarget::VertexSizeAndOffsetsByStage(layout,
texOffsets,
&colorOffset);
for (int i = 0; i < vertexCount; ++i) {
GrPoint* p = (GrPoint*)((intptr_t)verts + i * stride);
p->set(SkScalarToGrScalar(vertices[i].fX),
SkScalarToGrScalar(vertices[i].fY));
if (texOffset > 0) {
GrPoint* t = (GrPoint*)((intptr_t)p + texOffset);
if (texOffsets[0] > 0) {
GrPoint* t = (GrPoint*)((intptr_t)p + texOffsets[0]);
t->set(SkScalarToGrScalar(texs[i].fX),
SkScalarToGrScalar(texs[i].fY));
}
@ -1030,7 +1031,7 @@ SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
if (NULL != entry) {
newTexture = entry->texture();
ctx->setTexture(newTexture);
ctx->setTexture(0, newTexture);
if (texture) {
*texture = newTexture;
}

View File

@ -225,7 +225,6 @@
<ClCompile Include="..\..\gpu\src\GrMatrix.cpp" />
<ClCompile Include="..\..\gpu\src\GrMemory.cpp" />
<ClCompile Include="..\..\gpu\src\GrPath.cpp" />
<ClCompile Include="..\..\gpu\src\GrPrintf_printf.cpp" />
<ClCompile Include="..\..\gpu\src\GrRectanizer.cpp" />
<ClCompile Include="..\..\gpu\src\GrTextContext.cpp" />
<ClCompile Include="..\..\gpu\src\GrTextStrike.cpp" />
@ -407,6 +406,7 @@
<ClCompile Include="..\..\src\effects\SkRectShape.cpp" />
<ClCompile Include="..\..\src\effects\SkTableMaskFilter.cpp" />
<ClCompile Include="..\..\src\effects\SkTransparentShader.cpp" />
<ClCompile Include="..\..\src\gpu\GrPrintf_skia.cpp" />
<ClCompile Include="..\..\src\gpu\SkGpuCanvas.cpp" />
<ClCompile Include="..\..\src\gpu\SkGpuDevice.cpp" />
<ClCompile Include="..\..\src\gpu\SkGr.cpp" />