• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
sk_free_releaseproc(void * ptr,void *)14 static void sk_free_releaseproc(void* ptr, void*) {
15     sk_free(ptr);
16 }
17 
is_valid(const SkImageInfo & info,SkColorTable * ctable)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 
NewDirect(const SkImageInfo & info,void * addr,size_t rowBytes,SkColorTable * ctable)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 
NewUsing(void * (* alloc)(size_t),const SkImageInfo & info,size_t requestedRowBytes,SkColorTable * ctable)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 
NewAllocate(const SkImageInfo & info,size_t rowBytes,SkColorTable * ctable)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 
NewZeroed(const SkImageInfo & info,size_t rowBytes,SkColorTable * ctable)97 SkMallocPixelRef* SkMallocPixelRef::NewZeroed(const SkImageInfo& info,
98                                               size_t rowBytes,
99                                               SkColorTable* ctable) {
100     return NewUsing(sk_calloc, info, rowBytes, ctable);
101 }
102 
NewWithProc(const SkImageInfo & info,size_t rowBytes,SkColorTable * ctable,void * addr,SkMallocPixelRef::ReleaseProc proc,void * context)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 
sk_data_releaseproc(void *,void * dataPtr)118 static void sk_data_releaseproc(void*, void* dataPtr) {
119     (static_cast<SkData*>(dataPtr))->unref();
120 }
121 
NewWithData(const SkImageInfo & info,size_t rowBytes,SkColorTable * ctable,SkData * data)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 
SkMallocPixelRef(const SkImageInfo & info,void * storage,size_t rowBytes,SkColorTable * ctable,bool ownsPixels)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 
SkMallocPixelRef(const SkImageInfo & info,void * storage,size_t rowBytes,SkColorTable * ctable,SkMallocPixelRef::ReleaseProc proc,void * context)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 
~SkMallocPixelRef()193 SkMallocPixelRef::~SkMallocPixelRef() {
194     SkSafeUnref(fCTable);
195     if (fReleaseProc != nullptr) {
196         fReleaseProc(fStorage, fReleaseProcContext);
197     }
198 }
199 
onNewLockPixels(LockRec * rec)200 bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
201     rec->fPixels = fStorage;
202     rec->fRowBytes = fRB;
203     rec->fColorTable = fCTable;
204     return true;
205 }
206 
onUnlockPixels()207 void SkMallocPixelRef::onUnlockPixels() {
208     // nothing to do
209 }
210 
getAllocatedSizeInBytes() const211 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
212     return this->info().getSafeSize(fRB);
213 }
214 
215 ///////////////////////////////////////////////////////////////////////////////
216 
create(const SkImageInfo & info,size_t rowBytes,SkColorTable * ctable)217 SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t rowBytes,
218                                                 SkColorTable* ctable) {
219     return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable);
220 }
221 
create(const SkImageInfo & info,size_t rowBytes,SkColorTable * ctable)222 SkPixelRef* SkMallocPixelRef::ZeroedPRFactory::create(const SkImageInfo& info, size_t rowBytes,
223                                                       SkColorTable* ctable) {
224     return SkMallocPixelRef::NewZeroed(info, rowBytes, ctable);
225 }
226