add callbacks to Images that wrap client-provided content
BUG=skia: Review URL: https://codereview.chromium.org/1169553003
This commit is contained in:
parent
d7395d82d5
commit
de49988bc2
@ -44,10 +44,23 @@ public:
|
|||||||
SK_DECLARE_INST_COUNT(SkImage)
|
SK_DECLARE_INST_COUNT(SkImage)
|
||||||
|
|
||||||
typedef SkImageInfo Info;
|
typedef SkImageInfo Info;
|
||||||
|
typedef void* ReleaseContext;
|
||||||
|
|
||||||
static SkImage* NewRasterCopy(const Info&, const void* pixels, size_t rowBytes);
|
static SkImage* NewRasterCopy(const Info&, const void* pixels, size_t rowBytes);
|
||||||
static SkImage* NewRasterData(const Info&, SkData* pixels, size_t rowBytes);
|
static SkImage* NewRasterData(const Info&, SkData* pixels, size_t rowBytes);
|
||||||
|
|
||||||
|
typedef void (*RasterReleaseProc)(const void* pixels, ReleaseContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new Image referencing the specified pixels. These must remain valid and unchanged
|
||||||
|
* until the specified release-proc is called, indicating that Skia no longer has a reference
|
||||||
|
* to the pixels.
|
||||||
|
*
|
||||||
|
* Returns NULL if the requested Info is unsupported.
|
||||||
|
*/
|
||||||
|
static SkImage* NewFromRaster(const Info&, const void* pixels, size_t rowBytes,
|
||||||
|
RasterReleaseProc, ReleaseContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new SkImage based on the given ImageGenerator.
|
* Construct a new SkImage based on the given ImageGenerator.
|
||||||
* This function will always take ownership of the passed
|
* This function will always take ownership of the passed
|
||||||
@ -70,8 +83,25 @@ public:
|
|||||||
*
|
*
|
||||||
* Will return NULL if the specified descriptor is unsupported.
|
* Will return NULL if the specified descriptor is unsupported.
|
||||||
*/
|
*/
|
||||||
static SkImage* NewFromTexture(GrContext*, const GrBackendTextureDesc&,
|
static SkImage* NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc) {
|
||||||
SkAlphaType = kPremul_SkAlphaType);
|
return NewFromTexture(ctx, desc, kPremul_SkAlphaType, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkImage* NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& de, SkAlphaType at) {
|
||||||
|
return NewFromTexture(ctx, de, at, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*TextureReleaseProc)(ReleaseContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new image from the specified descriptor. The underlying platform texture must stay
|
||||||
|
* valid and unaltered until the specified release-proc is invoked, indicating that Skia
|
||||||
|
* nolonger is holding a reference to it.
|
||||||
|
*
|
||||||
|
* Will return NULL if the specified descriptor is unsupported.
|
||||||
|
*/
|
||||||
|
static SkImage* NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
|
||||||
|
TextureReleaseProc, ReleaseContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new image from the specified descriptor. Note - Skia will delete or recycle the
|
* Create a new image from the specified descriptor. Note - Skia will delete or recycle the
|
||||||
|
@ -282,7 +282,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t getSafeSize(size_t rowBytes) const {
|
size_t getSafeSize(size_t rowBytes) const {
|
||||||
return (size_t)this->getSafeSize64(rowBytes);
|
int64_t size = this->getSafeSize64(rowBytes);
|
||||||
|
if (!sk_64_isS32(size)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sk_64_asS32(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validRowBytes(size_t rowBytes) const {
|
bool validRowBytes(size_t rowBytes) const {
|
||||||
|
@ -127,6 +127,14 @@ public:
|
|||||||
inline GrSurfacePriv surfacePriv();
|
inline GrSurfacePriv surfacePriv();
|
||||||
inline const GrSurfacePriv surfacePriv() const;
|
inline const GrSurfacePriv surfacePriv() const;
|
||||||
|
|
||||||
|
typedef void* ReleaseCtx;
|
||||||
|
typedef void (*ReleaseProc)(ReleaseCtx);
|
||||||
|
|
||||||
|
void setRelease(ReleaseProc proc, ReleaseCtx ctx) {
|
||||||
|
fReleaseProc = proc;
|
||||||
|
fReleaseCtx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Methods made available via GrSurfacePriv
|
// Methods made available via GrSurfacePriv
|
||||||
SkImageInfo info() const;
|
SkImageInfo info() const;
|
||||||
@ -140,12 +148,32 @@ protected:
|
|||||||
|
|
||||||
GrSurface(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
|
GrSurface(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
|
||||||
: INHERITED(gpu, lifeCycle)
|
: INHERITED(gpu, lifeCycle)
|
||||||
, fDesc(desc) {
|
, fDesc(desc)
|
||||||
|
, fReleaseProc(NULL)
|
||||||
|
, fReleaseCtx(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~GrSurface() override {
|
||||||
|
// check that invokeReleaseProc has been called (if needed)
|
||||||
|
SkASSERT(NULL == fReleaseProc);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSurfaceDesc fDesc;
|
GrSurfaceDesc fDesc;
|
||||||
|
|
||||||
|
void invokeReleaseProc() {
|
||||||
|
if (fReleaseProc) {
|
||||||
|
fReleaseProc(fReleaseCtx);
|
||||||
|
fReleaseProc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onRelease() override;
|
||||||
|
void onAbandon() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ReleaseProc fReleaseProc;
|
||||||
|
ReleaseCtx fReleaseCtx;
|
||||||
|
|
||||||
typedef GrGpuResource INHERITED;
|
typedef GrGpuResource INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,3 +125,13 @@ bool GrSurface::hasPendingIO() const {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrSurface::onRelease() {
|
||||||
|
this->invokeReleaseProc();
|
||||||
|
this->INHERITED::onRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrSurface::onAbandon() {
|
||||||
|
this->invokeReleaseProc();
|
||||||
|
this->INHERITED::onAbandon();
|
||||||
|
}
|
||||||
|
@ -205,7 +205,8 @@ SkImage* SkImage_Base::onNewImage(int newWidth, int newHeight, const SkIRect* su
|
|||||||
|
|
||||||
#if !SK_SUPPORT_GPU
|
#if !SK_SUPPORT_GPU
|
||||||
|
|
||||||
SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
|
SkImage* SkImage::NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
|
||||||
|
TextureReleaseProc, ReleaseContext) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,9 @@ bool SkImage_Gpu::onReadPixels(const SkImageInfo& info, void* pixels, size_t row
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static SkImage* new_wrapped_texture_common(GrContext* ctx, const GrBackendTextureDesc& desc,
|
static SkImage* new_wrapped_texture_common(GrContext* ctx, const GrBackendTextureDesc& desc,
|
||||||
SkAlphaType at, GrWrapOwnership ownership) {
|
SkAlphaType at, GrWrapOwnership ownership,
|
||||||
|
SkImage::TextureReleaseProc releaseProc,
|
||||||
|
SkImage::ReleaseContext releaseCtx) {
|
||||||
if (desc.fWidth <= 0 || desc.fHeight <= 0) {
|
if (desc.fWidth <= 0 || desc.fHeight <= 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -123,18 +125,23 @@ static SkImage* new_wrapped_texture_common(GrContext* ctx, const GrBackendTextur
|
|||||||
if (!tex) {
|
if (!tex) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (releaseProc) {
|
||||||
|
tex->setRelease(releaseProc, releaseCtx);
|
||||||
|
}
|
||||||
|
|
||||||
const SkSurface::Budgeted budgeted = SkSurface::kNo_Budgeted;
|
const SkSurface::Budgeted budgeted = SkSurface::kNo_Budgeted;
|
||||||
return SkNEW_ARGS(SkImage_Gpu, (desc.fWidth, desc.fHeight, at, tex, 0, budgeted));
|
return SkNEW_ARGS(SkImage_Gpu, (desc.fWidth, desc.fHeight, at, tex, 0, budgeted));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkImage* SkImage::NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc, SkAlphaType at) {
|
SkImage* SkImage::NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc, SkAlphaType at,
|
||||||
return new_wrapped_texture_common(ctx, desc, at, kBorrow_GrWrapOwnership);
|
TextureReleaseProc releaseP, ReleaseContext releaseC) {
|
||||||
|
return new_wrapped_texture_common(ctx, desc, at, kBorrow_GrWrapOwnership, releaseP, releaseC);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkImage* SkImage::NewFromAdoptedTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
|
SkImage* SkImage::NewFromAdoptedTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
|
||||||
SkAlphaType at) {
|
SkAlphaType at) {
|
||||||
return new_wrapped_texture_common(ctx, desc, at, kAdopt_GrWrapOwnership);
|
return new_wrapped_texture_common(ctx, desc, at, kAdopt_GrWrapOwnership, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkImage* SkImage::NewFromTextureCopy(GrContext* ctx, const GrBackendTextureDesc& srcDesc,
|
SkImage* SkImage::NewFromTextureCopy(GrContext* ctx, const GrBackendTextureDesc& srcDesc,
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
class SkImage_Raster : public SkImage_Base {
|
class SkImage_Raster : public SkImage_Base {
|
||||||
public:
|
public:
|
||||||
static bool ValidArgs(const Info& info, size_t rowBytes) {
|
static bool ValidArgs(const Info& info, size_t rowBytes, size_t* minSize) {
|
||||||
const int maxDimension = SK_MaxS32 >> 2;
|
const int maxDimension = SK_MaxS32 >> 2;
|
||||||
const size_t kMaxPixelByteSize = SK_MaxS32;
|
|
||||||
|
|
||||||
if (info.width() <= 0 || info.height() <= 0) {
|
if (info.width() <= 0 || info.height() <= 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -43,10 +42,14 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t size = (int64_t)info.height() * rowBytes;
|
size_t size = info.getSafeSize(rowBytes);
|
||||||
if (size > (int64_t)kMaxPixelByteSize) {
|
if (0 == size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minSize) {
|
||||||
|
*minSize = size;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,23 +149,24 @@ bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
|
SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
|
||||||
if (!SkImage_Raster::ValidArgs(info, rowBytes) || !pixels) {
|
size_t size;
|
||||||
|
if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !pixels) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we actually make a copy of the caller's pixel data
|
// Here we actually make a copy of the caller's pixel data
|
||||||
SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.height() * rowBytes));
|
SkAutoDataUnref data(SkData::NewWithCopy(pixels, size));
|
||||||
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
|
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
|
SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
|
||||||
if (!SkImage_Raster::ValidArgs(info, rowBytes) || !data) {
|
size_t size;
|
||||||
|
if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !data) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// did they give us enough data?
|
// did they give us enough data?
|
||||||
size_t size = info.height() * rowBytes;
|
|
||||||
if (data->size() < size) {
|
if (data->size() < size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -170,6 +174,17 @@ SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t ro
|
|||||||
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
|
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkImage* SkImage::NewFromRaster(const SkImageInfo& info, const void* pixels, size_t rowBytes,
|
||||||
|
RasterReleaseProc proc, ReleaseContext ctx) {
|
||||||
|
size_t size;
|
||||||
|
if (!SkImage_Raster::ValidArgs(info, rowBytes, &size) || !pixels) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkAutoDataUnref data(SkData::NewWithProc(pixels, size, proc, ctx));
|
||||||
|
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
|
SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
|
||||||
SkBitmap bitmap;
|
SkBitmap bitmap;
|
||||||
if (!SkInstallDiscardablePixelRef(generator, &bitmap)) {
|
if (!SkInstallDiscardablePixelRef(generator, &bitmap)) {
|
||||||
@ -185,7 +200,7 @@ SkImage* SkImage::NewFromGenerator(SkImageGenerator* generator) {
|
|||||||
SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
|
SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
|
||||||
const SkIPoint& pixelRefOrigin, size_t rowBytes,
|
const SkIPoint& pixelRefOrigin, size_t rowBytes,
|
||||||
const SkSurfaceProps* props) {
|
const SkSurfaceProps* props) {
|
||||||
if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
|
if (!SkImage_Raster::ValidArgs(info, rowBytes, NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return SkNEW_ARGS(SkImage_Raster, (info, pr, pixelRefOrigin, rowBytes, props));
|
return SkNEW_ARGS(SkImage_Raster, (info, pr, pixelRefOrigin, rowBytes, props));
|
||||||
@ -193,7 +208,7 @@ SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
|
|||||||
|
|
||||||
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef,
|
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef,
|
||||||
const SkSurfaceProps* props) {
|
const SkSurfaceProps* props) {
|
||||||
if (!SkImage_Raster::ValidArgs(bm.info(), bm.rowBytes())) {
|
if (!SkImage_Raster::ValidArgs(bm.info(), bm.rowBytes(), NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context,
|
|||||||
enum ImageType {
|
enum ImageType {
|
||||||
kRasterCopy_ImageType,
|
kRasterCopy_ImageType,
|
||||||
kRasterData_ImageType,
|
kRasterData_ImageType,
|
||||||
|
kRasterProc_ImageType,
|
||||||
kGpu_ImageType,
|
kGpu_ImageType,
|
||||||
kCodec_ImageType,
|
kCodec_ImageType,
|
||||||
};
|
};
|
||||||
@ -81,6 +82,7 @@ static void test_empty_image(skiatest::Reporter* reporter) {
|
|||||||
|
|
||||||
REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterCopy(info, NULL, 0));
|
REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterCopy(info, NULL, 0));
|
||||||
REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterData(info, NULL, 0));
|
REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterData(info, NULL, 0));
|
||||||
|
REPORTER_ASSERT(reporter, NULL == SkImage::NewFromRaster(info, NULL, 0, NULL, NULL));
|
||||||
REPORTER_ASSERT(reporter, NULL == SkImage::NewFromGenerator(SkNEW(EmptyGenerator)));
|
REPORTER_ASSERT(reporter, NULL == SkImage::NewFromGenerator(SkNEW(EmptyGenerator)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +206,21 @@ static void test_image(skiatest::Reporter* reporter) {
|
|||||||
data->unref();
|
data->unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
static SkImage* createImage(ImageType imageType, GrContext* context, SkColor color) {
|
// Want to ensure that our Release is called when the owning image is destroyed
|
||||||
|
struct ReleaseDataContext {
|
||||||
|
skiatest::Reporter* fReporter;
|
||||||
|
SkData* fData;
|
||||||
|
|
||||||
|
static void Release(const void* pixels, void* context) {
|
||||||
|
ReleaseDataContext* state = (ReleaseDataContext*)context;
|
||||||
|
REPORTER_ASSERT(state->fReporter, state->fData);
|
||||||
|
state->fData->unref();
|
||||||
|
state->fData = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static SkImage* createImage(ImageType imageType, GrContext* context, SkColor color,
|
||||||
|
ReleaseDataContext* releaseContext) {
|
||||||
const SkPMColor pmcolor = SkPreMultiplyColor(color);
|
const SkPMColor pmcolor = SkPreMultiplyColor(color);
|
||||||
const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
|
const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
|
||||||
const size_t rowBytes = info.minRowBytes();
|
const size_t rowBytes = info.minRowBytes();
|
||||||
@ -219,6 +235,11 @@ static SkImage* createImage(ImageType imageType, GrContext* context, SkColor col
|
|||||||
return SkImage::NewRasterCopy(info, addr, rowBytes);
|
return SkImage::NewRasterCopy(info, addr, rowBytes);
|
||||||
case kRasterData_ImageType:
|
case kRasterData_ImageType:
|
||||||
return SkImage::NewRasterData(info, data, rowBytes);
|
return SkImage::NewRasterData(info, data, rowBytes);
|
||||||
|
case kRasterProc_ImageType:
|
||||||
|
SkASSERT(releaseContext);
|
||||||
|
releaseContext->fData = SkRef(data.get());
|
||||||
|
return SkImage::NewFromRaster(info, addr, rowBytes,
|
||||||
|
ReleaseDataContext::Release, releaseContext);
|
||||||
case kGpu_ImageType: {
|
case kGpu_ImageType: {
|
||||||
SkAutoTUnref<SkSurface> surf(
|
SkAutoTUnref<SkSurface> surf(
|
||||||
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0));
|
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0));
|
||||||
@ -302,6 +323,7 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
|
|||||||
} gRec[] = {
|
} gRec[] = {
|
||||||
{ kRasterCopy_ImageType, true, "RasterCopy" },
|
{ kRasterCopy_ImageType, true, "RasterCopy" },
|
||||||
{ kRasterData_ImageType, true, "RasterData" },
|
{ kRasterData_ImageType, true, "RasterData" },
|
||||||
|
{ kRasterProc_ImageType, true, "RasterProc" },
|
||||||
{ kGpu_ImageType, false, "Gpu" },
|
{ kGpu_ImageType, false, "Gpu" },
|
||||||
{ kCodec_ImageType, false, "Codec" },
|
{ kCodec_ImageType, false, "Codec" },
|
||||||
};
|
};
|
||||||
@ -317,15 +339,25 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ReleaseDataContext releaseCtx;
|
||||||
|
releaseCtx.fReporter = reporter;
|
||||||
|
|
||||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
|
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
|
||||||
SkImageInfo info;
|
SkImageInfo info;
|
||||||
size_t rowBytes;
|
size_t rowBytes;
|
||||||
|
|
||||||
SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color));
|
releaseCtx.fData = NULL;
|
||||||
|
SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color, &releaseCtx));
|
||||||
if (!image.get()) {
|
if (!image.get()) {
|
||||||
SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName);
|
SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName);
|
||||||
continue; // gpu may not be enabled
|
continue; // gpu may not be enabled
|
||||||
}
|
}
|
||||||
|
if (kRasterProc_ImageType == gRec[i].fType) {
|
||||||
|
REPORTER_ASSERT(reporter, NULL != releaseCtx.fData); // we are tracking the data
|
||||||
|
} else {
|
||||||
|
REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we ignored the context
|
||||||
|
}
|
||||||
|
|
||||||
const void* addr = image->peekPixels(&info, &rowBytes);
|
const void* addr = image->peekPixels(&info, &rowBytes);
|
||||||
bool success = SkToBool(addr);
|
bool success = SkToBool(addr);
|
||||||
REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success);
|
REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success);
|
||||||
@ -341,6 +373,7 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
|
|||||||
|
|
||||||
test_image_readpixels(reporter, image, pmcolor);
|
test_image_readpixels(reporter, image, pmcolor);
|
||||||
}
|
}
|
||||||
|
REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we released the data
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_canvaspeek(skiatest::Reporter* reporter,
|
static void test_canvaspeek(skiatest::Reporter* reporter,
|
||||||
@ -739,7 +772,28 @@ DEF_GPUTEST(Surface, reporter, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject texID, bool doCopy) {
|
|
||||||
|
struct ReleaseTextureContext {
|
||||||
|
ReleaseTextureContext(skiatest::Reporter* reporter) {
|
||||||
|
fReporter = reporter;
|
||||||
|
fIsReleased = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
skiatest::Reporter* fReporter;
|
||||||
|
bool fIsReleased;
|
||||||
|
|
||||||
|
void doRelease() {
|
||||||
|
REPORTER_ASSERT(fReporter, false == fIsReleased);
|
||||||
|
fIsReleased = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReleaseProc(void* context) {
|
||||||
|
((ReleaseTextureContext*)context)->doRelease();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject texID,
|
||||||
|
ReleaseTextureContext* releaseContext) {
|
||||||
GrBackendTextureDesc desc;
|
GrBackendTextureDesc desc;
|
||||||
desc.fConfig = kSkia8888_GrPixelConfig;
|
desc.fConfig = kSkia8888_GrPixelConfig;
|
||||||
// need to be a rendertarget for now...
|
// need to be a rendertarget for now...
|
||||||
@ -748,7 +802,10 @@ static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject te
|
|||||||
desc.fHeight = h;
|
desc.fHeight = h;
|
||||||
desc.fSampleCnt = 0;
|
desc.fSampleCnt = 0;
|
||||||
desc.fTextureHandle = texID;
|
desc.fTextureHandle = texID;
|
||||||
return doCopy ? SkImage::NewFromTextureCopy(ctx, desc) : SkImage::NewFromTexture(ctx, desc);
|
return releaseContext
|
||||||
|
? SkImage::NewFromTexture(ctx, desc, kPremul_SkAlphaType,
|
||||||
|
ReleaseTextureContext::ReleaseProc, releaseContext)
|
||||||
|
: SkImage::NewFromTextureCopy(ctx, desc, kPremul_SkAlphaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) {
|
static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) {
|
||||||
@ -787,8 +844,10 @@ DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GrBackendObject srcTex = tex->getTextureHandle();
|
GrBackendObject srcTex = tex->getTextureHandle();
|
||||||
SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, false));
|
ReleaseTextureContext releaseCtx(reporter);
|
||||||
SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, true));
|
|
||||||
|
SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, &releaseCtx));
|
||||||
|
SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, NULL));
|
||||||
|
|
||||||
test_image_color(reporter, refImg, expected0);
|
test_image_color(reporter, refImg, expected0);
|
||||||
test_image_color(reporter, cpyImg, expected0);
|
test_image_color(reporter, cpyImg, expected0);
|
||||||
@ -801,5 +860,10 @@ DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) {
|
|||||||
// We expect the ref'd image to see the new color, but cpy'd one should still see the old color
|
// We expect the ref'd image to see the new color, but cpy'd one should still see the old color
|
||||||
test_image_color(reporter, refImg, expected1);
|
test_image_color(reporter, refImg, expected1);
|
||||||
test_image_color(reporter, cpyImg, expected0);
|
test_image_color(reporter, cpyImg, expected0);
|
||||||
|
|
||||||
|
// Now exercise the release proc
|
||||||
|
REPORTER_ASSERT(reporter, !releaseCtx.fIsReleased);
|
||||||
|
refImg.reset(NULL); // force a release of the image
|
||||||
|
REPORTER_ASSERT(reporter, releaseCtx.fIsReleased);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user