Add SkImage_Base API to access planar data
In order to test YUV promise images we need to be able to access the planes.
Split out of: https://skia-review.googlesource.com/c/skia/+/151983 (Test YUV images in DDL)
Bug: skia:7903
Change-Id: If232a5fdeb90833da6db727b1997a3c744bcd9dd
Reviewed-on: https://skia-review.googlesource.com/156140
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 9ffd8a7..a5b71dd 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -20,43 +20,53 @@
#include "SkYUVPlanesCache.h"
#include "effects/GrYUVtoRGBEffect.h"
-sk_sp<SkCachedData> init_provider(GrYUVProvider* provider, SkYUVPlanesCache::Info* yuvInfo,
- void* planes[3]) {
+sk_sp<SkCachedData> GrYUVProvider::getPlanes(SkYUVSizeInfo* size,
+ SkYUVColorSpace* colorSpace,
+ const void* constPlanes[3]) {
sk_sp<SkCachedData> data;
- data.reset(SkYUVPlanesCache::FindAndRef(provider->onGetID(), yuvInfo));
+ SkYUVPlanesCache::Info yuvInfo;
+ data.reset(SkYUVPlanesCache::FindAndRef(this->onGetID(), &yuvInfo));
+
+ void* planes[3];
if (data.get()) {
planes[0] = (void*)data->data();
- planes[1] = (uint8_t*)planes[0] + (yuvInfo->fSizeInfo.fWidthBytes[SkYUVSizeInfo::kY] *
- yuvInfo->fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
- planes[2] = (uint8_t*)planes[1] + (yuvInfo->fSizeInfo.fWidthBytes[SkYUVSizeInfo::kU] *
- yuvInfo->fSizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight);
+ planes[1] = (uint8_t*)planes[0] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kY] *
+ yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
+ planes[2] = (uint8_t*)planes[1] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kU] *
+ yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight);
} else {
// Fetch yuv plane sizes for memory allocation.
- if (!provider->onQueryYUV8(&yuvInfo->fSizeInfo, &yuvInfo->fColorSpace)) {
+ if (!this->onQueryYUV8(&yuvInfo.fSizeInfo, &yuvInfo.fColorSpace)) {
return nullptr;
}
// Allocate the memory for YUV
size_t totalSize(0);
for (int i = 0; i < 3; i++) {
- totalSize += yuvInfo->fSizeInfo.fWidthBytes[i] * yuvInfo->fSizeInfo.fSizes[i].fHeight;
+ totalSize += yuvInfo.fSizeInfo.fWidthBytes[i] * yuvInfo.fSizeInfo.fSizes[i].fHeight;
}
data.reset(SkResourceCache::NewCachedData(totalSize));
planes[0] = data->writable_data();
- planes[1] = (uint8_t*)planes[0] + (yuvInfo->fSizeInfo.fWidthBytes[SkYUVSizeInfo::kY] *
- yuvInfo->fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
- planes[2] = (uint8_t*)planes[1] + (yuvInfo->fSizeInfo.fWidthBytes[SkYUVSizeInfo::kU] *
- yuvInfo->fSizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight);
+ planes[1] = (uint8_t*)planes[0] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kY] *
+ yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
+ planes[2] = (uint8_t*)planes[1] + (yuvInfo.fSizeInfo.fWidthBytes[SkYUVSizeInfo::kU] *
+ yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight);
// Get the YUV planes.
- if (!provider->onGetYUV8Planes(yuvInfo->fSizeInfo, planes)) {
+ if (!this->onGetYUV8Planes(yuvInfo.fSizeInfo, planes)) {
return nullptr;
}
// Decoding is done, cache the resulting YUV planes
- SkYUVPlanesCache::Add(provider->onGetID(), data.get(), yuvInfo);
+ SkYUVPlanesCache::Add(this->onGetID(), data.get(), &yuvInfo);
}
+
+ *size = yuvInfo.fSizeInfo;
+ *colorSpace = yuvInfo.fColorSpace;
+ constPlanes[0] = planes[0];
+ constPlanes[1] = planes[1];
+ constPlanes[2] = planes[2];
return data;
}
@@ -69,28 +79,29 @@
sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx, const GrSurfaceDesc& desc,
SkColorSpace* srcColorSpace,
SkColorSpace* dstColorSpace) {
- SkYUVPlanesCache::Info yuvInfo;
- void* planes[3];
+ SkYUVSizeInfo yuvSizeInfo;
+ SkYUVColorSpace yuvColorSpace;
+ const void* planes[3];
- sk_sp<SkCachedData> dataStorage = init_provider(this, &yuvInfo, planes);
+ sk_sp<SkCachedData> dataStorage = this->getPlanes(&yuvSizeInfo, &yuvColorSpace, planes);
if (!dataStorage) {
return nullptr;
}
sk_sp<GrTextureProxy> yuvTextureProxies[3];
for (int i = 0; i < 3; i++) {
- int componentWidth = yuvInfo.fSizeInfo.fSizes[i].fWidth;
- int componentHeight = yuvInfo.fSizeInfo.fSizes[i].fHeight;
+ int componentWidth = yuvSizeInfo.fSizes[i].fWidth;
+ int componentHeight = yuvSizeInfo.fSizes[i].fHeight;
// If the sizes of the components are not all the same we choose to create exact-match
- // textures for the smaller onces rather than add a texture domain to the draw.
- // TODO: revisit this decision to imporve texture reuse?
+ // textures for the smaller ones rather than add a texture domain to the draw.
+ // TODO: revisit this decision to improve texture reuse?
SkBackingFit fit =
- (componentWidth != yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth) ||
- (componentHeight != yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight)
+ (componentWidth != yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth) ||
+ (componentHeight != yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight)
? SkBackingFit::kExact : SkBackingFit::kApprox;
SkImageInfo imageInfo = SkImageInfo::MakeA8(componentWidth, componentHeight);
- SkPixmap pixmap(imageInfo, planes[i], yuvInfo.fSizeInfo.fWidthBytes[i]);
+ SkPixmap pixmap(imageInfo, planes[i], yuvSizeInfo.fWidthBytes[i]);
SkCachedData* dataStoragePtr = dataStorage.get();
// We grab a ref to cached yuv data. When the SkImage we create below goes away it will call
// the YUVGen_DataReleaseProc which will release this ref.
@@ -106,8 +117,8 @@
yuvTextureProxies[i] = proxyProvider->createTextureProxy(yuvImage, kNone_GrSurfaceFlags,
1, SkBudgeted::kYes, fit);
- SkASSERT(yuvTextureProxies[i]->width() == yuvInfo.fSizeInfo.fSizes[i].fWidth);
- SkASSERT(yuvTextureProxies[i]->height() == yuvInfo.fSizeInfo.fSizes[i].fHeight);
+ SkASSERT(yuvTextureProxies[i]->width() == yuvSizeInfo.fSizes[i].fWidth);
+ SkASSERT(yuvTextureProxies[i]->height() == yuvSizeInfo.fSizes[i].fHeight);
}
// TODO: investigate preallocating mip maps here
@@ -124,7 +135,7 @@
GrYUVtoRGBEffect::Make(std::move(yuvTextureProxies[0]),
std::move(yuvTextureProxies[1]),
std::move(yuvTextureProxies[2]),
- yuvInfo.fColorSpace, false);
+ yuvColorSpace, false);
paint.addColorFragmentProcessor(std::move(yuvToRgbProcessor));
// If the caller expects the pixels in a different color space than the one from the image,
@@ -136,8 +147,8 @@
}
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
- yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
+ const SkRect r = SkRect::MakeIWH(yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
+ yuvSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), r);
diff --git a/src/gpu/GrYUVProvider.h b/src/gpu/GrYUVProvider.h
index 42a823a..de6ce33 100644
--- a/src/gpu/GrYUVProvider.h
+++ b/src/gpu/GrYUVProvider.h
@@ -16,6 +16,7 @@
struct GrSurfaceDesc;
class GrTexture;
class GrTextureProxy;
+class SkCachedData;
/**
* There are at least 2 different ways to extract/retrieve YUV planar data...
@@ -42,7 +43,10 @@
SkColorSpace* srcColorSpace,
SkColorSpace* dstColorSpace);
- virtual uint32_t onGetID() = 0;
+ sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*, const void* planes[3]);
+
+private:
+ virtual uint32_t onGetID() const = 0;
// These are not meant to be called by a client, only by the implementation
@@ -68,7 +72,6 @@
*/
virtual bool onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) = 0;
-private:
// This is used as release callback for the YUV data that we capture in an SkImage when
// uploading to a gpu. When the upload is complete and we release the SkImage this callback will
// release the underlying data.
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 4c2c6db..00b7117 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -227,6 +227,10 @@
return as_IB(this)->onAsLegacyBitmap(bitmap);
}
+sk_sp<SkCachedData> SkImage_Base::getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*,const void*[3]) {
+ return nullptr;
+}
+
bool SkImage_Base::onAsLegacyBitmap(SkBitmap* bitmap) const {
// As the base-class, all we can do is make a copy (regardless of mode).
// Subclasses that want to be more optimal should override.
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index d9c738a..3adf51e 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -22,6 +22,8 @@
#include <new>
class GrSamplerState;
+class SkCachedData;
+struct SkYUVSizeInfo;
enum {
kNeedNewImageUniqueID = 0
@@ -72,6 +74,7 @@
virtual sk_sp<SkImage> onMakeSubset(const SkIRect&) const = 0;
+ virtual sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*, const void* planes[3]);
virtual sk_sp<SkData> onRefEncoded() const { return nullptr; }
virtual bool onAsLegacyBitmap(SkBitmap*) const;
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 15722fe..6aa0ca0 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -351,18 +351,21 @@
}
class Generator_GrYUVProvider : public GrYUVProvider {
- SkImageGenerator* fGen;
-
public:
Generator_GrYUVProvider(SkImageGenerator* gen) : fGen(gen) {}
- uint32_t onGetID() override { return fGen->uniqueID(); }
+private:
+ uint32_t onGetID() const override { return fGen->uniqueID(); }
bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override {
return fGen->queryYUV8(sizeInfo, colorSpace);
}
bool onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override {
return fGen->getYUV8Planes(sizeInfo, planes);
}
+
+ SkImageGenerator* fGen;
+
+ typedef GrYUVProvider INHERITED;
};
static void set_key_on_proxy(GrProxyProvider* proxyProvider,
@@ -383,6 +386,21 @@
}
}
+sk_sp<SkCachedData> SkImage_Lazy::getPlanes(SkYUVSizeInfo* yuvSizeInfo,
+ SkYUVColorSpace* yuvColorSpace,
+ const void* planes[3]) {
+ ScopedGenerator generator(fSharedGenerator);
+ Generator_GrYUVProvider provider(generator);
+
+ sk_sp<SkCachedData> data = provider.getPlanes(yuvSizeInfo, yuvColorSpace, planes);
+ if (!data) {
+ return nullptr;
+ }
+
+ return data;
+}
+
+
/*
* We have 4 ways to try to return a texture (in sorted order)
*
diff --git a/src/image/SkImage_Lazy.h b/src/image/SkImage_Lazy.h
index b13cd16..433817e 100644
--- a/src/image/SkImage_Lazy.h
+++ b/src/image/SkImage_Lazy.h
@@ -56,6 +56,7 @@
sk_sp<SkColorSpace>*,
SkScalar scaleAdjust[2]) const override;
#endif
+ sk_sp<SkCachedData> getPlanes(SkYUVSizeInfo*, SkYUVColorSpace*, const void* planes[3]) override;
sk_sp<SkData> onRefEncoded() const override;
sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override;