From 75f9f25d8bf2adc0494f9afbbd5965809ee13aca Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Tue, 31 Jan 2012 13:35:56 +0000 Subject: Add code path for Gr client to resolve an Gr-created MSAA render target. Review URL: http://codereview.appspot.com/5580049/ git-svn-id: http://skia.googlecode.com/svn/trunk@3112 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/gpu/GrContext.h | 14 ++++++++++++++ include/gpu/GrRenderTarget.h | 8 ++++++++ src/gpu/GrContext.cpp | 10 ++++++++++ src/gpu/GrGpu.cpp | 7 +++++++ src/gpu/GrGpu.h | 8 ++++++++ src/gpu/GrGpuGL.cpp | 8 +++++--- src/gpu/GrGpuGL.h | 6 ++++-- src/gpu/GrRenderTarget.cpp | 9 +++++++++ src/gpu/SkGpuDevice.cpp | 2 +- 9 files changed, 66 insertions(+), 6 deletions(-) diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index ca440a6243..3fb47750cf 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -562,6 +562,20 @@ public: * @param dst the render target to copy to. */ void copyTexture(GrTexture* src, GrRenderTarget* dst); + + /** + * Resolves a render target that has MSAA. The intermediate MSAA buffer is + * downsampled to the associated GrTexture (accessible via + * GrRenderTarget::asTexture()). Any pending draws to the render target will + * be executed before the resolve. + * + * This is only necessary when a client wants to access the object directly + * using the underlying graphics API. GrContext will detect when it must + * perform a resolve to a GrTexture used as the source of a draw or before + * reading pixels back from a GrTexture or GrRenderTarget. + */ + void resolveRenderTarget(GrRenderTarget* target); + /** * Applies a 1D convolution kernel in the X direction to a rectangle of * pixels from a given texture. diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h index 13b2160f79..909adb3e7d 100644 --- a/include/gpu/GrRenderTarget.h +++ b/include/gpu/GrRenderTarget.h @@ -112,6 +112,14 @@ public: */ const GrIRect& getResolveRect() const { return fResolveRect; } + /** + * If the render target is multisampled this will perform a multisample + * resolve. Any pending draws to the target are first flushed. This only + * applies to render targets that are associated with GrTextures. After the + * function returns the GrTexture will contain the resolved pixels. + */ + void resolve(); + // GrResource overrides virtual size_t sizeInBytes() const; diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 1e87cab35e..dd1b276806 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1900,6 +1900,16 @@ bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target, config, buffer, rowBytes, flipY); } +void GrContext::resolveRenderTarget(GrRenderTarget* target) { + GrAssert(target); + ASSERT_OWNED_RESOURCE(target); + // In the future we may track whether there are any pending draws to this + // target. We don't today so we always perform a flush. We don't promise + // this to our clients, though. + this->flush(); + fGpu->resolveRenderTarget(target); +} + void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) { if (NULL == src || NULL == dst) { return; diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 27a4497e7b..39960de054 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -260,6 +260,13 @@ void GrGpu::writeTexturePixels(GrTexture* texture, config, buffer, rowBytes); } +void GrGpu::resolveRenderTarget(GrRenderTarget* target) { + GrAssert(target); + this->handleDirtyContext(); + this->onResolveRenderTarget(target); +} + + //////////////////////////////////////////////////////////////////////////////// static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1; diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 8c23daa2f0..e617efb8e4 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -171,6 +171,11 @@ public: */ const GrVertexBuffer* getUnitSquareVertexBuffer() const; + /** + * Resolves MSAA. + */ + void resolveRenderTarget(GrRenderTarget* target); + /** * Ensures that the current render target is actually set in the * underlying 3D API. Used when client wants to use 3D API to directly @@ -433,6 +438,9 @@ protected: GrPixelConfig config, const void* buffer, size_t rowBytes) = 0; + // overridden by API-specific derived class to perform the resolve + virtual void onResolveRenderTarget(GrRenderTarget* target) = 0; + // called to program the vertex data, indexCount will be 0 if drawing non- // indexed geometry. The subclass may adjust the startVertex and/or // startIndex since it may have already accounted for these in the setup. diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp index a4a49ac59b..70d28d6785 100644 --- a/src/gpu/GrGpuGL.cpp +++ b/src/gpu/GrGpuGL.cpp @@ -1452,7 +1452,7 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, this->flushRenderTarget(&GrIRect::EmptyIRect()); break; case GrGLRenderTarget::kCanResolve_ResolveType: - this->resolveRenderTarget(tgt); + this->onResolveRenderTarget(tgt); // we don't track the state of the READ FBO ID. GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID())); @@ -1666,7 +1666,9 @@ void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type, #endif } -void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) { +void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { + + GrGLRenderTarget* rt = static_cast(target); if (rt->needsResolve()) { GrAssert(GLCaps::kNone_MSFBO != fGLCaps.fMSFBOType); @@ -2050,7 +2052,7 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { GrGLRenderTarget* texRT = static_cast(nextTexture->asRenderTarget()); if (NULL != texRT) { - resolveRenderTarget(texRT); + this->onResolveRenderTarget(texRT); } if (fHWDrawState.getTexture(s) != nextTexture) { diff --git a/src/gpu/GrGpuGL.h b/src/gpu/GrGpuGL.h index 3196c89c47..6ac48090c1 100644 --- a/src/gpu/GrGpuGL.h +++ b/src/gpu/GrGpuGL.h @@ -41,6 +41,7 @@ public: GrPixelConfig config, size_t rowBytes) const SK_OVERRIDE; virtual bool fullReadPixelsIsFasterThanPartial() const SK_OVERRIDE; + protected: GrGpuGL(const GrGLInterface* glInterface, GrGLBinding glBinding); @@ -193,6 +194,9 @@ protected: GrPixelConfig config, const void* buffer, size_t rowBytes) SK_OVERRIDE; + virtual void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE; + + virtual void onGpuDrawIndexed(GrPrimitiveType type, uint32_t startVertex, uint32_t startIndex, @@ -276,8 +280,6 @@ private: void flushStencil(); void flushAAState(GrPrimitiveType type); - void resolveRenderTarget(GrGLRenderTarget* texture); - bool configToGLFormats(GrPixelConfig config, bool getSizedInternal, GrGLenum* internalFormat, diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp index 7901648d3a..ed1a018a02 100644 --- a/src/gpu/GrRenderTarget.cpp +++ b/src/gpu/GrRenderTarget.cpp @@ -41,6 +41,15 @@ void GrRenderTarget::writePixels(int left, int top, int width, int height, config, buffer, rowBytes); } +void GrRenderTarget::resolve() { + // go through context so that all necessary flushing occurs + GrContext* context = this->getContext(); + if (NULL == context) { + return; + } + context->resolveRenderTarget(this); +} + size_t GrRenderTarget::sizeInBytes() const { int colorBits; if (kUnknown_GrPixelConfig == fConfig) { diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index d34ef6a194..da97fde820 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1769,7 +1769,7 @@ bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { } void SkGpuDevice::flush() { - fContext->flush(false); + fContext->resolveRenderTarget(fRenderTarget); } /////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3