Replace GrDrawState::AutoDeviceCoordDraw with GrDrawState::AutoViewMatrixRestore::setIdentity(). s
R=robertphillips@google.com
Review URL: https://codereview.chromium.org/15780002
git-svn-id: http://skia.googlecode.com/svn/trunk@9331 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index e76f0c8..77980e4 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -602,23 +602,21 @@
return true;
}
- GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
- GrDrawState* drawState = target->drawState();
-
- GrDrawState::AutoDeviceCoordDraw adcd(drawState);
- if (!adcd.succeeded()) {
+ SkMatrix viewMatrix = target->getDrawState().getViewMatrix();
+ GrDrawTarget::AutoStateRestore asr;
+ if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
return false;
}
- const SkMatrix* vm = &adcd.getOriginalMatrix();
+ GrDrawState* drawState = target->drawState();
// We use the fact that SkPath::transform path does subdivision based on
// perspective. Otherwise, we apply the view matrix when copying to the
// segment representation.
SkPath tmpPath;
- if (vm->hasPerspective()) {
- origPath.transform(*vm, &tmpPath);
+ if (viewMatrix.hasPerspective()) {
+ origPath.transform(viewMatrix, &tmpPath);
path = &tmpPath;
- vm = &SkMatrix::I();
+ viewMatrix = SkMatrix::I();
}
QuadVertex *verts;
@@ -633,7 +631,7 @@
SkSTArray<kPreallocSegmentCnt, Segment, true> segments;
SkPoint fanPt;
- if (!get_segments(*path, *vm, &segments, &fanPt, &vCount, &iCount)) {
+ if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount)) {
return false;
}
@@ -662,8 +660,8 @@
// This is valid because all the computed verts are within 1 pixel of the path control points.
SkRect devBounds;
- devBounds = origPath.getBounds();
- adcd.getOriginalMatrix().mapRect(&devBounds);
+ devBounds = path->getBounds();
+ viewMatrix.mapRect(&devBounds);
devBounds.outset(SK_Scalar1, SK_Scalar1);
// Check devBounds
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 51d5a79..1a15521 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -816,18 +816,16 @@
return false;
}
- GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
- GrDrawState* drawState = target->drawState();
+ GrDrawTarget::AutoStateRestore asr;
- GrDrawState::AutoDeviceCoordDraw adcd;
// createGeom transforms the geometry to device space when the matrix does not have
// perspective.
- if (!drawState->getViewMatrix().hasPerspective()) {
- adcd.set(drawState);
- if (!adcd.succeeded()) {
- return false;
- }
+ if (target->getDrawState().getViewMatrix().hasPerspective()) {
+ asr.set(target, GrDrawTarget::kPreserve_ASRInit);
+ } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
+ return false;
}
+ GrDrawState* drawState = target->drawState();
// TODO: See whether rendering lines as degenerate quads improves perf
// when we have a mix
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index c022b34d..1362179 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -347,9 +347,9 @@
SkRegion::Op op,
const GrIRect& dstBound,
const GrIRect& srcBound) {
+ GrDrawState::AutoViewMatrixRestore avmr;
GrDrawState* drawState = fGpu->drawState();
- SkMatrix oldMatrix = drawState->getViewMatrix();
- drawState->viewMatrix()->reset();
+ SkAssertResult(avmr.setIdentity(drawState));
drawState->setRenderTarget(dstMask->asRenderTarget());
@@ -366,7 +366,6 @@
fGpu->drawSimpleRect(SkRect::MakeFromIRect(dstBound), NULL);
drawState->disableStage(0);
- drawState->setViewMatrix(oldMatrix);
}
// get a texture to act as a temporary buffer for AA clip boolean operations
@@ -437,9 +436,6 @@
return NULL;
}
- GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
- GrDrawState* drawState = fGpu->drawState();
-
// The top-left of the mask corresponds to the top-left corner of the bounds.
SkVector clipToMaskOffset = {
SkIntToScalar(-clipSpaceIBounds.fLeft),
@@ -449,12 +445,16 @@
// we populate with a rasterization of the clip.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
+ // Set the matrix so that rendered clip elements are transformed to mask space from clip space.
+ SkMatrix translate;
+ translate.setTranslate(clipToMaskOffset);
+ GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &translate);
+
+ GrDrawState* drawState = fGpu->drawState();
+
// We're drawing a coverage mask and want coverage to be run through the blend function.
drawState->enableState(GrDrawState::kCoverageDrawing_StateBit);
- // Set the matrix so that rendered clip elements are transformed to mask space from clip space.
- drawState->viewMatrix()->setTranslate(clipToMaskOffset);
-
// The scratch texture that we are drawing into can be substantially larger than the mask. Only
// clear the part that we care about.
fGpu->clear(&maskSpaceIBounds,
@@ -589,8 +589,16 @@
stencilBuffer->setLastClip(genID, clipSpaceIBounds, clipSpaceToStencilOffset);
- GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
+ // Set the matrix so that rendered clip elements are transformed from clip to stencil space.
+ SkVector translate = {
+ SkIntToScalar(clipSpaceToStencilOffset.fX),
+ SkIntToScalar(clipSpaceToStencilOffset.fY)
+ };
+ SkMatrix matrix;
+ matrix.setTranslate(translate);
+ GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);
drawState = fGpu->drawState();
+
drawState->setRenderTarget(rt);
// We set the current clip to the bounds so that our recursive draws are scissored to them.
@@ -599,13 +607,6 @@
GrDrawTarget::AutoClipRestore acr(fGpu, stencilSpaceIBounds);
drawState->enableState(GrDrawState::kClip_StateBit);
- // Set the matrix so that rendered clip elements are transformed from clip to stencil space.
- SkVector translate = {
- SkIntToScalar(clipSpaceToStencilOffset.fX),
- SkIntToScalar(clipSpaceToStencilOffset.fY)
- };
- drawState->viewMatrix()->setTranslate(translate);
-
#if !VISUALIZE_COMPLEX_CLIP
drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
#endif
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 5f255a6..acae5b2 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -777,8 +777,8 @@
&combinedMatrix, &devRect,
&useVertexCoverage);
if (doAA) {
- GrDrawState::AutoDeviceCoordDraw adcd(target->drawState());
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(target->drawState())) {
return;
}
if (width >= 0) {
@@ -846,7 +846,6 @@
const SkMatrix* dstMatrix,
const SkMatrix* localMatrix) {
SK_TRACE_EVENT0("GrContext::drawRectToRect");
-
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
GrDrawState::AutoStageDisable atr(fDrawState);
@@ -1049,21 +1048,22 @@
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
GrDrawState::AutoStageDisable atr(fDrawState);
- bool useAA = paint.isAntiAlias() && !this->getRenderTarget()->isMultisampled();
+ bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled();
if (useAA && stroke.getWidth() < 0 && !path.isConvex()) {
// Concave AA paths are expensive - try to avoid them for special cases
bool useVertexCoverage;
SkRect rects[2];
if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) {
- GrDrawState::AutoDeviceCoordDraw adcd(target->drawState());
- if (!adcd.succeeded()) {
+ SkMatrix origViewMatrix = target->getDrawState().getViewMatrix();
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(target->drawState())) {
return;
}
fAARectRenderer->fillAANestedRects(this->getGpu(), target,
rects,
- adcd.getOriginalMatrix(),
+ origViewMatrix,
useVertexCoverage);
return;
}
@@ -1534,14 +1534,13 @@
// writeRenderTargetPixels can be called in the midst of drawing another
// object (e.g., when uploading a SW path rendering to the gpu while
// drawing a rect) so preserve the current geometry.
- GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
+ SkMatrix matrix;
+ matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
+ GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);
GrDrawState* drawState = fGpu->drawState();
GrAssert(effect);
drawState->setEffect(0, effect);
- SkMatrix matrix;
- matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
- drawState->setViewMatrix(matrix);
drawState->setRenderTarget(target);
fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
@@ -1565,8 +1564,7 @@
}
#endif
} else {
- fDrawState->reset();
- *fDrawState->viewMatrix() = fViewMatrix;
+ fDrawState->reset(fViewMatrix);
fDrawState->setRenderTarget(fRenderTarget.get());
}
GrDrawTarget* target;
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index 87deb9c..13bfe92 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -459,7 +459,7 @@
drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
}
GrRect bounds;
- GrDrawState::AutoDeviceCoordDraw adcd;
+ GrDrawState::AutoViewMatrixRestore avmr;
if (reverse) {
GrAssert(NULL != drawState->getRenderTarget());
// draw over the dev bounds (which will be the whole dst surface for inv fill).
@@ -470,7 +470,7 @@
drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
} else {
- adcd.set(drawState);
+ avmr.setIdentity(drawState);
}
} else {
bounds = path.getBounds();
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 2cc50f7..f114ccc 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -8,6 +8,25 @@
#include "GrDrawState.h"
#include "GrPaint.h"
+bool GrDrawState::setIdentityViewMatrix() {
+ SkMatrix invVM;
+ bool inverted = false;
+ for (int s = 0; s < GrDrawState::kNumStages; ++s) {
+ if (this->isStageEnabled(s)) {
+ if (!inverted) {
+ if (!fCommon.fViewMatrix.invert(&invVM)) {
+ // sad trombone sound
+ return false;
+ }
+ inverted = true;
+ }
+ fStages[s].localCoordChange(invVM);
+ }
+ }
+ fCommon.fViewMatrix.reset();
+ return true;
+}
+
void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
for (int i = 0; i < GrPaint::kMaxColorStages; ++i) {
int s = i + GrPaint::kFirstColorStage;
@@ -395,81 +414,59 @@
void GrDrawState::AutoViewMatrixRestore::restore() {
if (NULL != fDrawState) {
- fDrawState->setViewMatrix(fViewMatrix);
+ fDrawState->fCommon.fViewMatrix = fViewMatrix;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (fRestoreMask & (1 << s)) {
fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
}
}
+ fDrawState = NULL;
}
- fDrawState = NULL;
}
void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
const SkMatrix& preconcatMatrix) {
this->restore();
- fDrawState = drawState;
- if (NULL == drawState) {
+ if (NULL == drawState || preconcatMatrix.isIdentity()) {
return;
}
+ fDrawState = drawState;
fRestoreMask = 0;
fViewMatrix = drawState->getViewMatrix();
- drawState->preConcatViewMatrix(preconcatMatrix);
+ drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (drawState->isStageEnabled(s)) {
fRestoreMask |= (1 << s);
- fDrawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
+ drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
drawState->fStages[s].localCoordChange(preconcatMatrix);
}
}
}
-////////////////////////////////////////////////////////////////////////////////
-
-void GrDrawState::AutoDeviceCoordDraw::restore() {
- if (NULL != fDrawState) {
- fDrawState->setViewMatrix(fViewMatrix);
- for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- if (fRestoreMask & (1 << s)) {
- fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
- }
- }
- }
- fDrawState = NULL;
-}
-
-bool GrDrawState::AutoDeviceCoordDraw::set(GrDrawState* drawState) {
- GrAssert(NULL != drawState);
-
+bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
this->restore();
- fDrawState = drawState;
- if (NULL == fDrawState) {
+ if (NULL == drawState) {
return false;
}
+ if (drawState->getViewMatrix().isIdentity()) {
+ return true;
+ }
+
fViewMatrix = drawState->getViewMatrix();
fRestoreMask = 0;
- SkMatrix invVM;
- bool inverted = false;
-
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (drawState->isStageEnabled(s)) {
- if (!inverted && !fViewMatrix.invert(&invVM)) {
- // sad trombone sound
- fDrawState = NULL;
- return false;
- } else {
- inverted = true;
- }
fRestoreMask |= (1 << s);
- GrEffectStage* stage = drawState->fStages + s;
- stage->saveCoordChange(&fSavedCoordChanges[s]);
- stage->localCoordChange(invVM);
+ drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
}
}
- drawState->viewMatrix()->reset();
+ if (!drawState->setIdentityViewMatrix()) {
+ return false;
+ }
+ fDrawState = drawState;
return true;
}
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index bf3ef74..26422aa 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -56,43 +56,39 @@
kNumStages = GrPaint::kTotalStages + 2,
};
- GrDrawState() {
- this->reset();
- }
+ GrDrawState() { this->reset(); }
+ GrDrawState(const SkMatrix& initialViewMatrix) { this->reset(initialViewMatrix); }
+
+ /**
+ * Copies another draw state.
+ **/
GrDrawState(const GrDrawState& state) {
*this = state;
}
- virtual ~GrDrawState() {
- this->disableStages();
+ /**
+ * Copies another draw state with a preconcat to the view matrix.
+ **/
+ GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
+ *this = state;
+ if (!preConcatMatrix.isIdentity()) {
+ for (int i = 0; i < kNumStages; ++i) {
+ if (this->isStageEnabled(i)) {
+ fStages[i].localCoordChange(preConcatMatrix);
+ }
+ }
+ }
}
+ virtual ~GrDrawState() { this->disableStages(); }
+
/**
- * Resets to the default state.
- * GrEffects will be removed from all stages.
+ * Resets to the default state. GrEffects will be removed from all stages.
*/
- void reset() {
+ void reset() { this->onReset(NULL); }
- this->disableStages();
-
- fRenderTarget.reset(NULL);
-
- this->setDefaultVertexAttribs();
-
- fCommon.fColor = 0xffffffff;
- fCommon.fViewMatrix.reset();
- fCommon.fSrcBlend = kOne_GrBlendCoeff;
- fCommon.fDstBlend = kZero_GrBlendCoeff;
- fCommon.fBlendConstant = 0x0;
- fCommon.fFlagBits = 0x0;
- fCommon.fStencilSettings.setDisabled();
- fCommon.fFirstCoverageStage = kNumStages;
- fCommon.fCoverage = 0xffffffff;
- fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
- fCommon.fColorFilterColor = 0x0;
- fCommon.fDrawFace = kBoth_DrawFace;
- }
+ void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
/**
* Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
@@ -616,42 +612,10 @@
////
/**
- * Sets the matrix applied to vertex positions.
- *
- * In the post-view-matrix space the rectangle [0,w]x[0,h]
- * fully covers the render target. (w and h are the width and height of the
- * the render-target.)
+ * Sets the view matrix to identity and updates any installed effects to compensate for the
+ * coord system change.
*/
- void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
-
- /**
- * Gets a writable pointer to the view matrix.
- */
- SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
-
- /**
- * Multiplies the current view matrix by a matrix
- *
- * After this call V' = V*m where V is the old view matrix,
- * m is the parameter to this function, and V' is the new view matrix.
- * (We consider positions to be column vectors so position vector p is
- * transformed by matrix X as p' = X*p.)
- *
- * @param m the matrix used to modify the view matrix.
- */
- void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
-
- /**
- * Multiplies the current view matrix by a matrix
- *
- * After this call V' = m*V where V is the old view matrix,
- * m is the parameter to this function, and V' is the new view matrix.
- * (We consider positions to be column vectors so position vector p is
- * transformed by matrix X as p' = X*p.)
- *
- * @param m the matrix used to modify the view matrix.
- */
- void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
+ bool setIdentityViewMatrix();
/**
* Retrieves the current view matrix
@@ -685,7 +649,7 @@
/**
* Preconcats the current view matrix and restores the previous view matrix in the destructor.
- * Effect matrices are automatically adjusted to compensate.
+ * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
*/
class AutoViewMatrixRestore : public ::GrNoncopyable {
public:
@@ -705,60 +669,9 @@
void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
- bool isSet() const { return NULL != fDrawState; }
-
- private:
- GrDrawState* fDrawState;
- SkMatrix fViewMatrix;
- GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
- uint32_t fRestoreMask;
- };
-
- ////////////////////////////////////////////////////////////////////////////
-
- /**
- * This sets the view matrix to identity and adjusts stage matrices to compensate. The
- * destructor undoes the changes, restoring the view matrix that was set before the
- * constructor. It is similar to passing the inverse of the current view matrix to
- * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
- */
- class AutoDeviceCoordDraw : ::GrNoncopyable {
- public:
- AutoDeviceCoordDraw() : fDrawState(NULL) {}
- /**
- * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
- * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
- * to specify such stages.
- */
- AutoDeviceCoordDraw(GrDrawState* drawState) {
- fDrawState = NULL;
- this->set(drawState);
- }
-
- ~AutoDeviceCoordDraw() { this->restore(); }
-
- bool set(GrDrawState* drawState);
-
- /**
- * Returns true if this object was successfully initialized on to a GrDrawState. It may
- * return false because a non-default constructor or set() were never called or because
- * the view matrix was not invertible.
- */
- bool succeeded() const { return NULL != fDrawState; }
-
- /**
- * Returns the matrix that was set previously set on the drawState. This is only valid
- * if succeeded returns true.
- */
- const SkMatrix& getOriginalMatrix() const {
- GrAssert(this->succeeded());
- return fViewMatrix;
- }
-
- /**
- * Can be called prior to destructor to restore the original matrix.
- */
- void restore();
+ /** Sets the draw state's matrix to identity. This can fail because the current view matrix
+ is not invertible. */
+ bool setIdentity(GrDrawState* drawState);
private:
GrDrawState* fDrawState;
@@ -1027,6 +940,32 @@
private:
+ void onReset(const SkMatrix* initialViewMatrix) {
+
+ this->disableStages();
+
+ fRenderTarget.reset(NULL);
+
+ this->setDefaultVertexAttribs();
+
+ fCommon.fColor = 0xffffffff;
+ if (NULL == initialViewMatrix) {
+ fCommon.fViewMatrix.reset();
+ } else {
+ fCommon.fViewMatrix = *initialViewMatrix;
+ }
+ fCommon.fSrcBlend = kOne_GrBlendCoeff;
+ fCommon.fDstBlend = kZero_GrBlendCoeff;
+ fCommon.fBlendConstant = 0x0;
+ fCommon.fFlagBits = 0x0;
+ fCommon.fStencilSettings.setDisabled();
+ fCommon.fFirstCoverageStage = kNumStages;
+ fCommon.fCoverage = 0xffffffff;
+ fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
+ fCommon.fColorFilterColor = 0x0;
+ fCommon.fDrawFace = kBoth_DrawFace;
+ }
+
/** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
struct CommonState {
// These fields are roughly sorted by decreasing likelihood of being different in op==
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index aa475b3..02bc8d7 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -657,9 +657,10 @@
}
GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
- ASRInit init) {
+ ASRInit init,
+ const SkMatrix* vm) {
fDrawTarget = NULL;
- this->set(target, init);
+ this->set(target, init, vm);
}
GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
@@ -669,7 +670,31 @@
}
}
-void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
+void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
+ GrAssert(NULL == fDrawTarget);
+ fDrawTarget = target;
+ fSavedState = target->drawState();
+ GrAssert(fSavedState);
+ fSavedState->ref();
+ if (kReset_ASRInit == init) {
+ if (NULL == vm) {
+ // calls the default cons
+ fTempState.init();
+ } else {
+ SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
+ }
+ } else {
+ GrAssert(kPreserve_ASRInit == init);
+ if (NULL == vm) {
+ fTempState.set(*fSavedState);
+ } else {
+ SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
+ }
+ }
+ target->setDrawState(fTempState.get());
+}
+
+bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
GrAssert(NULL == fDrawTarget);
fDrawTarget = target;
fSavedState = target->drawState();
@@ -682,8 +707,17 @@
GrAssert(kPreserve_ASRInit == init);
// calls the copy cons
fTempState.set(*fSavedState);
+ if (!fTempState.get()->setIdentityViewMatrix()) {
+ // let go of any resources held by the temp
+ fTempState.get()->reset();
+ fDrawTarget = NULL;
+ fSavedState->unref();
+ fSavedState = NULL;
+ return false;
+ }
}
target->setDrawState(fTempState.get());
+ return true;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 8f5f09f..e876136 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -488,8 +488,12 @@
*
* @param init Should the newly installed GrDrawState be a copy of the
* previous state or a default-initialized GrDrawState.
+ * @param viewMatrix Optional view matrix. If init = kPreserve then the draw state's
+ * matrix will be preconcat'ed with the param. All stages will be
+ updated to compensate for the matrix change. If init == kReset
+ then the draw state's matrix will be this matrix.
*/
- AutoStateRestore(GrDrawTarget* target, ASRInit init);
+ AutoStateRestore(GrDrawTarget* target, ASRInit init, const SkMatrix* viewMatrix = NULL);
~AutoStateRestore();
@@ -501,13 +505,25 @@
*
* @param init Should the newly installed GrDrawState be a copy of the
* previous state or a default-initialized GrDrawState.
+ * @param viewMatrix Optional view matrix. If init = kPreserve then the draw state's
+ * matrix will be preconcat'ed with the param. All stages will be
+ updated to compensate for the matrix change. If init == kReset
+ then the draw state's matrix will be this matrix.
*/
- void set(GrDrawTarget* target, ASRInit init);
+ void set(GrDrawTarget* target, ASRInit init, const SkMatrix* viewMatrix = NULL);
+
+ /**
+ * Like set() but makes the view matrix identity. When init is kReset it is as though
+ * NULL was passed to set's viewMatrix param. When init is kPreserve it is as though
+ * the inverse view matrix was passed. If kPreserve is passed and the draw state's matrix
+ * is not invertible then this may fail.
+ */
+ bool setIdentity(GrDrawTarget* target, ASRInit init);
private:
- GrDrawTarget* fDrawTarget;
- SkTLazy<GrDrawState> fTempState;
- GrDrawState* fSavedState;
+ GrDrawTarget* fDrawTarget;
+ SkTLazy<GrDrawState> fTempState;
+ GrDrawState* fSavedState;
};
////////////////////////////////////////////////////////////////////////////
@@ -586,8 +602,10 @@
*/
class AutoGeometryAndStatePush : ::GrNoncopyable {
public:
- AutoGeometryAndStatePush(GrDrawTarget* target, ASRInit init)
- : fState(target, init){
+ AutoGeometryAndStatePush(GrDrawTarget* target,
+ ASRInit init,
+ const SkMatrix* viewMatrix = NULL)
+ : fState(target, init, viewMatrix) {
GrAssert(NULL != target);
fTarget = target;
target->pushGeometrySource();
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index a0dce18..18b70dc 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -158,8 +158,8 @@
// When the caller has provided an explicit source rect for a stage then we don't want to
// modify that stage's matrix. Otherwise if the effect is generating its source rect from
// the vertex positions then we have to account for the view matrix change.
- GrDrawState::AutoDeviceCoordDraw adcd(drawState);
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(drawState)) {
return;
}
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index dd9b19e..70b5c77 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -331,8 +331,8 @@
SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width()));
SkScalar strokeWidth = vm.mapRadius(stroke.getWidth());
- GrDrawState::AutoDeviceCoordDraw adcd(drawState);
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(drawState)) {
return;
}
@@ -493,8 +493,8 @@
yRadius += scaledStroke.fY;
}
- GrDrawState::AutoDeviceCoordDraw adcd(drawState);
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(drawState)) {
return false;
}
@@ -650,8 +650,8 @@
// reset to device coordinates
GrDrawState* drawState = target->drawState();
- GrDrawState::AutoDeviceCoordDraw adcd(drawState);
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(drawState)) {
return false;
}
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 2cf56d6..fc34591 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -187,8 +187,8 @@
const GrIRect& rect) {
GrDrawState* drawState = target->drawState();
- GrDrawState::AutoDeviceCoordDraw adcd(drawState);
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(drawState)) {
return;
}
enum {
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 36bdcff..21adc62 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -82,8 +82,8 @@
void draw_around_inv_path(GrDrawTarget* target,
const GrIRect& devClipBounds,
const GrIRect& devPathBounds) {
- GrDrawState::AutoDeviceCoordDraw adcd(target->drawState());
- if (!adcd.succeeded()) {
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(target->drawState())) {
return;
}
GrRect rect;
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index fa87599..4f88acf 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -79,7 +79,7 @@
// fill the path, zero out the stencil
GrRect bounds = p->getBounds();
SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf;
- GrDrawState::AutoDeviceCoordDraw adcd;
+ GrDrawState::AutoViewMatrixRestore avmr;
if (nonInvertedFill == path.getFillType()) {
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
@@ -111,7 +111,7 @@
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
} else {
- adcd.set(drawState);
+ avmr.setIdentity(drawState);
bloat = 0;
}
*drawState->stencil() = kInvertedStencilPass;