diff options
-rw-r--r-- | include/core/SkTLazy.h | 10 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 12 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 50 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.h | 9 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 29 |
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(), ©Rect); + 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, ©Rect, 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, |