Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Unified Diff: src/gpu/GrContext.cpp

Issue 1255483005: Attempt to somewhat simplify GrContext::readSurfacePixels interaction with GrGpu. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/gpu/GrGpu.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrContext.cpp
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 17b4b74a3956d284a5a4592a3f82f1558befd4b6..ba02d60b11ece81231086a890d33214dc03e3601 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -450,16 +450,6 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
return true;
}
-// toggles between RGBA and BGRA
-static SkColorType toggle_colortype32(SkColorType ct) {
- if (kRGBA_8888_SkColorType == ct) {
- return kBGRA_8888_SkColorType;
- } else {
- SkASSERT(kBGRA_8888_SkColorType == ct);
- return kRGBA_8888_SkColorType;
- }
-}
-
bool GrContext::readSurfacePixels(GrSurface* src,
int left, int top, int width, int height,
GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
@@ -480,126 +470,87 @@ bool GrContext::readSurfacePixels(GrSurface* src,
this->flush();
}
- // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
-
- // We ignore the preferred config if it is different than our config unless it is an R/B swap.
- // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped
- // config. Then we will call readPixels on the scratch with the swapped config. The swaps during
- // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
- // dstConfig.
- GrPixelConfig readConfig = dstConfig;
- bool swapRAndB = false;
- if (GrPixelConfigSwapRAndB(dstConfig) ==
- fGpu->preferredReadPixelsConfig(dstConfig, src->config())) {
- readConfig = GrPixelConfigSwapRAndB(readConfig);
- swapRAndB = true;
- }
-
- bool flipY = false;
- GrRenderTarget* srcAsRT = src->asRenderTarget();
- if (srcAsRT) {
- // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down.
- // We'll either do the flipY by drawing into a scratch with a matrix or on the cpu after the
- // read.
- flipY = fGpu->readPixelsWillPayForYFlip(srcAsRT, left, top,
- width, height, dstConfig,
- rowBytes);
- }
-
bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
- // The unpremul flag is only allowed for these two configs.
+ // The unpremul flag is only allowed for 8888 configs.
return false;
}
- SkAutoTUnref<GrTexture> tempTexture;
-
- // If the src is a texture and we would have to do conversions after read pixels, we instead
- // do the conversions by drawing the src to a scratch texture. If we handle any of the
- // conversions in the draw we set the corresponding bool to false so that we don't reapply it
- // on the read back pixels. We also do an intermediate draw if the src is not a render target as
- // GrGpu currently supports reading from render targets but not textures.
- GrTexture* srcAsTex = src->asTexture();
- GrRenderTarget* rtToRead = srcAsRT;
- if (srcAsTex && (swapRAndB || unpremul || flipY || !srcAsRT)) {
- // Make the scratch a render so we can read its pixels.
- GrSurfaceDesc desc;
- desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fWidth = width;
- desc.fHeight = height;
- desc.fConfig = readConfig;
- desc.fOrigin = kTopLeft_GrSurfaceOrigin;
-
- // When a full read back is faster than a partial we could always make the scratch exactly
- // match the passed rect. However, if we see many different size rectangles we will trash
- // our texture cache and pay the cost of creating and destroying many textures. So, we only
- // request an exact match when the caller is reading an entire RT.
+ GrGpu::DrawPreference drawPreference = unpremul ? GrGpu::kCallerPrefersDraw_DrawPreference :
+ GrGpu::kNoDraw_DrawPreference;
+ GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
+ if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
+ &tempDrawInfo)) {
+ return false;
+ }
+
+ GrRenderTarget* rtToRead = src->asRenderTarget();
+ bool didTempDraw = false;
+ if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch;
- if (0 == left &&
- 0 == top &&
- src->width() == width &&
- src->height() == height &&
- fGpu->fullReadPixelsIsFasterThanPartial()) {
- match = GrTextureProvider::kExact_ScratchTexMatch;
+ if (tempDrawInfo.fUseExactScratch) {
+ // We only respect this when the entire src is being read. Otherwise we can trigger too
+ // many odd ball texture sizes and trash the cache.
+ if (width == src->width() && height == src->height()) {
+ match = GrTextureProvider::kExact_ScratchTexMatch;
+ }
}
- tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match));
- if (tempTexture) {
- // compute a matrix to perform the draw
+ SkAutoTUnref<GrTexture> temp;
+ temp.reset(this->textureProvider()->refScratchTexture(tempDrawInfo.fTempSurfaceDesc, match));
+ if (temp) {
SkMatrix textureMatrix;
- textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
+ textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
textureMatrix.postIDiv(src->width(), src->height());
-
GrPaint paint;
SkAutoTUnref<const GrFragmentProcessor> fp;
if (unpremul) {
- fp.reset(this->createPMToUPMEffect(paint.getProcessorDataManager(), srcAsTex,
- swapRAndB, textureMatrix));
+ fp.reset(this->createPMToUPMEffect(
+ paint.getProcessorDataManager(), src->asTexture(), tempDrawInfo.fSwapRAndB,
+ textureMatrix));
if (fp) {
unpremul = false; // we no longer need to do this on CPU after the read back.
+ } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
+ // We only wanted to do the draw in order to perform the unpremul so don't
+ // bother.
+ temp.reset(NULL);
}
}
- // If we failed to create a PM->UPM effect and have no other conversions to perform then
- // there is no longer any point to using the scratch.
- if (fp || flipY || swapRAndB || !srcAsRT) {
- if (!fp) {
- fp.reset(GrConfigConversionEffect::Create(paint.getProcessorDataManager(),
- srcAsTex, swapRAndB, GrConfigConversionEffect::kNone_PMConversion,
- textureMatrix));
- }
- swapRAndB = false; // we will handle the swap in the draw.
-
- // We protect the existing geometry here since it may not be
- // clear to the caller that a draw operation (i.e., drawSimpleRect)
- // can be invoked in this method
- {
- GrDrawContext* drawContext = this->drawContext();
- if (!drawContext) {
- return false;
- }
-
- paint.addColorProcessor(fp);
-
- SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
-
- drawContext->drawRect(tempTexture->asRenderTarget(), GrClip::WideOpen(), paint,
- SkMatrix::I(), rect, NULL);
-
- // we want to read back from the scratch's origin
- left = 0;
- top = 0;
- rtToRead = tempTexture->asRenderTarget();
- }
- this->flushSurfaceWrites(tempTexture);
+ if (!fp && temp) {
+ fp.reset(GrConfigConversionEffect::Create(
+ paint.getProcessorDataManager(), src->asTexture(), tempDrawInfo.fSwapRAndB,
+ GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
+ }
+ if (fp) {
+ paint.addColorProcessor(fp);
+ SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+ GrDrawContext* drawContext = this->drawContext();
+ drawContext->drawRect(temp->asRenderTarget(), GrClip::WideOpen(), paint,
+ SkMatrix::I(), rect, NULL);
+ rtToRead = temp->asRenderTarget();
+ left = 0;
+ top = 0;
+ didTempDraw = true;
}
}
}
- if (!rtToRead ||
- !fGpu->readPixels(rtToRead, left, top, width, height, readConfig, buffer, rowBytes)) {
+ if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
return false;
}
- // Perform any conversions we weren't able to perform using a scratch texture.
- if (unpremul || swapRAndB) {
+ GrPixelConfig configToRead = dstConfig;
+ if (didTempDraw) {
+ this->flushSurfaceWrites(rtToRead);
+ // We swapped R and B while doing the temp draw. Swap back on the read.
+ if (tempDrawInfo.fSwapRAndB) {
+ configToRead = GrPixelConfigSwapRAndB(dstConfig);
+ }
+ }
+ if (!fGpu->readPixels(rtToRead, left, top, width, height, configToRead, buffer, rowBytes)) {
+ return false;
+ }
+
+ // Perform umpremul conversion if we weren't able to perform it as a draw.
+ if (unpremul) {
SkDstPixelInfo dstPI;
if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NULL)) {
return false;
@@ -609,7 +560,7 @@ bool GrContext::readSurfacePixels(GrSurface* src,
dstPI.fRowBytes = rowBytes;
SkSrcPixelInfo srcPI;
- srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType;
+ srcPI.fColorType = dstPI.fColorType;
srcPI.fAlphaType = kPremul_SkAlphaType;
srcPI.fPixels = buffer;
srcPI.fRowBytes = rowBytes;
« no previous file with comments | « no previous file | src/gpu/GrGpu.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698