Add compressed data support for SkImage.

Adds a new SkImage::MakeFromCompressed method which takes raw data,
a size, and a compression method, and returns a GPU-backed
image.

Bug: skia:8684
Change-Id: I570c9dafce283bcd64dfbef4fbe1c4bfeac6ce2a
Reviewed-on: https://skia-review.googlesource.com/c/184484
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 2019-01-17 15:52:33 -05:00 committed by Skia Commit-Bot
parent d4fdf78475
commit 57263c2e0c
5 changed files with 97 additions and 37 deletions

View File

@ -7,6 +7,7 @@
#include "gm.h"
#include "sk_tool_utils.h"
#include "SkImage.h"
#include "SkRandom.h"
#if SK_SUPPORT_GPU && !defined(SK_BUILD_FOR_GOOGLE3)
@ -51,13 +52,13 @@ protected:
}
int size = etc1_get_encoded_data_size(bm.width(), bm.height());
fETC1Data.reset(size);
fETC1Data = SkData::MakeUninitialized(size);
unsigned char* pixels = (unsigned char*) fETC1Data.get();
unsigned char* pixels = (unsigned char*) fETC1Data->writable_data();
if (etc1_encode_image((unsigned char*) bm.getAddr16(0, 0),
bm.width(), bm.height(), 2, bm.rowBytes(), pixels)) {
fETC1Data.reset();
fETC1Data = nullptr;
}
}
@ -74,40 +75,11 @@ protected:
return;
}
GrBackendTexture tex = context->contextPriv().getGpu()->createTestingOnlyBackendTexture(
fETC1Data.get(),
kTexWidth,
kTexHeight,
GrColorType::kRGB_ETC1,
false,
GrMipMapped::kNo,
kTexWidth/2); // rowbytes are meaningless for compressed textures, but this is
// basically right
sk_sp<SkImage> image = SkImage::MakeFromCompressed(context, fETC1Data,
kTexWidth, kTexHeight,
SkImage::kETC1_CompressionType);
if (!tex.isValid()) {
return;
}
auto proxy = context->contextPriv().proxyProvider()->wrapBackendTexture(
tex, kTopLeft_GrSurfaceOrigin,
kAdopt_GrWrapOwnership,
kRead_GrIOType);
if (!proxy) {
return;
}
const SkMatrix trans = SkMatrix::MakeTrans(-kPad, -kPad);
auto fp = GrSimpleTextureEffect::Make(proxy, trans);
GrPaint grPaint;
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
grPaint.addColorFragmentProcessor(std::move(fp));
SkRect rect = SkRect::MakeXYWH(kPad, kPad, kTexWidth, kTexHeight);
renderTargetContext->priv().testingOnly_addDrawOp(
GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone, SkMatrix::I(), rect));
canvas->drawImage(image, 0, 0);
}
private:
@ -115,7 +87,7 @@ private:
static const int kTexWidth = 16;
static const int kTexHeight = 20;
SkAutoTMalloc<char> fETC1Data;
sk_sp<SkData> fETC1Data;
typedef GM INHERITED;
};

View File

@ -176,6 +176,25 @@ public:
*/
static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
enum CompressionType {
kETC1_CompressionType, //!< compressed data uses ETC1 compression
};
/** Creates a GPU-backed SkImage from compressed data.
SkImage is returned if format of the compressed data is supported.
Supported formats vary by platform.
@param context GPU context
@param data compressed data to store in SkImage
@param width width of full SkImage
@param height height of full SkImage
@param type type of compression used
@return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
int width, int height, CompressionType type);
/** User function called when supplied texture may be deleted.
*/
typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);

View File

@ -412,6 +412,42 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format
fit, budgeted, surfaceFlags));
}
sk_sp<GrTextureProxy> GrProxyProvider::createProxy(sk_sp<SkData> data, const GrSurfaceDesc& desc) {
if (!this->caps()->isConfigTexturable(desc.fConfig)) {
return nullptr;
}
const GrColorType ct = GrPixelConfigToColorType(desc.fConfig);
const GrBackendFormat format = fCaps->getBackendFormatFromGrColorType(ct, GrSRGBEncoded::kNo);
sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
[desc, data](GrResourceProvider* resourceProvider) {
if (!resourceProvider) {
return sk_sp<GrTexture>();
}
GrMipLevel texels;
texels.fPixels = data->data();
texels.fRowBytes = GrBytesPerPixel(desc.fConfig)*desc.fWidth;
return resourceProvider->createTexture(desc, SkBudgeted::kYes, &texels, 1);
},
format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
SkBudgeted::kYes);
if (!proxy) {
return nullptr;
}
if (fResourceProvider) {
// In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
// we're better off instantiating the proxy immediately here.
if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
return nullptr;
}
}
return proxy;
}
sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture& backendTex,
GrSurfaceOrigin origin,
GrWrapOwnership ownership,

View File

@ -99,6 +99,11 @@ public:
surfaceFlags);
}
/*
* Create a texture proxy with data. It's assumed that the data is packed tightly.
*/
sk_sp<GrTextureProxy> createProxy(sk_sp<SkData>, const GrSurfaceDesc& desc);
// These match the definitions in SkImage & GrTexture.h, for whence they came
typedef void* ReleaseContext;
typedef void (*ReleaseProc)(ReleaseContext);

View File

@ -153,6 +153,34 @@ sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
kAdopt_GrWrapOwnership, nullptr, nullptr);
}
sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
int width, int height, CompressionType type) {
// create the backing texture
GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags;
desc.fWidth = width;
desc.fHeight = height;
switch (type) {
case kETC1_CompressionType:
desc.fConfig = kRGB_ETC1_GrPixelConfig;
break;
default:
desc.fConfig = kUnknown_GrPixelConfig;
break;
}
desc.fSampleCnt = 1;
GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(std::move(data), desc);
if (!proxy) {
return nullptr;
}
return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
std::move(proxy), nullptr);
}
sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
const GrBackendTexture yuvaTextures[],
const SkYUVAIndex yuvaIndices[4], SkISize size,