Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 784a62fa27db057459bc986323c4b5a36d8b2959..e8dc788415fc15e7c3d9d4af213837c44f505232 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -267,28 +267,6 @@ void GrGLGpu::contextAbandoned() { |
} |
/////////////////////////////////////////////////////////////////////////////// |
-GrPixelConfig GrGLGpu::preferredReadPixelsConfig(GrPixelConfig readConfig, |
- GrPixelConfig surfaceConfig) const { |
- if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == readConfig) { |
- return kBGRA_8888_GrPixelConfig; |
- } else if (kMesa_GrGLDriver == this->glContext().driver() && |
- GrBytesPerPixel(readConfig) == 4 && |
- GrPixelConfigSwapRAndB(readConfig) == surfaceConfig) { |
- // Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa. |
- // Perhaps this should be guarded by some compiletime or runtime check. |
- return surfaceConfig; |
- } else if (readConfig == kBGRA_8888_GrPixelConfig |
- && !this->glCaps().readPixelsSupported( |
- this->glInterface(), |
- GR_GL_BGRA, |
- GR_GL_UNSIGNED_BYTE, |
- surfaceConfig |
- )) { |
- return kRGBA_8888_GrPixelConfig; |
- } else { |
- return readConfig; |
- } |
-} |
GrPixelConfig GrGLGpu::preferredWritePixelsConfig(GrPixelConfig writeConfig, |
GrPixelConfig surfaceConfig) const { |
@@ -322,10 +300,6 @@ bool GrGLGpu::canWriteTexturePixels(const GrTexture* texture, GrPixelConfig srcC |
} |
} |
-bool GrGLGpu::fullReadPixelsIsFasterThanPartial() const { |
- return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL); |
-} |
- |
void GrGLGpu::onResetContext(uint32_t resetBits) { |
// we don't use the zb at all |
if (resetBits & kMisc_GrGLBackendState) { |
@@ -1651,7 +1625,6 @@ void GrGLGpu::discard(GrRenderTarget* renderTarget) { |
renderTarget->flagAsResolved(); |
} |
- |
void GrGLGpu::clearStencil(GrRenderTarget* target) { |
if (NULL == target) { |
return; |
@@ -1705,35 +1678,91 @@ void GrGLGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bo |
fHWStencilSettings.invalidate(); |
} |
-bool GrGLGpu::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget, |
- int left, int top, |
- int width, int height, |
- GrPixelConfig config, |
- size_t rowBytes) const { |
- // If this rendertarget is aready TopLeft, we don't need to flip. |
+static bool read_pixels_pays_for_y_flip(GrRenderTarget* renderTarget, const GrGLCaps& caps, |
+ int width, int height, GrPixelConfig config, |
+ size_t rowBytes) { |
+ // If this render target is already TopLeft, we don't need to flip. |
if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) { |
return false; |
} |
// if GL can do the flip then we'll never pay for it. |
- if (this->glCaps().packFlipYSupport()) { |
+ if (caps.packFlipYSupport()) { |
return false; |
} |
// If we have to do memcpy to handle non-trim rowBytes then we |
// get the flip for free. Otherwise it costs. |
- if (this->glCaps().packRowLengthSupport()) { |
- return true; |
+ // Note that we're assuming that 0 rowBytes has already been handled and that the width has been |
+ // clipped. |
+ return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes; |
+} |
+ |
+void elevate_draw_preference(GrGpu::DrawPreference* preference, GrGpu::DrawPreference elevation) { |
+ GR_STATIC_ASSERT(GrGpu::kCallerPrefersDraw_DrawPreference > GrGpu::kNoDraw_DrawPreference); |
+ GR_STATIC_ASSERT(GrGpu::kGpuPrefersDraw_DrawPreference > |
+ GrGpu::kCallerPrefersDraw_DrawPreference); |
+ GR_STATIC_ASSERT(GrGpu::kRequireDraw_DrawPreference > GrGpu::kGpuPrefersDraw_DrawPreference); |
+ *preference = SkTMax(*preference, elevation); |
+} |
+ |
+bool GrGLGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes, |
+ GrPixelConfig readConfig, DrawPreference* drawPreference, |
+ ReadPixelTempDrawInfo* tempDrawInfo) { |
+ SkASSERT(drawPreference); |
+ SkASSERT(tempDrawInfo); |
+ SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference); |
+ |
+ if (GrPixelConfigIsCompressed(readConfig)) { |
+ return false; |
} |
- // If we have to do memcpys to handle rowBytes then y-flip is free |
- // Note the rowBytes might be tight to the passed in data, but if data |
- // gets clipped in x to the target the rowBytes will no longer be tight. |
- if (left >= 0 && (left + width) < renderTarget->width()) { |
- return 0 == rowBytes || |
- GrBytesPerPixel(config) * width == rowBytes; |
- } else { |
+ |
+ tempDrawInfo->fSwapRAndB = false; |
+ |
+ // 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. |
+ tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag; |
+ tempDrawInfo->fTempSurfaceDesc.fWidth = width; |
+ tempDrawInfo->fTempSurfaceDesc.fHeight = height; |
+ tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0; |
+ tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL. |
+ tempDrawInfo->fUseExactScratch = SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL); |
+ |
+ // 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; |
+ |
+ if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == readConfig) { |
+ tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig; |
+ } else if (kMesa_GrGLDriver == this->glContext().driver() && |
+ GrBytesPerPixel(readConfig) == 4 && |
+ GrPixelConfigSwapRAndB(readConfig) == 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->fSwapRAndB = true; |
+ elevate_draw_preference(drawPreference, kGpuPrefersDraw_DrawPreference); |
+ } else if (readConfig == kBGRA_8888_GrPixelConfig && |
+ !this->glCaps().readPixelsSupported(this->glInterface(), GR_GL_BGRA, |
+ GR_GL_UNSIGNED_BYTE, srcConfig)) { |
+ tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; |
+ tempDrawInfo->fSwapRAndB = true; |
+ elevate_draw_preference(drawPreference, kRequireDraw_DrawPreference); |
+ } |
+ |
+ GrRenderTarget* srcAsRT = srcSurface->asRenderTarget(); |
+ if (!srcAsRT) { |
+ elevate_draw_preference(drawPreference, kRequireDraw_DrawPreference); |
+ } else if (read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig, |
+ rowBytes)) { |
+ elevate_draw_preference(drawPreference, kGpuPrefersDraw_DrawPreference); |
+ } |
+ |
+ if (kRequireDraw_DrawPreference == *drawPreference && !srcSurface->asTexture()) { |
return false; |
} |
+ return true; |
} |
bool GrGLGpu::onReadPixels(GrRenderTarget* target, |
@@ -1742,6 +1771,8 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target, |
GrPixelConfig config, |
void* buffer, |
size_t rowBytes) { |
+ SkASSERT(target); |
+ |
// We cannot read pixels into a compressed buffer |
if (GrPixelConfigIsCompressed(config)) { |
return false; |