Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 84f2bdda8e915863d4d648d518a5deaa842cea0d..f9457f205b21945e07311856c1557f155bbb7cde 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -2004,26 +2004,21 @@ bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig rea |
} |
} |
+static bool requires_srgb_conversion(GrPixelConfig a, GrPixelConfig b) { |
+ if (GrPixelConfigIsSRGB(a)) { |
+ return !GrPixelConfigIsSRGB(b) && !GrPixelConfigIsAlphaOnly(b); |
+ } else if (GrPixelConfigIsSRGB(b)) { |
+ return !GrPixelConfigIsSRGB(a) && !GrPixelConfigIsAlphaOnly(a); |
+ } |
+ return false; |
+} |
+ |
bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes, |
GrPixelConfig readConfig, DrawPreference* drawPreference, |
ReadPixelTempDrawInfo* tempDrawInfo) { |
- GrRenderTarget* srcAsRT = srcSurface->asRenderTarget(); |
- |
- // This subclass can only read pixels from a render target. We could use glTexSubImage2D on |
- // GL versions that support it but we don't today. |
- if (!srcAsRT) { |
- ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
- } |
- |
- if (GrPixelConfigIsSRGB(srcSurface->config()) != GrPixelConfigIsSRGB(readConfig)) { |
- ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
- } |
- |
- tempDrawInfo->fSwizzle = GrSwizzle::RGBA(); |
- tempDrawInfo->fReadConfig = readConfig; |
+ GrPixelConfig srcConfig = srcSurface->config(); |
- // These settings we will always want if a temp draw is performed. The config is set below |
- // depending on whether we want to do a R/B swap or not. |
+ // These settings we will always want if a temp draw is performed. |
tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag; |
tempDrawInfo->fTempSurfaceDesc.fWidth = width; |
tempDrawInfo->fTempSurfaceDesc.fHeight = height; |
@@ -2031,10 +2026,30 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, |
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL. |
tempDrawInfo->fUseExactScratch = this->glCaps().partialFBOReadIsSlow(); |
- // Start off assuming that any temp draw should be to the readConfig, then check if that will |
- // be inefficient. |
- GrPixelConfig srcConfig = srcSurface->config(); |
- tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; |
+ // For now assume no swizzling, we may change that below. |
+ tempDrawInfo->fSwizzle = GrSwizzle::RGBA(); |
+ |
+ // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read |
+ // from will be srcConfig and we will read readConfig pixels from it. |
+ // Not that if we require a draw and return a non-renderable format for the temp surface the |
+ // base class will fail for us. |
+ tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; |
+ tempDrawInfo->fReadConfig = readConfig; |
+ |
+ if (requires_srgb_conversion(srcConfig, readConfig)) { |
+ // Draw to do srgb to linear conversion or vice versa. |
+ ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; |
egdaniel
2016/01/25 21:28:24
so not 100% sure how the srgb coversion works, but
bsalomon
2016/01/25 21:45:17
Yes, the conversion to or from sRGB happens during
|
+ tempDrawInfo->fReadConfig = readConfig; |
+ return true; |
+ } |
+ |
+ GrRenderTarget* srcAsRT = srcSurface->asRenderTarget(); |
+ if (!srcAsRT) { |
+ // For now keep assuming the draw is not a format transformation, just a draw to get to a |
+ // RT. We may add additional transformations below. |
+ ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ } |
if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig && |
this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) { |
@@ -2056,11 +2071,35 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, |
if (readConfig == kBGRA_8888_GrPixelConfig && |
this->glCaps().isConfigRenderable(kRGBA_8888_GrPixelConfig, false) && |
this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) { |
- |
+ // We're trying to read BGRA but it's not supported. If RGBA is renderable and |
+ // we can read it back, then do a swizzling draw to a RGBA and read it back (which |
+ // will effectively be BGRA). |
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; |
tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); |
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig; |
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ } else if (readConfig == kAlpha_8_GrPixelConfig) { |
+ // onReadPixels implements a fallback for cases where we are want to read kAlpha_8, |
+ // it's unsupported, but 32bit RGBA reads are supported. |
+ // Don't attempt to do any srgb conversions since we only care about alpha. |
+ GrPixelConfig cpuTempConfig = kRGBA_8888_GrPixelConfig; |
+ if (GrPixelConfigIsSRGB(srcSurface->config())) { |
+ cpuTempConfig = kSRGBA_8888_GrPixelConfig; |
+ } |
+ if (!this->readPixelsSupported(srcSurface, cpuTempConfig)) { |
+ // If we can't read RGBA from the src try to draw to a kRGBA_8888 (or kSRGBA_8888) |
+ // first and then onReadPixels will read that to a 32bit temporary buffer. |
+ if (this->caps()->isConfigRenderable(cpuTempConfig, false)) { |
+ ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ tempDrawInfo->fTempSurfaceDesc.fConfig = cpuTempConfig; |
+ tempDrawInfo->fReadConfig = kAlpha_8_GrPixelConfig; |
+ } else { |
+ return false; |
+ } |
+ } else { |
+ SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == srcConfig); |
+ SkASSERT(tempDrawInfo->fReadConfig == kAlpha_8_GrPixelConfig); |
+ } |
} else { |
return false; |
} |
@@ -2088,7 +2127,32 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, |
} |
// OpenGL doesn't do sRGB <-> linear conversions when reading and writing pixels. |
- if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { |
+ if (requires_srgb_conversion(surface->config(), config)) { |
+ return false; |
+ } |
+ |
+ // We have a special case fallback for reading eight bit alpha. We will read back all four 8 |
+ // bit channels as RGBA and then extract A. |
+ if (!this->readPixelsSupported(tgt, config)) { |
+ // Don't attempt to do any srgb conversions since we only care about alpha. |
+ GrPixelConfig tempConfig = kRGBA_8888_GrPixelConfig; |
+ if (GrPixelConfigIsSRGB(tgt->config())) { |
+ tempConfig = kSRGBA_8888_GrPixelConfig; |
+ } |
+ if (kAlpha_8_GrPixelConfig == config && |
+ this->readPixelsSupported(surface, tempConfig)) { |
egdaniel
2016/01/25 21:28:24
just for symmetry can we use tgt instead of surfac
bsalomon
2016/01/25 21:45:17
Done, also renamed tgt to renderTarget.
|
+ SkAutoTDeleteArray<uint32_t> temp(new uint32_t[width * height * 4]); |
+ if (this->onReadPixels(surface, left, top, width, height, tempConfig, temp.get(), |
+ width*4)) { |
+ uint8_t* dst = reinterpret_cast<uint8_t*>(buffer); |
+ for (int j = 0; j < height; ++j) { |
+ for (int i = 0; i < width; ++i) { |
+ dst[j*rowBytes + i] = (0xFF000000U & temp[j*width+i]) >> 24; |
+ } |
+ } |
+ return true; |
+ } |
+ } |
return false; |
} |