aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2016-11-16 14:45:34 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-16 20:24:48 +0000
commitca79535dcb36ab3691eadc8664b687f4cd8a56b5 (patch)
treebb3f354cff997f717ed27025897f7973b3a340fc /src
parentcb677668519d117c51a7ca78375fee577f8f2aa9 (diff)
External SkImageGenerator API
Introduce an SkImageGenerator API to support the implementation of externally-managed image decode and scale caches. BUG=skia:5806 R=reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4720 Change-Id: Ibfe37af5471f78f28f88f9d5e80938882be1a344 Reviewed-on: https://skia-review.googlesource.com/4720 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Reed <reed@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkBitmapController.cpp31
-rw-r--r--src/core/SkBitmapProvider.cpp34
-rw-r--r--src/core/SkBitmapProvider.h4
-rw-r--r--src/core/SkDevice.cpp58
-rw-r--r--src/core/SkImageCacherator.cpp7
-rw-r--r--src/core/SkImageCacherator.h3
-rw-r--r--src/core/SkImageGenerator.cpp7
7 files changed, 143 insertions, 1 deletions
diff --git a/src/core/SkBitmapController.cpp b/src/core/SkBitmapController.cpp
index 4fee11db28..ed9903e7d3 100644
--- a/src/core/SkBitmapController.cpp
+++ b/src/core/SkBitmapController.cpp
@@ -48,6 +48,7 @@ private:
SkDestinationSurfaceColorMode fColorMode;
sk_sp<const SkMipMap> fCurrMip;
+ bool processExternalRequest(const SkBitmapProvider&);
bool processHQRequest(const SkBitmapProvider&);
bool processMediumRequest(const SkBitmapProvider&);
};
@@ -68,6 +69,28 @@ static inline bool cache_size_okay(const SkBitmapProvider& provider, const SkMat
}
/*
+ * Image generators can provide access to externally managed pixels
+ * (external scale/decode caches).
+ */
+bool SkDefaultBitmapControllerState::processExternalRequest(const SkBitmapProvider& provider) {
+ // TODO: actual srcRect
+
+ const SkRect src = SkRect::MakeIWH(provider.width(), provider.height());
+ SkRect adjustedSrc;
+
+ if (!provider.accessScaledImage(src, fInvMatrix, fQuality,
+ &fResultBitmap, &adjustedSrc, &fQuality)) {
+ return false;
+ }
+
+ fInvMatrix.postConcat(SkMatrix::MakeRectToRect(src, adjustedSrc, SkMatrix::kFill_ScaleToFit));
+ fResultBitmap.lockPixels();
+ SkASSERT(fResultBitmap.getPixels());
+
+ return true;
+}
+
+/*
* High quality is implemented by performing up-right scale-only filtering and then
* using bilerp for any remaining transformations.
*/
@@ -205,7 +228,13 @@ SkDefaultBitmapControllerState::SkDefaultBitmapControllerState(
fQuality = qual;
fColorMode = colorMode;
- if (this->processHQRequest(provider) || this->processMediumRequest(provider)) {
+ bool processed = this->processExternalRequest(provider);
+
+ // Externally handled requests are not guaranteed to reduce quality below kMedium -- so we
+ // always give our internal processors a shot.
+ processed |= this->processHQRequest(provider) || this->processMediumRequest(provider);
+
+ if (processed) {
SkASSERT(fResultBitmap.getPixels());
} else {
(void)provider.asBitmap(&fResultBitmap);
diff --git a/src/core/SkBitmapProvider.cpp b/src/core/SkBitmapProvider.cpp
index 8347d32d7f..11b1ac98d1 100644
--- a/src/core/SkBitmapProvider.cpp
+++ b/src/core/SkBitmapProvider.cpp
@@ -7,6 +7,7 @@
#include "SkBitmapProvider.h"
#include "SkImage_Base.h"
+#include "SkImageCacherator.h"
#include "SkPixelRef.h"
int SkBitmapProvider::width() const {
@@ -46,3 +47,36 @@ void SkBitmapProvider::notifyAddedToCache() const {
bool SkBitmapProvider::asBitmap(SkBitmap* bm) const {
return as_IB(fImage)->getROPixels(bm, SkImage::kAllow_CachingHint);
}
+
+bool SkBitmapProvider::accessScaledImage(const SkRect& srcRect,
+ const SkMatrix& invMatrix,
+ SkFilterQuality fq,
+ SkBitmap* scaledBitmap,
+ SkRect* adjustedSrcRect,
+ SkFilterQuality* adjustedFilterQuality) const {
+ if (!fImage) {
+ return false;
+ }
+
+ SkImageCacherator* cacherator = as_IB(fImage)->peekCacherator();
+ if (!cacherator) {
+ return false;
+ }
+
+ // TODO: stash the matrix someplace to avoid invert()?
+ SkMatrix m;
+ if (!invMatrix.invert(&m)) {
+ return false;
+ }
+
+ SkImageGenerator::ScaledImageRec rec;
+ if (!cacherator->directAccessScaledImage(srcRect, m, fq, &rec) ||
+ !rec.fImage->asLegacyBitmap(scaledBitmap, SkImage::kRO_LegacyBitmapMode)) {
+ return false;
+ }
+
+ *adjustedSrcRect = rec.fSrcRect;
+ *adjustedFilterQuality = rec.fQuality;
+
+ return true;
+}
diff --git a/src/core/SkBitmapProvider.h b/src/core/SkBitmapProvider.h
index 2e878b18ab..fd5b66219e 100644
--- a/src/core/SkBitmapProvider.h
+++ b/src/core/SkBitmapProvider.h
@@ -33,6 +33,10 @@ public:
// ... cause a decode and cache, or gpu-readback
bool asBitmap(SkBitmap*) const;
+ bool accessScaledImage(const SkRect& srcRect, const SkMatrix& invMatrix, SkFilterQuality fq,
+ SkBitmap* scaledBitmap, SkRect* adjustedSrcRect,
+ SkFilterQuality* adjustedFilterQuality) const;
+
private:
// Stack-allocated only.
void* operator new(size_t) = delete;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index b2ff2423ed..4caa8756cb 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -10,6 +10,7 @@
#include "SkDraw.h"
#include "SkDrawFilter.h"
#include "SkImage_Base.h"
+#include "SkImageCacherator.h"
#include "SkImageFilter.h"
#include "SkImageFilterCache.h"
#include "SkImagePriv.h"
@@ -24,6 +25,7 @@
#include "SkSpecialImage.h"
#include "SkTextBlobRunIterator.h"
#include "SkTextToPathIter.h"
+#include "SkTLazy.h"
SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfaceProps)
: fInfo(info)
@@ -177,9 +179,60 @@ void SkBaseDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSc
}
}
+bool SkBaseDevice::drawExternallyScaledImage(const SkDraw& draw,
+ const SkImage* image,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint& paint,
+ SkCanvas::SrcRectConstraint constraint) {
+ SkImageCacherator* cacherator = as_IB(image)->peekCacherator();
+ if (!cacherator) {
+ return false;
+ }
+
+ SkTLazy<SkRect> tmpSrc(src);
+ if (!tmpSrc.isValid()) {
+ tmpSrc.init(SkRect::Make(image->bounds()));
+ }
+
+ SkMatrix m = *draw.fMatrix;
+ m.preConcat(SkMatrix::MakeRectToRect(*tmpSrc.get(), dst, SkMatrix::kFill_ScaleToFit));
+
+ // constrain src to our bounds
+ if (!image->bounds().contains(*tmpSrc.get()) &&
+ !tmpSrc.get()->intersect(SkRect::Make(image->bounds()))) {
+ return false;
+ }
+
+ SkImageGenerator::ScaledImageRec rec;
+ if (!cacherator->directAccessScaledImage(*tmpSrc.get(), m, paint.getFilterQuality(), &rec)) {
+ return false;
+ }
+
+ SkBitmap bm;
+ if (!as_IB(rec.fImage)->getROPixels(&bm)) {
+ return false;
+ }
+
+ SkTCopyOnFirstWrite<SkPaint> adjustedPaint(paint);
+ if (rec.fQuality != paint.getFilterQuality()) {
+ adjustedPaint.writable()->setFilterQuality(rec.fQuality);
+ }
+
+ this->drawBitmapRect(draw, bm, &rec.fSrcRect, dst, *adjustedPaint, constraint);
+
+ return true;
+}
void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
const SkPaint& paint) {
// Default impl : turns everything into raster bitmap
+
+ if (this->drawExternallyScaledImage(draw, image, nullptr,
+ SkRect::Make(image->bounds()).makeOffset(x, y),
+ paint, SkCanvas::kFast_SrcRectConstraint)) {
+ return;
+ }
+
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm)) {
this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
@@ -190,6 +243,11 @@ void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const
const SkRect& dst, const SkPaint& paint,
SkCanvas::SrcRectConstraint constraint) {
// Default impl : turns everything into raster bitmap
+
+ if (this->drawExternallyScaledImage(draw, image, src, dst, paint, constraint)) {
+ return;
+ }
+
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm)) {
this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp
index 54045d5821..471dbd6d33 100644
--- a/src/core/SkImageCacherator.cpp
+++ b/src/core/SkImageCacherator.cpp
@@ -157,6 +157,13 @@ bool SkImageCacherator::directGeneratePixels(const SkImageInfo& info, void* pixe
return generator->getPixels(info, pixels, rb);
}
+bool SkImageCacherator::directAccessScaledImage(const SkRect& srcRect,
+ const SkMatrix& totalMatrix,
+ SkFilterQuality fq,
+ SkImageGenerator::ScaledImageRec* rec) {
+ return ScopedGenerator(fSharedGenerator)->accessScaledImage(srcRect, totalMatrix, fq, rec);
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////
bool SkImageCacherator::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap) {
diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h
index a8a05a1f90..0e8a953f37 100644
--- a/src/core/SkImageCacherator.h
+++ b/src/core/SkImageCacherator.h
@@ -69,6 +69,9 @@ public:
bool directGeneratePixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
int srcX, int srcY);
+ bool directAccessScaledImage(const SkRect& srcRect, const SkMatrix& totalMatrix,
+ SkFilterQuality, SkImageGenerator::ScaledImageRec*);
+
private:
// Ref-counted tuple(SkImageGenerator, SkMutex) which allows sharing of one generator
// among several cacherators.
diff --git a/src/core/SkImageGenerator.cpp b/src/core/SkImageGenerator.cpp
index ffa845b4db..5bb385e51b 100644
--- a/src/core/SkImageGenerator.cpp
+++ b/src/core/SkImageGenerator.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkImage.h"
#include "SkImageGenerator.h"
#include "SkNextID.h"
@@ -107,6 +108,12 @@ bool SkImageGenerator::generateScaledPixels(const SkISize& scaledSize,
return this->onGenerateScaledPixels(scaledSize, subsetOrigin, subsetPixels);
}
+bool SkImageGenerator::accessScaledImage(const SkRect& src, const SkMatrix& matrix,
+ SkFilterQuality fq, ScaledImageRec* rec) {
+ SkASSERT(fInfo.bounds().contains(src));
+ return this->onAccessScaledImage(src, matrix, fq, rec);
+}
+
/////////////////////////////////////////////////////////////////////////////////////////////
SkData* SkImageGenerator::onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM) {