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         return nullptr;
    111     }
    112     return new SkMallocPixelRef(info, addr, rowBytes, ctable, proc, context);
    113 }
    114 
    115 static void sk_data_releaseproc(void*, void* dataPtr) {
    116     (static_cast<SkData*>(dataPtr))->unref();
    117 }
    118 
    119 SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
    120                                                 size_t rowBytes,
    121                                                 SkColorTable* ctable,
    122                                                 SkData* data) {
    123     SkASSERT(data != nullptr);
    124     if (!is_valid(info, ctable)) {
    125         return nullptr;
    126     }
    127     if ((rowBytes < info.minRowBytes())
    128         || (data->size() < info.getSafeSize(rowBytes))) {
    129         return nullptr;
    130     }
    131     data->ref();
    132     SkMallocPixelRef* pr =
    133             new SkMallocPixelRef(info, const_cast<void*>(data->data()), rowBytes, ctable,
    134                                  sk_data_releaseproc, static_cast<void*>(data));
    135     SkASSERT(pr != nullptr);
    136     // We rely on the immutability of the pixels to make the
    137     // const_cast okay.
    138     pr->setImmutable();
    139     return pr;
    140 }
    141 
    142 ///////////////////////////////////////////////////////////////////////////////
    143 
    144 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    145                                    size_t rowBytes, SkColorTable* ctable,
    146                                    bool ownsPixels)
    147     : INHERITED(info)
    148     , fReleaseProc(ownsPixels ? sk_free_releaseproc : nullptr)
    149     , fReleaseProcContext(nullptr) {
    150     // This constructor is now DEPRICATED.
    151     SkASSERT(is_valid(info, ctable));
    152     SkASSERT(rowBytes >= info.minRowBytes());
    153 
    154     if (kIndex_8_SkColorType != info.colorType()) {
    155         ctable = nullptr;
    156     }
    157 
    158     fStorage = storage;
    159     fCTable = ctable;
    160     fRB = rowBytes;
    161     SkSafeRef(ctable);
    162 
    163     this->setPreLocked(fStorage, rowBytes, fCTable);
    164 }
    165 
    166 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    167                                    size_t rowBytes, SkColorTable* ctable,
    168                                    SkMallocPixelRef::ReleaseProc proc,
    169                                    void* context)
    170     : INHERITED(info)
    171     , fReleaseProc(proc)
    172     , fReleaseProcContext(context)
    173 {
    174     SkASSERT(is_valid(info, ctable));
    175     SkASSERT(rowBytes >= info.minRowBytes());
    176 
    177     if (kIndex_8_SkColorType != info.colorType()) {
    178         ctable = nullptr;
    179     }
    180 
    181     fStorage = storage;
    182     fCTable = ctable;
    183     fRB = rowBytes;
    184     SkSafeRef(ctable);
    185 
    186     this->setPreLocked(fStorage, rowBytes, fCTable);
    187 }
    188 
    189 
    190 SkMallocPixelRef::~SkMallocPixelRef() {
    191     SkSafeUnref(fCTable);
    192     if (fReleaseProc != nullptr) {
    193         fReleaseProc(fStorage, fReleaseProcContext);
    194     }
    195 }
    196 
    197 bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
    198     rec->fPixels = fStorage;
    199     rec->fRowBytes = fRB;
    200     rec->fColorTable = fCTable;
    201     return true;
    202 }
    203 
    204 void SkMallocPixelRef::onUnlockPixels() {
    205     // nothing to do
    206 }
    207 
    208 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
    209     return this->info().getSafeSize(fRB);
    210 }
    211 
    212 ///////////////////////////////////////////////////////////////////////////////
    213 
    214 SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t rowBytes,
    215                                                 SkColorTable* ctable) {
    216     return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable);
    217 }
    218 
    219 SkPixelRef* SkMallocPixelRef::ZeroedPRFactory::create(const SkImageInfo& info, size_t rowBytes,
    220                                                       SkColorTable* ctable) {
    221     return SkMallocPixelRef::NewZeroed(info, rowBytes, ctable);
    222 }
    223