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