diff options
author | robertphillips <robertphillips@google.com> | 2016-03-16 09:47:08 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-16 09:47:08 -0700 |
commit | 250581493a0859987e482810879e85e5ac2dc002 (patch) | |
tree | 2a9432c347327c16d35a15f6a6b8b53b7704aef3 /src | |
parent | b3b6beae044ca457edf99cf223cd6379a49d4ef0 (diff) |
Add SkSpecialImage::extractSubset & NewFromPixmap
This is calved off of: https://codereview.chromium.org/1785643003/ (Switch SkBlurImageFilter over to new onFilterImage interface)
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1787883002
Review URL: https://codereview.chromium.org/1787883002
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkAutoPixmapStorage.cpp | 64 | ||||
-rw-r--r-- | src/core/SkAutoPixmapStorage.h | 87 | ||||
-rw-r--r-- | src/core/SkPixmap.cpp | 48 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 1 | ||||
-rw-r--r-- | src/core/SkSpecialImage.cpp | 87 | ||||
-rw-r--r-- | src/core/SkSpecialImage.h | 39 | ||||
-rw-r--r-- | src/gpu/GrSWMaskHelper.h | 1 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 1 |
8 files changed, 250 insertions, 78 deletions
diff --git a/src/core/SkAutoPixmapStorage.cpp b/src/core/SkAutoPixmapStorage.cpp new file mode 100644 index 0000000000..3be28a94c4 --- /dev/null +++ b/src/core/SkAutoPixmapStorage.cpp @@ -0,0 +1,64 @@ + +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkAutoPixmapStorage.h" +#include "SkData.h" + +SkAutoPixmapStorage::SkAutoPixmapStorage() : fStorage(nullptr) {} + +SkAutoPixmapStorage::~SkAutoPixmapStorage() { + this->freeStorage(); +} + +size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) { + size_t rb = info.minRowBytes(); + if (rowBytes) { + *rowBytes = rb; + } + return info.getSafeSize(rb); +} + +bool SkAutoPixmapStorage::tryAlloc(const SkImageInfo& info) { + this->freeStorage(); + + size_t rb; + size_t size = AllocSize(info, &rb); + if (0 == size) { + return false; + } + void* pixels = sk_malloc_flags(size, 0); + if (nullptr == pixels) { + return false; + } + this->reset(info, pixels, rb); + fStorage = pixels; + return true; +} + +void SkAutoPixmapStorage::alloc(const SkImageInfo& info) { + if (!this->tryAlloc(info)) { + sk_throw(); + } +} + +const SkData* SkAutoPixmapStorage::detachPixelsAsData() { + if (!fStorage) { + return nullptr; + } + + auto data = SkData::MakeFromMalloc(fStorage, this->getSafeSize()); + fStorage = nullptr; + this->INHERITED::reset(); + + return data.release(); +} + +void SkAutoPixmapStorage::release() { + fStorage = nullptr; + this->INHERITED::reset(); +} diff --git a/src/core/SkAutoPixmapStorage.h b/src/core/SkAutoPixmapStorage.h new file mode 100644 index 0000000000..4379b13d24 --- /dev/null +++ b/src/core/SkAutoPixmapStorage.h @@ -0,0 +1,87 @@ + +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkAutoPixmapStorage_DEFINED +#define SkAutoPixmapStorage_DEFINED + +#include "SkPixmap.h" + +class SK_API SkAutoPixmapStorage : public SkPixmap { +public: + SkAutoPixmapStorage(); + ~SkAutoPixmapStorage(); + + /** + * Try to allocate memory for the pixels needed to match the specified Info. On success + * return true and fill out the pixmap to point to that memory. The storage will be freed + * when this object is destroyed, or if another call to tryAlloc() or alloc() is made. + * + * On failure, return false and reset() the pixmap to empty. + */ + bool tryAlloc(const SkImageInfo&); + + /** + * Allocate memory for the pixels needed to match the specified Info and fill out the pixmap + * to point to that memory. The storage will be freed when this object is destroyed, + * or if another call to tryAlloc() or alloc() is made. + * + * If the memory cannot be allocated, calls sk_throw(). + */ + void alloc(const SkImageInfo&); + + /** + * Gets the size and optionally the rowBytes that would be allocated by SkAutoPixmapStorage if + * alloc/tryAlloc was called. + */ + static size_t AllocSize(const SkImageInfo& info, size_t* rowBytes); + + /** + * Returns an SkData object wrapping the allocated pixels memory, and resets the pixmap. + * If the storage hasn't been allocated, the result is NULL. + */ + const SkData* SK_WARN_UNUSED_RESULT detachPixelsAsData(); + + /** + * Whereas 'reset' frees the backing memory and then clears the SkPixmap, + * this entry point disowns the backing memory before clearing so the memory + * isn't freed. It can be used when the Pixmap has been installed into + * an SkBitmap and the SkBitmap should manage the memory's lifetime. + */ + void release(); + + // We wrap these so we can clear our internal storage + + void reset() { + this->freeStorage(); + this->INHERITED::reset(); + } + void reset(const SkImageInfo& info, const void* addr, size_t rb, SkColorTable* ctable = NULL) { + this->freeStorage(); + this->INHERITED::reset(info, addr, rb, ctable); + } + void reset(const SkImageInfo& info) { + this->freeStorage(); + this->INHERITED::reset(info); + } + bool SK_WARN_UNUSED_RESULT reset(const SkMask& mask) { + this->freeStorage(); + return this->INHERITED::reset(mask); + } + +private: + void* fStorage; + + void freeStorage() { + sk_free(fStorage); + fStorage = nullptr; + } + + typedef SkPixmap INHERITED; +}; + +#endif diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index f7672d082f..aa1d213bf6 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -281,51 +281,3 @@ bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { ////////////////////////////////////////////////////////////////////////////////////////////////// -SkAutoPixmapStorage::SkAutoPixmapStorage() : fStorage(nullptr) {} - -SkAutoPixmapStorage::~SkAutoPixmapStorage() { - this->freeStorage(); -} - -size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) { - size_t rb = info.minRowBytes(); - if (rowBytes) { - *rowBytes = rb; - } - return info.getSafeSize(rb); -} - -bool SkAutoPixmapStorage::tryAlloc(const SkImageInfo& info) { - this->freeStorage(); - - size_t rb; - size_t size = AllocSize(info, &rb); - if (0 == size) { - return false; - } - void* pixels = sk_malloc_flags(size, 0); - if (nullptr == pixels) { - return false; - } - this->reset(info, pixels, rb); - fStorage = pixels; - return true; -} - -void SkAutoPixmapStorage::alloc(const SkImageInfo& info) { - if (!this->tryAlloc(info)) { - sk_throw(); - } -} - -const SkData* SkAutoPixmapStorage::detachPixelsAsData() { - if (!fStorage) { - return nullptr; - } - - auto data = SkData::MakeFromMalloc(fStorage, this->getSafeSize()); - fStorage = nullptr; - this->INHERITED::reset(); - - return data.release(); -} diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index a479c3782f..5e125f3008 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -8,6 +8,7 @@ #include "SkScalerContext.h" +#include "SkAutoPixmapStorage.h" #include "SkColorPriv.h" #include "SkDescriptor.h" #include "SkDraw.h" diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index a55fe65029..b17d5d4147 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -20,7 +20,7 @@ public: virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0; - virtual bool testingOnlyOnPeekPixels(SkPixmap*) const { return false; } + virtual bool onPeekPixels(SkPixmap*) const { return false; } virtual GrTexture* onPeekTexture() const { return nullptr; } @@ -29,7 +29,9 @@ public: // Delete this entry point ASAP (see skbug.com/4965) virtual bool getBitmapDeprecated(SkBitmap* result) const = 0; - virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; } + virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const = 0; + + virtual SkSpecialImage* onExtractSubset(const SkIRect& subset) const = 0; private: typedef SkSpecialImage INHERITED; @@ -44,8 +46,8 @@ void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPain return as_SIB(this)->onDraw(canvas, x, y, paint); } -bool SkSpecialImage::testingOnlyPeekPixels(SkPixmap* pixmap) const { - return as_SIB(this)->testingOnlyOnPeekPixels(pixmap); +bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const { + return as_SIB(this)->onPeekPixels(pixmap); } GrTexture* SkSpecialImage::peekTexture() const { @@ -60,6 +62,10 @@ SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const { return as_SIB(this)->onNewSurface(info); } +SkSpecialImage* SkSpecialImage::extractSubset(const SkIRect& subset) const { + return as_SIB(this)->onExtractSubset(subset); +} + #if SK_SUPPORT_GPU #include "SkGr.h" #include "SkGrPixelRef.h" @@ -85,8 +91,7 @@ bool SkSpecialImage::internal_getBM(SkBitmap* result) { return ib->getBitmapDeprecated(result); } -SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() { - SkASSERT(fProxy); +SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const { return fProxy; } @@ -129,7 +134,7 @@ public: dst, paint, SkCanvas::kStrict_SrcRectConstraint); } - bool testingOnlyOnPeekPixels(SkPixmap* pixmap) const override { + bool onPeekPixels(SkPixmap* pixmap) const override { return fImage->peekPixels(pixmap); } @@ -170,6 +175,17 @@ public: return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr); } + SkSpecialImage* onExtractSubset(const SkIRect& subset) const override { + SkAutoTUnref<SkImage> subsetImg(fImage->newSubset(subset)); + if (!subsetImg) { + return nullptr; + } + + return SkSpecialImage::NewFromImage(this->internal_getProxy(), + SkIRect::MakeWH(subset.width(), subset.height()), + subsetImg); + } + private: SkAutoTUnref<const SkImage> fImage; @@ -214,6 +230,17 @@ public: } } + SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, + const SkIRect& subset, + const SkPixmap& pixmap, + void (*releaseProc)(void* addr, void* context), + void* context) + : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) { + fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(), + pixmap.rowBytes(), pixmap.ctable(), + releaseProc, context); + } + ~SkSpecialImage_Raster() override { } bool isOpaque() const override { return fBitmap.isOpaque(); } @@ -228,19 +255,13 @@ public: dst, paint, SkCanvas::kStrict_SrcRectConstraint); } - bool testingOnlyOnPeekPixels(SkPixmap* pixmap) const override { + bool onPeekPixels(SkPixmap* pixmap) const override { const SkImageInfo info = fBitmap.info(); if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) { return false; } - const void* pixels = fBitmap.getPixels(); - if (pixels) { - if (pixmap) { - pixmap->reset(info, pixels, fBitmap.rowBytes()); - } - return true; - } - return false; + + return fBitmap.peekPixels(pixmap); } bool getBitmapDeprecated(SkBitmap* result) const override { @@ -257,6 +278,18 @@ public: return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr); } + SkSpecialImage* onExtractSubset(const SkIRect& subset) const override { + SkBitmap subsetBM; + + if (!fBitmap.extractSubset(&subsetBM, subset)) { + return nullptr; + } + + return SkSpecialImage::NewFromRaster(this->internal_getProxy(), + SkIRect::MakeWH(subset.width(), subset.height()), + subsetBM); + } + private: SkBitmap fBitmap; @@ -271,6 +304,15 @@ SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy, return new SkSpecialImage_Raster(proxy, subset, bm); } +SkSpecialImage* SkSpecialImage::NewFromPixmap(SkImageFilter::Proxy* proxy, + const SkIRect& subset, + const SkPixmap& src, + void (*releaseProc)(void* addr, void* context), + void* context) { + return new SkSpecialImage_Raster(proxy, subset, src, releaseProc, context); +} + + #if SK_SUPPORT_GPU /////////////////////////////////////////////////////////////////////////////// #include "GrTexture.h" @@ -315,7 +357,10 @@ public: return false; } - result->setPixelRef(new SkGrPixelRef(info, fTexture))->unref(); + const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height()); + + SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture)); + result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop); return true; } @@ -345,6 +390,14 @@ public: return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc); } + SkSpecialImage* onExtractSubset(const SkIRect& subset) const override { + return SkSpecialImage::NewFromGpu(this->internal_getProxy(), + subset, + this->uniqueID(), + fTexture, + fAlphaType); + } + private: SkAutoTUnref<GrTexture> fTexture; const SkAlphaType fAlphaType; diff --git a/src/core/SkSpecialImage.h b/src/core/SkSpecialImage.h index e90de097fb..b1b6a28d6a 100644 --- a/src/core/SkSpecialImage.h +++ b/src/core/SkSpecialImage.h @@ -63,16 +63,27 @@ public: uint32_t uniqueID, GrTexture*, SkAlphaType at = kPremul_SkAlphaType); + static SkSpecialImage* NewFromPixmap(SkImageFilter::Proxy*, + const SkIRect& subset, + const SkPixmap&, + void (*releaseProc)(void* addr, void* context), + void* context); /** * Create a new surface with a backend that is compatible with this image. */ SkSpecialSurface* newSurface(const SkImageInfo&) const; + /** + * Extract a subset of this special image and return it as a special image. + * It may or may not point to the same backing memory. + */ + SkSpecialImage* extractSubset(const SkIRect& subset) const; + // These three internal methods will go away (see skbug.com/4965) bool internal_getBM(SkBitmap* result); static SkSpecialImage* internal_fromBM(SkImageFilter::Proxy*, const SkBitmap&); - SkImageFilter::Proxy* internal_getProxy(); + SkImageFilter::Proxy* internal_getProxy() const; // TODO: hide this when GrLayerHoister uses SkSpecialImages more fully (see skbug.com/5063) /** @@ -81,6 +92,20 @@ public: */ GrTexture* peekTexture() const; + // TODO: hide this whe the imagefilter all have a consistent draw path (see skbug.com/5063) + /** + * If the SpecialImage is backed by cpu pixels, return the const address + * of those pixels and, if not null, the ImageInfo, rowBytes, and, if present, + * the color table. The returned address(es) is/are only valid while the image object + * is in scope. + * + * The returned ImageInfo represents the backing memory. Use 'subset' + * to get the active portion's dimensions. + * + * On failure, return false and ignore the pixmap parameter. + */ + bool peekPixels(SkPixmap*) const; + protected: SkSpecialImage(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID) : fSubset(subset) @@ -93,18 +118,6 @@ protected: friend class TestingSpecialImageAccess; friend class TestingSpecialSurfaceAccess; - /** - * If the SpecialImage is backed by cpu pixels, return the const address - * of those pixels and, if not null, return the ImageInfo and rowBytes. - * The returned address is only valid while the image object is in scope. - * - * The returned ImageInfo represents the backing memory. Use 'subset' - * to get the active portion's dimensions. - * - * On failure, return false and ignore the pixmap parameter. - */ - bool testingOnlyPeekPixels(SkPixmap*) const; - // This entry point is for testing only. It does a readback from VRAM for // GPU-backed special images. bool testingOnlyGetROPixels(SkBitmap*) const; diff --git a/src/gpu/GrSWMaskHelper.h b/src/gpu/GrSWMaskHelper.h index b90205b1a1..fb5d9e86aa 100644 --- a/src/gpu/GrSWMaskHelper.h +++ b/src/gpu/GrSWMaskHelper.h @@ -8,6 +8,7 @@ #ifndef GrSWMaskHelper_DEFINED #define GrSWMaskHelper_DEFINED +#include "SkAutoPixmapStorage.h" #include "GrColor.h" #include "GrPipelineBuilder.h" #include "SkBitmap.h" diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index cde4232d36..5e687b751a 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkAutoPixmapStorage.h" #include "GrCaps.h" #include "GrContext.h" #include "GrDrawContext.h" |