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:
parent
d4fdf78475
commit
57263c2e0c
46
gm/etc1.cpp
46
gm/etc1.cpp
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user