| Index: src/gpu/GrContext.cpp
|
| diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
|
| index 1c6007414305c3c0c1f938103263aa07f4d5cbfa..17b4b74a3956d284a5a4592a3f82f1558befd4b6 100755
|
| --- a/src/gpu/GrContext.cpp
|
| +++ b/src/gpu/GrContext.cpp
|
| @@ -347,6 +347,14 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
|
| }
|
| }
|
|
|
| + // Trim the params here so that if we wind up making a temporary surface it can be as small as
|
| + // necessary.
|
| + if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
|
| + GrBytesPerPixel(srcConfig), &left, &top, &width,
|
| + &height, &buffer, &rowBytes)) {
|
| + return false;
|
| + }
|
| +
|
| // If we didn't do a direct texture write then we upload the pixels to a texture and draw.
|
| GrRenderTarget* renderTarget = surface->asRenderTarget();
|
| if (!renderTarget) {
|
| @@ -452,25 +460,28 @@ static SkColorType toggle_colortype32(SkColorType ct) {
|
| }
|
| }
|
|
|
| -bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
| - int left, int top, int width, int height,
|
| - GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
|
| - uint32_t flags) {
|
| +bool GrContext::readSurfacePixels(GrSurface* src,
|
| + int left, int top, int width, int height,
|
| + GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
|
| + uint32_t flags) {
|
| RETURN_FALSE_IF_ABANDONED
|
| - ASSERT_OWNED_RESOURCE(target);
|
| - SkASSERT(target);
|
| + ASSERT_OWNED_RESOURCE(src);
|
| + SkASSERT(src);
|
| +
|
| + // Adjust the params so that if we wind up using an intermediate surface we've already done
|
| + // all the trimming and the temporary can be the min size required.
|
| + if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
|
| + GrBytesPerPixel(dstConfig), &left,
|
| + &top, &width, &height, &buffer, &rowBytes)) {
|
| + return false;
|
| + }
|
|
|
| - if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWrite()) {
|
| + if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
|
| this->flush();
|
| }
|
|
|
| // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
|
|
|
| - // 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.
|
| - bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
|
| - width, height, dstConfig,
|
| - rowBytes);
|
| // 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
|
| @@ -479,13 +490,23 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
| GrPixelConfig readConfig = dstConfig;
|
| bool swapRAndB = false;
|
| if (GrPixelConfigSwapRAndB(dstConfig) ==
|
| - fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
|
| + fGpu->preferredReadPixelsConfig(dstConfig, src->config())) {
|
| readConfig = GrPixelConfigSwapRAndB(readConfig);
|
| swapRAndB = true;
|
| }
|
|
|
| - bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
|
| + 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.
|
| return false;
|
| @@ -496,9 +517,11 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
| // 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.
|
| - GrTexture* src = target->asTexture();
|
| - if (src && (swapRAndB || unpremul || flipY)) {
|
| + // 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;
|
| @@ -514,8 +537,8 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
| GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch;
|
| if (0 == left &&
|
| 0 == top &&
|
| - target->width() == width &&
|
| - target->height() == height &&
|
| + src->width() == width &&
|
| + src->height() == height &&
|
| fGpu->fullReadPixelsIsFasterThanPartial()) {
|
| match = GrTextureProvider::kExact_ScratchTexMatch;
|
| }
|
| @@ -529,18 +552,18 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
| GrPaint paint;
|
| SkAutoTUnref<const GrFragmentProcessor> fp;
|
| if (unpremul) {
|
| - fp.reset(this->createPMToUPMEffect(paint.getProcessorDataManager(), src, swapRAndB,
|
| - textureMatrix));
|
| + fp.reset(this->createPMToUPMEffect(paint.getProcessorDataManager(), srcAsTex,
|
| + swapRAndB, textureMatrix));
|
| if (fp) {
|
| unpremul = false; // we no longer need to do this on CPU after the read back.
|
| }
|
| }
|
| // 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) {
|
| + if (fp || flipY || swapRAndB || !srcAsRT) {
|
| if (!fp) {
|
| fp.reset(GrConfigConversionEffect::Create(paint.getProcessorDataManager(),
|
| - src, swapRAndB, GrConfigConversionEffect::kNone_PMConversion,
|
| + srcAsTex, swapRAndB, GrConfigConversionEffect::kNone_PMConversion,
|
| textureMatrix));
|
| }
|
| swapRAndB = false; // we will handle the swap in the draw.
|
| @@ -564,16 +587,15 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
| // we want to read back from the scratch's origin
|
| left = 0;
|
| top = 0;
|
| - target = tempTexture->asRenderTarget();
|
| + rtToRead = tempTexture->asRenderTarget();
|
| }
|
| - this->flushSurfaceWrites(target);
|
| + this->flushSurfaceWrites(tempTexture);
|
| }
|
| }
|
| }
|
|
|
| - if (!fGpu->readPixels(target,
|
| - left, top, width, height,
|
| - readConfig, buffer, rowBytes)) {
|
| + if (!rtToRead ||
|
| + !fGpu->readPixels(rtToRead, left, top, width, height, readConfig, buffer, rowBytes)) {
|
| return false;
|
| }
|
| // Perform any conversions we weren't able to perform using a scratch texture.
|
|
|