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 14static void sk_free_releaseproc(void* ptr, void*) { 15 sk_free(ptr); 16} 17 18static 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 40SkMallocPixelRef* 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 90SkMallocPixelRef* 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 97SkMallocPixelRef* SkMallocPixelRef::NewZeroed(const SkImageInfo& info, 98 size_t rowBytes, 99 SkColorTable* ctable) { 100 return NewUsing(sk_calloc, info, rowBytes, ctable); 101} 102 103SkMallocPixelRef* 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 115static void sk_data_releaseproc(void*, void* dataPtr) { 116 (static_cast<SkData*>(dataPtr))->unref(); 117} 118 119SkMallocPixelRef* 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 144SkMallocPixelRef::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 166SkMallocPixelRef::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 190SkMallocPixelRef::~SkMallocPixelRef() { 191 SkSafeUnref(fCTable); 192 if (fReleaseProc != nullptr) { 193 fReleaseProc(fStorage, fReleaseProcContext); 194 } 195} 196 197bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) { 198 rec->fPixels = fStorage; 199 rec->fRowBytes = fRB; 200 rec->fColorTable = fCTable; 201 return true; 202} 203 204void SkMallocPixelRef::onUnlockPixels() { 205 // nothing to do 206} 207 208size_t SkMallocPixelRef::getAllocatedSizeInBytes() const { 209 return this->info().getSafeSize(fRB); 210} 211 212/////////////////////////////////////////////////////////////////////////////// 213 214SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t rowBytes, 215 SkColorTable* ctable) { 216 return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable); 217} 218 219SkPixelRef* SkMallocPixelRef::ZeroedPRFactory::create(const SkImageInfo& info, size_t rowBytes, 220 SkColorTable* ctable) { 221 return SkMallocPixelRef::NewZeroed(info, rowBytes, ctable); 222} 223