Chromium Code Reviews| Index: src/gpu/GrDrawTarget.cpp |
| =================================================================== |
| --- src/gpu/GrDrawTarget.cpp (revision 8438) |
| +++ src/gpu/GrDrawTarget.cpp (working copy) |
| @@ -9,6 +9,7 @@ |
| #include "GrDrawTarget.h" |
| +#include "GrContext.h" |
| #include "GrDrawTargetCaps.h" |
| #include "GrRenderTarget.h" |
| #include "GrTexture.h" |
| @@ -38,6 +39,9 @@ |
| } else { |
| fDevBounds = NULL; |
| } |
| + |
| + fDstCopy = di.fDstCopy; |
| + |
| return *this; |
| } |
| @@ -402,6 +406,65 @@ |
| return true; |
| } |
| +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) { |
| + return true; |
| + } |
| + GrRenderTarget* rt = this->drawState()->getRenderTarget(); |
| + // If the dst is not a texture then we don't currently have a way of copying the |
| + // texture. TODO: make copying RT->Tex (or Surface->Surface) a GrDrawTarget operation that can |
| + // be built on top of GL/D3D APIs. |
| + if (NULL == rt->asTexture()) { |
| + GrPrintf("Reading Dst of non-texture render target is not currently supported.\n"); |
| + return false; |
| + } |
| + // TODO: Consider bounds of draw and bounds of clip |
| + |
| + GrDrawTarget::AutoGeometryAndStatePush agasp(this, kReset_ASRInit); |
| + |
| + // The draw will resolve dst if it has MSAA. Two things to consider in the future: |
| + // 1) to make the dst values be pre-resolve we'd need to be able to copy to MSAA |
| + // texture and sample it correctly in the shader. 2) If 1 isn't available then we |
| + // should just resolve and use the resolved texture directly rather than making a |
| + // copy of it. |
| + GrTextureDesc desc; |
| + desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; |
| + desc.fWidth = rt->width(); |
| + desc.fHeight = rt->height(); |
| + desc.fSampleCnt = 0; |
| + desc.fConfig = rt->config(); |
| + |
| + GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); |
| + |
| + if (NULL == ast.texture()) { |
| + GrPrintf("Failed to create temporary copy of destination texture.\n"); |
| + return false; |
| + } |
| + SkMatrix textureMatrix; |
| + textureMatrix.setIDiv(rt->width(), rt->height()); |
| + this->drawState()->disableState(GrDrawState::kClip_StateBit); |
| + this->drawState()->setRenderTarget(ast.texture()->asRenderTarget()); |
| + static const int kTextureStage = 0; |
| + SkMatrix matrix; |
| + matrix.setIDiv(rt->width(), rt->height()); |
| + this->drawState()->createTextureEffect(kTextureStage, rt->asTexture(), matrix); |
| + SkRect dstRect = SkRect::MakeWH(SkIntToScalar(desc.fWidth), |
| + SkIntToScalar(desc.fHeight)); |
| + SkRect srcRect = dstRect; |
| + this->drawRect(dstRect, NULL, &srcRect, NULL); |
| + info->fDstCopy.setTexture(ast.texture()); |
| + info->fDstCopy.setOffset(0, 0); |
| + return true; |
| +} |
| + |
| void GrDrawTarget::drawIndexed(GrPrimitiveType type, |
| int startVertex, |
| int startIndex, |
| @@ -423,6 +486,9 @@ |
| if (NULL != devBounds) { |
| info.setDevBounds(*devBounds); |
| } |
| + if (!this->setupDstReadIfNecessary(&info)) { |
| + return; |
|
jvanverth1
2013/03/29 18:46:22
Do we want to try to draw something here, even if
bsalomon
2013/03/29 18:59:39
We could... and probably should. I'll put a commen
|
| + } |
| this->onDraw(info); |
| } |
| } |
| @@ -446,6 +512,9 @@ |
| if (NULL != devBounds) { |
| info.setDevBounds(*devBounds); |
| } |
| + if (!this->setupDstReadIfNecessary(&info)) { |
| + return; |
| + } |
| this->onDraw(info); |
| } |
| } |
| @@ -508,6 +577,9 @@ |
| if (NULL != devBounds) { |
| info.setDevBounds(*devBounds); |
| } |
| + if (!this->setupDstReadIfNecessary(&info)) { |
| + return; |
| + } |
| while (instanceCount) { |
| info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw); |