1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h"
6 
7 #include <memory>
8 
9 #include "base/compiler_specific.h"
10 #include "base/numerics/checked_math.h"
11 #include "build/build_config.h"
12 #include "third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h"
13 #include "third_party/blink/renderer/platform/graphics/cpu/mips/webgl_image_conversion_msa.h"
14 #include "third_party/blink/renderer/platform/graphics/cpu/x86/webgl_image_conversion_sse.h"
15 #include "third_party/blink/renderer/platform/graphics/image_observer.h"
16 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
17 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
18 #include "third_party/skia/include/core/SkImage.h"
19 
20 namespace blink {
21 
22 namespace {
23 
24 const float kMaxInt8Value = INT8_MAX;
25 const float kMaxUInt8Value = UINT8_MAX;
26 const float kMaxInt16Value = INT16_MAX;
27 const float kMaxUInt16Value = UINT16_MAX;
28 const double kMaxInt32Value = INT32_MAX;
29 const double kMaxUInt32Value = UINT32_MAX;
30 
ClampMin(int8_t value)31 int8_t ClampMin(int8_t value) {
32   const static int8_t kMinInt8Value = INT8_MIN + 1;
33   return value < kMinInt8Value ? kMinInt8Value : value;
34 }
35 
ClampMin(int16_t value)36 int16_t ClampMin(int16_t value) {
37   const static int16_t kMinInt16Value = INT16_MIN + 1;
38   return value < kMinInt16Value ? kMinInt16Value : value;
39 }
40 
ClampMin(int32_t value)41 int32_t ClampMin(int32_t value) {
42   const static int32_t kMinInt32Value = INT32_MIN + 1;
43   return value < kMinInt32Value ? kMinInt32Value : value;
44 }
45 
46 // Return kDataFormatNumFormats if format/type combination is invalid.
GetDataFormat(GLenum destination_format,GLenum destination_type)47 WebGLImageConversion::DataFormat GetDataFormat(GLenum destination_format,
48                                                GLenum destination_type) {
49   WebGLImageConversion::DataFormat dst_format =
50       WebGLImageConversion::kDataFormatRGBA8;
51   switch (destination_type) {
52     case GL_BYTE:
53       switch (destination_format) {
54         case GL_RED:
55         case GL_RED_INTEGER:
56           dst_format = WebGLImageConversion::kDataFormatR8_S;
57           break;
58         case GL_RG:
59         case GL_RG_INTEGER:
60           dst_format = WebGLImageConversion::kDataFormatRG8_S;
61           break;
62         case GL_RGB:
63         case GL_RGB_INTEGER:
64           dst_format = WebGLImageConversion::kDataFormatRGB8_S;
65           break;
66         case GL_RGBA:
67         case GL_RGBA_INTEGER:
68           dst_format = WebGLImageConversion::kDataFormatRGBA8_S;
69           break;
70         default:
71           return WebGLImageConversion::kDataFormatNumFormats;
72       }
73       break;
74     case GL_UNSIGNED_BYTE:
75       switch (destination_format) {
76         case GL_RGB:
77         case GL_RGB_INTEGER:
78         case GL_SRGB_EXT:
79           dst_format = WebGLImageConversion::kDataFormatRGB8;
80           break;
81         case GL_RGBA:
82         case GL_RGBA_INTEGER:
83         case GL_SRGB_ALPHA_EXT:
84           dst_format = WebGLImageConversion::kDataFormatRGBA8;
85           break;
86         case GL_ALPHA:
87           dst_format = WebGLImageConversion::kDataFormatA8;
88           break;
89         case GL_LUMINANCE:
90         case GL_RED:
91         case GL_RED_INTEGER:
92           dst_format = WebGLImageConversion::kDataFormatR8;
93           break;
94         case GL_RG:
95         case GL_RG_INTEGER:
96           dst_format = WebGLImageConversion::kDataFormatRG8;
97           break;
98         case GL_LUMINANCE_ALPHA:
99           dst_format = WebGLImageConversion::kDataFormatRA8;
100           break;
101         default:
102           return WebGLImageConversion::kDataFormatNumFormats;
103       }
104       break;
105     case GL_SHORT:
106       switch (destination_format) {
107         case GL_RED_INTEGER:
108           dst_format = WebGLImageConversion::kDataFormatR16_S;
109           break;
110         case GL_RG_INTEGER:
111           dst_format = WebGLImageConversion::kDataFormatRG16_S;
112           break;
113         case GL_RGB_INTEGER:
114           dst_format = WebGLImageConversion::kDataFormatRGB16_S;
115           break;
116         case GL_RGBA_INTEGER:
117           dst_format = WebGLImageConversion::kDataFormatRGBA16_S;
118           break;
119         default:
120           return WebGLImageConversion::kDataFormatNumFormats;
121       }
122       break;
123     case GL_UNSIGNED_SHORT:
124       switch (destination_format) {
125         case GL_RED_INTEGER:
126           dst_format = WebGLImageConversion::kDataFormatR16;
127           break;
128         case GL_DEPTH_COMPONENT:
129           dst_format = WebGLImageConversion::kDataFormatD16;
130           break;
131         case GL_RG_INTEGER:
132           dst_format = WebGLImageConversion::kDataFormatRG16;
133           break;
134         case GL_RGB_INTEGER:
135           dst_format = WebGLImageConversion::kDataFormatRGB16;
136           break;
137         case GL_RGBA_INTEGER:
138           dst_format = WebGLImageConversion::kDataFormatRGBA16;
139           break;
140         default:
141           return WebGLImageConversion::kDataFormatNumFormats;
142       }
143       break;
144     case GL_INT:
145       switch (destination_format) {
146         case GL_RED_INTEGER:
147           dst_format = WebGLImageConversion::kDataFormatR32_S;
148           break;
149         case GL_RG_INTEGER:
150           dst_format = WebGLImageConversion::kDataFormatRG32_S;
151           break;
152         case GL_RGB_INTEGER:
153           dst_format = WebGLImageConversion::kDataFormatRGB32_S;
154           break;
155         case GL_RGBA_INTEGER:
156           dst_format = WebGLImageConversion::kDataFormatRGBA32_S;
157           break;
158         default:
159           return WebGLImageConversion::kDataFormatNumFormats;
160       }
161       break;
162     case GL_UNSIGNED_INT:
163       switch (destination_format) {
164         case GL_RED_INTEGER:
165           dst_format = WebGLImageConversion::kDataFormatR32;
166           break;
167         case GL_DEPTH_COMPONENT:
168           dst_format = WebGLImageConversion::kDataFormatD32;
169           break;
170         case GL_RG_INTEGER:
171           dst_format = WebGLImageConversion::kDataFormatRG32;
172           break;
173         case GL_RGB_INTEGER:
174           dst_format = WebGLImageConversion::kDataFormatRGB32;
175           break;
176         case GL_RGBA_INTEGER:
177           dst_format = WebGLImageConversion::kDataFormatRGBA32;
178           break;
179         default:
180           return WebGLImageConversion::kDataFormatNumFormats;
181       }
182       break;
183     case GL_HALF_FLOAT_OES:  // OES_texture_half_float
184     case GL_HALF_FLOAT:
185       switch (destination_format) {
186         case GL_RGBA:
187           dst_format = WebGLImageConversion::kDataFormatRGBA16F;
188           break;
189         case GL_RGB:
190           dst_format = WebGLImageConversion::kDataFormatRGB16F;
191           break;
192         case GL_RG:
193           dst_format = WebGLImageConversion::kDataFormatRG16F;
194           break;
195         case GL_ALPHA:
196           dst_format = WebGLImageConversion::kDataFormatA16F;
197           break;
198         case GL_LUMINANCE:
199         case GL_RED:
200           dst_format = WebGLImageConversion::kDataFormatR16F;
201           break;
202         case GL_LUMINANCE_ALPHA:
203           dst_format = WebGLImageConversion::kDataFormatRA16F;
204           break;
205         default:
206           return WebGLImageConversion::kDataFormatNumFormats;
207       }
208       break;
209     case GL_FLOAT:  // OES_texture_float
210       switch (destination_format) {
211         case GL_RGBA:
212           dst_format = WebGLImageConversion::kDataFormatRGBA32F;
213           break;
214         case GL_RGB:
215           dst_format = WebGLImageConversion::kDataFormatRGB32F;
216           break;
217         case GL_RG:
218           dst_format = WebGLImageConversion::kDataFormatRG32F;
219           break;
220         case GL_ALPHA:
221           dst_format = WebGLImageConversion::kDataFormatA32F;
222           break;
223         case GL_LUMINANCE:
224         case GL_RED:
225           dst_format = WebGLImageConversion::kDataFormatR32F;
226           break;
227         case GL_DEPTH_COMPONENT:
228           dst_format = WebGLImageConversion::kDataFormatD32F;
229           break;
230         case GL_LUMINANCE_ALPHA:
231           dst_format = WebGLImageConversion::kDataFormatRA32F;
232           break;
233         default:
234           return WebGLImageConversion::kDataFormatNumFormats;
235       }
236       break;
237     case GL_UNSIGNED_SHORT_4_4_4_4:
238       dst_format = WebGLImageConversion::kDataFormatRGBA4444;
239       break;
240     case GL_UNSIGNED_SHORT_5_5_5_1:
241       dst_format = WebGLImageConversion::kDataFormatRGBA5551;
242       break;
243     case GL_UNSIGNED_SHORT_5_6_5:
244       dst_format = WebGLImageConversion::kDataFormatRGB565;
245       break;
246     case GL_UNSIGNED_INT_5_9_9_9_REV:
247       dst_format = WebGLImageConversion::kDataFormatRGB5999;
248       break;
249     case GL_UNSIGNED_INT_24_8:
250       dst_format = WebGLImageConversion::kDataFormatDS24_8;
251       break;
252     case GL_UNSIGNED_INT_10F_11F_11F_REV:
253       dst_format = WebGLImageConversion::kDataFormatRGB10F11F11F;
254       break;
255     case GL_UNSIGNED_INT_2_10_10_10_REV:
256       dst_format = WebGLImageConversion::kDataFormatRGBA2_10_10_10;
257       break;
258     default:
259       return WebGLImageConversion::kDataFormatNumFormats;
260   }
261   return dst_format;
262 }
263 
264 // The following Float to Half-Float conversion code is from the implementation
265 // of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf, "Fast Half
266 // Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September
267 // 2010). Specially, the basetable[512] and shifttable[512] are generated as
268 // follows:
269 /*
270 unsigned short basetable[512];
271 unsigned char shifttable[512];
272 
273 void generatetables(){
274     unsigned int i;
275     int e;
276     for (i = 0; i < 256; ++i){
277         e = i - 127;
278         if (e < -24){ // Very small numbers map to zero
279             basetable[i | 0x000] = 0x0000;
280             basetable[i | 0x100] = 0x8000;
281             shifttable[i | 0x000] = 24;
282             shifttable[i | 0x100] = 24;
283         }
284         else if (e < -14) { // Small numbers map to denorms
285             basetable[i | 0x000] = (0x0400>>(-e-14));
286             basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000;
287             shifttable[i | 0x000] = -e-1;
288             shifttable[i | 0x100] = -e-1;
289         }
290         else if (e <= 15){ // Normal numbers just lose precision
291             basetable[i | 0x000] = ((e+15)<<10);
292             basetable[i| 0x100] = ((e+15)<<10) | 0x8000;
293             shifttable[i|0x000] = 13;
294             shifttable[i|0x100] = 13;
295         }
296         else if (e<128){ // Large numbers map to Infinity
297             basetable[i|0x000] = 0x7C00;
298             basetable[i|0x100] = 0xFC00;
299             shifttable[i|0x000] = 24;
300             shifttable[i|0x100] = 24;
301         }
302         else { // Infinity and NaN's stay Infinity and NaN's
303             basetable[i|0x000] = 0x7C00;
304             basetable[i|0x100] = 0xFC00;
305             shifttable[i|0x000] = 13;
306             shifttable[i|0x100] = 13;
307        }
308     }
309 }
310 */
311 
312 uint16_t g_base_table[512] = {
313     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
314     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
315     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
316     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
317     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
318     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
319     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
320     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
321     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
322     0,     0,     0,     0,     1,     2,     4,     8,     16,    32,    64,
323     128,   256,   512,   1024,  2048,  3072,  4096,  5120,  6144,  7168,  8192,
324     9216,  10240, 11264, 12288, 13312, 14336, 15360, 16384, 17408, 18432, 19456,
325     20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720,
326     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
327     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
328     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
329     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
330     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
331     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
332     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
333     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
334     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
335     31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
336     31744, 31744, 31744, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
337     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
338     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
339     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
340     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
341     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
342     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
343     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
344     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
345     32768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776,
346     32784, 32800, 32832, 32896, 33024, 33280, 33792, 34816, 35840, 36864, 37888,
347     38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, 49152,
348     50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416,
349     61440, 62464, 63488, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
350     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
351     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
352     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
353     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
354     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
355     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
356     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
357     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
358     64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
359     64512, 64512, 64512, 64512, 64512, 64512};
360 
361 unsigned char g_shift_table[512] = {
362     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
363     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
364     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
365     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
366     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
367     24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,
368     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
369     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24,
370     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
371     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
372     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
373     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
374     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
375     24, 24, 24, 24, 24, 24, 24, 24, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
376     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
377     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
378     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
379     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
380     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22,
381     21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
382     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
383     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
384     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
385     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
386     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
387     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
388     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13};
389 
ConvertFloatToHalfFloat(float f)390 uint16_t ConvertFloatToHalfFloat(float f) {
391   unsigned temp = *(reinterpret_cast<unsigned*>(&f));
392   uint16_t signexp = (temp >> 23) & 0x1ff;
393   return g_base_table[signexp] +
394          ((temp & 0x007fffff) >> g_shift_table[signexp]);
395 }
396 
397 /* BEGIN CODE SHARED WITH MOZILLA FIREFOX */
398 
399 // The following packing and unpacking routines are expressed in terms of
400 // function templates and inline functions to achieve generality and speedup.
401 // Explicit template specializations correspond to the cases that would occur.
402 // Some code are merged back from Mozilla code in
403 // http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h
404 
405 //----------------------------------------------------------------------
406 // Pixel unpacking routines.
407 template <int format, typename SourceType, typename DstType>
Unpack(const SourceType *,DstType *,unsigned)408 void Unpack(const SourceType*, DstType*, unsigned) {
409   NOTREACHED();
410 }
411 
412 template <>
Unpack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)413 void Unpack<WebGLImageConversion::kDataFormatARGB8, uint8_t, uint8_t>(
414     const uint8_t* source,
415     uint8_t* destination,
416     unsigned pixels_per_row) {
417   for (unsigned i = 0; i < pixels_per_row; ++i) {
418     destination[0] = source[1];
419     destination[1] = source[2];
420     destination[2] = source[3];
421     destination[3] = source[0];
422     source += 4;
423     destination += 4;
424   }
425 }
426 
427 template <>
Unpack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)428 void Unpack<WebGLImageConversion::kDataFormatABGR8, uint8_t, uint8_t>(
429     const uint8_t* source,
430     uint8_t* destination,
431     unsigned pixels_per_row) {
432   for (unsigned i = 0; i < pixels_per_row; ++i) {
433     destination[0] = source[3];
434     destination[1] = source[2];
435     destination[2] = source[1];
436     destination[3] = source[0];
437     source += 4;
438     destination += 4;
439   }
440 }
441 
442 template <>
Unpack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)443 void Unpack<WebGLImageConversion::kDataFormatBGRA8, uint8_t, uint8_t>(
444     const uint8_t* source,
445     uint8_t* destination,
446     unsigned pixels_per_row) {
447   const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
448   uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
449 
450 #if defined(ARCH_CPU_X86_FAMILY)
451   simd::UnpackOneRowOfBGRA8LittleToRGBA8(source32, destination32,
452                                          pixels_per_row);
453 #endif
454 #if defined(HAVE_MIPS_MSA_INTRINSICS)
455   simd::unpackOneRowOfBGRA8LittleToRGBA8MSA(source32, destination32,
456                                             pixels_per_row);
457 #endif
458   for (unsigned i = 0; i < pixels_per_row; ++i) {
459     uint32_t bgra = source32[i];
460 #if defined(ARCH_CPU_BIG_ENDIAN)
461     uint32_t br_mask = 0xff00ff00;
462     uint32_t ga_mask = 0x00ff00ff;
463 #else
464     uint32_t br_mask = 0x00ff00ff;
465     uint32_t ga_mask = 0xff00ff00;
466 #endif
467     uint32_t rgba =
468         (((bgra >> 16) | (bgra << 16)) & br_mask) | (bgra & ga_mask);
469     destination32[i] = rgba;
470   }
471 }
472 
473 template <>
Unpack(const uint16_t * source,uint8_t * destination,unsigned pixels_per_row)474 void Unpack<WebGLImageConversion::kDataFormatRGBA5551, uint16_t, uint8_t>(
475     const uint16_t* source,
476     uint8_t* destination,
477     unsigned pixels_per_row) {
478 #if defined(ARCH_CPU_X86_FAMILY)
479   simd::UnpackOneRowOfRGBA5551LittleToRGBA8(source, destination,
480                                             pixels_per_row);
481 #endif
482 #if defined(CPU_ARM_NEON)
483   simd::UnpackOneRowOfRGBA5551ToRGBA8(source, destination, pixels_per_row);
484 #endif
485 #if defined(HAVE_MIPS_MSA_INTRINSICS)
486   simd::unpackOneRowOfRGBA5551ToRGBA8MSA(source, destination, pixels_per_row);
487 #endif
488 
489   for (unsigned i = 0; i < pixels_per_row; ++i) {
490     uint16_t packed_value = source[0];
491     uint8_t r = packed_value >> 11;
492     uint8_t g = (packed_value >> 6) & 0x1F;
493     uint8_t b = (packed_value >> 1) & 0x1F;
494     destination[0] = (r << 3) | (r & 0x7);
495     destination[1] = (g << 3) | (g & 0x7);
496     destination[2] = (b << 3) | (b & 0x7);
497     destination[3] = (packed_value & 0x1) ? 0xFF : 0x0;
498     source += 1;
499     destination += 4;
500   }
501 }
502 
503 template <>
Unpack(const uint16_t * source,uint8_t * destination,unsigned pixels_per_row)504 void Unpack<WebGLImageConversion::kDataFormatRGBA4444, uint16_t, uint8_t>(
505     const uint16_t* source,
506     uint8_t* destination,
507     unsigned pixels_per_row) {
508 #if defined(ARCH_CPU_X86_FAMILY)
509   simd::UnpackOneRowOfRGBA4444LittleToRGBA8(source, destination,
510                                             pixels_per_row);
511 #endif
512 #if defined(CPU_ARM_NEON)
513   simd::UnpackOneRowOfRGBA4444ToRGBA8(source, destination, pixels_per_row);
514 #endif
515 #if defined(HAVE_MIPS_MSA_INTRINSICS)
516   simd::unpackOneRowOfRGBA4444ToRGBA8MSA(source, destination, pixels_per_row);
517 #endif
518   for (unsigned i = 0; i < pixels_per_row; ++i) {
519     uint16_t packed_value = source[0];
520     uint8_t r = packed_value >> 12;
521     uint8_t g = (packed_value >> 8) & 0x0F;
522     uint8_t b = (packed_value >> 4) & 0x0F;
523     uint8_t a = packed_value & 0x0F;
524     destination[0] = r << 4 | r;
525     destination[1] = g << 4 | g;
526     destination[2] = b << 4 | b;
527     destination[3] = a << 4 | a;
528     source += 1;
529     destination += 4;
530   }
531 }
532 
533 template <>
Unpack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)534 void Unpack<WebGLImageConversion::kDataFormatRA8, uint8_t, uint8_t>(
535     const uint8_t* source,
536     uint8_t* destination,
537     unsigned pixels_per_row) {
538   for (unsigned i = 0; i < pixels_per_row; ++i) {
539     destination[0] = source[0];
540     destination[1] = source[0];
541     destination[2] = source[0];
542     destination[3] = source[1];
543     source += 2;
544     destination += 4;
545   }
546 }
547 
548 template <>
Unpack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)549 void Unpack<WebGLImageConversion::kDataFormatAR8, uint8_t, uint8_t>(
550     const uint8_t* source,
551     uint8_t* destination,
552     unsigned pixels_per_row) {
553   for (unsigned i = 0; i < pixels_per_row; ++i) {
554     destination[0] = source[1];
555     destination[1] = source[1];
556     destination[2] = source[1];
557     destination[3] = source[0];
558     source += 2;
559     destination += 4;
560   }
561 }
562 
563 template <>
Unpack(const uint8_t * source,float * destination,unsigned pixels_per_row)564 void Unpack<WebGLImageConversion::kDataFormatRGBA8, uint8_t, float>(
565     const uint8_t* source,
566     float* destination,
567     unsigned pixels_per_row) {
568   const float kScaleFactor = 1.0f / 255.0f;
569   for (unsigned i = 0; i < pixels_per_row; ++i) {
570     destination[0] = source[0] * kScaleFactor;
571     destination[1] = source[1] * kScaleFactor;
572     destination[2] = source[2] * kScaleFactor;
573     destination[3] = source[3] * kScaleFactor;
574     source += 4;
575     destination += 4;
576   }
577 }
578 
579 template <>
Unpack(const uint8_t * source,float * destination,unsigned pixels_per_row)580 void Unpack<WebGLImageConversion::kDataFormatBGRA8, uint8_t, float>(
581     const uint8_t* source,
582     float* destination,
583     unsigned pixels_per_row) {
584   const float kScaleFactor = 1.0f / 255.0f;
585   for (unsigned i = 0; i < pixels_per_row; ++i) {
586     destination[0] = source[2] * kScaleFactor;
587     destination[1] = source[1] * kScaleFactor;
588     destination[2] = source[0] * kScaleFactor;
589     destination[3] = source[3] * kScaleFactor;
590     source += 4;
591     destination += 4;
592   }
593 }
594 
595 template <>
Unpack(const uint8_t * source,float * destination,unsigned pixels_per_row)596 void Unpack<WebGLImageConversion::kDataFormatABGR8, uint8_t, float>(
597     const uint8_t* source,
598     float* destination,
599     unsigned pixels_per_row) {
600   const float kScaleFactor = 1.0f / 255.0f;
601   for (unsigned i = 0; i < pixels_per_row; ++i) {
602     destination[0] = source[3] * kScaleFactor;
603     destination[1] = source[2] * kScaleFactor;
604     destination[2] = source[1] * kScaleFactor;
605     destination[3] = source[0] * kScaleFactor;
606     source += 4;
607     destination += 4;
608   }
609 }
610 
611 template <>
Unpack(const uint8_t * source,float * destination,unsigned pixels_per_row)612 void Unpack<WebGLImageConversion::kDataFormatARGB8, uint8_t, float>(
613     const uint8_t* source,
614     float* destination,
615     unsigned pixels_per_row) {
616   const float kScaleFactor = 1.0f / 255.0f;
617   for (unsigned i = 0; i < pixels_per_row; ++i) {
618     destination[0] = source[1] * kScaleFactor;
619     destination[1] = source[2] * kScaleFactor;
620     destination[2] = source[3] * kScaleFactor;
621     destination[3] = source[0] * kScaleFactor;
622     source += 4;
623     destination += 4;
624   }
625 }
626 
627 template <>
Unpack(const float * source,float * destination,unsigned pixels_per_row)628 void Unpack<WebGLImageConversion::kDataFormatRA32F, float, float>(
629     const float* source,
630     float* destination,
631     unsigned pixels_per_row) {
632   for (unsigned i = 0; i < pixels_per_row; ++i) {
633     destination[0] = source[0];
634     destination[1] = source[0];
635     destination[2] = source[0];
636     destination[3] = source[1];
637     source += 2;
638     destination += 4;
639   }
640 }
641 
642 template <>
Unpack(const uint32_t * source,float * destination,unsigned pixels_per_row)643 void Unpack<WebGLImageConversion::kDataFormatRGBA2_10_10_10, uint32_t, float>(
644     const uint32_t* source,
645     float* destination,
646     unsigned pixels_per_row) {
647   static const float kRgbScaleFactor = 1.0f / 1023.0f;
648   static const float kAlphaScaleFactor = 1.0f / 3.0f;
649   for (unsigned i = 0; i < pixels_per_row; ++i) {
650     uint32_t packed_value = source[0];
651     destination[0] = static_cast<float>(packed_value & 0x3FF) * kRgbScaleFactor;
652     destination[1] =
653         static_cast<float>((packed_value >> 10) & 0x3FF) * kRgbScaleFactor;
654     destination[2] =
655         static_cast<float>((packed_value >> 20) & 0x3FF) * kRgbScaleFactor;
656     destination[3] = static_cast<float>(packed_value >> 30) * kAlphaScaleFactor;
657     source += 1;
658     destination += 4;
659   }
660 }
661 
662 //----------------------------------------------------------------------
663 // Pixel packing routines.
664 //
665 
666 template <int format, int alphaOp, typename SourceType, typename DstType>
Pack(const SourceType *,DstType *,unsigned)667 void Pack(const SourceType*, DstType*, unsigned) {
668   NOTREACHED();
669 }
670 
671 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)672 void Pack<WebGLImageConversion::kDataFormatA8,
673           WebGLImageConversion::kAlphaDoNothing,
674           uint8_t,
675           uint8_t>(const uint8_t* source,
676                    uint8_t* destination,
677                    unsigned pixels_per_row) {
678   for (unsigned i = 0; i < pixels_per_row; ++i) {
679     destination[0] = source[3];
680     source += 4;
681     destination += 1;
682   }
683 }
684 
685 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)686 void Pack<WebGLImageConversion::kDataFormatR8,
687           WebGLImageConversion::kAlphaDoNothing,
688           uint8_t,
689           uint8_t>(const uint8_t* source,
690                    uint8_t* destination,
691                    unsigned pixels_per_row) {
692   for (unsigned i = 0; i < pixels_per_row; ++i) {
693     destination[0] = source[0];
694     source += 4;
695     destination += 1;
696   }
697 }
698 
699 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)700 void Pack<WebGLImageConversion::kDataFormatR8,
701           WebGLImageConversion::kAlphaDoPremultiply,
702           uint8_t,
703           uint8_t>(const uint8_t* source,
704                    uint8_t* destination,
705                    unsigned pixels_per_row) {
706   for (unsigned i = 0; i < pixels_per_row; ++i) {
707     float scale_factor = source[3] / 255.0f;
708     uint8_t source_r =
709         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
710     destination[0] = source_r;
711     source += 4;
712     destination += 1;
713   }
714 }
715 
716 // FIXME: this routine is lossy and must be removed.
717 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)718 void Pack<WebGLImageConversion::kDataFormatR8,
719           WebGLImageConversion::kAlphaDoUnmultiply,
720           uint8_t,
721           uint8_t>(const uint8_t* source,
722                    uint8_t* destination,
723                    unsigned pixels_per_row) {
724 #if defined(ARCH_CPU_X86_FAMILY)
725   simd::PackOneRowOfRGBA8LittleToR8(source, destination, pixels_per_row);
726 #endif
727 #if defined(HAVE_MIPS_MSA_INTRINSICS)
728   simd::packOneRowOfRGBA8LittleToR8MSA(source, destination, pixels_per_row);
729 #endif
730   for (unsigned i = 0; i < pixels_per_row; ++i) {
731     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
732     uint8_t source_r =
733         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
734     destination[0] = source_r;
735     source += 4;
736     destination += 1;
737   }
738 }
739 
740 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)741 void Pack<WebGLImageConversion::kDataFormatRA8,
742           WebGLImageConversion::kAlphaDoNothing,
743           uint8_t,
744           uint8_t>(const uint8_t* source,
745                    uint8_t* destination,
746                    unsigned pixels_per_row) {
747   for (unsigned i = 0; i < pixels_per_row; ++i) {
748     destination[0] = source[0];
749     destination[1] = source[3];
750     source += 4;
751     destination += 2;
752   }
753 }
754 
755 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)756 void Pack<WebGLImageConversion::kDataFormatRA8,
757           WebGLImageConversion::kAlphaDoPremultiply,
758           uint8_t,
759           uint8_t>(const uint8_t* source,
760                    uint8_t* destination,
761                    unsigned pixels_per_row) {
762   for (unsigned i = 0; i < pixels_per_row; ++i) {
763     float scale_factor = source[3] / 255.0f;
764     uint8_t source_r =
765         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
766     destination[0] = source_r;
767     destination[1] = source[3];
768     source += 4;
769     destination += 2;
770   }
771 }
772 
773 // FIXME: this routine is lossy and must be removed.
774 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)775 void Pack<WebGLImageConversion::kDataFormatRA8,
776           WebGLImageConversion::kAlphaDoUnmultiply,
777           uint8_t,
778           uint8_t>(const uint8_t* source,
779                    uint8_t* destination,
780                    unsigned pixels_per_row) {
781 #if defined(ARCH_CPU_X86_FAMILY)
782   simd::PackOneRowOfRGBA8LittleToRA8(source, destination, pixels_per_row);
783 #endif
784 #if defined(HAVE_MIPS_MSA_INTRINSICS)
785   simd::packOneRowOfRGBA8LittleToRA8MSA(source, destination, pixels_per_row);
786 #endif
787   for (unsigned i = 0; i < pixels_per_row; ++i) {
788     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
789     uint8_t source_r =
790         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
791     destination[0] = source_r;
792     destination[1] = source[3];
793     source += 4;
794     destination += 2;
795   }
796 }
797 
798 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)799 void Pack<WebGLImageConversion::kDataFormatRGB8,
800           WebGLImageConversion::kAlphaDoNothing,
801           uint8_t,
802           uint8_t>(const uint8_t* source,
803                    uint8_t* destination,
804                    unsigned pixels_per_row) {
805   for (unsigned i = 0; i < pixels_per_row; ++i) {
806     destination[0] = source[0];
807     destination[1] = source[1];
808     destination[2] = source[2];
809     source += 4;
810     destination += 3;
811   }
812 }
813 
814 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)815 void Pack<WebGLImageConversion::kDataFormatRGB8,
816           WebGLImageConversion::kAlphaDoPremultiply,
817           uint8_t,
818           uint8_t>(const uint8_t* source,
819                    uint8_t* destination,
820                    unsigned pixels_per_row) {
821   for (unsigned i = 0; i < pixels_per_row; ++i) {
822     float scale_factor = source[3] / 255.0f;
823     uint8_t source_r =
824         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
825     uint8_t source_g =
826         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
827     uint8_t source_b =
828         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
829     destination[0] = source_r;
830     destination[1] = source_g;
831     destination[2] = source_b;
832     source += 4;
833     destination += 3;
834   }
835 }
836 
837 // FIXME: this routine is lossy and must be removed.
838 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)839 void Pack<WebGLImageConversion::kDataFormatRGB8,
840           WebGLImageConversion::kAlphaDoUnmultiply,
841           uint8_t,
842           uint8_t>(const uint8_t* source,
843                    uint8_t* destination,
844                    unsigned pixels_per_row) {
845   for (unsigned i = 0; i < pixels_per_row; ++i) {
846     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
847     uint8_t source_r =
848         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
849     uint8_t source_g =
850         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
851     uint8_t source_b =
852         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
853     destination[0] = source_r;
854     destination[1] = source_g;
855     destination[2] = source_b;
856     source += 4;
857     destination += 3;
858   }
859 }
860 
861 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)862 void Pack<WebGLImageConversion::kDataFormatRGBA8,
863           WebGLImageConversion::kAlphaDoPremultiply,
864           uint8_t,
865           uint8_t>(const uint8_t* source,
866                    uint8_t* destination,
867                    unsigned pixels_per_row) {
868   for (unsigned i = 0; i < pixels_per_row; ++i) {
869     float scale_factor = source[3] / 255.0f;
870     uint8_t source_r =
871         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
872     uint8_t source_g =
873         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
874     uint8_t source_b =
875         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
876     destination[0] = source_r;
877     destination[1] = source_g;
878     destination[2] = source_b;
879     destination[3] = source[3];
880     source += 4;
881     destination += 4;
882   }
883 }
884 
885 // FIXME: this routine is lossy and must be removed.
886 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)887 void Pack<WebGLImageConversion::kDataFormatRGBA8,
888           WebGLImageConversion::kAlphaDoUnmultiply,
889           uint8_t,
890           uint8_t>(const uint8_t* source,
891                    uint8_t* destination,
892                    unsigned pixels_per_row) {
893 #if defined(ARCH_CPU_X86_FAMILY)
894   simd::PackOneRowOfRGBA8LittleToRGBA8(source, destination, pixels_per_row);
895 #endif
896 #if defined(HAVE_MIPS_MSA_INTRINSICS)
897   simd::packOneRowOfRGBA8LittleToRGBA8MSA(source, destination, pixels_per_row);
898 #endif
899   for (unsigned i = 0; i < pixels_per_row; ++i) {
900     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
901     uint8_t source_r =
902         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
903     uint8_t source_g =
904         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
905     uint8_t source_b =
906         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
907     destination[0] = source_r;
908     destination[1] = source_g;
909     destination[2] = source_b;
910     destination[3] = source[3];
911     source += 4;
912     destination += 4;
913   }
914 }
915 
916 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)917 void Pack<WebGLImageConversion::kDataFormatRGBA4444,
918           WebGLImageConversion::kAlphaDoNothing,
919           uint8_t,
920           uint16_t>(const uint8_t* source,
921                     uint16_t* destination,
922                     unsigned pixels_per_row) {
923 #if defined(CPU_ARM_NEON)
924   simd::PackOneRowOfRGBA8ToUnsignedShort4444(source, destination,
925                                              pixels_per_row);
926 #endif
927 #if defined(HAVE_MIPS_MSA_INTRINSICS)
928   simd::packOneRowOfRGBA8ToUnsignedShort4444MSA(source, destination,
929                                                 pixels_per_row);
930 #endif
931   for (unsigned i = 0; i < pixels_per_row; ++i) {
932     *destination = (((source[0] & 0xF0) << 8) | ((source[1] & 0xF0) << 4) |
933                     (source[2] & 0xF0) | (source[3] >> 4));
934     source += 4;
935     destination += 1;
936   }
937 }
938 
939 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)940 void Pack<WebGLImageConversion::kDataFormatRGBA4444,
941           WebGLImageConversion::kAlphaDoPremultiply,
942           uint8_t,
943           uint16_t>(const uint8_t* source,
944                     uint16_t* destination,
945                     unsigned pixels_per_row) {
946   for (unsigned i = 0; i < pixels_per_row; ++i) {
947     float scale_factor = source[3] / 255.0f;
948     uint8_t source_r =
949         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
950     uint8_t source_g =
951         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
952     uint8_t source_b =
953         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
954     *destination = (((source_r & 0xF0) << 8) | ((source_g & 0xF0) << 4) |
955                     (source_b & 0xF0) | (source[3] >> 4));
956     source += 4;
957     destination += 1;
958   }
959 }
960 
961 // FIXME: this routine is lossy and must be removed.
962 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)963 void Pack<WebGLImageConversion::kDataFormatRGBA4444,
964           WebGLImageConversion::kAlphaDoUnmultiply,
965           uint8_t,
966           uint16_t>(const uint8_t* source,
967                     uint16_t* destination,
968                     unsigned pixels_per_row) {
969   for (unsigned i = 0; i < pixels_per_row; ++i) {
970     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
971     uint8_t source_r =
972         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
973     uint8_t source_g =
974         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
975     uint8_t source_b =
976         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
977     *destination = (((source_r & 0xF0) << 8) | ((source_g & 0xF0) << 4) |
978                     (source_b & 0xF0) | (source[3] >> 4));
979     source += 4;
980     destination += 1;
981   }
982 }
983 
984 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)985 void Pack<WebGLImageConversion::kDataFormatRGBA5551,
986           WebGLImageConversion::kAlphaDoNothing,
987           uint8_t,
988           uint16_t>(const uint8_t* source,
989                     uint16_t* destination,
990                     unsigned pixels_per_row) {
991 #if defined(CPU_ARM_NEON)
992   simd::PackOneRowOfRGBA8ToUnsignedShort5551(source, destination,
993                                              pixels_per_row);
994 #endif
995 #if defined(HAVE_MIPS_MSA_INTRINSICS)
996   simd::packOneRowOfRGBA8ToUnsignedShort5551MSA(source, destination,
997                                                 pixels_per_row);
998 #endif
999   for (unsigned i = 0; i < pixels_per_row; ++i) {
1000     *destination = (((source[0] & 0xF8) << 8) | ((source[1] & 0xF8) << 3) |
1001                     ((source[2] & 0xF8) >> 2) | (source[3] >> 7));
1002     source += 4;
1003     destination += 1;
1004   }
1005 }
1006 
1007 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)1008 void Pack<WebGLImageConversion::kDataFormatRGBA5551,
1009           WebGLImageConversion::kAlphaDoPremultiply,
1010           uint8_t,
1011           uint16_t>(const uint8_t* source,
1012                     uint16_t* destination,
1013                     unsigned pixels_per_row) {
1014   for (unsigned i = 0; i < pixels_per_row; ++i) {
1015     float scale_factor = source[3] / 255.0f;
1016     uint8_t source_r =
1017         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
1018     uint8_t source_g =
1019         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
1020     uint8_t source_b =
1021         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
1022     *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xF8) << 3) |
1023                     ((source_b & 0xF8) >> 2) | (source[3] >> 7));
1024     source += 4;
1025     destination += 1;
1026   }
1027 }
1028 
1029 // FIXME: this routine is lossy and must be removed.
1030 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)1031 void Pack<WebGLImageConversion::kDataFormatRGBA5551,
1032           WebGLImageConversion::kAlphaDoUnmultiply,
1033           uint8_t,
1034           uint16_t>(const uint8_t* source,
1035                     uint16_t* destination,
1036                     unsigned pixels_per_row) {
1037   for (unsigned i = 0; i < pixels_per_row; ++i) {
1038     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
1039     uint8_t source_r =
1040         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
1041     uint8_t source_g =
1042         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
1043     uint8_t source_b =
1044         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
1045     *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xF8) << 3) |
1046                     ((source_b & 0xF8) >> 2) | (source[3] >> 7));
1047     source += 4;
1048     destination += 1;
1049   }
1050 }
1051 
1052 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)1053 void Pack<WebGLImageConversion::kDataFormatRGB565,
1054           WebGLImageConversion::kAlphaDoNothing,
1055           uint8_t,
1056           uint16_t>(const uint8_t* source,
1057                     uint16_t* destination,
1058                     unsigned pixels_per_row) {
1059 #if defined(CPU_ARM_NEON)
1060   simd::PackOneRowOfRGBA8ToUnsignedShort565(source, destination,
1061                                             pixels_per_row);
1062 #endif
1063 #if defined(HAVE_MIPS_MSA_INTRINSICS)
1064   simd::packOneRowOfRGBA8ToUnsignedShort565MSA(source, destination,
1065                                                pixels_per_row);
1066 #endif
1067   for (unsigned i = 0; i < pixels_per_row; ++i) {
1068     *destination = (((source[0] & 0xF8) << 8) | ((source[1] & 0xFC) << 3) |
1069                     ((source[2] & 0xF8) >> 3));
1070     source += 4;
1071     destination += 1;
1072   }
1073 }
1074 
1075 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)1076 void Pack<WebGLImageConversion::kDataFormatRGB565,
1077           WebGLImageConversion::kAlphaDoPremultiply,
1078           uint8_t,
1079           uint16_t>(const uint8_t* source,
1080                     uint16_t* destination,
1081                     unsigned pixels_per_row) {
1082   for (unsigned i = 0; i < pixels_per_row; ++i) {
1083     float scale_factor = source[3] / 255.0f;
1084     uint8_t source_r =
1085         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
1086     uint8_t source_g =
1087         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
1088     uint8_t source_b =
1089         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
1090     *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xFC) << 3) |
1091                     ((source_b & 0xF8) >> 3));
1092     source += 4;
1093     destination += 1;
1094   }
1095 }
1096 
1097 // FIXME: this routine is lossy and must be removed.
1098 template <>
Pack(const uint8_t * source,uint16_t * destination,unsigned pixels_per_row)1099 void Pack<WebGLImageConversion::kDataFormatRGB565,
1100           WebGLImageConversion::kAlphaDoUnmultiply,
1101           uint8_t,
1102           uint16_t>(const uint8_t* source,
1103                     uint16_t* destination,
1104                     unsigned pixels_per_row) {
1105   for (unsigned i = 0; i < pixels_per_row; ++i) {
1106     float scale_factor = source[3] ? 255.0f / source[3] : 1.0f;
1107     uint8_t source_r =
1108         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
1109     uint8_t source_g =
1110         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
1111     uint8_t source_b =
1112         static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor);
1113     *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xFC) << 3) |
1114                     ((source_b & 0xF8) >> 3));
1115     source += 4;
1116     destination += 1;
1117   }
1118 }
1119 
1120 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1121 void Pack<WebGLImageConversion::kDataFormatRGB32F,
1122           WebGLImageConversion::kAlphaDoNothing,
1123           float,
1124           float>(const float* source,
1125                  float* destination,
1126                  unsigned pixels_per_row) {
1127   for (unsigned i = 0; i < pixels_per_row; ++i) {
1128     destination[0] = source[0];
1129     destination[1] = source[1];
1130     destination[2] = source[2];
1131     source += 4;
1132     destination += 3;
1133   }
1134 }
1135 
1136 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1137 void Pack<WebGLImageConversion::kDataFormatRGB32F,
1138           WebGLImageConversion::kAlphaDoPremultiply,
1139           float,
1140           float>(const float* source,
1141                  float* destination,
1142                  unsigned pixels_per_row) {
1143   for (unsigned i = 0; i < pixels_per_row; ++i) {
1144     float scale_factor = source[3];
1145     destination[0] = source[0] * scale_factor;
1146     destination[1] = source[1] * scale_factor;
1147     destination[2] = source[2] * scale_factor;
1148     source += 4;
1149     destination += 3;
1150   }
1151 }
1152 
1153 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1154 void Pack<WebGLImageConversion::kDataFormatRGB32F,
1155           WebGLImageConversion::kAlphaDoUnmultiply,
1156           float,
1157           float>(const float* source,
1158                  float* destination,
1159                  unsigned pixels_per_row) {
1160   for (unsigned i = 0; i < pixels_per_row; ++i) {
1161     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1162     destination[0] = source[0] * scale_factor;
1163     destination[1] = source[1] * scale_factor;
1164     destination[2] = source[2] * scale_factor;
1165     source += 4;
1166     destination += 3;
1167   }
1168 }
1169 
1170 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1171 void Pack<WebGLImageConversion::kDataFormatRGBA32F,
1172           WebGLImageConversion::kAlphaDoPremultiply,
1173           float,
1174           float>(const float* source,
1175                  float* destination,
1176                  unsigned pixels_per_row) {
1177   for (unsigned i = 0; i < pixels_per_row; ++i) {
1178     float scale_factor = source[3];
1179     destination[0] = source[0] * scale_factor;
1180     destination[1] = source[1] * scale_factor;
1181     destination[2] = source[2] * scale_factor;
1182     destination[3] = source[3];
1183     source += 4;
1184     destination += 4;
1185   }
1186 }
1187 
1188 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1189 void Pack<WebGLImageConversion::kDataFormatRGBA32F,
1190           WebGLImageConversion::kAlphaDoUnmultiply,
1191           float,
1192           float>(const float* source,
1193                  float* destination,
1194                  unsigned pixels_per_row) {
1195   for (unsigned i = 0; i < pixels_per_row; ++i) {
1196     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1197     destination[0] = source[0] * scale_factor;
1198     destination[1] = source[1] * scale_factor;
1199     destination[2] = source[2] * scale_factor;
1200     destination[3] = source[3];
1201     source += 4;
1202     destination += 4;
1203   }
1204 }
1205 
1206 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1207 void Pack<WebGLImageConversion::kDataFormatA32F,
1208           WebGLImageConversion::kAlphaDoNothing,
1209           float,
1210           float>(const float* source,
1211                  float* destination,
1212                  unsigned pixels_per_row) {
1213   for (unsigned i = 0; i < pixels_per_row; ++i) {
1214     destination[0] = source[3];
1215     source += 4;
1216     destination += 1;
1217   }
1218 }
1219 
1220 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1221 void Pack<WebGLImageConversion::kDataFormatR32F,
1222           WebGLImageConversion::kAlphaDoNothing,
1223           float,
1224           float>(const float* source,
1225                  float* destination,
1226                  unsigned pixels_per_row) {
1227   for (unsigned i = 0; i < pixels_per_row; ++i) {
1228     destination[0] = source[0];
1229     source += 4;
1230     destination += 1;
1231   }
1232 }
1233 
1234 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1235 void Pack<WebGLImageConversion::kDataFormatR32F,
1236           WebGLImageConversion::kAlphaDoPremultiply,
1237           float,
1238           float>(const float* source,
1239                  float* destination,
1240                  unsigned pixels_per_row) {
1241   for (unsigned i = 0; i < pixels_per_row; ++i) {
1242     float scale_factor = source[3];
1243     destination[0] = source[0] * scale_factor;
1244     source += 4;
1245     destination += 1;
1246   }
1247 }
1248 
1249 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1250 void Pack<WebGLImageConversion::kDataFormatR32F,
1251           WebGLImageConversion::kAlphaDoUnmultiply,
1252           float,
1253           float>(const float* source,
1254                  float* destination,
1255                  unsigned pixels_per_row) {
1256   for (unsigned i = 0; i < pixels_per_row; ++i) {
1257     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1258     destination[0] = source[0] * scale_factor;
1259     source += 4;
1260     destination += 1;
1261   }
1262 }
1263 
1264 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1265 void Pack<WebGLImageConversion::kDataFormatRA32F,
1266           WebGLImageConversion::kAlphaDoNothing,
1267           float,
1268           float>(const float* source,
1269                  float* destination,
1270                  unsigned pixels_per_row) {
1271   for (unsigned i = 0; i < pixels_per_row; ++i) {
1272     destination[0] = source[0];
1273     destination[1] = source[3];
1274     source += 4;
1275     destination += 2;
1276   }
1277 }
1278 
1279 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1280 void Pack<WebGLImageConversion::kDataFormatRA32F,
1281           WebGLImageConversion::kAlphaDoPremultiply,
1282           float,
1283           float>(const float* source,
1284                  float* destination,
1285                  unsigned pixels_per_row) {
1286   for (unsigned i = 0; i < pixels_per_row; ++i) {
1287     float scale_factor = source[3];
1288     destination[0] = source[0] * scale_factor;
1289     destination[1] = source[3];
1290     source += 4;
1291     destination += 2;
1292   }
1293 }
1294 
1295 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1296 void Pack<WebGLImageConversion::kDataFormatRA32F,
1297           WebGLImageConversion::kAlphaDoUnmultiply,
1298           float,
1299           float>(const float* source,
1300                  float* destination,
1301                  unsigned pixels_per_row) {
1302   for (unsigned i = 0; i < pixels_per_row; ++i) {
1303     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1304     destination[0] = source[0] * scale_factor;
1305     destination[1] = source[3];
1306     source += 4;
1307     destination += 2;
1308   }
1309 }
1310 
1311 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1312 void Pack<WebGLImageConversion::kDataFormatRGBA16F,
1313           WebGLImageConversion::kAlphaDoNothing,
1314           float,
1315           uint16_t>(const float* source,
1316                     uint16_t* destination,
1317                     unsigned pixels_per_row) {
1318   for (unsigned i = 0; i < pixels_per_row; ++i) {
1319     destination[0] = ConvertFloatToHalfFloat(source[0]);
1320     destination[1] = ConvertFloatToHalfFloat(source[1]);
1321     destination[2] = ConvertFloatToHalfFloat(source[2]);
1322     destination[3] = ConvertFloatToHalfFloat(source[3]);
1323     source += 4;
1324     destination += 4;
1325   }
1326 }
1327 
1328 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1329 void Pack<WebGLImageConversion::kDataFormatRGBA16F,
1330           WebGLImageConversion::kAlphaDoPremultiply,
1331           float,
1332           uint16_t>(const float* source,
1333                     uint16_t* destination,
1334                     unsigned pixels_per_row) {
1335   for (unsigned i = 0; i < pixels_per_row; ++i) {
1336     float scale_factor = source[3];
1337     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1338     destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor);
1339     destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor);
1340     destination[3] = ConvertFloatToHalfFloat(source[3]);
1341     source += 4;
1342     destination += 4;
1343   }
1344 }
1345 
1346 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1347 void Pack<WebGLImageConversion::kDataFormatRGBA16F,
1348           WebGLImageConversion::kAlphaDoUnmultiply,
1349           float,
1350           uint16_t>(const float* source,
1351                     uint16_t* destination,
1352                     unsigned pixels_per_row) {
1353   for (unsigned i = 0; i < pixels_per_row; ++i) {
1354     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1355     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1356     destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor);
1357     destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor);
1358     destination[3] = ConvertFloatToHalfFloat(source[3]);
1359     source += 4;
1360     destination += 4;
1361   }
1362 }
1363 
1364 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1365 void Pack<WebGLImageConversion::kDataFormatRGB16F,
1366           WebGLImageConversion::kAlphaDoNothing,
1367           float,
1368           uint16_t>(const float* source,
1369                     uint16_t* destination,
1370                     unsigned pixels_per_row) {
1371   for (unsigned i = 0; i < pixels_per_row; ++i) {
1372     destination[0] = ConvertFloatToHalfFloat(source[0]);
1373     destination[1] = ConvertFloatToHalfFloat(source[1]);
1374     destination[2] = ConvertFloatToHalfFloat(source[2]);
1375     source += 4;
1376     destination += 3;
1377   }
1378 }
1379 
1380 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1381 void Pack<WebGLImageConversion::kDataFormatRGB16F,
1382           WebGLImageConversion::kAlphaDoPremultiply,
1383           float,
1384           uint16_t>(const float* source,
1385                     uint16_t* destination,
1386                     unsigned pixels_per_row) {
1387   for (unsigned i = 0; i < pixels_per_row; ++i) {
1388     float scale_factor = source[3];
1389     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1390     destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor);
1391     destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor);
1392     source += 4;
1393     destination += 3;
1394   }
1395 }
1396 
1397 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1398 void Pack<WebGLImageConversion::kDataFormatRGB16F,
1399           WebGLImageConversion::kAlphaDoUnmultiply,
1400           float,
1401           uint16_t>(const float* source,
1402                     uint16_t* destination,
1403                     unsigned pixels_per_row) {
1404   for (unsigned i = 0; i < pixels_per_row; ++i) {
1405     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1406     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1407     destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor);
1408     destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor);
1409     source += 4;
1410     destination += 3;
1411   }
1412 }
1413 
1414 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1415 void Pack<WebGLImageConversion::kDataFormatRA16F,
1416           WebGLImageConversion::kAlphaDoNothing,
1417           float,
1418           uint16_t>(const float* source,
1419                     uint16_t* destination,
1420                     unsigned pixels_per_row) {
1421   for (unsigned i = 0; i < pixels_per_row; ++i) {
1422     destination[0] = ConvertFloatToHalfFloat(source[0]);
1423     destination[1] = ConvertFloatToHalfFloat(source[3]);
1424     source += 4;
1425     destination += 2;
1426   }
1427 }
1428 
1429 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1430 void Pack<WebGLImageConversion::kDataFormatRA16F,
1431           WebGLImageConversion::kAlphaDoPremultiply,
1432           float,
1433           uint16_t>(const float* source,
1434                     uint16_t* destination,
1435                     unsigned pixels_per_row) {
1436   for (unsigned i = 0; i < pixels_per_row; ++i) {
1437     float scale_factor = source[3];
1438     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1439     destination[1] = ConvertFloatToHalfFloat(source[3]);
1440     source += 4;
1441     destination += 2;
1442   }
1443 }
1444 
1445 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1446 void Pack<WebGLImageConversion::kDataFormatRA16F,
1447           WebGLImageConversion::kAlphaDoUnmultiply,
1448           float,
1449           uint16_t>(const float* source,
1450                     uint16_t* destination,
1451                     unsigned pixels_per_row) {
1452   for (unsigned i = 0; i < pixels_per_row; ++i) {
1453     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1454     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1455     destination[1] = ConvertFloatToHalfFloat(source[3]);
1456     source += 4;
1457     destination += 2;
1458   }
1459 }
1460 
1461 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1462 void Pack<WebGLImageConversion::kDataFormatR16F,
1463           WebGLImageConversion::kAlphaDoNothing,
1464           float,
1465           uint16_t>(const float* source,
1466                     uint16_t* destination,
1467                     unsigned pixels_per_row) {
1468   for (unsigned i = 0; i < pixels_per_row; ++i) {
1469     destination[0] = ConvertFloatToHalfFloat(source[0]);
1470     source += 4;
1471     destination += 1;
1472   }
1473 }
1474 
1475 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1476 void Pack<WebGLImageConversion::kDataFormatR16F,
1477           WebGLImageConversion::kAlphaDoPremultiply,
1478           float,
1479           uint16_t>(const float* source,
1480                     uint16_t* destination,
1481                     unsigned pixels_per_row) {
1482   for (unsigned i = 0; i < pixels_per_row; ++i) {
1483     float scale_factor = source[3];
1484     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1485     source += 4;
1486     destination += 1;
1487   }
1488 }
1489 
1490 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1491 void Pack<WebGLImageConversion::kDataFormatR16F,
1492           WebGLImageConversion::kAlphaDoUnmultiply,
1493           float,
1494           uint16_t>(const float* source,
1495                     uint16_t* destination,
1496                     unsigned pixels_per_row) {
1497   for (unsigned i = 0; i < pixels_per_row; ++i) {
1498     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1499     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1500     source += 4;
1501     destination += 1;
1502   }
1503 }
1504 
1505 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1506 void Pack<WebGLImageConversion::kDataFormatA16F,
1507           WebGLImageConversion::kAlphaDoNothing,
1508           float,
1509           uint16_t>(const float* source,
1510                     uint16_t* destination,
1511                     unsigned pixels_per_row) {
1512   for (unsigned i = 0; i < pixels_per_row; ++i) {
1513     destination[0] = ConvertFloatToHalfFloat(source[3]);
1514     source += 4;
1515     destination += 1;
1516   }
1517 }
1518 
1519 template <>
Pack(const int8_t * source,int8_t * destination,unsigned pixels_per_row)1520 void Pack<WebGLImageConversion::kDataFormatRGBA8_S,
1521           WebGLImageConversion::kAlphaDoPremultiply,
1522           int8_t,
1523           int8_t>(const int8_t* source,
1524                   int8_t* destination,
1525                   unsigned pixels_per_row) {
1526   for (unsigned i = 0; i < pixels_per_row; ++i) {
1527     destination[3] = ClampMin(source[3]);
1528     float scale_factor = static_cast<float>(destination[3]) / kMaxInt8Value;
1529     destination[0] = static_cast<int8_t>(
1530         static_cast<float>(ClampMin(source[0])) * scale_factor);
1531     destination[1] = static_cast<int8_t>(
1532         static_cast<float>(ClampMin(source[1])) * scale_factor);
1533     destination[2] = static_cast<int8_t>(
1534         static_cast<float>(ClampMin(source[2])) * scale_factor);
1535     source += 4;
1536     destination += 4;
1537   }
1538 }
1539 
1540 template <>
Pack(const uint16_t * source,uint16_t * destination,unsigned pixels_per_row)1541 void Pack<WebGLImageConversion::kDataFormatRGBA16,
1542           WebGLImageConversion::kAlphaDoPremultiply,
1543           uint16_t,
1544           uint16_t>(const uint16_t* source,
1545                     uint16_t* destination,
1546                     unsigned pixels_per_row) {
1547   for (unsigned i = 0; i < pixels_per_row; ++i) {
1548     float scale_factor = static_cast<float>(source[3]) / kMaxUInt16Value;
1549     destination[0] =
1550         static_cast<uint16_t>(static_cast<float>(source[0]) * scale_factor);
1551     destination[1] =
1552         static_cast<uint16_t>(static_cast<float>(source[1]) * scale_factor);
1553     destination[2] =
1554         static_cast<uint16_t>(static_cast<float>(source[2]) * scale_factor);
1555     destination[3] = source[3];
1556     source += 4;
1557     destination += 4;
1558   }
1559 }
1560 
1561 template <>
Pack(const int16_t * source,int16_t * destination,unsigned pixels_per_row)1562 void Pack<WebGLImageConversion::kDataFormatRGBA16_S,
1563           WebGLImageConversion::kAlphaDoPremultiply,
1564           int16_t,
1565           int16_t>(const int16_t* source,
1566                    int16_t* destination,
1567                    unsigned pixels_per_row) {
1568   for (unsigned i = 0; i < pixels_per_row; ++i) {
1569     destination[3] = ClampMin(source[3]);
1570     float scale_factor = static_cast<float>(destination[3]) / kMaxInt16Value;
1571     destination[0] = static_cast<int16_t>(
1572         static_cast<float>(ClampMin(source[0])) * scale_factor);
1573     destination[1] = static_cast<int16_t>(
1574         static_cast<float>(ClampMin(source[1])) * scale_factor);
1575     destination[2] = static_cast<int16_t>(
1576         static_cast<float>(ClampMin(source[2])) * scale_factor);
1577     source += 4;
1578     destination += 4;
1579   }
1580 }
1581 
1582 template <>
Pack(const uint32_t * source,uint32_t * destination,unsigned pixels_per_row)1583 void Pack<WebGLImageConversion::kDataFormatRGBA32,
1584           WebGLImageConversion::kAlphaDoPremultiply,
1585           uint32_t,
1586           uint32_t>(const uint32_t* source,
1587                     uint32_t* destination,
1588                     unsigned pixels_per_row) {
1589   for (unsigned i = 0; i < pixels_per_row; ++i) {
1590     double scale_factor = static_cast<double>(source[3]) / kMaxUInt32Value;
1591     destination[0] =
1592         static_cast<uint32_t>(static_cast<double>(source[0]) * scale_factor);
1593     destination[1] =
1594         static_cast<uint32_t>(static_cast<double>(source[1]) * scale_factor);
1595     destination[2] =
1596         static_cast<uint32_t>(static_cast<double>(source[2]) * scale_factor);
1597     destination[3] = source[3];
1598     source += 4;
1599     destination += 4;
1600   }
1601 }
1602 
1603 template <>
Pack(const int32_t * source,int32_t * destination,unsigned pixels_per_row)1604 void Pack<WebGLImageConversion::kDataFormatRGBA32_S,
1605           WebGLImageConversion::kAlphaDoPremultiply,
1606           int32_t,
1607           int32_t>(const int32_t* source,
1608                    int32_t* destination,
1609                    unsigned pixels_per_row) {
1610   for (unsigned i = 0; i < pixels_per_row; ++i) {
1611     destination[3] = ClampMin(source[3]);
1612     double scale_factor = static_cast<double>(destination[3]) / kMaxInt32Value;
1613     destination[0] = static_cast<int32_t>(
1614         static_cast<double>(ClampMin(source[0])) * scale_factor);
1615     destination[1] = static_cast<int32_t>(
1616         static_cast<double>(ClampMin(source[1])) * scale_factor);
1617     destination[2] = static_cast<int32_t>(
1618         static_cast<double>(ClampMin(source[2])) * scale_factor);
1619     source += 4;
1620     destination += 4;
1621   }
1622 }
1623 
1624 template <>
Pack(const float * source,uint32_t * destination,unsigned pixels_per_row)1625 void Pack<WebGLImageConversion::kDataFormatRGBA2_10_10_10,
1626           WebGLImageConversion::kAlphaDoNothing,
1627           float,
1628           uint32_t>(const float* source,
1629                     uint32_t* destination,
1630                     unsigned pixels_per_row) {
1631   for (unsigned i = 0; i < pixels_per_row; ++i) {
1632     uint32_t r = static_cast<uint32_t>(source[0] * 1023.0f);
1633     uint32_t g = static_cast<uint32_t>(source[1] * 1023.0f);
1634     uint32_t b = static_cast<uint32_t>(source[2] * 1023.0f);
1635     uint32_t a = static_cast<uint32_t>(source[3] * 3.0f);
1636     destination[0] = (a << 30) | (b << 20) | (g << 10) | r;
1637     source += 4;
1638     destination += 1;
1639   }
1640 }
1641 
1642 template <>
Pack(const float * source,uint32_t * destination,unsigned pixels_per_row)1643 void Pack<WebGLImageConversion::kDataFormatRGBA2_10_10_10,
1644           WebGLImageConversion::kAlphaDoPremultiply,
1645           float,
1646           uint32_t>(const float* source,
1647                     uint32_t* destination,
1648                     unsigned pixels_per_row) {
1649   for (unsigned i = 0; i < pixels_per_row; ++i) {
1650     uint32_t r = static_cast<uint32_t>(source[0] * source[3] * 1023.0f);
1651     uint32_t g = static_cast<uint32_t>(source[1] * source[3] * 1023.0f);
1652     uint32_t b = static_cast<uint32_t>(source[2] * source[3] * 1023.0f);
1653     uint32_t a = static_cast<uint32_t>(source[3] * 3.0f);
1654     destination[0] = (a << 30) | (b << 20) | (g << 10) | r;
1655     source += 4;
1656     destination += 1;
1657   }
1658 }
1659 
1660 template <>
Pack(const float * source,uint32_t * destination,unsigned pixels_per_row)1661 void Pack<WebGLImageConversion::kDataFormatRGBA2_10_10_10,
1662           WebGLImageConversion::kAlphaDoUnmultiply,
1663           float,
1664           uint32_t>(const float* source,
1665                     uint32_t* destination,
1666                     unsigned pixels_per_row) {
1667   for (unsigned i = 0; i < pixels_per_row; ++i) {
1668     float scale_factor = source[3] ? 1023.0f / source[3] : 1023.0f;
1669     uint32_t r = static_cast<uint32_t>(source[0] * scale_factor);
1670     uint32_t g = static_cast<uint32_t>(source[1] * scale_factor);
1671     uint32_t b = static_cast<uint32_t>(source[2] * scale_factor);
1672     uint32_t a = static_cast<uint32_t>(source[3] * 3.0f);
1673     destination[0] = (a << 30) | (b << 20) | (g << 10) | r;
1674     source += 4;
1675     destination += 1;
1676   }
1677 }
1678 
1679 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)1680 void Pack<WebGLImageConversion::kDataFormatRG8,
1681           WebGLImageConversion::kAlphaDoNothing,
1682           uint8_t,
1683           uint8_t>(const uint8_t* source,
1684                    uint8_t* destination,
1685                    unsigned pixels_per_row) {
1686   for (unsigned i = 0; i < pixels_per_row; ++i) {
1687     destination[0] = source[0];
1688     destination[1] = source[1];
1689     source += 4;
1690     destination += 2;
1691   }
1692 }
1693 
1694 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)1695 void Pack<WebGLImageConversion::kDataFormatRG8,
1696           WebGLImageConversion::kAlphaDoPremultiply,
1697           uint8_t,
1698           uint8_t>(const uint8_t* source,
1699                    uint8_t* destination,
1700                    unsigned pixels_per_row) {
1701   for (unsigned i = 0; i < pixels_per_row; ++i) {
1702     float scale_factor = static_cast<float>(source[3]) / kMaxUInt8Value;
1703     destination[0] =
1704         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
1705     destination[1] =
1706         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
1707     source += 4;
1708     destination += 2;
1709   }
1710 }
1711 
1712 // FIXME: this routine is lossy and must be removed.
1713 template <>
Pack(const uint8_t * source,uint8_t * destination,unsigned pixels_per_row)1714 void Pack<WebGLImageConversion::kDataFormatRG8,
1715           WebGLImageConversion::kAlphaDoUnmultiply,
1716           uint8_t,
1717           uint8_t>(const uint8_t* source,
1718                    uint8_t* destination,
1719                    unsigned pixels_per_row) {
1720   for (unsigned i = 0; i < pixels_per_row; ++i) {
1721     float scale_factor =
1722         source[3] ? kMaxUInt8Value / static_cast<float>(source[3]) : 1.0f;
1723     destination[0] =
1724         static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor);
1725     destination[1] =
1726         static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor);
1727     source += 4;
1728     destination += 2;
1729   }
1730 }
1731 
1732 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1733 void Pack<WebGLImageConversion::kDataFormatRG16F,
1734           WebGLImageConversion::kAlphaDoNothing,
1735           float,
1736           uint16_t>(const float* source,
1737                     uint16_t* destination,
1738                     unsigned pixels_per_row) {
1739   for (unsigned i = 0; i < pixels_per_row; ++i) {
1740     destination[0] = ConvertFloatToHalfFloat(source[0]);
1741     destination[1] = ConvertFloatToHalfFloat(source[1]);
1742     source += 4;
1743     destination += 2;
1744   }
1745 }
1746 
1747 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1748 void Pack<WebGLImageConversion::kDataFormatRG16F,
1749           WebGLImageConversion::kAlphaDoPremultiply,
1750           float,
1751           uint16_t>(const float* source,
1752                     uint16_t* destination,
1753                     unsigned pixels_per_row) {
1754   for (unsigned i = 0; i < pixels_per_row; ++i) {
1755     float scale_factor = source[3];
1756     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1757     destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor);
1758     source += 4;
1759     destination += 2;
1760   }
1761 }
1762 
1763 // FIXME: this routine is lossy and must be removed.
1764 template <>
Pack(const float * source,uint16_t * destination,unsigned pixels_per_row)1765 void Pack<WebGLImageConversion::kDataFormatRG16F,
1766           WebGLImageConversion::kAlphaDoUnmultiply,
1767           float,
1768           uint16_t>(const float* source,
1769                     uint16_t* destination,
1770                     unsigned pixels_per_row) {
1771   for (unsigned i = 0; i < pixels_per_row; ++i) {
1772     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1773     destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor);
1774     destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor);
1775     source += 4;
1776     destination += 2;
1777   }
1778 }
1779 
1780 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1781 void Pack<WebGLImageConversion::kDataFormatRG32F,
1782           WebGLImageConversion::kAlphaDoNothing,
1783           float,
1784           float>(const float* source,
1785                  float* destination,
1786                  unsigned pixels_per_row) {
1787   for (unsigned i = 0; i < pixels_per_row; ++i) {
1788     destination[0] = source[0];
1789     destination[1] = source[1];
1790     source += 4;
1791     destination += 2;
1792   }
1793 }
1794 
1795 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1796 void Pack<WebGLImageConversion::kDataFormatRG32F,
1797           WebGLImageConversion::kAlphaDoPremultiply,
1798           float,
1799           float>(const float* source,
1800                  float* destination,
1801                  unsigned pixels_per_row) {
1802   for (unsigned i = 0; i < pixels_per_row; ++i) {
1803     float scale_factor = source[3];
1804     destination[0] = source[0] * scale_factor;
1805     destination[1] = source[1] * scale_factor;
1806     source += 4;
1807     destination += 2;
1808   }
1809 }
1810 
1811 // FIXME: this routine is lossy and must be removed.
1812 template <>
Pack(const float * source,float * destination,unsigned pixels_per_row)1813 void Pack<WebGLImageConversion::kDataFormatRG32F,
1814           WebGLImageConversion::kAlphaDoUnmultiply,
1815           float,
1816           float>(const float* source,
1817                  float* destination,
1818                  unsigned pixels_per_row) {
1819   for (unsigned i = 0; i < pixels_per_row; ++i) {
1820     float scale_factor = source[3] ? 1.0f / source[3] : 1.0f;
1821     destination[0] = source[0] * scale_factor;
1822     destination[1] = source[1] * scale_factor;
1823     source += 4;
1824     destination += 2;
1825   }
1826 }
1827 
HasAlpha(int format)1828 bool HasAlpha(int format) {
1829   return format == WebGLImageConversion::kDataFormatA8 ||
1830          format == WebGLImageConversion::kDataFormatA16F ||
1831          format == WebGLImageConversion::kDataFormatA32F ||
1832          format == WebGLImageConversion::kDataFormatRA8 ||
1833          format == WebGLImageConversion::kDataFormatAR8 ||
1834          format == WebGLImageConversion::kDataFormatRA16F ||
1835          format == WebGLImageConversion::kDataFormatRA32F ||
1836          format == WebGLImageConversion::kDataFormatRGBA8 ||
1837          format == WebGLImageConversion::kDataFormatBGRA8 ||
1838          format == WebGLImageConversion::kDataFormatARGB8 ||
1839          format == WebGLImageConversion::kDataFormatABGR8 ||
1840          format == WebGLImageConversion::kDataFormatRGBA16F ||
1841          format == WebGLImageConversion::kDataFormatRGBA32F ||
1842          format == WebGLImageConversion::kDataFormatRGBA4444 ||
1843          format == WebGLImageConversion::kDataFormatRGBA5551 ||
1844          format == WebGLImageConversion::kDataFormatRGBA8_S ||
1845          format == WebGLImageConversion::kDataFormatRGBA16 ||
1846          format == WebGLImageConversion::kDataFormatRGBA16_S ||
1847          format == WebGLImageConversion::kDataFormatRGBA32 ||
1848          format == WebGLImageConversion::kDataFormatRGBA32_S ||
1849          format == WebGLImageConversion::kDataFormatRGBA2_10_10_10;
1850 }
1851 
HasColor(int format)1852 bool HasColor(int format) {
1853   return format == WebGLImageConversion::kDataFormatRGBA8 ||
1854          format == WebGLImageConversion::kDataFormatRGBA16F ||
1855          format == WebGLImageConversion::kDataFormatRGBA32F ||
1856          format == WebGLImageConversion::kDataFormatRGB8 ||
1857          format == WebGLImageConversion::kDataFormatRGB16F ||
1858          format == WebGLImageConversion::kDataFormatRGB32F ||
1859          format == WebGLImageConversion::kDataFormatBGR8 ||
1860          format == WebGLImageConversion::kDataFormatBGRA8 ||
1861          format == WebGLImageConversion::kDataFormatARGB8 ||
1862          format == WebGLImageConversion::kDataFormatABGR8 ||
1863          format == WebGLImageConversion::kDataFormatRGBA5551 ||
1864          format == WebGLImageConversion::kDataFormatRGBA4444 ||
1865          format == WebGLImageConversion::kDataFormatRGB565 ||
1866          format == WebGLImageConversion::kDataFormatR8 ||
1867          format == WebGLImageConversion::kDataFormatR16F ||
1868          format == WebGLImageConversion::kDataFormatR32F ||
1869          format == WebGLImageConversion::kDataFormatRA8 ||
1870          format == WebGLImageConversion::kDataFormatRA16F ||
1871          format == WebGLImageConversion::kDataFormatRA32F ||
1872          format == WebGLImageConversion::kDataFormatAR8 ||
1873          format == WebGLImageConversion::kDataFormatRGBA8_S ||
1874          format == WebGLImageConversion::kDataFormatRGBA16 ||
1875          format == WebGLImageConversion::kDataFormatRGBA16_S ||
1876          format == WebGLImageConversion::kDataFormatRGBA32 ||
1877          format == WebGLImageConversion::kDataFormatRGBA32_S ||
1878          format == WebGLImageConversion::kDataFormatRGBA2_10_10_10 ||
1879          format == WebGLImageConversion::kDataFormatRGB8_S ||
1880          format == WebGLImageConversion::kDataFormatRGB16 ||
1881          format == WebGLImageConversion::kDataFormatRGB16_S ||
1882          format == WebGLImageConversion::kDataFormatRGB32 ||
1883          format == WebGLImageConversion::kDataFormatRGB32_S ||
1884          format == WebGLImageConversion::kDataFormatRGB10F11F11F ||
1885          format == WebGLImageConversion::kDataFormatRGB5999 ||
1886          format == WebGLImageConversion::kDataFormatRG8 ||
1887          format == WebGLImageConversion::kDataFormatRG8_S ||
1888          format == WebGLImageConversion::kDataFormatRG16 ||
1889          format == WebGLImageConversion::kDataFormatRG16_S ||
1890          format == WebGLImageConversion::kDataFormatRG32 ||
1891          format == WebGLImageConversion::kDataFormatRG32_S ||
1892          format == WebGLImageConversion::kDataFormatRG16F ||
1893          format == WebGLImageConversion::kDataFormatRG32F ||
1894          format == WebGLImageConversion::kDataFormatR8_S ||
1895          format == WebGLImageConversion::kDataFormatR16 ||
1896          format == WebGLImageConversion::kDataFormatR16_S ||
1897          format == WebGLImageConversion::kDataFormatR32 ||
1898          format == WebGLImageConversion::kDataFormatR32_S;
1899 }
1900 
1901 template <int Format>
1902 struct IsInt8Format {
1903   STATIC_ONLY(IsInt8Format);
1904   static const bool value =
1905       Format == WebGLImageConversion::kDataFormatRGBA8_S ||
1906       Format == WebGLImageConversion::kDataFormatRGB8_S ||
1907       Format == WebGLImageConversion::kDataFormatRG8_S ||
1908       Format == WebGLImageConversion::kDataFormatR8_S;
1909 };
1910 
1911 template <int Format>
1912 struct IsInt16Format {
1913   STATIC_ONLY(IsInt16Format);
1914   static const bool value =
1915       Format == WebGLImageConversion::kDataFormatRGBA16_S ||
1916       Format == WebGLImageConversion::kDataFormatRGB16_S ||
1917       Format == WebGLImageConversion::kDataFormatRG16_S ||
1918       Format == WebGLImageConversion::kDataFormatR16_S;
1919 };
1920 
1921 template <int Format>
1922 struct IsInt32Format {
1923   STATIC_ONLY(IsInt32Format);
1924   static const bool value =
1925       Format == WebGLImageConversion::kDataFormatRGBA32_S ||
1926       Format == WebGLImageConversion::kDataFormatRGB32_S ||
1927       Format == WebGLImageConversion::kDataFormatRG32_S ||
1928       Format == WebGLImageConversion::kDataFormatR32_S;
1929 };
1930 
1931 template <int Format>
1932 struct IsUInt8Format {
1933   STATIC_ONLY(IsUInt8Format);
1934   static const bool value = Format == WebGLImageConversion::kDataFormatRGBA8 ||
1935                             Format == WebGLImageConversion::kDataFormatRGB8 ||
1936                             Format == WebGLImageConversion::kDataFormatRG8 ||
1937                             Format == WebGLImageConversion::kDataFormatR8 ||
1938                             Format == WebGLImageConversion::kDataFormatBGRA8 ||
1939                             Format == WebGLImageConversion::kDataFormatBGR8 ||
1940                             Format == WebGLImageConversion::kDataFormatARGB8 ||
1941                             Format == WebGLImageConversion::kDataFormatABGR8 ||
1942                             Format == WebGLImageConversion::kDataFormatRA8 ||
1943                             Format == WebGLImageConversion::kDataFormatAR8 ||
1944                             Format == WebGLImageConversion::kDataFormatA8;
1945 };
1946 
1947 template <int Format>
1948 struct IsUInt16Format {
1949   STATIC_ONLY(IsUInt16Format);
1950   static const bool value = Format == WebGLImageConversion::kDataFormatRGBA16 ||
1951                             Format == WebGLImageConversion::kDataFormatRGB16 ||
1952                             Format == WebGLImageConversion::kDataFormatRG16 ||
1953                             Format == WebGLImageConversion::kDataFormatR16;
1954 };
1955 
1956 template <int Format>
1957 struct IsUInt32Format {
1958   STATIC_ONLY(IsUInt32Format);
1959   static const bool value = Format == WebGLImageConversion::kDataFormatRGBA32 ||
1960                             Format == WebGLImageConversion::kDataFormatRGB32 ||
1961                             Format == WebGLImageConversion::kDataFormatRG32 ||
1962                             Format == WebGLImageConversion::kDataFormatR32;
1963 };
1964 
1965 template <int Format>
1966 struct IsFloatFormat {
1967   STATIC_ONLY(IsFloatFormat);
1968   static const bool value =
1969       Format == WebGLImageConversion::kDataFormatRGBA32F ||
1970       Format == WebGLImageConversion::kDataFormatRGB32F ||
1971       Format == WebGLImageConversion::kDataFormatRA32F ||
1972       Format == WebGLImageConversion::kDataFormatR32F ||
1973       Format == WebGLImageConversion::kDataFormatA32F ||
1974       Format == WebGLImageConversion::kDataFormatRG32F;
1975 };
1976 
1977 template <int Format>
1978 struct IsHalfFloatFormat {
1979   STATIC_ONLY(IsHalfFloatFormat);
1980   static const bool value =
1981       Format == WebGLImageConversion::kDataFormatRGBA16F ||
1982       Format == WebGLImageConversion::kDataFormatRGB16F ||
1983       Format == WebGLImageConversion::kDataFormatRA16F ||
1984       Format == WebGLImageConversion::kDataFormatR16F ||
1985       Format == WebGLImageConversion::kDataFormatA16F ||
1986       Format == WebGLImageConversion::kDataFormatRG16F;
1987 };
1988 
1989 template <int Format>
1990 struct Is32bppFormat {
1991   STATIC_ONLY(Is32bppFormat);
1992   static const bool value =
1993       Format == WebGLImageConversion::kDataFormatRGBA2_10_10_10 ||
1994       Format == WebGLImageConversion::kDataFormatRGB5999 ||
1995       Format == WebGLImageConversion::kDataFormatRGB10F11F11F;
1996 };
1997 
1998 template <int Format>
1999 struct Is16bppFormat {
2000   STATIC_ONLY(Is16bppFormat);
2001   static const bool value =
2002       Format == WebGLImageConversion::kDataFormatRGBA5551 ||
2003       Format == WebGLImageConversion::kDataFormatRGBA4444 ||
2004       Format == WebGLImageConversion::kDataFormatRGB565;
2005 };
2006 
2007 template <int Format,
2008           bool IsInt8Format = IsInt8Format<Format>::value,
2009           bool IsUInt8Format = IsUInt8Format<Format>::value,
2010           bool IsInt16Format = IsInt16Format<Format>::value,
2011           bool IsUInt16Format = IsUInt16Format<Format>::value,
2012           bool IsInt32Format = IsInt32Format<Format>::value,
2013           bool IsUInt32Format = IsUInt32Format<Format>::value,
2014           bool IsFloat = IsFloatFormat<Format>::value,
2015           bool IsHalfFloat = IsHalfFloatFormat<Format>::value,
2016           bool Is16bpp = Is16bppFormat<Format>::value,
2017           bool Is32bpp = Is32bppFormat<Format>::value>
2018 struct DataTypeForFormat {
2019   STATIC_ONLY(DataTypeForFormat);
2020   typedef double Type;  // Use a type that's not used in unpack/pack.
2021 };
2022 
2023 template <int Format>
2024 struct DataTypeForFormat<Format,
2025                          true,
2026                          false,
2027                          false,
2028                          false,
2029                          false,
2030                          false,
2031                          false,
2032                          false,
2033                          false,
2034                          false> {
2035   STATIC_ONLY(DataTypeForFormat);
2036   typedef int8_t Type;
2037 };
2038 
2039 template <int Format>
2040 struct DataTypeForFormat<Format,
2041                          false,
2042                          true,
2043                          false,
2044                          false,
2045                          false,
2046                          false,
2047                          false,
2048                          false,
2049                          false,
2050                          false> {
2051   STATIC_ONLY(DataTypeForFormat);
2052   typedef uint8_t Type;
2053 };
2054 
2055 template <int Format>
2056 struct DataTypeForFormat<Format,
2057                          false,
2058                          false,
2059                          true,
2060                          false,
2061                          false,
2062                          false,
2063                          false,
2064                          false,
2065                          false,
2066                          false> {
2067   STATIC_ONLY(DataTypeForFormat);
2068   typedef int16_t Type;
2069 };
2070 
2071 template <int Format>
2072 struct DataTypeForFormat<Format,
2073                          false,
2074                          false,
2075                          false,
2076                          true,
2077                          false,
2078                          false,
2079                          false,
2080                          false,
2081                          false,
2082                          false> {
2083   STATIC_ONLY(DataTypeForFormat);
2084   typedef uint16_t Type;
2085 };
2086 
2087 template <int Format>
2088 struct DataTypeForFormat<Format,
2089                          false,
2090                          false,
2091                          false,
2092                          false,
2093                          true,
2094                          false,
2095                          false,
2096                          false,
2097                          false,
2098                          false> {
2099   STATIC_ONLY(DataTypeForFormat);
2100   typedef int32_t Type;
2101 };
2102 
2103 template <int Format>
2104 struct DataTypeForFormat<Format,
2105                          false,
2106                          false,
2107                          false,
2108                          false,
2109                          false,
2110                          true,
2111                          false,
2112                          false,
2113                          false,
2114                          false> {
2115   STATIC_ONLY(DataTypeForFormat);
2116   typedef uint32_t Type;
2117 };
2118 
2119 template <int Format>
2120 struct DataTypeForFormat<Format,
2121                          false,
2122                          false,
2123                          false,
2124                          false,
2125                          false,
2126                          false,
2127                          true,
2128                          false,
2129                          false,
2130                          false> {
2131   STATIC_ONLY(DataTypeForFormat);
2132   typedef float Type;
2133 };
2134 
2135 template <int Format>
2136 struct DataTypeForFormat<Format,
2137                          false,
2138                          false,
2139                          false,
2140                          false,
2141                          false,
2142                          false,
2143                          false,
2144                          true,
2145                          false,
2146                          false> {
2147   STATIC_ONLY(DataTypeForFormat);
2148   typedef uint16_t Type;
2149 };
2150 
2151 template <int Format>
2152 struct DataTypeForFormat<Format,
2153                          false,
2154                          false,
2155                          false,
2156                          false,
2157                          false,
2158                          false,
2159                          false,
2160                          false,
2161                          true,
2162                          false> {
2163   STATIC_ONLY(DataTypeForFormat);
2164   typedef uint16_t Type;
2165 };
2166 
2167 template <int Format>
2168 struct DataTypeForFormat<Format,
2169                          false,
2170                          false,
2171                          false,
2172                          false,
2173                          false,
2174                          false,
2175                          false,
2176                          false,
2177                          false,
2178                          true> {
2179   STATIC_ONLY(DataTypeForFormat);
2180   typedef uint32_t Type;
2181 };
2182 
2183 template <int Format>
2184 struct UsesFloatIntermediateFormat {
2185   STATIC_ONLY(UsesFloatIntermediateFormat);
2186   static const bool value =
2187       IsFloatFormat<Format>::value || IsHalfFloatFormat<Format>::value ||
2188       Format == WebGLImageConversion::kDataFormatRGBA2_10_10_10 ||
2189       Format == WebGLImageConversion::kDataFormatRGB10F11F11F ||
2190       Format == WebGLImageConversion::kDataFormatRGB5999;
2191 };
2192 
2193 template <int Format>
2194 struct IntermediateFormat {
2195   STATIC_ONLY(IntermediateFormat);
2196   static const int value =
2197       UsesFloatIntermediateFormat<Format>::value
2198           ? WebGLImageConversion::kDataFormatRGBA32F
2199           : IsInt32Format<Format>::value
2200                 ? WebGLImageConversion::kDataFormatRGBA32_S
2201                 : IsUInt32Format<Format>::value
2202                       ? WebGLImageConversion::kDataFormatRGBA32
2203                       : IsInt16Format<Format>::value
2204                             ? WebGLImageConversion::kDataFormatRGBA16_S
2205                             : (IsUInt16Format<Format>::value ||
2206                                Is32bppFormat<Format>::value)
2207                                   ? WebGLImageConversion::kDataFormatRGBA16
2208                                   : IsInt8Format<Format>::value
2209                                         ? WebGLImageConversion::
2210                                               kDataFormatRGBA8_S
2211                                         : WebGLImageConversion::
2212                                               kDataFormatRGBA8;
2213 };
2214 
TexelBytesForFormat(WebGLImageConversion::DataFormat format)2215 unsigned TexelBytesForFormat(WebGLImageConversion::DataFormat format) {
2216   switch (format) {
2217     case WebGLImageConversion::kDataFormatR8:
2218     case WebGLImageConversion::kDataFormatR8_S:
2219     case WebGLImageConversion::kDataFormatA8:
2220       return 1;
2221     case WebGLImageConversion::kDataFormatRG8:
2222     case WebGLImageConversion::kDataFormatRG8_S:
2223     case WebGLImageConversion::kDataFormatRA8:
2224     case WebGLImageConversion::kDataFormatAR8:
2225     case WebGLImageConversion::kDataFormatRGBA5551:
2226     case WebGLImageConversion::kDataFormatRGBA4444:
2227     case WebGLImageConversion::kDataFormatRGB565:
2228     case WebGLImageConversion::kDataFormatA16F:
2229     case WebGLImageConversion::kDataFormatR16:
2230     case WebGLImageConversion::kDataFormatR16_S:
2231     case WebGLImageConversion::kDataFormatR16F:
2232     case WebGLImageConversion::kDataFormatD16:
2233       return 2;
2234     case WebGLImageConversion::kDataFormatRGB8:
2235     case WebGLImageConversion::kDataFormatRGB8_S:
2236     case WebGLImageConversion::kDataFormatBGR8:
2237       return 3;
2238     case WebGLImageConversion::kDataFormatRGBA8:
2239     case WebGLImageConversion::kDataFormatRGBA8_S:
2240     case WebGLImageConversion::kDataFormatARGB8:
2241     case WebGLImageConversion::kDataFormatABGR8:
2242     case WebGLImageConversion::kDataFormatBGRA8:
2243     case WebGLImageConversion::kDataFormatR32:
2244     case WebGLImageConversion::kDataFormatR32_S:
2245     case WebGLImageConversion::kDataFormatR32F:
2246     case WebGLImageConversion::kDataFormatA32F:
2247     case WebGLImageConversion::kDataFormatRA16F:
2248     case WebGLImageConversion::kDataFormatRGBA2_10_10_10:
2249     case WebGLImageConversion::kDataFormatRGB10F11F11F:
2250     case WebGLImageConversion::kDataFormatRGB5999:
2251     case WebGLImageConversion::kDataFormatRG16:
2252     case WebGLImageConversion::kDataFormatRG16_S:
2253     case WebGLImageConversion::kDataFormatRG16F:
2254     case WebGLImageConversion::kDataFormatD32:
2255     case WebGLImageConversion::kDataFormatD32F:
2256     case WebGLImageConversion::kDataFormatDS24_8:
2257       return 4;
2258     case WebGLImageConversion::kDataFormatRGB16:
2259     case WebGLImageConversion::kDataFormatRGB16_S:
2260     case WebGLImageConversion::kDataFormatRGB16F:
2261       return 6;
2262     case WebGLImageConversion::kDataFormatRGBA16:
2263     case WebGLImageConversion::kDataFormatRGBA16_S:
2264     case WebGLImageConversion::kDataFormatRA32F:
2265     case WebGLImageConversion::kDataFormatRGBA16F:
2266     case WebGLImageConversion::kDataFormatRG32:
2267     case WebGLImageConversion::kDataFormatRG32_S:
2268     case WebGLImageConversion::kDataFormatRG32F:
2269       return 8;
2270     case WebGLImageConversion::kDataFormatRGB32:
2271     case WebGLImageConversion::kDataFormatRGB32_S:
2272     case WebGLImageConversion::kDataFormatRGB32F:
2273       return 12;
2274     case WebGLImageConversion::kDataFormatRGBA32:
2275     case WebGLImageConversion::kDataFormatRGBA32_S:
2276     case WebGLImageConversion::kDataFormatRGBA32F:
2277       return 16;
2278     default:
2279       return 0;
2280   }
2281 }
2282 
2283 /* END CODE SHARED WITH MOZILLA FIREFOX */
2284 
2285 class FormatConverter {
2286   STACK_ALLOCATED();
2287 
2288  public:
FormatConverter(const IntRect & source_data_sub_rectangle,int depth,int unpack_image_height,const void * src_start,void * dst_start,int src_stride,int src_row_offset,int dst_stride)2289   FormatConverter(const IntRect& source_data_sub_rectangle,
2290                   int depth,
2291                   int unpack_image_height,
2292                   const void* src_start,
2293                   void* dst_start,
2294                   int src_stride,
2295                   int src_row_offset,
2296                   int dst_stride)
2297       : src_sub_rectangle_(source_data_sub_rectangle),
2298         depth_(depth),
2299         unpack_image_height_(unpack_image_height),
2300         src_start_(src_start),
2301         dst_start_(dst_start),
2302         src_stride_(src_stride),
2303         src_row_offset_(src_row_offset),
2304         dst_stride_(dst_stride),
2305         success_(false) {
2306     const unsigned kMaxNumberOfComponents = 4;
2307     const unsigned kMaxBytesPerComponent = 4;
2308     unpacked_intermediate_src_data_ = std::make_unique<uint8_t[]>(
2309         src_sub_rectangle_.Width() * kMaxNumberOfComponents *
2310         kMaxBytesPerComponent);
2311     DCHECK(unpacked_intermediate_src_data_.get());
2312   }
2313 
2314   void Convert(WebGLImageConversion::DataFormat src_format,
2315                WebGLImageConversion::DataFormat dst_format,
2316                WebGLImageConversion::AlphaOp);
Success() const2317   bool Success() const { return success_; }
2318 
2319  private:
2320   template <WebGLImageConversion::DataFormat SrcFormat>
2321   void Convert(WebGLImageConversion::DataFormat dst_format,
2322                WebGLImageConversion::AlphaOp);
2323 
2324   template <WebGLImageConversion::DataFormat SrcFormat,
2325             WebGLImageConversion::DataFormat DstFormat>
2326   void Convert(WebGLImageConversion::AlphaOp);
2327 
2328   template <WebGLImageConversion::DataFormat SrcFormat,
2329             WebGLImageConversion::DataFormat DstFormat,
2330             WebGLImageConversion::AlphaOp alphaOp>
2331   void Convert();
2332 
2333   const IntRect& src_sub_rectangle_;
2334   const int depth_;
2335   const int unpack_image_height_;
2336   const void* const src_start_;
2337   void* const dst_start_;
2338   const int src_stride_, src_row_offset_, dst_stride_;
2339   bool success_;
2340   std::unique_ptr<uint8_t[]> unpacked_intermediate_src_data_;
2341 };
2342 
Convert(WebGLImageConversion::DataFormat src_format,WebGLImageConversion::DataFormat dst_format,WebGLImageConversion::AlphaOp alpha_op)2343 void FormatConverter::Convert(WebGLImageConversion::DataFormat src_format,
2344                               WebGLImageConversion::DataFormat dst_format,
2345                               WebGLImageConversion::AlphaOp alpha_op) {
2346 #define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \
2347   case SrcFormat:                                 \
2348     return Convert<SrcFormat>(dst_format, alpha_op);
2349 
2350   switch (src_format) {
2351     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRA8)
2352     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRA32F)
2353     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA8)
2354     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatARGB8)
2355     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatABGR8)
2356     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatAR8)
2357     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatBGRA8)
2358     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA5551)
2359     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA4444)
2360     FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA32F)
2361     FORMATCONVERTER_CASE_SRCFORMAT(
2362         WebGLImageConversion::kDataFormatRGBA2_10_10_10)
2363     default:
2364       NOTREACHED();
2365   }
2366 #undef FORMATCONVERTER_CASE_SRCFORMAT
2367 }
2368 
2369 template <WebGLImageConversion::DataFormat SrcFormat>
Convert(WebGLImageConversion::DataFormat dst_format,WebGLImageConversion::AlphaOp alpha_op)2370 void FormatConverter::Convert(WebGLImageConversion::DataFormat dst_format,
2371                               WebGLImageConversion::AlphaOp alpha_op) {
2372 #define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \
2373   case DstFormat:                                 \
2374     return Convert<SrcFormat, DstFormat>(alpha_op);
2375 
2376   switch (dst_format) {
2377     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatR8)
2378     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatR16F)
2379     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatR32F)
2380     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatA8)
2381     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatA16F)
2382     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatA32F)
2383     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRA8)
2384     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRA16F)
2385     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRA32F)
2386     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB8)
2387     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB565)
2388     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB16F)
2389     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB32F)
2390     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA8)
2391     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA5551)
2392     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA4444)
2393     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA16F)
2394     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA32F)
2395     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA8_S)
2396     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA16)
2397     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA16_S)
2398     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA32)
2399     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA32_S)
2400     FORMATCONVERTER_CASE_DSTFORMAT(
2401         WebGLImageConversion::kDataFormatRGBA2_10_10_10)
2402     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRG8)
2403     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRG16F)
2404     FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRG32F)
2405     default:
2406       NOTREACHED();
2407   }
2408 
2409 #undef FORMATCONVERTER_CASE_DSTFORMAT
2410 }
2411 
2412 template <WebGLImageConversion::DataFormat SrcFormat,
2413           WebGLImageConversion::DataFormat DstFormat>
Convert(WebGLImageConversion::AlphaOp alpha_op)2414 void FormatConverter::Convert(WebGLImageConversion::AlphaOp alpha_op) {
2415 #define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \
2416   case alphaOp:                               \
2417     return Convert<SrcFormat, DstFormat, alphaOp>();
2418 
2419   switch (alpha_op) {
2420     FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::kAlphaDoNothing)
2421     FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::kAlphaDoPremultiply)
2422     FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::kAlphaDoUnmultiply)
2423     default:
2424       NOTREACHED();
2425   }
2426 #undef FORMATCONVERTER_CASE_ALPHAOP
2427 }
2428 
2429 template <int Format>
2430 struct SupportsConversionFromDomElements {
2431   STATIC_ONLY(SupportsConversionFromDomElements);
2432   static const bool value =
2433       Format == WebGLImageConversion::kDataFormatRGBA8 ||
2434       Format == WebGLImageConversion::kDataFormatRGB8 ||
2435       Format == WebGLImageConversion::kDataFormatRG8 ||
2436       Format == WebGLImageConversion::kDataFormatRA8 ||
2437       Format == WebGLImageConversion::kDataFormatR8 ||
2438       Format == WebGLImageConversion::kDataFormatRGBA32F ||
2439       Format == WebGLImageConversion::kDataFormatRGB32F ||
2440       Format == WebGLImageConversion::kDataFormatRG32F ||
2441       Format == WebGLImageConversion::kDataFormatRA32F ||
2442       Format == WebGLImageConversion::kDataFormatR32F ||
2443       Format == WebGLImageConversion::kDataFormatRGBA16F ||
2444       Format == WebGLImageConversion::kDataFormatRGB16F ||
2445       Format == WebGLImageConversion::kDataFormatRG16F ||
2446       Format == WebGLImageConversion::kDataFormatRA16F ||
2447       Format == WebGLImageConversion::kDataFormatR16F ||
2448       Format == WebGLImageConversion::kDataFormatRGBA5551 ||
2449       Format == WebGLImageConversion::kDataFormatRGBA4444 ||
2450       Format == WebGLImageConversion::kDataFormatRGB565 ||
2451       Format == WebGLImageConversion::kDataFormatRGBA2_10_10_10;
2452 };
2453 
2454 template <WebGLImageConversion::DataFormat SrcFormat,
2455           WebGLImageConversion::DataFormat DstFormat,
2456           WebGLImageConversion::AlphaOp alphaOp>
Convert()2457 void FormatConverter::Convert() {
2458   // Many instantiations of this template function will never be entered, so we
2459   // try to return immediately in these cases to avoid generating useless code.
2460   if (SrcFormat == DstFormat &&
2461       alphaOp == WebGLImageConversion::kAlphaDoNothing) {
2462     NOTREACHED();
2463     return;
2464   }
2465   if (!IsFloatFormat<DstFormat>::value && IsFloatFormat<SrcFormat>::value) {
2466     NOTREACHED();
2467     return;
2468   }
2469 
2470   // Only textures uploaded from DOM elements or ImageData can allow DstFormat
2471   // != SrcFormat.
2472   const bool src_format_comes_from_dom_element_or_image_data =
2473       WebGLImageConversion::SrcFormatComeFromDOMElementOrImageData(SrcFormat);
2474   if (!src_format_comes_from_dom_element_or_image_data &&
2475       SrcFormat != DstFormat) {
2476     NOTREACHED();
2477     return;
2478   }
2479   // Likewise, only textures uploaded from DOM elements or ImageData can
2480   // possibly need to be unpremultiplied.
2481   if (!src_format_comes_from_dom_element_or_image_data &&
2482       alphaOp == WebGLImageConversion::kAlphaDoUnmultiply) {
2483     NOTREACHED();
2484     return;
2485   }
2486   if (src_format_comes_from_dom_element_or_image_data &&
2487       alphaOp == WebGLImageConversion::kAlphaDoUnmultiply &&
2488       !SupportsConversionFromDomElements<DstFormat>::value) {
2489     NOTREACHED();
2490     return;
2491   }
2492   if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) &&
2493       alphaOp != WebGLImageConversion::kAlphaDoNothing) {
2494     NOTREACHED();
2495     return;
2496   }
2497   // If converting DOM element data to UNSIGNED_INT_5_9_9_9_REV or
2498   // UNSIGNED_INT_10F_11F_11F_REV, we should always switch to FLOAT instead to
2499   // avoid unpacking/packing these two types.
2500   if (src_format_comes_from_dom_element_or_image_data &&
2501       SrcFormat != DstFormat &&
2502       (DstFormat == WebGLImageConversion::kDataFormatRGB5999 ||
2503        DstFormat == WebGLImageConversion::kDataFormatRGB10F11F11F)) {
2504     NOTREACHED();
2505     return;
2506   }
2507 
2508   typedef typename DataTypeForFormat<SrcFormat>::Type SrcType;
2509   typedef typename DataTypeForFormat<DstFormat>::Type DstType;
2510   const int kIntermFormat = IntermediateFormat<DstFormat>::value;
2511   typedef typename DataTypeForFormat<kIntermFormat>::Type IntermType;
2512   // stride here could be negative.
2513   const ptrdiff_t src_stride_in_elements =
2514       src_stride_ / static_cast<int>(sizeof(SrcType));
2515   const ptrdiff_t dst_stride_in_elements =
2516       dst_stride_ / static_cast<int>(sizeof(DstType));
2517   const bool kTrivialUnpack = SrcFormat == kIntermFormat;
2518   const bool kTrivialPack = DstFormat == kIntermFormat &&
2519                             alphaOp == WebGLImageConversion::kAlphaDoNothing;
2520   DCHECK(!kTrivialUnpack || !kTrivialPack);
2521 
2522   const SrcType* src_row_start =
2523       static_cast<const SrcType*>(static_cast<const void*>(
2524           static_cast<const uint8_t*>(src_start_) +
2525           ((src_stride_ * src_sub_rectangle_.Y()) + src_row_offset_)));
2526 
2527   // If packing multiple images into a 3D texture, and flipY is true,
2528   // then the sub-rectangle is pointing at the start of the
2529   // "bottommost" of those images. Since the source pointer strides in
2530   // the positive direction, we need to back it up to point at the
2531   // last, or "topmost", of these images.
2532   if (dst_stride_ < 0 && depth_ > 1) {
2533     src_row_start -=
2534         (depth_ - 1) * src_stride_in_elements * unpack_image_height_;
2535   }
2536 
2537   DstType* dst_row_start = static_cast<DstType*>(dst_start_);
2538   if (kTrivialUnpack) {
2539     for (int d = 0; d < depth_; ++d) {
2540       for (int i = 0; i < src_sub_rectangle_.Height(); ++i) {
2541         Pack<DstFormat, alphaOp>(src_row_start, dst_row_start,
2542                                  src_sub_rectangle_.Width());
2543         src_row_start += src_stride_in_elements;
2544         dst_row_start += dst_stride_in_elements;
2545       }
2546       src_row_start += src_stride_in_elements *
2547                        (unpack_image_height_ - src_sub_rectangle_.Height());
2548     }
2549   } else if (kTrivialPack) {
2550     for (int d = 0; d < depth_; ++d) {
2551       for (int i = 0; i < src_sub_rectangle_.Height(); ++i) {
2552         Unpack<SrcFormat>(src_row_start, dst_row_start,
2553                           src_sub_rectangle_.Width());
2554         src_row_start += src_stride_in_elements;
2555         dst_row_start += dst_stride_in_elements;
2556       }
2557       src_row_start += src_stride_in_elements *
2558                        (unpack_image_height_ - src_sub_rectangle_.Height());
2559     }
2560   } else {
2561     for (int d = 0; d < depth_; ++d) {
2562       for (int i = 0; i < src_sub_rectangle_.Height(); ++i) {
2563         Unpack<SrcFormat>(src_row_start,
2564                           reinterpret_cast<IntermType*>(
2565                               unpacked_intermediate_src_data_.get()),
2566                           src_sub_rectangle_.Width());
2567         Pack<DstFormat, alphaOp>(reinterpret_cast<IntermType*>(
2568                                      unpacked_intermediate_src_data_.get()),
2569                                  dst_row_start, src_sub_rectangle_.Width());
2570         src_row_start += src_stride_in_elements;
2571         dst_row_start += dst_stride_in_elements;
2572       }
2573       src_row_start += src_stride_in_elements *
2574                        (unpack_image_height_ - src_sub_rectangle_.Height());
2575     }
2576   }
2577   success_ = true;
2578   return;
2579 }
2580 
FrameIsValid(const SkBitmap & frame_bitmap)2581 bool FrameIsValid(const SkBitmap& frame_bitmap) {
2582   return !frame_bitmap.isNull() && !frame_bitmap.empty() &&
2583          frame_bitmap.colorType() == kN32_SkColorType;
2584 }
2585 
2586 }  // anonymous namespace
2587 
PixelStoreParams()2588 WebGLImageConversion::PixelStoreParams::PixelStoreParams()
2589     : alignment(4),
2590       row_length(0),
2591       image_height(0),
2592       skip_pixels(0),
2593       skip_rows(0),
2594       skip_images(0) {}
2595 
ComputeFormatAndTypeParameters(GLenum format,GLenum type,unsigned * components_per_pixel,unsigned * bytes_per_component)2596 bool WebGLImageConversion::ComputeFormatAndTypeParameters(
2597     GLenum format,
2598     GLenum type,
2599     unsigned* components_per_pixel,
2600     unsigned* bytes_per_component) {
2601   switch (format) {
2602     case GL_ALPHA:
2603     case GL_LUMINANCE:
2604     case GL_RED:
2605     case GL_RED_INTEGER:
2606     case GL_DEPTH_COMPONENT:
2607     case GL_DEPTH_STENCIL:  // Treat it as one component.
2608       *components_per_pixel = 1;
2609       break;
2610     case GL_LUMINANCE_ALPHA:
2611     case GL_RG:
2612     case GL_RG_INTEGER:
2613       *components_per_pixel = 2;
2614       break;
2615     case GL_RGB:
2616     case GL_RGB_INTEGER:
2617     case GL_SRGB_EXT:  // GL_EXT_sRGB
2618       *components_per_pixel = 3;
2619       break;
2620     case GL_RGBA:
2621     case GL_RGBA_INTEGER:
2622     case GL_BGRA_EXT:        // GL_EXT_texture_format_BGRA8888
2623     case GL_SRGB_ALPHA_EXT:  // GL_EXT_sRGB
2624       *components_per_pixel = 4;
2625       break;
2626     default:
2627       return false;
2628   }
2629   switch (type) {
2630     case GL_BYTE:
2631       *bytes_per_component = sizeof(GLbyte);
2632       break;
2633     case GL_UNSIGNED_BYTE:
2634       *bytes_per_component = sizeof(GLubyte);
2635       break;
2636     case GL_SHORT:
2637       *bytes_per_component = sizeof(GLshort);
2638       break;
2639     case GL_UNSIGNED_SHORT:
2640       *bytes_per_component = sizeof(GLushort);
2641       break;
2642     case GL_UNSIGNED_SHORT_5_6_5:
2643     case GL_UNSIGNED_SHORT_4_4_4_4:
2644     case GL_UNSIGNED_SHORT_5_5_5_1:
2645       *components_per_pixel = 1;
2646       *bytes_per_component = sizeof(GLushort);
2647       break;
2648     case GL_INT:
2649       *bytes_per_component = sizeof(GLint);
2650       break;
2651     case GL_UNSIGNED_INT:
2652       *bytes_per_component = sizeof(GLuint);
2653       break;
2654     case GL_UNSIGNED_INT_24_8_OES:
2655     case GL_UNSIGNED_INT_10F_11F_11F_REV:
2656     case GL_UNSIGNED_INT_5_9_9_9_REV:
2657     case GL_UNSIGNED_INT_2_10_10_10_REV:
2658       *components_per_pixel = 1;
2659       *bytes_per_component = sizeof(GLuint);
2660       break;
2661     case GL_FLOAT:  // OES_texture_float
2662       *bytes_per_component = sizeof(GLfloat);
2663       break;
2664     case GL_HALF_FLOAT:
2665     case GL_HALF_FLOAT_OES:  // OES_texture_half_float
2666       *bytes_per_component = sizeof(GLushort);
2667       break;
2668     default:
2669       return false;
2670   }
2671   return true;
2672 }
2673 
ComputeImageSizeInBytes(GLenum format,GLenum type,GLsizei width,GLsizei height,GLsizei depth,const PixelStoreParams & params,unsigned * image_size_in_bytes,unsigned * padding_in_bytes,unsigned * skip_size_in_bytes)2674 GLenum WebGLImageConversion::ComputeImageSizeInBytes(
2675     GLenum format,
2676     GLenum type,
2677     GLsizei width,
2678     GLsizei height,
2679     GLsizei depth,
2680     const PixelStoreParams& params,
2681     unsigned* image_size_in_bytes,
2682     unsigned* padding_in_bytes,
2683     unsigned* skip_size_in_bytes) {
2684   DCHECK(image_size_in_bytes);
2685   DCHECK(params.alignment == 1 || params.alignment == 2 ||
2686          params.alignment == 4 || params.alignment == 8);
2687   DCHECK_GE(params.row_length, 0);
2688   DCHECK_GE(params.image_height, 0);
2689   DCHECK_GE(params.skip_pixels, 0);
2690   DCHECK_GE(params.skip_rows, 0);
2691   DCHECK_GE(params.skip_images, 0);
2692   if (width < 0 || height < 0 || depth < 0)
2693     return GL_INVALID_VALUE;
2694   if (!width || !height || !depth) {
2695     *image_size_in_bytes = 0;
2696     if (padding_in_bytes)
2697       *padding_in_bytes = 0;
2698     if (skip_size_in_bytes)
2699       *skip_size_in_bytes = 0;
2700     return GL_NO_ERROR;
2701   }
2702 
2703   int row_length = params.row_length > 0 ? params.row_length : width;
2704   int image_height = params.image_height > 0 ? params.image_height : height;
2705 
2706   unsigned bytes_per_component, components_per_pixel;
2707   if (!ComputeFormatAndTypeParameters(format, type, &bytes_per_component,
2708                                       &components_per_pixel))
2709     return GL_INVALID_ENUM;
2710   unsigned bytes_per_group = bytes_per_component * components_per_pixel;
2711   base::CheckedNumeric<uint32_t> checked_value =
2712       static_cast<uint32_t>(row_length);
2713   checked_value *= bytes_per_group;
2714   if (!checked_value.IsValid())
2715     return GL_INVALID_VALUE;
2716 
2717   unsigned last_row_size;
2718   if (params.row_length > 0 && params.row_length != width) {
2719     base::CheckedNumeric<uint32_t> tmp = width;
2720     tmp *= bytes_per_group;
2721     if (!tmp.IsValid())
2722       return GL_INVALID_VALUE;
2723     last_row_size = tmp.ValueOrDie();
2724   } else {
2725     last_row_size = checked_value.ValueOrDie();
2726   }
2727 
2728   unsigned padding = 0;
2729   base::CheckedNumeric<uint32_t> checked_residual = checked_value;
2730   checked_residual %= static_cast<uint32_t>(params.alignment);
2731   if (!checked_residual.IsValid()) {
2732     return GL_INVALID_VALUE;
2733   }
2734   unsigned residual = checked_residual.ValueOrDie();
2735   if (residual) {
2736     padding = params.alignment - residual;
2737     checked_value += padding;
2738   }
2739   if (!checked_value.IsValid())
2740     return GL_INVALID_VALUE;
2741   unsigned padded_row_size = checked_value.ValueOrDie();
2742 
2743   base::CheckedNumeric<uint32_t> rows = image_height;
2744   rows *= (depth - 1);
2745   // Last image is not affected by IMAGE_HEIGHT parameter.
2746   rows += height;
2747   if (!rows.IsValid())
2748     return GL_INVALID_VALUE;
2749   checked_value *= (rows - 1);
2750   // Last row is not affected by ROW_LENGTH parameter.
2751   checked_value += last_row_size;
2752   if (!checked_value.IsValid())
2753     return GL_INVALID_VALUE;
2754   *image_size_in_bytes = checked_value.ValueOrDie();
2755   if (padding_in_bytes)
2756     *padding_in_bytes = padding;
2757 
2758   base::CheckedNumeric<uint32_t> skip_size = 0;
2759   if (params.skip_images > 0) {
2760     base::CheckedNumeric<uint32_t> tmp = padded_row_size;
2761     tmp *= image_height;
2762     tmp *= params.skip_images;
2763     if (!tmp.IsValid())
2764       return GL_INVALID_VALUE;
2765     skip_size += tmp.ValueOrDie();
2766   }
2767   if (params.skip_rows > 0) {
2768     base::CheckedNumeric<uint32_t> tmp = padded_row_size;
2769     tmp *= params.skip_rows;
2770     if (!tmp.IsValid())
2771       return GL_INVALID_VALUE;
2772     skip_size += tmp.ValueOrDie();
2773   }
2774   if (params.skip_pixels > 0) {
2775     base::CheckedNumeric<uint32_t> tmp = bytes_per_group;
2776     tmp *= params.skip_pixels;
2777     if (!tmp.IsValid())
2778       return GL_INVALID_VALUE;
2779     skip_size += tmp.ValueOrDie();
2780   }
2781   if (!skip_size.IsValid())
2782     return GL_INVALID_VALUE;
2783   if (skip_size_in_bytes)
2784     *skip_size_in_bytes = skip_size.ValueOrDie();
2785 
2786   checked_value += skip_size.ValueOrDie();
2787   if (!checked_value.IsValid())
2788     return GL_INVALID_VALUE;
2789   return GL_NO_ERROR;
2790 }
2791 
ImageExtractor(Image * image,ImageHtmlDomSource image_html_dom_source,bool premultiply_alpha,bool ignore_color_space)2792 WebGLImageConversion::ImageExtractor::ImageExtractor(
2793     Image* image,
2794     ImageHtmlDomSource image_html_dom_source,
2795     bool premultiply_alpha,
2796     bool ignore_color_space) {
2797   image_ = image;
2798   image_html_dom_source_ = image_html_dom_source;
2799   ExtractImage(premultiply_alpha, ignore_color_space);
2800 }
2801 
ExtractImage(bool premultiply_alpha,bool ignore_color_space)2802 void WebGLImageConversion::ImageExtractor::ExtractImage(
2803     bool premultiply_alpha,
2804     bool ignore_color_space) {
2805   DCHECK(!image_pixel_locker_);
2806 
2807   if (!image_)
2808     return;
2809 
2810   sk_sp<SkImage> skia_image = image_->PaintImageForCurrentFrame().GetSkImage();
2811   SkImageInfo info =
2812       skia_image ? SkImageInfo::MakeN32Premul(image_->width(), image_->height())
2813                  : SkImageInfo::MakeUnknown();
2814   alpha_op_ = kAlphaDoNothing;
2815   bool has_alpha = skia_image ? !skia_image->isOpaque() : true;
2816 
2817   if ((!skia_image || ignore_color_space ||
2818        (has_alpha && !premultiply_alpha)) &&
2819       image_->Data()) {
2820     // Attempt to get raw unpremultiplied image data.
2821     const bool data_complete = true;
2822     std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
2823         image_->Data(), data_complete, ImageDecoder::kAlphaNotPremultiplied,
2824         ImageDecoder::kDefaultBitDepth,
2825         ignore_color_space ? ColorBehavior::Ignore()
2826                            : ColorBehavior::TransformToSRGB(),
2827         ImageDecoder::OverrideAllowDecodeToYuv::kDeny));
2828     if (!decoder || !decoder->FrameCount())
2829       return;
2830     ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
2831     if (!frame || frame->GetStatus() != ImageFrame::kFrameComplete)
2832       return;
2833     has_alpha = frame->HasAlpha();
2834     SkBitmap bitmap = frame->Bitmap();
2835     if (!FrameIsValid(bitmap))
2836       return;
2837 
2838     // TODO(fmalita): Partial frames are not supported currently: only fully
2839     // decoded frames make it through.  We could potentially relax this and
2840     // use SkImage::MakeFromBitmap(bitmap) to make a copy.
2841     skia_image = frame->FinalizePixelsAndGetImage();
2842     info = bitmap.info();
2843 
2844     if (has_alpha && premultiply_alpha)
2845       alpha_op_ = kAlphaDoPremultiply;
2846   } else if (!premultiply_alpha && has_alpha) {
2847     // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha
2848     //    had been applied and the alpha value for each pixel is 0xFF.  This is
2849     //    true at present; if it is changed in the future it will need
2850     //    adjustment accordingly.
2851     // 2. For texImage2D with HTMLCanvasElement input in which alpha is already
2852     //    premultiplied in this port, do AlphaDoUnmultiply if
2853     //    UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
2854     if (image_html_dom_source_ != kHtmlDomVideo)
2855       alpha_op_ = kAlphaDoUnmultiply;
2856   }
2857 
2858   if (!skia_image)
2859     return;
2860 
2861 #if SK_B32_SHIFT
2862   image_source_format_ = kDataFormatRGBA8;
2863 #else
2864   image_source_format_ = kDataFormatBGRA8;
2865 #endif
2866   image_source_unpack_alignment_ =
2867       0;  // FIXME: this seems to always be zero - why use at all?
2868 
2869   DCHECK(skia_image->width());
2870   DCHECK(skia_image->height());
2871   image_width_ = skia_image->width();
2872   image_height_ = skia_image->height();
2873 
2874   // Fail if the image was downsampled because of memory limits.
2875   if (image_width_ != (unsigned)image_->width() ||
2876       image_height_ != (unsigned)image_->height())
2877     return;
2878 
2879   image_pixel_locker_.emplace(std::move(skia_image), info.alphaType(),
2880                               kN32_SkColorType);
2881 }
2882 
GetChannelBitsByFormat(GLenum format)2883 unsigned WebGLImageConversion::GetChannelBitsByFormat(GLenum format) {
2884   switch (format) {
2885     case GL_ALPHA:
2886       return kChannelAlpha;
2887     case GL_RED:
2888     case GL_RED_INTEGER:
2889     case GL_R8:
2890     case GL_R8_SNORM:
2891     case GL_R8UI:
2892     case GL_R8I:
2893     case GL_R16UI:
2894     case GL_R16I:
2895     case GL_R32UI:
2896     case GL_R32I:
2897     case GL_R16F:
2898     case GL_R32F:
2899       return kChannelRed;
2900     case GL_RG:
2901     case GL_RG_INTEGER:
2902     case GL_RG8:
2903     case GL_RG8_SNORM:
2904     case GL_RG8UI:
2905     case GL_RG8I:
2906     case GL_RG16UI:
2907     case GL_RG16I:
2908     case GL_RG32UI:
2909     case GL_RG32I:
2910     case GL_RG16F:
2911     case GL_RG32F:
2912       return kChannelRG;
2913     case GL_LUMINANCE:
2914       return kChannelRGB;
2915     case GL_LUMINANCE_ALPHA:
2916       return kChannelRGBA;
2917     case GL_RGB:
2918     case GL_RGB_INTEGER:
2919     case GL_RGB8:
2920     case GL_RGB8_SNORM:
2921     case GL_RGB8UI:
2922     case GL_RGB8I:
2923     case GL_RGB16UI:
2924     case GL_RGB16I:
2925     case GL_RGB32UI:
2926     case GL_RGB32I:
2927     case GL_RGB16F:
2928     case GL_RGB32F:
2929     case GL_RGB565:
2930     case GL_R11F_G11F_B10F:
2931     case GL_RGB9_E5:
2932     case GL_SRGB_EXT:
2933     case GL_SRGB8:
2934       return kChannelRGB;
2935     case GL_RGBA:
2936     case GL_RGBA_INTEGER:
2937     case GL_RGBA8:
2938     case GL_RGBA8_SNORM:
2939     case GL_RGBA8UI:
2940     case GL_RGBA8I:
2941     case GL_RGBA16UI:
2942     case GL_RGBA16I:
2943     case GL_RGBA32UI:
2944     case GL_RGBA32I:
2945     case GL_RGBA16F:
2946     case GL_RGBA32F:
2947     case GL_RGBA4:
2948     case GL_RGB5_A1:
2949     case GL_RGB10_A2:
2950     case GL_RGB10_A2UI:
2951     case GL_SRGB_ALPHA_EXT:
2952     case GL_SRGB8_ALPHA8:
2953       return kChannelRGBA;
2954     case GL_DEPTH_COMPONENT:
2955     case GL_DEPTH_COMPONENT16:
2956     case GL_DEPTH_COMPONENT24:
2957     case GL_DEPTH_COMPONENT32F:
2958       return kChannelDepth;
2959     case GL_STENCIL:
2960     case GL_STENCIL_INDEX8:
2961       return kChannelStencil;
2962     case GL_DEPTH_STENCIL:
2963     case GL_DEPTH24_STENCIL8:
2964     case GL_DEPTH32F_STENCIL8:
2965       return kChannelDepthStencil;
2966     default:
2967       return 0;
2968   }
2969 }
2970 
PackImageData(Image * image,const void * pixels,GLenum format,GLenum type,bool flip_y,AlphaOp alpha_op,DataFormat source_format,unsigned source_image_width,unsigned source_image_height,const IntRect & source_image_sub_rectangle,int depth,unsigned source_unpack_alignment,int unpack_image_height,Vector<uint8_t> & data)2971 bool WebGLImageConversion::PackImageData(
2972     Image* image,
2973     const void* pixels,
2974     GLenum format,
2975     GLenum type,
2976     bool flip_y,
2977     AlphaOp alpha_op,
2978     DataFormat source_format,
2979     unsigned source_image_width,
2980     unsigned source_image_height,
2981     const IntRect& source_image_sub_rectangle,
2982     int depth,
2983     unsigned source_unpack_alignment,
2984     int unpack_image_height,
2985     Vector<uint8_t>& data) {
2986   if (!pixels)
2987     return false;
2988 
2989   unsigned packed_size;
2990   // Output data is tightly packed (alignment == 1).
2991   PixelStoreParams params;
2992   params.alignment = 1;
2993   if (ComputeImageSizeInBytes(format, type, source_image_sub_rectangle.Width(),
2994                               source_image_sub_rectangle.Height(), depth,
2995                               params, &packed_size, nullptr,
2996                               nullptr) != GL_NO_ERROR)
2997     return false;
2998   data.resize(packed_size);
2999 
3000   return PackPixels(reinterpret_cast<const uint8_t*>(pixels), source_format,
3001                     source_image_width, source_image_height,
3002                     source_image_sub_rectangle, depth, source_unpack_alignment,
3003                     unpack_image_height, format, type, alpha_op, data.data(),
3004                     flip_y);
3005 }
3006 
ExtractImageData(const uint8_t * image_data,DataFormat source_data_format,const IntSize & image_data_size,const IntRect & source_image_sub_rectangle,int depth,int unpack_image_height,GLenum format,GLenum type,bool flip_y,bool premultiply_alpha,Vector<uint8_t> & data)3007 bool WebGLImageConversion::ExtractImageData(
3008     const uint8_t* image_data,
3009     DataFormat source_data_format,
3010     const IntSize& image_data_size,
3011     const IntRect& source_image_sub_rectangle,
3012     int depth,
3013     int unpack_image_height,
3014     GLenum format,
3015     GLenum type,
3016     bool flip_y,
3017     bool premultiply_alpha,
3018     Vector<uint8_t>& data) {
3019   if (!image_data)
3020     return false;
3021   int width = image_data_size.Width();
3022   int height = image_data_size.Height();
3023 
3024   unsigned packed_size;
3025   // Output data is tightly packed (alignment == 1).
3026   PixelStoreParams params;
3027   params.alignment = 1;
3028   if (ComputeImageSizeInBytes(format, type, source_image_sub_rectangle.Width(),
3029                               source_image_sub_rectangle.Height(), depth,
3030                               params, &packed_size, nullptr,
3031                               nullptr) != GL_NO_ERROR)
3032     return false;
3033   data.resize(packed_size);
3034 
3035   if (!PackPixels(image_data, source_data_format, width, height,
3036                   source_image_sub_rectangle, depth, 0, unpack_image_height,
3037                   format, type,
3038                   premultiply_alpha ? kAlphaDoPremultiply : kAlphaDoNothing,
3039                   data.data(), flip_y))
3040     return false;
3041 
3042   return true;
3043 }
3044 
ExtractTextureData(unsigned width,unsigned height,GLenum format,GLenum type,const PixelStoreParams & unpack_params,bool flip_y,bool premultiply_alpha,const void * pixels,Vector<uint8_t> & data)3045 bool WebGLImageConversion::ExtractTextureData(
3046     unsigned width,
3047     unsigned height,
3048     GLenum format,
3049     GLenum type,
3050     const PixelStoreParams& unpack_params,
3051     bool flip_y,
3052     bool premultiply_alpha,
3053     const void* pixels,
3054     Vector<uint8_t>& data) {
3055   // Assumes format, type, etc. have already been validated.
3056   DataFormat source_data_format = GetDataFormat(format, type);
3057   if (source_data_format == kDataFormatNumFormats)
3058     return false;
3059 
3060   // Resize the output buffer.
3061   unsigned int components_per_pixel, bytes_per_component;
3062   if (!ComputeFormatAndTypeParameters(format, type, &components_per_pixel,
3063                                       &bytes_per_component))
3064     return false;
3065   unsigned bytes_per_pixel = components_per_pixel * bytes_per_component;
3066   data.resize(width * height * bytes_per_pixel);
3067 
3068   unsigned image_size_in_bytes, skip_size_in_bytes;
3069   ComputeImageSizeInBytes(format, type, width, height, 1, unpack_params,
3070                           &image_size_in_bytes, nullptr, &skip_size_in_bytes);
3071   const uint8_t* src_data = static_cast<const uint8_t*>(pixels);
3072   if (skip_size_in_bytes) {
3073     src_data += skip_size_in_bytes;
3074   }
3075 
3076   if (!PackPixels(src_data, source_data_format,
3077                   unpack_params.row_length ? unpack_params.row_length : width,
3078                   height, IntRect(0, 0, width, height), 1,
3079                   unpack_params.alignment, 0, format, type,
3080                   (premultiply_alpha ? kAlphaDoPremultiply : kAlphaDoNothing),
3081                   data.data(), flip_y))
3082     return false;
3083 
3084   return true;
3085 }
3086 
PackPixels(const uint8_t * source_data,DataFormat source_data_format,unsigned source_data_width,unsigned source_data_height,const IntRect & source_data_sub_rectangle,int depth,unsigned source_unpack_alignment,int unpack_image_height,unsigned destination_format,unsigned destination_type,AlphaOp alpha_op,void * destination_data,bool flip_y)3087 bool WebGLImageConversion::PackPixels(const uint8_t* source_data,
3088                                       DataFormat source_data_format,
3089                                       unsigned source_data_width,
3090                                       unsigned source_data_height,
3091                                       const IntRect& source_data_sub_rectangle,
3092                                       int depth,
3093                                       unsigned source_unpack_alignment,
3094                                       int unpack_image_height,
3095                                       unsigned destination_format,
3096                                       unsigned destination_type,
3097                                       AlphaOp alpha_op,
3098                                       void* destination_data,
3099                                       bool flip_y) {
3100   DCHECK_GE(depth, 1);
3101   if (unpack_image_height == 0) {
3102     unpack_image_height = source_data_sub_rectangle.Height();
3103   }
3104   int valid_src = source_data_width * TexelBytesForFormat(source_data_format);
3105   int remainder =
3106       source_unpack_alignment ? (valid_src % source_unpack_alignment) : 0;
3107   int src_stride =
3108       remainder ? (valid_src + source_unpack_alignment - remainder) : valid_src;
3109   int src_row_offset =
3110       source_data_sub_rectangle.X() * TexelBytesForFormat(source_data_format);
3111 
3112   DataFormat dst_data_format =
3113       GetDataFormat(destination_format, destination_type);
3114   if (dst_data_format == kDataFormatNumFormats)
3115     return false;
3116   int dst_stride =
3117       source_data_sub_rectangle.Width() * TexelBytesForFormat(dst_data_format);
3118   if (flip_y) {
3119     destination_data =
3120         static_cast<uint8_t*>(destination_data) +
3121         dst_stride * ((depth * source_data_sub_rectangle.Height()) - 1);
3122     dst_stride = -dst_stride;
3123   }
3124   if (!HasAlpha(source_data_format) || !HasColor(source_data_format) ||
3125       !HasColor(dst_data_format))
3126     alpha_op = kAlphaDoNothing;
3127 
3128   if (source_data_format == dst_data_format && alpha_op == kAlphaDoNothing) {
3129     const uint8_t* base_ptr =
3130         source_data + src_stride * source_data_sub_rectangle.Y();
3131     const uint8_t* base_end =
3132         source_data + src_stride * source_data_sub_rectangle.MaxY();
3133 
3134     // If packing multiple images into a 3D texture, and flipY is true,
3135     // then the sub-rectangle is pointing at the start of the
3136     // "bottommost" of those images. Since the source pointer strides in
3137     // the positive direction, we need to back it up to point at the
3138     // last, or "topmost", of these images.
3139     if (flip_y && depth > 1) {
3140       const ptrdiff_t distance_to_top_image =
3141           (depth - 1) * src_stride * unpack_image_height;
3142       base_ptr -= distance_to_top_image;
3143       base_end -= distance_to_top_image;
3144     }
3145 
3146     unsigned row_size = (dst_stride > 0) ? dst_stride : -dst_stride;
3147     uint8_t* dst = static_cast<uint8_t*>(destination_data);
3148 
3149     for (int i = 0; i < depth; ++i) {
3150       const uint8_t* ptr = base_ptr;
3151       const uint8_t* ptr_end = base_end;
3152       while (ptr < ptr_end) {
3153         memcpy(dst, ptr + src_row_offset, row_size);
3154         ptr += src_stride;
3155         dst += dst_stride;
3156       }
3157       base_ptr += unpack_image_height * src_stride;
3158       base_end += unpack_image_height * src_stride;
3159     }
3160     return true;
3161   }
3162 
3163   FormatConverter converter(source_data_sub_rectangle, depth,
3164                             unpack_image_height, source_data, destination_data,
3165                             src_stride, src_row_offset, dst_stride);
3166   converter.Convert(source_data_format, dst_data_format, alpha_op);
3167   if (!converter.Success())
3168     return false;
3169   return true;
3170 }
3171 
UnpackPixels(const uint16_t * source_data,DataFormat source_data_format,unsigned pixels_per_row,uint8_t * destination_data)3172 void WebGLImageConversion::UnpackPixels(const uint16_t* source_data,
3173                                         DataFormat source_data_format,
3174                                         unsigned pixels_per_row,
3175                                         uint8_t* destination_data) {
3176   switch (source_data_format) {
3177     case kDataFormatRGBA4444: {
3178       typedef typename DataTypeForFormat<
3179           WebGLImageConversion::kDataFormatRGBA4444>::Type SrcType;
3180       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3181       Unpack<WebGLImageConversion::kDataFormatRGBA4444>(
3182           src_row_start, destination_data, pixels_per_row);
3183     } break;
3184     case kDataFormatRGBA5551: {
3185       typedef typename DataTypeForFormat<
3186           WebGLImageConversion::kDataFormatRGBA5551>::Type SrcType;
3187       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3188       Unpack<WebGLImageConversion::kDataFormatRGBA5551>(
3189           src_row_start, destination_data, pixels_per_row);
3190     } break;
3191     case kDataFormatBGRA8: {
3192       const uint8_t* psrc = (const uint8_t*)source_data;
3193       typedef typename DataTypeForFormat<
3194           WebGLImageConversion::kDataFormatBGRA8>::Type SrcType;
3195       const SrcType* src_row_start = static_cast<const SrcType*>(psrc);
3196       Unpack<WebGLImageConversion::kDataFormatBGRA8>(
3197           src_row_start, destination_data, pixels_per_row);
3198     } break;
3199     default:
3200       break;
3201   }
3202 }
3203 
PackPixels(const uint8_t * source_data,DataFormat source_data_format,unsigned pixels_per_row,uint8_t * destination_data)3204 void WebGLImageConversion::PackPixels(const uint8_t* source_data,
3205                                       DataFormat source_data_format,
3206                                       unsigned pixels_per_row,
3207                                       uint8_t* destination_data) {
3208   switch (source_data_format) {
3209     case kDataFormatRA8: {
3210       typedef typename DataTypeForFormat<
3211           WebGLImageConversion::kDataFormatRGBA8>::Type SrcType;
3212       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3213       Pack<WebGLImageConversion::kDataFormatRA8,
3214            WebGLImageConversion::kAlphaDoUnmultiply>(
3215           src_row_start, destination_data, pixels_per_row);
3216     } break;
3217     case kDataFormatR8: {
3218       typedef typename DataTypeForFormat<
3219           WebGLImageConversion::kDataFormatRGBA8>::Type SrcType;
3220       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3221       Pack<WebGLImageConversion::kDataFormatR8,
3222            WebGLImageConversion::kAlphaDoUnmultiply>(
3223           src_row_start, destination_data, pixels_per_row);
3224     } break;
3225     case kDataFormatRGBA8: {
3226       typedef typename DataTypeForFormat<
3227           WebGLImageConversion::kDataFormatRGBA8>::Type SrcType;
3228       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3229       Pack<WebGLImageConversion::kDataFormatRGBA8,
3230            WebGLImageConversion::kAlphaDoUnmultiply>(
3231           src_row_start, destination_data, pixels_per_row);
3232     } break;
3233     case kDataFormatRGBA4444: {
3234       uint16_t* pdst = (uint16_t*)destination_data;
3235       typedef typename DataTypeForFormat<
3236           WebGLImageConversion::kDataFormatRGBA8>::Type SrcType;
3237       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3238       typedef typename DataTypeForFormat<
3239           WebGLImageConversion::kDataFormatRGBA4444>::Type DstType;
3240       DstType* dst_row_start = static_cast<DstType*>(pdst);
3241       Pack<WebGLImageConversion::kDataFormatRGBA4444,
3242            WebGLImageConversion::kAlphaDoNothing>(src_row_start, dst_row_start,
3243                                                   pixels_per_row);
3244     } break;
3245     case kDataFormatRGBA5551: {
3246       uint16_t* pdst = (uint16_t*)destination_data;
3247       typedef typename DataTypeForFormat<
3248           WebGLImageConversion::kDataFormatRGBA8>::Type SrcType;
3249       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3250       typedef typename DataTypeForFormat<
3251           WebGLImageConversion::kDataFormatRGBA5551>::Type DstType;
3252       DstType* dst_row_start = static_cast<DstType*>(pdst);
3253       Pack<WebGLImageConversion::kDataFormatRGBA5551,
3254            WebGLImageConversion::kAlphaDoNothing>(src_row_start, dst_row_start,
3255                                                   pixels_per_row);
3256     } break;
3257     case kDataFormatRGB565: {
3258       uint16_t* pdst = (uint16_t*)destination_data;
3259       typedef typename DataTypeForFormat<
3260           WebGLImageConversion::kDataFormatRGBA8>::Type SrcType;
3261       const SrcType* src_row_start = static_cast<const SrcType*>(source_data);
3262       typedef typename DataTypeForFormat<
3263           WebGLImageConversion::kDataFormatRGB565>::Type DstType;
3264       DstType* dst_row_start = static_cast<DstType*>(pdst);
3265       Pack<WebGLImageConversion::kDataFormatRGB565,
3266            WebGLImageConversion::kAlphaDoNothing>(src_row_start, dst_row_start,
3267                                                   pixels_per_row);
3268     } break;
3269     default:
3270       break;
3271   }
3272 }
3273 
3274 }  // namespace blink
3275