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