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 COMPUTER, 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 COMPUTER, 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 #ifndef WEBGLTEXELCONVERSIONS_H_
29 #define WEBGLTEXELCONVERSIONS_H_
30
31 #ifdef __SUNPRO_CC
32 #define __restrict
33 #endif
34
35 #include "WebGLTypes.h"
36 #include <stdint.h>
37 #include "mozilla/Attributes.h"
38 #include "mozilla/Casting.h"
39
40 namespace mozilla {
41
42 bool ConvertImage(size_t width, size_t height,
43 const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
44 WebGLTexelFormat srcFormat, bool srcPremultiplied,
45 void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
46 WebGLTexelFormat dstFormat, bool dstPremultiplied,
47 bool* out_wasTrivial);
48
49 //////////////////////////////////////////////////////////////////////////////////////////
50
51 // single precision float
52 // seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
53
54 // half precision float
55 // seeeeemmmmmmmmmm
56
57 // IEEE 16bits floating point:
58 const uint16_t kFloat16Value_Zero = 0x0000; // = 0000000000000000b
59 const uint16_t kFloat16Value_One = 0x3C00; // = 0011110000000000b
60 const uint16_t kFloat16Value_Infinity = 0x7C00; // = 0111110000000000b
61 const uint16_t kFloat16Value_NaN = 0x7FFF; // = 011111yyyyyyyyyyb (nonzero y)
62
63 MOZ_ALWAYS_INLINE uint16_t
packToFloat16(float v)64 packToFloat16(float v)
65 {
66 union {
67 float f32Value;
68 uint32_t f32Bits;
69 };
70
71 f32Value = v;
72
73 // pull the sign from v into f16bits
74 uint16_t f16Bits = uint16_t(f32Bits >> 16) & 0x8000;
75 const uint32_t mantissa = f32Bits & 0x7FFFFF;
76 const uint32_t exp = (f32Bits >> 23) & 0xFF;
77
78 // Adapted from: OpenGL ES 2.0 Programming Guide Appx.
79 // Converting Float to Half-Float
80 // 143 = 255 - 127 + 15
81 // = sp_max - sp_bias + hp_bias
82 if (exp >= 143) {
83 if (mantissa && exp == 0xFF) {
84 // Single precision was NaN
85 return f16Bits | kFloat16Value_NaN;
86 } else {
87 // Outside range, store as infinity
88 return f16Bits | kFloat16Value_Infinity;
89 }
90 }
91
92 // too small, try to make a denormalized number
93 // 112 = 255 - 127 - (15 + 1)
94 // = sp_max - sp_bias - (hp_bias + 1)
95 if (exp <= 112) {
96 return f16Bits | uint16_t(mantissa >> (14 + 112 - exp));
97 }
98
99 f16Bits |= uint16_t(exp - 112) << 10;
100 f16Bits |= uint16_t(mantissa >> 13) & 0x03FF;
101
102 return f16Bits;
103 }
104
105 MOZ_ALWAYS_INLINE float
unpackFromFloat16(uint16_t v)106 unpackFromFloat16(uint16_t v)
107 {
108 union {
109 float f32Value;
110 uint32_t f32Bits;
111 };
112
113 // grab sign bit
114 f32Bits = uint32_t(v & 0x8000) << 16;
115 uint16_t exp = (v >> 10) & 0x001F;
116 uint16_t mantissa = v & 0x03FF;
117
118 if (!exp) {
119 // Handle denormalized numbers
120 // Adapted from: OpenGL ES 2.0 Programming Guide Appx.
121 // Converting Float to Half-Float
122 if (mantissa) {
123 exp = 112; // See packToFloat16
124 mantissa <<= 1;
125 // For every leading zero, decrement the exponent
126 // and shift the mantissa to the left
127 while ((mantissa & (1 << 10)) == 0) {
128 mantissa <<= 1;
129 --exp;
130 }
131 mantissa &= 0x03FF;
132
133 f32Bits |= (exp << 23) | (mantissa << 13);
134
135 // Denormalized number
136 return f32Value;
137 }
138
139 // +/- zero
140 return f32Value;
141 }
142
143 if (exp == 0x001F) {
144 if (v & 0x03FF) {
145 // this is a NaN
146 f32Bits |= 0x7FFFFFFF;
147 } else {
148 // this is -inf or +inf
149 f32Bits |= 0x7F800000;
150 }
151 return f32Value;
152 }
153
154 f32Bits |= uint32_t(exp + (-15 + 127)) << 23;
155 f32Bits |= uint32_t(v & 0x03FF) << 13;
156
157 return f32Value;
158 }
159
160 // These routines come from angle/common/mathutil.h
161 // They are copied here to remove the dependency on ANGLE headers
162 // included from mathutil.h
163 MOZ_ALWAYS_INLINE uint16_t
packToFloat11(float fp32)164 packToFloat11(float fp32)
165 {
166 const unsigned int float32MantissaMask = 0x7FFFFF;
167 const unsigned int float32ExponentMask = 0x7F800000;
168 const unsigned int float32SignMask = 0x80000000;
169 const unsigned int float32ValueMask = ~float32SignMask;
170 const unsigned int float32ExponentFirstBit = 23;
171 const unsigned int float32ExponentBias = 127;
172
173 const unsigned short float11Max = 0x7BF;
174 const unsigned short float11MantissaMask = 0x3F;
175 const unsigned short float11ExponentMask = 0x7C0;
176 const unsigned short float11BitMask = 0x7FF;
177 const unsigned int float11ExponentBias = 14;
178
179 const unsigned int float32Maxfloat11 = 0x477E0000;
180 const unsigned int float32Minfloat11 = 0x38800000;
181
182 const unsigned int float32Bits = BitwiseCast<unsigned int>(fp32);
183 const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
184
185 unsigned int float32Val = float32Bits & float32ValueMask;
186
187 if ((float32Val & float32ExponentMask) == float32ExponentMask)
188 {
189 // INF or NAN
190 if ((float32Val & float32MantissaMask) != 0)
191 {
192 return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
193 }
194 else if (float32Sign)
195 {
196 // -INF is clamped to 0 since float11 is positive only
197 return 0;
198 }
199 else
200 {
201 return float11ExponentMask;
202 }
203 }
204 else if (float32Sign)
205 {
206 // float11 is positive only, so clamp to zero
207 return 0;
208 }
209 else if (float32Val > float32Maxfloat11)
210 {
211 // The number is too large to be represented as a float11, set to max
212 return float11Max;
213 }
214 else
215 {
216 if (float32Val < float32Minfloat11)
217 {
218 // The number is too small to be represented as a normalized float11
219 // Convert it to a denormalized value.
220 const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
221 float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
222 }
223 else
224 {
225 // Rebias the exponent to represent the value as a normalized float11
226 float32Val += 0xC8000000;
227 }
228
229 return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
230 }
231 }
232
233 MOZ_ALWAYS_INLINE uint16_t
packToFloat10(float fp32)234 packToFloat10(float fp32)
235 {
236 const unsigned int float32MantissaMask = 0x7FFFFF;
237 const unsigned int float32ExponentMask = 0x7F800000;
238 const unsigned int float32SignMask = 0x80000000;
239 const unsigned int float32ValueMask = ~float32SignMask;
240 const unsigned int float32ExponentFirstBit = 23;
241 const unsigned int float32ExponentBias = 127;
242
243 const unsigned short float10Max = 0x3DF;
244 const unsigned short float10MantissaMask = 0x1F;
245 const unsigned short float10ExponentMask = 0x3E0;
246 const unsigned short float10BitMask = 0x3FF;
247 const unsigned int float10ExponentBias = 14;
248
249 const unsigned int float32Maxfloat10 = 0x477C0000;
250 const unsigned int float32Minfloat10 = 0x38800000;
251
252 const unsigned int float32Bits = BitwiseCast<unsigned int>(fp32);
253 const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
254
255 unsigned int float32Val = float32Bits & float32ValueMask;
256
257 if ((float32Val & float32ExponentMask) == float32ExponentMask)
258 {
259 // INF or NAN
260 if ((float32Val & float32MantissaMask) != 0)
261 {
262 return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
263 }
264 else if (float32Sign)
265 {
266 // -INF is clamped to 0 since float11 is positive only
267 return 0;
268 }
269 else
270 {
271 return float10ExponentMask;
272 }
273 }
274 else if (float32Sign)
275 {
276 // float10 is positive only, so clamp to zero
277 return 0;
278 }
279 else if (float32Val > float32Maxfloat10)
280 {
281 // The number is too large to be represented as a float11, set to max
282 return float10Max;
283 }
284 else
285 {
286 if (float32Val < float32Minfloat10)
287 {
288 // The number is too small to be represented as a normalized float11
289 // Convert it to a denormalized value.
290 const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
291 float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
292 }
293 else
294 {
295 // Rebias the exponent to represent the value as a normalized float11
296 float32Val += 0xC8000000;
297 }
298
299 return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
300 }
301 }
302
303
304 enum class WebGLTexelPremultiplicationOp : int {
305 None,
306 Premultiply,
307 Unpremultiply
308 };
309
310 namespace WebGLTexelConversions {
311
312 template<WebGLTexelFormat Format>
313 struct IsFloatFormat
314 {
315 static const bool Value =
316 Format == WebGLTexelFormat::A32F ||
317 Format == WebGLTexelFormat::R32F ||
318 Format == WebGLTexelFormat::RA32F ||
319 Format == WebGLTexelFormat::RG32F ||
320 Format == WebGLTexelFormat::RGB11F11F10F ||
321 Format == WebGLTexelFormat::RGB32F ||
322 Format == WebGLTexelFormat::RGBA32F;
323 };
324
325 template<WebGLTexelFormat Format>
326 struct IsHalfFloatFormat
327 {
328 static const bool Value =
329 Format == WebGLTexelFormat::A16F ||
330 Format == WebGLTexelFormat::R16F ||
331 Format == WebGLTexelFormat::RA16F ||
332 Format == WebGLTexelFormat::RG16F ||
333 Format == WebGLTexelFormat::RGB16F ||
334 Format == WebGLTexelFormat::RGBA16F;
335 };
336
337 template<WebGLTexelFormat Format>
338 struct Is16bppFormat
339 {
340 static const bool Value =
341 Format == WebGLTexelFormat::RGB565 ||
342 Format == WebGLTexelFormat::RGBA4444 ||
343 Format == WebGLTexelFormat::RGBA5551;
344 };
345
346 template<WebGLTexelFormat Format,
347 bool IsFloat = IsFloatFormat<Format>::Value,
348 bool Is16bpp = Is16bppFormat<Format>::Value,
349 bool IsHalfFloat = IsHalfFloatFormat<Format>::Value>
350 struct DataTypeForFormat
351 {
352 typedef uint8_t Type;
353 };
354
355 template<WebGLTexelFormat Format>
356 struct DataTypeForFormat<Format, true, false, false>
357 {
358 typedef float Type;
359 };
360
361 template<WebGLTexelFormat Format>
362 struct DataTypeForFormat<Format, false, true, false>
363 {
364 typedef uint16_t Type;
365 };
366
367 template<WebGLTexelFormat Format>
368 struct DataTypeForFormat<Format, false, false, true>
369 {
370 typedef uint16_t Type;
371 };
372
373 template<>
374 struct DataTypeForFormat<WebGLTexelFormat::RGB11F11F10F, true, false, false>
375 {
376 typedef uint32_t Type;
377 };
378
379 template<WebGLTexelFormat Format>
380 struct IntermediateFormat
381 {
382 static const WebGLTexelFormat Value
383 = IsFloatFormat<Format>::Value
384 ? WebGLTexelFormat::RGBA32F
385 : IsHalfFloatFormat<Format>::Value ? WebGLTexelFormat::RGBA16F
386 : WebGLTexelFormat::RGBA8;
387 };
388
389 inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
390 switch (format) {
391 case WebGLTexelFormat::A8:
392 case WebGLTexelFormat::R8:
393 return 1;
394 case WebGLTexelFormat::A16F:
395 case WebGLTexelFormat::R16F:
396 case WebGLTexelFormat::RA8:
397 case WebGLTexelFormat::RG8:
398 case WebGLTexelFormat::RGB565:
399 case WebGLTexelFormat::RGBA4444:
400 case WebGLTexelFormat::RGBA5551:
401 return 2;
402 case WebGLTexelFormat::RGB8:
403 return 3;
404 case WebGLTexelFormat::A32F:
405 case WebGLTexelFormat::R32F:
406 case WebGLTexelFormat::RA16F:
407 case WebGLTexelFormat::RG16F:
408 case WebGLTexelFormat::RGB11F11F10F:
409 case WebGLTexelFormat::RGBA8:
410 case WebGLTexelFormat::BGRX8:
411 case WebGLTexelFormat::BGRA8:
412 return 4;
413 case WebGLTexelFormat::RGB16F:
414 return 6;
415 case WebGLTexelFormat::RA32F:
416 case WebGLTexelFormat::RG32F:
417 case WebGLTexelFormat::RGBA16F:
418 return 8;
419 case WebGLTexelFormat::RGB32F:
420 return 12;
421 case WebGLTexelFormat::RGBA32F:
422 return 16;
423 default:
424 MOZ_ASSERT(false, "Unknown texel format. Coding mistake?");
425 return 0;
426 }
427 }
428
429 MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) {
430 return (format == WebGLTexelFormat::A8 ||
431 format == WebGLTexelFormat::A16F ||
432 format == WebGLTexelFormat::A32F ||
433 format == WebGLTexelFormat::RA8 ||
434 format == WebGLTexelFormat::RA16F ||
435 format == WebGLTexelFormat::RA32F ||
436 format == WebGLTexelFormat::RGBA4444 ||
437 format == WebGLTexelFormat::RGBA5551 ||
438 format == WebGLTexelFormat::RGBA8 ||
439 format == WebGLTexelFormat::RGBA16F ||
440 format == WebGLTexelFormat::RGBA32F ||
441 format == WebGLTexelFormat::BGRA8);
442 }
443
444 MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) {
445 return (format == WebGLTexelFormat::R8 ||
446 format == WebGLTexelFormat::R16F ||
447 format == WebGLTexelFormat::R32F ||
448 format == WebGLTexelFormat::RA8 ||
449 format == WebGLTexelFormat::RA16F ||
450 format == WebGLTexelFormat::RA32F ||
451 format == WebGLTexelFormat::RG8 ||
452 format == WebGLTexelFormat::RG16F ||
453 format == WebGLTexelFormat::RG32F ||
454 format == WebGLTexelFormat::RGB565 ||
455 format == WebGLTexelFormat::RGB8 ||
456 format == WebGLTexelFormat::RGB11F11F10F ||
457 format == WebGLTexelFormat::RGB16F ||
458 format == WebGLTexelFormat::RGB32F ||
459 format == WebGLTexelFormat::RGBA4444 ||
460 format == WebGLTexelFormat::RGBA5551 ||
461 format == WebGLTexelFormat::RGBA8 ||
462 format == WebGLTexelFormat::RGBA16F ||
463 format == WebGLTexelFormat::RGBA32F ||
464 format == WebGLTexelFormat::BGRX8 ||
465 format == WebGLTexelFormat::BGRA8);
466 }
467
468 /****** BEGIN CODE SHARED WITH WEBKIT ******/
469
470 // the pack/unpack functions here are originally from this file:
471 // http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp
472
473 //----------------------------------------------------------------------
474 // Pixel unpacking routines.
475
476 template<WebGLTexelFormat Format, typename SrcType, typename DstType>
477 MOZ_ALWAYS_INLINE void
478 unpack(const SrcType* __restrict src,
479 DstType* __restrict dst)
480 {
481 MOZ_ASSERT(false, "Unimplemented texture format conversion");
482 }
483
484 ////////////////////////////////////////////////////////////////////////////////
485 // 1-channel formats
486 template<> MOZ_ALWAYS_INLINE void
487 unpack<WebGLTexelFormat::A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
488 {
489 dst[0] = 0;
490 dst[1] = 0;
491 dst[2] = 0;
492 dst[3] = src[0];
493 }
494
495 template<> MOZ_ALWAYS_INLINE void
496 unpack<WebGLTexelFormat::A16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
497 {
498 dst[0] = kFloat16Value_Zero;
499 dst[1] = kFloat16Value_Zero;
500 dst[2] = kFloat16Value_Zero;
501 dst[3] = src[0];
502 }
503
504 template<> MOZ_ALWAYS_INLINE void
505 unpack<WebGLTexelFormat::A32F, float, float>(const float* __restrict src, float* __restrict dst)
506 {
507 dst[0] = 0;
508 dst[1] = 0;
509 dst[2] = 0;
510 dst[3] = src[0];
511 }
512
513 template<> MOZ_ALWAYS_INLINE void
514 unpack<WebGLTexelFormat::R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
515 {
516 dst[0] = src[0];
517 dst[1] = src[0];
518 dst[2] = src[0];
519 dst[3] = 0xFF;
520 }
521
522 template<> MOZ_ALWAYS_INLINE void
523 unpack<WebGLTexelFormat::R16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
524 {
525 dst[0] = src[0];
526 dst[1] = src[0];
527 dst[2] = src[0];
528 dst[3] = kFloat16Value_One;
529 }
530
531 template<> MOZ_ALWAYS_INLINE void
532 unpack<WebGLTexelFormat::R32F, float, float>(const float* __restrict src, float* __restrict dst)
533 {
534 dst[0] = src[0];
535 dst[1] = src[0];
536 dst[2] = src[0];
537 dst[3] = 1.0f;
538 }
539
540 ////////////////////////////////////////////////////////////////////////////////
541 // 2-channel formats
542 template<> MOZ_ALWAYS_INLINE void
543 unpack<WebGLTexelFormat::RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
544 {
545 dst[0] = src[0];
546 dst[1] = src[0];
547 dst[2] = src[0];
548 dst[3] = src[1];
549 }
550
551 template<> MOZ_ALWAYS_INLINE void
552 unpack<WebGLTexelFormat::RA16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
553 {
554 dst[0] = src[0];
555 dst[1] = src[0];
556 dst[2] = src[0];
557 dst[3] = src[1];
558 }
559
560 template<> MOZ_ALWAYS_INLINE void
561 unpack<WebGLTexelFormat::RA32F, float, float>(const float* __restrict src, float* __restrict dst)
562 {
563 dst[0] = src[0];
564 dst[1] = src[0];
565 dst[2] = src[0];
566 dst[3] = src[1];
567 }
568
569 ////////////////////////////////////////////////////////////////////////////////
570 // 3-channel formats
571 template<> MOZ_ALWAYS_INLINE void
572 unpack<WebGLTexelFormat::RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
573 {
574 uint16_t packedValue = src[0];
575 uint8_t r = (packedValue >> 11) & 0x1F;
576 uint8_t g = (packedValue >> 5) & 0x3F;
577 uint8_t b = packedValue & 0x1F;
578 dst[0] = (r << 3) | (r & 0x7);
579 dst[1] = (g << 2) | (g & 0x3);
580 dst[2] = (b << 3) | (b & 0x7);
581 dst[3] = 0xFF;
582 }
583
584 template<> MOZ_ALWAYS_INLINE void
585 unpack<WebGLTexelFormat::RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
586 {
587 dst[0] = src[0];
588 dst[1] = src[1];
589 dst[2] = src[2];
590 dst[3] = 0xFF;
591 }
592
593 template<> MOZ_ALWAYS_INLINE void
594 unpack<WebGLTexelFormat::RGB16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
595 {
596 dst[0] = src[0];
597 dst[1] = src[1];
598 dst[2] = src[2];
599 dst[3] = kFloat16Value_One;
600 }
601
602 template<> MOZ_ALWAYS_INLINE void
603 unpack<WebGLTexelFormat::RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
604 {
605 dst[0] = src[0];
606 dst[1] = src[1];
607 dst[2] = src[2];
608 dst[3] = 1.0f;
609 }
610
611 ////////////////////////////////////////////////////////////////////////////////
612 // 4-channel formats
613 template<> MOZ_ALWAYS_INLINE void
614 unpack<WebGLTexelFormat::RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
615 {
616 uint16_t packedValue = src[0];
617 uint8_t r = (packedValue >> 12) & 0x0F;
618 uint8_t g = (packedValue >> 8) & 0x0F;
619 uint8_t b = (packedValue >> 4) & 0x0F;
620 uint8_t a = packedValue & 0x0F;
621 dst[0] = (r << 4) | r;
622 dst[1] = (g << 4) | g;
623 dst[2] = (b << 4) | b;
624 dst[3] = (a << 4) | a;
625 }
626
627 template<> MOZ_ALWAYS_INLINE void
628 unpack<WebGLTexelFormat::RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
629 {
630 uint16_t packedValue = src[0];
631 uint8_t r = (packedValue >> 11) & 0x1F;
632 uint8_t g = (packedValue >> 6) & 0x1F;
633 uint8_t b = (packedValue >> 1) & 0x1F;
634 dst[0] = (r << 3) | (r & 0x7);
635 dst[1] = (g << 3) | (g & 0x7);
636 dst[2] = (b << 3) | (b & 0x7);
637 dst[3] = (packedValue & 0x1) ? 0xFF : 0;
638 }
639
640 template<> MOZ_ALWAYS_INLINE void
641 unpack<WebGLTexelFormat::RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
642 {
643 dst[0] = src[0];
644 dst[1] = src[1];
645 dst[2] = src[2];
646 dst[3] = src[3];
647 }
648
649 template<> MOZ_ALWAYS_INLINE void
650 unpack<WebGLTexelFormat::RGBA16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
651 {
652 dst[0] = src[0];
653 dst[1] = src[1];
654 dst[2] = src[2];
655 dst[3] = src[3];
656 }
657
658 template<> MOZ_ALWAYS_INLINE void
659 unpack<WebGLTexelFormat::RGBA32F, float, float>(const float* __restrict src, float* __restrict dst)
660 {
661 dst[0] = src[0];
662 dst[1] = src[1];
663 dst[2] = src[2];
664 dst[3] = src[3];
665 }
666
667 ////////////////////////////////////////////////////////////////////////////////
668 // DOM element formats
669 template<> MOZ_ALWAYS_INLINE void
670 unpack<WebGLTexelFormat::BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
671 {
672 dst[0] = src[2];
673 dst[1] = src[1];
674 dst[2] = src[0];
675 dst[3] = 0xFF;
676 }
677
678 template<> MOZ_ALWAYS_INLINE void
679 unpack<WebGLTexelFormat::BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
680 {
681 dst[0] = src[2];
682 dst[1] = src[1];
683 dst[2] = src[0];
684 dst[3] = src[3];
685 }
686
687 //----------------------------------------------------------------------
688 // Pixel packing routines.
689 //
690
691 template<WebGLTexelFormat Format,
692 WebGLTexelPremultiplicationOp PremultiplicationOp,
693 typename SrcType,
694 typename DstType>
695 MOZ_ALWAYS_INLINE void
696 pack(const SrcType* __restrict src,
697 DstType* __restrict dst)
698 {
699 MOZ_CRASH("GFX: Unimplemented texture format conversion");
700 }
701
702 ////////////////////////////////////////////////////////////////////////////////
703 // 1-channel formats
704 template<> MOZ_ALWAYS_INLINE void
705 pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
706 {
707 dst[0] = src[3];
708 }
709
710 template<> MOZ_ALWAYS_INLINE void
711 pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
712 {
713 dst[0] = src[3];
714 }
715
716 template<> MOZ_ALWAYS_INLINE void
717 pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
718 {
719 dst[0] = src[3];
720 }
721
722 template<> MOZ_ALWAYS_INLINE void
723 pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
724 {
725 dst[0] = src[3];
726 }
727
728 template<> MOZ_ALWAYS_INLINE void
729 pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
730 {
731 dst[0] = src[3];
732 }
733
734 template<> MOZ_ALWAYS_INLINE void
735 pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
736 {
737 dst[0] = src[3];
738 }
739
740 template<> MOZ_ALWAYS_INLINE void
741 pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
742 {
743 dst[0] = src[3];
744 }
745
746 template<> MOZ_ALWAYS_INLINE void
747 pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
748 {
749 dst[0] = src[3];
750 }
751
752 template<> MOZ_ALWAYS_INLINE void
753 pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
754 {
755 dst[0] = src[3];
756 }
757
758 template<> MOZ_ALWAYS_INLINE void
759 pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
760 {
761 dst[0] = src[0];
762 }
763
764 template<> MOZ_ALWAYS_INLINE void
765 pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
766 {
767 float scaleFactor = src[3] / 255.0f;
768 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
769 dst[0] = srcR;
770 }
771
772 template<> MOZ_ALWAYS_INLINE void
773 pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
774 {
775 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
776 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
777 dst[0] = srcR;
778 }
779
780 template<> MOZ_ALWAYS_INLINE void
781 pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
782 {
783 dst[0] = src[0];
784 }
785
786 template<> MOZ_ALWAYS_INLINE void
787 pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
788 {
789 float scaleFactor = unpackFromFloat16(src[3]);
790 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
791 }
792
793 template<> MOZ_ALWAYS_INLINE void
794 pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
795 {
796 float unpackedAlpha = unpackFromFloat16(src[3]);
797 float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
798 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
799 }
800
801 template<> MOZ_ALWAYS_INLINE void
802 pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
803 {
804 dst[0] = src[0];
805 }
806
807 template<> MOZ_ALWAYS_INLINE void
808 pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
809 {
810 float scaleFactor = src[3];
811 dst[0] = src[0] * scaleFactor;
812 }
813
814 template<> MOZ_ALWAYS_INLINE void
815 pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
816 {
817 float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
818 dst[0] = src[0] * scaleFactor;
819 }
820
821 ////////////////////////////////////////////////////////////////////////////////
822 // 2-channel formats
823 template<> MOZ_ALWAYS_INLINE void
824 pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
825 {
826 dst[0] = src[0];
827 dst[1] = src[3];
828 }
829
830 template<> MOZ_ALWAYS_INLINE void
831 pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
832 {
833 float scaleFactor = src[3] / 255.0f;
834 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
835 dst[0] = srcR;
836 dst[1] = src[3];
837 }
838
839 // FIXME: this routine is lossy and must be removed.
840 template<> MOZ_ALWAYS_INLINE void
841 pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
842 {
843 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
844 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
845 dst[0] = srcR;
846 dst[1] = src[3];
847 }
848
849 template<> MOZ_ALWAYS_INLINE void
850 pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
851 {
852 dst[0] = src[0];
853 dst[1] = src[3];
854 }
855
856 template<> MOZ_ALWAYS_INLINE void
857 pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
858 {
859 float scaleFactor = unpackFromFloat16(src[3]);
860 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
861 dst[1] = src[3];
862 }
863
864 template<> MOZ_ALWAYS_INLINE void
865 pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
866 {
867 float unpackedAlpha = unpackFromFloat16(src[3]);
868 float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
869 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
870 dst[1] = src[3];
871 }
872
873 template<> MOZ_ALWAYS_INLINE void
874 pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
875 {
876 dst[0] = src[0];
877 dst[1] = src[3];
878 }
879
880 template<> MOZ_ALWAYS_INLINE void
881 pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
882 {
883 float scaleFactor = src[3];
884 dst[0] = src[0] * scaleFactor;
885 dst[1] = src[3];
886 }
887
888 template<> MOZ_ALWAYS_INLINE void
889 pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
890 {
891 float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
892 dst[0] = src[0] * scaleFactor;
893 dst[1] = src[3];
894 }
895
896 template<> MOZ_ALWAYS_INLINE void
897 pack<WebGLTexelFormat::RG8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
898 {
899 dst[0] = src[0];
900 dst[1] = src[1];
901 }
902
903 template<> MOZ_ALWAYS_INLINE void
904 pack<WebGLTexelFormat::RG8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
905 {
906 float scaleFactor = src[3] / 255.0f;
907 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
908 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
909 dst[0] = srcR;
910 dst[1] = srcG;
911 }
912
913 // FIXME: this routine is lossy and must be removed.
914 template<> MOZ_ALWAYS_INLINE void
915 pack<WebGLTexelFormat::RG8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
916 {
917 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
918 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
919 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
920 dst[0] = srcR;
921 dst[1] = srcG;
922 }
923
924 template<> MOZ_ALWAYS_INLINE void
925 pack<WebGLTexelFormat::RG16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
926 {
927 dst[0] = src[0];
928 dst[1] = src[1];
929 }
930
931 template<> MOZ_ALWAYS_INLINE void
932 pack<WebGLTexelFormat::RG16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
933 {
934 float scaleFactor = unpackFromFloat16(src[3]);
935 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
936 dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
937 }
938
939 template<> MOZ_ALWAYS_INLINE void
940 pack<WebGLTexelFormat::RG16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
941 {
942 float unpackedAlpha = unpackFromFloat16(src[3]);
943 float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
944 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
945 dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
946 }
947
948 template<> MOZ_ALWAYS_INLINE void
949 pack<WebGLTexelFormat::RG32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
950 {
951 dst[0] = src[0];
952 dst[1] = src[1];
953 }
954
955 template<> MOZ_ALWAYS_INLINE void
956 pack<WebGLTexelFormat::RG32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
957 {
958 float scaleFactor = src[3];
959 dst[0] = src[0] * scaleFactor;
960 dst[1] = src[1] * scaleFactor;
961 }
962
963 template<> MOZ_ALWAYS_INLINE void
964 pack<WebGLTexelFormat::RG32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
965 {
966 float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
967 dst[0] = src[0] * scaleFactor;
968 dst[1] = src[1] * scaleFactor;
969 }
970
971 ////////////////////////////////////////////////////////////////////////////////
972 // 3-channel formats
973 template<> MOZ_ALWAYS_INLINE void
974 pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
975 {
976 *dst = ( ((src[0] & 0xF8) << 8)
977 | ((src[1] & 0xFC) << 3)
978 | ((src[2] & 0xF8) >> 3));
979 }
980
981 template<> MOZ_ALWAYS_INLINE void
982 pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
983 {
984 float scaleFactor = src[3] / 255.0f;
985 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
986 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
987 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
988 *dst = ( ((srcR & 0xF8) << 8)
989 | ((srcG & 0xFC) << 3)
990 | ((srcB & 0xF8) >> 3));
991 }
992
993 // FIXME: this routine is lossy and must be removed.
994 template<> MOZ_ALWAYS_INLINE void
995 pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
996 {
997 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
998 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
999 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1000 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1001 *dst = ( ((srcR & 0xF8) << 8)
1002 | ((srcG & 0xFC) << 3)
1003 | ((srcB & 0xF8) >> 3));
1004 }
1005
1006 template<> MOZ_ALWAYS_INLINE void
1007 pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1008 {
1009 dst[0] = src[0];
1010 dst[1] = src[1];
1011 dst[2] = src[2];
1012 }
1013
1014 template<> MOZ_ALWAYS_INLINE void
1015 pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1016 {
1017 float scaleFactor = src[3] / 255.0f;
1018 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1019 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1020 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1021 dst[0] = srcR;
1022 dst[1] = srcG;
1023 dst[2] = srcB;
1024 }
1025
1026 template<> MOZ_ALWAYS_INLINE void
1027 pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1028 {
1029 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
1030 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1031 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1032 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1033 dst[0] = srcR;
1034 dst[1] = srcG;
1035 dst[2] = srcB;
1036 }
1037
1038 template<> MOZ_ALWAYS_INLINE void
1039 pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::None, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst)
1040 {
1041 dst[0] = ((packToFloat11(src[0]) << 0) |
1042 (packToFloat11(src[1]) << 11) |
1043 (packToFloat10(src[2]) << 22));
1044 }
1045
1046 template<> MOZ_ALWAYS_INLINE void
1047 pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::Premultiply, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst)
1048 {
1049 float scaleFactor = src[3];
1050 dst[0] = ((packToFloat11(src[0] * scaleFactor) << 0) |
1051 (packToFloat11(src[1] * scaleFactor) << 11) |
1052 (packToFloat10(src[2] * scaleFactor) << 22));
1053 }
1054
1055 template<> MOZ_ALWAYS_INLINE void
1056 pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::Unpremultiply, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst)
1057 {
1058 float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
1059 dst[0] = ((packToFloat11(src[0] * scaleFactor) << 0) |
1060 (packToFloat11(src[1] * scaleFactor) << 11) |
1061 (packToFloat10(src[2] * scaleFactor) << 22));
1062 }
1063
1064 template<> MOZ_ALWAYS_INLINE void
1065 pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1066 {
1067 dst[0] = src[0];
1068 dst[1] = src[1];
1069 dst[2] = src[2];
1070 }
1071
1072 template<> MOZ_ALWAYS_INLINE void
1073 pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1074 {
1075 float scaleFactor = unpackFromFloat16(src[3]);
1076 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
1077 dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
1078 dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
1079 }
1080
1081 template<> MOZ_ALWAYS_INLINE void
1082 pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1083 {
1084 float unpackedAlpha = unpackFromFloat16(src[3]);
1085 float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
1086 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
1087 dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
1088 dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
1089 }
1090
1091 template<> MOZ_ALWAYS_INLINE void
1092 pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
1093 {
1094 dst[0] = src[0];
1095 dst[1] = src[1];
1096 dst[2] = src[2];
1097 }
1098
1099 template<> MOZ_ALWAYS_INLINE void
1100 pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
1101 {
1102 float scaleFactor = src[3];
1103 dst[0] = src[0] * scaleFactor;
1104 dst[1] = src[1] * scaleFactor;
1105 dst[2] = src[2] * scaleFactor;
1106 }
1107
1108 template<> MOZ_ALWAYS_INLINE void
1109 pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
1110 {
1111 float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
1112 dst[0] = src[0] * scaleFactor;
1113 dst[1] = src[1] * scaleFactor;
1114 dst[2] = src[2] * scaleFactor;
1115 }
1116
1117 ////////////////////////////////////////////////////////////////////////////////
1118 // 4-channel formats
1119 template<> MOZ_ALWAYS_INLINE void
1120 pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1121 {
1122 *dst = ( ((src[0] & 0xF0) << 8)
1123 | ((src[1] & 0xF0) << 4)
1124 | (src[2] & 0xF0)
1125 | (src[3] >> 4) );
1126 }
1127
1128 template<> MOZ_ALWAYS_INLINE void
1129 pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1130 {
1131 float scaleFactor = src[3] / 255.0f;
1132 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1133 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1134 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1135 *dst = ( ((srcR & 0xF0) << 8)
1136 | ((srcG & 0xF0) << 4)
1137 | (srcB & 0xF0)
1138 | (src[3] >> 4));
1139 }
1140
1141 // FIXME: this routine is lossy and must be removed.
1142 template<> MOZ_ALWAYS_INLINE void
1143 pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1144 {
1145 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
1146 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1147 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1148 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1149 *dst = ( ((srcR & 0xF0) << 8)
1150 | ((srcG & 0xF0) << 4)
1151 | (srcB & 0xF0)
1152 | (src[3] >> 4));
1153 }
1154
1155 template<> MOZ_ALWAYS_INLINE void
1156 pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1157 {
1158 *dst = ( ((src[0] & 0xF8) << 8)
1159 | ((src[1] & 0xF8) << 3)
1160 | ((src[2] & 0xF8) >> 2)
1161 | (src[3] >> 7));
1162 }
1163
1164 template<> MOZ_ALWAYS_INLINE void
1165 pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1166 {
1167 float scaleFactor = src[3] / 255.0f;
1168 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1169 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1170 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1171 *dst = ( ((srcR & 0xF8) << 8)
1172 | ((srcG & 0xF8) << 3)
1173 | ((srcB & 0xF8) >> 2)
1174 | (src[3] >> 7));
1175 }
1176
1177 // FIXME: this routine is lossy and must be removed.
1178 template<> MOZ_ALWAYS_INLINE void
1179 pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1180 {
1181 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
1182 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1183 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1184 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1185 *dst = ( ((srcR & 0xF8) << 8)
1186 | ((srcG & 0xF8) << 3)
1187 | ((srcB & 0xF8) >> 2)
1188 | (src[3] >> 7));
1189 }
1190
1191 template<> MOZ_ALWAYS_INLINE void
1192 pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1193 {
1194 dst[0] = src[0];
1195 dst[1] = src[1];
1196 dst[2] = src[2];
1197 dst[3] = src[3];
1198 }
1199
1200 template<> MOZ_ALWAYS_INLINE void
1201 pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1202 {
1203 float scaleFactor = src[3] / 255.0f;
1204 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1205 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1206 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1207 dst[0] = srcR;
1208 dst[1] = srcG;
1209 dst[2] = srcB;
1210 dst[3] = src[3];
1211 }
1212
1213 // FIXME: this routine is lossy and must be removed.
1214 template<> MOZ_ALWAYS_INLINE void
1215 pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1216 {
1217 float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
1218 uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
1219 uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
1220 uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
1221 dst[0] = srcR;
1222 dst[1] = srcG;
1223 dst[2] = srcB;
1224 dst[3] = src[3];
1225 }
1226
1227 template<> MOZ_ALWAYS_INLINE void
1228 pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1229 {
1230 dst[0] = src[0];
1231 dst[1] = src[1];
1232 dst[2] = src[2];
1233 dst[3] = src[3];
1234 }
1235
1236 template<> MOZ_ALWAYS_INLINE void
1237 pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1238 {
1239 float scaleFactor = unpackFromFloat16(src[3]);
1240 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
1241 dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
1242 dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
1243 dst[3] = src[3];
1244 }
1245
1246 template<> MOZ_ALWAYS_INLINE void
1247 pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1248 {
1249 float unpackedAlpha = unpackFromFloat16(src[3]);
1250 float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
1251 dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
1252 dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
1253 dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
1254 dst[3] = src[3];
1255 }
1256
1257 template<> MOZ_ALWAYS_INLINE void
1258 pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
1259 {
1260 dst[0] = src[0];
1261 dst[1] = src[1];
1262 dst[2] = src[2];
1263 dst[3] = src[3];
1264 }
1265
1266 template<> MOZ_ALWAYS_INLINE void
1267 pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
1268 {
1269 float scaleFactor = src[3];
1270 dst[0] = src[0] * scaleFactor;
1271 dst[1] = src[1] * scaleFactor;
1272 dst[2] = src[2] * scaleFactor;
1273 dst[3] = src[3];
1274 }
1275
1276 template<> MOZ_ALWAYS_INLINE void
1277 pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
1278 {
1279 float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
1280 dst[0] = src[0] * scaleFactor;
1281 dst[1] = src[1] * scaleFactor;
1282 dst[2] = src[2] * scaleFactor;
1283 dst[3] = src[3];
1284 }
1285
1286 /****** END CODE SHARED WITH WEBKIT ******/
1287
1288 template<typename SrcType, typename DstType> MOZ_ALWAYS_INLINE void
1289 convertType(const SrcType* __restrict src, DstType* __restrict dst)
1290 {
1291 MOZ_ASSERT(false, "Unimplemented texture format conversion");
1292 }
1293
1294 template<> MOZ_ALWAYS_INLINE void
1295 convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
1296 {
1297 dst[0] = src[0];
1298 dst[1] = src[1];
1299 dst[2] = src[2];
1300 dst[3] = src[3];
1301 }
1302
1303 template<> MOZ_ALWAYS_INLINE void
1304 convertType<uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
1305 {
1306 dst[0] = src[0];
1307 dst[1] = src[1];
1308 dst[2] = src[2];
1309 dst[3] = src[3];
1310 }
1311
1312 template<> MOZ_ALWAYS_INLINE void
1313 convertType<float, float>(const float* __restrict src, float* __restrict dst)
1314 {
1315 dst[0] = src[0];
1316 dst[1] = src[1];
1317 dst[2] = src[2];
1318 dst[3] = src[3];
1319 }
1320
1321 template<> MOZ_ALWAYS_INLINE void
1322 convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst)
1323 {
1324 const float scaleFactor = 1.f / 255.0f;
1325 dst[0] = src[0] * scaleFactor;
1326 dst[1] = src[1] * scaleFactor;
1327 dst[2] = src[2] * scaleFactor;
1328 dst[3] = src[3] * scaleFactor;
1329 }
1330
1331 template<> MOZ_ALWAYS_INLINE void
1332 convertType<uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
1333 {
1334 const float scaleFactor = 1.f / 255.0f;
1335 dst[0] = packToFloat16(src[0] * scaleFactor);
1336 dst[1] = packToFloat16(src[1] * scaleFactor);
1337 dst[2] = packToFloat16(src[2] * scaleFactor);
1338 dst[3] = packToFloat16(src[3] * scaleFactor);
1339 }
1340
1341 } // end namespace WebGLTexelConversions
1342
1343 } // end namespace mozilla
1344
1345 #endif // WEBGLTEXELCONVERSIONS_H_
1346