Verify YUVA channel information and add premultiplied alpha
Bug: skia:7903
Change-Id: Ia5394192febd1ffb6f2dcf700fc551407ceb80c1
Reviewed-on: https://skia-review.googlesource.com/c/170265
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index d324c5a..567e91e 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -90,6 +90,9 @@
const GrSamplerState::Filter* filterOrNullForBicubic) {
// Check simple cases to see if we need to fall back to flattening the image
+ // TODO: See if we can relax this -- for example, if filterConstraint
+ // is kYes_FilterConstraint we still may not need a TextureDomain
+ // in some cases.
if (!textureMatrix.isIdentity() || kNo_FilterConstraint != filterConstraint ||
!coordsLimitedToConstraintRect || !filterOrNullForBicubic) {
return this->INHERITED::createFragmentProcessor(textureMatrix, constraintRect,
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp
index 1ab100a..61d2456 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -127,6 +127,8 @@
fragBuilder->codeAppendf(
"float a = tmp%d.%c;", _outer.yuvaIndex(3).fIndex,
kChannelToChar[(int)_outer.yuvaIndex(3).fChannel]);
+ // premultiply alpha
+ fragBuilder->codeAppend("yuvOne *= a;");
} else {
fragBuilder->codeAppendf("float a = 1.0;");
}
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index cb0219f..b8aa1a5 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -39,7 +39,6 @@
#include "SkImage_Gpu.h"
#include "SkMipMap.h"
#include "SkTraceEvent.h"
-#include "SkYUVAIndex.h"
#include "effects/GrYUVtoRGBEffect.h"
#include "gl/GrGLTexture.h"
@@ -127,8 +126,8 @@
}
sk_sp<GrTextureProxy> tempTextureProxies[4];
- if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, origin,
- tempTextureProxies)) {
+ if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
+ origin, tempTextureProxies)) {
return nullptr;
}
@@ -138,8 +137,9 @@
return nullptr;
}
+ SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
// MDB: this call is okay bc we know 'renderTargetContext' was exact
- return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
+ return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
renderTargetContext->asTextureProxyRef(),
renderTargetContext->colorSpaceInfo().refColorSpace(),
isBudgeted);
@@ -180,8 +180,9 @@
sk_sp<SkColorSpace> imageColorSpace) {
GrBackendTexture backendTextureCopy = backendTexture;
+ SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
if (!SkImage_Gpu::ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig,
- kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)) {
+ kRGBA_8888_SkColorType, at, nullptr)) {
return nullptr;
}
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 332e725..8360361 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -291,7 +291,8 @@
}
bool SkImage_GpuBase::MakeTempTextureProxies(GrContext* ctx, const GrBackendTexture yuvaTextures[],
- int numTextures, GrSurfaceOrigin imageOrigin,
+ int numTextures, const SkYUVAIndex yuvaIndices[4],
+ GrSurfaceOrigin imageOrigin,
sk_sp<GrTextureProxy> tempTextureProxies[4]) {
GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
@@ -312,6 +313,33 @@
if (!tempTextureProxies[textureIndex]) {
return false;
}
+
+ // Check that each texture contains the channel data for the corresponding YUVA index
+ GrPixelConfig config = yuvaTexturesCopy[textureIndex].fConfig;
+ for (int yuvaIndex = 0; yuvaIndex < SkYUVAIndex::kIndexCount; ++yuvaIndex) {
+ if (yuvaIndices[yuvaIndex].fIndex == textureIndex) {
+ switch (yuvaIndices[yuvaIndex].fChannel) {
+ case SkColorChannel::kR:
+ if (kAlpha_8_as_Alpha_GrPixelConfig == config) {
+ return false;
+ }
+ break;
+ case SkColorChannel::kG:
+ case SkColorChannel::kB:
+ if (kAlpha_8_as_Alpha_GrPixelConfig == config ||
+ kAlpha_8_as_Red_GrPixelConfig == config) {
+ return false;
+ }
+ break;
+ case SkColorChannel::kA:
+ default:
+ if (kRGB_888_GrPixelConfig == config) {
+ return false;
+ }
+ break;
+ }
+ }
+ }
}
return true;
@@ -329,8 +357,6 @@
GrPaint paint;
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- // TODO: modify the YUVtoRGBEffect to do premul if needed
- // (e.g., if SkImage_GpuYUVA::fImageAlphaType is kPremul_AlphaType)
paint.addColorFragmentProcessor(GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
yuvColorSpace,
GrSamplerState::Filter::kNearest));
diff --git a/src/image/SkImage_GpuBase.h b/src/image/SkImage_GpuBase.h
index 38b6065..9a85e56 100644
--- a/src/image/SkImage_GpuBase.h
+++ b/src/image/SkImage_GpuBase.h
@@ -11,6 +11,7 @@
#include "GrBackendSurface.h"
#include "GrTypesPriv.h"
#include "SkImage_Base.h"
+#include "SkYUVAIndex.h"
class GrContext;
class SkColorSpace;
@@ -62,9 +63,15 @@
GrPixelConfig* config, SkColorType ct, SkAlphaType at,
sk_sp<SkColorSpace> cs);
static bool MakeTempTextureProxies(GrContext* ctx, const GrBackendTexture yuvaTextures[],
- int numTextures, GrSurfaceOrigin imageOrigin,
+ int numTextures, const SkYUVAIndex [4],
+ GrSurfaceOrigin imageOrigin,
sk_sp<GrTextureProxy> tempTextureProxies[4]);
+ static SkAlphaType GetAlphaTypeFromYUVAIndices(const SkYUVAIndex yuvaIndices[4]) {
+ return -1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex ? kPremul_SkAlphaType
+ : kOpaque_SkAlphaType;
+ }
+
typedef ReleaseContext TextureContext;
typedef void(*TextureFulfillProc)(TextureContext textureContext, GrBackendTexture* outTexture);
typedef void(*PromiseDoneProc)(TextureContext textureContext);
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index a492448..ab13835 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -32,8 +32,7 @@
// If an alpha channel is present we always switch to kPremul. This is because,
// although the planar data is always un-premul, the final interleaved RGB image
// is/would-be premul.
- -1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex ? kPremul_SkAlphaType
- : kOpaque_SkAlphaType,
+ GetAlphaTypeFromYUVAIndices(yuvaIndices),
budgeted, imageColorSpace)
, fNumProxies(numProxies)
, fYUVColorSpace(colorSpace)
@@ -132,14 +131,11 @@
}
sk_sp<GrTextureProxy> tempTextureProxies[4];
- if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, imageOrigin,
- tempTextureProxies)) {
+ if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
+ imageOrigin, tempTextureProxies)) {
return nullptr;
}
- // TODO: Check that for each plane, the channel actually exist in the image source we are
- // reading from.
-
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(ctx), imageSize.width(), imageSize.height(),
kNeedNewImageUniqueID, colorSpace, tempTextureProxies,
numTextures, yuvaIndices, imageOrigin, imageColorSpace,
diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h
index aee49d4..e5a4469 100644
--- a/src/image/SkImage_GpuYUVA.h
+++ b/src/image/SkImage_GpuYUVA.h
@@ -12,7 +12,6 @@
#include "GrContext.h"
#include "SkCachedData.h"
#include "SkImage_GpuBase.h"
-#include "SkYUVAIndex.h"
class GrTexture;
struct SkYUVASizeInfo;