diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp index 53b9b46d87..c75f298807 100644 --- a/src/gpu/GrResourceProvider.cpp +++ b/src/gpu/GrResourceProvider.cpp @@ -65,7 +65,7 @@ bool validate_desc(const GrSurfaceDesc& desc, const GrCaps& caps, int levelCount return false; } } - if (levelCount > 1 && GrPixelConfigIsSint(desc.fConfig)) { + if (levelCount > 1 && (GrPixelConfigIsSint(desc.fConfig) || !caps.mipMapSupport())) { return false; } return true; diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 521e2553f0..cb675bdb85 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -1571,14 +1571,16 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions, fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_BGRA; fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_BGRA8; if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) { - // The APPLE extension doesn't make this renderable. - fConfigTable[kBGRA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag; - if (version < GR_GL_VER(3,0) && !ctxInfo.hasExtension("GL_EXT_texture_storage")) { - // On ES2 the internal format of a BGRA texture is RGBA with the APPLE extension. - // Though, that seems to not be the case if the texture storage extension is - // present. The specs don't exactly make that clear. - fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_RGBA; - fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_RGBA8; + // This APPLE extension introduces complexity on ES2. It leaves the internal format + // as RGBA, but allows BGRA as the external format. From testing, it appears that the + // driver remembers the external format when the texture is created (with TexImage). + // If you then try to upload data in the other swizzle (with TexSubImage), it fails. + // We could work around this, but it adds even more state tracking to code that is + // already too tricky. Instead, we opt not to support BGRA on ES2 with this extension. + // This also side-steps some ambiguous interactions with the texture storage extension. + if (version >= GR_GL_VER(3,0)) { + // The APPLE extension doesn't make this renderable. + fConfigTable[kBGRA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag; } } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) { fConfigTable[kBGRA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag | diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp index 8c596d915b..4a20f50089 100644 --- a/tests/GrSurfaceTest.cpp +++ b/tests/GrSurfaceTest.cpp @@ -17,6 +17,7 @@ #include "GrTest.h" #include "GrTexture.h" #include "GrSurfacePriv.h" +#include "SkMipMap.h" #include "Test.h" // Tests that GrSurface::asTexture(), GrSurface::asRenderTarget(), and static upcasting of texture @@ -99,6 +100,16 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability, reporter, ctxInfo) { desc.fWidth = 64; desc.fHeight = 64; + // Enough space for the first mip of our largest pixel config + const size_t pixelBufferSize = desc.fWidth * desc.fHeight * + GrBytesPerPixel(kRGBA_float_GrPixelConfig); + std::unique_ptr pixelData(new char[pixelBufferSize]); + memset(pixelData.get(), 0, pixelBufferSize); + + // We re-use the same mip level objects (with updated pointers and rowBytes) for each config + const int levelCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight); + std::unique_ptr texels(new GrMipLevel[levelCount]); + for (GrPixelConfig config : configs) { for (GrSurfaceOrigin origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) { desc.fFlags = kNone_GrSurfaceFlags; @@ -109,6 +120,18 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability, reporter, ctxInfo) { sk_sp tex = resourceProvider->createTexture(desc, SkBudgeted::kNo); REPORTER_ASSERT(reporter, SkToBool(tex.get()) == caps->isConfigTexturable(desc.fConfig)); + size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig); + for (int i = 0; i < levelCount; ++i) { + texels[i].fPixels = pixelData.get(); + texels[i].fRowBytes = rowBytes >> i; + } + sk_sp proxy = resourceProvider->createMipMappedTexture( + desc, SkBudgeted::kNo, texels.get(), levelCount); + REPORTER_ASSERT(reporter, SkToBool(proxy.get()) == + (caps->isConfigTexturable(desc.fConfig) && + caps->mipMapSupport() && + !GrPixelConfigIsSint(desc.fConfig))); + desc.fFlags = kRenderTarget_GrSurfaceFlag; tex = resourceProvider->createTexture(desc, SkBudgeted::kNo); REPORTER_ASSERT(reporter, SkToBool(tex.get()) == caps->isConfigRenderable(config, false)); diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 08f60ea1c5..460d4ee096 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -1714,7 +1714,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) { // Mipmapped versions - { + if (context->caps()->mipMapSupport()) { sk_sp proxy; proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);