WEBGL_video_texture : sharing texture prototype in skia

Bug: 776222

Change-Id: I84c81bdaa6dc0b5548f116a28c6319e601effb32
Reviewed-on: https://skia-review.googlesource.com/146695
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Kenneth Russell <kbr@google.com>
This commit is contained in:
Brian Salomon 2018-09-17 21:57:11 -04:00 committed by Skia Commit-Bot
parent 29a49bd220
commit d2fcfb5813
6 changed files with 227 additions and 19 deletions

View File

@ -31,7 +31,7 @@ protected:
} }
SkISize onISize() override { SkISize onISize() override {
return SkISize::Make(50, 175); return SkISize::Make(50, 300);
} }
void onOnceBeforeDraw() override { void onOnceBeforeDraw() override {
@ -114,6 +114,23 @@ protected:
context->resetContext(); context->resetContext();
} }
void createExternalBackendTexture(GrContext* context, int width, int height,
GrBackendTexture externalBackendTexture[1]) {
if (context->abandoned()) {
return;
}
GrGpu* gpu = context->contextPriv().getGpu();
if (!gpu) {
return;
}
externalBackendTexture[0] = gpu->createTestingOnlyBackendTexture(
nullptr, width, height, kRGBA_8888_GrPixelConfig, true, GrMipMapped::kNo);
context->resetContext();
}
void deleteYUVTextures(GrContext* context, GrBackendTexture yuvTextures[3]) { void deleteYUVTextures(GrContext* context, GrBackendTexture yuvTextures[3]) {
if (context->abandoned()) { if (context->abandoned()) {
return; return;
@ -135,6 +152,19 @@ protected:
context->resetContext(); context->resetContext();
} }
void deleteAllTextures(GrContext* context, GrBackendTexture yuvTextures[3],
GrBackendTexture externalBackendTexture) {
this->deleteYUVTextures(context, yuvTextures);
GrGpu* gpu = context->contextPriv().getGpu();
gpu->testingOnly_flushGpuAndSync();
if (externalBackendTexture.isValid()) {
gpu->deleteTestingOnlyBackendTexture(externalBackendTexture);
}
context->resetContext();
}
void onDraw(SkCanvas* canvas) override { void onDraw(SkCanvas* canvas) override {
GrContext* context = canvas->getGrContext(); GrContext* context = canvas->getGrContext();
if (!context) { if (!context) {
@ -162,6 +192,30 @@ protected:
canvas->drawImage(images[i].get(), x, y); canvas->drawImage(images[i].get(), x, y);
} }
sk_sp<SkImage> image;
for (int space = kJPEG_SkYUVColorSpace, i = images.count();
space <= kLastEnum_SkYUVColorSpace; ++space, ++i) {
GrBackendTexture yuvTextures[3];
GrBackendTexture externalBackendTexture[1];
this->createYUVTextures(context, yuvTextures);
this->createExternalBackendTexture(context,
yuvTextures[0].width(),
yuvTextures[0].height(),
externalBackendTexture);
image = SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
context,
static_cast<SkYUVColorSpace>(space),
yuvTextures,
kTopLeft_GrSurfaceOrigin,
externalBackendTexture[0]);
SkScalar y = (i + 1) * kPad + i * fYUVBmps[0].height();
SkScalar x = kPad;
canvas->drawImage(image.get(), x, y);
this->deleteAllTextures(context, yuvTextures, externalBackendTexture[0]);
}
} }
private: private:

View File

@ -1,7 +1,7 @@
# Copyright 2016 Google Inc. # Copyright 2016 Google Inc.
# #
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
# Things are easiest for everyone if these source paths are absolute. # Things are easiest for everyone if these source paths are absolute.
_gm = get_path_info("../gm", "abspath") _gm = get_path_info("../gm", "abspath")

View File

@ -342,6 +342,25 @@ public:
GrSurfaceOrigin surfaceOrigin, GrSurfaceOrigin surfaceOrigin,
sk_sp<SkColorSpace> colorSpace = nullptr); sk_sp<SkColorSpace> colorSpace = nullptr);
/** Creates SkImage from copy of yuvTextures, an array of textures on GPU.
yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions
yuvTextures[0] and stores pixels in backendTexture. yuvColorSpace describes how YUV colors
convert to RGB colors.
@param context GPU context
@param yuvColorSpace one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
kRec709_SkYUVColorSpace
@param yuvTextures array of YUV textures on GPU
@param surfaceOrigin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
@param backendTexture the resource that stores the final pixels
@param colorSpace range of colors; may be nullptr
@return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
GrContext* context, SkYUVColorSpace yuvColorSpace,
const GrBackendTexture yuvTextures[3], GrSurfaceOrigin surfaceOrigin,
const GrBackendTexture backendTexture, sk_sp<SkColorSpace> colorSpace = nullptr);
/** Creates SkImage from copy of nv12Textures, an array of textures on GPU. /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
nv12Textures[0] contains pixels for YUV component y plane. nv12Textures[0] contains pixels for YUV component y plane.
nv12Textures[1] contains pixels for YUV component u plane, nv12Textures[1] contains pixels for YUV component u plane,
@ -363,6 +382,30 @@ public:
GrSurfaceOrigin surfaceOrigin, GrSurfaceOrigin surfaceOrigin,
sk_sp<SkColorSpace> colorSpace = nullptr); sk_sp<SkColorSpace> colorSpace = nullptr);
/** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
nv12Textures[0] contains pixels for YUV_Component_Y plane.
nv12Textures[1] contains pixels for YUV_Component_U plane,
followed by pixels for YUV_Component_V plane.
Returned SkImage has the dimensions nv12Textures[2] and stores pixels in backendTexture.
yuvColorSpace describes how YUV colors convert to RGB colors.
@param context GPU context
@param yuvColorSpace one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
kRec709_SkYUVColorSpace
@param nv12Textures array of YUV textures on GPU
@param surfaceOrigin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
@param backendTexture the resource that stores the final pixels
@param colorSpace range of colors; may be nullptr
@return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromNV12TexturesCopyWithExternalBackend(
GrContext* context,
SkYUVColorSpace yuvColorSpace,
const GrBackendTexture nv12Textures[2],
GrSurfaceOrigin surfaceOrigin,
const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> colorSpace = nullptr);
enum class BitDepth { enum class BitDepth {
kU8, //!< uses 8-bit unsigned int per color component kU8, //!< uses 8-bit unsigned int per color component
kF16, //!< uses 16-bit float per color component kF16, //!< uses 16-bit float per color component

View File

@ -377,6 +377,13 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace
return nullptr; return nullptr;
} }
sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
GrContext* context, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
GrSurfaceOrigin surfaceOrigin, const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> colorSpace) {
return nullptr;
}
sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace space, sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace space,
const GrBackendTexture[2], const GrBackendTexture[2],
GrSurfaceOrigin origin, GrSurfaceOrigin origin,
@ -389,6 +396,15 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, SkColorSpace* dstColorSpace
return nullptr; return nullptr;
} }
sk_sp<SkImage> MakeFromNV12TexturesCopyWithExternalBackend(GrContext* context,
SkYUVColorSpace yuvColorSpace,
const GrBackendTexture nv12Textures[2],
GrSurfaceOrigin surfaceOrigin,
const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> colorSpace) {
return nullptr;
}
#endif #endif
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -339,13 +339,12 @@ sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
kAdopt_GrWrapOwnership, nullptr, nullptr); kAdopt_GrWrapOwnership, nullptr, nullptr);
} }
sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyImpl(GrContext* ctx, sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(
SkYUVColorSpace colorSpace, GrContext* ctx, SkYUVColorSpace colorSpace, const GrBackendTexture yuvaTextures[],
const GrBackendTexture yuvaTextures[], SkYUVAIndex yuvaIndices[4], SkISize size, GrSurfaceOrigin origin, SkBudgeted isBudgeted,
SkYUVAIndex yuvaIndices[4], GrRenderTargetContext* renderTargetContext) {
SkISize size, SkASSERT(renderTargetContext);
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
// Right now this still only deals with YUV and NV12 formats. Assuming that YUV has different // Right now this still only deals with YUV and NV12 formats. Assuming that YUV has different
@ -411,15 +410,6 @@ sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyImpl(GrContext* ctx,
const int width = size.width(); const int width = size.width();
const int height = size.height(); const int height = size.height();
// Needs to be a render target in order to draw to it for the yuv->rgb conversion.
sk_sp<GrRenderTargetContext> renderTargetContext(
ctx->contextPriv().makeDeferredRenderTargetContext(
SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig,
std::move(imageColorSpace), 1, GrMipMapped::kNo, origin));
if (!renderTargetContext) {
return nullptr;
}
GrPaint paint; GrPaint paint;
paint.setPorterDuffXPFactory(SkBlendMode::kSrc); paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
// TODO: Modify the fragment processor to sample from different channel instead of taking nv12 // TODO: Modify the fragment processor to sample from different channel instead of taking nv12
@ -442,7 +432,62 @@ sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyImpl(GrContext* ctx,
return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, kOpaque_SkAlphaType, return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
renderTargetContext->asTextureProxyRef(), renderTargetContext->asTextureProxyRef(),
renderTargetContext->colorSpaceInfo().refColorSpace(), renderTargetContext->colorSpaceInfo().refColorSpace(),
SkBudgeted::kYes); isBudgeted);
}
sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyImpl(GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture yuvaTextures[],
SkYUVAIndex yuvaIndices[4],
SkISize size,
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
const int width = size.width();
const int height = size.height();
// Needs to create a render target in order to draw to it for the yuv->rgb conversion.
sk_sp<GrRenderTargetContext> renderTargetContext(
ctx->contextPriv().makeDeferredRenderTargetContext(
SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig,
std::move(imageColorSpace), 1, GrMipMapped::kNo, origin));
if (!renderTargetContext) {
return nullptr;
}
return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, colorSpace, yuvaTextures, yuvaIndices, size,
origin, SkBudgeted::kYes,
renderTargetContext.get());
}
sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture yuvaTextures[],
SkYUVAIndex yuvaIndices[4],
SkISize size,
GrSurfaceOrigin origin,
const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> imageColorSpace) {
GrBackendTexture backendTextureCopy = backendTexture;
if (!validate_backend_texture(ctx, backendTextureCopy, &backendTextureCopy.fConfig, kRGBA_8888_SkColorType,
kPremul_SkAlphaType, nullptr)) {
return nullptr;
}
// Needs to create a render target with external texture
// in order to draw to it for the yuv->rgb conversion.
sk_sp<GrRenderTargetContext> renderTargetContext(
ctx->contextPriv().makeBackendTextureRenderTargetContext(backendTextureCopy, origin, 1,
std::move(imageColorSpace)));
if (!renderTargetContext) {
return nullptr;
}
return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, colorSpace, yuvaTextures, yuvaIndices, size,
origin, SkBudgeted::kNo,
renderTargetContext.get());
} }
sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
@ -460,6 +505,21 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace
size, origin, std::move(imageColorSpace)); size, origin, std::move(imageColorSpace));
} }
sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
GrContext* ctx, SkYUVColorSpace colorSpace, const GrBackendTexture yuvTextures[3],
GrSurfaceOrigin origin, const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> imageColorSpace) {
SkYUVAIndex yuvaIndices[4] = {
SkYUVAIndex{0, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{2, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{-1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel}};
SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
ctx, colorSpace, yuvTextures, yuvaIndices, size, origin, backendTexture,
std::move(imageColorSpace));
}
sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
const GrBackendTexture nv12Textures[2], const GrBackendTexture nv12Textures[2],
GrSurfaceOrigin origin, GrSurfaceOrigin origin,
@ -475,6 +535,24 @@ sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace
size, origin, std::move(imageColorSpace)); size, origin, std::move(imageColorSpace));
} }
sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture nv12Textures[2],
GrSurfaceOrigin origin,
const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> imageColorSpace) {
SkYUVAIndex yuvaIndices[4] = {
SkYUVAIndex{0, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel},
SkYUVAIndex{-1, SkImageSourceChannel::kLastEnum_SkImageSourceChannel}};
SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
ctx, colorSpace, nv12Textures, yuvaIndices, size, origin, backendTexture,
std::move(imageColorSpace));
}
static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer, static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
SkAlphaType at, uint32_t id, SkAlphaType at, uint32_t id,
SkColorSpace* dstColorSpace, SkColorSpace* dstColorSpace,

View File

@ -131,6 +131,18 @@ public:
GrSurfaceOrigin origin, GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace); sk_sp<SkColorSpace> imageColorSpace);
/** Implementation of MakeFromYUVTexturesCopyWithExternalBackend and
MakeFromNV12TexturesCopyWithExternalBackend */
static sk_sp<SkImage> MakeFromYUVATexturesCopyWithExternalBackendImpl(
GrContext* ctx,
SkYUVColorSpace colorSpace,
const GrBackendTexture yuvaTextures[],
SkYUVAIndex yuvaIndices[4],
SkISize size,
GrSurfaceOrigin origin,
const GrBackendTexture backendTexture,
sk_sp<SkColorSpace> imageColorSpace);
bool onIsValid(GrContext*) const override; bool onIsValid(GrContext*) const override;
void resetContext(sk_sp<GrContext> newContext) { void resetContext(sk_sp<GrContext> newContext) {
@ -139,6 +151,11 @@ public:
} }
private: private:
static sk_sp<SkImage> ConvertYUVATexturesToRGB(
GrContext* ctx, SkYUVColorSpace colorSpace, const GrBackendTexture yuvaTextures[],
SkYUVAIndex yuvaIndices[4], SkISize size, GrSurfaceOrigin origin,
SkBudgeted isBudgeted, GrRenderTargetContext* renderTargetContext);
sk_sp<GrContext> fContext; sk_sp<GrContext> fContext;
sk_sp<GrTextureProxy> fProxy; sk_sp<GrTextureProxy> fProxy;
const SkAlphaType fAlphaType; const SkAlphaType fAlphaType;