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