1 /*
2 * Copyright 2015 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 "include/core/SkPixmap.h"
9
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkColorPriv.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkUnPreMultiply.h"
15 #include "include/private/SkColorData.h"
16 #include "include/private/base/SkFloatingPoint.h"
17 #include "include/private/base/SkTPin.h"
18 #include "src/base/SkHalf.h"
19 #include "src/base/SkVx.h"
20 #include "src/core/SkConvertPixels.h"
21 #include "src/core/SkImageInfoPriv.h"
22 #include "src/core/SkMask.h"
23 #include "src/core/SkReadPixelsRec.h"
24 #include "src/core/SkSwizzlePriv.h"
25 #include "src/opts/SkMemset_opts.h"
26
27 #include <cstdint>
28 #include <cstring>
29 #include <iterator>
30 #include <utility>
31
reset()32 void SkPixmap::reset() {
33 fPixels = nullptr;
34 fRowBytes = 0;
35 fInfo = SkImageInfo::MakeUnknown();
36 }
37
reset(const SkImageInfo & info,const void * addr,size_t rowBytes)38 void SkPixmap::reset(const SkImageInfo& info, const void* addr, size_t rowBytes) {
39 if (addr) {
40 SkASSERT(info.validRowBytes(rowBytes));
41 }
42 fPixels = addr;
43 fRowBytes = rowBytes;
44 fInfo = info;
45 }
46
reset(const SkMask & src)47 bool SkPixmap::reset(const SkMask& src) {
48 if (SkMask::kA8_Format == src.fFormat) {
49 this->reset(SkImageInfo::MakeA8(src.fBounds.width(), src.fBounds.height()),
50 src.fImage, src.fRowBytes);
51 return true;
52 }
53 this->reset();
54 return false;
55 }
56
setColorSpace(sk_sp<SkColorSpace> cs)57 void SkPixmap::setColorSpace(sk_sp<SkColorSpace> cs) {
58 fInfo = fInfo.makeColorSpace(std::move(cs));
59 }
60
colorSpace() const61 SkColorSpace* SkPixmap::colorSpace() const { return fInfo.colorSpace(); }
62
refColorSpace() const63 sk_sp<SkColorSpace> SkPixmap::refColorSpace() const { return fInfo.refColorSpace(); }
64
extractSubset(SkPixmap * result,const SkIRect & subset) const65 bool SkPixmap::extractSubset(SkPixmap* result, const SkIRect& subset) const {
66 SkIRect srcRect, r;
67 srcRect.setWH(this->width(), this->height());
68 if (!r.intersect(srcRect, subset)) {
69 return false; // r is empty (i.e. no intersection)
70 }
71
72 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
73 // exited above.
74 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
75 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
76
77 const void* pixels = nullptr;
78 if (fPixels) {
79 const size_t bpp = fInfo.bytesPerPixel();
80 pixels = (const uint8_t*)fPixels + r.fTop * fRowBytes + r.fLeft * bpp;
81 }
82 result->reset(fInfo.makeDimensions(r.size()), pixels, fRowBytes);
83 return true;
84 }
85
86 // This is the same as SkPixmap::addr(x,y), but this version gets inlined, while the public
87 // method does not. Perhaps we could bloat it so it can be inlined, but that would grow code-size
88 // everywhere, instead of just here (on behalf of getAlphaf()).
fast_getaddr(const SkPixmap & pm,int x,int y)89 static const void* fast_getaddr(const SkPixmap& pm, int x, int y) {
90 x <<= SkColorTypeShiftPerPixel(pm.colorType());
91 return static_cast<const char*>(pm.addr()) + y * pm.rowBytes() + x;
92 }
93
getAlphaf(int x,int y) const94 float SkPixmap::getAlphaf(int x, int y) const {
95 SkASSERT(this->addr());
96 SkASSERT((unsigned)x < (unsigned)this->width());
97 SkASSERT((unsigned)y < (unsigned)this->height());
98
99 float value = 0;
100 const void* srcPtr = fast_getaddr(*this, x, y);
101
102 switch (this->colorType()) {
103 case kUnknown_SkColorType:
104 return 0;
105 case kGray_8_SkColorType:
106 case kR8G8_unorm_SkColorType:
107 case kR16G16_unorm_SkColorType:
108 case kR16G16_float_SkColorType:
109 case kRGB_565_SkColorType:
110 case kRGB_888x_SkColorType:
111 case kRGB_101010x_SkColorType:
112 case kBGR_101010x_SkColorType:
113 case kBGR_101010x_XR_SkColorType:
114 case kR8_unorm_SkColorType:
115 return 1;
116 case kAlpha_8_SkColorType:
117 value = static_cast<const uint8_t*>(srcPtr)[0] * (1.0f/255);
118 break;
119 case kA16_unorm_SkColorType:
120 value = static_cast<const uint16_t*>(srcPtr)[0] * (1.0f/65535);
121 break;
122 case kA16_float_SkColorType: {
123 SkHalf half = static_cast<const SkHalf*>(srcPtr)[0];
124 value = SkHalfToFloat(half);
125 break;
126 }
127 case kARGB_4444_SkColorType: {
128 uint16_t u16 = static_cast<const uint16_t*>(srcPtr)[0];
129 value = SkGetPackedA4444(u16) * (1.0f/15);
130 break;
131 }
132 case kRGBA_8888_SkColorType:
133 case kBGRA_8888_SkColorType:
134 case kSRGBA_8888_SkColorType:
135 value = static_cast<const uint8_t*>(srcPtr)[3] * (1.0f/255);
136 break;
137 case kRGBA_1010102_SkColorType:
138 case kBGRA_1010102_SkColorType: {
139 uint32_t u32 = static_cast<const uint32_t*>(srcPtr)[0];
140 value = (u32 >> 30) * (1.0f/3);
141 break;
142 }
143 case kBGRA_10101010_XR_SkColorType: {
144 uint64_t u64 = static_cast<const uint64_t*>(srcPtr)[0];
145 value = ((u64 >> 54) - 384) / 510.f;
146 break;
147 }
148 case kRGBA_10x6_SkColorType: {
149 uint64_t u64 = static_cast<const uint64_t*>(srcPtr)[0];
150 value = (u64 >> 54) * (1.0f/1023);
151 break;
152 }
153 case kR16G16B16A16_unorm_SkColorType: {
154 uint64_t u64 = static_cast<const uint64_t*>(srcPtr)[0];
155 value = (u64 >> 48) * (1.0f/65535);
156 break;
157 }
158 case kRGBA_F16Norm_SkColorType:
159 case kRGBA_F16_SkColorType: {
160 value = from_half(skvx::half4::Load(srcPtr))[3];
161 break;
162 }
163 case kRGBA_F32_SkColorType:
164 value = static_cast<const float*>(srcPtr)[3];
165 break;
166 }
167 return value;
168 }
169
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRB,int x,int y) const170 bool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
171 int x, int y) const {
172 if (!SkImageInfoValidConversion(dstInfo, fInfo)) {
173 return false;
174 }
175
176 SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, x, y);
177 if (!rec.trim(fInfo.width(), fInfo.height())) {
178 return false;
179 }
180
181 const void* srcPixels = this->addr(rec.fX, rec.fY);
182 const SkImageInfo srcInfo = fInfo.makeDimensions(rec.fInfo.dimensions());
183 return SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels,
184 this->rowBytes());
185 }
186
getColor(int x,int y) const187 SkColor SkPixmap::getColor(int x, int y) const {
188 SkASSERT(this->addr());
189 SkASSERT((unsigned)x < (unsigned)this->width());
190 SkASSERT((unsigned)y < (unsigned)this->height());
191
192 const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType());
193 auto toColor = [needsUnpremul](uint32_t maybePremulColor) {
194 return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor)
195 : SkSwizzle_BGRA_to_PMColor(maybePremulColor);
196 };
197
198 switch (this->colorType()) {
199 case kGray_8_SkColorType: {
200 uint8_t value = *this->addr8(x, y);
201 return SkColorSetRGB(value, value, value);
202 }
203 case kR8_unorm_SkColorType: {
204 uint8_t value = *this->addr8(x, y);
205 return SkColorSetRGB(value, 0, 0);
206 }
207 case kAlpha_8_SkColorType: {
208 return SkColorSetA(0, *this->addr8(x, y));
209 }
210 case kA16_unorm_SkColorType: {
211 uint16_t value = *this->addr16(x, y);
212 return SkColorSetA(0, value * (255 / 65535.0f));
213 }
214 case kA16_float_SkColorType: {
215 SkHalf value = *this->addr16(x, y);
216 return SkColorSetA(0, 255 * SkHalfToFloat(value));
217 }
218 case kRGB_565_SkColorType: {
219 return SkPixel16ToColor(*this->addr16(x, y));
220 }
221 case kARGB_4444_SkColorType: {
222 uint16_t value = *this->addr16(x, y);
223 SkPMColor c = SkPixel4444ToPixel32(value);
224 return toColor(c);
225 }
226 case kR8G8_unorm_SkColorType: {
227 uint16_t value = *this->addr16(x, y);
228 return (uint32_t)( ((value >> 0) & 0xff) ) << 16
229 | (uint32_t)( ((value >> 8) & 0xff) ) << 8
230 | 0xff000000;
231 }
232 case kR16G16_unorm_SkColorType: {
233 uint32_t value = *this->addr32(x, y);
234 return (uint32_t)( ((value >> 0) & 0xffff) * (255/65535.0f) ) << 16
235 | (uint32_t)( ((value >> 16) & 0xffff) * (255/65535.0f) ) << 8
236 | 0xff000000;
237 }
238 case kR16G16_float_SkColorType: {
239 uint32_t value = *this->addr32(x, y);
240 uint32_t r = 255 * SkHalfToFloat((value >> 0) & 0xffff);
241 uint32_t g = 255 * SkHalfToFloat((value >> 16) & 0xffff);
242 return (r << 16) | (g << 8) | 0xff000000;
243 }
244 case kRGB_888x_SkColorType: {
245 uint32_t value = *this->addr32(x, y);
246 return SkSwizzle_RB(value | 0xff000000);
247 }
248 case kBGRA_8888_SkColorType: {
249 uint32_t value = *this->addr32(x, y);
250 SkPMColor c = SkSwizzle_BGRA_to_PMColor(value);
251 return toColor(c);
252 }
253 case kRGBA_8888_SkColorType: {
254 uint32_t value = *this->addr32(x, y);
255 SkPMColor c = SkSwizzle_RGBA_to_PMColor(value);
256 return toColor(c);
257 }
258 case kSRGBA_8888_SkColorType: {
259 auto srgb_to_linear = [](float x) {
260 return (x <= 0.04045f) ? x * (1 / 12.92f)
261 : std::pow(x * (1 / 1.055f) + (0.055f / 1.055f), 2.4f);
262 };
263
264 uint32_t value = *this->addr32(x, y);
265 float r = ((value >> 0) & 0xff) * (1/255.0f),
266 g = ((value >> 8) & 0xff) * (1/255.0f),
267 b = ((value >> 16) & 0xff) * (1/255.0f),
268 a = ((value >> 24) & 0xff) * (1/255.0f);
269 r = srgb_to_linear(r);
270 g = srgb_to_linear(g);
271 b = srgb_to_linear(b);
272 if (a != 0 && needsUnpremul) {
273 r = SkTPin(r/a, 0.0f, 1.0f);
274 g = SkTPin(g/a, 0.0f, 1.0f);
275 b = SkTPin(b/a, 0.0f, 1.0f);
276 }
277 return (uint32_t)( r * 255.0f ) << 16
278 | (uint32_t)( g * 255.0f ) << 8
279 | (uint32_t)( b * 255.0f ) << 0
280 | (uint32_t)( a * 255.0f ) << 24;
281 }
282 case kRGB_101010x_SkColorType: {
283 uint32_t value = *this->addr32(x, y);
284 // Convert 10-bit rgb to 8-bit bgr, and mask in 0xff alpha at the top.
285 return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 16
286 | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8
287 | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 0
288 | 0xff000000;
289 }
290 case kBGR_101010x_XR_SkColorType: {
291 SkASSERT(false);
292 return 0;
293 }
294 case kBGR_101010x_SkColorType: {
295 uint32_t value = *this->addr32(x, y);
296 // Convert 10-bit bgr to 8-bit bgr, and mask in 0xff alpha at the top.
297 return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 0
298 | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8
299 | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 16
300 | 0xff000000;
301 }
302 case kRGBA_1010102_SkColorType:
303 case kBGRA_1010102_SkColorType: {
304 uint32_t value = *this->addr32(x, y);
305
306 float r = ((value >> 0) & 0x3ff) * (1/1023.0f),
307 g = ((value >> 10) & 0x3ff) * (1/1023.0f),
308 b = ((value >> 20) & 0x3ff) * (1/1023.0f),
309 a = ((value >> 30) & 0x3 ) * (1/ 3.0f);
310 if (this->colorType() == kBGRA_1010102_SkColorType) {
311 std::swap(r,b);
312 }
313 if (a != 0 && needsUnpremul) {
314 r = SkTPin(r/a, 0.0f, 1.0f);
315 g = SkTPin(g/a, 0.0f, 1.0f);
316 b = SkTPin(b/a, 0.0f, 1.0f);
317 }
318 return (uint32_t)( r * 255.0f ) << 16
319 | (uint32_t)( g * 255.0f ) << 8
320 | (uint32_t)( b * 255.0f ) << 0
321 | (uint32_t)( a * 255.0f ) << 24;
322 }
323 case kBGRA_10101010_XR_SkColorType: {
324 SkASSERT(false);
325 return 0;
326 }
327 case kRGBA_10x6_SkColorType: {
328 uint64_t value = *this->addr64(x, y);
329 float r = ((value >> 6) & 0x3ff) * (1/1023.0f),
330 g = ((value >> 22) & 0x3ff) * (1/1023.0f),
331 b = ((value >> 38) & 0x3ff) * (1/1023.0f),
332 a = ((value >> 54) & 0x3ff) * (1/1023.0f);
333 return (uint32_t)( r * 255.0f ) << 16
334 | (uint32_t)( g * 255.0f ) << 8
335 | (uint32_t)( b * 255.0f ) << 0
336 | (uint32_t)( a * 255.0f ) << 24;
337 }
338 case kR16G16B16A16_unorm_SkColorType: {
339 uint64_t value = *this->addr64(x, y);
340
341 float r = ((value ) & 0xffff) * (1/65535.0f),
342 g = ((value >> 16) & 0xffff) * (1/65535.0f),
343 b = ((value >> 32) & 0xffff) * (1/65535.0f),
344 a = ((value >> 48) & 0xffff) * (1/65535.0f);
345 if (a != 0 && needsUnpremul) {
346 r *= (1.0f/a);
347 g *= (1.0f/a);
348 b *= (1.0f/a);
349 }
350 return (uint32_t)( r * 255.0f ) << 16
351 | (uint32_t)( g * 255.0f ) << 8
352 | (uint32_t)( b * 255.0f ) << 0
353 | (uint32_t)( a * 255.0f ) << 24;
354 }
355 case kRGBA_F16Norm_SkColorType:
356 case kRGBA_F16_SkColorType: {
357 const uint64_t* addr =
358 (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x;
359 skvx::float4 p4 = from_half(skvx::half4::Load(addr));
360 if (p4[3] && needsUnpremul) {
361 float inva = 1 / p4[3];
362 p4 = p4 * skvx::float4(inva, inva, inva, 1);
363 }
364 // p4 is RGBA, but we want BGRA, so we need to swap next
365 return Sk4f_toL32(swizzle_rb(p4));
366 }
367 case kRGBA_F32_SkColorType: {
368 const float* rgba =
369 (const float*)fPixels + 4*y*(fRowBytes >> 4) + 4*x;
370 skvx::float4 p4 = skvx::float4::Load(rgba);
371 // From here on, just like F16:
372 if (p4[3] && needsUnpremul) {
373 float inva = 1 / p4[3];
374 p4 = p4 * skvx::float4(inva, inva, inva, 1);
375 }
376 // p4 is RGBA, but we want BGRA, so we need to swap next
377 return Sk4f_toL32(swizzle_rb(p4));
378 }
379 case kUnknown_SkColorType:
380 break;
381 }
382 SkDEBUGFAIL("");
383 return SkColorSetARGB(0, 0, 0, 0);
384 }
385
386 //////////////////////////////////////////////////////////////////////////////////////////////////
387
getColor4f(int x,int y) const388 SkColor4f SkPixmap::getColor4f(int x, int y) const {
389 SkASSERT(this->addr());
390 SkASSERT((unsigned)x < (unsigned)this->width());
391 SkASSERT((unsigned)y < (unsigned)this->height());
392
393 const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType());
394 auto toColor = [needsUnpremul](uint32_t maybePremulColor) {
395 return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor)
396 : SkSwizzle_BGRA_to_PMColor(maybePremulColor);
397 };
398
399 switch (this->colorType()) {
400 case kGray_8_SkColorType: {
401 float value = *this->addr8(x, y) / 255.0f;
402 return SkColor4f{value, value, value, 1.0};
403 }
404 case kR8_unorm_SkColorType: {
405 float value = *this->addr8(x, y) / 255.0f;
406 return SkColor4f{value, 0.0f, 0.0f, 1.0f};
407 }
408 case kAlpha_8_SkColorType: {
409 float value = *this->addr8(x, y) / 255.0f;
410 return SkColor4f{0.0f, 0.0f, 0.0f, value};
411 }
412 case kA16_unorm_SkColorType: {
413 float value = *this->addr16(x, y) / 65535.0f;
414 return SkColor4f{0.0f, 0.0f, 0.0f, value};
415 }
416 case kA16_float_SkColorType: {
417 SkHalf value = *this->addr16(x, y);
418 return SkColor4f{0.0f, 0.0f, 0.0f, SkHalfToFloat(value)};
419 }
420 case kRGB_565_SkColorType: {
421 SkColor c = SkPixel16ToColor(*this->addr16(x, y));
422 return SkColor4f::FromColor(c);
423 }
424 case kARGB_4444_SkColorType: {
425 uint16_t value = *this->addr16(x, y);
426 SkPMColor c = SkPixel4444ToPixel32(value);
427 return SkColor4f::FromColor(toColor(c));
428 }
429 case kR8G8_unorm_SkColorType: {
430 uint16_t value = *this->addr16(x, y);
431 SkColor c = (uint32_t)(((value >> 0) & 0xff)) << 16 |
432 (uint32_t)(((value >> 8) & 0xff)) << 8 | 0xff000000;
433 return SkColor4f::FromColor(c);
434 }
435 case kR16G16_unorm_SkColorType: {
436 uint32_t value = *this->addr32(x, y);
437 SkColor c = (uint32_t)(((value >> 0) & 0xffff) * (255 / 65535.0f)) << 16 |
438 (uint32_t)(((value >> 16) & 0xffff) * (255 / 65535.0f)) << 8 | 0xff000000;
439 return SkColor4f::FromColor(c);
440 }
441 case kR16G16_float_SkColorType: {
442 uint32_t value = *this->addr32(x, y);
443 float r = SkHalfToFloat((value >> 0) & 0xffff);
444 float g = SkHalfToFloat((value >> 16) & 0xffff);
445 return SkColor4f{r, g, 0.0, 1.0};
446 }
447 case kRGB_888x_SkColorType: {
448 uint32_t value = *this->addr32(x, y);
449 SkColor c = SkSwizzle_RB(value | 0xff000000);
450 return SkColor4f::FromColor(c);
451 }
452 case kBGRA_8888_SkColorType: {
453 uint32_t value = *this->addr32(x, y);
454 SkPMColor c = SkSwizzle_BGRA_to_PMColor(value);
455 return SkColor4f::FromColor(toColor(c));
456 }
457 case kRGBA_8888_SkColorType: {
458 uint32_t value = *this->addr32(x, y);
459 SkPMColor c = SkSwizzle_RGBA_to_PMColor(value);
460 return SkColor4f::FromColor(toColor(c));
461 }
462 case kSRGBA_8888_SkColorType: {
463 auto srgb_to_linear = [](float x) {
464 return (x <= 0.04045f) ? x * (1 / 12.92f)
465 : std::pow(x * (1 / 1.055f) + (0.055f / 1.055f), 2.4f);
466 };
467
468 uint32_t value = *this->addr32(x, y);
469 float r = ((value >> 0) & 0xff) * (1 / 255.0f),
470 g = ((value >> 8) & 0xff) * (1 / 255.0f),
471 b = ((value >> 16) & 0xff) * (1 / 255.0f),
472 a = ((value >> 24) & 0xff) * (1 / 255.0f);
473 r = srgb_to_linear(r);
474 g = srgb_to_linear(g);
475 b = srgb_to_linear(b);
476 if (a != 0 && needsUnpremul) {
477 r = SkTPin(r / a, 0.0f, 1.0f);
478 g = SkTPin(g / a, 0.0f, 1.0f);
479 b = SkTPin(b / a, 0.0f, 1.0f);
480 }
481 return SkColor4f{r, g, b, a};
482 }
483 case kBGR_101010x_XR_SkColorType: {
484 SkASSERT(false);
485 return {};
486 }
487 case kRGB_101010x_SkColorType: {
488 uint32_t value = *this->addr32(x, y);
489 // Convert 10-bit rgb to float rgb, and mask in 0xff alpha at the top.
490 float r = (uint32_t)((value >> 0) & 0x3ff) / (1023.0f);
491 float g = (uint32_t)((value >> 10) & 0x3ff) / (1023.0f);
492 float b = (uint32_t)((value >> 20) & 0x3ff) / (1023.0f);
493 float a = 1.0f;
494 return SkColor4f{r, g, b, a};
495 }
496 case kBGR_101010x_SkColorType: {
497 uint32_t value = *this->addr32(x, y);
498 // Convert 10-bit bgr to float rgb, and mask in 0xff alpha at the top.
499 float r = (uint32_t)((value >> 20) & 0x3ff) / (1023.0f);
500 float g = (uint32_t)((value >> 10) & 0x3ff) / (1023.0f);
501 float b = (uint32_t)((value >> 0) & 0x3ff) / (1023.0f);
502 float a = 1.0f;
503 return SkColor4f{r, g, b, a};
504 }
505 case kRGBA_1010102_SkColorType:
506 case kBGRA_1010102_SkColorType: {
507 uint32_t value = *this->addr32(x, y);
508
509 float r = ((value >> 0) & 0x3ff) * (1 / 1023.0f),
510 g = ((value >> 10) & 0x3ff) * (1 / 1023.0f),
511 b = ((value >> 20) & 0x3ff) * (1 / 1023.0f),
512 a = ((value >> 30) & 0x3) * (1 / 3.0f);
513 if (this->colorType() == kBGRA_1010102_SkColorType) {
514 std::swap(r, b);
515 }
516 if (a != 0 && needsUnpremul) {
517 r = SkTPin(r / a, 0.0f, 1.0f);
518 g = SkTPin(g / a, 0.0f, 1.0f);
519 b = SkTPin(b / a, 0.0f, 1.0f);
520 }
521 return SkColor4f{r, g, b, a};
522 }
523 case kBGRA_10101010_XR_SkColorType: {
524 SkASSERT(false);
525 return {};
526 }
527 case kRGBA_10x6_SkColorType: {
528 uint64_t value = *this->addr64(x, y);
529
530 float r = ((value >> 6) & 0x3ff) * (1/1023.0f),
531 g = ((value >> 22) & 0x3ff) * (1/1023.0f),
532 b = ((value >> 38) & 0x3ff) * (1/1023.0f),
533 a = ((value >> 54) & 0x3ff) * (1/1023.0f);
534 return SkColor4f{r, g, b, a};
535 }
536 case kR16G16B16A16_unorm_SkColorType: {
537 uint64_t value = *this->addr64(x, y);
538
539 float r = ((value)&0xffff) * (1 / 65535.0f),
540 g = ((value >> 16) & 0xffff) * (1 / 65535.0f),
541 b = ((value >> 32) & 0xffff) * (1 / 65535.0f),
542 a = ((value >> 48) & 0xffff) * (1 / 65535.0f);
543 if (a != 0 && needsUnpremul) {
544 r *= (1.0f / a);
545 g *= (1.0f / a);
546 b *= (1.0f / a);
547 }
548 return SkColor4f{r, g, b, a};
549 }
550 case kRGBA_F16Norm_SkColorType:
551 case kRGBA_F16_SkColorType: {
552 const uint64_t* addr = (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x;
553 skvx::float4 p4 = from_half(skvx::half4::Load(addr));
554 if (p4[3] && needsUnpremul) {
555 float inva = 1 / p4[3];
556 p4 = p4 * skvx::float4(inva, inva, inva, 1);
557 }
558 return SkColor4f{p4[0], p4[1], p4[2], p4[3]};
559 }
560 case kRGBA_F32_SkColorType: {
561 const float* rgba = (const float*)fPixels + 4 * y * (fRowBytes >> 4) + 4 * x;
562 skvx::float4 p4 = skvx::float4::Load(rgba);
563 // From here on, just like F16:
564 if (p4[3] && needsUnpremul) {
565 float inva = 1 / p4[3];
566 p4 = p4 * skvx::float4(inva, inva, inva, 1);
567 }
568 return SkColor4f{p4[0], p4[1], p4[2], p4[3]};
569 }
570 case kUnknown_SkColorType:
571 break;
572 }
573 SkDEBUGFAIL("");
574 return SkColors::kTransparent;
575 }
576
computeIsOpaque() const577 bool SkPixmap::computeIsOpaque() const {
578 const int height = this->height();
579 const int width = this->width();
580
581 switch (this->colorType()) {
582 case kAlpha_8_SkColorType: {
583 unsigned a = 0xFF;
584 for (int y = 0; y < height; ++y) {
585 const uint8_t* row = this->addr8(0, y);
586 for (int x = 0; x < width; ++x) {
587 a &= row[x];
588 }
589 if (0xFF != a) {
590 return false;
591 }
592 }
593 return true;
594 }
595 case kA16_unorm_SkColorType: {
596 unsigned a = 0xFFFF;
597 for (int y = 0; y < height; ++y) {
598 const uint16_t* row = this->addr16(0, y);
599 for (int x = 0; x < width; ++x) {
600 a &= row[x];
601 }
602 if (0xFFFF != a) {
603 return false;
604 }
605 }
606 return true;
607 }
608 case kA16_float_SkColorType: {
609 for (int y = 0; y < height; ++y) {
610 const SkHalf* row = this->addr16(0, y);
611 for (int x = 0; x < width; ++x) {
612 if (row[x] < SK_Half1) {
613 return false;
614 }
615 }
616 }
617 return true;
618 }
619 case kRGB_565_SkColorType:
620 case kGray_8_SkColorType:
621 case kR8G8_unorm_SkColorType:
622 case kR16G16_unorm_SkColorType:
623 case kR16G16_float_SkColorType:
624 case kRGB_888x_SkColorType:
625 case kRGB_101010x_SkColorType:
626 case kBGR_101010x_SkColorType:
627 case kBGR_101010x_XR_SkColorType:
628 case kR8_unorm_SkColorType:
629 return true;
630 case kARGB_4444_SkColorType: {
631 unsigned c = 0xFFFF;
632 for (int y = 0; y < height; ++y) {
633 const SkPMColor16* row = this->addr16(0, y);
634 for (int x = 0; x < width; ++x) {
635 c &= row[x];
636 }
637 if (0xF != SkGetPackedA4444(c)) {
638 return false;
639 }
640 }
641 return true;
642 }
643 case kBGRA_8888_SkColorType:
644 case kRGBA_8888_SkColorType:
645 case kSRGBA_8888_SkColorType: {
646 SkPMColor c = (SkPMColor)~0;
647 for (int y = 0; y < height; ++y) {
648 const SkPMColor* row = this->addr32(0, y);
649 for (int x = 0; x < width; ++x) {
650 c &= row[x];
651 }
652 if (0xFF != SkGetPackedA32(c)) {
653 return false;
654 }
655 }
656 return true;
657 }
658 case kRGBA_F16Norm_SkColorType:
659 case kRGBA_F16_SkColorType: {
660 const SkHalf* row = (const SkHalf*)this->addr();
661 for (int y = 0; y < height; ++y) {
662 for (int x = 0; x < width; ++x) {
663 if (row[4 * x + 3] < SK_Half1) {
664 return false;
665 }
666 }
667 row += this->rowBytes() >> 1;
668 }
669 return true;
670 }
671 case kRGBA_F32_SkColorType: {
672 const float* row = (const float*)this->addr();
673 for (int y = 0; y < height; ++y) {
674 for (int x = 0; x < width; ++x) {
675 if (row[4 * x + 3] < 1.0f) {
676 return false;
677 }
678 }
679 row += this->rowBytes() >> 2;
680 }
681 return true;
682 }
683 case kRGBA_1010102_SkColorType:
684 case kBGRA_1010102_SkColorType: {
685 uint32_t c = ~0;
686 for (int y = 0; y < height; ++y) {
687 const uint32_t* row = this->addr32(0, y);
688 for (int x = 0; x < width; ++x) {
689 c &= row[x];
690 }
691 if (0b11 != c >> 30) {
692 return false;
693 }
694 }
695 return true;
696 }
697 case kBGRA_10101010_XR_SkColorType:{
698 static constexpr uint64_t kOne = 510 + 384;
699 for (int y = 0; y < height; ++y) {
700 const uint64_t* row = this->addr64(0, y);
701 for (int x = 0; x < width; ++x) {
702 if ((row[x] >> 54) < kOne) {
703 return false;
704 }
705 }
706 }
707 return true;
708 }
709 case kRGBA_10x6_SkColorType: {
710 uint16_t acc = 0xFFC0; // Ignore bottom six bits
711 for (int y = 0; y < height; ++y) {
712 const uint64_t* row = this->addr64(0, y);
713 for (int x = 0; x < width; ++x) {
714 acc &= (row[x] >> 48);
715 }
716 if (0xFFC0 != acc) {
717 return false;
718 }
719 }
720 return true;
721 }
722 case kR16G16B16A16_unorm_SkColorType: {
723 uint16_t acc = 0xFFFF;
724 for (int y = 0; y < height; ++y) {
725 const uint64_t* row = this->addr64(0, y);
726 for (int x = 0; x < width; ++x) {
727 acc &= (row[x] >> 48);
728 }
729 if (0xFFFF != acc) {
730 return false;
731 }
732 }
733 return true;
734 }
735 case kUnknown_SkColorType:
736 SkDEBUGFAIL("");
737 break;
738 }
739 return false;
740 }
741
erase(SkColor color,const SkIRect & subset) const742 bool SkPixmap::erase(SkColor color, const SkIRect& subset) const {
743 return this->erase(SkColor4f::FromColor(color), &subset);
744 }
745
erase(const SkColor4f & color,const SkIRect * subset) const746 bool SkPixmap::erase(const SkColor4f& color, const SkIRect* subset) const {
747 if (this->colorType() == kUnknown_SkColorType) {
748 return false;
749 }
750
751 SkIRect clip = this->bounds();
752 if (subset && !clip.intersect(*subset)) {
753 return false; // is this check really needed (i.e. to return false in this case?)
754 }
755
756 // Erase is meant to simulate drawing in kSRC mode -- which means we have to convert out
757 // unpremul input into premul (which we always do when we draw).
758 const auto c = color.premul();
759
760 const auto dst = SkImageInfo::Make(1, 1, this->colorType(), this->alphaType(),
761 sk_ref_sp(this->colorSpace()));
762 const auto src = SkImageInfo::Make(1, 1, kRGBA_F32_SkColorType, kPremul_SkAlphaType, nullptr);
763
764 uint64_t dstPixel[2] = {}; // be large enough for our widest config (F32 x 4)
765 SkASSERT((size_t)dst.bytesPerPixel() <= sizeof(dstPixel));
766
767 if (!SkConvertPixels(dst, dstPixel, sizeof(dstPixel), src, &c, sizeof(c))) {
768 return false;
769 }
770
771 if (this->colorType() == kRGBA_F32_SkColorType) {
772 SkColor4f dstColor;
773 memcpy(&dstColor, dstPixel, sizeof(dstColor));
774 for (int y = clip.fTop; y < clip.fBottom; ++y) {
775 SkColor4f* addr = (SkColor4f*)this->writable_addr(clip.fLeft, y);
776 SK_OPTS_NS::memsetT(addr, dstColor, clip.width());
777 }
778 } else {
779 using MemSet = void(*)(void*, uint64_t c, int count);
780 const MemSet procs[] = {
781 [](void* addr, uint64_t c, int count) {
782 SkASSERT(c == (uint8_t)c);
783 SK_OPTS_NS::memsetT((uint8_t*)addr, (uint8_t)c, count);
784 },
785 [](void* addr, uint64_t c, int count) {
786 SkASSERT(c == (uint16_t)c);
787 SK_OPTS_NS::memsetT((uint16_t*)addr, (uint16_t)c, count);
788 },
789 [](void* addr, uint64_t c, int count) {
790 SkASSERT(c == (uint32_t)c);
791 SK_OPTS_NS::memsetT((uint32_t*)addr, (uint32_t)c, count);
792 },
793 [](void* addr, uint64_t c, int count) {
794 SK_OPTS_NS::memsetT((uint64_t*)addr, c, count);
795 },
796 };
797
798 unsigned shift = SkColorTypeShiftPerPixel(this->colorType());
799 SkASSERT(shift < std::size(procs));
800 auto proc = procs[shift];
801
802 for (int y = clip.fTop; y < clip.fBottom; ++y) {
803 proc(this->writable_addr(clip.fLeft, y), dstPixel[0], clip.width());
804 }
805 }
806 return true;
807 }
808