Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / gpu / WebGLImageConversion.cpp
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 "config.h"
6 #include "platform/graphics/gpu/WebGLImageConversion.h"
7
8 #include "platform/CheckedInt.h"
9 #include "platform/graphics/ImageObserver.h"
10 #include "platform/graphics/cpu/arm/WebGLImageConversionNEON.h"
11 #include "platform/image-decoders/ImageDecoder.h"
12 #include "wtf/OwnPtr.h"
13 #include "wtf/PassOwnPtr.h"
14
15 namespace blink {
16
17 namespace {
18
19 WebGLImageConversion::DataFormat getDataFormat(GLenum destinationFormat, GLenum destinationType)
20 {
21     WebGLImageConversion::DataFormat dstFormat = WebGLImageConversion::DataFormatRGBA8;
22     switch (destinationType) {
23     case GL_UNSIGNED_BYTE:
24         switch (destinationFormat) {
25         case GL_RGB:
26             dstFormat = WebGLImageConversion::DataFormatRGB8;
27             break;
28         case GL_RGBA:
29             dstFormat = WebGLImageConversion::DataFormatRGBA8;
30             break;
31         case GL_ALPHA:
32             dstFormat = WebGLImageConversion::DataFormatA8;
33             break;
34         case GL_LUMINANCE:
35             dstFormat = WebGLImageConversion::DataFormatR8;
36             break;
37         case GL_LUMINANCE_ALPHA:
38             dstFormat = WebGLImageConversion::DataFormatRA8;
39             break;
40         default:
41             ASSERT_NOT_REACHED();
42         }
43         break;
44     case GL_UNSIGNED_SHORT_4_4_4_4:
45         dstFormat = WebGLImageConversion::DataFormatRGBA4444;
46         break;
47     case GL_UNSIGNED_SHORT_5_5_5_1:
48         dstFormat = WebGLImageConversion::DataFormatRGBA5551;
49         break;
50     case GL_UNSIGNED_SHORT_5_6_5:
51         dstFormat = WebGLImageConversion::DataFormatRGB565;
52         break;
53     case GL_HALF_FLOAT_OES: // OES_texture_half_float
54         switch (destinationFormat) {
55         case GL_RGB:
56             dstFormat = WebGLImageConversion::DataFormatRGB16F;
57             break;
58         case GL_RGBA:
59             dstFormat = WebGLImageConversion::DataFormatRGBA16F;
60             break;
61         case GL_ALPHA:
62             dstFormat = WebGLImageConversion::DataFormatA16F;
63             break;
64         case GL_LUMINANCE:
65             dstFormat = WebGLImageConversion::DataFormatR16F;
66             break;
67         case GL_LUMINANCE_ALPHA:
68             dstFormat = WebGLImageConversion::DataFormatRA16F;
69             break;
70         default:
71             ASSERT_NOT_REACHED();
72         }
73         break;
74     case GL_FLOAT: // OES_texture_float
75         switch (destinationFormat) {
76         case GL_RGB:
77             dstFormat = WebGLImageConversion::DataFormatRGB32F;
78             break;
79         case GL_RGBA:
80             dstFormat = WebGLImageConversion::DataFormatRGBA32F;
81             break;
82         case GL_ALPHA:
83             dstFormat = WebGLImageConversion::DataFormatA32F;
84             break;
85         case GL_LUMINANCE:
86             dstFormat = WebGLImageConversion::DataFormatR32F;
87             break;
88         case GL_LUMINANCE_ALPHA:
89             dstFormat = WebGLImageConversion::DataFormatRA32F;
90             break;
91         default:
92             ASSERT_NOT_REACHED();
93         }
94         break;
95     default:
96         ASSERT_NOT_REACHED();
97     }
98     return dstFormat;
99 }
100
101 // Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf,
102 // "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010).
103 // Specially, the basetable[512] and shifttable[512] are generated as follows:
104 /*
105 unsigned short basetable[512];
106 unsigned char shifttable[512];
107
108 void generatetables(){
109     unsigned int i;
110     int e;
111     for (i = 0; i < 256; ++i){
112         e = i - 127;
113         if (e < -24){ // Very small numbers map to zero
114             basetable[i | 0x000] = 0x0000;
115             basetable[i | 0x100] = 0x8000;
116             shifttable[i | 0x000] = 24;
117             shifttable[i | 0x100] = 24;
118         }
119         else if (e < -14) { // Small numbers map to denorms
120             basetable[i | 0x000] = (0x0400>>(-e-14));
121             basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000;
122             shifttable[i | 0x000] = -e-1;
123             shifttable[i | 0x100] = -e-1;
124         }
125         else if (e <= 15){ // Normal numbers just lose precision
126             basetable[i | 0x000] = ((e+15)<<10);
127             basetable[i| 0x100] = ((e+15)<<10) | 0x8000;
128             shifttable[i|0x000] = 13;
129             shifttable[i|0x100] = 13;
130         }
131         else if (e<128){ // Large numbers map to Infinity
132             basetable[i|0x000] = 0x7C00;
133             basetable[i|0x100] = 0xFC00;
134             shifttable[i|0x000] = 24;
135             shifttable[i|0x100] = 24;
136         }
137         else { // Infinity and NaN's stay Infinity and NaN's
138             basetable[i|0x000] = 0x7C00;
139             basetable[i|0x100] = 0xFC00;
140             shifttable[i|0x000] = 13;
141             shifttable[i|0x100] = 13;
142        }
143     }
144 }
145 */
146
147 unsigned short baseTable[512] = {
148 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
149 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
150 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
151 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
152 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
153 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
154 0,      0,      0,      0,      0,      0,      0,      1,      2,      4,      8,      16,     32,     64,     128,    256,
155 512,    1024,   2048,   3072,   4096,   5120,   6144,   7168,   8192,   9216,   10240,  11264,  12288,  13312,  14336,  15360,
156 16384,  17408,  18432,  19456,  20480,  21504,  22528,  23552,  24576,  25600,  26624,  27648,  28672,  29696,  30720,  31744,
157 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
158 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
159 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
160 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
161 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
162 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
163 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
164 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
165 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
166 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
167 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
168 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
169 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
170 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32769,  32770,  32772,  32776,  32784,  32800,  32832,  32896,  33024,
171 33280,  33792,  34816,  35840,  36864,  37888,  38912,  39936,  40960,  41984,  43008,  44032,  45056,  46080,  47104,  48128,
172 49152,  50176,  51200,  52224,  53248,  54272,  55296,  56320,  57344,  58368,  59392,  60416,  61440,  62464,  63488,  64512,
173 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
174 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
175 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
176 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
177 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
178 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
179 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512
180 };
181
182 unsigned char shiftTable[512] = {
183 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
184 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
185 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
186 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
187 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
188 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
189 24,     24,     24,     24,     24,     24,     24,     23,     22,     21,     20,     19,     18,     17,     16,     15,
190 14,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,
191 13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     24,
192 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
193 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
194 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
195 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
196 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
197 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
198 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     13,
199 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
200 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
201 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
202 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
203 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
204 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
205 24,     24,     24,     24,     24,     24,     24,     23,     22,     21,     20,     19,     18,     17,     16,     15,
206 14,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,
207 13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     24,
208 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
209 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
210 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
211 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
212 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
213 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
214 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     13
215 };
216
217 unsigned short convertFloatToHalfFloat(float f)
218 {
219     unsigned temp = *(reinterpret_cast<unsigned *>(&f));
220     unsigned signexp = (temp >> 23) & 0x1ff;
221     return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]);
222 }
223
224 /* BEGIN CODE SHARED WITH MOZILLA FIREFOX */
225
226 // The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup.
227 // Explicit template specializations correspond to the cases that would occur.
228 // Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h
229
230 //----------------------------------------------------------------------
231 // Pixel unpacking routines.
232 template<int format, typename SourceType, typename DstType>
233 void unpack(const SourceType*, DstType*, unsigned)
234 {
235     ASSERT_NOT_REACHED();
236 }
237
238 template<> void unpack<WebGLImageConversion::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
239 {
240     for (unsigned i = 0; i < pixelsPerRow; ++i) {
241         destination[0] = source[0];
242         destination[1] = source[1];
243         destination[2] = source[2];
244         destination[3] = 0xFF;
245         source += 3;
246         destination += 4;
247     }
248 }
249
250 template<> void unpack<WebGLImageConversion::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
251 {
252     for (unsigned i = 0; i < pixelsPerRow; ++i) {
253         destination[0] = source[2];
254         destination[1] = source[1];
255         destination[2] = source[0];
256         destination[3] = 0xFF;
257         source += 3;
258         destination += 4;
259     }
260 }
261
262 template<> void unpack<WebGLImageConversion::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
263 {
264     for (unsigned i = 0; i < pixelsPerRow; ++i) {
265         destination[0] = source[1];
266         destination[1] = source[2];
267         destination[2] = source[3];
268         destination[3] = source[0];
269         source += 4;
270         destination += 4;
271     }
272 }
273
274 template<> void unpack<WebGLImageConversion::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
275 {
276     for (unsigned i = 0; i < pixelsPerRow; ++i) {
277         destination[0] = source[3];
278         destination[1] = source[2];
279         destination[2] = source[1];
280         destination[3] = source[0];
281         source += 4;
282         destination += 4;
283     }
284 }
285
286 template<> void unpack<WebGLImageConversion::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
287 {
288     const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
289     uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
290     for (unsigned i = 0; i < pixelsPerRow; ++i) {
291         uint32_t bgra = source32[i];
292 #if CPU(BIG_ENDIAN)
293         uint32_t brMask = 0xff00ff00;
294         uint32_t gaMask = 0x00ff00ff;
295 #else
296         uint32_t brMask = 0x00ff00ff;
297         uint32_t gaMask = 0xff00ff00;
298 #endif
299         uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask);
300         destination32[i] = rgba;
301     }
302 }
303
304 template<> void unpack<WebGLImageConversion::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
305 {
306 #if HAVE(ARM_NEON_INTRINSICS)
307     SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow);
308 #endif
309     for (unsigned i = 0; i < pixelsPerRow; ++i) {
310         uint16_t packedValue = source[0];
311         uint8_t r = packedValue >> 11;
312         uint8_t g = (packedValue >> 6) & 0x1F;
313         uint8_t b = (packedValue >> 1) & 0x1F;
314         destination[0] = (r << 3) | (r & 0x7);
315         destination[1] = (g << 3) | (g & 0x7);
316         destination[2] = (b << 3) | (b & 0x7);
317         destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
318         source += 1;
319         destination += 4;
320     }
321 }
322
323 template<> void unpack<WebGLImageConversion::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
324 {
325 #if HAVE(ARM_NEON_INTRINSICS)
326     SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow);
327 #endif
328     for (unsigned i = 0; i < pixelsPerRow; ++i) {
329         uint16_t packedValue = source[0];
330         uint8_t r = packedValue >> 12;
331         uint8_t g = (packedValue >> 8) & 0x0F;
332         uint8_t b = (packedValue >> 4) & 0x0F;
333         uint8_t a = packedValue & 0x0F;
334         destination[0] = r << 4 | r;
335         destination[1] = g << 4 | g;
336         destination[2] = b << 4 | b;
337         destination[3] = a << 4 | a;
338         source += 1;
339         destination += 4;
340     }
341 }
342
343 template<> void unpack<WebGLImageConversion::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
344 {
345 #if HAVE(ARM_NEON_INTRINSICS)
346     SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow);
347 #endif
348     for (unsigned i = 0; i < pixelsPerRow; ++i) {
349         uint16_t packedValue = source[0];
350         uint8_t r = packedValue >> 11;
351         uint8_t g = (packedValue >> 5) & 0x3F;
352         uint8_t b = packedValue & 0x1F;
353         destination[0] = (r << 3) | (r & 0x7);
354         destination[1] = (g << 2) | (g & 0x3);
355         destination[2] = (b << 3) | (b & 0x7);
356         destination[3] = 0xFF;
357         source += 1;
358         destination += 4;
359     }
360 }
361
362 template<> void unpack<WebGLImageConversion::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
363 {
364     for (unsigned i = 0; i < pixelsPerRow; ++i) {
365         destination[0] = source[0];
366         destination[1] = source[0];
367         destination[2] = source[0];
368         destination[3] = 0xFF;
369         source += 1;
370         destination += 4;
371     }
372 }
373
374 template<> void unpack<WebGLImageConversion::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
375 {
376     for (unsigned i = 0; i < pixelsPerRow; ++i) {
377         destination[0] = source[0];
378         destination[1] = source[0];
379         destination[2] = source[0];
380         destination[3] = source[1];
381         source += 2;
382         destination += 4;
383     }
384 }
385
386 template<> void unpack<WebGLImageConversion::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
387 {
388     for (unsigned i = 0; i < pixelsPerRow; ++i) {
389         destination[0] = source[1];
390         destination[1] = source[1];
391         destination[2] = source[1];
392         destination[3] = source[0];
393         source += 2;
394         destination += 4;
395     }
396 }
397
398 template<> void unpack<WebGLImageConversion::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
399 {
400     for (unsigned i = 0; i < pixelsPerRow; ++i) {
401         destination[0] = 0x0;
402         destination[1] = 0x0;
403         destination[2] = 0x0;
404         destination[3] = source[0];
405         source += 1;
406         destination += 4;
407     }
408 }
409
410 template<> void unpack<WebGLImageConversion::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
411 {
412     const float scaleFactor = 1.0f / 255.0f;
413     for (unsigned i = 0; i < pixelsPerRow; ++i) {
414         destination[0] = source[0] * scaleFactor;
415         destination[1] = source[1] * scaleFactor;
416         destination[2] = source[2] * scaleFactor;
417         destination[3] = source[3] * scaleFactor;
418         source += 4;
419         destination += 4;
420     }
421 }
422
423 template<> void unpack<WebGLImageConversion::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
424 {
425     const float scaleFactor = 1.0f / 255.0f;
426     for (unsigned i = 0; i < pixelsPerRow; ++i) {
427         destination[0] = source[2] * scaleFactor;
428         destination[1] = source[1] * scaleFactor;
429         destination[2] = source[0] * scaleFactor;
430         destination[3] = source[3] * scaleFactor;
431         source += 4;
432         destination += 4;
433     }
434 }
435
436 template<> void unpack<WebGLImageConversion::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
437 {
438     const float scaleFactor = 1.0f / 255.0f;
439     for (unsigned i = 0; i < pixelsPerRow; ++i) {
440         destination[0] = source[3] * scaleFactor;
441         destination[1] = source[2] * scaleFactor;
442         destination[2] = source[1] * scaleFactor;
443         destination[3] = source[0] * scaleFactor;
444         source += 4;
445         destination += 4;
446     }
447 }
448
449 template<> void unpack<WebGLImageConversion::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
450 {
451     const float scaleFactor = 1.0f / 255.0f;
452     for (unsigned i = 0; i < pixelsPerRow; ++i) {
453         destination[0] = source[1] * scaleFactor;
454         destination[1] = source[2] * scaleFactor;
455         destination[2] = source[3] * scaleFactor;
456         destination[3] = source[0] * scaleFactor;
457         source += 4;
458         destination += 4;
459     }
460 }
461
462 template<> void unpack<WebGLImageConversion::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
463 {
464     const float scaleFactor = 1.0f / 255.0f;
465     for (unsigned i = 0; i < pixelsPerRow; ++i) {
466         destination[0] = source[0] * scaleFactor;
467         destination[1] = source[1] * scaleFactor;
468         destination[2] = source[2] * scaleFactor;
469         destination[3] = 1;
470         source += 3;
471         destination += 4;
472     }
473 }
474
475 template<> void unpack<WebGLImageConversion::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
476 {
477     const float scaleFactor = 1.0f / 255.0f;
478     for (unsigned i = 0; i < pixelsPerRow; ++i) {
479         destination[0] = source[2] * scaleFactor;
480         destination[1] = source[1] * scaleFactor;
481         destination[2] = source[0] * scaleFactor;
482         destination[3] = 1;
483         source += 3;
484         destination += 4;
485     }
486 }
487
488 template<> void unpack<WebGLImageConversion::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
489 {
490     for (unsigned i = 0; i < pixelsPerRow; ++i) {
491         destination[0] = source[0];
492         destination[1] = source[1];
493         destination[2] = source[2];
494         destination[3] = 1;
495         source += 3;
496         destination += 4;
497     }
498 }
499
500 template<> void unpack<WebGLImageConversion::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
501 {
502     for (unsigned i = 0; i < pixelsPerRow; ++i) {
503         destination[0] = source[0];
504         destination[1] = source[0];
505         destination[2] = source[0];
506         destination[3] = 1;
507         source += 1;
508         destination += 4;
509     }
510 }
511
512 template<> void unpack<WebGLImageConversion::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
513 {
514     for (unsigned i = 0; i < pixelsPerRow; ++i) {
515         destination[0] = source[0];
516         destination[1] = source[0];
517         destination[2] = source[0];
518         destination[3] = source[1];
519         source += 2;
520         destination += 4;
521     }
522 }
523
524 template<> void unpack<WebGLImageConversion::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
525 {
526     for (unsigned i = 0; i < pixelsPerRow; ++i) {
527         destination[0] = 0;
528         destination[1] = 0;
529         destination[2] = 0;
530         destination[3] = source[0];
531         source += 1;
532         destination += 4;
533     }
534 }
535
536 //----------------------------------------------------------------------
537 // Pixel packing routines.
538 //
539
540 template<int format, int alphaOp, typename SourceType, typename DstType>
541 void pack(const SourceType*, DstType*, unsigned)
542 {
543     ASSERT_NOT_REACHED();
544 }
545
546 template<> void pack<WebGLImageConversion::DataFormatA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
547 {
548     for (unsigned i = 0; i < pixelsPerRow; ++i) {
549         destination[0] = source[3];
550         source += 4;
551         destination += 1;
552     }
553 }
554
555 template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
556 {
557     for (unsigned i = 0; i < pixelsPerRow; ++i) {
558         destination[0] = source[0];
559         source += 4;
560         destination += 1;
561     }
562 }
563
564 template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
565 {
566     for (unsigned i = 0; i < pixelsPerRow; ++i) {
567         float scaleFactor = source[3] / 255.0f;
568         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
569         destination[0] = sourceR;
570         source += 4;
571         destination += 1;
572     }
573 }
574
575 // FIXME: this routine is lossy and must be removed.
576 template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
577 {
578     for (unsigned i = 0; i < pixelsPerRow; ++i) {
579         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
580         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
581         destination[0] = sourceR;
582         source += 4;
583         destination += 1;
584     }
585 }
586
587 template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
588 {
589     for (unsigned i = 0; i < pixelsPerRow; ++i) {
590         destination[0] = source[0];
591         destination[1] = source[3];
592         source += 4;
593         destination += 2;
594     }
595 }
596
597 template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
598 {
599     for (unsigned i = 0; i < pixelsPerRow; ++i) {
600         float scaleFactor = source[3] / 255.0f;
601         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
602         destination[0] = sourceR;
603         destination[1] = source[3];
604         source += 4;
605         destination += 2;
606     }
607 }
608
609 // FIXME: this routine is lossy and must be removed.
610 template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
611 {
612     for (unsigned i = 0; i < pixelsPerRow; ++i) {
613         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
614         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
615         destination[0] = sourceR;
616         destination[1] = source[3];
617         source += 4;
618         destination += 2;
619     }
620 }
621
622 template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
623 {
624     for (unsigned i = 0; i < pixelsPerRow; ++i) {
625         destination[0] = source[0];
626         destination[1] = source[1];
627         destination[2] = source[2];
628         source += 4;
629         destination += 3;
630     }
631 }
632
633 template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
634 {
635     for (unsigned i = 0; i < pixelsPerRow; ++i) {
636         float scaleFactor = source[3] / 255.0f;
637         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
638         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
639         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
640         destination[0] = sourceR;
641         destination[1] = sourceG;
642         destination[2] = sourceB;
643         source += 4;
644         destination += 3;
645     }
646 }
647
648 // FIXME: this routine is lossy and must be removed.
649 template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
650 {
651     for (unsigned i = 0; i < pixelsPerRow; ++i) {
652         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
653         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
654         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
655         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
656         destination[0] = sourceR;
657         destination[1] = sourceG;
658         destination[2] = sourceB;
659         source += 4;
660         destination += 3;
661     }
662 }
663
664
665 template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
666 {
667     memcpy(destination, source, pixelsPerRow * 4);
668 }
669
670 template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
671 {
672     for (unsigned i = 0; i < pixelsPerRow; ++i) {
673         float scaleFactor = source[3] / 255.0f;
674         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
675         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
676         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
677         destination[0] = sourceR;
678         destination[1] = sourceG;
679         destination[2] = sourceB;
680         destination[3] = source[3];
681         source += 4;
682         destination += 4;
683     }
684 }
685
686 // FIXME: this routine is lossy and must be removed.
687 template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
688 {
689     for (unsigned i = 0; i < pixelsPerRow; ++i) {
690         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
691         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
692         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
693         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
694         destination[0] = sourceR;
695         destination[1] = sourceG;
696         destination[2] = sourceB;
697         destination[3] = source[3];
698         source += 4;
699         destination += 4;
700     }
701 }
702
703 template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
704 {
705 #if HAVE(ARM_NEON_INTRINSICS)
706     SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow);
707 #endif
708     for (unsigned i = 0; i < pixelsPerRow; ++i) {
709         *destination = (((source[0] & 0xF0) << 8)
710                         | ((source[1] & 0xF0) << 4)
711                         | (source[2] & 0xF0)
712                         | (source[3] >> 4));
713         source += 4;
714         destination += 1;
715     }
716 }
717
718 template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
719 {
720     for (unsigned i = 0; i < pixelsPerRow; ++i) {
721         float scaleFactor = source[3] / 255.0f;
722         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
723         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
724         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
725         *destination = (((sourceR & 0xF0) << 8)
726                         | ((sourceG & 0xF0) << 4)
727                         | (sourceB & 0xF0)
728                         | (source[3] >> 4));
729         source += 4;
730         destination += 1;
731     }
732 }
733
734 // FIXME: this routine is lossy and must be removed.
735 template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
736 {
737     for (unsigned i = 0; i < pixelsPerRow; ++i) {
738         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
739         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
740         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
741         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
742         *destination = (((sourceR & 0xF0) << 8)
743                         | ((sourceG & 0xF0) << 4)
744                         | (sourceB & 0xF0)
745                         | (source[3] >> 4));
746         source += 4;
747         destination += 1;
748     }
749 }
750
751 template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
752 {
753 #if HAVE(ARM_NEON_INTRINSICS)
754     SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow);
755 #endif
756     for (unsigned i = 0; i < pixelsPerRow; ++i) {
757         *destination = (((source[0] & 0xF8) << 8)
758                         | ((source[1] & 0xF8) << 3)
759                         | ((source[2] & 0xF8) >> 2)
760                         | (source[3] >> 7));
761         source += 4;
762         destination += 1;
763     }
764 }
765
766 template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
767 {
768     for (unsigned i = 0; i < pixelsPerRow; ++i) {
769         float scaleFactor = source[3] / 255.0f;
770         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
771         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
772         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
773         *destination = (((sourceR & 0xF8) << 8)
774                         | ((sourceG & 0xF8) << 3)
775                         | ((sourceB & 0xF8) >> 2)
776                         | (source[3] >> 7));
777         source += 4;
778         destination += 1;
779     }
780 }
781
782 // FIXME: this routine is lossy and must be removed.
783 template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
784 {
785     for (unsigned i = 0; i < pixelsPerRow; ++i) {
786         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
787         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
788         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
789         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
790         *destination = (((sourceR & 0xF8) << 8)
791                         | ((sourceG & 0xF8) << 3)
792                         | ((sourceB & 0xF8) >> 2)
793                         | (source[3] >> 7));
794         source += 4;
795         destination += 1;
796     }
797 }
798
799 template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
800 {
801 #if HAVE(ARM_NEON_INTRINSICS)
802     SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow);
803 #endif
804     for (unsigned i = 0; i < pixelsPerRow; ++i) {
805         *destination = (((source[0] & 0xF8) << 8)
806                         | ((source[1] & 0xFC) << 3)
807                         | ((source[2] & 0xF8) >> 3));
808         source += 4;
809         destination += 1;
810     }
811 }
812
813 template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
814 {
815     for (unsigned i = 0; i < pixelsPerRow; ++i) {
816         float scaleFactor = source[3] / 255.0f;
817         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
818         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
819         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
820         *destination = (((sourceR & 0xF8) << 8)
821                         | ((sourceG & 0xFC) << 3)
822                         | ((sourceB & 0xF8) >> 3));
823         source += 4;
824         destination += 1;
825     }
826 }
827
828 // FIXME: this routine is lossy and must be removed.
829 template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
830 {
831     for (unsigned i = 0; i < pixelsPerRow; ++i) {
832         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
833         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
834         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
835         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
836         *destination = (((sourceR & 0xF8) << 8)
837                         | ((sourceG & 0xFC) << 3)
838                         | ((sourceB & 0xF8) >> 3));
839         source += 4;
840         destination += 1;
841     }
842 }
843
844 template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
845 {
846     for (unsigned i = 0; i < pixelsPerRow; ++i) {
847         destination[0] = source[0];
848         destination[1] = source[1];
849         destination[2] = source[2];
850         source += 4;
851         destination += 3;
852     }
853 }
854
855 template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
856 {
857     for (unsigned i = 0; i < pixelsPerRow; ++i) {
858         float scaleFactor = source[3];
859         destination[0] = source[0] * scaleFactor;
860         destination[1] = source[1] * scaleFactor;
861         destination[2] = source[2] * scaleFactor;
862         source += 4;
863         destination += 3;
864     }
865 }
866
867 template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
868 {
869     for (unsigned i = 0; i < pixelsPerRow; ++i) {
870         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
871         destination[0] = source[0] * scaleFactor;
872         destination[1] = source[1] * scaleFactor;
873         destination[2] = source[2] * scaleFactor;
874         source += 4;
875         destination += 3;
876     }
877 }
878
879 // Used only during RGBA8 or BGRA8 -> floating-point uploads.
880 template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
881 {
882     memcpy(destination, source, pixelsPerRow * 4 * sizeof(float));
883 }
884
885 template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
886 {
887     for (unsigned i = 0; i < pixelsPerRow; ++i) {
888         float scaleFactor = source[3];
889         destination[0] = source[0] * scaleFactor;
890         destination[1] = source[1] * scaleFactor;
891         destination[2] = source[2] * scaleFactor;
892         destination[3] = source[3];
893         source += 4;
894         destination += 4;
895     }
896 }
897
898 template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
899 {
900     for (unsigned i = 0; i < pixelsPerRow; ++i) {
901         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
902         destination[0] = source[0] * scaleFactor;
903         destination[1] = source[1] * scaleFactor;
904         destination[2] = source[2] * scaleFactor;
905         destination[3] = source[3];
906         source += 4;
907         destination += 4;
908     }
909 }
910
911 template<> void pack<WebGLImageConversion::DataFormatA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
912 {
913     for (unsigned i = 0; i < pixelsPerRow; ++i) {
914         destination[0] = source[3];
915         source += 4;
916         destination += 1;
917     }
918 }
919
920 template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
921 {
922     for (unsigned i = 0; i < pixelsPerRow; ++i) {
923         destination[0] = source[0];
924         source += 4;
925         destination += 1;
926     }
927 }
928
929 template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
930 {
931     for (unsigned i = 0; i < pixelsPerRow; ++i) {
932         float scaleFactor = source[3];
933         destination[0] = source[0] * scaleFactor;
934         source += 4;
935         destination += 1;
936     }
937 }
938
939 template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
940 {
941     for (unsigned i = 0; i < pixelsPerRow; ++i) {
942         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
943         destination[0] = source[0] * scaleFactor;
944         source += 4;
945         destination += 1;
946     }
947 }
948
949 template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
950 {
951     for (unsigned i = 0; i < pixelsPerRow; ++i) {
952         destination[0] = source[0];
953         destination[1] = source[3];
954         source += 4;
955         destination += 2;
956     }
957 }
958
959 template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
960 {
961     for (unsigned i = 0; i < pixelsPerRow; ++i) {
962         float scaleFactor = source[3];
963         destination[0] = source[0] * scaleFactor;
964         destination[1] = source[3];
965         source += 4;
966         destination += 2;
967     }
968 }
969
970 template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
971 {
972     for (unsigned i = 0; i < pixelsPerRow; ++i) {
973         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
974         destination[0] = source[0] * scaleFactor;
975         destination[1] = source[3];
976         source += 4;
977         destination += 2;
978     }
979 }
980
981 template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
982 {
983     for (unsigned i = 0; i < pixelsPerRow; ++i) {
984         destination[0] = convertFloatToHalfFloat(source[0]);
985         destination[1] = convertFloatToHalfFloat(source[1]);
986         destination[2] = convertFloatToHalfFloat(source[2]);
987         destination[3] = convertFloatToHalfFloat(source[3]);
988         source += 4;
989         destination += 4;
990     }
991 }
992
993 template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
994 {
995     for (unsigned i = 0; i < pixelsPerRow; ++i) {
996         float scaleFactor = source[3];
997         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
998         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
999         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
1000         destination[3] = convertFloatToHalfFloat(source[3]);
1001         source += 4;
1002         destination += 4;
1003     }
1004 }
1005
1006 template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1007 {
1008     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1009         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1010         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1011         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
1012         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
1013         destination[3] = convertFloatToHalfFloat(source[3]);
1014         source += 4;
1015         destination += 4;
1016     }
1017 }
1018
1019 template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1020 {
1021     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1022         destination[0] = convertFloatToHalfFloat(source[0]);
1023         destination[1] = convertFloatToHalfFloat(source[1]);
1024         destination[2] = convertFloatToHalfFloat(source[2]);
1025         source += 4;
1026         destination += 3;
1027     }
1028 }
1029
1030 template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1031 {
1032     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1033         float scaleFactor = source[3];
1034         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1035         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
1036         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
1037         source += 4;
1038         destination += 3;
1039     }
1040 }
1041
1042 template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1043 {
1044     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1045         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1046         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1047         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
1048         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
1049         source += 4;
1050         destination += 3;
1051     }
1052 }
1053
1054 template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1055 {
1056     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1057         destination[0] = convertFloatToHalfFloat(source[0]);
1058         destination[1] = convertFloatToHalfFloat(source[3]);
1059         source += 4;
1060         destination += 2;
1061     }
1062 }
1063
1064 template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1065 {
1066     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1067         float scaleFactor = source[3];
1068         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1069         destination[1] = convertFloatToHalfFloat(source[3]);
1070         source += 4;
1071         destination += 2;
1072     }
1073 }
1074
1075 template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1076 {
1077     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1078         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1079         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1080         destination[1] = convertFloatToHalfFloat(source[3]);
1081         source += 4;
1082         destination += 2;
1083     }
1084 }
1085
1086 template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1087 {
1088     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1089         destination[0] = convertFloatToHalfFloat(source[0]);
1090         source += 4;
1091         destination += 1;
1092     }
1093 }
1094
1095 template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1096 {
1097     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1098         float scaleFactor = source[3];
1099         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1100         source += 4;
1101         destination += 1;
1102     }
1103 }
1104
1105 template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1106 {
1107     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1108         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1109         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1110         source += 4;
1111         destination += 1;
1112     }
1113 }
1114
1115 template<> void pack<WebGLImageConversion::DataFormatA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1116 {
1117     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1118         destination[0] = convertFloatToHalfFloat(source[3]);
1119         source += 4;
1120         destination += 1;
1121     }
1122 }
1123
1124 bool HasAlpha(int format)
1125 {
1126     return format == WebGLImageConversion::DataFormatA8
1127         || format == WebGLImageConversion::DataFormatA16F
1128         || format == WebGLImageConversion::DataFormatA32F
1129         || format == WebGLImageConversion::DataFormatRA8
1130         || format == WebGLImageConversion::DataFormatAR8
1131         || format == WebGLImageConversion::DataFormatRA16F
1132         || format == WebGLImageConversion::DataFormatRA32F
1133         || format == WebGLImageConversion::DataFormatRGBA8
1134         || format == WebGLImageConversion::DataFormatBGRA8
1135         || format == WebGLImageConversion::DataFormatARGB8
1136         || format == WebGLImageConversion::DataFormatABGR8
1137         || format == WebGLImageConversion::DataFormatRGBA16F
1138         || format == WebGLImageConversion::DataFormatRGBA32F
1139         || format == WebGLImageConversion::DataFormatRGBA4444
1140         || format == WebGLImageConversion::DataFormatRGBA5551;
1141 }
1142
1143 bool HasColor(int format)
1144 {
1145     return format == WebGLImageConversion::DataFormatRGBA8
1146         || format == WebGLImageConversion::DataFormatRGBA16F
1147         || format == WebGLImageConversion::DataFormatRGBA32F
1148         || format == WebGLImageConversion::DataFormatRGB8
1149         || format == WebGLImageConversion::DataFormatRGB16F
1150         || format == WebGLImageConversion::DataFormatRGB32F
1151         || format == WebGLImageConversion::DataFormatBGR8
1152         || format == WebGLImageConversion::DataFormatBGRA8
1153         || format == WebGLImageConversion::DataFormatARGB8
1154         || format == WebGLImageConversion::DataFormatABGR8
1155         || format == WebGLImageConversion::DataFormatRGBA5551
1156         || format == WebGLImageConversion::DataFormatRGBA4444
1157         || format == WebGLImageConversion::DataFormatRGB565
1158         || format == WebGLImageConversion::DataFormatR8
1159         || format == WebGLImageConversion::DataFormatR16F
1160         || format == WebGLImageConversion::DataFormatR32F
1161         || format == WebGLImageConversion::DataFormatRA8
1162         || format == WebGLImageConversion::DataFormatRA16F
1163         || format == WebGLImageConversion::DataFormatRA32F
1164         || format == WebGLImageConversion::DataFormatAR8;
1165 }
1166
1167 template<int Format>
1168 struct IsFloatFormat {
1169     static const bool Value =
1170         Format == WebGLImageConversion::DataFormatRGBA32F
1171         || Format == WebGLImageConversion::DataFormatRGB32F
1172         || Format == WebGLImageConversion::DataFormatRA32F
1173         || Format == WebGLImageConversion::DataFormatR32F
1174         || Format == WebGLImageConversion::DataFormatA32F;
1175 };
1176
1177 template<int Format>
1178 struct IsHalfFloatFormat {
1179     static const bool Value =
1180         Format == WebGLImageConversion::DataFormatRGBA16F
1181         || Format == WebGLImageConversion::DataFormatRGB16F
1182         || Format == WebGLImageConversion::DataFormatRA16F
1183         || Format == WebGLImageConversion::DataFormatR16F
1184         || Format == WebGLImageConversion::DataFormatA16F;
1185 };
1186
1187 template<int Format>
1188 struct Is16bppFormat {
1189     static const bool Value =
1190         Format == WebGLImageConversion::DataFormatRGBA5551
1191         || Format == WebGLImageConversion::DataFormatRGBA4444
1192         || Format == WebGLImageConversion::DataFormatRGB565;
1193 };
1194
1195 template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value>
1196 struct DataTypeForFormat {
1197     typedef uint8_t Type;
1198 };
1199
1200 template<int Format>
1201 struct DataTypeForFormat<Format, true, false, false> {
1202     typedef float Type;
1203 };
1204
1205 template<int Format>
1206 struct DataTypeForFormat<Format, false, true, false> {
1207     typedef uint16_t Type;
1208 };
1209
1210 template<int Format>
1211 struct DataTypeForFormat<Format, false, false, true> {
1212     typedef uint16_t Type;
1213 };
1214
1215 template<int Format>
1216 struct IntermediateFormat {
1217     static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? WebGLImageConversion::DataFormatRGBA32F : WebGLImageConversion::DataFormatRGBA8;
1218 };
1219
1220 unsigned TexelBytesForFormat(WebGLImageConversion::DataFormat format)
1221 {
1222     switch (format) {
1223     case WebGLImageConversion::DataFormatR8:
1224     case WebGLImageConversion::DataFormatA8:
1225         return 1;
1226     case WebGLImageConversion::DataFormatRA8:
1227     case WebGLImageConversion::DataFormatAR8:
1228     case WebGLImageConversion::DataFormatRGBA5551:
1229     case WebGLImageConversion::DataFormatRGBA4444:
1230     case WebGLImageConversion::DataFormatRGB565:
1231     case WebGLImageConversion::DataFormatA16F:
1232     case WebGLImageConversion::DataFormatR16F:
1233         return 2;
1234     case WebGLImageConversion::DataFormatRGB8:
1235     case WebGLImageConversion::DataFormatBGR8:
1236         return 3;
1237     case WebGLImageConversion::DataFormatRGBA8:
1238     case WebGLImageConversion::DataFormatARGB8:
1239     case WebGLImageConversion::DataFormatABGR8:
1240     case WebGLImageConversion::DataFormatBGRA8:
1241     case WebGLImageConversion::DataFormatR32F:
1242     case WebGLImageConversion::DataFormatA32F:
1243     case WebGLImageConversion::DataFormatRA16F:
1244         return 4;
1245     case WebGLImageConversion::DataFormatRGB16F:
1246         return 6;
1247     case WebGLImageConversion::DataFormatRA32F:
1248     case WebGLImageConversion::DataFormatRGBA16F:
1249         return 8;
1250     case WebGLImageConversion::DataFormatRGB32F:
1251         return 12;
1252     case WebGLImageConversion::DataFormatRGBA32F:
1253         return 16;
1254     default:
1255         return 0;
1256     }
1257 }
1258
1259 /* END CODE SHARED WITH MOZILLA FIREFOX */
1260
1261 class FormatConverter {
1262 public:
1263     FormatConverter(unsigned width, unsigned height,
1264         const void* srcStart, void* dstStart, int srcStride, int dstStride)
1265         : m_width(width), m_height(height), m_srcStart(srcStart), m_dstStart(dstStart), m_srcStride(srcStride), m_dstStride(dstStride), m_success(false)
1266     {
1267         const unsigned MaxNumberOfComponents = 4;
1268         const unsigned MaxBytesPerComponent  = 4;
1269         m_unpackedIntermediateSrcData = adoptArrayPtr(new uint8_t[m_width * MaxNumberOfComponents *MaxBytesPerComponent]);
1270         ASSERT(m_unpackedIntermediateSrcData.get());
1271     }
1272
1273     void convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp);
1274     bool Success() const { return m_success; }
1275
1276 private:
1277     template<WebGLImageConversion::DataFormat SrcFormat>
1278     void convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp);
1279
1280     template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat>
1281     void convert(WebGLImageConversion::AlphaOp);
1282
1283     template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp>
1284     void convert();
1285
1286     const unsigned m_width, m_height;
1287     const void* const m_srcStart;
1288     void* const m_dstStart;
1289     const int m_srcStride, m_dstStride;
1290     bool m_success;
1291     OwnPtr<uint8_t[]> m_unpackedIntermediateSrcData;
1292 };
1293
1294 void FormatConverter::convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp)
1295 {
1296 #define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \
1297     case SrcFormat: \
1298         return convert<SrcFormat>(dstFormat, alphaOp);
1299
1300         switch (srcFormat) {
1301             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR8)
1302             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA8)
1303             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR32F)
1304             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA32F)
1305             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA8)
1306             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA32F)
1307             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB8)
1308             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGR8)
1309             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB565)
1310             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB32F)
1311             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA8)
1312             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatARGB8)
1313             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatABGR8)
1314             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatAR8)
1315             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGRA8)
1316             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA5551)
1317             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA4444)
1318             FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA32F)
1319         default:
1320             ASSERT_NOT_REACHED();
1321         }
1322 #undef FORMATCONVERTER_CASE_SRCFORMAT
1323 }
1324
1325 template<WebGLImageConversion::DataFormat SrcFormat>
1326 void FormatConverter::convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp)
1327 {
1328 #define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \
1329     case DstFormat: \
1330         return convert<SrcFormat, DstFormat>(alphaOp);
1331
1332         switch (dstFormat) {
1333             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR8)
1334             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR16F)
1335             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR32F)
1336             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA8)
1337             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA16F)
1338             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA32F)
1339             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA8)
1340             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA16F)
1341             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA32F)
1342             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB8)
1343             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB565)
1344             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB16F)
1345             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB32F)
1346             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA8)
1347             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA5551)
1348             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA4444)
1349             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA16F)
1350             FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA32F)
1351         default:
1352             ASSERT_NOT_REACHED();
1353         }
1354
1355 #undef FORMATCONVERTER_CASE_DSTFORMAT
1356 }
1357
1358 template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat>
1359 void FormatConverter::convert(WebGLImageConversion::AlphaOp alphaOp)
1360 {
1361 #define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \
1362     case alphaOp: \
1363         return convert<SrcFormat, DstFormat, alphaOp>();
1364
1365         switch (alphaOp) {
1366             FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoNothing)
1367             FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoPremultiply)
1368             FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoUnmultiply)
1369         default:
1370             ASSERT_NOT_REACHED();
1371         }
1372 #undef FORMATCONVERTER_CASE_ALPHAOP
1373 }
1374
1375 template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp>
1376 void FormatConverter::convert()
1377 {
1378     // Many instantiations of this template function will never be entered, so we try
1379     // to return immediately in these cases to avoid the compiler to generate useless code.
1380     if (SrcFormat == DstFormat && alphaOp == WebGLImageConversion::AlphaDoNothing) {
1381         ASSERT_NOT_REACHED();
1382         return;
1383     }
1384     if (!IsFloatFormat<DstFormat>::Value && IsFloatFormat<SrcFormat>::Value) {
1385         ASSERT_NOT_REACHED();
1386         return;
1387     }
1388
1389     // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat.
1390     const bool srcFormatComesFromDOMElementOrImageData = WebGLImageConversion::srcFormatComeFromDOMElementOrImageData(SrcFormat);
1391     if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) {
1392         ASSERT_NOT_REACHED();
1393         return;
1394     }
1395     // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
1396     if (!srcFormatComesFromDOMElementOrImageData && alphaOp == WebGLImageConversion::AlphaDoUnmultiply) {
1397         ASSERT_NOT_REACHED();
1398         return;
1399     }
1400     if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && alphaOp != WebGLImageConversion::AlphaDoNothing) {
1401         ASSERT_NOT_REACHED();
1402         return;
1403     }
1404
1405     typedef typename DataTypeForFormat<SrcFormat>::Type SrcType;
1406     typedef typename DataTypeForFormat<DstFormat>::Type DstType;
1407     const int IntermediateSrcFormat = IntermediateFormat<DstFormat>::Value;
1408     typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType;
1409     const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType);
1410     const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType);
1411     const bool trivialUnpack = (SrcFormat == WebGLImageConversion::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == WebGLImageConversion::DataFormatRGBA32F;
1412     const bool trivialPack = (DstFormat == WebGLImageConversion::DataFormatRGBA8 || DstFormat == WebGLImageConversion::DataFormatRGBA32F) && alphaOp == WebGLImageConversion::AlphaDoNothing && m_dstStride > 0;
1413     ASSERT(!trivialUnpack || !trivialPack);
1414
1415     const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart);
1416     DstType* dstRowStart = static_cast<DstType*>(m_dstStart);
1417     if (!trivialUnpack && trivialPack) {
1418         for (size_t i = 0; i < m_height; ++i) {
1419             unpack<SrcFormat>(srcRowStart, dstRowStart, m_width);
1420             srcRowStart += srcStrideInElements;
1421             dstRowStart += dstStrideInElements;
1422         }
1423     } else if (!trivialUnpack && !trivialPack) {
1424         for (size_t i = 0; i < m_height; ++i) {
1425             unpack<SrcFormat>(srcRowStart, reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), m_width);
1426             pack<DstFormat, alphaOp>(reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), dstRowStart, m_width);
1427             srcRowStart += srcStrideInElements;
1428             dstRowStart += dstStrideInElements;
1429         }
1430     } else {
1431         for (size_t i = 0; i < m_height; ++i) {
1432             pack<DstFormat, alphaOp>(srcRowStart, dstRowStart, m_width);
1433             srcRowStart += srcStrideInElements;
1434             dstRowStart += dstStrideInElements;
1435         }
1436     }
1437     m_success = true;
1438     return;
1439 }
1440
1441 } // anonymous namespace
1442
1443 bool WebGLImageConversion::computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent)
1444 {
1445     switch (format) {
1446     case GL_ALPHA:
1447     case GL_LUMINANCE:
1448     case GL_DEPTH_COMPONENT:
1449     case GL_DEPTH_STENCIL_OES:
1450         *componentsPerPixel = 1;
1451         break;
1452     case GL_LUMINANCE_ALPHA:
1453         *componentsPerPixel = 2;
1454         break;
1455     case GL_RGB:
1456     case GL_SRGB_EXT: // GL_EXT_sRGB
1457         *componentsPerPixel = 3;
1458         break;
1459     case GL_RGBA:
1460     case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888
1461     case GL_SRGB_ALPHA_EXT: // GL_EXT_sRGB
1462         *componentsPerPixel = 4;
1463         break;
1464     default:
1465         return false;
1466     }
1467     switch (type) {
1468     case GL_UNSIGNED_BYTE:
1469         *bytesPerComponent = sizeof(GLubyte);
1470         break;
1471     case GL_UNSIGNED_SHORT:
1472         *bytesPerComponent = sizeof(GLushort);
1473         break;
1474     case GL_UNSIGNED_SHORT_5_6_5:
1475     case GL_UNSIGNED_SHORT_4_4_4_4:
1476     case GL_UNSIGNED_SHORT_5_5_5_1:
1477         *componentsPerPixel = 1;
1478         *bytesPerComponent = sizeof(GLushort);
1479         break;
1480     case GL_UNSIGNED_INT_24_8_OES:
1481     case GL_UNSIGNED_INT:
1482         *bytesPerComponent = sizeof(GLuint);
1483         break;
1484     case GL_FLOAT: // OES_texture_float
1485         *bytesPerComponent = sizeof(GLfloat);
1486         break;
1487     case GL_HALF_FLOAT_OES: // OES_texture_half_float
1488         *bytesPerComponent = sizeof(GLushort);
1489         break;
1490     default:
1491         return false;
1492     }
1493     return true;
1494 }
1495
1496 GLenum WebGLImageConversion::computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes)
1497 {
1498     ASSERT(imageSizeInBytes);
1499     ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
1500     if (width < 0 || height < 0)
1501         return GL_INVALID_VALUE;
1502     unsigned bytesPerComponent, componentsPerPixel;
1503     if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
1504         return GL_INVALID_ENUM;
1505     if (!width || !height) {
1506         *imageSizeInBytes = 0;
1507         if (paddingInBytes)
1508             *paddingInBytes = 0;
1509         return GL_NO_ERROR;
1510     }
1511     CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
1512     checkedValue *=  width;
1513     if (!checkedValue.isValid())
1514         return GL_INVALID_VALUE;
1515     unsigned validRowSize = checkedValue.value();
1516     unsigned padding = 0;
1517     unsigned residual = validRowSize % alignment;
1518     if (residual) {
1519         padding = alignment - residual;
1520         checkedValue += padding;
1521     }
1522     // Last row needs no padding.
1523     checkedValue *= (height - 1);
1524     checkedValue += validRowSize;
1525     if (!checkedValue.isValid())
1526         return GL_INVALID_VALUE;
1527     *imageSizeInBytes = checkedValue.value();
1528     if (paddingInBytes)
1529         *paddingInBytes = padding;
1530     return GL_NO_ERROR;
1531 }
1532
1533 WebGLImageConversion::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
1534 {
1535     m_image = image;
1536     m_imageHtmlDomSource = imageHtmlDomSource;
1537     m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
1538 }
1539
1540 WebGLImageConversion::ImageExtractor::~ImageExtractor()
1541 {
1542     if (m_skiaImage)
1543         m_skiaImage->bitmap().unlockPixels();
1544 }
1545
1546 bool WebGLImageConversion::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
1547 {
1548     if (!m_image)
1549         return false;
1550     m_skiaImage = m_image->nativeImageForCurrentFrame();
1551     m_alphaOp = AlphaDoNothing;
1552     bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true;
1553     if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) {
1554         // Attempt to get raw unpremultiplied image data.
1555         OwnPtr<ImageDecoder> decoder(ImageDecoder::create(
1556             *(m_image->data()), ImageSource::AlphaNotPremultiplied,
1557             ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied));
1558         if (!decoder)
1559             return false;
1560         decoder->setData(m_image->data(), true);
1561         if (!decoder->frameCount())
1562             return false;
1563         ImageFrame* frame = decoder->frameBufferAtIndex(0);
1564         if (!frame || frame->status() != ImageFrame::FrameComplete)
1565             return false;
1566         hasAlpha = frame->hasAlpha();
1567         m_nativeImage = frame->asNewNativeImage();
1568         if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height())
1569             return false;
1570         if (m_nativeImage->bitmap().colorType() != kN32_SkColorType)
1571             return false;
1572         m_skiaImage = m_nativeImage.get();
1573         if (hasAlpha && premultiplyAlpha)
1574             m_alphaOp = AlphaDoPremultiply;
1575     } else if (!premultiplyAlpha && hasAlpha) {
1576         // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF
1577         // which is true at present and may be changed in the future and needs adjustment accordingly.
1578         // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
1579         // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
1580         if (m_imageHtmlDomSource != HtmlDomVideo)
1581             m_alphaOp = AlphaDoUnmultiply;
1582     }
1583     if (!m_skiaImage)
1584         return false;
1585
1586     m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8;
1587     m_imageWidth = m_skiaImage->bitmap().width();
1588     m_imageHeight = m_skiaImage->bitmap().height();
1589     if (!m_imageWidth || !m_imageHeight) {
1590         m_skiaImage.clear();
1591         return false;
1592     }
1593     // Fail if the image was downsampled because of memory limits.
1594     if (m_imageWidth != (unsigned)m_image->size().width() || m_imageHeight != (unsigned)m_image->size().height()) {
1595         m_skiaImage.clear();
1596         return false;
1597     }
1598     m_imageSourceUnpackAlignment = 0;
1599     m_skiaImage->bitmap().lockPixels();
1600     m_imagePixelData = m_skiaImage->bitmap().getPixels();
1601     return true;
1602 }
1603
1604 unsigned WebGLImageConversion::getClearBitsByFormat(GLenum format)
1605 {
1606     switch (format) {
1607     case GL_ALPHA:
1608     case GL_LUMINANCE:
1609     case GL_LUMINANCE_ALPHA:
1610     case GL_RGB:
1611     case GL_RGB565:
1612     case GL_RGBA:
1613     case GL_RGBA4:
1614     case GL_RGB5_A1:
1615     case GL_SRGB_EXT:
1616     case GL_SRGB_ALPHA_EXT:
1617         return GL_COLOR_BUFFER_BIT;
1618     case GL_DEPTH_COMPONENT16:
1619     case GL_DEPTH_COMPONENT:
1620         return GL_DEPTH_BUFFER_BIT;
1621     case GL_STENCIL_INDEX8:
1622         return GL_STENCIL_BUFFER_BIT;
1623     case GL_DEPTH_STENCIL_OES:
1624         return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
1625     default:
1626         return 0;
1627     }
1628 }
1629
1630 unsigned WebGLImageConversion::getChannelBitsByFormat(GLenum format)
1631 {
1632     switch (format) {
1633     case GL_ALPHA:
1634         return ChannelAlpha;
1635     case GL_LUMINANCE:
1636         return ChannelRGB;
1637     case GL_LUMINANCE_ALPHA:
1638         return ChannelRGBA;
1639     case GL_RGB:
1640     case GL_RGB565:
1641     case GL_SRGB_EXT:
1642         return ChannelRGB;
1643     case GL_RGBA:
1644     case GL_RGBA4:
1645     case GL_RGB5_A1:
1646     case GL_SRGB_ALPHA_EXT:
1647         return ChannelRGBA;
1648     case GL_DEPTH_COMPONENT16:
1649     case GL_DEPTH_COMPONENT:
1650         return ChannelDepth;
1651     case GL_STENCIL_INDEX8:
1652         return ChannelStencil;
1653     case GL_DEPTH_STENCIL_OES:
1654         return ChannelDepth | ChannelStencil;
1655     default:
1656         return 0;
1657     }
1658 }
1659
1660 bool WebGLImageConversion::packImageData(
1661     Image* image,
1662     const void* pixels,
1663     GLenum format,
1664     GLenum type,
1665     bool flipY,
1666     AlphaOp alphaOp,
1667     DataFormat sourceFormat,
1668     unsigned width,
1669     unsigned height,
1670     unsigned sourceUnpackAlignment,
1671     Vector<uint8_t>& data)
1672 {
1673     if (!pixels)
1674         return false;
1675
1676     unsigned packedSize;
1677     // Output data is tightly packed (alignment == 1).
1678     if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GL_NO_ERROR)
1679         return false;
1680     data.resize(packedSize);
1681
1682     if (!packPixels(reinterpret_cast<const uint8_t*>(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY))
1683         return false;
1684     if (ImageObserver *observer = image->imageObserver())
1685         observer->didDraw(image);
1686     return true;
1687 }
1688
1689 bool WebGLImageConversion::extractImageData(
1690     const uint8_t* imageData,
1691     const IntSize& imageDataSize,
1692     GLenum format,
1693     GLenum type,
1694     bool flipY,
1695     bool premultiplyAlpha,
1696     Vector<uint8_t>& data)
1697 {
1698     if (!imageData)
1699         return false;
1700     int width = imageDataSize.width();
1701     int height = imageDataSize.height();
1702
1703     unsigned packedSize;
1704     // Output data is tightly packed (alignment == 1).
1705     if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GL_NO_ERROR)
1706         return false;
1707     data.resize(packedSize);
1708
1709     if (!packPixels(imageData, DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY))
1710         return false;
1711
1712     return true;
1713 }
1714
1715 bool WebGLImageConversion::extractTextureData(
1716     unsigned width,
1717     unsigned height,
1718     GLenum format, GLenum type,
1719     unsigned unpackAlignment,
1720     bool flipY, bool premultiplyAlpha,
1721     const void* pixels,
1722     Vector<uint8_t>& data)
1723 {
1724     // Assumes format, type, etc. have already been validated.
1725     DataFormat sourceDataFormat = getDataFormat(format, type);
1726
1727     // Resize the output buffer.
1728     unsigned int componentsPerPixel, bytesPerComponent;
1729     if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent))
1730         return false;
1731     unsigned bytesPerPixel = componentsPerPixel * bytesPerComponent;
1732     data.resize(width * height * bytesPerPixel);
1733
1734     if (!packPixels(static_cast<const uint8_t*>(pixels), sourceDataFormat, width, height, unpackAlignment, format, type, (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data(), flipY))
1735         return false;
1736
1737     return true;
1738 }
1739
1740 bool WebGLImageConversion::packPixels(
1741     const uint8_t* sourceData,
1742     DataFormat sourceDataFormat,
1743     unsigned width,
1744     unsigned height,
1745     unsigned sourceUnpackAlignment,
1746     unsigned destinationFormat,
1747     unsigned destinationType,
1748     AlphaOp alphaOp,
1749     void* destinationData,
1750     bool flipY)
1751 {
1752     int validSrc = width * TexelBytesForFormat(sourceDataFormat);
1753     int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0;
1754     int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc;
1755
1756     DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType);
1757     int dstStride = width * TexelBytesForFormat(dstDataFormat);
1758     if (flipY) {
1759         destinationData = static_cast<uint8_t*>(destinationData) + dstStride*(height - 1);
1760         dstStride = -dstStride;
1761     }
1762     if (!HasAlpha(sourceDataFormat) || !HasColor(sourceDataFormat) || !HasColor(dstDataFormat))
1763         alphaOp = AlphaDoNothing;
1764
1765     if (sourceDataFormat == dstDataFormat && alphaOp == AlphaDoNothing) {
1766         const uint8_t* ptr = sourceData;
1767         const uint8_t* ptrEnd = sourceData + srcStride * height;
1768         unsigned rowSize = (dstStride > 0) ? dstStride: -dstStride;
1769         uint8_t* dst = static_cast<uint8_t*>(destinationData);
1770         while (ptr < ptrEnd) {
1771             memcpy(dst, ptr, rowSize);
1772             ptr += srcStride;
1773             dst += dstStride;
1774         }
1775         return true;
1776     }
1777
1778     FormatConverter converter(width, height, sourceData, destinationData, srcStride, dstStride);
1779     converter.convert(sourceDataFormat, dstDataFormat, alphaOp);
1780     if (!converter.Success())
1781         return false;
1782     return true;
1783 }
1784
1785 } // namespace blink