.: Replace "Apple Computer, Inc." with "Apple Inc." in copyright headers
[WebKit-https.git] / Source / WebCore / platform / graphics / FormatConverter.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Google Inc. All rights reserved.
4  * Copyright (C) 2010 Mozilla Corporation. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #include "config.h"
29
30 #if USE(3D_GRAPHICS)
31
32 #include "FormatConverter.h"
33
34 #if HAVE(ARM_NEON_INTRINSICS)
35 #include "GraphicsContext3DNEON.h"
36 #endif
37
38 // Visual Studio crashes with a C1063 Fatal Error if everything is inlined.
39 #if COMPILER(MSVC)
40 #define ALWAYS_INLINE_EXCEPT_MSVC
41 #else
42 #define ALWAYS_INLINE_EXCEPT_MSVC ALWAYS_INLINE
43 #endif
44
45 namespace WebCore {
46
47
48 // Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf,
49 // "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010).
50 // Specially, the basetable[512] and shifttable[512] are generated as follows:
51 /*
52 unsigned short basetable[512];
53 unsigned char shifttable[512];
54
55 void generatetables(){
56     unsigned int i;
57     int e;
58     for (i = 0; i < 256; ++i){
59         e = i - 127;
60         if (e < -24){ // Very small numbers map to zero
61             basetable[i | 0x000] = 0x0000;
62             basetable[i | 0x100] = 0x8000;
63             shifttable[i | 0x000] = 24;
64             shifttable[i | 0x100] = 24;
65         }
66         else if (e < -14) { // Small numbers map to denorms
67             basetable[i | 0x000] = (0x0400>>(-e-14));
68             basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000;
69             shifttable[i | 0x000] = -e-1;
70             shifttable[i | 0x100] = -e-1;
71         }
72         else if (e <= 15){ // Normal numbers just lose precision
73             basetable[i | 0x000] = ((e+15)<<10);
74             basetable[i| 0x100] = ((e+15)<<10) | 0x8000;
75             shifttable[i|0x000] = 13;
76             shifttable[i|0x100] = 13;
77         }
78         else if (e<128){ // Large numbers map to Infinity
79             basetable[i|0x000] = 0x7C00;
80             basetable[i|0x100] = 0xFC00;
81             shifttable[i|0x000] = 24;
82             shifttable[i|0x100] = 24;
83         }
84         else { // Infinity and NaN's stay Infinity and NaN's
85             basetable[i|0x000] = 0x7C00;
86             basetable[i|0x100] = 0xFC00;
87             shifttable[i|0x000] = 13;
88             shifttable[i|0x100] = 13;
89        }
90     }
91 }
92 */
93
94 unsigned short baseTable[512] = {
95 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
96 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
97 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
98 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
99 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
100 0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
101 0,      0,      0,      0,      0,      0,      0,      1,      2,      4,      8,      16,     32,     64,     128,    256,
102 512,    1024,   2048,   3072,   4096,   5120,   6144,   7168,   8192,   9216,   10240,  11264,  12288,  13312,  14336,  15360,
103 16384,  17408,  18432,  19456,  20480,  21504,  22528,  23552,  24576,  25600,  26624,  27648,  28672,  29696,  30720,  31744,
104 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
105 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
106 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
107 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
108 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
109 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
110 31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,  31744,
111 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
112 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
113 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
114 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
115 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
116 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,  32768,
117 32768,  32768,  32768,  32768,  32768,  32768,  32768,  32769,  32770,  32772,  32776,  32784,  32800,  32832,  32896,  33024,
118 33280,  33792,  34816,  35840,  36864,  37888,  38912,  39936,  40960,  41984,  43008,  44032,  45056,  46080,  47104,  48128,
119 49152,  50176,  51200,  52224,  53248,  54272,  55296,  56320,  57344,  58368,  59392,  60416,  61440,  62464,  63488,  64512,
120 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
121 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
122 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
123 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
124 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
125 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,
126 64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512,  64512
127 };
128
129 unsigned char shiftTable[512] = {
130 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
131 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
132 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
133 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
134 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
135 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
136 24,     24,     24,     24,     24,     24,     24,     23,     22,     21,     20,     19,     18,     17,     16,     15,
137 14,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,
138 13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     24,
139 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
140 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
141 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
142 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
143 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
144 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
145 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     13,
146 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
147 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
148 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
149 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
150 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
151 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
152 24,     24,     24,     24,     24,     24,     24,     23,     22,     21,     20,     19,     18,     17,     16,     15,
153 14,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,
154 13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     13,     24,
155 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
156 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
157 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
158 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
159 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
160 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,
161 24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     24,     13
162 };
163
164 inline unsigned short convertFloatToHalfFloat(float f)
165 {
166     unsigned temp = *(reinterpret_cast<unsigned *>(&f));
167     unsigned signexp = (temp >> 23) & 0x1ff;
168     return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]);
169 }
170
171 /* BEGIN CODE SHARED WITH MOZILLA FIREFOX */
172
173 // The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup.
174 // Explicit template specializations correspond to the cases that would occur.
175 // Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h
176
177 //----------------------------------------------------------------------
178 // Pixel unpacking routines.
179 template<int format, typename SourceType, typename DstType>
180 ALWAYS_INLINE void unpack(const SourceType*, DstType*, unsigned)
181 {
182     ASSERT_NOT_REACHED();
183 }
184
185 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
186 {
187     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
188         destination[0] = source[0];
189         destination[1] = source[1];
190         destination[2] = source[2];
191         destination[3] = 0xFF;
192         source += 3;
193         destination += 4;
194     }
195 }
196
197 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
198 {
199     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
200         destination[0] = source[2];
201         destination[1] = source[1];
202         destination[2] = source[0];
203         destination[3] = 0xFF;
204         source += 3;
205         destination += 4;
206     }
207 }
208
209 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
210 {
211     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
212         destination[0] = source[1];
213         destination[1] = source[2];
214         destination[2] = source[3];
215         destination[3] = source[0];
216         source += 4;
217         destination += 4;
218     }
219 }
220
221 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
222 {
223     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
224         destination[0] = source[3];
225         destination[1] = source[2];
226         destination[2] = source[1];
227         destination[3] = source[0];
228         source += 4;
229         destination += 4;
230     }
231 }
232
233 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
234 {
235     const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
236     uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
237     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
238         uint32_t bgra = source32[i];
239 #if CPU(BIG_ENDIAN)
240         uint32_t brMask = 0xff00ff00;
241         uint32_t gaMask = 0x00ff00ff;
242 #else
243         uint32_t brMask = 0x00ff00ff;
244         uint32_t gaMask = 0xff00ff00;
245 #endif
246         uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask);
247         destination32[i] = rgba;
248     }
249 }
250
251 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
252 {
253 #if HAVE(ARM_NEON_INTRINSICS)
254     SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow);
255 #endif
256     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
257         uint16_t packedValue = source[0];
258         uint8_t r = packedValue >> 11;
259         uint8_t g = (packedValue >> 6) & 0x1F;
260         uint8_t b = (packedValue >> 1) & 0x1F;
261         destination[0] = (r << 3) | (r & 0x7);
262         destination[1] = (g << 3) | (g & 0x7);
263         destination[2] = (b << 3) | (b & 0x7);
264         destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
265         source += 1;
266         destination += 4;
267     }
268 }
269
270 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
271 {
272 #if HAVE(ARM_NEON_INTRINSICS)
273     SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow);
274 #endif
275     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
276         uint16_t packedValue = source[0];
277         uint8_t r = packedValue >> 12;
278         uint8_t g = (packedValue >> 8) & 0x0F;
279         uint8_t b = (packedValue >> 4) & 0x0F;
280         uint8_t a = packedValue & 0x0F;
281         destination[0] = r << 4 | r;
282         destination[1] = g << 4 | g;
283         destination[2] = b << 4 | b;
284         destination[3] = a << 4 | a;
285         source += 1;
286         destination += 4;
287     }
288 }
289
290 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
291 {
292 #if HAVE(ARM_NEON_INTRINSICS)
293     SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow);
294 #endif
295     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
296         uint16_t packedValue = source[0];
297         uint8_t r = packedValue >> 11;
298         uint8_t g = (packedValue >> 5) & 0x3F;
299         uint8_t b = packedValue & 0x1F;
300         destination[0] = (r << 3) | (r & 0x7);
301         destination[1] = (g << 2) | (g & 0x3);
302         destination[2] = (b << 3) | (b & 0x7);
303         destination[3] = 0xFF;
304         source += 1;
305         destination += 4;
306     }
307 }
308
309 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
310 {
311     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
312         destination[0] = source[0];
313         destination[1] = source[0];
314         destination[2] = source[0];
315         destination[3] = 0xFF;
316         source += 1;
317         destination += 4;
318     }
319 }
320
321 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
322 {
323     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
324         destination[0] = source[0];
325         destination[1] = source[0];
326         destination[2] = source[0];
327         destination[3] = source[1];
328         source += 2;
329         destination += 4;
330     }
331 }
332
333 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
334 {
335     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
336         destination[0] = source[1];
337         destination[1] = source[1];
338         destination[2] = source[1];
339         destination[3] = source[0];
340         source += 2;
341         destination += 4;
342     }
343 }
344
345 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
346 {
347     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
348         destination[0] = 0x0;
349         destination[1] = 0x0;
350         destination[2] = 0x0;
351         destination[3] = source[0];
352         source += 1;
353         destination += 4;
354     }
355 }
356
357 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
358 {
359     const float scaleFactor = 1.0f / 255.0f;
360     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
361         destination[0] = source[0] * scaleFactor;
362         destination[1] = source[1] * scaleFactor;
363         destination[2] = source[2] * scaleFactor;
364         destination[3] = source[3] * scaleFactor;
365         source += 4;
366         destination += 4;
367     }
368 }
369
370 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
371 {
372     const float scaleFactor = 1.0f / 255.0f;
373     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
374         destination[0] = source[2] * scaleFactor;
375         destination[1] = source[1] * scaleFactor;
376         destination[2] = source[0] * scaleFactor;
377         destination[3] = source[3] * scaleFactor;
378         source += 4;
379         destination += 4;
380     }
381 }
382
383 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
384 {
385     const float scaleFactor = 1.0f / 255.0f;
386     for (unsigned i = 0; i < pixelsPerRow; ++i) {
387         destination[0] = source[3] * scaleFactor;
388         destination[1] = source[2] * scaleFactor;
389         destination[2] = source[1] * scaleFactor;
390         destination[3] = source[0] * scaleFactor;
391         source += 4;
392         destination += 4;
393     }
394 }
395
396 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
397 {
398     const float scaleFactor = 1.0f / 255.0f;
399     for (unsigned i = 0; i < pixelsPerRow; ++i) {
400         destination[0] = source[1] * scaleFactor;
401         destination[1] = source[2] * scaleFactor;
402         destination[2] = source[3] * scaleFactor;
403         destination[3] = source[0] * scaleFactor;
404         source += 4;
405         destination += 4;
406     }
407 }
408
409 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
410 {
411     const float scaleFactor = 1.0f / 255.0f;
412     for (unsigned i = 0; i < pixelsPerRow; ++i) {
413         destination[0] = source[0] * scaleFactor;
414         destination[1] = source[1] * scaleFactor;
415         destination[2] = source[2] * scaleFactor;
416         destination[3] = 1;
417         source += 3;
418         destination += 4;
419     }
420 }
421
422 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
423 {
424     const float scaleFactor = 1.0f / 255.0f;
425     for (unsigned i = 0; i < pixelsPerRow; ++i) {
426         destination[0] = source[2] * scaleFactor;
427         destination[1] = source[1] * scaleFactor;
428         destination[2] = source[0] * scaleFactor;
429         destination[3] = 1;
430         source += 3;
431         destination += 4;
432     }
433 }
434
435 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
436 {
437     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
438         destination[0] = source[0];
439         destination[1] = source[1];
440         destination[2] = source[2];
441         destination[3] = 1;
442         source += 3;
443         destination += 4;
444     }
445 }
446
447 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
448 {
449     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
450         destination[0] = source[0];
451         destination[1] = source[0];
452         destination[2] = source[0];
453         destination[3] = 1;
454         source += 1;
455         destination += 4;
456     }
457 }
458
459 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
460 {
461     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
462         destination[0] = source[0];
463         destination[1] = source[0];
464         destination[2] = source[0];
465         destination[3] = source[1];
466         source += 2;
467         destination += 4;
468     }
469 }
470
471 template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
472 {
473     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
474         destination[0] = 0;
475         destination[1] = 0;
476         destination[2] = 0;
477         destination[3] = source[0];
478         source += 1;
479         destination += 4;
480     }
481 }
482
483 //----------------------------------------------------------------------
484 // Pixel packing routines.
485 //
486
487 template<int format, int alphaOp, typename SourceType, typename DstType>
488 ALWAYS_INLINE void pack(const SourceType*, DstType*, unsigned)
489 {
490     ASSERT_NOT_REACHED();
491 }
492
493 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
494 {
495     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
496         destination[0] = source[3];
497         source += 4;
498         destination += 1;
499     }
500 }
501
502 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
503 {
504     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
505         destination[0] = source[0];
506         source += 4;
507         destination += 1;
508     }
509 }
510
511 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
512 {
513     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
514         float scaleFactor = source[3] / 255.0f;
515         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
516         destination[0] = sourceR;
517         source += 4;
518         destination += 1;
519     }
520 }
521
522 // FIXME: this routine is lossy and must be removed.
523 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
524 {
525     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
526         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
527         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
528         destination[0] = sourceR;
529         source += 4;
530         destination += 1;
531     }
532 }
533
534 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
535 {
536     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
537         destination[0] = source[0];
538         destination[1] = source[3];
539         source += 4;
540         destination += 2;
541     }
542 }
543
544 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
545 {
546     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
547         float scaleFactor = source[3] / 255.0f;
548         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
549         destination[0] = sourceR;
550         destination[1] = source[3];
551         source += 4;
552         destination += 2;
553     }
554 }
555
556 // FIXME: this routine is lossy and must be removed.
557 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
558 {
559     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
560         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
561         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
562         destination[0] = sourceR;
563         destination[1] = source[3];
564         source += 4;
565         destination += 2;
566     }
567 }
568
569 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
570 {
571     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
572         destination[0] = source[0];
573         destination[1] = source[1];
574         destination[2] = source[2];
575         source += 4;
576         destination += 3;
577     }
578 }
579
580 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
581 {
582     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
583         float scaleFactor = source[3] / 255.0f;
584         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
585         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
586         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
587         destination[0] = sourceR;
588         destination[1] = sourceG;
589         destination[2] = sourceB;
590         source += 4;
591         destination += 3;
592     }
593 }
594
595 // FIXME: this routine is lossy and must be removed.
596 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
597 {
598     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
599         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
600         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
601         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
602         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
603         destination[0] = sourceR;
604         destination[1] = sourceG;
605         destination[2] = sourceB;
606         source += 4;
607         destination += 3;
608     }
609 }
610
611
612 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
613 {
614     memcpy(destination, source, pixelsPerRow * 4);
615 }
616
617 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
618 {
619     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
620         float scaleFactor = source[3] / 255.0f;
621         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
622         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
623         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
624         destination[0] = sourceR;
625         destination[1] = sourceG;
626         destination[2] = sourceB;
627         destination[3] = source[3];
628         source += 4;
629         destination += 4;
630     }
631 }
632
633 // FIXME: this routine is lossy and must be removed.
634 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
635 {
636     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
637         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
638         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
639         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
640         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
641         destination[0] = sourceR;
642         destination[1] = sourceG;
643         destination[2] = sourceB;
644         destination[3] = source[3];
645         source += 4;
646         destination += 4;
647     }
648 }
649
650 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
651 {
652 #if HAVE(ARM_NEON_INTRINSICS)
653     SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow);
654 #endif
655     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
656         *destination = (((source[0] & 0xF0) << 8)
657                         | ((source[1] & 0xF0) << 4)
658                         | (source[2] & 0xF0)
659                         | (source[3] >> 4));
660         source += 4;
661         destination += 1;
662     }
663 }
664
665 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
666 {
667     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
668         float scaleFactor = source[3] / 255.0f;
669         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
670         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
671         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
672         *destination = (((sourceR & 0xF0) << 8)
673                         | ((sourceG & 0xF0) << 4)
674                         | (sourceB & 0xF0)
675                         | (source[3] >> 4));
676         source += 4;
677         destination += 1;
678     }
679 }
680
681 // FIXME: this routine is lossy and must be removed.
682 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
683 {
684     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
685         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
686         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
687         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
688         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
689         *destination = (((sourceR & 0xF0) << 8)
690                         | ((sourceG & 0xF0) << 4)
691                         | (sourceB & 0xF0)
692                         | (source[3] >> 4));
693         source += 4;
694         destination += 1;
695     }
696 }
697
698 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
699 {
700 #if HAVE(ARM_NEON_INTRINSICS)
701     SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow);
702 #endif
703     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
704         *destination = (((source[0] & 0xF8) << 8)
705                         | ((source[1] & 0xF8) << 3)
706                         | ((source[2] & 0xF8) >> 2)
707                         | (source[3] >> 7));
708         source += 4;
709         destination += 1;
710     }
711 }
712
713 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
714 {
715     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
716         float scaleFactor = source[3] / 255.0f;
717         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
718         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
719         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
720         *destination = (((sourceR & 0xF8) << 8)
721                         | ((sourceG & 0xF8) << 3)
722                         | ((sourceB & 0xF8) >> 2)
723                         | (source[3] >> 7));
724         source += 4;
725         destination += 1;
726     }
727 }
728
729 // FIXME: this routine is lossy and must be removed.
730 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
731 {
732     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
733         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
734         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
735         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
736         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
737         *destination = (((sourceR & 0xF8) << 8)
738                         | ((sourceG & 0xF8) << 3)
739                         | ((sourceB & 0xF8) >> 2)
740                         | (source[3] >> 7));
741         source += 4;
742         destination += 1;
743     }
744 }
745
746 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
747 {
748 #if HAVE(ARM_NEON_INTRINSICS)
749     SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow);
750 #endif
751     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
752         *destination = (((source[0] & 0xF8) << 8)
753                         | ((source[1] & 0xFC) << 3)
754                         | ((source[2] & 0xF8) >> 3));
755         source += 4;
756         destination += 1;
757     }
758 }
759
760 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
761 {
762     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
763         float scaleFactor = source[3] / 255.0f;
764         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
765         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
766         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
767         *destination = (((sourceR & 0xF8) << 8)
768                         | ((sourceG & 0xFC) << 3)
769                         | ((sourceB & 0xF8) >> 3));
770         source += 4;
771         destination += 1;
772     }
773 }
774
775 // FIXME: this routine is lossy and must be removed.
776 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
777 {
778     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
779         float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
780         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
781         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
782         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
783         *destination = (((sourceR & 0xF8) << 8)
784                         | ((sourceG & 0xFC) << 3)
785                         | ((sourceB & 0xF8) >> 3));
786         source += 4;
787         destination += 1;
788     }
789 }
790
791 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
792 {
793     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
794         destination[0] = source[0];
795         destination[1] = source[1];
796         destination[2] = source[2];
797         source += 4;
798         destination += 3;
799     }
800 }
801
802 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
803 {
804     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
805         float scaleFactor = source[3];
806         destination[0] = source[0] * scaleFactor;
807         destination[1] = source[1] * scaleFactor;
808         destination[2] = source[2] * scaleFactor;
809         source += 4;
810         destination += 3;
811     }
812 }
813
814 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
815 {
816     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
817         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
818         destination[0] = source[0] * scaleFactor;
819         destination[1] = source[1] * scaleFactor;
820         destination[2] = source[2] * scaleFactor;
821         source += 4;
822         destination += 3;
823     }
824 }
825
826 // Used only during RGBA8 or BGRA8 -> floating-point uploads.
827 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
828 {
829     memcpy(destination, source, pixelsPerRow * 4 * sizeof(float));
830 }
831
832 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
833 {
834     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
835         float scaleFactor = source[3];
836         destination[0] = source[0] * scaleFactor;
837         destination[1] = source[1] * scaleFactor;
838         destination[2] = source[2] * scaleFactor;
839         destination[3] = source[3];
840         source += 4;
841         destination += 4;
842     }
843 }
844
845 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
846 {
847     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
848         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
849         destination[0] = source[0] * scaleFactor;
850         destination[1] = source[1] * scaleFactor;
851         destination[2] = source[2] * scaleFactor;
852         destination[3] = source[3];
853         source += 4;
854         destination += 4;
855     }
856 }
857
858 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
859 {
860     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
861         destination[0] = source[3];
862         source += 4;
863         destination += 1;
864     }
865 }
866
867 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
868 {
869     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
870         destination[0] = source[0];
871         source += 4;
872         destination += 1;
873     }
874 }
875
876 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
877 {
878     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
879         float scaleFactor = source[3];
880         destination[0] = source[0] * scaleFactor;
881         source += 4;
882         destination += 1;
883     }
884 }
885
886 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR32F, 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         source += 4;
892         destination += 1;
893     }
894 }
895
896 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
897 {
898     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
899         destination[0] = source[0];
900         destination[1] = source[3];
901         source += 4;
902         destination += 2;
903     }
904 }
905
906 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
907 {
908     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
909         float scaleFactor = source[3];
910         destination[0] = source[0] * scaleFactor;
911         destination[1] = source[3];
912         source += 4;
913         destination += 2;
914     }
915 }
916
917 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA32F, 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[3];
923         source += 4;
924         destination += 2;
925     }
926 }
927
928 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
929 {
930     for (unsigned i = 0; i < pixelsPerRow; ++i) {
931         destination[0] = convertFloatToHalfFloat(source[0]);
932         destination[1] = convertFloatToHalfFloat(source[1]);
933         destination[2] = convertFloatToHalfFloat(source[2]);
934         destination[3] = convertFloatToHalfFloat(source[3]);
935         source += 4;
936         destination += 4;
937     }
938 }
939
940 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
941 {
942     for (unsigned i = 0; i < pixelsPerRow; ++i) {
943         float scaleFactor = source[3];
944         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
945         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
946         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
947         destination[3] = convertFloatToHalfFloat(source[3]);
948         source += 4;
949         destination += 4;
950     }
951 }
952
953 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
954 {
955     for (unsigned i = 0; i < pixelsPerRow; ++i) {
956         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
957         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
958         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
959         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
960         destination[3] = convertFloatToHalfFloat(source[3]);
961         source += 4;
962         destination += 4;
963     }
964 }
965
966 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
967 {
968     for (unsigned i = 0; i < pixelsPerRow; ++i) {
969         destination[0] = convertFloatToHalfFloat(source[0]);
970         destination[1] = convertFloatToHalfFloat(source[1]);
971         destination[2] = convertFloatToHalfFloat(source[2]);
972         source += 4;
973         destination += 3;
974     }
975 }
976
977 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
978 {
979     for (unsigned i = 0; i < pixelsPerRow; ++i) {
980         float scaleFactor = source[3];
981         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
982         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
983         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
984         source += 4;
985         destination += 3;
986     }
987 }
988
989 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
990 {
991     for (unsigned i = 0; i < pixelsPerRow; ++i) {
992         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
993         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
994         destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
995         destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
996         source += 4;
997         destination += 3;
998     }
999 }
1000
1001 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1002 {
1003     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1004         destination[0] = convertFloatToHalfFloat(source[0]);
1005         destination[1] = convertFloatToHalfFloat(source[3]);
1006         source += 4;
1007         destination += 2;
1008     }
1009 }
1010
1011 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1012 {
1013     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1014         float scaleFactor = source[3];
1015         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1016         destination[1] = convertFloatToHalfFloat(source[3]);
1017         source += 4;
1018         destination += 2;
1019     }
1020 }
1021
1022 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1023 {
1024     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1025         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1026         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1027         destination[1] = convertFloatToHalfFloat(source[3]);
1028         source += 4;
1029         destination += 2;
1030     }
1031 }
1032
1033 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1034 {
1035     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1036         destination[0] = convertFloatToHalfFloat(source[0]);
1037         source += 4;
1038         destination += 1;
1039     }
1040 }
1041
1042 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoPremultiply, 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];
1046         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1047         source += 4;
1048         destination += 1;
1049     }
1050 }
1051
1052 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1053 {
1054     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1055         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1056         destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
1057         source += 4;
1058         destination += 1;
1059     }
1060 }
1061
1062 template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
1063 {
1064     for (unsigned i = 0; i < pixelsPerRow; ++i) {
1065         destination[0] = convertFloatToHalfFloat(source[3]);
1066         source += 4;
1067         destination += 1;
1068     }
1069 }
1070
1071 template<int Format>
1072 struct IsFloatFormat {
1073     static const bool Value =
1074         Format == GraphicsContext3D::DataFormatRGBA32F
1075         || Format == GraphicsContext3D::DataFormatRGB32F
1076         || Format == GraphicsContext3D::DataFormatRA32F
1077         || Format == GraphicsContext3D::DataFormatR32F
1078         || Format == GraphicsContext3D::DataFormatA32F;
1079 };
1080
1081 template<int Format>
1082 struct IsHalfFloatFormat {
1083     static const bool Value =
1084         Format == GraphicsContext3D::DataFormatRGBA16F
1085         || Format == GraphicsContext3D::DataFormatRGB16F
1086         || Format == GraphicsContext3D::DataFormatRA16F
1087         || Format == GraphicsContext3D::DataFormatR16F
1088         || Format == GraphicsContext3D::DataFormatA16F;
1089 };
1090
1091 template<int Format>
1092 struct Is16bppFormat {
1093     static const bool Value =
1094         Format == GraphicsContext3D::DataFormatRGBA5551
1095         || Format == GraphicsContext3D::DataFormatRGBA4444
1096         || Format == GraphicsContext3D::DataFormatRGB565;
1097 };
1098
1099 template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value>
1100 struct DataTypeForFormat {
1101     typedef uint8_t Type;
1102 };
1103
1104 template<int Format>
1105 struct DataTypeForFormat<Format, true, false, false> {
1106     typedef float Type;
1107 };
1108
1109 template<int Format>
1110 struct DataTypeForFormat<Format, false, true, false> {
1111     typedef uint16_t Type;
1112 };
1113
1114 template<int Format>
1115 struct DataTypeForFormat<Format, false, false, true> {
1116     typedef uint16_t Type;
1117 };
1118
1119 template<int Format>
1120 struct IntermediateFormat {
1121     static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? GraphicsContext3D::DataFormatRGBA32F : GraphicsContext3D::DataFormatRGBA8;
1122 };
1123
1124
1125 /* END CODE SHARED WITH MOZILLA FIREFOX */
1126
1127 void FormatConverter::convert(GraphicsContext3D::DataFormat srcFormat, GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp)
1128 {
1129 #define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \
1130     case SrcFormat: \
1131         return convert<SrcFormat>(dstFormat, alphaOp);
1132
1133         switch (srcFormat) {
1134             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR8)
1135             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA8)
1136             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR32F)
1137             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA32F)
1138             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA8)
1139             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA32F)
1140             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB8)
1141             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGR8)
1142             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB565)
1143             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB32F)
1144             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA8)
1145             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatARGB8)
1146             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatABGR8)
1147             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatAR8)
1148             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGRA8)
1149             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA5551)
1150             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA4444)
1151             FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA32F)
1152         default:
1153             ASSERT_NOT_REACHED();
1154         }
1155 #undef FORMATCONVERTER_CASE_SRCFORMAT
1156 }
1157
1158 template<GraphicsContext3D::DataFormat SrcFormat>
1159 ALWAYS_INLINE void FormatConverter::convert(GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp)
1160 {
1161 #define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \
1162     case DstFormat: \
1163         return convert<SrcFormat, DstFormat>(alphaOp);
1164
1165         switch (dstFormat) {
1166             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR8)
1167             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR16F)
1168             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR32F)
1169             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA8)
1170             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA16F)
1171             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA32F)
1172             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA8)
1173             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA16F)
1174             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA32F)
1175             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB8)
1176             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB565)
1177             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB16F)
1178             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB32F)
1179             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA8)
1180             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA5551)
1181             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA4444)
1182             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA16F)
1183             FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA32F)
1184         default:
1185             ASSERT_NOT_REACHED();
1186         }
1187
1188 #undef FORMATCONVERTER_CASE_DSTFORMAT
1189 }
1190
1191 template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat>
1192 ALWAYS_INLINE void FormatConverter::convert(GraphicsContext3D::AlphaOp alphaOp)
1193 {
1194 #define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \
1195     case alphaOp: \
1196         return convert<SrcFormat, DstFormat, alphaOp>();
1197
1198         switch (alphaOp) {
1199             FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoNothing)
1200             FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoPremultiply)
1201             FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoUnmultiply)
1202         default:
1203             ASSERT_NOT_REACHED();
1204         }
1205 #undef FORMATCONVERTER_CASE_ALPHAOP
1206 }
1207
1208 template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat, GraphicsContext3D::AlphaOp alphaOp>
1209 ALWAYS_INLINE_EXCEPT_MSVC void FormatConverter::convert()
1210 {
1211     // Many instantiations of this template function will never be entered, so we try
1212     // to return immediately in these cases to avoid the compiler to generate useless code.
1213     if (SrcFormat == DstFormat && alphaOp == GraphicsContext3D::AlphaDoNothing) {
1214         ASSERT_NOT_REACHED();
1215         return;
1216     }
1217     if (!IsFloatFormat<DstFormat>::Value && IsFloatFormat<SrcFormat>::Value) {
1218         ASSERT_NOT_REACHED();
1219         return;
1220     }
1221
1222     // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat.
1223     const bool srcFormatComesFromDOMElementOrImageData = GraphicsContext3D::srcFormatComesFromDOMElementOrImageData(SrcFormat);
1224     if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) {
1225         ASSERT_NOT_REACHED();
1226         return;
1227     }
1228     // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
1229     if (!srcFormatComesFromDOMElementOrImageData && alphaOp == GraphicsContext3D::AlphaDoUnmultiply) {
1230         ASSERT_NOT_REACHED();
1231         return;
1232     }
1233     if ((!GraphicsContext3D::hasAlpha(SrcFormat) || !GraphicsContext3D::hasColor(SrcFormat) || !GraphicsContext3D::hasColor(DstFormat)) && alphaOp != GraphicsContext3D::AlphaDoNothing) {
1234         ASSERT_NOT_REACHED();
1235         return;
1236     }
1237
1238     typedef typename DataTypeForFormat<SrcFormat>::Type SrcType;
1239     typedef typename DataTypeForFormat<DstFormat>::Type DstType;
1240     const int IntermediateSrcFormat = IntermediateFormat<DstFormat>::Value;
1241     typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType;
1242     const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType);
1243     const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType);
1244     const bool trivialUnpack = (SrcFormat == GraphicsContext3D::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == GraphicsContext3D::DataFormatRGBA32F;
1245     const bool trivialPack = (DstFormat == GraphicsContext3D::DataFormatRGBA8 || DstFormat == GraphicsContext3D::DataFormatRGBA32F) && alphaOp == GraphicsContext3D::AlphaDoNothing && m_dstStride > 0;
1246     ASSERT(!trivialUnpack || !trivialPack);
1247
1248     const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart);
1249     DstType* dstRowStart = static_cast<DstType*>(m_dstStart);
1250     if (!trivialUnpack && trivialPack) {
1251         for (size_t i = 0; i < m_height; ++i) {
1252             unpack<SrcFormat>(srcRowStart, dstRowStart, m_width);
1253             srcRowStart += srcStrideInElements;
1254             dstRowStart += dstStrideInElements;
1255         }
1256     } else if (!trivialUnpack && !trivialPack) {
1257         for (size_t i = 0; i < m_height; ++i) {
1258             unpack<SrcFormat>(srcRowStart, reinterpret_cast_ptr<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), m_width);
1259             pack<DstFormat, alphaOp>(reinterpret_cast_ptr<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), dstRowStart, m_width);
1260             srcRowStart += srcStrideInElements;
1261             dstRowStart += dstStrideInElements;
1262         }
1263     } else {
1264         for (size_t i = 0; i < m_height; ++i) {
1265             pack<DstFormat, alphaOp>(srcRowStart, dstRowStart, m_width);
1266             srcRowStart += srcStrideInElements;
1267             dstRowStart += dstStrideInElements;
1268         }
1269     }
1270     m_success = true;
1271     return;
1272 }
1273
1274 } // namespace WebCore
1275
1276 #endif // USE(3D_GRAPHICS)