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