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(sk_sp<SkPixelRef>, const SkSurfaceProps*);
     24 
     25     SkCanvas* onNewCanvas() override;
     26     sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
     27     sk_sp<SkImage> onNewImageSnapshot() 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             if (info.colorSpace()) {
     53                 return false;
     54             }
     55             shift = 0;
     56             break;
     57         case kRGB_565_SkColorType:
     58             if (info.colorSpace()) {
     59                 return false;
     60             }
     61             shift = 1;
     62             break;
     63         case kN32_SkColorType:
     64             if (info.colorSpace() && !info.colorSpace()->gammaCloseToSRGB()) {
     65                 return false;
     66             }
     67             shift = 2;
     68             break;
     69         case kRGBA_F16_SkColorType:
     70             if (info.colorSpace() && !info.colorSpace()->gammaIsLinear()) {
     71                 return false;
     72             }
     73             shift = 3;
     74             break;
     75         default:
     76             return false;
     77     }
     78 
     79     if (kIgnoreRowBytesValue == rowBytes) {
     80         return true;
     81     }
     82 
     83     uint64_t minRB = (uint64_t)info.width() << shift;
     84     if (minRB > rowBytes) {
     85         return false;
     86     }
     87 
     88     size_t alignedRowBytes = rowBytes >> shift << shift;
     89     if (alignedRowBytes != rowBytes) {
     90         return false;
     91     }
     92 
     93     uint64_t size = sk_64_mul(info.height(), rowBytes);
     94     if (size > kMaxTotalSize) {
     95         return false;
     96     }
     97 
     98     return true;
     99 }
    100 
    101 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb,
    102                                    void (*releaseProc)(void* pixels, void* context), void* context,
    103                                    const SkSurfaceProps* props)
    104     : INHERITED(info, props)
    105 {
    106     fBitmap.installPixels(info, pixels, rb, nullptr, releaseProc, context);
    107     fRowBytes = 0;              // don't need to track the rowbytes
    108     fWeOwnThePixels = false;    // We are "Direct"
    109 }
    110 
    111 SkSurface_Raster::SkSurface_Raster(sk_sp<SkPixelRef> pr, const SkSurfaceProps* props)
    112     : INHERITED(pr->info().width(), pr->info().height(), props)
    113 {
    114     const SkImageInfo& info = pr->info();
    115 
    116     fBitmap.setInfo(info, pr->rowBytes());
    117     fRowBytes = pr->rowBytes(); // we track this, so that subsequent re-allocs will match
    118     fBitmap.setPixelRef(std::move(pr), 0, 0);
    119     fWeOwnThePixels = true;
    120 }
    121 
    122 SkCanvas* SkSurface_Raster::onNewCanvas() { return new SkCanvas(fBitmap, this->props()); }
    123 
    124 sk_sp<SkSurface> SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
    125     return SkSurface::MakeRaster(info, &this->props());
    126 }
    127 
    128 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
    129                               const SkPaint* paint) {
    130     canvas->drawBitmap(fBitmap, x, y, paint);
    131 }
    132 
    133 sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot() {
    134     SkCopyPixelsMode cpm = kIfMutable_SkCopyPixelsMode;
    135     if (fWeOwnThePixels) {
    136         // SkImage_raster requires these pixels are immutable for its full lifetime.
    137         // We'll undo this via onRestoreBackingMutability() if we can avoid the COW.
    138         if (SkPixelRef* pr = fBitmap.pixelRef()) {
    139             pr->setTemporarilyImmutable();
    140         }
    141     } else {
    142         cpm = kAlways_SkCopyPixelsMode;
    143     }
    144 
    145     // Our pixels are in memory, so read access on the snapshot SkImage could be cheap.
    146     // Lock the shared pixel ref to ensure peekPixels() is usable.
    147     return SkMakeImageFromRasterBitmap(fBitmap, cpm);
    148 }
    149 
    150 void SkSurface_Raster::onRestoreBackingMutability() {
    151     SkASSERT(!this->hasCachedImage());  // Shouldn't be any snapshots out there.
    152     if (SkPixelRef* pr = fBitmap.pixelRef()) {
    153         pr->restoreMutability();
    154     }
    155 }
    156 
    157 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
    158     // are we sharing pixelrefs with the image?
    159     sk_sp<SkImage> cached(this->refCachedImage());
    160     SkASSERT(cached);
    161     if (SkBitmapImageGetPixelRef(cached.get()) == fBitmap.pixelRef()) {
    162         SkASSERT(fWeOwnThePixels);
    163         if (kDiscard_ContentChangeMode == mode) {
    164             fBitmap.allocPixels();
    165         } else {
    166             SkBitmap prev(fBitmap);
    167             fBitmap.allocPixels();
    168             prev.lockPixels();
    169             SkASSERT(prev.info() == fBitmap.info());
    170             SkASSERT(prev.rowBytes() == fBitmap.rowBytes());
    171             memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.getSafeSize());
    172         }
    173         SkASSERT(fBitmap.rowBytes() == fRowBytes);  // be sure we always use the same value
    174 
    175         // Now fBitmap is a deep copy of itself (and therefore different from
    176         // what is being used by the image. Next we update the canvas to use
    177         // this as its backend, so we can't modify the image's pixels anymore.
    178         SkASSERT(this->getCachedCanvas());
    179         this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
    180     }
    181 }
    182 
    183 ///////////////////////////////////////////////////////////////////////////////
    184 
    185 sk_sp<SkSurface> SkSurface::MakeRasterDirectReleaseProc(const SkImageInfo& info, void* pixels,
    186         size_t rb, void (*releaseProc)(void* pixels, void* context), void* context,
    187         const SkSurfaceProps* props) {
    188     if (nullptr == releaseProc) {
    189         context = nullptr;
    190     }
    191     if (!SkSurface_Raster::Valid(info, rb)) {
    192         return nullptr;
    193     }
    194     if (nullptr == pixels) {
    195         return nullptr;
    196     }
    197 
    198     return sk_make_sp<SkSurface_Raster>(info, pixels, rb, releaseProc, context, props);
    199 }
    200 
    201 sk_sp<SkSurface> SkSurface::MakeRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes,
    202                                              const SkSurfaceProps* props) {
    203     return MakeRasterDirectReleaseProc(info, pixels, rowBytes, nullptr, nullptr, props);
    204 }
    205 
    206 sk_sp<SkSurface> SkSurface::MakeRaster(const SkImageInfo& info, size_t rowBytes,
    207                                        const SkSurfaceProps* props) {
    208     if (!SkSurface_Raster::Valid(info)) {
    209         return nullptr;
    210     }
    211 
    212     sk_sp<SkPixelRef> pr(SkMallocPixelRef::NewZeroed(info, rowBytes, nullptr));
    213     if (!pr) {
    214         return nullptr;
    215     }
    216     if (rowBytes) {
    217         SkASSERT(pr->rowBytes() == rowBytes);
    218     }
    219     return sk_make_sp<SkSurface_Raster>(std::move(pr), props);
    220 }
    221