aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkTLazy.h10
-rw-r--r--src/gpu/GrDrawState.h12
-rw-r--r--src/gpu/GrDrawTarget.cpp50
-rw-r--r--src/gpu/GrDrawTarget.h9
-rw-r--r--src/gpu/GrOvalRenderer.cpp29
5 files changed, 75 insertions, 35 deletions
diff --git a/include/core/SkTLazy.h b/include/core/SkTLazy.h
index 2fe05f1db1..0daf98caa7 100644
--- a/include/core/SkTLazy.h
+++ b/include/core/SkTLazy.h
@@ -81,10 +81,16 @@ public:
bool isValid() const { return NULL != fPtr; }
/**
- * Returns either NULL, or a copy of the object that was passed to
- * set() or the constructor.
+ * Returns the object. This version should only be called when the caller
+ * knows that the object has been initialized.
*/
T* get() const { SkASSERT(this->isValid()); return fPtr; }
+
+ /**
+ * Like above but doesn't assert if object isn't initialized (in which case
+ * NULL is returned).
+ */
+ T* getMaybeNull() const { return fPtr; }
private:
friend void* operator new<T>(size_t, SkTLazy* lazy);
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 002c4ede34..d16efa893c 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -507,6 +507,18 @@ public:
}
}
}
+
+ /**
+ * Checks whether any of the effects will read the dst pixel color.
+ */
+ bool willEffectReadDst() const {
+ for (int s = 0; s < kNumStages; ++s) {
+ if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDst()) {
+ return true;
+ }
+ }
+ return false;
+ }
/// @}
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 4d4ba49dff..bc7d39e573 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -407,15 +407,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
}
bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) {
- bool willReadDst = false;
- for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- const GrEffectRef* effect = this->drawState()->getStage(s).getEffect();
- if (NULL != effect && (*effect)->willReadDst()) {
- willReadDst = true;
- break;
- }
- }
- if (!willReadDst) {
+ if (!this->getDrawState().willEffectReadDst()) {
return true;
}
GrRenderTarget* rt = this->drawState()->getRenderTarget();
@@ -426,8 +418,24 @@ bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) {
GrPrintf("Reading Dst of non-texture render target is not currently supported.\n");
return false;
}
- // TODO: Consider bounds of draw and bounds of clip
+ const GrClipData* clip = this->getClip();
+ GrIRect copyRect;
+ clip->getConservativeBounds(this->getDrawState().getRenderTarget(), &copyRect);
+ SkIRect drawIBounds;
+ if (info->getDevIBounds(&drawIBounds)) {
+ if (!copyRect.intersect(drawIBounds)) {
+#if GR_DEBUG
+ GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
+#endif
+ return false;
+ }
+ } else {
+#if GR_DEBUG
+ //GrPrintf("No dev bounds when dst copy is made.\n");
+#endif
+ }
+
GrDrawTarget::AutoGeometryAndStatePush agasp(this, kReset_ASRInit);
// The draw will resolve dst if it has MSAA. Two things to consider in the future:
@@ -437,8 +445,8 @@ bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) {
// copy of it.
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- desc.fWidth = rt->width();
- desc.fHeight = rt->height();
+ desc.fWidth = copyRect.width();
+ desc.fHeight = copyRect.height();
desc.fSampleCnt = 0;
desc.fConfig = rt->config();
@@ -454,11 +462,14 @@ bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) {
SkMatrix matrix;
matrix.setIDiv(rt->width(), rt->height());
this->drawState()->createTextureEffect(kTextureStage, rt->asTexture(), matrix);
- SkRect copyRect = SkRect::MakeWH(SkIntToScalar(desc.fWidth),
- SkIntToScalar(desc.fHeight));
- this->drawRect(copyRect, NULL, &copyRect, NULL);
+
+ SkRect srcRect = SkRect::MakeFromIRect(copyRect);
+ SkRect dstRect = SkRect::MakeWH(SkIntToScalar(copyRect.width()),
+ SkIntToScalar(copyRect.height()));
+ this->drawRect(dstRect, NULL, &srcRect, NULL);
+
info->fDstCopy.setTexture(ast.texture());
- info->fDstCopy.setOffset(0, 0);
+ info->fDstCopy.setOffset(copyRect.fLeft, copyRect.fTop);
return true;
}
@@ -645,8 +656,13 @@ void GrDrawTarget::drawRect(const GrRect& rect,
localMatrix->mapPointsWithStride(coords, vsize, 4);
}
}
+ SkTLazy<SkRect> bounds;
+ if (this->getDrawState().willEffectReadDst()) {
+ bounds.init();
+ this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect);
+ }
- this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
+ this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, bounds.getMaybeNull());
}
void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 737ce8637d..df3f31bbc8 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -654,6 +654,15 @@ protected:
fDevBounds = &fDevBoundsStorage;
}
const SkRect* getDevBounds() const { return fDevBounds; }
+
+ bool getDevIBounds(SkIRect* bounds) const {
+ if (NULL != fDevBounds) {
+ fDevBounds->roundOut(bounds);
+ return true;
+ } else {
+ return false;
+ }
+ }
// NULL if no copy of the dst is needed for the draw.
const GrDeviceCoordTexture* getDstCopy() const {
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index 2d25d54ce5..7da89bd245 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -136,24 +136,21 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
verts[i].fInnerRadius = innerRadius - 0.5f;
}
- SkScalar L = -outerRadius;
- SkScalar R = +outerRadius;
- SkScalar T = -outerRadius;
- SkScalar B = +outerRadius;
-
// We've extended the outer radius out half a pixel to antialias.
// Expand the drawn rect here so all the pixels will be captured.
- L += center.fX - SK_ScalarHalf;
- R += center.fX + SK_ScalarHalf;
- T += center.fY - SK_ScalarHalf;
- B += center.fY + SK_ScalarHalf;
-
- verts[0].fPos = SkPoint::Make(L, T);
- verts[1].fPos = SkPoint::Make(R, T);
- verts[2].fPos = SkPoint::Make(L, B);
- verts[3].fPos = SkPoint::Make(R, B);
-
- target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
+ SkRect bounds = SkRect::MakeLTRB(
+ center.fX - outerRadius - SK_ScalarHalf,
+ center.fY - outerRadius - SK_ScalarHalf,
+ center.fX + outerRadius + SK_ScalarHalf,
+ center.fY + outerRadius + SK_ScalarHalf
+ );
+
+ verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
+ verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
+ verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
+ verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
+
+ target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
}
void GrOvalRenderer::drawEllipse(GrDrawTarget* target,