Home | History | Annotate | Download | only in image
      1 /*
      2  * Copyright 2012 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 "SkSurface_Base.h"
      9 #include "SkImagePriv.h"
     10 #include "SkCanvas.h"
     11 #include "SkDevice.h"
     12 #include "SkMallocPixelRef.h"
     13 
     14 static const size_t kIgnoreRowBytesValue = (size_t)~0;
     15 
     16 class SkSurface_Raster : public SkSurface_Base {
     17 public:
     18     static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
     19 
     20     SkSurface_Raster(const SkImageInfo&, void*, size_t rb,
     21                      void (*releaseProc)(void* pixels, void* context), void* context,
     22                      const SkSurfaceProps*);
     23     SkSurface_Raster(SkPixelRef*, const SkSurfaceProps*);
     24 
     25     SkCanvas* onNewCanvas() override;
     26     SkSurface* onNewSurface(const SkImageInfo&) override;
     27     SkImage* onNewImageSnapshot(SkBudgeted, ForceCopyMode) override;
     28     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override;
     29     void onCopyOnWrite(ContentChangeMode) override;
     30     void onRestoreBackingMutability() override;
     31 
     32 private:
     33     SkBitmap    fBitmap;
     34     size_t      fRowBytes;
     35     bool        fWeOwnThePixels;
     36 
     37     typedef SkSurface_Base INHERITED;
     38 };
     39 
     40 ///////////////////////////////////////////////////////////////////////////////
     41 
     42 bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
     43     if (info.isEmpty()) {
     44         return false;
     45     }
     46 
     47     static const size_t kMaxTotalSize = SK_MaxS32;
     48 
     49     int shift = 0;
     50     switch (info.colorType()) {
     51         case kAlpha_8_SkColorType:
     52             shift = 0;
     53             break;
     54         case kRGB_565_SkColorType:
     55             shift = 1;
     56             break;
     57         case kN32_SkColorType:
     58             shift = 2;
     59             break;
     60         case kRGBA_F16_SkColorType:
     61             shift = 3;
     62             break;
     63         default:
     64             return false;
     65     }
     66 
     67     if (kIgnoreRowBytesValue == rowBytes) {
     68         return true;
     69     }
     70 
     71     uint64_t minRB = (uint64_t)info.width() << shift;
     72     if (minRB > rowBytes) {
     73         return false;
     74     }
     75 
     76     size_t alignedRowBytes = rowBytes >> shift << shift;
     77     if (alignedRowBytes != rowBytes) {
     78         return false;
     79     }
     80 
     81     uint64_t size = sk_64_mul(info.height(), rowBytes);
     82     if (size > kMaxTotalSize) {
     83         return false;
     84     }
     85 
     86     return true;
     87 }
     88 
     89 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb,
     90                                    void (*releaseProc)(void* pixels, void* context), void* context,
     91                                    const SkSurfaceProps* props)
     92     : INHERITED(info, props)
     93 {
     94     fBitmap.installPixels(info, pixels, rb, nullptr, releaseProc, context);
     95     fRowBytes = 0;              // don't need to track the rowbytes
     96     fWeOwnThePixels = false;    // We are "Direct"
     97 }
     98 
     99 SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr, const SkSurfaceProps* props)
    100     : INHERITED(pr->info().width(), pr->info().height(), props)
    101 {
    102     const SkImageInfo& info = pr->info();
    103 
    104     fBitmap.setInfo(info, pr->rowBytes());
    105     fBitmap.setPixelRef(pr);
    106     fRowBytes = pr->rowBytes(); // we track this, so that subsequent re-allocs will match
    107     fWeOwnThePixels = true;
    108 }
    109 
    110 SkCanvas* SkSurface_Raster::onNewCanvas() { return new SkCanvas(fBitmap, this->props()); }
    111 
    112 SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
    113     return SkSurface::NewRaster(info, &this->props());
    114 }
    115 
    116 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
    117                               const SkPaint* paint) {
    118     canvas->drawBitmap(fBitmap, x, y, paint);
    119 }
    120 
    121 SkImage* SkSurface_Raster::onNewImageSnapshot(SkBudgeted, ForceCopyMode forceCopyMode) {
    122     if (fWeOwnThePixels) {
    123         // SkImage_raster requires these pixels are immutable for its full lifetime.
    124         // We'll undo this via onRestoreBackingMutability() if we can avoid the COW.
    125         if (SkPixelRef* pr = fBitmap.pixelRef()) {
    126             pr->setTemporarilyImmutable();
    127         }
    128     } else {
    129         forceCopyMode = kYes_ForceCopyMode;
    130     }
    131 
    132     // Our pixels are in memory, so read access on the snapshot SkImage could be cheap.
    133     // Lock the shared pixel ref to ensure peekPixels() is usable.
    134     return SkNewImageFromRasterBitmap(fBitmap, forceCopyMode);
    135 }
    136 
    137 void SkSurface_Raster::onRestoreBackingMutability() {
    138     SkASSERT(!this->hasCachedImage());  // Shouldn't be any snapshots out there.
    139     if (SkPixelRef* pr = fBitmap.pixelRef()) {
    140         pr->restoreMutability();
    141     }
    142 }
    143 
    144 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
    145     // are we sharing pixelrefs with the image?
    146     SkAutoTUnref<SkImage> cached(this->refCachedImage(SkBudgeted::kNo, kNo_ForceUnique));
    147     SkASSERT(cached);
    148     if (SkBitmapImageGetPixelRef(cached) == fBitmap.pixelRef()) {
    149         SkASSERT(fWeOwnThePixels);
    150         if (kDiscard_ContentChangeMode == mode) {
    151             fBitmap.allocPixels();
    152         } else {
    153             SkBitmap prev(fBitmap);
    154             fBitmap.allocPixels();
    155             prev.lockPixels();
    156             SkASSERT(prev.info() == fBitmap.info());
    157             SkASSERT(prev.rowBytes() == fBitmap.rowBytes());
    158             memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.getSafeSize());
    159         }
    160         SkASSERT(fBitmap.rowBytes() == fRowBytes);  // be sure we always use the same value
    161 
    162         // Now fBitmap is a deep copy of itself (and therefore different from
    163         // what is being used by the image. Next we update the canvas to use
    164         // this as its backend, so we can't modify the image's pixels anymore.
    165         SkASSERT(this->getCachedCanvas());
    166         this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
    167     }
    168 }
    169 
    170 ///////////////////////////////////////////////////////////////////////////////
    171 
    172 SkSurface* SkSurface::NewRasterDirectReleaseProc(const SkImageInfo& info, void* pixels, size_t rb,
    173                                                  void (*releaseProc)(void* pixels, void* context),
    174                                                  void* context, const SkSurfaceProps* props) {
    175     if (nullptr == releaseProc) {
    176         context = nullptr;
    177     }
    178     if (!SkSurface_Raster::Valid(info, rb)) {
    179         return nullptr;
    180     }
    181     if (nullptr == pixels) {
    182         return nullptr;
    183     }
    184 
    185     return new SkSurface_Raster(info, pixels, rb, releaseProc, context, props);
    186 }
    187 
    188 SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes,
    189                                       const SkSurfaceProps* props) {
    190     return NewRasterDirectReleaseProc(info, pixels, rowBytes, nullptr, nullptr, props);
    191 }
    192 
    193 SkSurface* SkSurface::NewRaster(const SkImageInfo& info, size_t rowBytes,
    194                                 const SkSurfaceProps* props) {
    195     if (!SkSurface_Raster::Valid(info)) {
    196         return nullptr;
    197     }
    198 
    199     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewZeroed(info, rowBytes, nullptr));
    200     if (nullptr == pr.get()) {
    201         return nullptr;
    202     }
    203     if (rowBytes) {
    204         SkASSERT(pr->rowBytes() == rowBytes);
    205     }
    206     return new SkSurface_Raster(pr, props);
    207 }
    208 
    209 SkSurface* SkSurface::NewRaster(const SkImageInfo& info, const SkSurfaceProps* props) {
    210     return NewRaster(info, 0, props);
    211 }
    212