diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-02-07 15:44:39 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-02-07 15:44:39 +0000 |
commit | aa6773557919fc9640e0873b7e87d4138aa2a6ad (patch) | |
tree | b879af478da55338e4c81c99c94d6c7faa1038b6 | |
parent | 0a9cc44a40a2bc101da1af89926152098ffcc44b (diff) |
Allow chrome to limit the number of FBO status checks
Review URL: https://codereview.appspot.com/5635052
git-svn-id: http://skia.googlecode.com/svn/trunk@3144 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/gpu/GrGLConfig.h | 33 | ||||
-rw-r--r-- | include/gpu/GrGLConfig_chrome.h | 3 | ||||
-rw-r--r-- | include/gpu/GrTypes.h | 2 | ||||
-rw-r--r-- | src/gpu/GrGpuGL.cpp | 155 | ||||
-rw-r--r-- | src/gpu/GrGpuGL.h | 40 |
5 files changed, 190 insertions, 43 deletions
diff --git a/include/gpu/GrGLConfig.h b/include/gpu/GrGLConfig.h index 167c8eb072..5ae931c607 100644 --- a/include/gpu/GrGLConfig.h +++ b/include/gpu/GrGLConfig.h @@ -92,50 +92,61 @@ * amounts to ensuring the error is GL_NO_ERROR, calling the allocating * function, and then checking that the error is still GL_NO_ERROR. When the * value is 0 we will assume no error was generated without checking. + * + * GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT: We will normally check the FBO status + * every time we bind a texture or renderbuffer to an FBO. However, in some + * environments CheckFrameBufferStatus is very expensive. If this is set we will + * check the first time we use a color format or a combination of color / + * stencil formats as attachments. If the FBO is complete we will assume + * subsequent attachments with the same formats are complete as well. */ #if !defined(GR_GL_LOG_CALLS) - #define GR_GL_LOG_CALLS GR_DEBUG + #define GR_GL_LOG_CALLS GR_DEBUG #endif #if !defined(GR_GL_LOG_CALLS_START) - #define GR_GL_LOG_CALLS_START 0 + #define GR_GL_LOG_CALLS_START 0 #endif #if !defined(GR_GL_CHECK_ERROR) - #define GR_GL_CHECK_ERROR GR_DEBUG + #define GR_GL_CHECK_ERROR GR_DEBUG #endif #if !defined(GR_GL_CHECK_ERROR_START) - #define GR_GL_CHECK_ERROR_START 1 + #define GR_GL_CHECK_ERROR_START 1 #endif #if !defined(GR_GL_NO_CONSTANT_ATTRIBUTES) - #define GR_GL_NO_CONSTANT_ATTRIBUTES 0 + #define GR_GL_NO_CONSTANT_ATTRIBUTES 0 #endif #if !defined(GR_GL_ATTRIBUTE_MATRICES) - #define GR_GL_ATTRIBUTE_MATRICES 0 + #define GR_GL_ATTRIBUTE_MATRICES 0 #endif #if !defined(GR_GL_USE_BUFFER_DATA_NULL_HINT) - #define GR_GL_USE_BUFFER_DATA_NULL_HINT 1 + #define GR_GL_USE_BUFFER_DATA_NULL_HINT 1 #endif #if !defined(GR_GL_PER_GL_FUNC_CALLBACK) - #define GR_GL_PER_GL_FUNC_CALLBACK 0 + #define GR_GL_PER_GL_FUNC_CALLBACK 0 #endif #if !defined(GR_GL_RGBA_8888_PIXEL_OPS_SLOW) - #define GR_GL_RGBA_8888_PIXEL_OPS_SLOW 0 + #define GR_GL_RGBA_8888_PIXEL_OPS_SLOW 0 #endif #if !defined(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL) - #define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL 0 + #define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL 0 #endif #if !defined(GR_GL_CHECK_ALLOC_WITH_GET_ERROR) - #define GR_GL_CHECK_ALLOC_WITH_GET_ERROR 1 + #define GR_GL_CHECK_ALLOC_WITH_GET_ERROR 1 +#endif + +#if !defined(GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT) + #define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT 0 #endif #if(GR_GL_NO_CONSTANT_ATTRIBUTES) && (GR_GL_ATTRIBUTE_MATRICES) diff --git a/include/gpu/GrGLConfig_chrome.h b/include/gpu/GrGLConfig_chrome.h index 2bae14579e..50ea34c6d3 100644 --- a/include/gpu/GrGLConfig_chrome.h +++ b/include/gpu/GrGLConfig_chrome.h @@ -31,4 +31,7 @@ // compositor also doesn't check its allocations. #define GR_GL_CHECK_ALLOC_WITH_GET_ERROR 0 +// CheckFramebufferStatus in chrome synchronizes the gpu and renderer processes. +#define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT 1 + #endif diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h index 9f245d944a..f6809d6ca4 100644 --- a/include/gpu/GrTypes.h +++ b/include/gpu/GrTypes.h @@ -301,6 +301,8 @@ enum GrPixelConfig { * Unpremultiplied. Byte order is b,g,r,a */ kBGRA_8888_UPM_GrPixelConfig, + + kGrPixelConfigCount }; // Aliases for pixel configs that match skia's byte order diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp index 70d28d6785..7d77a3f8b3 100644 --- a/src/gpu/GrGpuGL.cpp +++ b/src/gpu/GrGpuGL.cpp @@ -34,6 +34,78 @@ static const int SPARE_TEX_UNIT = GrDrawState::kNumStages; #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR #endif +/////////////////////////////////////////////////////////////////////////////// + +void GrGpuGL::GLCaps::markConfigAsValidColorAttachment(GrPixelConfig config) { +#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT + return; +#endif + GrAssert(config < kGrPixelConfigCount); + int u32Idx = config / 32; + int bitIdx = config % 32; + fVerifiedColorAttachmentConfigs[u32Idx] |= (1 << bitIdx); +} + +bool GrGpuGL::GLCaps::isConfigVerifiedColorAttachment( + GrPixelConfig config) const { +#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT + return false; +#endif + GrAssert((unsigned)config < kGrPixelConfigCount); + int u32Idx = config / 32; + int bitIdx = config % 32; + return SkToBool(fVerifiedColorAttachmentConfigs[u32Idx] & (1 << bitIdx)); +} + +void GrGpuGL::GLCaps::markColorConfigAndStencilFormatAsVerified( + GrPixelConfig config, + const GrGLStencilBuffer::Format& format) { +#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT + return; +#endif + GrAssert((unsigned)config < kGrPixelConfigCount); + int count = fStencilFormats.count(); + // we expect a really small number of possible formats so linear search + // should be OK + GrAssert(count < 16); + for (int i = 0; i < count; ++i) { + if (format.fInternalFormat == + fStencilFormats[i].fFormat.fInternalFormat) { + int u32Idx = config / 32; + int bitIdx = config % 32; + fStencilFormats[i].fVerifiedColorConfigs[u32Idx] |= (1 << bitIdx); + return; + } + } + SkDEBUGFAIL("Why are we seeing a stencil format that GLCaps doesn't know about."); +} + +bool GrGpuGL::GLCaps::isColorConfigAndStencilFormatVerified( + GrPixelConfig config, + const GrGLStencilBuffer::Format& format) const { +#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT + return false; +#endif + GrAssert((unsigned)config < kGrPixelConfigCount); + int count = fStencilFormats.count(); + // we expect a really small number of possible formats so linear search + // should be OK + GrAssert(count < 16); + for (int i = 0; i < count; ++i) { + if (format.fInternalFormat == + fStencilFormats[i].fFormat.fInternalFormat) { + int u32Idx = config / 32; + int bitIdx = config % 32; + return SkToBool(fStencilFormats[i].fVerifiedColorConfigs[u32Idx] & + (1 << bitIdx)); + } + } + SkDEBUGFAIL("Why are we seeing a stencil format that GLCaps doesn't know about."); + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + static const GrGLenum gXfermodeCoeff2Blend[] = { GR_GL_ZERO, GR_GL_ONE, @@ -402,14 +474,16 @@ void GrGpuGL::initStencilFormats() { // these consts are in order of most preferred to least preferred // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8 - static const GrGLStencilBuffer::Format + + // Omitting fVerifiedColorConfigs from initializer list should init to 0. + static const GLCaps::StencilFormat // internal Format stencil bits total bits packed? - gS8 = {GR_GL_STENCIL_INDEX8, 8, 8, false}, - gS16 = {GR_GL_STENCIL_INDEX16, 16, 16, false}, - gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, 32, true }, - gS4 = {GR_GL_STENCIL_INDEX4, 4, 4, false}, - gS = {GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false}, - gDS = {GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true }; + gS8 = {{GR_GL_STENCIL_INDEX8, 8, 8, false}}, + gS16 = {{GR_GL_STENCIL_INDEX16, 16, 16, false}}, + gD24S8 = {{GR_GL_DEPTH24_STENCIL8, 8, 32, true }}, + gS4 = {{GR_GL_STENCIL_INDEX4, 4, 4, false}}, + gS = {{GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false}}, + gDS = {{GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true }}; if (kDesktop_GrGLBinding == this->glBinding()) { bool supportsPackedDS = fGLVersion >= GR_GL_VER(3,0) || @@ -442,6 +516,17 @@ void GrGpuGL::initStencilFormats() { fGLCaps.fStencilFormats.push_back() = gS4; } } +#if GR_DEBUG + // ensure that initially all color / stencil format combos have unverified + // fbo status. + for (int i = 0; i < fGLCaps.fStencilFormats.count(); ++i) { + int numU32 = + GR_ARRAY_COUNT(fGLCaps.fStencilFormats[i].fVerifiedColorConfigs); + for (int j = 0; j < numU32; ++j) { + GrAssert(0 == fGLCaps.fStencilFormats[i].fVerifiedColorConfigs); + } + } +#endif } GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const { @@ -910,9 +995,12 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER, desc->fMSColorRenderbufferID)); - GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); - if (status != GR_GL_FRAMEBUFFER_COMPLETE) { - goto FAILED; + if (!fGLCaps.isConfigVerifiedColorAttachment(desc->fConfig)) { + GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { + goto FAILED; + } + fGLCaps.markConfigAsValidColorAttachment(desc->fConfig); } } GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID)); @@ -921,9 +1009,12 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D, texID, 0)); - GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); - if (status != GR_GL_FRAMEBUFFER_COMPLETE) { - goto FAILED; + if (!fGLCaps.isConfigVerifiedColorAttachment(desc->fConfig)) { + GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { + goto FAILED; + } + fGLCaps.markConfigAsValidColorAttachment(desc->fConfig); } return true; @@ -1115,7 +1206,7 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt, // that we won't go through this loop more than once after the // first (painful) stencil creation. int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt; - const GrGLStencilBuffer::Format& sFmt = fGLCaps.fStencilFormats[sIdx]; + const GLCaps::StencilFormat& sFmt = fGLCaps.fStencilFormats[sIdx]; CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); // we do this "if" so that we don't call the multisample // version on a GL that doesn't have an MSAA extension. @@ -1123,12 +1214,12 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt, GL_ALLOC_CALL(this->glInterface(), RenderbufferStorageMultisample(GR_GL_RENDERBUFFER, samples, - sFmt.fInternalFormat, + sFmt.fFormat.fInternalFormat, width, height)); } else { GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER, - sFmt.fInternalFormat, + sFmt.fFormat.fInternalFormat, width, height)); } @@ -1136,7 +1227,7 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt, if (err == GR_GL_NO_ERROR) { // After sized formats we attempt an unsized format and take whatever // sizes GL gives us. In that case we query for the size. - GrGLStencilBuffer::Format format = sFmt; + GrGLStencilBuffer::Format format = sFmt.fFormat; get_stencil_rb_sizes(this->glInterface(), sbID, &format); sb = new GrGLStencilBuffer(this, sbID, width, height, samples, format); @@ -1195,20 +1286,26 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, } GrGLenum status; - GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); - if (status != GR_GL_FRAMEBUFFER_COMPLETE) { - GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, - GR_GL_STENCIL_ATTACHMENT, - GR_GL_RENDERBUFFER, 0)); - if (glsb->format().fPacked) { + if (!fGLCaps.isColorConfigAndStencilFormatVerified(rt->config(), + glsb->format())) { + GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, - GR_GL_DEPTH_ATTACHMENT, + GR_GL_STENCIL_ATTACHMENT, GR_GL_RENDERBUFFER, 0)); + if (glsb->format().fPacked) { + GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, + GR_GL_DEPTH_ATTACHMENT, + GR_GL_RENDERBUFFER, 0)); + } + return false; + } else { + fGLCaps.markColorConfigAndStencilFormatAsVerified( + rt->config(), + glsb->format()); } - return false; - } else { - return true; } + return true; } } @@ -2430,8 +2527,8 @@ void GrGpuGL::GLCaps::print() const { for (int i = 0; i < fStencilFormats.count(); ++i) { GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n", i, - fStencilFormats[i].fStencilBits, - fStencilFormats[i].fTotalBits); + fStencilFormats[i].fFormat.fStencilBits, + fStencilFormats[i].fFormat.fTotalBits); } GR_STATIC_ASSERT(0 == kNone_MSFBO); diff --git a/src/gpu/GrGpuGL.h b/src/gpu/GrGpuGL.h index 6ac48090c1..e11143289f 100644 --- a/src/gpu/GrGpuGL.h +++ b/src/gpu/GrGpuGL.h @@ -61,8 +61,41 @@ protected: , fPackFlipYSupport(false) , fTextureUsageSupport(false) , fTexStorageSupport(false) { + memset(&fVerifiedColorAttachmentConfigs, 0, + sizeof(fVerifiedColorAttachmentConfigs)); } - SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats; + + // Call to note that a color config has been verified as a valid + // color attachment. This may save future calls to + // CheckFramebufferStatus + void markConfigAsValidColorAttachment(GrPixelConfig config); + + // Call to check whether a config has been verified as a valid color + // attachment. + bool isConfigVerifiedColorAttachment(GrPixelConfig config) const; + + // Call to note that a color config / stencil format pair passed + // FBO status check. We may skip calling CheckFramebufferStatus for + // this combination in the future. + void markColorConfigAndStencilFormatAsVerified( + GrPixelConfig config, + const GrGLStencilBuffer::Format& format); + + // Call to check whether color config / stencil format pair has already + // passed FBO status check. + bool isColorConfigAndStencilFormatVerified( + GrPixelConfig config, + const GrGLStencilBuffer::Format& format) const; + + void print() const; + + struct StencilFormat { + GrGLStencilBuffer::Format fFormat; + uint32_t fVerifiedColorConfigs[(kGrPixelConfigCount + 31) / 32]; + }; + + SkTArray<StencilFormat, true> fStencilFormats; + enum { /** @@ -118,9 +151,10 @@ protected: // Is there support for glTexStorage bool fTexStorageSupport; - void print() const; + private: + uint32_t fVerifiedColorAttachmentConfigs[(kGrPixelConfigCount + 31) / 32]; } fGLCaps; - + struct { size_t fVertexOffset; GrVertexLayout fVertexLayout; |