These files appear to have been mis-merged
[platform/upstream/libSkiaSharp.git] / src / core / SkConvertPixels.cpp
1 /*
2  * Copyright 2014 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 "SkColorSpaceXform_Base.h"
9 #include "SkColorSpaceXformPriv.h"
10 #include "SkColorTable.h"
11 #include "SkConvertPixels.h"
12 #include "SkHalf.h"
13 #include "SkImageInfoPriv.h"
14 #include "SkOpts.h"
15 #include "SkPM4fPriv.h"
16 #include "SkRasterPipeline.h"
17 #include "SkUnPreMultiply.h"
18 #include "SkUnPreMultiplyPriv.h"
19 #include "../jumper/SkJumper.h"
20
21 // Fast Path 1: The memcpy() case.
22 static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
23     if (dstInfo.colorType() != srcInfo.colorType()) {
24         return false;
25     }
26
27     if (kAlpha_8_SkColorType == dstInfo.colorType()) {
28         return true;
29     }
30
31     if (dstInfo.alphaType() != srcInfo.alphaType() &&
32         kOpaque_SkAlphaType != dstInfo.alphaType() &&
33         kOpaque_SkAlphaType != srcInfo.alphaType())
34     {
35         // We need to premultiply or unpremultiply.
36         return false;
37     }
38
39     return !dstInfo.colorSpace() ||
40            SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
41 }
42
43 // Fast Path 2: Simple swizzles and premuls.
44 enum AlphaVerb {
45     kNothing_AlphaVerb,
46     kPremul_AlphaVerb,
47     kUnpremul_AlphaVerb,
48 };
49
50 template <bool kSwapRB>
51 static void wrap_unpremultiply(uint32_t* dst, const void* src, int count) {
52     SkUnpremultiplyRow<kSwapRB>(dst, (const uint32_t*) src, count);
53 }
54
55 void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
56                           const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
57     void (*proc)(uint32_t* dst, const void* src, int count);
58     const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
59     AlphaVerb alphaVerb = kNothing_AlphaVerb;
60     if (kPremul_SkAlphaType == dstInfo.alphaType() &&
61         kUnpremul_SkAlphaType == srcInfo.alphaType())
62     {
63         alphaVerb = kPremul_AlphaVerb;
64     } else if (kUnpremul_SkAlphaType == dstInfo.alphaType() &&
65                kPremul_SkAlphaType == srcInfo.alphaType()) {
66         alphaVerb = kUnpremul_AlphaVerb;
67     }
68
69     switch (alphaVerb) {
70         case kNothing_AlphaVerb:
71             // If we do not need to swap or multiply, we should hit the memcpy case.
72             SkASSERT(swapRB);
73             proc = SkOpts::RGBA_to_BGRA;
74             break;
75         case kPremul_AlphaVerb:
76             proc = swapRB ? SkOpts::RGBA_to_bgrA : SkOpts::RGBA_to_rgbA;
77             break;
78         case kUnpremul_AlphaVerb:
79             proc = swapRB ? wrap_unpremultiply<true> : wrap_unpremultiply<false>;
80             break;
81     }
82
83     for (int y = 0; y < dstInfo.height(); y++) {
84         proc((uint32_t*) dstPixels, srcPixels, dstInfo.width());
85         dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
86         srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
87     }
88 }
89
90 // Fast Path 3: Color space xform.
91 static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo,
92                                          SkTransferFunctionBehavior behavior) {
93     // Unpremultiplication is unsupported by SkColorSpaceXform.  Note that if |src| is non-linearly
94     // premultiplied, we're always going to have to unpremultiply before doing anything.
95     if (kPremul_SkAlphaType == srcInfo.alphaType() &&
96             (kUnpremul_SkAlphaType == dstInfo.alphaType() ||
97              SkTransferFunctionBehavior::kIgnore == behavior)) {
98         return false;
99     }
100
101     switch (dstInfo.colorType()) {
102         case kRGBA_8888_SkColorType:
103         case kBGRA_8888_SkColorType:
104         case kRGBA_F16_SkColorType:
105             break;
106         default:
107             return false;
108     }
109
110     switch (srcInfo.colorType()) {
111         case kRGBA_8888_SkColorType:
112         case kBGRA_8888_SkColorType:
113             break;
114         default:
115             return false;
116     }
117
118     return true;
119 }
120
121 static inline void apply_color_xform(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
122                                      const SkImageInfo& srcInfo, const void* srcPixels,
123                                      size_t srcRB, SkTransferFunctionBehavior behavior) {
124     SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
125     SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(srcInfo.colorType());
126     SkAlphaType xformAlpha;
127     switch (srcInfo.alphaType()) {
128         case kOpaque_SkAlphaType:
129             xformAlpha = kOpaque_SkAlphaType;
130             break;
131         case kPremul_SkAlphaType:
132             SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType());
133
134             // This signal means: copy the src alpha to the dst, do not premultiply (in this
135             // case because the pixels are already premultiplied).
136             xformAlpha = kUnpremul_SkAlphaType;
137             break;
138         case kUnpremul_SkAlphaType:
139             SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType() ||
140                      kUnpremul_SkAlphaType == dstInfo.alphaType());
141
142             xformAlpha = dstInfo.alphaType();
143             break;
144         default:
145             SkASSERT(false);
146             xformAlpha = kUnpremul_SkAlphaType;
147             break;
148     }
149
150     std::unique_ptr<SkColorSpaceXform> xform =
151             SkColorSpaceXform_Base::New(srcInfo.colorSpace(), dstInfo.colorSpace(), behavior);
152     SkASSERT(xform);
153
154     for (int y = 0; y < dstInfo.height(); y++) {
155         SkAssertResult(xform->apply(dstFormat, dstPixels, srcFormat, srcPixels, dstInfo.width(),
156                        xformAlpha));
157         dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
158         srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
159     }
160 }
161
162 // Fast Path 4: Index 8 sources.
163 template <typename T>
164 void do_index8(const SkImageInfo& dstInfo, T* dstPixels, size_t dstRB,
165                const SkImageInfo& srcInfo, const uint8_t* srcPixels, size_t srcRB,
166                SkColorTable* ctable, SkTransferFunctionBehavior behavior) {
167     T dstCTable[256];
168     int count = ctable->count();
169     SkImageInfo srcInfo8888 = srcInfo.makeColorType(kN32_SkColorType).makeWH(count, 1);
170     SkImageInfo dstInfoCT = dstInfo.makeWH(count, 1);
171     size_t rowBytes = count * sizeof(T);
172     SkConvertPixels(dstInfoCT, dstCTable, rowBytes, srcInfo8888, ctable->readColors(), rowBytes,
173                     nullptr, behavior);
174
175     for (int y = 0; y < dstInfo.height(); y++) {
176         for (int x = 0; x < dstInfo.width(); x++) {
177             dstPixels[x] = dstCTable[srcPixels[x]];
178         }
179         dstPixels = SkTAddOffset<T>(dstPixels, dstRB);
180         srcPixels = SkTAddOffset<const uint8_t>(srcPixels, srcRB);
181     }
182 }
183
184 void convert_from_index8(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
185                          const SkImageInfo& srcInfo, const uint8_t* srcPixels, size_t srcRB,
186                          SkColorTable* ctable, SkTransferFunctionBehavior behavior) {
187     switch (dstInfo.colorType()) {
188         case kAlpha_8_SkColorType:
189             do_index8(dstInfo, (uint8_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
190                       behavior);
191             break;
192         case kRGB_565_SkColorType:
193         case kARGB_4444_SkColorType:
194             do_index8(dstInfo, (uint16_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
195                       behavior);
196             break;
197         case kRGBA_8888_SkColorType:
198         case kBGRA_8888_SkColorType:
199             do_index8(dstInfo, (uint32_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
200                       behavior);
201             break;
202         case kRGBA_F16_SkColorType:
203             do_index8(dstInfo, (uint64_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
204                       behavior);
205             break;
206         default:
207             SkASSERT(false);
208     }
209 }
210
211 // Fast Path 5: Alpha 8 dsts.
212 static void convert_to_alpha8(uint8_t* dst, size_t dstRB, const SkImageInfo& srcInfo,
213                               const void* src, size_t srcRB, SkColorTable* ctable) {
214     if (srcInfo.isOpaque()) {
215         for (int y = 0; y < srcInfo.height(); ++y) {
216            memset(dst, 0xFF, srcInfo.width());
217            dst = SkTAddOffset<uint8_t>(dst, dstRB);
218         }
219         return;
220     }
221
222     switch (srcInfo.colorType()) {
223         case kBGRA_8888_SkColorType:
224         case kRGBA_8888_SkColorType: {
225             auto src32 = (const uint32_t*) src;
226             for (int y = 0; y < srcInfo.height(); y++) {
227                 for (int x = 0; x < srcInfo.width(); x++) {
228                     dst[x] = src32[x] >> 24;
229                 }
230                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
231                 src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
232             }
233             break;
234         }
235         case kARGB_4444_SkColorType: {
236             auto src16 = (const uint16_t*) src;
237             for (int y = 0; y < srcInfo.height(); y++) {
238                 for (int x = 0; x < srcInfo.width(); x++) {
239                     dst[x] = SkPacked4444ToA32(src16[x]);
240                 }
241                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
242                 src16 = SkTAddOffset<const uint16_t>(src16, srcRB);
243             }
244             break;
245         }
246         case kIndex_8_SkColorType: {
247             SkASSERT(ctable);
248             const uint32_t* table = ctable->readColors();
249             auto src8 = (const uint8_t*)src;
250             for (int y = 0; y < srcInfo.height(); y++) {
251                 for (int x = 0; x < srcInfo.width(); x++) {
252                     dst[x] = table[src8[x]] >> 24;
253                 }
254                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
255                 src8 = SkTAddOffset<const uint8_t>(src8, srcRB);
256             }
257             break;
258         }
259         case kRGBA_F16_SkColorType: {
260             auto src64 = (const uint64_t*) src;
261             for (int y = 0; y < srcInfo.height(); y++) {
262                 for (int x = 0; x < srcInfo.width(); x++) {
263                     dst[x] = (uint8_t) (255.0f * SkHalfToFloat(src64[x] >> 48));
264                 }
265                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
266                 src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
267             }
268             break;
269         }
270         default:
271             SkASSERT(false);
272             break;
273     }
274 }
275
276 // Default: Use the pipeline.
277 static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
278                                   const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
279                                   bool isColorAware, SkTransferFunctionBehavior behavior) {
280     SkRasterPipeline_<256> pipeline;
281     switch (srcInfo.colorType()) {
282         case kRGBA_8888_SkColorType:
283             pipeline.append(SkRasterPipeline::load_8888, &srcRow);
284             break;
285         case kBGRA_8888_SkColorType:
286             pipeline.append(SkRasterPipeline::load_8888, &srcRow);
287             pipeline.append(SkRasterPipeline::swap_rb);
288             break;
289         case kRGB_565_SkColorType:
290             pipeline.append(SkRasterPipeline::load_565, &srcRow);
291             break;
292         case kRGBA_F16_SkColorType:
293             pipeline.append(SkRasterPipeline::load_f16, &srcRow);
294             break;
295         case kGray_8_SkColorType:
296             pipeline.append(SkRasterPipeline::load_g8, &srcRow);
297             break;
298         case kARGB_4444_SkColorType:
299             pipeline.append(SkRasterPipeline::load_4444, &srcRow);
300             break;
301         default:
302             SkASSERT(false);
303             break;
304     }
305
306     SkAlphaType premulState = srcInfo.alphaType();
307     if (kPremul_SkAlphaType == premulState && SkTransferFunctionBehavior::kIgnore == behavior) {
308         pipeline.append(SkRasterPipeline::unpremul);
309         premulState = kUnpremul_SkAlphaType;
310     }
311
312     if (isColorAware && srcInfo.gammaCloseToSRGB()) {
313         pipeline.append_from_srgb(srcInfo.alphaType());
314     } else if (isColorAware && !srcInfo.colorSpace()->gammaIsLinear()) {
315         SkColorSpaceTransferFn fn;
316         SkAssertResult(srcInfo.colorSpace()->isNumericalTransferFn(&fn));
317         pipeline.append(SkRasterPipeline::parametric_r, &fn);
318         pipeline.append(SkRasterPipeline::parametric_g, &fn);
319         pipeline.append(SkRasterPipeline::parametric_b, &fn);
320     }
321
322     float matrix[12];
323     if (isColorAware) {
324         append_gamut_transform(&pipeline, matrix, srcInfo.colorSpace(), dstInfo.colorSpace(),
325                                premulState);
326     }
327
328     SkAlphaType dat = dstInfo.alphaType();
329     if (SkTransferFunctionBehavior::kRespect == behavior) {
330         if (kPremul_SkAlphaType == premulState && kUnpremul_SkAlphaType == dat) {
331             pipeline.append(SkRasterPipeline::unpremul);
332             premulState = kUnpremul_SkAlphaType;
333         } else if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat) {
334             pipeline.append(SkRasterPipeline::premul);
335             premulState = kPremul_SkAlphaType;
336         }
337     }
338
339     if (isColorAware && dstInfo.gammaCloseToSRGB()) {
340         pipeline.append(SkRasterPipeline::to_srgb);
341     } else if (isColorAware && !dstInfo.colorSpace()->gammaIsLinear()) {
342         SkColorSpaceTransferFn fn;
343         SkAssertResult(dstInfo.colorSpace()->isNumericalTransferFn(&fn));
344         fn = fn.invert();
345         pipeline.append(SkRasterPipeline::parametric_r, &fn);
346         pipeline.append(SkRasterPipeline::parametric_g, &fn);
347         pipeline.append(SkRasterPipeline::parametric_b, &fn);
348     }
349
350     if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat &&
351         SkTransferFunctionBehavior::kIgnore == behavior)
352     {
353         pipeline.append(SkRasterPipeline::premul);
354         premulState = kPremul_SkAlphaType;
355     }
356
357     // The final premul state must equal the dst alpha type.  Note that if we are "converting"
358     // opaque to another alpha type, there's no need to worry about multiplication.
359     SkASSERT(premulState == dat || kOpaque_SkAlphaType == srcInfo.alphaType());
360
361     // We'll dither if we're decreasing precision below 32-bit.
362     int y;
363     SkJumper_DitherCtx dither = {&y, 0.0f};
364     if (srcInfo.bytesPerPixel() > dstInfo.bytesPerPixel()) {
365         switch (dstInfo.colorType()) {
366             case   kRGB_565_SkColorType: dither.rate = 1/63.0f; break;
367             case kARGB_4444_SkColorType: dither.rate = 1/15.0f; break;
368             default:                     dither.rate =    0.0f; break;
369         }
370     }
371     if (dither.rate > 0) {
372         pipeline.append(SkRasterPipeline::dither, &dither);
373     }
374
375     switch (dstInfo.colorType()) {
376         case kRGBA_8888_SkColorType:
377             pipeline.append(SkRasterPipeline::store_8888, &dstRow);
378             break;
379         case kBGRA_8888_SkColorType:
380             pipeline.append(SkRasterPipeline::swap_rb);
381             pipeline.append(SkRasterPipeline::store_8888, &dstRow);
382             break;
383         case kRGB_565_SkColorType:
384             pipeline.append(SkRasterPipeline::store_565, &dstRow);
385             break;
386         case kRGBA_F16_SkColorType:
387             pipeline.append(SkRasterPipeline::store_f16, &dstRow);
388             break;
389         case kARGB_4444_SkColorType:
390             pipeline.append(SkRasterPipeline::store_4444, &dstRow);
391             break;
392         default:
393             SkASSERT(false);
394             break;
395     }
396
397     // This y is declared above when handling dither (which needs to know y).
398     for (y = 0; y < srcInfo.height(); ++y) {
399         pipeline.run(0,srcInfo.width());
400         // The pipeline has pointers to srcRow and dstRow, so we just need to update them in the
401         // loop to move between rows of src/dst.
402         dstRow = SkTAddOffset<void>(dstRow, dstRB);
403         srcRow = SkTAddOffset<const void>(srcRow, srcRB);
404     }
405 }
406
407 void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
408                      const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
409                      SkColorTable* ctable, SkTransferFunctionBehavior behavior) {
410     SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
411     SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));
412
413     // Fast Path 1: The memcpy() case.
414     if (can_memcpy(dstInfo, srcInfo)) {
415         SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
416         return;
417     }
418
419     const bool isColorAware = dstInfo.colorSpace();
420     SkASSERT(srcInfo.colorSpace() || !isColorAware);
421
422     // Fast Path 2: Simple swizzles and premuls.
423     if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
424         swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
425         return;
426     }
427
428     // Fast Path 3: Color space xform.
429     if (isColorAware && optimized_color_xform(dstInfo, srcInfo, behavior)) {
430         apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, behavior);
431         return;
432     }
433
434     // Fast Path 4: Index 8 sources.
435     if (kIndex_8_SkColorType == srcInfo.colorType()) {
436         SkASSERT(ctable);
437         convert_from_index8(dstInfo, dstPixels, dstRB, srcInfo, (const uint8_t*) srcPixels, srcRB,
438                             ctable, behavior);
439         return;
440     }
441
442     // Fast Path 5: Alpha 8 dsts.
443     if (kAlpha_8_SkColorType == dstInfo.colorType()) {
444         convert_to_alpha8((uint8_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
445         return;
446     }
447
448     // Default: Use the pipeline.
449     convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware,
450                           behavior);
451 }