Add SkImage::MakeFromYUVAPixmaps

Bug: skia:7903
Change-Id: I41ee31ad3657aee372e22ec3e7a0a317e31b2791
Reviewed-on: https://skia-review.googlesource.com/c/171007
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Jim Van Verth 2018-11-20 11:12:37 -05:00 committed by Skia Commit-Bot
parent e3deee1319
commit c8429addf1
5 changed files with 161 additions and 49 deletions

View File

@ -462,6 +462,27 @@ if (source.peekPixels(&pixmap)) {
#Method ## #Method ##
#Method static sk_sp<SkImage> MakeFromYUVAPixmaps(
GrContext* context,
SkYUVColorSpace yuvColorSpace,
const SkPixmap yuvaPixmaps[],
const SkYUVAIndex yuvaIndices[4],
SkISize imageSize,
GrSurfaceOrigin imageOrigin,
bool buildMips,
bool limitToMaxTextureSize = false,
sk_sp<SkColorSpace> imageColorSpace = nullptr);
#In Constructor
#Line # creates Image from YUV_ColorSpace data ##
#Populate
#NoExample
##
#SeeAlso MakeFromYUVATextures
#Method ##
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -743,6 +743,7 @@ protected:
} }
GrBackendTexture yuvaTextures[4]; GrBackendTexture yuvaTextures[4];
SkPixmap yuvaPixmaps[4];
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
if (!used[i]) { if (!used[i]) {
@ -757,9 +758,12 @@ protected:
false, false,
GrMipMapped::kNo, GrMipMapped::kNo,
resultBMs[i].rowBytes()); resultBMs[i].rowBytes());
yuvaPixmaps[i] = resultBMs[i].pixmap();
} }
if (counter & 0x1) { int counterMod = counter % 3;
switch (counterMod) {
case 0:
fImages[opaque][cs][format] = SkImage::MakeFromYUVATexturesCopy( fImages[opaque][cs][format] = SkImage::MakeFromYUVATexturesCopy(
context, context,
(SkYUVColorSpace)cs, (SkYUVColorSpace)cs,
@ -767,7 +771,8 @@ protected:
yuvaIndices, yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() }, { fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
kTopLeft_GrSurfaceOrigin); kTopLeft_GrSurfaceOrigin);
} else { break;
case 1:
fImages[opaque][cs][format] = SkImage::MakeFromYUVATextures( fImages[opaque][cs][format] = SkImage::MakeFromYUVATextures(
context, context,
(SkYUVColorSpace)cs, (SkYUVColorSpace)cs,
@ -775,7 +780,19 @@ protected:
yuvaIndices, yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() }, { fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
kTopLeft_GrSurfaceOrigin); kTopLeft_GrSurfaceOrigin);
break;
case 2:
default:
fImages[opaque][cs][format] = SkImage::MakeFromYUVAPixmaps(
context,
(SkYUVColorSpace)cs,
yuvaPixmaps,
yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
kTopLeft_GrSurfaceOrigin, true);
break;
} }
++counter;
} else { } else {
fImages[opaque][cs][format] = make_yuv_gen_image( fImages[opaque][cs][format] = make_yuv_gen_image(
fOriginalBMs[opaque].info(), fOriginalBMs[opaque].info(),
@ -785,7 +802,6 @@ protected:
} }
} }
} }
++counter;
} }
} }

View File

@ -357,31 +357,6 @@ public:
GrSurfaceOrigin imageOrigin, GrSurfaceOrigin imageOrigin,
sk_sp<SkColorSpace> imageColorSpace = nullptr); sk_sp<SkColorSpace> imageColorSpace = nullptr);
/** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
via multitexturing.
@param context GPU context
@param yuvColorSpace How the YUV values are converted to RGB. One of:
kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
kRec709_SkYUVColorSpace
@param yuvaTextures array of (up to four) YUVA textures on GPU which contain the,
possibly interleaved, YUVA planes
@param yuvaIndices array indicating which texture in yuvaTextures, and channel
in that texture, maps to each component of YUVA.
@param imageSize size of the resulting image
@param imageOrigin origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
kTopLeft_GrSurfaceOrigin
@param imageColorSpace range of colors of the resulting image; may be nullptr
@return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromYUVATextures(GrContext* context,
SkYUVColorSpace yuvColorSpace,
const GrBackendTexture yuvaTextures[],
const SkYUVAIndex yuvaIndices[4],
SkISize imageSize,
GrSurfaceOrigin imageOrigin,
sk_sp<SkColorSpace> imageColorSpace = nullptr);
/** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
image. 'backendTexture' is used to store the result of the flattening. image. 'backendTexture' is used to store the result of the flattening.
@ -410,36 +385,71 @@ public:
const GrBackendTexture& backendTexture, const GrBackendTexture& backendTexture,
sk_sp<SkColorSpace> imageColorSpace = nullptr); sk_sp<SkColorSpace> imageColorSpace = nullptr);
/** Creates SkImage from copy of yuvTextures, an array of textures on GPU. /** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions via multitexturing.
yuvTextures[0]. yuvColorSpace describes how YUV colors convert to RGB colors.
@param context GPU context @param context GPU context
@param yuvColorSpace one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace, @param yuvColorSpace How the YUV values are converted to RGB. One of:
kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
kRec709_SkYUVColorSpace kRec709_SkYUVColorSpace
@param yuvTextures array of YUV textures on GPU @param yuvaTextures array of (up to four) YUVA textures on GPU which contain the,
@param imageOrigin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin possibly interleaved, YUVA planes
@param imageColorSpace range of colors; may be nullptr @param yuvaIndices array indicating which texture in yuvaTextures, and channel
in that texture, maps to each component of YUVA.
@param imageSize size of the resulting image
@param imageOrigin origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
kTopLeft_GrSurfaceOrigin
@param imageColorSpace range of colors of the resulting image; may be nullptr
@return created SkImage, or nullptr @return created SkImage, or nullptr
*/ */
static sk_sp<SkImage> MakeFromYUVATextures(GrContext* context,
SkYUVColorSpace yuvColorSpace,
const GrBackendTexture yuvaTextures[],
const SkYUVAIndex yuvaIndices[4],
SkISize imageSize,
GrSurfaceOrigin imageOrigin,
sk_sp<SkColorSpace> imageColorSpace = nullptr);
/** Creates SkImage from pixmap array representing YUVA data.
SkImage is uploaded to GPU back-end using context.
Each GrBackendTexture created from yuvaPixmaps array is uploaded to match SkSurface
using SkColorSpace of SkPixmap. SkColorSpace of SkImage is determined by imageColorSpace.
SkImage is returned referring to GPU back-end if context is not nullptr and
format of data is recognized and supported. Otherwise, nullptr is returned.
Recognized GPU formats vary by platform and GPU back-end.
@param context GPU context
@param yuvColorSpace How the YUV values are converted to RGB. One of:
kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
kRec709_SkYUVColorSpace
@param yuvaPixmaps array of (up to four) SkPixmap which contain the,
possibly interleaved, YUVA planes
@param yuvaIndices array indicating which pixmap in yuvaPixmaps, and channel
in that pixmap, maps to each component of YUVA.
@param imageSize size of the resulting image
@param imageOrigin origin of the resulting image. One of:
kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
@param buildMips create internal YUVA textures as mip map if true
@param limitToMaxTextureSize downscale image to GPU maximum texture size, if necessary
@param imageColorSpace range of colors of the resulting image; may be nullptr
@return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromYUVAPixmaps(
GrContext* context, SkYUVColorSpace yuvColorSpace, const SkPixmap yuvaPixmaps[],
const SkYUVAIndex yuvaIndices[4], SkISize imageSize, GrSurfaceOrigin imageOrigin,
bool buildMips, bool limitToMaxTextureSize = false,
sk_sp<SkColorSpace> imageColorSpace = nullptr);
/** To be deprecated.
*/
static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace, static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,
const GrBackendTexture yuvTextures[3], const GrBackendTexture yuvTextures[3],
GrSurfaceOrigin imageOrigin, GrSurfaceOrigin imageOrigin,
sk_sp<SkColorSpace> imageColorSpace = nullptr); sk_sp<SkColorSpace> imageColorSpace = nullptr);
/** Creates SkImage from copy of yuvTextures, an array of textures on GPU. /** To be deprecated.
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 imageOrigin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
@param backendTexture the resource that stores the final pixels
@param imageColorSpace range of colors; may be nullptr
@return created SkImage, or nullptr
*/ */
static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend( static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
GrContext* context, SkYUVColorSpace yuvColorSpace, GrContext* context, SkYUVColorSpace yuvColorSpace,

View File

@ -94,6 +94,8 @@ public:
PromiseDoneProc promiseDoneProc, PromiseDoneProc promiseDoneProc,
TextureContext textureContext); TextureContext textureContext);
/** To be deprecated. Use SkImage_GpuYUVA::MakePromiseYUVATexture instead.
*/
static sk_sp<SkImage> MakePromiseYUVATexture(GrContext* context, static sk_sp<SkImage> MakePromiseYUVATexture(GrContext* context,
SkYUVColorSpace yuvColorSpace, SkYUVColorSpace yuvColorSpace,
const GrBackendFormat yuvaFormats[], const GrBackendFormat yuvaFormats[],

View File

@ -16,6 +16,7 @@
#include "GrRenderTargetContext.h" #include "GrRenderTargetContext.h"
#include "GrTexture.h" #include "GrTexture.h"
#include "GrTextureProducer.h" #include "GrTextureProducer.h"
#include "SkAutoPixmapStorage.h"
#include "SkGr.h" #include "SkGr.h"
#include "SkImage_Gpu.h" #include "SkImage_Gpu.h"
#include "SkImage_GpuYUVA.h" #include "SkImage_GpuYUVA.h"
@ -144,6 +145,68 @@ sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrContext* ctx,
numTextures, yuvaIndices, imageOrigin, imageColorSpace, numTextures, yuvaIndices, imageOrigin, imageColorSpace,
SkBudgeted::kYes); SkBudgeted::kYes);
} }
sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(
GrContext* context, SkYUVColorSpace yuvColorSpace, const SkPixmap yuvaPixmaps[],
const SkYUVAIndex yuvaIndices[4], SkISize imageSize, GrSurfaceOrigin imageOrigin,
bool buildMips, bool limitToMaxTextureSize, sk_sp<SkColorSpace> imageColorSpace) {
int numPixmaps;
if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numPixmaps)) {
return nullptr;
}
// Make proxies
GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
sk_sp<GrTextureProxy> tempTextureProxies[4];
for (int i = 0; i < numPixmaps; ++i) {
const SkPixmap* pixmap = &yuvaPixmaps[i];
SkAutoPixmapStorage resized;
int maxTextureSize = context->contextPriv().caps()->maxTextureSize();
int maxDim = SkTMax(yuvaPixmaps[i].width(), yuvaPixmaps[i].height());
if (limitToMaxTextureSize && maxDim > maxTextureSize) {
float scale = static_cast<float>(maxTextureSize) / maxDim;
int newWidth = SkTMin(static_cast<int>(yuvaPixmaps[i].width() * scale),
maxTextureSize);
int newHeight = SkTMin(static_cast<int>(yuvaPixmaps[i].height() * scale),
maxTextureSize);
SkImageInfo info = yuvaPixmaps[i].info().makeWH(newWidth, newHeight);
if (!resized.tryAlloc(info) ||
!yuvaPixmaps[i].scalePixels(resized, kLow_SkFilterQuality)) {
return nullptr;
}
pixmap = &resized;
}
// Turn the pixmap into a GrTextureProxy
if (buildMips) {
SkBitmap bmp;
bmp.installPixels(*pixmap);
tempTextureProxies[i] = proxyProvider->createMipMapProxyFromBitmap(bmp);
} else {
if (SkImageInfoIsValid(pixmap->info())) {
ATRACE_ANDROID_FRAMEWORK("Upload Texture [%ux%u]",
pixmap->width(), pixmap->height());
// We don't need a release proc on the data in pixmap since we know we are in a
// GrContext that has a resource provider. Thus the createTextureProxy call will
// immediately upload the data.
sk_sp<SkImage> image = SkImage::MakeFromRaster(*pixmap, nullptr, nullptr);
tempTextureProxies[i] =
proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags, 1,
SkBudgeted::kYes, SkBackingFit::kExact);
}
}
if (!tempTextureProxies[i]) {
return nullptr;
}
}
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), imageSize.width(), imageSize.height(),
kNeedNewImageUniqueID, yuvColorSpace, tempTextureProxies,
numPixmaps, yuvaIndices, imageOrigin, imageColorSpace,
SkBudgeted::kYes);
}
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(GrContext* context, sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(GrContext* context,
SkYUVColorSpace yuvColorSpace, SkYUVColorSpace yuvColorSpace,