Line data Source code
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 43 : static void sk_free_releaseproc(void* ptr, void*) {
15 43 : sk_free(ptr);
16 43 : }
17 :
18 270 : static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
19 1080 : if (info.width() < 0 || info.height() < 0 ||
20 810 : (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType ||
21 270 : (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType)
22 : {
23 0 : 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 270 : return true;
38 : }
39 :
40 0 : sk_sp<SkPixelRef> SkMallocPixelRef::MakeDirect(const SkImageInfo& info,
41 : void* addr,
42 : size_t rowBytes,
43 : sk_sp<SkColorTable> ctable) {
44 0 : if (!is_valid(info, ctable.get())) {
45 0 : return nullptr;
46 : }
47 0 : return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, std::move(ctable),
48 0 : nullptr, nullptr));
49 : }
50 :
51 :
52 66 : sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*alloc)(size_t),
53 : const SkImageInfo& info,
54 : size_t requestedRowBytes,
55 : sk_sp<SkColorTable> ctable) {
56 66 : if (!is_valid(info, ctable.get())) {
57 0 : return nullptr;
58 : }
59 :
60 : // only want to permit 31bits of rowBytes
61 66 : int64_t minRB = (int64_t)info.minRowBytes64();
62 66 : if (minRB < 0 || !sk_64_isS32(minRB)) {
63 0 : return nullptr; // allocation will be too large
64 : }
65 66 : if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
66 0 : return nullptr; // cannot meet requested rowbytes
67 : }
68 :
69 : int32_t rowBytes;
70 66 : if (requestedRowBytes) {
71 48 : rowBytes = SkToS32(requestedRowBytes);
72 : } else {
73 18 : rowBytes = minRB;
74 : }
75 :
76 66 : int64_t bigSize = (int64_t)info.height() * rowBytes;
77 66 : if (!sk_64_isS32(bigSize)) {
78 0 : return nullptr;
79 : }
80 :
81 66 : size_t size = sk_64_asS32(bigSize);
82 66 : SkASSERT(size >= info.getSafeSize(rowBytes));
83 66 : void* addr = alloc(size);
84 66 : if (nullptr == addr) {
85 0 : return nullptr;
86 : }
87 :
88 66 : return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, std::move(ctable),
89 132 : sk_free_releaseproc, nullptr));
90 : }
91 :
92 21 : sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info,
93 : size_t rowBytes,
94 : sk_sp<SkColorTable> ctable) {
95 63 : auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
96 21 : return MakeUsing(sk_malloc_nothrow, info, rowBytes, std::move(ctable));
97 : }
98 :
99 45 : sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info,
100 : size_t rowBytes,
101 : sk_sp<SkColorTable> ctable) {
102 45 : return MakeUsing(sk_calloc, info, rowBytes, std::move(ctable));
103 : }
104 :
105 0 : static void sk_data_releaseproc(void*, void* dataPtr) {
106 0 : (static_cast<SkData*>(dataPtr))->unref();
107 0 : }
108 :
109 204 : sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info,
110 : size_t rowBytes,
111 : sk_sp<SkColorTable> ctable,
112 : void* addr,
113 : SkMallocPixelRef::ReleaseProc proc,
114 : void* context) {
115 204 : if (!is_valid(info, ctable.get())) {
116 0 : if (proc) {
117 0 : proc(addr, context);
118 : }
119 0 : return nullptr;
120 : }
121 204 : return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, std::move(ctable),
122 408 : proc, context));
123 : }
124 :
125 0 : sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info,
126 : size_t rowBytes,
127 : sk_sp<SkColorTable> ctable,
128 : sk_sp<SkData> data) {
129 0 : SkASSERT(data != nullptr);
130 0 : if (!is_valid(info, ctable.get())) {
131 0 : return nullptr;
132 : }
133 0 : if ((rowBytes < info.minRowBytes()) || (data->size() < info.getSafeSize(rowBytes))) {
134 0 : return nullptr;
135 : }
136 : // must get this address before we call release
137 0 : void* pixels = const_cast<void*>(data->data());
138 0 : SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes, std::move(ctable),
139 0 : sk_data_releaseproc, data.release());
140 0 : pr->setImmutable(); // since we were created with (immutable) data
141 0 : return sk_sp<SkPixelRef>(pr);
142 : }
143 :
144 : ///////////////////////////////////////////////////////////////////////////////
145 :
146 270 : static sk_sp<SkColorTable> sanitize(const SkImageInfo& info, sk_sp<SkColorTable> ctable) {
147 270 : if (kIndex_8_SkColorType == info.colorType()) {
148 0 : SkASSERT(ctable);
149 : } else {
150 270 : ctable.reset(nullptr);
151 : }
152 270 : return ctable;
153 : }
154 :
155 270 : SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
156 : size_t rowBytes, sk_sp<SkColorTable> ctable,
157 : SkMallocPixelRef::ReleaseProc proc,
158 270 : void* context)
159 540 : : INHERITED(info, storage, rowBytes, sanitize(info, std::move(ctable)))
160 : , fReleaseProc(proc)
161 540 : , fReleaseProcContext(context)
162 270 : {}
163 :
164 :
165 675 : SkMallocPixelRef::~SkMallocPixelRef() {
166 225 : if (fReleaseProc != nullptr) {
167 191 : fReleaseProc(this->pixels(), fReleaseProcContext);
168 : }
169 675 : }
170 :
171 : #ifdef SK_SUPPORT_LEGACY_NO_ADDR_PIXELREF
172 : bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
173 : sk_throw(); // should never get here
174 : return true;
175 : }
176 :
177 : void SkMallocPixelRef::onUnlockPixels() {
178 : // nothing to do
179 : }
180 : #endif
181 :
182 0 : size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
183 0 : return this->info().getSafeSize(this->rowBytes());
184 : }
185 :
186 : #ifdef SK_SUPPORT_LEGACY_PIXELREFFACTORY
187 : SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
188 : size_t rowBytes,
189 : SkColorTable* ctable,
190 : SkData* data) {
191 : return (SkMallocPixelRef*)MakeWithData(info, rowBytes, sk_ref_sp(ctable), sk_ref_sp(data)).release();
192 : }
193 : #endif
|