scaling API on SkPixmap

BUG=skia:4481

Review URL: https://codereview.chromium.org/1463373002
This commit is contained in:
reed 2015-11-23 12:32:16 -08:00 committed by Commit bot
parent 512e437e1e
commit 095530389d
15 changed files with 268 additions and 51 deletions

View File

@ -192,3 +192,111 @@ private:
typedef skiagm::GM INHERITED;
};
DEF_GM( return new ImageGM; )
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkPictureRecorder.h"
static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pmap) {
SkBitmap bitmap;
bitmap.installPixels(pmap.info(), (void*)pmap.addr(), pmap.rowBytes());
canvas->drawBitmap(bitmap, 0, 0, nullptr);
}
static void show_scaled_pixels(SkCanvas* canvas, SkImage* image) {
SkAutoCanvasRestore acr(canvas, true);
canvas->drawImage(image, 0, 0, nullptr);
canvas->translate(110, 10);
const SkImageInfo info = SkImageInfo::MakeN32Premul(40, 40);
SkAutoPixmapStorage storage;
storage.alloc(info);
const SkImage::CachingHint chints[] = {
SkImage::kAllow_CachingHint, // SkImage::kDisallow_CachingHint,
};
const SkFilterQuality qualities[] = {
kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality,
};
for (auto ch : chints) {
canvas->save();
for (auto q : qualities) {
if (image->scalePixels(storage, q, ch)) {
draw_pixmap(canvas, storage);
}
canvas->translate(70, 0);
}
canvas->restore();
canvas->translate(0, 45);
}
}
static void draw_contents(SkCanvas* canvas) {
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(20);
canvas->drawCircle(50, 50, 35, paint);
}
static SkImage* make_raster(const SkImageInfo& info, GrContext*) {
SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
draw_contents(surface->getCanvas());
return surface->newImageSnapshot();
}
static SkImage* make_picture(const SkImageInfo& info, GrContext*) {
SkPictureRecorder recorder;
draw_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
SkAutoTUnref<SkPicture> pict(recorder.endRecording());
return SkImage::NewFromPicture(pict, info.dimensions(), nullptr, nullptr);
}
static SkImage* make_codec(const SkImageInfo& info, GrContext*) {
SkAutoTUnref<SkImage> image(make_raster(info, nullptr));
SkAutoTUnref<SkData> data(image->encode());
return SkImage::NewFromEncoded(data);
}
static SkImage* make_gpu(const SkImageInfo& info, GrContext* ctx) {
if (!ctx) { return nullptr; }
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info));
draw_contents(surface->getCanvas());
return surface->newImageSnapshot();
}
typedef SkImage* (*ImageMakerProc)(const SkImageInfo&, GrContext*);
class ScalePixelsGM : public skiagm::GM {
public:
ScalePixelsGM() {}
protected:
SkString onShortName() override {
return SkString("scale-pixels");
}
SkISize onISize() override {
return SkISize::Make(960, 1200);
}
void onDraw(SkCanvas* canvas) override {
const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
const ImageMakerProc procs[] = {
make_raster, make_picture, make_codec, make_gpu,
};
for (auto& proc : procs) {
SkAutoTUnref<SkImage> image(proc(info, canvas->getGrContext()));
if (image) {
show_scaled_pixels(canvas, image);
}
canvas->translate(0, 120);
}
}
private:
typedef skiagm::GM INHERITED;
};
DEF_GM( return new ScalePixelsGM; )

View File

@ -207,6 +207,16 @@ public:
*/
GrBackendObject getTextureHandle(bool flushPendingGrContextIO) const;
/**
* Hints to image calls where the system might cache computed intermediates (e.g. the results
* of decoding or a read-back from the GPU. Passing kAllow signals that the system's default
* behavior is fine. Passing kDisallow signals that caching should be avoided.
*/
enum CachingHint {
kAllow_CachingHint,
kDisallow_CachingHint,
};
/**
* Copy the pixels from the image into the specified buffer (pixels + rowBytes),
* converting them into the requested format (dstInfo). The image pixels are read
@ -226,9 +236,19 @@ public:
* - If the requested colortype/alphatype cannot be converted from the image's types.
*/
bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY) const;
int srcX, int srcY, CachingHint = kAllow_CachingHint) const;
bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;
bool readPixels(const SkPixmap& dst, int srcX, int srcY,
CachingHint = kAllow_CachingHint) const;
/**
* Copy the pixels from this image into the dst pixmap, converting as needed into dst's
* colortype/alphatype. If the conversion cannot be performed, false is returned.
*
* If dst's dimensions differ from the src dimension, the image will be scaled, applying the
* specified filter-quality.
*/
bool scalePixels(const SkPixmap& dst, SkFilterQuality, CachingHint = kAllow_CachingHint) const;
/**
* Encode the image's pixels and return the result as a new SkData, which

View File

@ -9,6 +9,7 @@
#define SkPixmap_DEFINED
#include "SkColor.h"
#include "SkFilterQuality.h"
#include "SkImageInfo.h"
class SkColorTable;
@ -134,6 +135,15 @@ public:
return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
}
/**
* Copy the pixels from this pixmap into the dst pixmap, converting as needed into dst's
* colortype/alphatype. If the conversion cannot be performed, false is returned.
*
* If dst's dimensions differ from the src dimension, the image will be scaled, applying the
* specified filter-quality.
*/
bool scalePixels(const SkPixmap& dst, SkFilterQuality) const;
/**
* Returns true if pixels were written to (e.g. if colorType is kUnknown_SkColorType, this
* will return false). If subset does not intersect the bounds of this pixmap, returns false.

View File

@ -121,8 +121,10 @@ bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmapProvider& pr
SkASSERT(fResultBitmap.getPixels());
fResultBitmap.setImmutable();
if (SkBitmapCache::AddWH(desc, fResultBitmap)) {
provider.notifyAddedToCache();
if (!provider.isVolatile()) {
if (SkBitmapCache::AddWH(desc, fResultBitmap)) {
provider.notifyAddedToCache();
}
}
}

View File

@ -52,6 +52,14 @@ SkImageInfo SkBitmapProvider::info() const {
}
}
bool SkBitmapProvider::isVolatile() const {
if (fImage) {
return false; // add flag to images?
} else {
return fBitmap.isVolatile();
}
}
SkBitmapCacheDesc SkBitmapProvider::makeCacheDesc(int w, int h) const {
return fImage ? SkBitmapCacheDesc::Make(fImage, w, h) : SkBitmapCacheDesc::Make(fBitmap, w, h);
}
@ -70,7 +78,7 @@ void SkBitmapProvider::notifyAddedToCache() const {
bool SkBitmapProvider::asBitmap(SkBitmap* bm) const {
if (fImage) {
return as_IB(fImage)->getROPixels(bm);
return as_IB(fImage)->getROPixels(bm, SkImage::kAllow_CachingHint);
} else {
*bm = fBitmap;
return true;

View File

@ -27,6 +27,7 @@ public:
bool validForDrawing() const;
SkImageInfo info() const;
bool isVolatile() const;
SkBitmapCacheDesc makeCacheDesc(int w, int h) const;
SkBitmapCacheDesc makeCacheDesc() const;

View File

@ -110,7 +110,8 @@ bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) {
//////////////////////////////////////////////////////////////////////////////////////////////////
bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client) {
bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client,
SkImage::CachingHint chint) {
if (SkBitmapCache::Find(fUniqueID, bitmap)) {
return check_output_bitmap(*bitmap, fUniqueID);
}
@ -120,16 +121,18 @@ bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client)
}
bitmap->pixelRef()->setImmutableWithID(fUniqueID);
SkBitmapCache::Add(fUniqueID, *bitmap);
if (client) {
as_IB(client)->notifyAddedToCache();
if (SkImage::kAllow_CachingHint == chint) {
SkBitmapCache::Add(fUniqueID, *bitmap);
if (client) {
as_IB(client)->notifyAddedToCache();
}
}
return true;
}
bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client) {
if (this->tryLockAsBitmap(bitmap, client)) {
bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client,
SkImage::CachingHint chint) {
if (this->tryLockAsBitmap(bitmap, client, chint)) {
return check_output_bitmap(*bitmap, fUniqueID);
}
@ -160,11 +163,12 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client) {
}
bitmap->pixelRef()->setImmutableWithID(fUniqueID);
SkBitmapCache::Add(fUniqueID, *bitmap);
if (client) {
as_IB(client)->notifyAddedToCache();
if (SkImage::kAllow_CachingHint == chint) {
SkBitmapCache::Add(fUniqueID, *bitmap);
if (client) {
as_IB(client)->notifyAddedToCache();
}
}
return check_output_bitmap(*bitmap, fUniqueID);
#else
return false;
@ -220,7 +224,7 @@ static GrTexture* set_key_and_return(GrTexture* tex, const GrUniqueKey& key) {
* 5. Ask the generator to return RGB(A) data, which the GPU can convert
*/
GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key,
const SkImage* client) {
const SkImage* client, SkImage::CachingHint chint) {
// 1. Check the cache for a pre-existing one
if (key.isValid()) {
if (GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key)) {
@ -260,7 +264,7 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key
// 5. Ask the generator to return RGB(A) data, which the GPU can convert
SkBitmap bitmap;
if (this->tryLockAsBitmap(&bitmap, client)) {
if (this->tryLockAsBitmap(&bitmap, client, chint)) {
GrTexture* tex = GrUploadBitmapToTexture(ctx, bitmap);
if (tex) {
return set_key_and_return(tex, key);
@ -275,10 +279,13 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key
class Cacherator_GrTextureMaker : public GrTextureMaker {
public:
Cacherator_GrTextureMaker(GrContext* context, SkImageCacherator* cacher, const SkImage* client)
Cacherator_GrTextureMaker(GrContext* context, SkImageCacherator* cacher, const SkImage* client,
SkImage::CachingHint chint)
: INHERITED(context, cacher->info().width(), cacher->info().height())
, fCacher(cacher)
, fClient(client) {
, fClient(client)
, fCachingHint(chint)
{
if (client) {
GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(),
SkIRect::MakeWH(this->width(), this->height()));
@ -291,7 +298,7 @@ protected:
// GrTexture* generateTextureForParams(const CopyParams&) override;
GrTexture* refOriginalTexture() override {
return fCacher->lockTexture(this->context(), fOriginalKey, fClient);
return fCacher->lockTexture(this->context(), fOriginalKey, fClient, fCachingHint);
}
void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override {
@ -310,23 +317,24 @@ private:
SkImageCacherator* fCacher;
const SkImage* fClient;
GrUniqueKey fOriginalKey;
SkImage::CachingHint fCachingHint;
typedef GrTextureMaker INHERITED;
};
GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, const GrTextureParams& params,
const SkImage* client) {
const SkImage* client, SkImage::CachingHint chint) {
if (!ctx) {
return nullptr;
}
return Cacherator_GrTextureMaker(ctx, this, client).refTextureForParams(params);
return Cacherator_GrTextureMaker(ctx, this, client, chint).refTextureForParams(params);
}
#else
GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, const GrTextureParams&,
const SkImage* client) {
const SkImage* client, SkImage::CachingHint) {
return nullptr;
}

View File

@ -36,7 +36,8 @@ public:
* If not NULL, the client will be notified (->notifyAddedToCache()) when resources are
* added to the cache on its behalf.
*/
bool lockAsBitmap(SkBitmap*, const SkImage* client);
bool lockAsBitmap(SkBitmap*, const SkImage* client,
SkImage::CachingHint = SkImage::kAllow_CachingHint);
/**
* Returns a ref() on the texture produced by this generator. The caller must call unref()
@ -47,7 +48,8 @@ public:
*
* The caller is responsible for calling texture->unref() when they are done.
*/
GrTexture* lockAsTexture(GrContext*, const GrTextureParams&, const SkImage* client);
GrTexture* lockAsTexture(GrContext*, const GrTextureParams&, const SkImage* client,
SkImage::CachingHint = SkImage::kAllow_CachingHint);
/**
* If the underlying src naturally is represented by an encoded blob (in SkData), this returns
@ -59,11 +61,12 @@ private:
SkImageCacherator(SkImageGenerator*, const SkImageInfo&, const SkIPoint&, uint32_t uniqueID);
bool generateBitmap(SkBitmap*);
bool tryLockAsBitmap(SkBitmap*, const SkImage*);
bool tryLockAsBitmap(SkBitmap*, const SkImage*, SkImage::CachingHint);
#if SK_SUPPORT_GPU
// Returns the texture. If the cacherator is generating the texture and wants to cache it,
// it should use the passed in key (if the key is valid).
GrTexture* lockTexture(GrContext*, const GrUniqueKey& key, const SkImage* client);
GrTexture* lockTexture(GrContext*, const GrUniqueKey& key, const SkImage* client,
SkImage::CachingHint);
#endif
class ScopedGenerator {

View File

@ -205,6 +205,44 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
return true;
}
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkSurface.h"
#include "SkXfermode.h"
bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const {
// Can't do anthing with empty src or dst
if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) {
return false;
}
// no scaling involved?
if (dst.width() == this->width() && dst.height() == this->height()) {
return this->readPixels(dst);
}
SkBitmap bitmap;
// we will only ready from this pixmap, but the bitmap setting takes void*, hence the cast
void* readOnlyAddr = const_cast<void*>(this->addr());
if (!bitmap.installPixels(this->info(), readOnlyAddr, this->rowBytes())) {
return false;
}
bitmap.setIsVolatile(true); // so we don't try to cache it
SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterDirect(dst.info(), dst.writable_addr(),
dst.rowBytes()));
if (!surface) {
return false;
}
SkPaint paint;
paint.setFilterQuality(quality);
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
surface->getCanvas()->drawBitmapRect(bitmap, SkRect::MakeIWH(dst.width(), dst.height()),
&paint);
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
SkAutoPixmapStorage::SkAutoPixmapStorage() : fStorage(nullptr) {}

View File

@ -48,12 +48,29 @@ const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
}
bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY) const {
int srcX, int srcY, CachingHint chint) const {
SkReadPixelsRec rec(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
if (!rec.trim(this->width(), this->height())) {
return false;
}
return as_IB(this)->onReadPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
return as_IB(this)->onReadPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY, chint);
}
bool SkImage::scalePixels(const SkPixmap& dst, SkFilterQuality quality, CachingHint chint) const {
// Idea: If/when SkImageGenerator supports a native-scaling API (where the generator itself
// can scale more efficiently) we should take advantage of it here.
//
SkBitmap bm;
if (as_IB(this)->getROPixels(&bm, chint)) {
bm.lockPixels();
SkPixmap pmap;
// Note: By calling the pixmap scaler, we never cache the final result, so the chint
// is (currently) only being applied to the getROPixels. If we get a request to
// also attempt to cache the final (scaled) result, we would add that logic here.
//
return bm.peekPixels(&pmap) && pmap.scalePixels(dst, quality);
}
return false;
}
void SkImage::preroll(GrContext* ctx) const {
@ -286,7 +303,7 @@ SkImage_Base::~SkImage_Base() {
}
bool SkImage_Base::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY) const {
int srcX, int srcY, CachingHint) const {
if (!raster_canvas_supports(dstInfo)) {
return false;
}
@ -317,8 +334,8 @@ bool SkImage::peekPixels(SkPixmap* pmap) const {
return false;
}
bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY) const {
return this->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), srcX, srcY);
bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY, CachingHint chint) const {
return this->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), srcX, srcY, chint);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -29,13 +29,13 @@ public:
// Default impl calls onDraw
virtual bool onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY) const;
int srcX, int srcY, CachingHint) const;
virtual GrTexture* peekTexture() const { return nullptr; }
// return a read-only copy of the pixels. We promise to not modify them,
// but only inspect them (or encode them).
virtual bool getROPixels(SkBitmap*) const = 0;
virtual bool getROPixels(SkBitmap*, CachingHint = kAllow_CachingHint) const = 0;
virtual SkImage* onApplyFilter(SkImageFilter*, SkIPoint* offset,
bool forceResultToOriginalSize) const;

View File

@ -21,12 +21,12 @@ public:
, fCache(cache) // take ownership
{}
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override;
const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
SkData* onRefEncoded() const override;
bool isOpaque() const override { return fCache->info().isOpaque(); }
SkImage* onNewSubset(const SkIRect&) const override;
bool getROPixels(SkBitmap*) const override;
bool getROPixels(SkBitmap*, CachingHint) const override;
GrTexture* asTextureRef(GrContext*, const GrTextureParams&) const override;
bool onIsLazyGenerated() const override { return true; }
@ -39,9 +39,9 @@ private:
///////////////////////////////////////////////////////////////////////////////
bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
int srcX, int srcY) const {
int srcX, int srcY, CachingHint chint) const {
SkBitmap bm;
if (this->getROPixels(&bm)) {
if (this->getROPixels(&bm, chint)) {
return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
}
return false;
@ -55,8 +55,8 @@ SkData* SkImage_Generator::onRefEncoded() const {
return fCache->refEncoded();
}
bool SkImage_Generator::getROPixels(SkBitmap* bitmap) const {
return fCache->lockAsBitmap(bitmap, this);
bool SkImage_Generator::getROPixels(SkBitmap* bitmap, CachingHint chint) const {
return fCache->lockAsBitmap(bitmap, this, chint);
}
GrTexture* SkImage_Generator::asTextureRef(GrContext* ctx, const GrTextureParams& params) const {

View File

@ -45,7 +45,7 @@ static SkImageInfo make_info(int w, int h, bool isOpaque) {
return SkImageInfo::MakeN32(w, h, isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
}
bool SkImage_Gpu::getROPixels(SkBitmap* dst) const {
bool SkImage_Gpu::getROPixels(SkBitmap* dst, CachingHint chint) const {
if (SkBitmapCache::Find(this->uniqueID(), dst)) {
SkASSERT(dst->getGenerationID() == this->uniqueID());
SkASSERT(dst->isImmutable());
@ -62,8 +62,10 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst) const {
}
dst->pixelRef()->setImmutableWithID(this->uniqueID());
SkBitmapCache::Add(this->uniqueID(), *dst);
fAddedRasterVersionToCache.store(true);
if (kAllow_CachingHint == chint) {
SkBitmapCache::Add(this->uniqueID(), *dst);
fAddedRasterVersionToCache.store(true);
}
return true;
}
@ -120,7 +122,7 @@ static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes)
}
bool SkImage_Gpu::onReadPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
int srcX, int srcY) const {
int srcX, int srcY, CachingHint) const {
GrPixelConfig config = SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType(),
info.profileType());
uint32_t flags = 0;

View File

@ -35,14 +35,14 @@ public:
}
}
bool getROPixels(SkBitmap*) const override;
bool getROPixels(SkBitmap*, CachingHint) const override;
GrTexture* asTextureRef(GrContext* ctx, const GrTextureParams& params) const override;
SkImage* onNewSubset(const SkIRect&) const override;
GrTexture* peekTexture() const override { return fTexture; }
bool isOpaque() const override;
bool onReadPixels(const SkImageInfo&, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY) const override;
int srcX, int srcY, CachingHint) const override;
SkImage* onApplyFilter(SkImageFilter*, SkIPoint* offset,
bool forceResultToOriginalSize) const override;

View File

@ -66,10 +66,10 @@ public:
SkImage_Raster(const SkImageInfo&, SkData*, size_t rb, SkColorTable*);
virtual ~SkImage_Raster();
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY) const override;
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override;
const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
SkData* onRefEncoded() const override;
bool getROPixels(SkBitmap*) const override;
bool getROPixels(SkBitmap*, CachingHint) const override;
GrTexture* asTextureRef(GrContext*, const GrTextureParams&) const override;
SkImage* onNewSubset(const SkIRect&) const override;
@ -135,7 +135,7 @@ SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, const SkIPoint&
SkImage_Raster::~SkImage_Raster() {}
bool SkImage_Raster::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY) const {
int srcX, int srcY, CachingHint) const {
SkBitmap shallowCopy(fBitmap);
return shallowCopy.readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
}
@ -162,7 +162,7 @@ SkData* SkImage_Raster::onRefEncoded() const {
return nullptr;
}
bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
bool SkImage_Raster::getROPixels(SkBitmap* dst, CachingHint) const {
*dst = fBitmap;
return true;
}