SkSwizzler.cpp revision cbb12ca953c8db8030e4e52bb12e2dae98d2692b
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 "SkCodecPriv.h"
9#include "SkColorPriv.h"
10#include "SkSwizzler.h"
11#include "SkTemplates.h"
12#include "SkUtils.h"
13
14SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha,
15                                              uint8_t maxAlpha) {
16    // In the transparent case, this returns 0x0000
17    // In the opaque case, this returns 0xFFFF
18    // If the row is neither transparent nor opaque, returns something else
19    return (((uint16_t) maxAlpha) << 8) | zeroAlpha;
20}
21
22// kBit
23// These routines exclusively choose between white and black
24
25#define GRAYSCALE_BLACK 0
26#define GRAYSCALE_WHITE 0xFF
27
28static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale(
29        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
30        int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) {
31    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
32
33    // Determine how many full bytes are in the row
34    int bytesInRow = width >> 3;
35    int i;
36    for (i = 0; i < bytesInRow; i++) {
37        U8CPU currByte = src[i];
38        for (int j = 0; j < 8; j++) {
39            dst[j] = ((currByte >> (7 - j)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
40        }
41        dst += 8;
42    }
43
44    // Finish the remaining bits
45    width &= 7;
46    if (width > 0) {
47        U8CPU currByte = src[i];
48        for (int j = 0; j < width; j++) {
49            dst[j] = ((currByte >> 7) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
50            currByte <<= 1;
51        }
52    }
53    return SkSwizzler::kOpaque_ResultAlpha;
54}
55
56#undef GRAYSCALE_BLACK
57#undef GRAYSCALE_WHITE
58
59static SkSwizzler::ResultAlpha swizzle_bit_to_index(
60        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
61        int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) {
62    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
63
64    // Determine how many full bytes are in the row
65    int bytesInRow = width >> 3;
66    int i;
67    for (i = 0; i < bytesInRow; i++) {
68        U8CPU currByte = src[i];
69        for (int j = 0; j < 8; j++) {
70            dst[j] = (currByte >> (7 - j)) & 1;
71        }
72        dst += 8;
73    }
74
75    // Finish the remaining bits
76    width &= 7;
77    if (width > 0) {
78        U8CPU currByte = src[i];
79        for (int j = 0; j < width; j++) {
80            dst[j] = ((currByte >> 7) & 1);
81            currByte <<= 1;
82        }
83    }
84    return SkSwizzler::kOpaque_ResultAlpha;
85}
86
87static SkSwizzler::ResultAlpha swizzle_bit_to_n32(
88        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
89        int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) {
90    SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
91
92    // Determine how many full bytes are in the row
93    int bytesInRow = width >> 3;
94    int i;
95    for (i = 0; i < bytesInRow; i++) {
96        U8CPU currByte = src[i];
97        for (int j = 0; j < 8; j++) {
98            dst[j] = ((currByte >> (7 - j)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
99        }
100        dst += 8;
101    }
102
103    // Finish the remaining bits
104    width &= 7;
105    if (width > 0) {
106        U8CPU currByte = src[i];
107        for (int j = 0; j < width; j++) {
108            dst[j] = ((currByte >> 7) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
109            currByte <<= 1;
110        }
111    }
112    return SkSwizzler::kOpaque_ResultAlpha;
113}
114
115// kIndex1, kIndex2, kIndex4
116
117static SkSwizzler::ResultAlpha swizzle_small_index_to_index(
118        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
119        int bitsPerPixel, const SkPMColor ctable[]) {
120
121    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
122    INIT_RESULT_ALPHA;
123    const uint32_t pixelsPerByte = 8 / bitsPerPixel;
124    const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
125    const uint8_t mask = (1 << bitsPerPixel) - 1;
126    int x = 0;
127    for (uint32_t byte = 0; byte < rowBytes; byte++) {
128        uint8_t pixelData = src[byte];
129        for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
130            uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
131            UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
132            dst[x] = index;
133            pixelData <<= bitsPerPixel;
134            x++;
135        }
136    }
137    return COMPUTE_RESULT_ALPHA;
138}
139
140static SkSwizzler::ResultAlpha swizzle_small_index_to_n32(
141        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
142        int bitsPerPixel, const SkPMColor ctable[]) {
143
144    SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
145    INIT_RESULT_ALPHA;
146    const uint32_t pixelsPerByte = 8 / bitsPerPixel;
147    const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
148    const uint8_t mask = (1 << bitsPerPixel) - 1;
149    int x = 0;
150    for (uint32_t byte = 0; byte < rowBytes; byte++) {
151        uint8_t pixelData = src[byte];
152        for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
153            uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
154            SkPMColor c = ctable[index];
155            UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
156            dst[x] = c;
157            pixelData <<= bitsPerPixel;
158            x++;
159        }
160    }
161    return COMPUTE_RESULT_ALPHA;
162}
163
164// kIndex
165
166static SkSwizzler::ResultAlpha swizzle_index_to_index(
167        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
168        int bytesPerPixel, const SkPMColor ctable[]) {
169
170    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
171    memcpy(dst, src, width);
172    // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque?
173    //                 SkScaledBitmap sampler just guesses that it is opaque.  This is dangerous
174    //                 and probably wrong since gif and bmp (rarely) may have alpha.
175    INIT_RESULT_ALPHA;
176    for (int x = 0; x < width; x++) {
177        UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT);
178    }
179    return COMPUTE_RESULT_ALPHA;
180}
181
182static SkSwizzler::ResultAlpha swizzle_index_to_n32(
183        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
184        int bytesPerPixel, const SkPMColor ctable[]) {
185
186    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
187    INIT_RESULT_ALPHA;
188    for (int x = 0; x < width; x++) {
189        SkPMColor c = ctable[src[x]];
190        UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
191        dst[x] = c;
192    }
193    return COMPUTE_RESULT_ALPHA;
194}
195
196static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
197        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
198        int bytesPerPixel, const SkPMColor ctable[]) {
199
200    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
201    INIT_RESULT_ALPHA;
202    for (int x = 0; x < width; x++) {
203        SkPMColor c = ctable[src[x]];
204        UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
205        if (c != 0) {
206            dst[x] = c;
207        }
208    }
209    return COMPUTE_RESULT_ALPHA;
210}
211
212#undef A32_MASK_IN_PLACE
213
214// kGray
215
216static SkSwizzler::ResultAlpha swizzle_gray_to_n32(
217        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
218        int bytesPerPixel, const SkPMColor ctable[]) {
219
220    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
221    for (int x = 0; x < width; x++) {
222        dst[x] = SkPackARGB32NoCheck(0xFF, src[x], src[x], src[x]);
223    }
224    return SkSwizzler::kOpaque_ResultAlpha;
225}
226
227static SkSwizzler::ResultAlpha swizzle_gray_to_gray(
228        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
229        int bytesPerPixel, const SkPMColor ctable[]) {
230    memcpy(dstRow, src, width);
231    return SkSwizzler::kOpaque_ResultAlpha;
232}
233
234// kBGRX
235
236static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
237        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
238        int bytesPerPixel, const SkPMColor ctable[]) {
239
240    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
241    for (int x = 0; x < width; x++) {
242        dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
243        src += bytesPerPixel;
244    }
245    return SkSwizzler::kOpaque_ResultAlpha;
246}
247
248// kBGRA
249
250static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
251        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
252        int bytesPerPixel, const SkPMColor ctable[]) {
253
254    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
255    INIT_RESULT_ALPHA;
256    for (int x = 0; x < width; x++) {
257        uint8_t alpha = src[3];
258        UPDATE_RESULT_ALPHA(alpha);
259        dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
260        src += bytesPerPixel;
261    }
262    return COMPUTE_RESULT_ALPHA;
263}
264
265static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
266        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
267        int bytesPerPixel, const SkPMColor ctable[]) {
268
269    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
270    INIT_RESULT_ALPHA;
271    for (int x = 0; x < width; x++) {
272        uint8_t alpha = src[3];
273        UPDATE_RESULT_ALPHA(alpha);
274        dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]);
275        src += bytesPerPixel;
276    }
277    return COMPUTE_RESULT_ALPHA;
278}
279
280// n32
281static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
282        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
283        int bytesPerPixel, const SkPMColor ctable[]) {
284
285    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
286    for (int x = 0; x < width; x++) {
287        dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
288        src += bytesPerPixel;
289    }
290    return SkSwizzler::kOpaque_ResultAlpha;
291}
292
293static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
294        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
295        int bytesPerPixel, const SkPMColor ctable[]) {
296
297    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
298    INIT_RESULT_ALPHA;
299    for (int x = 0; x < width; x++) {
300        unsigned alpha = src[3];
301        UPDATE_RESULT_ALPHA(alpha);
302        dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
303        src += bytesPerPixel;
304    }
305    return COMPUTE_RESULT_ALPHA;
306}
307
308static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul(
309        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
310        int bytesPerPixel, const SkPMColor ctable[]) {
311
312    uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
313    INIT_RESULT_ALPHA;
314    for (int x = 0; x < width; x++) {
315        unsigned alpha = src[3];
316        UPDATE_RESULT_ALPHA(alpha);
317        dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
318        src += bytesPerPixel;
319    }
320    return COMPUTE_RESULT_ALPHA;
321}
322
323static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ(
324        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
325        int bytesPerPixel, const SkPMColor ctable[]) {
326
327    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
328    INIT_RESULT_ALPHA;
329    for (int x = 0; x < width; x++) {
330        unsigned alpha = src[3];
331        UPDATE_RESULT_ALPHA(alpha);
332        if (0 != alpha) {
333            dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
334        }
335        src += bytesPerPixel;
336    }
337    return COMPUTE_RESULT_ALPHA;
338}
339
340/**
341    FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes.
342    This would be fine for drawing normally, but not for drawing with transfer modes. Being
343    honest means we can draw correctly with transfer modes, with the cost of not being able
344    to take advantage of Android's free unwritten pages. Something to keep in mind when we
345    decide whether to switch to unpremul default.
346static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
347                                               const uint8_t* SK_RESTRICT src,
348                                               int width, int bitsPerPixel,
349                                               const SkPMColor[]) {
350    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
351    unsigned alphaMask = 0xFF;
352    for (int x = 0; x < width; x++) {
353        unsigned alpha = src[3];
354        // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible
355        // the color components are not zero, but we skip them anyway, meaning they'll remain
356        // zero (implied by the request to skip zeroes).
357        if (0 != alpha) {
358            dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
359        }
360        src += deltaSrc;
361        alphaMask &= alpha;
362    }
363    return alphaMask != 0xFF;
364}
365*/
366
367SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
368                                       const SkPMColor* ctable,
369                                       const SkImageInfo& info,
370                                       SkCodec::ZeroInitialized zeroInit) {
371    if (info.colorType() == kUnknown_SkColorType || kUnknown == sc) {
372        return NULL;
373    }
374    if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
375            && NULL == ctable) {
376        return NULL;
377    }
378    RowProc proc = NULL;
379    switch (sc) {
380        case kBit:
381            switch (info.colorType()) {
382                case kN32_SkColorType:
383                    proc = &swizzle_bit_to_n32;
384                    break;
385                case kIndex_8_SkColorType:
386                    proc = &swizzle_bit_to_index;
387                    break;
388                case kGray_8_SkColorType:
389                    proc = &swizzle_bit_to_grayscale;
390                    break;
391                default:
392                    break;
393            }
394            break;
395        case kIndex1:
396        case kIndex2:
397        case kIndex4:
398            switch (info.colorType()) {
399                case kN32_SkColorType:
400                    proc = &swizzle_small_index_to_n32;
401                    break;
402                case kIndex_8_SkColorType:
403                    proc = &swizzle_small_index_to_index;
404                    break;
405                default:
406                    break;
407            }
408            break;
409        case kIndex:
410            switch (info.colorType()) {
411                case kN32_SkColorType:
412                    // We assume the color premultiplied ctable (or not) as desired.
413                    if (SkCodec::kYes_ZeroInitialized == zeroInit) {
414                        proc = &swizzle_index_to_n32_skipZ;
415                        break;
416                    } else {
417                        proc = &swizzle_index_to_n32;
418                        break;
419                    }
420                    break;
421                case kIndex_8_SkColorType:
422                    proc = &swizzle_index_to_index;
423                    break;
424                default:
425                    break;
426            }
427            break;
428        case kGray:
429            switch (info.colorType()) {
430                case kN32_SkColorType:
431                    proc = &swizzle_gray_to_n32;
432                    break;
433                case kGray_8_SkColorType:
434                    proc = &swizzle_gray_to_gray;
435                default:
436                    break;
437            }
438            break;
439        case kBGR:
440        case kBGRX:
441            switch (info.colorType()) {
442                case kN32_SkColorType:
443                    proc = &swizzle_bgrx_to_n32;
444                    break;
445                default:
446                    break;
447            }
448            break;
449        case kBGRA:
450            switch (info.colorType()) {
451                case kN32_SkColorType:
452                    switch (info.alphaType()) {
453                        case kUnpremul_SkAlphaType:
454                            proc = &swizzle_bgra_to_n32_unpremul;
455                            break;
456                        case kPremul_SkAlphaType:
457                            proc = &swizzle_bgra_to_n32_premul;
458                            break;
459                        default:
460                            break;
461                    }
462                    break;
463                default:
464                    break;
465            }
466            break;
467        case kRGBX:
468            // TODO: Support other swizzles.
469            switch (info.colorType()) {
470                case kN32_SkColorType:
471                    proc = &swizzle_rgbx_to_n32;
472                    break;
473                default:
474                    break;
475            }
476            break;
477        case kRGBA:
478            switch (info.colorType()) {
479                case kN32_SkColorType:
480                    if (info.alphaType() == kUnpremul_SkAlphaType) {
481                        // Respect zeroInit?
482                        proc = &swizzle_rgba_to_n32_unpremul;
483                    } else {
484                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
485                            proc = &swizzle_rgba_to_n32_premul_skipZ;
486                        } else {
487                            proc = &swizzle_rgba_to_n32_premul;
488                        }
489                    }
490                    break;
491                default:
492                    break;
493            }
494            break;
495        case kRGB:
496            switch (info.colorType()) {
497                case kN32_SkColorType:
498                    proc = &swizzle_rgbx_to_n32;
499                    break;
500                default:
501                    break;
502            }
503            break;
504        default:
505            break;
506    }
507    if (NULL == proc) {
508        return NULL;
509    }
510
511    // Store deltaSrc in bytes if it is an even multiple, otherwise use bits
512    int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) :
513            BitsPerPixel(sc);
514    return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, info));
515}
516
517SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable,
518                       int deltaSrc, const SkImageInfo& info)
519    : fRowProc(proc)
520    , fColorTable(ctable)
521    , fDeltaSrc(deltaSrc)
522    , fDstInfo(info)
523{}
524
525SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
526    SkASSERT(NULL != dst && NULL != src);
527    return fRowProc(dst, src, fDstInfo.width(), fDeltaSrc, fColorTable);
528}
529
530void SkSwizzler::Fill(void* dstStartRow, const SkImageInfo& dstInfo, size_t dstRowBytes,
531        uint32_t numRows, uint32_t colorOrIndex, const SkPMColor* colorTable) {
532    SkASSERT(dstStartRow != NULL);
533    SkASSERT(numRows <= (uint32_t) dstInfo.height());
534
535    // Calculate bytes to fill.  We use getSafeSize since the last row may not be padded.
536    const size_t bytesToFill = dstInfo.makeWH(dstInfo.width(), numRows).getSafeSize(dstRowBytes);
537
538    // Use the proper memset routine to fill the remaining bytes
539    switch(dstInfo.colorType()) {
540        case kN32_SkColorType:
541            // Assume input is an index if we have a color table
542            uint32_t color;
543            if (NULL != colorTable) {
544                SkASSERT(colorOrIndex == (uint8_t) colorOrIndex);
545                color = colorTable[colorOrIndex];
546            // Otherwise, assume the input is a color
547            } else {
548                color = colorOrIndex;
549            }
550
551            // We must fill row by row in the case of unaligned row bytes
552            if (SkIsAlign4((size_t) dstStartRow) && SkIsAlign4(dstRowBytes)) {
553                sk_memset32((uint32_t*) dstStartRow, color,
554                        (uint32_t) bytesToFill / sizeof(SkPMColor));
555            } else {
556                // This is an unlikely, slow case
557                SkCodecPrintf("Warning: Strange number of row bytes, fill will be slow.\n");
558                uint32_t* dstRow = (uint32_t*) dstStartRow;
559                for (uint32_t row = 0; row < numRows; row++) {
560                    for (int32_t col = 0; col < dstInfo.width(); col++) {
561                        dstRow[col] = color;
562                    }
563                    dstRow = SkTAddOffset<uint32_t>(dstRow, dstRowBytes);
564                }
565            }
566            break;
567        // On an index destination color type, always assume the input is an index
568        case kIndex_8_SkColorType:
569            SkASSERT(colorOrIndex == (uint8_t) colorOrIndex);
570            memset(dstStartRow, colorOrIndex, bytesToFill);
571            break;
572        case kGray_8_SkColorType:
573            // If the destination is kGray, the caller passes in an 8-bit color.
574            // We will not assert that the high bits of colorOrIndex must be zeroed.
575            // This allows us to take advantage of the fact that the low 8 bits of an
576            // SKPMColor may be a valid a grayscale color.  For example, the low 8
577            // bits of SK_ColorBLACK are identical to the grayscale representation
578            // for black.
579            memset(dstStartRow, (uint8_t) colorOrIndex, bytesToFill);
580            break;
581        case kRGB_565_SkColorType:
582            // If the destination is k565, the caller passes in a 16-bit color.
583            // We will not assert that the high bits of colorOrIndex must be zeroed.
584            // This allows us to take advantage of the fact that the low 16 bits of an
585            // SKPMColor may be a valid a 565 color.  For example, the low 16
586            // bits of SK_ColorBLACK are identical to the 565 representation
587            // for black.
588            memset(dstStartRow, (uint16_t) colorOrIndex, bytesToFill);
589            break;
590        default:
591            SkCodecPrintf("Error: Unsupported dst color type for fill().  Doing nothing.\n");
592            SkASSERT(false);
593            break;
594    }
595}
596