Separate out the texture matrix from the coord-system change matrix in GrSamplerState. This is a step towards moving texture matrix to GrCustomStage.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6721047
git-svn-id: http://skia.googlecode.com/svn/trunk@5973 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index be0f573..4fd6026 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -10,17 +10,20 @@
#ifndef GrContext_DEFINED
#define GrContext_DEFINED
-#include "GrConfig.h"
-#include "GrPaint.h"
+#include "GrColor.h"
#include "GrAARectRenderer.h"
#include "GrClipData.h"
+#include "GrMatrix.h"
+#include "GrPaint.h"
// not strictly needed but requires WK change in LayerTextureUpdaterCanvas to
// remove.
#include "GrRenderTarget.h"
-#include "SkClipStack.h"
+#include "GrRefCnt.h"
+#include "GrTexture.h"
class GrAutoScratchTexture;
class GrCacheKey;
+class GrCustomStage;
class GrDrawState;
class GrDrawTarget;
class GrFontCache;
@@ -33,6 +36,7 @@
class GrResourceEntry;
class GrResourceCache;
class GrStencilBuffer;
+class GrTextureParams;
class GrVertexBuffer;
class GrVertexBufferAllocPool;
class GrSoftwarePathRenderer;
@@ -711,7 +715,7 @@
this->restore();
if (NULL != paint) {
- if (!paint->preConcatSamplerMatricesWithInverse(context->getMatrix())) {
+ if (!paint->sourceCoordChangeByInverse(context->getMatrix())) {
return false;
}
}
@@ -749,7 +753,7 @@
*/
void preConcat(const GrMatrix& preConcat, GrPaint* paint = NULL) {
if (NULL != paint) {
- paint->preConcatSamplerMatrices(preConcat);
+ paint->sourceCoordChange(preConcat);
}
fContext->concatMatrix(preConcat);
}
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 3c29662..843a934 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -10,7 +10,6 @@
#ifndef GrPaint_DEFINED
#define GrPaint_DEFINED
-#include "GrTexture.h"
#include "GrColor.h"
#include "GrSamplerState.h"
@@ -189,47 +188,49 @@
bool hasStage() const { return this->hasColorStage() || this->hasCoverageStage(); }
/**
- * Preconcats the matrix of all enabled stages with the inverse of a matrix. If the matrix
- * inverse cannot be computed (and there is at least one enabled stage) then false is returned.
+ * Called when the source coord system is changing. preConcatInverse is the inverse of the
+ * transformation from the old coord system to the new coord system. Returns false if the matrix
+ * cannot be inverted.
*/
- bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
+ bool sourceCoordChangeByInverse(const GrMatrix& preConcatInverse) {
GrMatrix inv;
bool computed = false;
for (int i = 0; i < kMaxColorStages; ++i) {
if (this->isColorStageEnabled(i)) {
- if (!computed && !matrix.invert(&inv)) {
+ if (!computed && !preConcatInverse.invert(&inv)) {
return false;
} else {
computed = true;
}
- fColorSamplers[i].preConcatMatrix(inv);
+ fColorSamplers[i].preConcatCoordChange(inv);
}
}
for (int i = 0; i < kMaxCoverageStages; ++i) {
if (this->isCoverageStageEnabled(i)) {
- if (!computed && !matrix.invert(&inv)) {
+ if (!computed && !preConcatInverse.invert(&inv)) {
return false;
} else {
computed = true;
}
- fCoverageSamplers[i].preConcatMatrix(inv);
+ fCoverageSamplers[i].preConcatCoordChange(inv);
}
}
return true;
}
/**
- * Preconcats the matrix of all stages with a matrix.
+ * Called when the source coord system is changing. preConcat gives the transformation from the
+ * old coord system to the new coord system.
*/
- void preConcatSamplerMatrices(const GrMatrix& matrix) {
+ void sourceCoordChange(const GrMatrix& preConcat) {
for (int i = 0; i < kMaxColorStages; ++i) {
if (this->isColorStageEnabled(i)) {
- fColorSamplers[i].preConcatMatrix(matrix);
+ fColorSamplers[i].preConcatCoordChange(preConcat);
}
}
for (int i = 0; i < kMaxCoverageStages; ++i) {
if (this->isCoverageStageEnabled(i)) {
- fCoverageSamplers[i].preConcatMatrix(matrix);
+ fCoverageSamplers[i].preConcatCoordChange(preConcat);
}
}
}
diff --git a/include/gpu/GrSamplerState.h b/include/gpu/GrSamplerState.h
index da52e95..bb7e42a 100644
--- a/include/gpu/GrSamplerState.h
+++ b/include/gpu/GrSamplerState.h
@@ -22,79 +22,125 @@
GrSamplerState()
: fCustomStage (NULL) {
- memset(this, 0, sizeof(GrSamplerState));
- this->reset();
+ GR_DEBUGCODE(fSavedCoordChangeCnt = 0;)
}
~GrSamplerState() {
GrSafeUnref(fCustomStage);
+ GrAssert(0 == fSavedCoordChangeCnt);
}
- bool operator ==(const GrSamplerState& s) const {
- /* We must be bit-identical as far as the CustomStage;
- there may be multiple CustomStages that will produce
- the same shader code and so are equivalent.
- Can't take the address of fWrapX because it's :8 */
- int bitwiseRegion = (intptr_t) &fCustomStage - (intptr_t) this;
- GrAssert(sizeof(GrSamplerState) ==
- bitwiseRegion + sizeof(fCustomStage));
- return !memcmp(this, &s, bitwiseRegion) &&
- ((fCustomStage == s.fCustomStage) ||
- (fCustomStage && s.fCustomStage &&
- (fCustomStage->getFactory() ==
- s.fCustomStage->getFactory()) &&
- fCustomStage->isEqual(*s.fCustomStage)));
+ bool operator ==(const GrSamplerState& other) const {
+ // first handle cases where one or the other has no custom stage
+ if (NULL == fCustomStage) {
+ return NULL == other.fCustomStage;
+ } else if (NULL == other.fCustomStage) {
+ return false;
+ }
+
+ if (fCustomStage->getFactory() != other.fCustomStage->getFactory()) {
+ return false;
+ }
+
+ if (!fCustomStage->isEqual(*other.fCustomStage)) {
+ return false;
+ }
+
+ return fMatrix == other.fMatrix && fCoordChangeMatrix == other.fCoordChangeMatrix;
}
+
bool operator !=(const GrSamplerState& s) const { return !(*this == s); }
- GrSamplerState& operator =(const GrSamplerState& s) {
- fMatrix = s.fMatrix;
- GrSafeAssign(fCustomStage, s.fCustomStage);
+ GrSamplerState& operator =(const GrSamplerState& other) {
+ GrSafeAssign(fCustomStage, other.fCustomStage);
+ if (NULL != fCustomStage) {
+ fMatrix = other.fMatrix;
+ fCoordChangeMatrix = other.fCoordChangeMatrix;
+ }
return *this;
}
+ /**
+ * This is called when the coordinate system in which the geometry is specified will change.
+ *
+ * @param matrix The transformation from the old coord system to the new one.
+ */
+ void preConcatCoordChange(const GrMatrix& matrix) { fCoordChangeMatrix.preConcat(matrix); }
+
+ class SavedCoordChange {
+ private:
+ GrMatrix fCoordChangeMatrix;
+ GR_DEBUGCODE(mutable SkAutoTUnref<GrCustomStage> fCustomStage;)
+
+ friend class GrSamplerState;
+ };
+
+ /**
+ * This gets the current coordinate system change. It is the accumulation of
+ * preConcatCoordChange calls since the custom stage was installed. It is used when then caller
+ * wants to temporarily change the source geometry coord system, draw something, and then
+ * restore the previous coord system (e.g. temporarily draw in device coords).s
+ */
+ void saveCoordChange(SavedCoordChange* savedCoordChange) const {
+ savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
+ GrAssert(NULL == savedCoordChange->fCustomStage.get());
+ GR_DEBUGCODE(GrSafeRef(fCustomStage);)
+ GR_DEBUGCODE(savedCoordChange->fCustomStage.reset(fCustomStage);)
+ GR_DEBUGCODE(++fSavedCoordChangeCnt);
+ }
+
+ /**
+ * This balances the saveCoordChange call.
+ */
+ void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
+ fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
+ GrAssert(savedCoordChange.fCustomStage.get() == fCustomStage);
+ GR_DEBUGCODE(--fSavedCoordChangeCnt);
+ GR_DEBUGCODE(savedCoordChange.fCustomStage.reset(NULL);)
+ }
+
+ /**
+ * Gets the texture matrix. This is will be removed soon and be managed by GrCustomStage.
+ */
const GrMatrix& getMatrix() const { return fMatrix; }
/**
- * Multiplies the current sampler matrix a matrix
- *
- * After this call M' = M*m where M is the old matrix, m is the parameter
- * to this function, and M' is the new matrix. (We consider points to
- * be column vectors so tex cood vector t is transformed by matrix X as
- * t' = X*t.)
- *
- * @param matrix the matrix used to modify the matrix.
+ * Gets the matrix to apply at draw time. This is the original texture matrix combined with
+ * any coord system changes.
*/
- void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
-
- /**
- * Do not call this function. It will be removed soon.
- */
- void setMatrixDeprecated(const GrMatrix& matrix) { fMatrix = matrix; }
+ void getTotalMatrix(GrMatrix* matrix) const {
+ *matrix = fMatrix;
+ matrix->preConcat(fCoordChangeMatrix);
+ }
void reset() {
- fMatrix.reset();
GrSafeSetNull(fCustomStage);
}
GrCustomStage* setCustomStage(GrCustomStage* stage) {
+ GrAssert(0 == fSavedCoordChangeCnt);
GrSafeAssign(fCustomStage, stage);
fMatrix.reset();
+ fCoordChangeMatrix.reset();
return stage;
}
GrCustomStage* setCustomStage(GrCustomStage* stage, const GrMatrix& matrix) {
+ GrAssert(0 == fSavedCoordChangeCnt);
GrSafeAssign(fCustomStage, stage);
fMatrix = matrix;
+ fCoordChangeMatrix.reset();
return stage;
}
const GrCustomStage* getCustomStage() const { return fCustomStage; }
private:
- GrMatrix fMatrix;
-
+ GrMatrix fCoordChangeMatrix;
+ GrMatrix fMatrix; // TODO: remove this, store in GrCustomStage
GrCustomStage* fCustomStage;
+
+ GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;)
};
#endif
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index 4f725af..2b9179f 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -450,6 +450,7 @@
drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
}
GrRect bounds;
+ GrDrawState::AutoDeviceCoordDraw adcd;
if (reverse) {
GrAssert(NULL != drawState->getRenderTarget());
// draw over the whole world.
@@ -462,12 +463,7 @@
drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
} else {
- const GrMatrix& vm = drawState->getViewMatrix();
- if (!drawState->preConcatSamplerMatricesWithInverse(vm)) {
- GrPrintf("Could not invert matrix.\n");
- return false;
- }
- drawState->viewMatrix()->reset();
+ adcd.set(drawState);
}
} else {
bounds = path.getBounds();
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index cc11f6c..c95049a 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -54,7 +54,7 @@
fDrawState->setViewMatrix(fViewMatrix);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (fRestoreMask & (1 << s)) {
- fDrawState->sampler(s)->setMatrixDeprecated(fSamplerMatrices[s]);
+ fDrawState->sampler(s)->restoreCoordChange(fSavedCoordChanges[s]);
}
}
}
@@ -77,8 +77,8 @@
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
fRestoreMask |= (1 << s);
- fSamplerMatrices[s] = drawState->sampler(s)->getMatrix();
- drawState->sampler(s)->preConcatMatrix(preconcatMatrix);
+ fDrawState->sampler(s)->saveCoordChange(&fSavedCoordChanges[s]);
+ drawState->sampler(s)->preConcatCoordChange(preconcatMatrix);
}
}
}
@@ -90,7 +90,7 @@
fDrawState->setViewMatrix(fViewMatrix);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (fRestoreMask & (1 << s)) {
- fDrawState->sampler(s)->setMatrixDeprecated(fSamplerMatrices[s]);
+ fDrawState->sampler(s)->restoreCoordChange(fSavedCoordChanges[s]);
}
}
}
@@ -124,8 +124,8 @@
}
fRestoreMask |= (1 << s);
GrSamplerState* sampler = drawState->sampler(s);
- fSamplerMatrices[s] = sampler->getMatrix();
- sampler->preConcatMatrix(invVM);
+ sampler->saveCoordChange(&fSavedCoordChanges[s]);
+ sampler->preConcatCoordChange(invVM);
}
}
drawState->viewMatrix()->reset();
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index f3d5e37..7bfb5e5 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -10,7 +10,6 @@
#include "GrColor.h"
#include "GrMatrix.h"
-#include "GrNoncopyable.h"
#include "GrRefCnt.h"
#include "GrSamplerState.h"
#include "GrStencil.h"
@@ -267,32 +266,33 @@
}
/**
- * Preconcats the matrix of all samplers of enabled stages with a matrix.
+ * Called when the source coord system is changing. preConcat gives the transformation from the
+ * old coord system to the new coord system.
*/
- void preConcatSamplerMatrices(const GrMatrix& matrix) {
+ void preConcatSamplerMatrices(const GrMatrix& preConcat) {
for (int i = 0; i < kNumStages; ++i) {
if (this->isStageEnabled(i)) {
- fSamplerStates[i].preConcatMatrix(matrix);
+ fSamplerStates[i].preConcatCoordChange(preConcat);
}
}
}
/**
- * Preconcats the matrix of all samplers in the mask with the inverse of a
- * matrix. If the matrix inverse cannot be computed (and there is at least
- * one enabled stage) then false is returned.
+ * Called when the source coord system is changing. preConcatInverse is the inverse of the
+ * transformation from the old coord system to the new coord system. Returns false if the matrix
+ * cannot be inverted.
*/
- bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
+ bool preConcatSamplerMatricesWithInverse(const GrMatrix& preConcatInverse) {
GrMatrix inv;
bool computed = false;
for (int i = 0; i < kNumStages; ++i) {
if (this->isStageEnabled(i)) {
- if (!computed && !matrix.invert(&inv)) {
+ if (!computed && !preConcatInverse.invert(&inv)) {
return false;
} else {
computed = true;
}
- fSamplerStates[i].preConcatMatrix(inv);
+ fSamplerStates[i].preConcatCoordChange(preConcatInverse);
}
}
return true;
@@ -503,10 +503,10 @@
bool isSet() const { return NULL != fDrawState; }
private:
- GrDrawState* fDrawState;
- GrMatrix fViewMatrix;
- GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
- uint32_t fRestoreMask;
+ GrDrawState* fDrawState;
+ GrMatrix fViewMatrix;
+ GrSamplerState::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
+ uint32_t fRestoreMask;
};
////////////////////////////////////////////////////////////////////////////
@@ -557,10 +557,10 @@
void restore();
private:
- GrDrawState* fDrawState;
- GrMatrix fViewMatrix;
- GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
- uint32_t fRestoreMask;
+ GrDrawState* fDrawState;
+ GrMatrix fViewMatrix;
+ GrSamplerState::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
+ uint32_t fRestoreMask;
};
/// @}
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index d2a22d0..351ff53 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -151,11 +151,9 @@
static void AdjustTextureMatrix(const GrGLTexture* texture,
GrMatrix* matrix);
- // subclass may try to take advantage of identity tex matrices.
- // This helper determines if matrix will be identity after all
- // adjustments are applied.
- static bool TextureMatrixIsIdentity(const GrGLTexture* texture,
- const GrSamplerState& sampler);
+ // This helper determines if what optimizations can be applied to the matrix after any coord
+ // adjustments are applied. The return is a bitfield of GrGLProgram::StageDesc::OptFlags.
+ static int TextureMatrixOptFlags(const GrGLTexture* texture, const GrSamplerState& sampler);
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 9e3a5d8..e579331 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -177,19 +177,20 @@
}
}
-bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
- const GrSamplerState& sampler) {
+int GrGpuGL::TextureMatrixOptFlags(const GrGLTexture* texture,
+ const GrSamplerState& sampler) {
GrAssert(NULL != texture);
- if (!sampler.getMatrix().isIdentity()) {
- return false;
+ GrMatrix matrix;
+ sampler.getTotalMatrix(&matrix);
+
+ bool canBeIndentity = GrGLTexture::kTopDown_Orientation == texture->orientation();
+
+ if (canBeIndentity && matrix.isIdentity()) {
+ return GrGLProgram::StageDesc::kIdentityMatrix_OptFlagBit;
+ } else if (!matrix.hasPerspective()) {
+ return GrGLProgram::StageDesc::kNoPerspective_OptFlagBit;
}
- GrGLTexture::Orientation orientation = texture->orientation();
- if (GrGLTexture::kBottomUp_Orientation == orientation) {
- return false;
- } else {
- GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
- }
- return true;
+ return 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -208,7 +209,8 @@
UniformHandle matrixUni = fCurrentProgram->fUniforms.fStages[s].fTextureMatrixUni;
const GrMatrix& hwMatrix = fCurrentProgram->fTextureMatrices[s];
- const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix();
+ GrMatrix samplerMatrix;
+ drawState.getSampler(s).getTotalMatrix(&samplerMatrix);
if (kInvalidUniformHandle != matrixUni &&
(orientationChange || !hwMatrix.cheapEqualTo(samplerMatrix))) {
@@ -238,7 +240,6 @@
}
}
-
void GrGpuGL::flushColorMatrix() {
UniformHandle matrixUni = fCurrentProgram->fUniforms.fColorMatrixUni;
UniformHandle vecUni = fCurrentProgram->fUniforms.fColorMatrixVecUni;
@@ -701,15 +702,13 @@
// FIXME: Still assuming one texture per custom stage
const GrCustomStage* customStage = drawState.getSampler(s).getCustomStage();
const GrGLTexture* texture = static_cast<const GrGLTexture*>(customStage->texture(0));
+ GrMatrix samplerMatrix;
+ sampler.getTotalMatrix(&samplerMatrix);
if (NULL != texture) {
// We call this helper function rather then simply checking the client-specified
// texture matrix. This is because we may have to concat a y-inversion to account
// for texture orientation.
- if (TextureMatrixIsIdentity(texture, sampler)) {
- stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
- } else if (!sampler.getMatrix().hasPerspective()) {
- stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit;
- }
+ stage.fOptFlags |= TextureMatrixOptFlags(texture, sampler);
}
setup_custom_stage(&stage, sampler, this->glCaps(), customStages,