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