Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 74f7e0bc107f013eefdacbe3149a13bd87a598bb..3eee2f6dfca3ca4893fc603788e626fa337cc0d2 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; |