Bundle shared SkImage_Gpu methods.

Also adds an enum to make YUV index more explicit.

Bug: skia:7903
Change-Id: I21ae4cac126275fa7fd257235910fd3be155d293
Reviewed-on: https://skia-review.googlesource.com/c/159160
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Jim Van Verth 2018-10-03 10:47:05 -04:00 committed by Skia Commit-Bot
parent 08417bccf2
commit 49fdd7ad18
8 changed files with 169 additions and 122 deletions

View File

@ -542,6 +542,8 @@ skia_gpu_sources = [
"$_src/image/SkImage_Gpu.h",
"$_src/image/SkImage_Gpu.cpp",
"$_src/image/SkImage_GpuShared.h",
"$_src/image/SkImage_GpuShared.cpp",
"$_src/image/SkImage_GpuYUVA.h",
"$_src/image/SkImage_GpuYUVA.cpp",
"$_src/image/SkSurface_Gpu.h",

View File

@ -116,6 +116,14 @@ enum SkImageSourceChannel {
to read from.
*/
struct SK_API SkYUVAIndex {
// Index in the array of SkYUVAIndex
enum Index {
kY_Index = 0,
kU_Index = 1,
kV_Index = 2,
kA_Index = 3
};
/** The index is a number between -1..3 which definies which image source to read from, where -1
* means the image source doesn't exist. The assumption is we will always have image sources for
* each of YUV planes, but optionally have image source for A plane. */

View File

@ -37,6 +37,7 @@
#include "SkGr.h"
#include "SkImageInfoPriv.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuShared.h"
#include "SkMipMap.h"
#include "SkPixelRef.h"
#include "SkReadPixelsRec.h"
@ -44,6 +45,8 @@
#include "effects/GrYUVtoRGBEffect.h"
#include "gl/GrGLTexture.h"
using namespace SkImage_GpuShared;
SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
sk_sp<GrTextureProxy> proxy, sk_sp<SkColorSpace> colorSpace,
SkBudgeted budgeted)
@ -121,14 +124,8 @@ sk_sp<GrTextureProxy> SkImage_Gpu::asTextureProxyRef(GrContext* context,
SkColorSpace* dstColorSpace,
sk_sp<SkColorSpace>* texColorSpace,
SkScalar scaleAdjust[2]) const {
if (context->uniqueID() != fContext->uniqueID()) {
SkASSERT(0);
return nullptr;
}
GrTextureAdjuster adjuster(fContext.get(), fProxy, this->alphaType(), this->uniqueID(),
this->fColorSpace.get());
return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust);
return AsTextureProxyRef(context, params, dstColorSpace, texColorSpace, scaleAdjust,
fContext.get(), this, fAlphaType, fColorSpace.get());
}
static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {
@ -246,28 +243,6 @@ bool SkImage_Gpu::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size
return true;
}
sk_sp<SkImage> SkImage_Gpu::onMakeSubset(const SkIRect& subset) const {
GrSurfaceDesc desc;
desc.fWidth = subset.width();
desc.fHeight = subset.height();
desc.fConfig = fProxy->config();
sk_sp<GrSurfaceContext> sContext(fContext->contextPriv().makeDeferredSurfaceContext(
desc, fProxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, fBudgeted));
if (!sContext) {
return nullptr;
}
if (!sContext->copy(fProxy.get(), subset, SkIPoint::Make(0, 0))) {
return nullptr;
}
// MDB: this call is okay bc we know 'sContext' was kExact
return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
fAlphaType, sContext->asTextureProxyRef(),
fColorSpace, fBudgeted);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
@ -291,22 +266,6 @@ static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
std::move(colorSpace), SkBudgeted::kNo);
}
static bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex,
GrPixelConfig* config, SkColorType ct, SkAlphaType at,
sk_sp<SkColorSpace> cs) {
if (!tex.isValid()) {
return false;
}
// TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to
// create a fake image info here.
SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs);
if (!SkImageInfoIsValid(info)) {
return false;
}
return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config);
}
sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
const GrBackendTexture& tex, GrSurfaceOrigin origin,
SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
@ -315,7 +274,7 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
return nullptr;
}
GrBackendTexture texCopy = tex;
if (!validate_backend_texture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) {
if (!ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) {
return nullptr;
}
return new_wrapped_texture_common(ctx, texCopy, origin, at, std::move(cs),
@ -331,7 +290,7 @@ sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
return nullptr;
}
GrBackendTexture texCopy = tex;
if (!validate_backend_texture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) {
if (!ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) {
return nullptr;
}
return new_wrapped_texture_common(ctx, texCopy, origin, at, std::move(cs),
@ -371,8 +330,8 @@ sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(
yuvaTexturesCopy[yuvaIndex.fIndex] = yuvaTextures[yuvaIndex.fIndex];
// TODO: Instead of using assumption about whether it is NV12 format to guess colorType,
// actually use channel information here.
if (!validate_backend_texture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig,
ct, kPremul_SkAlphaType, nullptr)) {
if (!ValidateBackendTexture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig,
ct, kPremul_SkAlphaType, nullptr)) {
return nullptr;
}
}
@ -469,8 +428,8 @@ sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
sk_sp<SkColorSpace> imageColorSpace) {
GrBackendTexture backendTextureCopy = backendTexture;
if (!validate_backend_texture(ctx, backendTextureCopy, &backendTextureCopy.fConfig, kRGBA_8888_SkColorType,
kPremul_SkAlphaType, nullptr)) {
if (!ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig,
kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)) {
return nullptr;
}
@ -864,7 +823,7 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseYUVATexture(GrContext* context,
bool slotUsed[4] = { false, false, false, false };
for (int i = 0; i < 4; ++i) {
if (yuvaIndices[i].fIndex < 0) {
SkASSERT(3 == i); // We had better have YUV channels
SkASSERT(SkYUVAIndex::kA_Index == i); // We had better have YUV channels
continue;
}
@ -903,7 +862,7 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseYUVATexture(GrContext* context,
desc.fWidth = imageWidth;
desc.fHeight = imageHeight;
// Hack since we're just returning the Y-plane
desc.fConfig = params.fConfigs[params.fLocalIndices[0].fIndex];
desc.fConfig = params.fConfigs[params.fLocalIndices[SkYUVAIndex::kY_Index].fIndex];
desc.fSampleCnt = 1;
@ -936,7 +895,7 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseYUVATexture(GrContext* context,
// For the time being, simply return the Y-plane. The reason for this is that
// this lazy proxy is instantiated at flush time, after the sort, therefore
// we cannot be introducing a new opList (in order to render the YUV texture).
int yIndex = params.fLocalIndices[0].fIndex;
int yIndex = params.fLocalIndices[SkYUVAIndex::kY_Index].fIndex;
return params.fPromiseHelpers[yIndex].getTexture(resourceProvider,
params.fConfigs[yIndex]);
#else

View File

@ -14,6 +14,7 @@
#include "SkGr.h"
#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkImage_GpuShared.h"
class GrTexture;
@ -28,7 +29,10 @@ public:
SkImageInfo onImageInfo() const override;
bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override;
sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
sk_sp<SkImage> onMakeSubset(const SkIRect& subset) const override {
return SkImage_GpuShared::OnMakeSubset(subset, fContext, this, fAlphaType, fColorSpace,
fBudgeted);
}
GrContext* context() const override { return fContext.get(); }
GrTextureProxy* peekProxy() const override {

View File

@ -0,0 +1,79 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrBackendSurface.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrTextureAdjuster.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuShared.h"
namespace SkImage_GpuShared {
bool ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex,
GrPixelConfig* config, SkColorType ct, SkAlphaType at,
sk_sp<SkColorSpace> cs) {
if (!tex.isValid()) {
return false;
}
// TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to
// create a fake image info here.
SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs);
if (!SkImageInfoIsValid(info)) {
return false;
}
return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config);
}
sk_sp<GrTextureProxy> AsTextureProxyRef(GrContext* context,
const GrSamplerState& params,
SkColorSpace* dstColorSpace,
sk_sp<SkColorSpace>* texColorSpace,
SkScalar scaleAdjust[2],
GrContext* imageContext,
const SkImage_Base* image,
const SkAlphaType imageAlphaType,
SkColorSpace* imageColorSpace) {
if (context->uniqueID() != imageContext->uniqueID()) {
SkASSERT(0);
return nullptr;
}
GrTextureAdjuster adjuster(imageContext, image->asTextureProxyRef(), imageAlphaType,
image->uniqueID(), imageColorSpace);
return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust);
}
sk_sp<SkImage> OnMakeSubset(const SkIRect& subset, sk_sp<GrContext> imageContext,
const SkImage_Base* image, const SkAlphaType imageAlphaType,
sk_sp<SkColorSpace> imageColorSpace, const SkBudgeted budgeted){
sk_sp<GrSurfaceProxy> proxy = image->asTextureProxyRef();
GrSurfaceDesc desc;
desc.fWidth = subset.width();
desc.fHeight = subset.height();
desc.fConfig = proxy->config();
sk_sp<GrSurfaceContext> sContext(imageContext->contextPriv().makeDeferredSurfaceContext(
desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, budgeted));
if (!sContext) {
return nullptr;
}
if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
return nullptr;
}
// MDB: this call is okay bc we know 'sContext' was kExact
return sk_make_sp<SkImage_Gpu>(imageContext, kNeedNewImageUniqueID,
imageAlphaType, sContext->asTextureProxyRef(),
imageColorSpace, budgeted);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImage_GpuShared_DEFINED
#define SkImage_GpuShared_DEFINED
#include "SkImageInfo.h"
#include "SkTypes.h"
class GrContext;
class SkImage_Base;
namespace SkImage_GpuShared {
bool ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex,
GrPixelConfig* config, SkColorType ct, SkAlphaType at,
sk_sp<SkColorSpace> cs);
sk_sp<GrTextureProxy> AsTextureProxyRef(GrContext* context,
const GrSamplerState& params,
SkColorSpace* dstColorSpace,
sk_sp<SkColorSpace>* texColorSpace,
SkScalar scaleAdjust[2],
GrContext* imageContext,
const SkImage_Base* image,
const SkAlphaType imageAlphaType,
SkColorSpace* imageColorSpace);
sk_sp<SkImage> OnMakeSubset(const SkIRect& subset, sk_sp<GrContext> imageContext,
const SkImage_Base* image, const SkAlphaType imageAlphaType,
sk_sp<SkColorSpace> imageColorSpace, const SkBudgeted budgeted);
}
#endif

View File

@ -16,10 +16,13 @@
#include "GrTexture.h"
#include "GrTextureAdjuster.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuShared.h"
#include "SkImage_GpuYUVA.h"
#include "SkReadPixelsRec.h"
#include "effects/GrYUVtoRGBEffect.h"
using namespace SkImage_GpuShared;
SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrContext> context, uint32_t uniqueID,
SkYUVColorSpace colorSpace, sk_sp<GrTextureProxy> proxies[],
SkYUVAIndex yuvaIndices[4], SkISize size, GrSurfaceOrigin origin,
@ -37,7 +40,7 @@ SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrContext> context, uint32_t uniqueID,
memcpy(fYUVAIndices, yuvaIndices, 4*sizeof(SkYUVAIndex));
// 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.
if (-1 != yuvaIndices[3].fIndex) {
if (-1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex) {
fImageAlphaType = kPremul_SkAlphaType;
}
}
@ -50,32 +53,13 @@ SkImageInfo SkImage_GpuYUVA::onImageInfo() const {
fImageAlphaType, fImageColorSpace);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// need shared defs with SkImage_Gpu
static bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex,
GrPixelConfig* config, SkColorType ct, SkAlphaType at,
sk_sp<SkColorSpace> cs) {
if (!tex.isValid()) {
return false;
}
// TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to
// create a fake image info here.
SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs);
if (!SkImageInfoIsValid(info)) {
return false;
}
return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<GrTextureProxy> SkImage_GpuYUVA::asTextureProxyRef() const {
if (!fRGBProxy) {
sk_sp<GrTextureProxy> yProxy = fProxies[fYUVAIndices[0].fIndex];
sk_sp<GrTextureProxy> uProxy = fProxies[fYUVAIndices[1].fIndex];
sk_sp<GrTextureProxy> vProxy = fProxies[fYUVAIndices[2].fIndex];
sk_sp<GrTextureProxy> yProxy = fProxies[fYUVAIndices[SkYUVAIndex::kY_Index].fIndex];
sk_sp<GrTextureProxy> uProxy = fProxies[fYUVAIndices[SkYUVAIndex::kU_Index].fIndex];
sk_sp<GrTextureProxy> vProxy = fProxies[fYUVAIndices[SkYUVAIndex::kV_Index].fIndex];
if (!yProxy || !uProxy || !vProxy) {
return nullptr;
@ -85,7 +69,8 @@ sk_sp<GrTextureProxy> SkImage_GpuYUVA::asTextureProxyRef() const {
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
// TODO: Modify the fragment processor to sample from different channel
// instead of taking nv12 bool.
bool nv12 = (fYUVAIndices[1].fIndex == fYUVAIndices[2].fIndex);
bool nv12 = (fYUVAIndices[SkYUVAIndex::kU_Index].fIndex ==
fYUVAIndices[SkYUVAIndex::kV_Index].fIndex);
// TODO: modify the YUVtoRGBEffect to do premul if fImageAlphaType is kPremul_AlphaType
paint.addColorFragmentProcessor(GrYUVtoRGBEffect::Make(std::move(yProxy), std::move(uProxy),
std::move(vProxy), fColorSpace,
@ -122,14 +107,8 @@ sk_sp<GrTextureProxy> SkImage_GpuYUVA::asTextureProxyRef(GrContext* context,
SkColorSpace* dstColorSpace,
sk_sp<SkColorSpace>* texColorSpace,
SkScalar scaleAdjust[2]) const {
if (context->uniqueID() != fContext->uniqueID()) {
SkASSERT(0);
return nullptr;
}
GrTextureAdjuster adjuster(fContext.get(), this->asTextureProxyRef(), this->alphaType(),
this->uniqueID(), this->fImageColorSpace.get());
return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust);
return AsTextureProxyRef(context, params, dstColorSpace, texColorSpace, scaleAdjust,
fContext.get(), this, fImageAlphaType, fImageColorSpace.get());
}
bool SkImage_GpuYUVA::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
@ -172,32 +151,6 @@ bool SkImage_GpuYUVA::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels,
return true;
}
sk_sp<SkImage> SkImage_GpuYUVA::onMakeSubset(const SkIRect& subset) const {
// Flatten the YUVA planes to a single texture
sk_sp<GrSurfaceProxy> proxy = this->asTextureProxyRef();
GrSurfaceDesc desc;
desc.fWidth = subset.width();
desc.fHeight = subset.height();
desc.fConfig = proxy->config();
sk_sp<GrSurfaceContext> sContext(fContext->contextPriv().makeDeferredSurfaceContext(
desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, fBudgeted));
if (!sContext) {
return nullptr;
}
if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
return nullptr;
}
// MDB: this call is okay bc we know 'sContext' was kExact
return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
fImageAlphaType, sContext->asTextureProxyRef(),
fImageColorSpace, fBudgeted);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//*** bundle this into a helper function used by this and SkImage_Gpu?
@ -212,7 +165,8 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx,
// Right now this still only deals with YUV and NV12 formats. Assuming that YUV has different
// textures for U and V planes, while NV12 uses same texture for U and V planes.
bool nv12 = (yuvaIndices[1].fIndex == yuvaIndices[2].fIndex);
bool nv12 = (yuvaIndices[SkYUVAIndex::kU_Index].fIndex ==
yuvaIndices[SkYUVAIndex::kV_Index].fIndex);
auto ct = nv12 ? kRGBA_8888_SkColorType : kAlpha_8_SkColorType;
// We need to make a copy of the input backend textures because we need to preserve the result
@ -221,7 +175,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx,
for (int i = 0; i < 4; ++i) {
// Validate that the yuvaIndices refer to valid backend textures.
const SkYUVAIndex& yuvaIndex = yuvaIndices[i];
if (3 == i && yuvaIndex.fIndex == -1) {
if (SkYUVAIndex::kA_Index == i && yuvaIndex.fIndex == -1) {
// Meaning the A plane isn't passed in.
continue;
}
@ -234,8 +188,8 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx,
yuvaTexturesCopy[yuvaIndex.fIndex] = yuvaTextures[yuvaIndex.fIndex];
// TODO: Instead of using assumption about whether it is NV12 format to guess colorType,
// actually use channel information here.
if (!validate_backend_texture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig,
ct, kUnpremul_SkAlphaType, nullptr)) {
if (!ValidateBackendTexture(ctx, yuvaTexturesCopy[i], &yuvaTexturesCopy[i].fConfig,
ct, kUnpremul_SkAlphaType, nullptr)) {
return nullptr;
}
}
@ -251,7 +205,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx,
// Safely ignore since this means we are missing the A plane.
if (textureIndex == -1) {
SkASSERT(3 == i);
SkASSERT(SkYUVAIndex::kA_Index == i);
continue;
}
@ -261,8 +215,9 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakeFromYUVATextures(GrContext* ctx,
proxyProvider->wrapBackendTexture(yuvaTexturesCopy[textureIndex], origin);
}
}
if (!tempTextureProxies[yuvaIndices[0].fIndex] || !tempTextureProxies[yuvaIndices[1].fIndex] ||
!tempTextureProxies[yuvaIndices[2].fIndex]) {
if (!tempTextureProxies[yuvaIndices[SkYUVAIndex::kY_Index].fIndex] ||
!tempTextureProxies[yuvaIndices[SkYUVAIndex::kU_Index].fIndex] ||
!tempTextureProxies[yuvaIndices[SkYUVAIndex::kV_Index].fIndex]) {
return nullptr;
}

View File

@ -32,7 +32,10 @@ public:
bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override {
return false;
}
sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
sk_sp<SkImage> onMakeSubset(const SkIRect& subset) const override {
return SkImage_GpuShared::OnMakeSubset(subset, fContext, this, fImageAlphaType,
fImageColorSpace, fBudgeted);
}
GrContext* context() const override { return fContext.get(); }
GrTextureProxy* peekProxy() const override { return nullptr; }