Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2011 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 "SkMallocPixelRef.h"
      9 #include "SkBitmap.h"
     10 #include "SkReadBuffer.h"
     11 #include "SkWriteBuffer.h"
     12 
     13 // assumes ptr was allocated via sk_malloc
     14 static void sk_free_releaseproc(void* ptr, void*) {
     15     sk_free(ptr);
     16 }
     17 
     18 static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
     19     if (info.width() < 0 || info.height() < 0 ||
     20         (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType ||
     21         (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType)
     22     {
     23         return false;
     24     }
     25 
     26     // these seem like good checks, but currently we have (at least) tests
     27     // that expect the pixelref to succeed even when there is a mismatch
     28     // with colortables. fix?
     29 #if 0
     30     if (kIndex8_SkColorType == info.fColorType && nullptr == ctable) {
     31         return false;
     32     }
     33     if (kIndex8_SkColorType != info.fColorType && ctable) {
     34         return false;
     35     }
     36 #endif
     37     return true;
     38 }
     39 
     40 SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
     41                                               void* addr,
     42                                               size_t rowBytes,
     43                                               SkColorTable* ctable) {
     44     if (!is_valid(info, ctable)) {
     45         return nullptr;
     46     }
     47     return new SkMallocPixelRef(info, addr, rowBytes, ctable, nullptr, nullptr);
     48 }
     49 
     50 
     51  SkMallocPixelRef* SkMallocPixelRef::NewUsing(void*(*alloc)(size_t),
     52                                               const SkImageInfo& info,
     53                                               size_t requestedRowBytes,
     54                                               SkColorTable* ctable) {
     55     if (!is_valid(info, ctable)) {
     56         return nullptr;
     57     }
     58 
     59     // only want to permit 31bits of rowBytes
     60     int64_t minRB = (int64_t)info.minRowBytes64();
     61     if (minRB < 0 || !sk_64_isS32(minRB)) {
     62         return nullptr;    // allocation will be too large
     63     }
     64     if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
     65         return nullptr;    // cannot meet requested rowbytes
     66     }
     67 
     68     int32_t rowBytes;
     69     if (requestedRowBytes) {
     70         rowBytes = SkToS32(requestedRowBytes);
     71     } else {
     72         rowBytes = minRB;
     73     }
     74 
     75     int64_t bigSize = (int64_t)info.height() * rowBytes;
     76     if (!sk_64_isS32(bigSize)) {
     77         return nullptr;
     78     }
     79 
     80     size_t size = sk_64_asS32(bigSize);
     81     SkASSERT(size >= info.getSafeSize(rowBytes));
     82     void* addr = alloc(size);
     83     if (nullptr == addr) {
     84         return nullptr;
     85     }
     86 
     87     return new SkMallocPixelRef(info, addr, rowBytes, ctable, sk_free_releaseproc, nullptr);
     88 }
     89 
     90 SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
     91                                                 size_t rowBytes,
     92                                                 SkColorTable* ctable) {
     93     auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
     94     return NewUsing(sk_malloc_nothrow, info, rowBytes, ctable);
     95 }
     96 
     97 SkMallocPixelRef* SkMallocPixelRef::NewZeroed(const SkImageInfo& info,
     98                                               size_t rowBytes,
     99                                               SkColorTable* ctable) {
    100     return NewUsing(sk_calloc, info, rowBytes, ctable);
    101 }
    102 
    103 SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
    104                                                 size_t rowBytes,
    105                                                 SkColorTable* ctable,
    106                                                 void* addr,
    107                                                 SkMallocPixelRef::ReleaseProc proc,
    108                                                 void* context) {
    109     if (!is_valid(info, ctable)) {
    110         if (proc) {
    111             proc(addr, context);
    112         }
    113         return nullptr;
    114     }
    115     return new SkMallocPixelRef(info, addr, rowBytes, ctable, proc, context);
    116 }
    117 
    118 static void sk_data_releaseproc(void*, void* dataPtr) {
    119     (static_cast<SkData*>(dataPtr))->unref();
    120 }
    121 
    122 SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
    123                                                 size_t rowBytes,
    124                                                 SkColorTable* ctable,
    125                                                 SkData* data) {
    126     SkASSERT(data != nullptr);
    127     if (!is_valid(info, ctable)) {
    128         return nullptr;
    129     }
    130     if ((rowBytes < info.minRowBytes())
    131         || (data->size() < info.getSafeSize(rowBytes))) {
    132         return nullptr;
    133     }
    134     data->ref();
    135     SkMallocPixelRef* pr =
    136             new SkMallocPixelRef(info, const_cast<void*>(data->data()), rowBytes, ctable,
    137                                  sk_data_releaseproc, static_cast<void*>(data));
    138     SkASSERT(pr != nullptr);
    139     // We rely on the immutability of the pixels to make the
    140     // const_cast okay.
    141     pr->setImmutable();
    142     return pr;
    143 }
    144 
    145 ///////////////////////////////////////////////////////////////////////////////
    146 
    147 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    148                                    size_t rowBytes, SkColorTable* ctable,
    149                                    bool ownsPixels)
    150     : INHERITED(info)
    151     , fReleaseProc(ownsPixels ? sk_free_releaseproc : nullptr)
    152     , fReleaseProcContext(nullptr) {
    153     // This constructor is now DEPRICATED.
    154     SkASSERT(is_valid(info, ctable));
    155     SkASSERT(rowBytes >= info.minRowBytes());
    156 
    157     if (kIndex_8_SkColorType != info.colorType()) {
    158         ctable = nullptr;
    159     }
    160 
    161     fStorage = storage;
    162     fCTable = ctable;
    163     fRB = rowBytes;
    164     SkSafeRef(ctable);
    165 
    166     this->setPreLocked(fStorage, rowBytes, fCTable);
    167 }
    168 
    169 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    170                                    size_t rowBytes, SkColorTable* ctable,
    171                                    SkMallocPixelRef::ReleaseProc proc,
    172                                    void* context)
    173     : INHERITED(info)
    174     , fReleaseProc(proc)
    175     , fReleaseProcContext(context)
    176 {
    177     SkASSERT(is_valid(info, ctable));
    178     SkASSERT(rowBytes >= info.minRowBytes());
    179 
    180     if (kIndex_8_SkColorType != info.colorType()) {
    181         ctable = nullptr;
    182     }
    183 
    184     fStorage = storage;
    185     fCTable = ctable;
    186     fRB = rowBytes;
    187     SkSafeRef(ctable);
    188 
    189     this->setPreLocked(fStorage, rowBytes, fCTable);
    190 }
    191 
    192 
    193 SkMallocPixelRef::~SkMallocPixelRef() {
    194     SkSafeUnref(fCTable);
    195     if (fReleaseProc != nullptr) {
    196         fReleaseProc(fStorage, fReleaseProcContext);
    197     }
    198 }
    199 
    200 bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
    201     rec->fPixels = fStorage;
    202     rec->fRowBytes = fRB;
    203     rec->fColorTable = fCTable;
    204     return true;
    205 }
    206 
    207 void SkMallocPixelRef::onUnlockPixels() {
    208     // nothing to do
    209 }
    210 
    211 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
    212     return this->info().getSafeSize(fRB);
    213 }
    214 
    215 ///////////////////////////////////////////////////////////////////////////////
    216 
    217 SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t rowBytes,
    218                                                 SkColorTable* ctable) {
    219     return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable);
    220 }
    221 
    222 SkPixelRef* SkMallocPixelRef::ZeroedPRFactory::create(const SkImageInfo& info, size_t rowBytes,
    223                                                       SkColorTable* ctable) {
    224     return SkMallocPixelRef::NewZeroed(info, rowBytes, ctable);
    225 }
    226