namespace {
+void release_proc(void*, void* releaseCtx) {
+ reinterpret_cast<SkImage*>(releaseCtx)->unref();
+}
+
class ExternalGenerator : public SkImageGenerator {
public:
ExternalGenerator(const SkISize size)
const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height());
const int lvl = SkScalarFloorToInt(-SkScalarLog2(scale));
- rec->fImage = fMips[SkTPin(lvl, 0, fMips.count())];
+ const sk_sp<SkImage>& img = fMips[SkTPin(lvl, 0, fMips.count())];
+ SkAssertResult(img->peekPixels(&rec->fPixmap));
const SkRect origBounds = SkRect::Make(this->getInfo().bounds());
- const SkRect newBounds = SkRect::Make(rec->fImage->bounds());
+ const SkRect newBounds = SkRect::Make(img->bounds());
SkMatrix srcMap = SkMatrix::MakeScale(newBounds.width() / origBounds.width(),
newBounds.height() / origBounds.height());
rec->fQuality = kLow_SkFilterQuality;
+ rec->fReleaseProc = release_proc;
+ rec->fReleaseCtx = SkRef(img.get());
+
return true;
}
* External generator API: provides efficient access to externally-managed image data.
*
* Skia calls accessScaledPixels() during rasterization, to gain temporary access to
- * the external pixel data, packaged as a raster SkImage.
+ * the external pixel data. When done, the provided callback is invoked to release the
+ * associated resources.
*
* @param srcRect the source rect in use for the current draw
* @param totalMatrix full matrix in effect (mapping srcRect -> device space)
* @param quality the SkFilterQuality requested for rasterization.
* @param rec out param, expected to be set when the call succeeds:
*
- * - fImage wraps the external pixel data
- * - fSrcRect is an adjusted srcRect
- * - fQuality is the adjusted filter quality
+ * - fPixmap external pixel data
+ * - fSrcRect is an adjusted srcRect
+ * - fQuality is the adjusted filter quality
+ * - fReleaseProc pixmap release callback, same signature as the
+ * SkBitmap::installPixels() callback
+ * - fReleaseCtx opaque release context argument
*
* @return true on success, false otherwise (error or if this API is not supported;
* in this case Skia will fall back to its internal scaling and caching
*/
struct ScaledImageRec {
- sk_sp<SkImage> fImage;
+ SkPixmap fPixmap;
SkRect fSrcRect;
SkFilterQuality fQuality;
+
+ using ReleaseProcT = void (*)(void* pixels, void* releaseCtx);
+
+ ReleaseProcT fReleaseProc;
+ void* fReleaseCtx;
};
bool accessScaledImage(const SkRect& srcRect, const SkMatrix& totalMatrix,
SkImageGenerator::ScaledImageRec rec;
if (!cacherator->directAccessScaledImage(srcRect, m, fq, &rec) ||
- !rec.fImage->asLegacyBitmap(scaledBitmap, SkImage::kRO_LegacyBitmapMode)) {
+ !scaledBitmap->installPixels(rec.fPixmap.info(), const_cast<void*>(rec.fPixmap.addr()),
+ rec.fPixmap.rowBytes(), rec.fPixmap.ctable(),
+ rec.fReleaseProc, rec.fReleaseCtx)) {
return false;
}
return false;
}
- SkDestinationSurfaceColorMode colorMode = this->imageInfo().colorSpace()
- ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
- : SkDestinationSurfaceColorMode::kLegacy;
SkBitmap bm;
- if (!as_IB(rec.fImage)->getROPixels(&bm, colorMode)) {
+ if (!bm.installPixels(rec.fPixmap.info(), const_cast<void*>(rec.fPixmap.addr()),
+ rec.fPixmap.rowBytes(), rec.fPixmap.ctable(),
+ rec.fReleaseProc, rec.fReleaseCtx)) {
return false;
}