Pass alpha type to GrSurfaceContext::read/writePixels and remove flags.
We deduce whether to premul or unpremul based on the the input/output
alpha types. This means we also now support unpremuling on write and
premuling on read.
Class-ify former struct GrPixelInfo. Remove origin and instead pass a
flip bool to GrConvertPixels.
Unifies read/write methods on GrSurfaceContext via automatic conversion
of SkImageInfo to GrPixelInfo and making GrDirectContext an optional
parameter.
Bug: skia:7580
Change-Id: I42f6997852b4b902fb81264c6de68ca9537606aa
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/224281
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrDataUtils.cpp b/src/gpu/GrDataUtils.cpp
index 9dcc25b..bbd6f3d 100644
--- a/src/gpu/GrDataUtils.cpp
+++ b/src/gpu/GrDataUtils.cpp
@@ -469,72 +469,76 @@
pipeline->append_gamut_clamp_if_normalized(fakeII);
}
-bool GrConvertPixels(const GrPixelInfo& dstInfo, void* dst, const GrPixelInfo& srcInfo,
- const void* src, GrSwizzle swizzle) {
+bool GrConvertPixels(const GrPixelInfo& dstInfo, void* dst, size_t dstRB,
+ const GrPixelInfo& srcInfo, const void* src, size_t srcRB,
+ bool flipY, GrSwizzle swizzle) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
-
- if (dstInfo.fWidth != srcInfo.fWidth || srcInfo.fHeight != dstInfo.fHeight) {
+ if (!srcInfo.isValid() || !dstInfo.isValid()) {
return false;
}
- if (dstInfo.fWidth <= 0 || dstInfo.fHeight <= 0) {
+ if (!src || !dst) {
return false;
}
- if (GrColorTypeComponentFlags(dstInfo.fColorInfo.fColorType) & kGray_SkColorTypeComponentFlag) {
+ if (dstInfo.width() != srcInfo.width() || srcInfo.height() != dstInfo.height()) {
+ return false;
+ }
+ if (GrColorTypeComponentFlags(dstInfo.colorType()) & kGray_SkColorTypeComponentFlag) {
// We don't currently support conversion to Gray.
return false;
}
- size_t srcBpp = GrColorTypeBytesPerPixel(srcInfo.fColorInfo.fColorType);
- size_t dstBpp = GrColorTypeBytesPerPixel(dstInfo.fColorInfo.fColorType);
- if (!srcBpp || !dstBpp) {
- // Either src or dst is compressed or kUnknown.
+ if (dstRB < dstInfo.minRowBytes() || srcRB < srcInfo.minRowBytes()) {
return false;
}
+
+ size_t srcBpp = srcInfo.bpp();
+ size_t dstBpp = dstInfo.bpp();
+
// SkRasterPipeline operates on row-pixels not row-bytes.
- SkASSERT(dstInfo.fRowBytes % dstBpp == 0);
- SkASSERT(srcInfo.fRowBytes % srcBpp == 0);
+ SkASSERT(dstRB % dstBpp == 0);
+ SkASSERT(srcRB % srcBpp == 0);
SkRasterPipeline::StockStage load;
bool srcIsNormalized;
- auto loadSwizzle =
- get_load_and_get_swizzle(srcInfo.fColorInfo.fColorType, &load, &srcIsNormalized);
+ auto loadSwizzle = get_load_and_get_swizzle(srcInfo.colorType(), &load, &srcIsNormalized);
loadSwizzle = GrSwizzle::Concat(loadSwizzle, swizzle);
SkRasterPipeline::StockStage store;
bool dstIsNormalized;
- auto storeSwizzle =
- get_dst_swizzle_and_store(dstInfo.fColorInfo.fColorType, &store, &dstIsNormalized);
+ auto storeSwizzle = get_dst_swizzle_and_store(dstInfo.colorType(), &store, &dstIsNormalized);
+ bool premul = srcInfo.alphaType() == kUnpremul_SkAlphaType &&
+ dstInfo.alphaType() == kPremul_SkAlphaType;
+ bool unpremul = srcInfo.alphaType() == kPremul_SkAlphaType &&
+ dstInfo.alphaType() == kUnpremul_SkAlphaType;
bool alphaOrCSConversion =
- (srcInfo.fColorInfo.fAlphaType != dstInfo.fColorInfo.fAlphaType &&
- srcInfo.fColorInfo.fAlphaType != kOpaque_SkAlphaType) ||
- !SkColorSpace::Equals(srcInfo.fColorInfo.fColorSpace, dstInfo.fColorInfo.fColorSpace);
+ premul || unpremul || !SkColorSpace::Equals(srcInfo.colorSpace(), dstInfo.colorSpace());
bool clampGamut;
SkTLazy<SkColorSpaceXformSteps> steps;
GrSwizzle loadStoreSwizzle;
if (alphaOrCSConversion) {
- steps.init(srcInfo.fColorInfo.fColorSpace, srcInfo.fColorInfo.fAlphaType,
- dstInfo.fColorInfo.fColorSpace, dstInfo.fColorInfo.fAlphaType);
- clampGamut = dstIsNormalized && dstInfo.fColorInfo.fAlphaType == kPremul_SkAlphaType;
+ steps.init(srcInfo.colorSpace(), srcInfo.alphaType(),
+ dstInfo.colorSpace(), dstInfo.alphaType());
+ clampGamut = dstIsNormalized && dstInfo.alphaType() == kPremul_SkAlphaType;
} else {
- clampGamut = dstIsNormalized && !srcIsNormalized &&
- dstInfo.fColorInfo.fAlphaType == kPremul_SkAlphaType;
+ clampGamut =
+ dstIsNormalized && !srcIsNormalized && dstInfo.alphaType() == kPremul_SkAlphaType;
if (!clampGamut) {
loadStoreSwizzle = GrSwizzle::Concat(loadSwizzle, storeSwizzle);
}
}
int cnt = 1;
- int height = srcInfo.fHeight;
- SkRasterPipeline_MemoryCtx srcCtx{const_cast<void*>(src), SkToInt(srcInfo.fRowBytes / srcBpp)},
- dstCtx{ dst , SkToInt(dstInfo.fRowBytes / dstBpp)};
+ int height = srcInfo.height();
+ SkRasterPipeline_MemoryCtx srcCtx{const_cast<void*>(src), SkToInt(srcRB / srcBpp)},
+ dstCtx{ dst , SkToInt(dstRB / dstBpp)};
- if (srcInfo.fOrigin != dstInfo.fOrigin) {
+ if (flipY) {
// It *almost* works to point the src at the last row and negate the stride and run the
// whole rectangle. However, SkRasterPipeline::run()'s control loop uses size_t loop
// variables so it winds up relying on unsigned overflow math. It works out in practice
// but UBSAN says "no!" as it's technically undefined and in theory a compiler could emit
// code that didn't do what is intended. So we go one row at a time. :(
- srcCtx.pixels = static_cast<char*>(srcCtx.pixels) + srcInfo.fRowBytes * (height - 1);
+ srcCtx.pixels = static_cast<char*>(srcCtx.pixels) + srcRB * (height - 1);
std::swap(cnt, height);
}
for (int i = 0; i < cnt; ++i) {
@@ -558,9 +562,9 @@
}
}
pipeline.append(store, &dstCtx);
- pipeline.run(0, 0, srcInfo.fWidth, height);
- srcCtx.pixels = static_cast<char*>(srcCtx.pixels) - srcInfo.fRowBytes;
- dstCtx.pixels = static_cast<char*>(dstCtx.pixels) + dstInfo.fRowBytes;
+ pipeline.run(0, 0, srcInfo.width(), height);
+ srcCtx.pixels = static_cast<char*>(srcCtx.pixels) - srcRB;
+ dstCtx.pixels = static_cast<char*>(dstCtx.pixels) + dstRB;
}
return true;
}