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