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