Revert "Add function to GrDataUtils to handle color conversions."
This reverts commit 55091020435c876d12f2d74697b21edbc98e13fa.
Reason for revert: valgrind issues
Original change's description:
> Add function to GrDataUtils to handle color conversions.
>
> Like SkConvertPixels but knows about all GrColorTypes, origin, and can
> apply an arbitrary GrSwizzle.
>
> Use in GrSurfaceContext read/write pixels methods.
>
> Add support for '0' to GrSwizzle.
>
>
> Change-Id: Ib9dd215fcb0ee8b33c4020893c22b4ab7ce1f40b
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/220761
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Greg Daniel <egdaniel@google.com>
TBR=egdaniel@google.com,bsalomon@google.com,brianosman@google.com
Change-Id: If50f3e26875787d9309009e9c701774fbad0afda
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221538
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 4b29ce0..71113b4 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -13,7 +13,6 @@
#include "src/core/SkAutoPixmapStorage.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -225,52 +224,71 @@
buffer, rowBytes, flags);
}
+ bool convert = unpremul || needColorConversion;
+
bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
- auto supportedRead = caps->supportedReadPixelsColorType(
- srcProxy->config(), srcProxy->backendFormat(), dstColorType);
+ if (flip) {
+ top = srcSurface->height() - top - height;
+ }
- bool convert = unpremul || needColorConversion || flip ||
- (dstColorType != supportedRead.fColorType) ||
- supportedRead.fSwizzle != GrSwizzle::RGBA();
+ GrColorType allowedColorType = caps->supportedReadPixelsColorType(srcProxy->config(),
+ dstColorType);
+ convert = convert || (dstColorType != allowedColorType);
- std::unique_ptr<char[]> tmpPixels;
- GrPixelInfo tmpInfo;
- GrPixelInfo dstInfo;
- void* readDst = buffer;
+ SkAutoPixmapStorage tempPixmap;
+ SkPixmap finalPixmap;
if (convert) {
- tmpInfo.fColorInfo.fColorType = supportedRead.fColorType;
- tmpInfo.fColorInfo.fAlphaType = kPremul_SkAlphaType;
- tmpInfo.fColorInfo.fColorSpace = this->colorSpaceInfo().colorSpace();
- tmpInfo.fOrigin = srcProxy->origin();
- tmpInfo.fRowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * width;
-
- dstInfo.fColorInfo.fColorType = dstColorType;
- dstInfo.fColorInfo.fAlphaType = unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
- dstInfo.fColorInfo.fColorSpace = dstColorSpace;
- dstInfo.fOrigin = kTopLeft_GrSurfaceOrigin;
- dstInfo.fRowBytes = rowBytes;
-
- dstInfo.fWidth = tmpInfo.fWidth = width;
- dstInfo.fHeight = tmpInfo.fHeight = height;
-
- size_t size = tmpInfo.fRowBytes * height;
- tmpPixels.reset(new char[size]);
- // Chrome MSAN bots require this.
- sk_bzero(tmpPixels.get(), size);
- readDst = tmpPixels.get();
- rowBytes = tmpInfo.fRowBytes;
- top = flip ? srcSurface->height() - top - height : top;
+ SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
+ SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
+ bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
+ bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
+ if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
+ return false;
+ }
+ auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+ auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
+ this->colorSpaceInfo().refColorSpace());
+ SkASSERT(!unpremul || !dstAlwaysOpaque);
+ auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
+ ? 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;
+ }
+ if (!tempPixmap.tryAlloc(tempII)) {
+ return false;
+ }
+ finalPixmap.reset(finalII, buffer, rowBytes);
+ buffer = tempPixmap.writable_addr();
+ rowBytes = tempPixmap.rowBytes();
+ // Chrome msan bots require this.
+ sk_bzero(buffer, tempPixmap.computeByteSize());
}
direct->priv().flushSurface(srcProxy);
- if (!direct->priv().getGpu()->readPixels(srcSurface, left, top, width, height,
- supportedRead.fColorType, readDst, rowBytes)) {
+ if (!direct->priv().getGpu()->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) {
- return GrConvertPixels(dstInfo, buffer, tmpInfo, tmpPixels.get(), supportedRead.fSwizzle);
+ if (!tempPixmap.readPixels(finalPixmap)) {
+ return false;
+ }
}
return true;
}
@@ -365,8 +383,8 @@
// data into it which requires the origins to match. If the final proxy is a render target
// we can use a draw instead which doesn't have this origin restriction. Thus for render
// targets we will use top left and otherwise we will make the origins match.
- GrSurfaceOrigin tempOrigin =
- this->asRenderTargetContext() ? kTopLeft_GrSurfaceOrigin : dstProxy->origin();
+ GrSurfaceOrigin tempOrigin = this->asRenderTargetContext() ? kTopLeft_GrSurfaceOrigin :
+ dstProxy->origin();
auto tempProxy = direct->priv().proxyProvider()->createProxy(
format, desc, tempOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
@@ -420,44 +438,63 @@
return true;
}
+ bool convert = premul || needColorConversion;
+
if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
return false;
}
GrColorType allowedColorType = caps->supportedWritePixelsColorType(dstProxy->config(),
srcColorType);
- bool convert = premul || needColorConversion || (srcColorType != allowedColorType) ||
- dstProxy->origin() == kBottomLeft_GrSurfaceOrigin;
+ convert = convert || (srcColorType != allowedColorType);
- std::unique_ptr<char[]> tmpPixels;
+ std::unique_ptr<char[]> tempBuffer;
if (convert) {
- GrPixelInfo srcInfo;
- srcInfo.fColorInfo.fAlphaType = (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
- srcInfo.fColorInfo.fColorType = srcColorType;
- srcInfo.fColorInfo.fColorSpace = srcColorSpace;
- srcInfo.fRowBytes = srcRowBytes;
- srcInfo.fOrigin = kTopLeft_GrSurfaceOrigin;
-
- GrPixelInfo tmpInfo;
- tmpInfo.fColorInfo.fAlphaType = kPremul_SkAlphaType;
- tmpInfo.fColorInfo.fColorType = allowedColorType;
- tmpInfo.fColorInfo.fColorSpace = this->colorSpaceInfo().colorSpace();
- tmpInfo.fRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
- tmpInfo.fOrigin = dstProxy->origin();
-
- srcInfo.fWidth = tmpInfo.fWidth = width;
- srcInfo.fHeight = tmpInfo.fHeight = height;
-
- tmpPixels.reset(new char[tmpInfo.fRowBytes * height]);
-
- GrConvertPixels(tmpInfo, tmpPixels.get(), srcInfo, srcBuffer);
-
- srcColorType = tmpInfo.fColorInfo.fColorType;
- srcBuffer = tmpPixels.get();
- srcRowBytes = tmpInfo.fRowBytes;
+ auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
+ auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
+ if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
+ return false;
+ }
+ auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
+ ? kOpaque_SkAlphaType
+ : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
+ SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
+ sk_ref_sp(srcColorSpace)),
+ srcBuffer, srcRowBytes);
+ auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
+ this->colorSpaceInfo().refColorSpace());
+ auto size = tempSrcII.computeMinByteSize();
+ if (!size) {
+ return false;
+ }
+ tempBuffer.reset(new char[size]);
+ SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
+ if (!src.readPixels(tempSrc)) {
+ return false;
+ }
+ srcColorType = allowedColorType;
+ srcBuffer = tempSrc.addr();
+ srcRowBytes = tempSrc.rowBytes();
if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+ std::unique_ptr<char[]> row(new char[srcRowBytes]);
+ for (int y = 0; y < height / 2; ++y) {
+ memcpy(row.get(), tempSrc.addr(0, y), srcRowBytes);
+ memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), srcRowBytes);
+ memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), srcRowBytes);
+ }
top = dstSurface->height() - top - height;
}
+ } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+ size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
+ tempBuffer.reset(new char[trimRowBytes * height]);
+ char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
+ const char* src = reinterpret_cast<const char*>(srcBuffer);
+ for (int i = 0; i < height; ++i, src += srcRowBytes, dst -= trimRowBytes) {
+ memcpy(dst, src, trimRowBytes);
+ }
+ srcBuffer = tempBuffer.get();
+ srcRowBytes = trimRowBytes;
+ top = dstSurface->height() - top - height;
}
// On platforms that prefer flushes over VRAM use (i.e., ANGLE) we're better off forcing a