Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 8fffc4d917d85f58a4808da429ac925a3f39e62b..d7a060031e55deb265d045fd3cc70f023b28f37d 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -2069,12 +2069,55 @@ static bool read_pixels_pays_for_y_flip(GrRenderTarget* renderTarget, const GrGL |
return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes; |
} |
+bool GrGLGpu::readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig) { |
+ auto bindRenderTarget = [this, target]() -> bool { |
+ this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect()); |
+ return true; |
+ }; |
+ auto getIntegerv = [this](GrGLenum query, GrGLint* value) { |
+ GR_GL_GetIntegerv(this->glInterface(), query, value); |
+ }; |
+ GrPixelConfig rtConfig = target->config(); |
+ return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget); |
+} |
+ |
+bool GrGLGpu::readPixelsSupported(GrPixelConfig rtConfig, GrPixelConfig readConfig) { |
+ auto bindRenderTarget = [this, rtConfig]() -> bool { |
+ GrTextureDesc desc; |
+ desc.fConfig = rtConfig; |
+ desc.fWidth = desc.fHeight = 16; |
+ desc.fFlags = kRenderTarget_GrSurfaceFlag; |
+ SkAutoTUnref<GrTexture> temp(this->createTexture(desc, false, nullptr, 0)); |
+ if (!temp) { |
+ return false; |
+ } |
+ GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(temp->asRenderTarget()); |
+ this->flushRenderTarget(glrt, &SkIRect::EmptyIRect()); |
+ return true; |
+ }; |
+ auto getIntegerv = [this](GrGLenum query, GrGLint* value) { |
+ GR_GL_GetIntegerv(this->glInterface(), query, value); |
+ }; |
+ return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget); |
+} |
+ |
+bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig) { |
+ if (GrRenderTarget* rt = surfaceForConfig->asRenderTarget()) { |
+ return this->readPixelsSupported(rt, readConfig); |
+ } else { |
+ GrPixelConfig config = surfaceForConfig->config(); |
+ return this->readPixelsSupported(config, readConfig); |
+ } |
+} |
+ |
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 (!srcSurface->asRenderTarget()) { |
+ if (!srcAsRT) { |
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
} |
@@ -2099,33 +2142,38 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, |
GrPixelConfig srcConfig = srcSurface->config(); |
tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; |
- if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig) { |
+ if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig && |
+ this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) { |
tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig; |
tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); |
tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig; |
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); |
} else if (kMesa_GrGLDriver == this->glContext().driver() && |
GrBytesPerPixel(readConfig) == 4 && |
- GrPixelConfigSwapRAndB(readConfig) == srcConfig) { |
+ GrPixelConfigSwapRAndB(readConfig) == srcConfig && |
+ this->readPixelsSupported(srcSurface, srcConfig)) { |
// Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa. |
// Better to do a draw with a R/B swap and then read as the original config. |
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; |
tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); |
tempDrawInfo->fReadConfig = srcConfig; |
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); |
- } else if (readConfig == kBGRA_8888_GrPixelConfig && |
- !this->glCaps().readPixelsSupported(this->glInterface(), readConfig, srcConfig)) { |
- tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; |
- tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); |
- tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig; |
- ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ } else if (!this->readPixelsSupported(srcSurface, readConfig)) { |
+ if (readConfig == kBGRA_8888_GrPixelConfig && |
+ this->glCaps().isConfigRenderable(kRGBA_8888_GrPixelConfig, false) && |
+ this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) { |
+ |
+ tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; |
+ tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); |
+ tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig; |
+ ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
+ } else { |
+ return false; |
+ } |
} |
- GrRenderTarget* srcAsRT = srcSurface->asRenderTarget(); |
- if (!srcAsRT) { |
- ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
- } else if (read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig, |
- rowBytes)) { |
+ if (srcAsRT && |
+ read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig, rowBytes)) { |
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); |
} |