diff options
author | bsalomon <bsalomon@google.com> | 2015-07-30 15:34:56 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-30 15:34:56 -0700 |
commit | 16921ec30a81976129d507b1148c93a322e61a4f (patch) | |
tree | 5eb7ceafe1b43b2a168de7f46d4ebdde3bc1d7cc /src | |
parent | 381b26f03bdccac1e3d9055fb4f7855792cfefb0 (diff) |
SRGB read and write pixels working and unit test
Review URL: https://codereview.chromium.org/1264003002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 59 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 15 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 59 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 1 |
4 files changed, 93 insertions, 41 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 318426b5bc..161dac6e9f 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -49,6 +49,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fIsCoreProfile = false; fFullClearIsFree = false; fBindFragDataLocationSupport = false; + fSRGBWriteControl = false; fReadPixelsSupportedCache.reset(); @@ -191,6 +192,27 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, // can change based on which render target is bound fTwoFormatLimit = kGLES_GrGLStandard == standard; + // We only enable srgb support if both textures and FBOs support srgb. + bool srgbSupport = false; + if (kGL_GrGLStandard == standard) { + if (ctxInfo.version() >= GR_GL_VER(3,0)) { + srgbSupport = true; + } else if (ctxInfo.hasExtension("GL_EXT_texture_sRGB")) { + if (ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") || + ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) { + srgbSupport = true; + } + } + // All the above srgb extensions support toggling srgb writes + fSRGBWriteControl = srgbSupport; + } else { + srgbSupport = ctxInfo.version() >= GR_GL_VER(3,0) || + ctxInfo.hasExtension("GL_EXT_sRGB"); + // ES through 3.1 requires EXT_srgb_write_control to support toggling + // sRGB writing for destinations. + fSRGBWriteControl = ctxInfo.hasExtension("GL_EXT_sRGB_write_control"); + } + // Frag Coords Convention support is not part of ES // Known issue on at least some Intel platforms: // http://code.google.com/p/skia/issues/detail?id=946 @@ -455,8 +477,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, ctxInfo.hasExtension("GL_EXT_instanced_arrays")); } - this->initConfigTexturableTable(ctxInfo, gli); - this->initConfigRenderableTable(ctxInfo); + this->initConfigTexturableTable(ctxInfo, gli, srgbSupport); + this->initConfigRenderableTable(ctxInfo, srgbSupport); this->initShaderPrecisionTable(ctxInfo, gli, glslCaps); this->applyOptionsOverrides(contextOptions); @@ -496,7 +518,7 @@ bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrG return true; } -void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) { +void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo, bool srgbSupport) { // 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, @@ -574,21 +596,9 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) { } } - if (this->fRGBA8RenderbufferSupport && this->isConfigTexturable(kSRGBA_8888_GrPixelConfig)) { - if (kGL_GrGLStandard == standard) { - if (ctxInfo.version() >= GR_GL_VER(3,0) || - ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") || - ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) { - fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true; - fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = true; - } - } else { - if (ctxInfo.version() >= GR_GL_VER(3,0) || - ctxInfo.hasExtension("GL_EXT_sRGB")) { - fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true; - fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = true; - } - } + if (this->fRGBA8RenderbufferSupport && srgbSupport) { + fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true; + fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = true; } if (this->isConfigTexturable(kRGBA_float_GrPixelConfig)) { @@ -658,7 +668,8 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) { } } -void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { +void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli, + bool srgbSupport) { GrGLStandard standard = ctxInfo.standard(); GrGLVersion version = ctxInfo.version(); @@ -697,14 +708,7 @@ void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const G kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig); } - // Check for sRGBA - if (kGL_GrGLStandard == standard) { - fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = - (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_texture_sRGB")); - } else { - fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = - (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_sRGB")); - } + fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] = srgbSupport; // Compressed texture support @@ -1118,6 +1122,7 @@ SkString GrGLCaps::dump() const { r.appendf("Use non-VBO for dynamic data: %s\n", (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO")); r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO")); + r.appendf("SRGB write contol: %s\n", (fSRGBWriteControl ? "YES" : "NO")); return r; } diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index ac90aa1db6..0622e68edc 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -26,8 +26,6 @@ class GrGLSLCaps; */ class GrGLCaps : public GrCaps { public: - - typedef GrGLStencilAttachment::Format StencilFormat; /** @@ -254,12 +252,18 @@ public: bool isCoreProfile() const { return fIsCoreProfile; } - bool fullClearIsFree() const { return fFullClearIsFree; } bool bindFragDataLocationSupport() const { return fBindFragDataLocationSupport; } /** + * Is there support for enabling/disabling sRGB writes for sRGB-capable color attachments? + * If false this does not mean sRGB is not supported but rather that if it is supported + * it cannot be turned off for configs that support it. + */ + bool srgbWriteControl() const { return fSRGBWriteControl; } + + /** * Returns a string containing the caps info. */ SkString dump() const override; @@ -324,8 +328,8 @@ private: void initBlendEqationSupport(const GrGLContextInfo&); void initStencilFormats(const GrGLContextInfo&); // This must be called after initFSAASupport(). - void initConfigRenderableTable(const GrGLContextInfo&); - void initConfigTexturableTable(const GrGLContextInfo&, const GrGLInterface*); + void initConfigRenderableTable(const GrGLContextInfo&, bool srgbSupport); + void initConfigTexturableTable(const GrGLContextInfo&, const GrGLInterface*, bool srgbSupport); bool doReadPixelsSupported(const GrGLInterface* intf, GrGLenum format, GrGLenum type) const; @@ -375,6 +379,7 @@ private: bool fIsCoreProfile : 1; bool fFullClearIsFree : 1; bool fBindFragDataLocationSupport : 1; + bool fSRGBWriteControl : 1; struct ReadPixelsSupportedFormat { GrGLenum fFormat; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 74f7e0bc10..3eee2f6dfc 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -355,6 +355,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) { if (resetBits & kRenderTarget_GrGLBackendState) { fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; + fHWSRGBFramebuffer = kUnknown_TriState; } if (resetBits & kPathRendering_GrGLBackendState) { @@ -519,6 +520,10 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); } + if (GrPixelConfigIsSRGB(dstSurface->config()) != GrPixelConfigIsSRGB(srcConfig)) { + ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); + } + tempDrawInfo->fSwapRAndB = false; // These settings we will always want if a temp draw is performed. Initially set the config @@ -566,11 +571,17 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, if (NULL == buffer) { return false; } + GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); if (!glTex) { return false; } + // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels. + if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { + return false; + } + this->setScratchTextureUnit(); GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID())); @@ -1737,6 +1748,10 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); } + if (GrPixelConfigIsSRGB(srcSurface->config()) != GrPixelConfigIsSRGB(readConfig)) { + ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); + } + tempDrawInfo->fSwapRAndB = false; // These settings we will always want if a temp draw is performed. The config is set below @@ -1797,6 +1812,11 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, return false; } + // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels. + if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { + return false; + } + GrGLenum format = 0; GrGLenum type = 0; bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); @@ -1804,6 +1824,12 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, return false; } + // glReadPixels does not allow GL_SRGB_ALPHA. Instead use GL_RGBA. This will not trigger a + // conversion when the src is srgb. + if (GR_GL_SRGB_ALPHA == format) { + format = GR_GL_RGBA; + } + // resolve the render target if necessary switch (tgt->getResolveType()) { case GrGLRenderTarget::kCantResolve_ResolveType: @@ -1931,6 +1957,16 @@ void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) vp.pushToGLViewport(this->glInterface()); fHWViewport = vp; } + if (this->glCaps().srgbWriteControl()) { + bool enableSRGBWrite = GrPixelConfigIsSRGB(target->config()); + if (enableSRGBWrite && kYes_TriState != fHWSRGBFramebuffer) { + GL_CALL(Enable(GR_GL_FRAMEBUFFER_SRGB)); + fHWSRGBFramebuffer = kYes_TriState; + } else if (!enableSRGBWrite && kNo_TriState != fHWSRGBFramebuffer) { + GL_CALL(Disable(GR_GL_FRAMEBUFFER_SRGB)); + fHWSRGBFramebuffer = kNo_TriState; + } + } } if (NULL == bound || !bound->isEmpty()) { target->flagAsNeedingResolve(bound); @@ -2437,19 +2473,24 @@ bool GrGLGpu::configToGLFormats(GrPixelConfig config, *externalType = GR_GL_UNSIGNED_BYTE; break; case kSRGBA_8888_GrPixelConfig: - *internalFormat = GR_GL_SRGB_ALPHA; - *externalFormat = GR_GL_SRGB_ALPHA; - if (getSizedInternalFormat || kGL_GrGLStandard == this->glStandard()) { - // desktop or ES 3.0 - SkASSERT(this->glVersion() >= GR_GL_VER(3, 0)); + if (getSizedInternalFormat) { *internalFormat = GR_GL_SRGB8_ALPHA8; - *externalFormat = GR_GL_RGBA; } else { - // ES 2.0 with EXT_sRGB - SkASSERT(kGL_GrGLStandard != this->glStandard() && - this->glVersion() < GR_GL_VER(3, 0)); *internalFormat = GR_GL_SRGB_ALPHA; + } + // OpenGL ES 2.0 + GL_EXT_sRGB allows GL_SRGB_ALPHA to be specified as the <format> + // param to Tex(Sub)Image2D. ES 2.0 requires the internalFormat and format to match. + // Thus, on ES 2.0 we will use GL_SRGB_ALPHA as the externalFormat. However, + // onReadPixels needs code to override that because GL_SRGB_ALPHA is not allowed as a + // glReadPixels format. + // On OpenGL and ES 3.0 GL_SRGB_ALPHA does not work for the <format> param to + // glReadPixels nor does it work with Tex(Sub)Image2D So we always set the externalFormat + // return to GL_RGBA. + if (this->glStandard() == kGLES_GrGLStandard && + this->glVersion() == GR_GL_VER(2,0)) { *externalFormat = GR_GL_SRGB_ALPHA; + } else { + *externalFormat = GR_GL_RGBA; } *externalType = GR_GL_UNSIGNED_BYTE; break; diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 5724107223..eb9795ca16 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -489,6 +489,7 @@ private: TriState fHWWriteToColor; TriState fHWDitherEnabled; uint32_t fHWBoundRenderTargetUniqueID; + TriState fHWSRGBFramebuffer; SkTArray<uint32_t, true> fHWBoundTextureUniqueIDs; ///@} |