fFShaderID = 0;
fProgramID = 0;
- fViewMatrix = SkMatrix::InvalidMatrix();
- fViewportSize.set(-1, -1);
- fOrigin = (GrSurfaceOrigin) -1;
fColor = GrColor_ILLEGAL;
fColorFilterColor = GrColor_ILLEGAL;
- fRTHeight = -1;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
fEffects[s] = NULL;
SharedGLState* sharedState) {
const GrDrawState& drawState = gpu->getDrawState();
- int rtHeight = drawState.getRenderTarget()->height();
- if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni &&
- fRTHeight != rtHeight) {
- fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(rtHeight));
- fRTHeight = rtHeight;
- }
-
this->setColor(drawState, color, sharedState);
this->setCoverage(drawState, coverage, sharedState);
+ this->setMatrixAndRenderTargetHeight(drawState);
// Setup the SkXfermode::Mode-based colorfilter uniform if necessary
if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fColorFilterUni &&
}
}
}
+
+void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
+ const GrRenderTarget* rt = drawState.getRenderTarget();
+ SkISize size;
+ size.set(rt->width(), rt->height());
+
+ // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
+ if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni &&
+ fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
+ fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
+ }
+
+ if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
+ !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
+ fMatrixState.fRenderTargetSize != size) {
+ SkMatrix m;
+ if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
+ m.setAll(
+ SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1,
+ 0,-SkIntToScalar(2) / size.fHeight, SK_Scalar1,
+ 0, 0, SkMatrix::I()[8]);
+ } else {
+ m.setAll(
+ SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1,
+ 0, SkIntToScalar(2) / size.fHeight,-SK_Scalar1,
+ 0, 0, SkMatrix::I()[8]);
+ }
+ m.setConcat(m, drawState.getViewMatrix());
+
+ // ES doesn't allow you to pass true to the transpose param so we do our own transpose.
+ GrGLfloat mt[] = {
+ SkScalarToFloat(m[SkMatrix::kMScaleX]),
+ SkScalarToFloat(m[SkMatrix::kMSkewY]),
+ SkScalarToFloat(m[SkMatrix::kMPersp0]),
+ SkScalarToFloat(m[SkMatrix::kMSkewX]),
+ SkScalarToFloat(m[SkMatrix::kMScaleY]),
+ SkScalarToFloat(m[SkMatrix::kMPersp1]),
+ SkScalarToFloat(m[SkMatrix::kMTransX]),
+ SkScalarToFloat(m[SkMatrix::kMTransY]),
+ SkScalarToFloat(m[SkMatrix::kMPersp2])
+ };
+ fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, mt);
+ fMatrixState.fViewMatrix = drawState.getViewMatrix();
+ fMatrixState.fRenderTargetSize = size;
+ fMatrixState.fRenderTargetOrigin = rt->origin();
+ }
+}
const Desc& getDesc() { return fDesc; }
+ /**
+ * Gets the GL program ID for this program.
+ */
+ GrGLuint programID() const { return fProgramID; }
+
/**
* Attribute indices. These should not overlap.
*/
}
};
+ /**
+ * The GrDrawState's view matrix along with the aspects of the render target determine the
+ * matrix sent to GL. The size of the render target affects the GL matrix because we must
+ * convert from Skia device coords to GL's normalized coords. Also the origin of the render
+ * target may require us to perform a mirror-flip.
+ */
+ struct MatrixState {
+ SkMatrix fViewMatrix;
+ SkISize fRenderTargetSize;
+ GrSurfaceOrigin fRenderTargetOrigin;
+
+ MatrixState() { this->invalidate(); }
+ void invalidate() {
+ fViewMatrix = SkMatrix::InvalidMatrix();
+ fRenderTargetSize.fWidth = -1; // just make the first value compared illegal.
+ fRenderTargetOrigin = (GrSurfaceOrigin) -1;
+ }
+ };
+
/**
* This function uploads uniforms and calls each GrGLEffect's setData. It is called before a
* draw occurs using the program after the program has already been bound. It also uses the
friend class GrGLProgram;
};
+
private:
GrGLProgram(const GrGLContextInfo& gl,
const Desc& desc,
// per-vertex coverages.
void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*);
+ // Helper for setData() that sets the view matrix and loads the render target height uniform
+ void setMatrixAndRenderTargetHeight(const GrDrawState&);
+
typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray;
struct UniformHandles {
GrGLuint fGShaderID;
GrGLuint fFShaderID;
GrGLuint fProgramID;
- // The matrix sent to GL is determined by the client's matrix,
- // the size of the viewport, and the origin of the render target.
- SkMatrix fViewMatrix;
- SkISize fViewportSize;
- GrSurfaceOrigin fOrigin;
// these reflect the current values of uniforms (GL uniform values travel with program)
+ MatrixState fMatrixState;
GrColor fColor;
GrColor fCoverage;
GrColor fColorFilterColor;
- int fRTHeight;
GrGLEffect* fEffects[GrDrawState::kNumStages];
GrGLUniformManager fUniformManager;
UniformHandles fUniformHandles;
- friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality.
-
typedef GrRefCnt INHERITED;
};
if (0 != fHWProgramID) {
// detach the current program so there is no confusion on OpenGL's part
// that we want it to be deleted
- GrAssert(fHWProgramID == fCurrentProgram->fProgramID);
+ GrAssert(fHWProgramID == fCurrentProgram->programID());
GL_CALL(UseProgram(0));
}
fHWBoundRenderTarget = NULL;
- fHWPathMatrixState.invalidate();
+ fHWPathStencilMatrixState.invalidate();
if (fCaps.pathStencilingSupport()) {
// we don't use the model view matrix.
GL_CALL(MatrixMode(GR_GL_MODELVIEW));
const GrGLContextInfo& fGL;
};
-
- // sets the MVP matrix uniform for currently bound program
- void flushViewMatrix(DrawType type);
+ // sets the matrix for path stenciling (uses the GL fixed pipe matrices)
+ void flushPathStencilMatrix();
// flushes dithering, color-mask, and face culling stat
void flushMiscFixedFunctionState();
}
} fHWAAState;
- struct {
- SkMatrix fViewMatrix;
- SkISize fRTSize;
- GrSurfaceOrigin fLastOrigin;
- void invalidate() {
- fViewMatrix = SkMatrix::InvalidMatrix();
- fRTSize.fWidth = -1; // just make the first value compared illegal.
- fLastOrigin = (GrSurfaceOrigin) -1;
- }
- } fHWPathMatrixState;
- GrStencilSettings fHWStencilSettings;
- TriState fHWStencilTestEnabled;
+ GrGLProgram::MatrixState fHWPathStencilMatrixState;
+
+ GrStencilSettings fHWStencilSettings;
+ TriState fHWStencilTestEnabled;
- GrDrawState::DrawFace fHWDrawFace;
- TriState fHWWriteToColor;
- TriState fHWDitherEnabled;
- GrRenderTarget* fHWBoundRenderTarget;
- GrTexture* fHWBoundTextures[GrDrawState::kNumStages];
+ GrDrawState::DrawFace fHWDrawFace;
+ TriState fHWWriteToColor;
+ TriState fHWDitherEnabled;
+ GrRenderTarget* fHWBoundRenderTarget;
+ GrTexture* fHWBoundTextures[GrDrawState::kNumStages];
///@}
// we record what stencil format worked last time to hopefully exit early
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
-void GrGpuGL::flushViewMatrix(DrawType type) {
- const GrGLRenderTarget* rt = static_cast<const GrGLRenderTarget*>(this->getDrawState().getRenderTarget());
- SkISize viewportSize;
- const GrGLIRect& viewport = rt->getViewport();
- viewportSize.set(viewport.fWidth, viewport.fHeight);
-
+void GrGpuGL::flushPathStencilMatrix() {
+ const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix();
+ const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
+ SkISize size;
+ size.set(rt->width(), rt->height());
const SkMatrix& vm = this->getDrawState().getViewMatrix();
- if (kStencilPath_DrawType == type) {
- if (fHWPathMatrixState.fLastOrigin != rt->origin() ||
- fHWPathMatrixState.fViewMatrix != vm ||
- fHWPathMatrixState.fRTSize != viewportSize) {
- // rescale the coords from skia's "device" coords to GL's normalized coords,
- // and perform a y-flip if required.
- SkMatrix m;
- if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
- m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height());
- m.postTranslate(-SK_Scalar1, SK_Scalar1);
- } else {
- m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height());
- m.postTranslate(-SK_Scalar1, -SK_Scalar1);
- }
- m.preConcat(vm);
-
- // GL wants a column-major 4x4.
- GrGLfloat mv[] = {
- // col 0
- SkScalarToFloat(m[SkMatrix::kMScaleX]),
- SkScalarToFloat(m[SkMatrix::kMSkewY]),
- 0,
- SkScalarToFloat(m[SkMatrix::kMPersp0]),
-
- // col 1
- SkScalarToFloat(m[SkMatrix::kMSkewX]),
- SkScalarToFloat(m[SkMatrix::kMScaleY]),
- 0,
- SkScalarToFloat(m[SkMatrix::kMPersp1]),
-
- // col 2
- 0, 0, 0, 0,
-
- // col3
- SkScalarToFloat(m[SkMatrix::kMTransX]),
- SkScalarToFloat(m[SkMatrix::kMTransY]),
- 0.0f,
- SkScalarToFloat(m[SkMatrix::kMPersp2])
- };
- GL_CALL(MatrixMode(GR_GL_PROJECTION));
- GL_CALL(LoadMatrixf(mv));
- fHWPathMatrixState.fViewMatrix = vm;
- fHWPathMatrixState.fRTSize = viewportSize;
- fHWPathMatrixState.fLastOrigin = rt->origin();
- }
- } else if (fCurrentProgram->fOrigin != rt->origin() ||
- !fCurrentProgram->fViewMatrix.cheapEqualTo(vm) ||
- fCurrentProgram->fViewportSize != viewportSize) {
+ if (fHWPathStencilMatrixState.fRenderTargetOrigin != rt->origin() ||
+ fHWPathStencilMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) ||
+ fHWPathStencilMatrixState.fRenderTargetSize!= size) {
+ // rescale the coords from skia's "device" coords to GL's normalized coords,
+ // and perform a y-flip if required.
SkMatrix m;
if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
- m.setAll(
- SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1,
- 0,-SkIntToScalar(2) / viewportSize.fHeight, SK_Scalar1,
- 0, 0, SkMatrix::I()[8]);
+ m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height());
+ m.postTranslate(-SK_Scalar1, SK_Scalar1);
} else {
- m.setAll(
- SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1,
- 0, SkIntToScalar(2) / viewportSize.fHeight,-SK_Scalar1,
- 0, 0, SkMatrix::I()[8]);
+ m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height());
+ m.postTranslate(-SK_Scalar1, -SK_Scalar1);
}
- m.setConcat(m, vm);
+ m.preConcat(vm);
- // ES doesn't allow you to pass true to the transpose param,
- // so do our own transpose
- GrGLfloat mt[] = {
+ // GL wants a column-major 4x4.
+ GrGLfloat mv[] = {
+ // col 0
SkScalarToFloat(m[SkMatrix::kMScaleX]),
SkScalarToFloat(m[SkMatrix::kMSkewY]),
+ 0,
SkScalarToFloat(m[SkMatrix::kMPersp0]),
+
+ // col 1
SkScalarToFloat(m[SkMatrix::kMSkewX]),
SkScalarToFloat(m[SkMatrix::kMScaleY]),
+ 0,
SkScalarToFloat(m[SkMatrix::kMPersp1]),
+
+ // col 2
+ 0, 0, 0, 0,
+
+ // col3
SkScalarToFloat(m[SkMatrix::kMTransX]),
SkScalarToFloat(m[SkMatrix::kMTransY]),
+ 0.0f,
SkScalarToFloat(m[SkMatrix::kMPersp2])
};
- fCurrentProgram->fUniformManager.setMatrix3f(
- fCurrentProgram->fUniformHandles.fViewMatrixUni,
- mt);
- fCurrentProgram->fViewMatrix = vm;
- fCurrentProgram->fViewportSize = viewportSize;
- fCurrentProgram->fOrigin = rt->origin();
+ GL_CALL(MatrixMode(GR_GL_PROJECTION));
+ GL_CALL(LoadMatrixf(mv));
+ fHWPathStencilMatrixState.fViewMatrix = vm;
+ fHWPathStencilMatrixState.fRenderTargetSize = size;
+ fHWPathStencilMatrixState.fRenderTargetOrigin = rt->origin();
}
}
bool GrGpuGL::flushGraphicsState(DrawType type) {
const GrDrawState& drawState = this->getDrawState();
- // GrGpu::setupClipAndFlushState should have already checked this
- // and bailed if not true.
+ // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
GrAssert(NULL != drawState.getRenderTarget());
- if (kStencilPath_DrawType != type) {
+ if (kStencilPath_DrawType == type) {
+ this->flushPathStencilMatrix();
+ } else {
this->flushMiscFixedFunctionState();
GrBlendCoeff srcCoeff;
}
fCurrentProgram.get()->ref();
- if (fHWProgramID != fCurrentProgram->fProgramID) {
- GL_CALL(UseProgram(fCurrentProgram->fProgramID));
- fHWProgramID = fCurrentProgram->fProgramID;
+ GrGLuint programID = fCurrentProgram->programID();
+ if (fHWProgramID != programID) {
+ GL_CALL(UseProgram(programID));
+ fHWProgramID = programID;
}
+
fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
fCurrentProgram->setData(this, color, coverage, &fSharedGLProgramState);
}
this->flushStencil(type);
- this->flushViewMatrix(type);
this->flushScissor();
this->flushAAState(type);