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>
diff --git a/docs/SkImage_Reference.bmh b/docs/SkImage_Reference.bmh
index 97538cd..7a0bc33 100644
--- a/docs/SkImage_Reference.bmh
+++ b/docs/SkImage_Reference.bmh
@@ -462,6 +462,27 @@
#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 ##
# ------------------------------------------------------------------------------
diff --git a/gm/wacky_yuv_formats.cpp b/gm/wacky_yuv_formats.cpp
index 8ea25c0..00c2fe1 100644
--- a/gm/wacky_yuv_formats.cpp
+++ b/gm/wacky_yuv_formats.cpp
@@ -743,6 +743,7 @@
}
GrBackendTexture yuvaTextures[4];
+ SkPixmap yuvaPixmaps[4];
for (int i = 0; i < 4; ++i) {
if (!used[i]) {
@@ -757,9 +758,12 @@
false,
GrMipMapped::kNo,
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(
context,
(SkYUVColorSpace)cs,
@@ -767,7 +771,8 @@
yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
kTopLeft_GrSurfaceOrigin);
- } else {
+ break;
+ case 1:
fImages[opaque][cs][format] = SkImage::MakeFromYUVATextures(
context,
(SkYUVColorSpace)cs,
@@ -775,7 +780,19 @@
yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
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 {
fImages[opaque][cs][format] = make_yuv_gen_image(
fOriginalBMs[opaque].info(),
@@ -785,7 +802,6 @@
}
}
}
- ++counter;
}
}
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 79067af..9b97884 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -357,31 +357,6 @@
GrSurfaceOrigin imageOrigin,
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
image. 'backendTexture' is used to store the result of the flattening.
@@ -410,36 +385,71 @@
const GrBackendTexture& backendTexture,
sk_sp<SkColorSpace> imageColorSpace = 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]. yuvColorSpace describes how YUV colors convert to RGB colors.
+ /** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
+ via multitexturing.
@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 imageColorSpace range of colors; may be nullptr
+ @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 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,
const GrBackendTexture yuvTextures[3],
GrSurfaceOrigin imageOrigin,
sk_sp<SkColorSpace> imageColorSpace = 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 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
+ /** To be deprecated.
*/
static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
GrContext* context, SkYUVColorSpace yuvColorSpace,
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index 7da0ca4..e184e17 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -94,6 +94,8 @@
PromiseDoneProc promiseDoneProc,
TextureContext textureContext);
+ /** To be deprecated. Use SkImage_GpuYUVA::MakePromiseYUVATexture instead.
+ */
static sk_sp<SkImage> MakePromiseYUVATexture(GrContext* context,
SkYUVColorSpace yuvColorSpace,
const GrBackendFormat yuvaFormats[],
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index a1d0696..3113c1c 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -16,6 +16,7 @@
#include "GrRenderTargetContext.h"
#include "GrTexture.h"
#include "GrTextureProducer.h"
+#include "SkAutoPixmapStorage.h"
#include "SkGr.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuYUVA.h"
@@ -144,6 +145,68 @@
numTextures, yuvaIndices, imageOrigin, imageColorSpace,
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,
SkYUVColorSpace yuvColorSpace,