Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file
      6  */
      7 
      8 #include "SkCanvas.h"
      9 #include "SkSpecialImage.h"
     10 #include "SkSpecialSurface.h"
     11 
     12 ///////////////////////////////////////////////////////////////////////////////
     13 class SkSpecialImage_Base : public SkSpecialImage {
     14 public:
     15     SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID)
     16         : INHERITED(proxy, subset, uniqueID) {
     17     }
     18     virtual ~SkSpecialImage_Base() { }
     19 
     20     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
     21 
     22     virtual bool onPeekPixels(SkPixmap*) const { return false; }
     23 
     24     virtual GrTexture* onPeekTexture() const { return nullptr; }
     25 
     26     // Delete this entry point ASAP (see skbug.com/4965)
     27     virtual bool getBitmap(SkBitmap* result) const = 0;
     28 
     29     virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; }
     30 
     31 private:
     32     typedef SkSpecialImage INHERITED;
     33 };
     34 
     35 ///////////////////////////////////////////////////////////////////////////////
     36 static inline const SkSpecialImage_Base* as_IB(const SkSpecialImage* image) {
     37     return static_cast<const SkSpecialImage_Base*>(image);
     38 }
     39 
     40 void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
     41     return as_IB(this)->onDraw(canvas, x, y, paint);
     42 }
     43 
     44 bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
     45     return as_IB(this)->onPeekPixels(pixmap);
     46 }
     47 
     48 GrTexture* SkSpecialImage::peekTexture() const {
     49     return as_IB(this)->onPeekTexture();
     50 }
     51 
     52 SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const {
     53     return as_IB(this)->onNewSurface(info);
     54 }
     55 
     56 #if SK_SUPPORT_GPU
     57 #include "SkGr.h"
     58 #include "SkGrPixelRef.h"
     59 #endif
     60 
     61 SkSpecialImage* SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy,
     62                                                 const SkBitmap& src) {
     63     // Need to test offset case! (see skbug.com/4967)
     64     if (src.getTexture()) {
     65         return SkSpecialImage::NewFromGpu(proxy,
     66                                           src.bounds(),
     67                                           src.getGenerationID(),
     68                                           src.getTexture());
     69     }
     70 
     71     return SkSpecialImage::NewFromRaster(proxy, src.bounds(), src);
     72 }
     73 
     74 bool SkSpecialImage::internal_getBM(SkBitmap* result) {
     75     const SkSpecialImage_Base* ib = as_IB(this);
     76 
     77     // TODO: need to test offset case! (see skbug.com/4967)
     78     return ib->getBitmap(result);
     79 }
     80 
     81 SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() {
     82     SkASSERT(fProxy);
     83     return fProxy;
     84 }
     85 
     86 ///////////////////////////////////////////////////////////////////////////////
     87 #include "SkImage.h"
     88 #if SK_SUPPORT_GPU
     89 #include "SkGrPriv.h"
     90 #endif
     91 
     92 class SkSpecialImage_Image : public SkSpecialImage_Base {
     93 public:
     94     SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkImage* image)
     95         : INHERITED(proxy, subset, image->uniqueID())
     96         , fImage(SkRef(image)) {
     97     }
     98 
     99     ~SkSpecialImage_Image() override { }
    100 
    101     bool isOpaque() const override { return fImage->isOpaque(); }
    102 
    103     size_t getSize() const override {
    104 #if SK_SUPPORT_GPU
    105         if (fImage->getTexture()) {
    106             return fImage->getTexture()->gpuMemorySize();
    107         } else
    108 #endif
    109         {
    110             SkImageInfo info;
    111             size_t rowBytes;
    112 
    113             if (fImage->peekPixels(&info, &rowBytes)) {
    114                 return info.height() * rowBytes;
    115             }
    116         }
    117         return 0;
    118     }
    119 
    120     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
    121         SkRect dst = SkRect::MakeXYWH(x, y, this->subset().width(), this->subset().height());
    122 
    123         canvas->drawImageRect(fImage, this->subset(),
    124                               dst, paint, SkCanvas::kStrict_SrcRectConstraint);
    125     }
    126 
    127     bool onPeekPixels(SkPixmap* pixmap) const override {
    128         return fImage->peekPixels(pixmap);
    129     }
    130 
    131     GrTexture* onPeekTexture() const override { return fImage->getTexture(); }
    132 
    133     bool getBitmap(SkBitmap* result) const override {
    134         return false;
    135     }
    136 
    137     SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
    138 #if SK_SUPPORT_GPU
    139         GrTexture* texture = fImage->getTexture();
    140         if (texture) {
    141             GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
    142             desc.fFlags = kRenderTarget_GrSurfaceFlag;
    143 
    144             return SkSpecialSurface::NewRenderTarget(this->proxy(), texture->getContext(), desc);
    145         }
    146 #endif
    147         return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
    148     }
    149 
    150 private:
    151     SkAutoTUnref<const SkImage> fImage;
    152 
    153     typedef SkSpecialImage_Base INHERITED;
    154 };
    155 
    156 #ifdef SK_DEBUG
    157 static bool rect_fits(const SkIRect& rect, int width, int height) {
    158     return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
    159            rect.fRight >= 0 && rect.fRight <= width &&
    160            rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
    161            rect.fBottom >= 0 && rect.fBottom <= height;
    162 }
    163 #endif
    164 
    165 SkSpecialImage* SkSpecialImage::NewFromImage(const SkIRect& subset, const SkImage* image) {
    166     SkASSERT(rect_fits(subset, image->width(), image->height()));
    167     return new SkSpecialImage_Image(nullptr, subset, image);
    168 }
    169 
    170 ///////////////////////////////////////////////////////////////////////////////
    171 #include "SkBitmap.h"
    172 #include "SkImageInfo.h"
    173 #include "SkPixelRef.h"
    174 
    175 class SkSpecialImage_Raster : public SkSpecialImage_Base {
    176 public:
    177     SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm)
    178         : INHERITED(proxy, subset, bm.getGenerationID())
    179         , fBitmap(bm) {
    180         if (bm.pixelRef()->isPreLocked()) {
    181             // we only preemptively lock if there is no chance of triggering something expensive
    182             // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already.
    183             fBitmap.lockPixels();
    184         }
    185     }
    186 
    187     ~SkSpecialImage_Raster() override { }
    188 
    189     bool isOpaque() const override { return fBitmap.isOpaque(); }
    190 
    191     size_t getSize() const override { return fBitmap.getSize(); }
    192 
    193     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
    194         SkRect dst = SkRect::MakeXYWH(x, y,
    195                                       this->subset().width(), this->subset().height());
    196 
    197         canvas->drawBitmapRect(fBitmap, this->subset(),
    198                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
    199     }
    200 
    201     bool onPeekPixels(SkPixmap* pixmap) const override {
    202         const SkImageInfo info = fBitmap.info();
    203         if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
    204             return false;
    205         }
    206         const void* pixels = fBitmap.getPixels();
    207         if (pixels) {
    208             if (pixmap) {
    209                 pixmap->reset(info, pixels, fBitmap.rowBytes());
    210             }
    211             return true;
    212         }
    213         return false;
    214     }
    215 
    216     bool getBitmap(SkBitmap* result) const override {
    217         *result = fBitmap;
    218         return true;
    219     }
    220 
    221     SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
    222         return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
    223     }
    224 
    225 private:
    226     SkBitmap fBitmap;
    227 
    228     typedef SkSpecialImage_Base INHERITED;
    229 };
    230 
    231 SkSpecialImage* SkSpecialImage::NewFromRaster(SkImageFilter::Proxy* proxy,
    232                                               const SkIRect& subset,
    233                                               const SkBitmap& bm) {
    234     SkASSERT(nullptr == bm.getTexture());
    235     SkASSERT(rect_fits(subset, bm.width(), bm.height()));
    236     return new SkSpecialImage_Raster(proxy, subset, bm);
    237 }
    238 
    239 #if SK_SUPPORT_GPU
    240 ///////////////////////////////////////////////////////////////////////////////
    241 #include "GrTexture.h"
    242 
    243 class SkSpecialImage_Gpu : public SkSpecialImage_Base {
    244 public:
    245     SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset,
    246                        uint32_t uniqueID, GrTexture* tex, SkAlphaType at)
    247         : INHERITED(proxy, subset, uniqueID)
    248         , fTexture(SkRef(tex))
    249         , fAlphaType(at) {
    250     }
    251 
    252     ~SkSpecialImage_Gpu() override { }
    253 
    254     bool isOpaque() const override {
    255         return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
    256     }
    257 
    258     size_t getSize() const override { return fTexture->gpuMemorySize(); }
    259 
    260     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
    261         SkRect dst = SkRect::MakeXYWH(x, y,
    262                                       this->subset().width(), this->subset().height());
    263 
    264         SkBitmap bm;
    265 
    266         GrWrapTextureInBitmap(fTexture,
    267                               fTexture->width(), fTexture->height(), this->isOpaque(), &bm);
    268 
    269         canvas->drawBitmapRect(bm, this->subset(),
    270                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
    271     }
    272 
    273     GrTexture* onPeekTexture() const override { return fTexture; }
    274 
    275     bool getBitmap(SkBitmap* result) const override {
    276         const SkImageInfo info = GrMakeInfoFromTexture(fTexture,
    277                                                        this->width(), this->height(),
    278                                                        this->isOpaque());
    279         if (!result->setInfo(info)) {
    280             return false;
    281         }
    282 
    283         result->setPixelRef(new SkGrPixelRef(info, fTexture))->unref();
    284         return true;
    285     }
    286 
    287     SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override {
    288         GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info);
    289         desc.fFlags = kRenderTarget_GrSurfaceFlag;
    290 
    291         return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc);
    292     }
    293 
    294 private:
    295     SkAutoTUnref<GrTexture> fTexture;
    296     const SkAlphaType       fAlphaType;
    297 
    298     typedef SkSpecialImage_Base INHERITED;
    299 };
    300 
    301 SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
    302                                            const SkIRect& subset,
    303                                            uint32_t uniqueID,
    304                                            GrTexture* tex,
    305                                            SkAlphaType at) {
    306     SkASSERT(rect_fits(subset, tex->width(), tex->height()));
    307     return new SkSpecialImage_Gpu(proxy, subset, uniqueID, tex, at);
    308 }
    309 
    310 #else
    311 
    312 SkSpecialImage* SkSpecialImage::NewFromGpu(SkImageFilter::Proxy* proxy,
    313                                            const SkIRect& subset,
    314                                            uint32_t uniqueID,
    315                                            GrTexture* tex,
    316                                            SkAlphaType at) {
    317     return nullptr;
    318 }
    319 
    320 #endif
    321