From 0748f217ba21f764401757886cda3bdb395a360d Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Tue, 1 Feb 2011 22:56:16 +0000 Subject: [PATCH] Attempt to simplify NPOT texture caps. Also fixes case where textures would unnecessarily be bloated to POT. Adds setting of sampler's filter setting in paint conversion. git-svn-id: http://skia.googlecode.com/svn/trunk@751 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gpu/include/GrGpu.h | 56 ++++++++++------------- gpu/src/GrContext.cpp | 38 +++++++++------- gpu/src/GrGpu.cpp | 1 - gpu/src/GrGpuGL.cpp | 119 ++++++++++++++++++++---------------------------- src/gpu/SkGpuDevice.cpp | 2 +- 5 files changed, 96 insertions(+), 120 deletions(-) diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h index 5a9281e..2bbb419 100644 --- a/gpu/include/GrGpu.h +++ b/gpu/include/GrGpu.h @@ -55,28 +55,6 @@ public: static GrGpu* Create(Engine, Platform3DContext context3D); /** - * Describes levels of support for non-power-of-two textures. - */ - enum NPOTTextureTypes { - /** - * no support for NPOT textures - */ - kNone_NPOTTextureType, - /** - * only clamp is supported for textures - */ - kNoRepeat_NPOTTextureType, - /** - * no texture restrictions at all, but rendertargets must be POW2 - */ - kNonRendertarget_NPOTTextureType, - /** - * no POW2 restrictions at all - */ - kFull_NPOTTextureType - }; - - /** * Used to control the level of antialiasing available for a rendertarget. * Anti-alias quality levels depend on the underlying API/GPU capabilities. */ @@ -173,7 +151,10 @@ public: void unimpl(const char[]); /** - * Creates a texture object + * Creates a texture object. If desc width or height is not a power of + * two but underlying API requires a power of two texture then srcData + * will be embedded in a power of two texture. The extra width and height + * is filled as though srcData were rendered clamped into the texture. * * @param desc describes the texture to be created. * @param srcData texel data to load texture. Begins with full-size @@ -278,14 +259,25 @@ public: int minRenderTargetHeight() const { return fMinRenderTargetHeight; } /** - * Retrieves the level of NPOT texture support. Regardless of support level - * NPOT textures can always be created, but internally they may be imbedded - * in a POT texture. An exception is paletted textures which must be - * specified as a POT when npotTextureSupport() is not Full. + * Returns true if NPOT textures can be created + * + * @return true if NPOT textures can be created + */ + bool npotTextureSupport() const { return fNPOTTextureSupport; } + + /** + * Returns true if NPOT textures can be repeat/mirror tiled. * - * @return the level of NPOT texture support. + * @return true if NPOT textures can be tiled */ - NPOTTextureTypes npotTextureSupport() const { return fNPOTTextureSupport; } + bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; } + + /** + * Returns true if a NPOT texture can be a rendertarget + * + * @return the true if NPOT texture/rendertarget can be created. + */ + bool npotRenderTargetSupport() const { return fNPOTRenderTargetSupport; } int maxTextureDimension() const { return fMaxTextureDimension; } @@ -374,8 +366,10 @@ protected: // defaults to false, subclass can set true to support palleted textures bool f8bitPaletteSupport; - // defaults to false, subclass can set higher support level - NPOTTextureTypes fNPOTTextureSupport; + // set by subclass + bool fNPOTTextureSupport; + bool fNPOTTextureTileSupport; + bool fNPOTRenderTargetSupport; // True if only one stencil pass is required to implement the winding path // fill rule. Subclass responsible for setting this value. diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index bcccc4e..f966c2c 100644 --- a/gpu/src/GrContext.cpp +++ b/gpu/src/GrContext.cpp @@ -260,22 +260,21 @@ bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler, return false; } - bool needsRepeat = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode || - sampler.getWrapY() != GrSamplerState::kClamp_WrapMode; + bool isPow2 = GrIsPow2(width) && GrIsPow2(height); - switch (fGpu->npotTextureSupport()) { - case GrGpu::kNone_NPOTTextureType: - return isPow2; - case GrGpu::kNoRepeat_NPOTTextureType: - return isPow2 || !needsRepeat; - case GrGpu::kNonRendertarget_NPOTTextureType: - case GrGpu::kFull_NPOTTextureType: - return true; + if (!isPow2) { + if (!fGpu->npotTextureSupport()) { + return false; + } + + bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode || + sampler.getWrapY() != GrSamplerState::kClamp_WrapMode; + if (tiled && !fGpu->npotTextureTileSupport()) { + return false; + } } - // should never get here - GrAssert(!"Bad enum from fGpu->npotTextureSupport"); - return false; + return true; } //////////////////////////////////////////////////////////////////////////////// @@ -1141,10 +1140,15 @@ bool GrContext::finalizeTextureKey(GrTextureKey* key, uint32_t bits = 0; uint16_t width = key->width(); uint16_t height = key->height(); - if (fGpu->npotTextureSupport() < GrGpu::kNonRendertarget_NPOTTextureType) { - if ((sampler.getWrapX() != GrSamplerState::kClamp_WrapMode || - sampler.getWrapY() != GrSamplerState::kClamp_WrapMode) && - (!GrIsPow2(width) || !GrIsPow2(height))) { + + + if (!fGpu->npotTextureTileSupport()) { + bool isPow2 = GrIsPow2(width) && GrIsPow2(height); + + bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) || + (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode); + + if (tiled && !isPow2) { bits |= 1; bits |= sampler.isFilter() ? 2 : 0; } diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp index 3624747..057a8c9 100644 --- a/gpu/src/GrGpu.cpp +++ b/gpu/src/GrGpu.cpp @@ -57,7 +57,6 @@ bool GrTexture::PixelConfigIsOpaque(PixelConfig config) { extern void gr_run_unittests(); GrGpu::GrGpu() : f8bitPaletteSupport(false), - fNPOTTextureSupport(kNone_NPOTTextureType), fQuadIndexBuffer(NULL), fUnitSquareVertexBuffer(NULL) { #if GR_DEBUG diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp index fb23152..3d86d1b 100644 --- a/gpu/src/GrGpuGL.cpp +++ b/gpu/src/GrGpuGL.cpp @@ -250,18 +250,20 @@ GrGpuGL::GrGpuGL() { } #if GR_SUPPORT_GLDESKTOP - fNPOTTextureSupport = - (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) ? - kFull_NPOTTextureType : - kNone_NPOTTextureType; + if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) { + fNPOTTextureTileSupport = true; + fNPOTTextureSupport = true; + } else { + fNPOTTextureTileSupport = false; + fNPOTTextureSupport = false; + } #else - if (has_gl_extension("GL_OES_texture_npot")) { - fNPOTTextureSupport = kFull_NPOTTextureType; - } else if (major >= 2 || - has_gl_extension("GL_APPLE_texture_2D_limited_npot")) { - fNPOTTextureSupport = kNoRepeat_NPOTTextureType; + if (major >= 2) { + fNPOTTextureSupport = true; + fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot"); } else { - fNPOTTextureSupport = kNone_NPOTTextureType; + fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot"); + fNPOTTextureTileSupport = false; } #endif //////////////////////////////////////////////////////////////////////////// @@ -269,16 +271,16 @@ GrGpuGL::GrGpuGL() { // these a preprocess that generate some compile time constants. // sanity check to make sure we can at least create an FBO from a POT texture - if (fNPOTTextureSupport < kFull_NPOTTextureType) { - bool npotFBOSuccess = fbo_test(fExts, 128, 128); - if (gPrintStartupSpew) { - if (!npotFBOSuccess) { - GrPrintf("FBO Sanity Test: FAILED\n"); - } else { - GrPrintf("FBO Sanity Test: PASSED\n"); - } + + bool simpleFBOSuccess = fbo_test(fExts, 128, 128); + if (gPrintStartupSpew) { + if (!simpleFBOSuccess) { + GrPrintf("FBO Sanity Test: FAILED\n"); + } else { + GrPrintf("FBO Sanity Test: PASSED\n"); } } + GrAssert(simpleFBOSuccess); /* Experimentation has found that some GLs that support NPOT textures do not support FBOs with a NPOT texture. They report "unsupported" FBO @@ -287,34 +289,26 @@ GrGpuGL::GrGpuGL() { texture. Presumably, the implementation bloats the renderbuffer internally to the next POT. */ - if (fNPOTTextureSupport == kFull_NPOTTextureType) { - bool npotFBOSuccess = fbo_test(fExts, 200, 200); - if (!npotFBOSuccess) { - fNPOTTextureSupport = kNonRendertarget_NPOTTextureType; - if (gPrintStartupSpew) { - GrPrintf("NPOT Renderbuffer Test: FAILED\n"); - } - } else { - if (gPrintStartupSpew) { - GrPrintf("NPOT Renderbuffer Test: PASSED\n"); - } - } + bool fNPOTRenderTargetSupport = false; + if (fNPOTTextureSupport) { + fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200); } - + if (gPrintStartupSpew) { - switch (fNPOTTextureSupport) { - case kNone_NPOTTextureType: - GrPrintf("NPOT Support: NONE\n"); - break; - case kNoRepeat_NPOTTextureType: - GrPrintf("NPOT Support: NO REPEAT\n"); - break; - case kNonRendertarget_NPOTTextureType: - GrPrintf("NPOT Support: NO FBOTEX\n"); - break; - case kFull_NPOTTextureType: - GrPrintf("NPOT Support: FULL\n"); - break; + if (fNPOTTextureSupport) { + GrPrintf("NPOT textures supported\n"); + if (fNPOTTextureTileSupport) { + GrPrintf("NPOT texture tiling supported\n"); + } else { + GrPrintf("NPOT texture tiling NOT supported\n"); + } + if (fNPOTRenderTargetSupport) { + GrPrintf("NPOT render targets supported\n"); + } else { + GrPrintf("NPOT render targets NOT supported\n"); + } + } else { + GrPrintf("NPOT textures NOT supported\n"); } } @@ -329,8 +323,8 @@ GrGpuGL::GrGpuGL() { if (gPrintStartupSpew) { GrPrintf("Small height FBO texture experiments\n"); } - for (GLuint i = 1; i <= 256; - (kFull_NPOTTextureType != fNPOTTextureSupport) ? i *= 2 : ++i) { + + for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) { GLuint w = maxRenderSize; GLuint h = i; if (fbo_test(fExts, w, h)) { @@ -351,8 +345,7 @@ GrGpuGL::GrGpuGL() { GrPrintf("Small width FBO texture experiments\n"); } fMinRenderTargetWidth = GR_MAX_GLUINT; - for (GLuint i = 1; i <= 256; - (kFull_NPOTTextureType != fNPOTTextureSupport) ? i *= 2 : ++i) { + for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) { GLuint w = i; GLuint h = maxRenderSize; if (fbo_test(fExts, w, h)) { @@ -369,22 +362,7 @@ GrGpuGL::GrGpuGL() { } GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth); -#if GR_IOS_BUILD - /* - The iPad seems to fail, at least sometimes, if the height is < 16, - so we pin the values here for now. A better fix might be to - conditionalize this based on known that its an iPad (or some other - check). - */ - fMinRenderTargetWidth = GrMax(fMinRenderTargetWidth, 16); - fMinRenderTargetHeight = GrMax(fMinRenderTargetHeight, 16); -#endif - GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension); - -#if GR_COLLECT_STATS - ++fStats.fRenderTargetChngCnt; -#endif } GrGpuGL::~GrGpuGL() { @@ -607,18 +585,19 @@ GrTexture* GrGpuGL::createTexture(const TextureDesc& desc, } #endif - if (fNPOTTextureSupport < kNonRendertarget_NPOTTextureType || - (fNPOTTextureSupport == kNonRendertarget_NPOTTextureType && - renderTarget)) { - glDesc.fAllocWidth = GrNextPow2(desc.fWidth); - glDesc.fAllocHeight = GrNextPow2(desc.fHeight); - } - if (renderTarget) { + if (!this->npotRenderTargetSupport()) { + glDesc.fAllocWidth = GrNextPow2(desc.fWidth); + glDesc.fAllocHeight = GrNextPow2(desc.fHeight); + } + glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth, glDesc.fAllocWidth); glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight, glDesc.fAllocHeight); + } else if (!this->npotTextureSupport()) { + glDesc.fAllocWidth = GrNextPow2(desc.fWidth); + glDesc.fAllocHeight = GrNextPow2(desc.fHeight); } GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID)); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 3afd46c..5059569 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -405,7 +405,7 @@ bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint, return false; } grPaint->fSampler.setSampleMode(sampleMode); - + grPaint->fSampler.setFilter(skPaint.isFilterBitmap()); grPaint->fSampler.setWrapX(sk_tile_mode_to_grwrap(tileModes[0])); grPaint->fSampler.setWrapY(sk_tile_mode_to_grwrap(tileModes[1])); -- 2.7.4