aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrContext.cpp
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2018-03-19 12:29:39 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-19 17:19:45 +0000
commitc9a642edf2d1c7f5380fe829adbb1a692f9969a6 (patch)
tree8d5ee55a8ae11c14a5e14867baf52efa38851a2a /src/gpu/GrContext.cpp
parent8430eace0bbf7258b25e42f289b6a63f38b075e7 (diff)
New read pixels implementation that is simpler but does all conversions on CPU.
Change-Id: Ia548cd24a8544b35a233311706faf48de353b7cf Reviewed-on: https://skia-review.googlesource.com/109902 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/gpu/GrContext.cpp')
-rw-r--r--src/gpu/GrContext.cpp151
1 files changed, 148 insertions, 3 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index f9c941565c..626b3f6ecd 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -26,6 +26,7 @@
#include "GrTextureContext.h"
#include "GrTextureStripAtlas.h"
#include "GrTracing.h"
+#include "SkAutoPixmapStorage.h"
#include "SkConvertPixels.h"
#include "SkDeferredDisplayList.h"
#include "SkGr.h"
@@ -611,6 +612,10 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top,
int height, GrColorType dstColorType,
SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
uint32_t flags) {
+#ifndef SK_LEGACY_GPU_PIXEL_OPS
+ return this->readSurfacePixels2(src, left, top, width, height, dstColorType, dstColorSpace,
+ buffer, rowBytes, flags);
+#endif
// TODO: Color space conversion
ASSERT_SINGLE_OWNER_PRIV
@@ -618,6 +623,10 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top,
SkASSERT(src);
ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
+ SkASSERT(!(flags & kDontFlush_PixelOpsFlag));
+ if (flags & kDontFlush_PixelOpsFlag) {
+ return false;
+ }
// MDB TODO: delay this instantiation until later in the method
if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) {
@@ -667,7 +676,7 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top,
return false;
}
- if (!(kDontFlush_PixelOpsFlag & flags) && srcSurface->surfacePriv().hasPendingWrite()) {
+ if (srcSurface->surfacePriv().hasPendingWrite()) {
this->flush(nullptr); // MDB TODO: tighten this
}
@@ -799,6 +808,12 @@ bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top
}
if (!fContext->caps()->surfaceSupportsWritePixels(dstSurface)) {
+ // We don't expect callers that are skipping flushes to require an intermediate draw.
+ SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
+ if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
+ return false;
+ }
+
GrSurfaceDesc desc;
desc.fConfig = dstProxy->config();
desc.fWidth = width;
@@ -871,7 +886,7 @@ bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top
memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes);
memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes);
}
- top = dstProxy->height() - top - height;
+ top = dstSurface->height() - top - height;
}
} else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
@@ -883,7 +898,7 @@ bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top
}
buffer = tempBuffer.get();
rowBytes = trimRowBytes;
- top = dstProxy->height() - top - height;
+ top = dstSurface->height() - top - height;
}
if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) {
@@ -894,6 +909,136 @@ bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top
rowBytes);
}
+bool GrContextPriv::readSurfacePixels2(GrSurfaceContext* src, int left, int top, int width,
+ int height, GrColorType dstColorType,
+ SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
+ uint32_t flags) {
+ SkASSERT(!(flags & kDontFlush_PixelOpsFlag));
+ if (flags & kDontFlush_PixelOpsFlag){
+ return false;
+ }
+ ASSERT_SINGLE_OWNER_PRIV
+ RETURN_FALSE_IF_ABANDONED_PRIV
+ SkASSERT(src);
+ SkASSERT(buffer);
+ ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
+ GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels2", fContext);
+
+ // MDB TODO: delay this instantiation until later in the method
+ if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) {
+ return false;
+ }
+
+ GrSurfaceProxy* srcProxy = src->asSurfaceProxy();
+ GrSurface* srcSurface = srcProxy->priv().peekSurface();
+
+ if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
+ GrColorTypeBytesPerPixel(dstColorType), &left, &top,
+ &width, &height, &buffer, &rowBytes)) {
+ return false;
+ }
+
+ // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type.
+ bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
+ bool convert = unpremul;
+
+ if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
+ return false;
+ }
+
+ if (!fContext->caps()->surfaceSupportsReadPixels(srcSurface)) {
+ GrSurfaceDesc desc;
+ desc.fConfig = srcProxy->config();
+ desc.fWidth = width;
+ desc.fHeight = height;
+ desc.fSampleCnt = 1;
+ auto tempProxy = this->proxyProvider()->createProxy(
+ desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
+ if (!tempProxy) {
+ return false;
+ }
+ auto tempCtx = this->drawingManager()->makeTextureContext(
+ tempProxy, src->colorSpaceInfo().refColorSpace());
+ if (!tempCtx) {
+ return false;
+ }
+ if (!tempCtx->copy(srcProxy, {left, top, width, height}, {0, 0})) {
+ return false;
+ }
+ return this->readSurfacePixels2(tempCtx.get(), 0, 0, width, height, dstColorType,
+ dstColorSpace, buffer, rowBytes, flags);
+ }
+
+ bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
+ if (flip) {
+ top = srcSurface->height() - top - height;
+ }
+
+ GrColorType allowedColorType =
+ fContext->caps()->supportedReadPixelsColorType(srcProxy->config(), dstColorType);
+ convert = convert || (dstColorType != allowedColorType);
+
+ if (!src->colorSpaceInfo().colorSpace()) {
+ // "Legacy" mode - no color space conversions.
+ dstColorSpace = nullptr;
+ }
+ convert = convert || !SkColorSpace::Equals(dstColorSpace, src->colorSpaceInfo().colorSpace());
+
+ SkAutoPixmapStorage tempPixmap;
+ SkPixmap finalPixmap;
+ if (convert) {
+ SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
+ SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
+ if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
+ return false;
+ }
+ auto tempAT = SkColorTypeIsAlwaysOpaque(srcSkColorType) ? kOpaque_SkAlphaType
+ : kPremul_SkAlphaType;
+ auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
+ src->colorSpaceInfo().refColorSpace());
+ SkASSERT(!unpremul || !SkColorTypeIsAlwaysOpaque(dstSkColorType));
+ auto finalAT = SkColorTypeIsAlwaysOpaque(srcSkColorType)
+ ? kOpaque_SkAlphaType
+ : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
+ auto finalII =
+ SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
+ if (!SkImageInfoValidConversion(finalII, tempII)) {
+ return false;
+ }
+ tempPixmap.alloc(tempII);
+ finalPixmap.reset(finalII, buffer, rowBytes);
+ buffer = tempPixmap.writable_addr();
+ rowBytes = tempPixmap.rowBytes();
+ }
+
+ if (srcSurface->surfacePriv().hasPendingWrite()) {
+ this->flush(nullptr); // MDB TODO: tighten this
+ }
+
+ if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer,
+ rowBytes)) {
+ return false;
+ }
+
+ if (flip) {
+ size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
+ std::unique_ptr<char[]> row(new char[trimRowBytes]);
+ char* upper = reinterpret_cast<char*>(buffer);
+ char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
+ for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
+ memcpy(row.get(), upper, trimRowBytes);
+ memcpy(upper, lower, trimRowBytes);
+ memcpy(lower, row.get(), trimRowBytes);
+ }
+ }
+ if (convert) {
+ if (!tempPixmap.readPixels(finalPixmap)) {
+ return false;
+ }
+ }
+ return true;
+}
+
void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
ASSERT_SINGLE_OWNER_PRIV
RETURN_IF_ABANDONED_PRIV