From 99a5ac0b67a14048a1db3f429878775854d29397 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Tue, 10 Apr 2012 19:26:38 +0000 Subject: [PATCH] Updated blur to use A8/R8 (instead of RGBA8) when available - this provides a performance gain for large blurs http://codereview.appspot.com/5988071/ git-svn-id: http://skia.googlecode.com/svn/trunk@3647 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/gpu/GrContext.h | 5 +++ src/gpu/GrContext.cpp | 22 +++++++++++--- src/gpu/GrGpu.cpp | 4 +++ src/gpu/GrGpu.h | 12 ++++++++ src/gpu/SkGpuDevice.cpp | 8 +++-- src/gpu/gl/GrGLCaps.cpp | 2 +- src/gpu/gl/GrGpuGL.cpp | 67 +++++++++++++++++++++++++++++++++++++++++ src/gpu/gl/GrGpuGL.h | 2 ++ 8 files changed, 115 insertions(+), 7 deletions(-) diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index bed2d990c4..433c113a04 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -274,6 +274,11 @@ public: const GrRenderTarget* getRenderTarget() const; GrRenderTarget* getRenderTarget(); + /** + * Can the provided configuration act as a color render target? + */ + bool isConfigRenderable(GrPixelConfig config) const; + /////////////////////////////////////////////////////////////////////////// // Platform Surfaces diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index f044909452..3fb944b6ce 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1989,6 +1989,10 @@ const GrRenderTarget* GrContext::getRenderTarget() const { return fDrawState->getRenderTarget(); } +bool GrContext::isConfigRenderable(GrPixelConfig config) const { + return fGpu->isConfigRenderable(config); +} + const GrMatrix& GrContext::getMatrix() const { return fDrawState->getViewMatrix(); } @@ -2112,16 +2116,22 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, static_cast(scaleFactorY)); this->setClip(srcRect); + GrAssert(kBGRA_8888_PM_GrPixelConfig == srcTexture->config() || + kRGBA_8888_PM_GrPixelConfig == srcTexture->config() || + kAlpha_8_GrPixelConfig == srcTexture->config()); + const GrTextureDesc desc = { kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit, SkScalarFloorToInt(srcRect.width()), SkScalarFloorToInt(srcRect.height()), - kRGBA_8888_PM_GrPixelConfig, + srcTexture->config(), 0 // samples }; temp1->set(this, desc); - if (temp2) temp2->set(this, desc); + if (temp2) { + temp2->set(this, desc); + } GrTexture* dstTexture = temp1->texture(); GrPaint paint; @@ -2160,7 +2170,9 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, convolve(fGpu, srcTexture, srcRect, kernelX, kernelWidthX, GrSamplerState::kX_FilterDirection); SkTSwap(srcTexture, dstTexture); - if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture(); + if (temp2 && dstTexture == origTexture) { + dstTexture = temp2->texture(); + } } if (sigmaY > 0.0f) { @@ -2180,7 +2192,9 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, convolve(fGpu, srcTexture, srcRect, kernelY, kernelWidthY, GrSamplerState::kY_FilterDirection); SkTSwap(srcTexture, dstTexture); - if (temp2 && dstTexture == origTexture) dstTexture = temp2->texture(); + if (temp2 && dstTexture == origTexture) { + dstTexture = temp2->texture(); + } } if (scaleFactorX > 1 || scaleFactorY > 1) { diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index aeb104c6ae..57e73c4226 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -57,6 +57,10 @@ GrGpu::GrGpu() poolState.fPoolStartIndex = DEBUG_INVAL_START_IDX; #endif resetStats(); + + for (int i = 0; i < kGrPixelConfigCount; ++i) { + fConfigRenderSupport[i] = false; + }; } GrGpu::~GrGpu() { diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 52282ed7aa..4a986b17ab 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -333,6 +333,14 @@ public: return fResetTimestamp; } + /** + * Can the provided configuration act as a color render target? + */ + bool isConfigRenderable(GrPixelConfig config) const { + GrAssert(kGrPixelConfigCount > config); + return fConfigRenderSupport[config]; + } + protected: enum PrivateDrawStateStateBits { kFirstBit = (GrDrawState::kLastPublicStateBit << 1), @@ -377,6 +385,10 @@ protected: return fGeomPoolStateStack.back(); } + // Derived classes need access to this so they can fill it out in their + // constructors + bool fConfigRenderSupport[kGrPixelConfigCount]; + // GrDrawTarget overrides virtual bool onReserveVertexSpace(GrVertexLayout vertexLayout, int vertexCount, diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index cf05284740..bb088b2e39 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -788,16 +788,20 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path, } GrPoint offset = GrPoint::Make(-srcRect.fLeft, -srcRect.fTop); srcRect.offset(offset); - const GrTextureDesc desc = { + GrTextureDesc desc = { kRenderTarget_GrTextureFlagBit, SkScalarCeilToInt(srcRect.width()), SkScalarCeilToInt(srcRect.height()), // We actually only need A8, but it often isn't supported as a - // render target + // render target so default to RGBA_8888 kRGBA_8888_PM_GrPixelConfig, 0 // samples }; + if (context->isConfigRenderable(kAlpha_8_GrPixelConfig)) { + desc.fConfig = kAlpha_8_GrPixelConfig; + } + GrAutoScratchTexture pathEntry(context, desc); GrTexture* pathTexture = pathEntry.texture(); if (NULL == pathTexture) { diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 8b14a1b678..53619672d6 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -136,7 +136,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo) { fTextureRedSupport = version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_ARB_texture_rg"); } else { - fTextureRedSupport = ctxInfo.hasExtension("GL_ARB_texture_rg"); + fTextureRedSupport = ctxInfo.hasExtension("GL_EXT_texture_rg"); } this->initFSAASupport(ctxInfo); diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 8481b74ab4..dcde84e6b2 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -181,6 +181,8 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { GrAssert(ctxInfo.isInitialized()); + fillInConfigRenderableTable(); + fPrintedCaps = false; GrGLClearErr(fGLContextInfo.interface()); @@ -293,6 +295,71 @@ void GrGpuGL::initCaps() { fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType(); } +void GrGpuGL::fillInConfigRenderableTable() { + + // OpenGL < 3.0 + // no support for render targets unless the GL_ARB_framebuffer_object + // extension is supported (in which case we get ALPHA, RED, RG, RGB, + // RGBA (ALPHA8, RGBA4, RGBA8) for OpenGL > 1.1). Note that we + // probably don't get R8 in this case. + + // OpenGL 3.0 + // base color renderable: ALPHA, RED, RG, RGB, and RGBA + // sized derivatives: ALPHA8, R8, RGBA4, RGBA8 + + // >= OpenGL 3.1 + // base color renderable: RED, RG, RGB, and RGBA + // sized derivatives: R8, RGBA4, RGBA8 + // if the GL_ARB_compatibility extension is supported then we get back + // support for GL_ALPHA and ALPHA8 + + // GL_EXT_bgra adds BGRA render targets to any version + + // ES 2.0 + // color renderable: RGBA4, RGB5_A1, RGB565 + // GL_EXT_texture_rg adds support for R8 as a color render target + // GL_OES_rgb8_rgba8 and/or GL_ARM_rgba8 adds support for RGBA8 + // GL_EXT_texture_format_BGRA8888 and/or GL_APPLE_texture_format_BGRA8888 + // added BGRA support + + if (kDesktop_GrGLBinding == this->glBinding()) { + // Post 3.0 we will get R8 + // Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object) + if (this->glVersion() >= GR_GL_VER(3,0) || + this->hasExtension("GL_ARB_framebuffer_object")) { + fConfigRenderSupport[kAlpha_8_GrPixelConfig] = true; + } + } else { + // On ES we can only hope for R8 + fConfigRenderSupport[kAlpha_8_GrPixelConfig] = + this->glCaps().textureRedSupport(); + } + + if (kDesktop_GrGLBinding != this->glBinding()) { + // only available in ES + fConfigRenderSupport[kRGB_565_GrPixelConfig] = true; + } + + // Pre 3.0, Ganesh relies on either GL_ARB_framebuffer_object or + // GL_EXT_framebuffer_object for FBO support. Both of these + // allow RGBA4 render targets so this is always supported. + fConfigRenderSupport[kRGBA_4444_GrPixelConfig] = true; + + if (this->glCaps().rgba8RenderbufferSupport()) { + fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig] = true; + } + + if (this->glCaps().bgraFormatSupport()) { + fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig] = true; + } + + // the un-premultiplied formats just inherit the premultiplied setting + fConfigRenderSupport[kRGBA_8888_UPM_GrPixelConfig] = + fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig]; + fConfigRenderSupport[kBGRA_8888_UPM_GrPixelConfig] = + fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig]; +} + bool GrGpuGL::canPreserveReadWriteUnpremulPixels() { if (kUnknown_CanPreserveUnpremulRoundtrip == fCanPreserveUnpremulRoundtrip) { diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 398a2fc8e8..928b50e876 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -233,6 +233,8 @@ private: GrGLuint texID, GrGLRenderTarget::Desc* desc); + void fillInConfigRenderableTable(); + friend class GrGLVertexBuffer; friend class GrGLIndexBuffer; friend class GrGLTexture;