• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getDataFormat(GC3Denum destinationFormat,GC3Denum destinationType)38 GraphicsContext3D::DataFormat getDataFormat(GC3Denum destinationFormat, GC3Denum 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 
convertFloatToHalfFloat(float f)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>
unpack(const SourceType *,DstType *,unsigned)252 void unpack(const SourceType*, DstType*, unsigned)
253 {
254     ASSERT_NOT_REACHED();
255 }
256 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint16_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint16_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint16_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,float * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,float * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,float * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,float * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,float * destination,unsigned pixelsPerRow)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 
unpack(const uint8_t * source,float * destination,unsigned pixelsPerRow)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 
unpack(const float * source,float * destination,unsigned pixelsPerRow)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 
unpack(const float * source,float * destination,unsigned pixelsPerRow)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 
unpack(const float * source,float * destination,unsigned pixelsPerRow)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 
unpack(const float * source,float * destination,unsigned pixelsPerRow)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>
pack(const SourceType *,DstType *,unsigned)560 void pack(const SourceType*, DstType*, unsigned)
561 {
562     ASSERT_NOT_REACHED();
563 }
564 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint8_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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.
pack(const uint8_t * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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.
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,float * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
pack(const float * source,uint16_t * destination,unsigned pixelsPerRow)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 
HasAlpha(int format)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 
HasColor(int format)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 
TexelBytesForFormat(GraphicsContext3D::DataFormat format)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:
FormatConverter(unsigned width,unsigned height,const void * srcStart,void * dstStart,int srcStride,int dstStride)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);
Success() const1293     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 
convert(GraphicsContext3D::DataFormat srcFormat,GraphicsContext3D::DataFormat dstFormat,GraphicsContext3D::AlphaOp alphaOp)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>
convert(GraphicsContext3D::DataFormat dstFormat,GraphicsContext3D::AlphaOp alphaOp)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>
convert(GraphicsContext3D::AlphaOp alphaOp)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>
convert()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 
packImageData(Image * image,const void * pixels,GC3Denum format,GC3Denum type,bool flipY,AlphaOp alphaOp,DataFormat sourceFormat,unsigned width,unsigned height,unsigned sourceUnpackAlignment,Vector<uint8_t> & data)1462 bool GraphicsContext3D::packImageData(
1463     Image* image,
1464     const void* pixels,
1465     GC3Denum format,
1466     GC3Denum 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 
extractImageData(const uint8_t * imageData,const IntSize & imageDataSize,GC3Denum format,GC3Denum type,bool flipY,bool premultiplyAlpha,Vector<uint8_t> & data)1491 bool GraphicsContext3D::extractImageData(
1492     const uint8_t* imageData,
1493     const IntSize& imageDataSize,
1494     GC3Denum format,
1495     GC3Denum 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 
extractTextureData(unsigned width,unsigned height,GC3Denum format,GC3Denum type,unsigned unpackAlignment,bool flipY,bool premultiplyAlpha,const void * pixels,Vector<uint8_t> & data)1517 bool GraphicsContext3D::extractTextureData(
1518     unsigned width,
1519     unsigned height,
1520     GC3Denum format, GC3Denum 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 
packPixels(const uint8_t * sourceData,DataFormat sourceDataFormat,unsigned width,unsigned height,unsigned sourceUnpackAlignment,unsigned destinationFormat,unsigned destinationType,AlphaOp alphaOp,void * destinationData,bool flipY)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 
1589