Add SkSpecialImage::extractSubset & NewFromPixmap
authorrobertphillips <robertphillips@google.com>
Thu, 17 Mar 2016 13:58:39 +0000 (06:58 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 17 Mar 2016 13:58:39 +0000 (06:58 -0700)
This is calved off of: https://codereview.chromium.org/1785643003/ (Switch SkBlurImageFilter over to new onFilterImage interface)

This now relies on: https://codereview.chromium.org/1813483002/ (ImagePixelLocker now manually allocates SkPixmap) to clean up the uses of SkAutoPixmapStorage in Chromium

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1787883002

Committed: https://skia.googlesource.com/skia/+/250581493a0859987e482810879e85e5ac2dc002

Review URL: https://codereview.chromium.org/1787883002

19 files changed:
bench/CoverageBench.cpp
bench/PDFBench.cpp
gm/image.cpp
gyp/core.gypi
include/core/SkPixmap.h
src/core/SkAutoPixmapStorage.cpp [new file with mode: 0644]
src/core/SkAutoPixmapStorage.h [new file with mode: 0644]
src/core/SkPixmap.cpp
src/core/SkScalerContext.cpp
src/core/SkSpecialImage.cpp
src/core/SkSpecialImage.h
src/gpu/GrSWMaskHelper.h
src/image/SkImage_Gpu.cpp
tests/DeviceLooperTest.cpp
tests/Float16Test.cpp
tests/ImageTest.cpp
tests/SpecialImageTest.cpp
tests/TestingSpecialImageAccess.h
tests/TextureCompressionTest.cpp

index 3dee66836f190863be4192b2eb9e72b7e3dfd520..ebde4208a01ca4b127e7945a42c9572c04b0ad48 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "Benchmark.h"
+#include "SkAutoPixmapStorage.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkColorPriv.h"
index b7f48daac8a2dfa4b8ed115dd92b432504bda04b..ba25e44f37d2c80a6964f4302b4d6e4138528c1a 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "Benchmark.h"
 #include "Resources.h"
+#include "SkAutoPixmapStorage.h"
 #include "SkData.h"
 #include "SkImage.h"
 #include "SkPDFBitmap.h"
index 2ddda8f8a42935c533bc971181b73a5bc76c1d8e..4e22dd0ff52487a66250d2b6864fe2bb1a469d32 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <functional>
 #include "gm.h"
+#include "SkAutoPixmapStorage.h"
 #include "SkData.h"
 #include "SkCanvas.h"
 #include "SkRandom.h"
index 15af4649a12644f53b213c45ac46ea57d8c6b9d0..b9ee244a5fc6e4f0e87a0c815d71f4164ed58fca 100644 (file)
@@ -23,6 +23,8 @@
         '<(skia_src_path)/core/SkAlphaRuns.cpp',
         '<(skia_src_path)/core/SkAntiRun.h',
         '<(skia_src_path)/core/SkAutoKern.h',
+        '<(skia_src_path)/core/SkAutoPixmapStorage.h',
+        '<(skia_src_path)/core/SkAutoPixmapStorage.cpp',
         '<(skia_src_path)/core/SkBBHFactory.cpp',
         '<(skia_src_path)/core/SkBBoxHierarchy.h',
         '<(skia_src_path)/core/SkBigPicture.cpp',
index b43072b9579687a3b658ae455caee79536adac38..3a7abdf13451f712f4e47f10a81d44c713d4f8ce 100644 (file)
@@ -187,71 +187,6 @@ private:
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 
-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();
-
-    // 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;
-};
-
 /////////////////////////////////////////////////////////////////////////////////////////////
 
 class SK_API SkAutoPixmapUnlock : ::SkNoncopyable {
diff --git a/src/core/SkAutoPixmapStorage.cpp b/src/core/SkAutoPixmapStorage.cpp
new file mode 100644 (file)
index 0000000..3be28a9
--- /dev/null
@@ -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 (file)
index 0000000..4379b13
--- /dev/null
@@ -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
index f7672d082f0e3ca99024bf1a99c6d5b449875efb..aa1d213bf60cd46406bc39807ab1810f205ef239 100644 (file)
@@ -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();
-}
index a479c3782ffc3a36b5701395d24321867536c28f..5e125f30082e3bd1c3743aeb129e20be5ea04d90 100644 (file)
@@ -8,6 +8,7 @@
 
 
 #include "SkScalerContext.h"
+#include "SkAutoPixmapStorage.h"
 #include "SkColorPriv.h"
 #include "SkDescriptor.h"
 #include "SkDraw.h"
index a55fe650293e0216b8ddc4167e4864fdcfb7f55a..b17d5d4147d998d85016a1f2d50c6bbb63ac91e7 100644 (file)
@@ -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;
index e90de097fb8d185275c13dd6fcf9a6d5656dd5ae..b1b6a28d6a846ee046092b376ab6b24fd08a5cc8 100644 (file)
@@ -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;
index b90205b1a1e93afbb882c51d5c698d93255bb309..fb5d9e86aa5b92377587884843bd370ce0111d0d 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef GrSWMaskHelper_DEFINED
 #define GrSWMaskHelper_DEFINED
 
+#include "SkAutoPixmapStorage.h"
 #include "GrColor.h"
 #include "GrPipelineBuilder.h"
 #include "SkBitmap.h"
index cde4232d36c7a6e2ad8a9e3527faf878b036165d..5e687b751af60131bc83cda075b7c830a124f815 100644 (file)
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkAutoPixmapStorage.h"
 #include "GrCaps.h"
 #include "GrContext.h"
 #include "GrDrawContext.h"
index 1a51b5898038e7cb6e3cd1dfd58040188c0c4f91..c8eb3c7b7587c724c4993c4d8ae21ea683ac2e67 100644 (file)
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkAutoPixmapStorage.h"
 #include "SkDeviceLooper.h"
 #include "SkRasterClip.h"
 #include "Test.h"
index ef349c6cb6c0fd40f1409828d6a88c44d9660d9e..6a7f9842f4e7e3ea630ab2c992c52013ef488e43 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "Test.h"
+#include "SkAutoPixmapStorage.h"
 #include "SkColor.h"
 #include "SkHalf.h"
 #include "SkOpts.h"
index 3c2c31cca9f600a0a44fa1e73ece97a447502429..da9268dded166a514e1d349b8b8209abe8fca1eb 100644 (file)
@@ -9,6 +9,7 @@
 #include <initializer_list>
 #include "DMGpuSupport.h"
 
+#include "SkAutoPixmapStorage.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkData.h"
index 9bde7eec3348546474bbbc377cbfbc87139a099f..7511e6297123a82b6d78ccfadf3ba4f670e5072c 100644 (file)
@@ -5,9 +5,11 @@
  * found in the LICENSE file
  */
 
+#include "SkAutoPixmapStorage.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkImage.h"
+#include "SkPixmap.h"
 #include "SkSpecialImage.h"
 #include "SkSpecialSurface.h"
 #include "Test.h"
@@ -48,10 +50,11 @@ static SkBitmap create_bm() {
 
 // Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
 static void test_image(SkSpecialImage* img, skiatest::Reporter* reporter,
-                       bool peekPixelsSucceeds, bool peekTextureSucceeds) {
+                       bool peekPixelsSucceeds, bool peekTextureSucceeds,
+                       int offset, int size) {
     const SkIRect subset = TestingSpecialImageAccess::Subset(img);
-    REPORTER_ASSERT(reporter, kPad == subset.left());
-    REPORTER_ASSERT(reporter, kPad == subset.top());
+    REPORTER_ASSERT(reporter, offset == subset.left());
+    REPORTER_ASSERT(reporter, offset == subset.top());
     REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
     REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
 
@@ -63,8 +66,8 @@ static void test_image(SkSpecialImage* img, skiatest::Reporter* reporter,
     REPORTER_ASSERT(reporter, peekPixelsSucceeds ==
                               !!TestingSpecialImageAccess::PeekPixels(img, &pixmap));
     if (peekPixelsSucceeds) {
-        REPORTER_ASSERT(reporter, kFullSize == pixmap.width());
-        REPORTER_ASSERT(reporter, kFullSize == pixmap.height());
+        REPORTER_ASSERT(reporter, size == pixmap.width());
+        REPORTER_ASSERT(reporter, size == pixmap.height());
     }
 
     //--------------
@@ -95,10 +98,22 @@ static void test_image(SkSpecialImage* img, skiatest::Reporter* reporter,
 DEF_TEST(SpecialImage_Raster, reporter) {
     SkBitmap bm = create_bm();
 
+    SkAutoTUnref<SkSpecialImage> fullSImage(SkSpecialImage::NewFromRaster(
+                                                            nullptr,
+                                                            SkIRect::MakeWH(kFullSize, kFullSize),
+                                                            bm));
+
     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
 
-    SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromRaster(nullptr, subset, bm));
-    test_image(img, reporter, true, false);
+    {
+        SkAutoTUnref<SkSpecialImage> subSImg1(SkSpecialImage::NewFromRaster(nullptr, subset, bm));
+        test_image(subSImg1, reporter, true, false, kPad, kFullSize);
+    }
+
+    {
+        SkAutoTUnref<SkSpecialImage> subSImg2(fullSImage->extractSubset(subset));
+        test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
+    }
 }
 
 DEF_TEST(SpecialImage_Image, reporter) {
@@ -106,12 +121,56 @@ DEF_TEST(SpecialImage_Image, reporter) {
 
     SkAutoTUnref<SkImage> fullImage(SkImage::NewFromBitmap(bm));
 
+    SkAutoTUnref<SkSpecialImage> fullSImage(SkSpecialImage::NewFromImage(
+                                                            nullptr,
+                                                            SkIRect::MakeWH(kFullSize, kFullSize),
+                                                            fullImage));
+
     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
 
-    SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromImage(nullptr, subset, fullImage));
-    test_image(img, reporter, true, false);
+    {
+        SkAutoTUnref<SkSpecialImage> subSImg1(SkSpecialImage::NewFromImage(nullptr,
+                                                                           subset,
+                                                                           fullImage));
+        test_image(subSImg1, reporter, true, false, kPad, kFullSize);
+    }
+
+    {
+        SkAutoTUnref<SkSpecialImage> subSImg2(fullSImage->extractSubset(subset));
+        test_image(subSImg2, reporter, true, false, 0, kSmallerSize);
+    }
 }
 
+DEF_TEST(SpecialImage_Pixmap, reporter) {
+    SkAutoPixmapStorage pixmap;
+
+    const SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
+    pixmap.alloc(info);
+    pixmap.erase(SK_ColorGREEN);
+
+    const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
+
+    pixmap.erase(SK_ColorRED, subset);
+
+    {
+        // The SkAutoPixmapStorage keeps hold of the memory
+        SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromPixmap(nullptr, subset, pixmap,
+                                                                       nullptr, nullptr));
+        test_image(img, reporter, true, false, kPad, kFullSize);
+    }
+
+    {
+        // The image takes ownership of the memory
+        SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromPixmap(
+                                               nullptr, subset, pixmap,
+                                               [] (void* addr, void*) -> void { sk_free(addr); },
+                                               nullptr));
+        pixmap.release();
+        test_image(img, reporter, true, false, kPad, kFullSize);
+    }
+}
+
+
 #if SK_SUPPORT_GPU
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) {
     SkBitmap bm = create_bm();
@@ -128,12 +187,26 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu, reporter, context) {
         return;
     }
 
+    SkAutoTUnref<SkSpecialImage> fullSImg(SkSpecialImage::NewFromGpu(
+                                                            nullptr,
+                                                            SkIRect::MakeWH(kFullSize, kFullSize),
+                                                            kNeedNewImageUniqueID_SpecialImage,
+                                                            texture));
+
     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
 
-    SkAutoTUnref<SkSpecialImage> img(SkSpecialImage::NewFromGpu(nullptr, subset, 
-                                                                kNeedNewImageUniqueID_SpecialImage,
-                                                                texture));
-    test_image(img, reporter, false, true);
+    {
+        SkAutoTUnref<SkSpecialImage> subSImg1(SkSpecialImage::NewFromGpu(
+                                                               nullptr, subset, 
+                                                               kNeedNewImageUniqueID_SpecialImage,
+                                                               texture));
+        test_image(subSImg1, reporter, false, true, kPad, kFullSize);
+    }
+
+    {
+        SkAutoTUnref<SkSpecialImage> subSImg2(fullSImg->extractSubset(subset));
+        test_image(subSImg2, reporter, false, true, kPad, kFullSize);
+    }
 }
 
 #endif
index cd9d77c7ff06fe0d3f031c4d82e0a45381ecc8fb..8dd4e9bb50c0a9edf661f2b745d058fd721cf601 100644 (file)
@@ -15,7 +15,7 @@ public:
     }
 
     static bool PeekPixels(const SkSpecialImage* img, SkPixmap* pixmap) {
-        return img->testingOnlyPeekPixels(pixmap);
+        return img->peekPixels(pixmap);
     }
 
     static GrTexture* PeekTexture(const SkSpecialImage* img) {
index 18afebeff2c39175724a0ee5c492448a17b2ffdb..09086605a5ad234e291be8741f8275ffc6ca268f 100644 (file)
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkAutoPixmapStorage.h"
 #include "SkBitmap.h"
 #include "SkData.h"
 #include "SkEndian.h"