From 2c17fcdc45f9fa9a2dc785786347040fbe30928b Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Wed, 6 Jul 2011 17:47:02 +0000 Subject: Reduce gets of ext string and check validity of stencil format enums Review URL: http://codereview.appspot.com/4678043/ git-svn-id: http://skia.googlecode.com/svn/trunk@1801 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gpu/include/GrGLInterface.h | 5 +- gpu/src/GrGLInterface.cpp | 26 +++++++- gpu/src/GrGpuGL.cpp | 144 +++++++++++++++++++++++++------------------- gpu/src/GrGpuGL.h | 23 +++++++ gpu/src/GrGpuGLShaders.cpp | 8 +-- 5 files changed, 138 insertions(+), 68 deletions(-) diff --git a/gpu/include/GrGLInterface.h b/gpu/include/GrGLInterface.h index e3942cd203..42ff0c8a2c 100644 --- a/gpu/include/GrGLInterface.h +++ b/gpu/include/GrGLInterface.h @@ -31,14 +31,17 @@ * Helpers for glGetString() */ +// these variants assume caller already has a string from glGetString() void gl_version_from_string(int* major, int* minor, const char* versionString); +float gl_version_as_float_from_string(const char* versionString); bool has_gl_extension_from_string(const char* ext, const char* extensionString); +// these variants call glGetString() bool has_gl_extension(const char* ext); void gl_version(int* major, int* minor); - +float gl_version_as_float(); //////////////////////////////////////////////////////////////////////////////// diff --git a/gpu/src/GrGLInterface.cpp b/gpu/src/GrGLInterface.cpp index 5ecf8eb591..2237474f97 100644 --- a/gpu/src/GrGLInterface.cpp +++ b/gpu/src/GrGLInterface.cpp @@ -54,6 +54,25 @@ void gl_version_from_string(int* major, int* minor, } } +float gl_version_as_float_from_string(const char* versionString) { + int major, minor; + gl_version_from_string(&major, &minor, versionString); + GrAssert(minor >= 0); + // AFAIK there are only single digit minor numbers + if (minor < 10) { + return major + minor / 10.f; + } else if (minor < 100) { + return major + minor / 100.f; + } else if (minor < 1000) { + return major + minor / 1000.f; + } else { + GrAssert(!"Why so many digits in minor revision number?"); + char temp[32]; + sprintf(temp, "%d.%d", major, minor); + return (float) atof(temp); + } +} + bool has_gl_extension_from_string(const char* ext, const char* extensionString) { int extLength = strlen(ext); @@ -72,7 +91,6 @@ bool has_gl_extension_from_string(const char* ext, return false; } - GR_API void GrGLSetGLInterface(GrGLInterface* gl_interface) { gGLInterface = gl_interface; } @@ -94,6 +112,12 @@ void gl_version(int* major, int* minor) { gl_version_from_string(major, minor, v); } +float gl_version_as_float() { + const char* v = reinterpret_cast( + GrGLGetGLInterface()->fGetString(GR_GL_VERSION)); + return gl_version_as_float_from_string(v); +} + bool GrGLInterface::validateShaderFunctions() const { // required for GrGpuGLShaders if (NULL == fAttachShader || diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp index fe51875bb9..1f9afdcb5d 100644 --- a/gpu/src/GrGpuGL.cpp +++ b/gpu/src/GrGpuGL.cpp @@ -262,7 +262,10 @@ static int probe_for_min_render_target_width(bool hasNPOTRenderTargetSupport, } -GrGpuGL::GrGpuGL() { +GrGpuGL::GrGpuGL() + : fStencilFormats(8) { + + GrGLClearErr(); if (gPrintStartupSpew) { GrPrintf("------------------------- create GrGpuGL %p --------------\n", @@ -277,9 +280,10 @@ GrGpuGL::GrGpuGL() { GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS)); } - GrGLClearErr(); + fGLVersion = gl_version_as_float(); + fExtensionString = (const char*) GR_GL(GetString(GR_GL_EXTENSIONS)); - resetDirtyFlags(); + this->resetDirtyFlags(); GrGLint maxTextureUnits; // check FS and fixed-function texture unit limits @@ -307,8 +311,7 @@ GrGpuGL::GrGpuGL() { //////////////////////////////////////////////////////////////////////////// // Check for supported features. - int major, minor; - gl_version(&major, &minor); + this->setupStencilFormats(); GrGLint numFormats; GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); @@ -333,19 +336,19 @@ GrGpuGL::GrGpuGL() { memset(fAASamples, 0, sizeof(fAASamples)); fMSFBOType = kNone_MSFBO; if (GR_GL_SUPPORT_ES) { - if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) { + if (this->hasExtension("GL_CHROMIUM_framebuffer_multisample")) { // chrome's extension is equivalent to the EXT msaa // and fbo_blit extensions. fMSFBOType = kDesktopEXT_MSFBO; - } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) { + } else if (this->hasExtension("GL_APPLE_framebuffer_multisample")) { fMSFBOType = kAppleES_MSFBO; } } else { GrAssert(GR_GL_SUPPORT_DESKTOP); - if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) { + if ((fGLVersion >= 3.f) || this->hasExtension("GL_ARB_framebuffer_object")) { fMSFBOType = kDesktopARB_MSFBO; - } else if (has_gl_extension("GL_EXT_framebuffer_multisample") && - has_gl_extension("GL_EXT_framebuffer_blit")) { + } else if (this->hasExtension("GL_EXT_framebuffer_multisample") && + this->hasExtension("GL_EXT_framebuffer_blit")) { fMSFBOType = kDesktopEXT_MSFBO; } } @@ -386,10 +389,10 @@ GrGpuGL::GrGpuGL() { fFSAASupport = fAASamples[kHigh_GrAALevel] > 0; if (GR_GL_SUPPORT_DESKTOP) { - fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) || - has_gl_extension("GL_EXT_stencil_wrap"); + fHasStencilWrap = (fGLVersion >= 1.4f) || + this->hasExtension("GL_EXT_stencil_wrap"); } else { - fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap"); + fHasStencilWrap = (fGLVersion >= 2.0f) || this->hasExtension("GL_OES_stencil_wrap"); } if (gPrintStartupSpew) { GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO")); @@ -399,18 +402,17 @@ GrGpuGL::GrGpuGL() { // we could also look for GL_ATI_separate_stencil extension or // GL_EXT_stencil_two_side but they use different function signatures // than GL2.0+ (and than each other). - fTwoSidedStencilSupport = (major >= 2); + fTwoSidedStencilSupport = (fGLVersion >= 2.f); // supported on GL 1.4 and higher or by extension - fStencilWrapOpsSupport = (major > 1) || - ((1 == major) && (minor >= 4)) || - has_gl_extension("GL_EXT_stencil_wrap"); + fStencilWrapOpsSupport = (fGLVersion >= 1.4f) || + this->hasExtension("GL_EXT_stencil_wrap"); } else { // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be // an ES1 extension. - fTwoSidedStencilSupport = (major >= 2); + fTwoSidedStencilSupport = (fGLVersion >= 2.f); // stencil wrap support is in ES2, ES1 requires extension. - fStencilWrapOpsSupport = (major > 1) || - has_gl_extension("GL_OES_stencil_wrap"); + fStencilWrapOpsSupport = (fGLVersion >= 2.f) || + this->hasExtension("GL_OES_stencil_wrap"); } if (gPrintStartupSpew) { GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n", @@ -421,7 +423,7 @@ GrGpuGL::GrGpuGL() { if (GR_GL_SUPPORT_DESKTOP) { fRGBA8Renderbuffer = true; } else { - fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8"); + fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8"); } if (gPrintStartupSpew) { GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO")); @@ -430,7 +432,7 @@ GrGpuGL::GrGpuGL() { if (GR_GL_SUPPORT_ES) { if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) { - GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888")); + GrAssert(this->hasExtension("GL_EXT_texture_format_BGRA8888")); } } @@ -438,7 +440,7 @@ GrGpuGL::GrGpuGL() { fBufferLockSupport = true; // we require VBO support and the desktop VBO // extension includes glMapBuffer. } else { - fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer"); + fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer"); } if (gPrintStartupSpew) { @@ -446,7 +448,8 @@ GrGpuGL::GrGpuGL() { } if (GR_GL_SUPPORT_DESKTOP) { - if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) { + if (fGLVersion >= 2.f || + this->hasExtension("GL_ARB_texture_non_power_of_two")) { fNPOTTextureTileSupport = true; fNPOTTextureSupport = true; } else { @@ -454,12 +457,12 @@ GrGpuGL::GrGpuGL() { fNPOTTextureSupport = false; } } else { - if (major >= 2) { + if (fGLVersion >= 2.f) { fNPOTTextureSupport = true; - fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot"); + fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot"); } else { fNPOTTextureSupport = - has_gl_extension("GL_APPLE_texture_2D_limited_npot"); + this->hasExtension("GL_APPLE_texture_2D_limited_npot"); fNPOTTextureTileSupport = false; } } @@ -685,37 +688,57 @@ GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() { /////////////////////////////////////////////////////////////////////////////// -static const GrGLuint UNKNOWN_BITS = ~0; +void GrGpuGL::setupStencilFormats() { -struct StencilFormat { - GrGLenum fEnum; - GrGLuint fBits; - bool fPacked; -}; - -const StencilFormat* GrGLStencilFormats(int* count) { - // defines stencil formats from more to less preferred - static const StencilFormat desktopStencilFormats[] = { - {GR_GL_STENCIL_INDEX8, 8, false}, - {GR_GL_STENCIL_INDEX16, 16, false}, - {GR_GL_DEPTH24_STENCIL8, 8, true }, - {GR_GL_STENCIL_INDEX4, 4, false}, - {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false}, - {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true }, - }; + // Build up list of legal stencil formats (though perhaps not supported on + // the particular gpu/driver) from most preferred to least. - static const StencilFormat esStencilFormats[] = { - {GR_GL_STENCIL_INDEX8, 8, false}, - {GR_GL_DEPTH24_STENCIL8, 8, true }, - {GR_GL_STENCIL_INDEX4, 4, false}, - }; + // 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 StencilFormat gS8 = {GR_GL_STENCIL_INDEX8, 8, false}; + static const StencilFormat gS16 = {GR_GL_STENCIL_INDEX16, 16, false}; + static const StencilFormat gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, true }; + static const StencilFormat gS4 = {GR_GL_STENCIL_INDEX4, 4, false}; + static const StencilFormat gS = {GR_GL_STENCIL_INDEX, gUNKNOWN_BITCOUNT, false}; + static const StencilFormat gDS = {GR_GL_DEPTH_STENCIL, gUNKNOWN_BITCOUNT, true }; if (GR_GL_SUPPORT_DESKTOP) { - *count = GR_ARRAY_COUNT(desktopStencilFormats); - return desktopStencilFormats; + bool supportsPackedDS = fGLVersion >= 3.0f || + this->hasExtension("GL_EXT_packed_depth_stencil") || + this->hasExtension("GL_ARB_framebuffer_object"); + + // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we + // require FBO support we can expect these are legal formats and don't + // check. These also all support the unsized GL_STENCIL_INDEX. + fStencilFormats.push_back() = gS8; + fStencilFormats.push_back() = gS16; + if (supportsPackedDS) { + fStencilFormats.push_back() = gD24S8; + } + fStencilFormats.push_back() = gS4; + if (supportsPackedDS) { + fStencilFormats.push_back() = gDS; + } } else { - *count = GR_ARRAY_COUNT(esStencilFormats); - return esStencilFormats; + // ES2 has STENCIL_INDEX8 without extensions. + // ES1 with GL_OES_framebuffer_object (which we require for ES1) + // introduces tokens for S1 thu S8 but there are separate extensions + // that make them legal (GL_OES_stencil1, ...). + // GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8 + // ES doesn't support using the unsized formats. + + if (fGLVersion >= 2.f || this->hasExtension("GL_OES_stencil8")) { + fStencilFormats.push_back() = gS8; + } + //fStencilFormats.push_back() = gS16; + if (this->hasExtension("GL_OES_packed_depth_stencil")) { + fStencilFormats.push_back() = gD24S8; + } + if (this->hasExtension("GL_OES_stencil4")) { + fStencilFormats.push_back() = gS4; + } + // we require some stencil format. + GrAssert(fStencilFormats.count() > 0); } } @@ -983,9 +1006,8 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, err = ~GR_GL_NO_ERROR; int stencilFmtCnt; - const StencilFormat* stencilFormats = NULL; if (rtIDs.fStencilRenderbufferID) { - stencilFormats = GrGLStencilFormats(&stencilFmtCnt); + stencilFmtCnt = fStencilFormats.count(); } else { stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil } @@ -1003,12 +1025,12 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, GR_GL_NO_ERR(RenderbufferStorageMultisample( GR_GL_RENDERBUFFER, samples, - stencilFormats[sIdx].fEnum, + fStencilFormats[sIdx].fEnum, glDesc.fAllocWidth, glDesc.fAllocHeight)); } else { GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER, - stencilFormats[sIdx].fEnum, + fStencilFormats[sIdx].fEnum, glDesc.fAllocWidth, glDesc.fAllocHeight)); } @@ -1064,7 +1086,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, rtIDs.fStencilRenderbufferID)); // if it is a packed format bind to depth also, otherwise // we may get an unsupported fbo completeness result - if (stencilFormats[sIdx].fPacked) { + if (fStencilFormats[sIdx].fPacked) { GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, GR_GL_RENDERBUFFER, @@ -1076,7 +1098,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, if (status != GR_GL_FRAMEBUFFER_COMPLETE) { // undo the depth bind if (rtIDs.fStencilRenderbufferID && - stencilFormats[sIdx].fPacked) { + fStencilFormats[sIdx].fPacked) { GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, GR_GL_RENDERBUFFER, @@ -1088,10 +1110,10 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, failed = false; if (rtIDs.fStencilRenderbufferID) { fLastSuccessfulStencilFmtIdx = sIdx; - if (UNKNOWN_BITS == stencilFormats[sIdx].fBits) { + if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) { GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits); } else { - glDesc.fStencilBits = stencilFormats[sIdx].fBits; + glDesc.fStencilBits = fStencilFormats[sIdx].fBits; } } break; diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h index aec55d8b7b..7f13ea11a4 100644 --- a/gpu/src/GrGpuGL.h +++ b/gpu/src/GrGpuGL.h @@ -25,6 +25,8 @@ #include "GrGLVertexBuffer.h" #include "GrGLIndexBuffer.h" +#include "SkString.h" + class GrGpuGL : public GrGpu { public: virtual ~GrGpuGL(); @@ -48,6 +50,10 @@ protected: DrState fHWDrawState; bool fHWStencilClip; + // read these once at begining and then never again + SkString fExtensionString; + float fGLVersion; + // As flush of GL state proceeds it updates fHDrawState // to reflect the new state. Later parts of the state flush // may perform cascaded changes but cannot refer to fHWDrawState. @@ -127,6 +133,10 @@ protected: GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff); + bool hasExtension(const char* ext) { + return has_gl_extension_from_string(ext, fExtensionString.c_str()); + } + // adjusts texture matrix to account for orientation, size, and npotness static void AdjustTextureMatrix(const GrGLTexture* texture, GrSamplerState::SampleMode mode, @@ -142,6 +152,9 @@ protected: private: + // determines valid stencil formats + void setupStencilFormats(); + // notify callbacks to update state tracking when related // objects are bound to GL or deleted outside of the class void notifyVertexBufferBind(const GrGLVertexBuffer* buffer); @@ -175,6 +188,16 @@ private: friend class GrGLTexture; friend class GrGLRenderTarget; + static const GrGLuint gUNKNOWN_BITCOUNT = ~0; + + struct StencilFormat { + GrGLenum fEnum; + GrGLuint fBits; + bool fPacked; + }; + + GrTArray fStencilFormats; + bool fHWBlendDisabled; GrGLuint fAASamples[4]; diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp index b474be240e..13f7543ae5 100644 --- a/gpu/src/GrGpuGLShaders.cpp +++ b/gpu/src/GrGpuGLShaders.cpp @@ -248,14 +248,12 @@ void GrGpuGLShaders::ProgramUnitTest() { GrGpuGLShaders::GrGpuGLShaders() { resetContext(); - int major, minor; - gl_version(&major, &minor); f4X4DownsampleFilterSupport = true; if (GR_GL_SUPPORT_DESKTOP) { - fDualSourceBlendingSupport = - major > 3 ||(3 == major && 3 <= minor) || - has_gl_extension("GL_ARB_blend_func_extended"); + fDualSourceBlendingSupport = + fGLVersion >= 3.3f || + this->hasExtension("GL_ARB_blend_func_extended"); } else { fDualSourceBlendingSupport = false; } -- cgit v1.2.3