diff options
Diffstat (limited to 'dom/canvas/WebGLTexelConversions.h')
-rw-r--r-- | dom/canvas/WebGLTexelConversions.h | 1345 |
1 files changed, 1345 insertions, 0 deletions
diff --git a/dom/canvas/WebGLTexelConversions.h b/dom/canvas/WebGLTexelConversions.h new file mode 100644 index 000000000..19af9f65e --- /dev/null +++ b/dom/canvas/WebGLTexelConversions.h @@ -0,0 +1,1345 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010 Mozilla Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WEBGLTEXELCONVERSIONS_H_ +#define WEBGLTEXELCONVERSIONS_H_ + +#ifdef __SUNPRO_CC +#define __restrict +#endif + +#include "WebGLTypes.h" +#include <stdint.h> +#include "mozilla/Attributes.h" +#include "mozilla/Casting.h" + +namespace mozilla { + +bool ConvertImage(size_t width, size_t height, + const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin, + WebGLTexelFormat srcFormat, bool srcPremultiplied, + void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin, + WebGLTexelFormat dstFormat, bool dstPremultiplied, + bool* out_wasTrivial); + +////////////////////////////////////////////////////////////////////////////////////////// + +// single precision float +// seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm + +// half precision float +// seeeeemmmmmmmmmm + +// IEEE 16bits floating point: +const uint16_t kFloat16Value_Zero = 0x0000; // = 0000000000000000b +const uint16_t kFloat16Value_One = 0x3C00; // = 0011110000000000b +const uint16_t kFloat16Value_Infinity = 0x7C00; // = 0111110000000000b +const uint16_t kFloat16Value_NaN = 0x7FFF; // = 011111yyyyyyyyyyb (nonzero y) + +MOZ_ALWAYS_INLINE uint16_t +packToFloat16(float v) +{ + union { + float f32Value; + uint32_t f32Bits; + }; + + f32Value = v; + + // pull the sign from v into f16bits + uint16_t f16Bits = uint16_t(f32Bits >> 16) & 0x8000; + const uint32_t mantissa = f32Bits & 0x7FFFFF; + const uint32_t exp = (f32Bits >> 23) & 0xFF; + + // Adapted from: OpenGL ES 2.0 Programming Guide Appx. + // Converting Float to Half-Float + // 143 = 255 - 127 + 15 + // = sp_max - sp_bias + hp_bias + if (exp >= 143) { + if (mantissa && exp == 0xFF) { + // Single precision was NaN + return f16Bits | kFloat16Value_NaN; + } else { + // Outside range, store as infinity + return f16Bits | kFloat16Value_Infinity; + } + } + + // too small, try to make a denormalized number + // 112 = 255 - 127 - (15 + 1) + // = sp_max - sp_bias - (hp_bias + 1) + if (exp <= 112) { + return f16Bits | uint16_t(mantissa >> (14 + 112 - exp)); + } + + f16Bits |= uint16_t(exp - 112) << 10; + f16Bits |= uint16_t(mantissa >> 13) & 0x03FF; + + return f16Bits; +} + +MOZ_ALWAYS_INLINE float +unpackFromFloat16(uint16_t v) +{ + union { + float f32Value; + uint32_t f32Bits; + }; + + // grab sign bit + f32Bits = uint32_t(v & 0x8000) << 16; + uint16_t exp = (v >> 10) & 0x001F; + uint16_t mantissa = v & 0x03FF; + + if (!exp) { + // Handle denormalized numbers + // Adapted from: OpenGL ES 2.0 Programming Guide Appx. + // Converting Float to Half-Float + if (mantissa) { + exp = 112; // See packToFloat16 + mantissa <<= 1; + // For every leading zero, decrement the exponent + // and shift the mantissa to the left + while ((mantissa & (1 << 10)) == 0) { + mantissa <<= 1; + --exp; + } + mantissa &= 0x03FF; + + f32Bits |= (exp << 23) | (mantissa << 13); + + // Denormalized number + return f32Value; + } + + // +/- zero + return f32Value; + } + + if (exp == 0x001F) { + if (v & 0x03FF) { + // this is a NaN + f32Bits |= 0x7FFFFFFF; + } else { + // this is -inf or +inf + f32Bits |= 0x7F800000; + } + return f32Value; + } + + f32Bits |= uint32_t(exp + (-15 + 127)) << 23; + f32Bits |= uint32_t(v & 0x03FF) << 13; + + return f32Value; +} + +// These routines come from angle/common/mathutil.h +// They are copied here to remove the dependency on ANGLE headers +// included from mathutil.h +MOZ_ALWAYS_INLINE uint16_t +packToFloat11(float fp32) +{ + const unsigned int float32MantissaMask = 0x7FFFFF; + const unsigned int float32ExponentMask = 0x7F800000; + const unsigned int float32SignMask = 0x80000000; + const unsigned int float32ValueMask = ~float32SignMask; + const unsigned int float32ExponentFirstBit = 23; + const unsigned int float32ExponentBias = 127; + + const unsigned short float11Max = 0x7BF; + const unsigned short float11MantissaMask = 0x3F; + const unsigned short float11ExponentMask = 0x7C0; + const unsigned short float11BitMask = 0x7FF; + const unsigned int float11ExponentBias = 14; + + const unsigned int float32Maxfloat11 = 0x477E0000; + const unsigned int float32Minfloat11 = 0x38800000; + + const unsigned int float32Bits = BitwiseCast<unsigned int>(fp32); + const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; + + unsigned int float32Val = float32Bits & float32ValueMask; + + if ((float32Val & float32ExponentMask) == float32ExponentMask) + { + // INF or NAN + if ((float32Val & float32MantissaMask) != 0) + { + return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask); + } + else if (float32Sign) + { + // -INF is clamped to 0 since float11 is positive only + return 0; + } + else + { + return float11ExponentMask; + } + } + else if (float32Sign) + { + // float11 is positive only, so clamp to zero + return 0; + } + else if (float32Val > float32Maxfloat11) + { + // The number is too large to be represented as a float11, set to max + return float11Max; + } + else + { + if (float32Val < float32Minfloat11) + { + // The number is too small to be represented as a normalized float11 + // Convert it to a denormalized value. + const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit); + float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift; + } + else + { + // Rebias the exponent to represent the value as a normalized float11 + float32Val += 0xC8000000; + } + + return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask; + } +} + +MOZ_ALWAYS_INLINE uint16_t +packToFloat10(float fp32) +{ + const unsigned int float32MantissaMask = 0x7FFFFF; + const unsigned int float32ExponentMask = 0x7F800000; + const unsigned int float32SignMask = 0x80000000; + const unsigned int float32ValueMask = ~float32SignMask; + const unsigned int float32ExponentFirstBit = 23; + const unsigned int float32ExponentBias = 127; + + const unsigned short float10Max = 0x3DF; + const unsigned short float10MantissaMask = 0x1F; + const unsigned short float10ExponentMask = 0x3E0; + const unsigned short float10BitMask = 0x3FF; + const unsigned int float10ExponentBias = 14; + + const unsigned int float32Maxfloat10 = 0x477C0000; + const unsigned int float32Minfloat10 = 0x38800000; + + const unsigned int float32Bits = BitwiseCast<unsigned int>(fp32); + const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; + + unsigned int float32Val = float32Bits & float32ValueMask; + + if ((float32Val & float32ExponentMask) == float32ExponentMask) + { + // INF or NAN + if ((float32Val & float32MantissaMask) != 0) + { + return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask); + } + else if (float32Sign) + { + // -INF is clamped to 0 since float11 is positive only + return 0; + } + else + { + return float10ExponentMask; + } + } + else if (float32Sign) + { + // float10 is positive only, so clamp to zero + return 0; + } + else if (float32Val > float32Maxfloat10) + { + // The number is too large to be represented as a float11, set to max + return float10Max; + } + else + { + if (float32Val < float32Minfloat10) + { + // The number is too small to be represented as a normalized float11 + // Convert it to a denormalized value. + const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit); + float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift; + } + else + { + // Rebias the exponent to represent the value as a normalized float11 + float32Val += 0xC8000000; + } + + return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask; + } +} + + +enum class WebGLTexelPremultiplicationOp : int { + None, + Premultiply, + Unpremultiply +}; + +namespace WebGLTexelConversions { + +template<WebGLTexelFormat Format> +struct IsFloatFormat +{ + static const bool Value = + Format == WebGLTexelFormat::A32F || + Format == WebGLTexelFormat::R32F || + Format == WebGLTexelFormat::RA32F || + Format == WebGLTexelFormat::RG32F || + Format == WebGLTexelFormat::RGB11F11F10F || + Format == WebGLTexelFormat::RGB32F || + Format == WebGLTexelFormat::RGBA32F; +}; + +template<WebGLTexelFormat Format> +struct IsHalfFloatFormat +{ + static const bool Value = + Format == WebGLTexelFormat::A16F || + Format == WebGLTexelFormat::R16F || + Format == WebGLTexelFormat::RA16F || + Format == WebGLTexelFormat::RG16F || + Format == WebGLTexelFormat::RGB16F || + Format == WebGLTexelFormat::RGBA16F; +}; + +template<WebGLTexelFormat Format> +struct Is16bppFormat +{ + static const bool Value = + Format == WebGLTexelFormat::RGB565 || + Format == WebGLTexelFormat::RGBA4444 || + Format == WebGLTexelFormat::RGBA5551; +}; + +template<WebGLTexelFormat Format, + bool IsFloat = IsFloatFormat<Format>::Value, + bool Is16bpp = Is16bppFormat<Format>::Value, + bool IsHalfFloat = IsHalfFloatFormat<Format>::Value> +struct DataTypeForFormat +{ + typedef uint8_t Type; +}; + +template<WebGLTexelFormat Format> +struct DataTypeForFormat<Format, true, false, false> +{ + typedef float Type; +}; + +template<WebGLTexelFormat Format> +struct DataTypeForFormat<Format, false, true, false> +{ + typedef uint16_t Type; +}; + +template<WebGLTexelFormat Format> +struct DataTypeForFormat<Format, false, false, true> +{ + typedef uint16_t Type; +}; + +template<> +struct DataTypeForFormat<WebGLTexelFormat::RGB11F11F10F, true, false, false> +{ + typedef uint32_t Type; +}; + +template<WebGLTexelFormat Format> +struct IntermediateFormat +{ + static const WebGLTexelFormat Value + = IsFloatFormat<Format>::Value + ? WebGLTexelFormat::RGBA32F + : IsHalfFloatFormat<Format>::Value ? WebGLTexelFormat::RGBA16F + : WebGLTexelFormat::RGBA8; +}; + +inline size_t TexelBytesForFormat(WebGLTexelFormat format) { + switch (format) { + case WebGLTexelFormat::A8: + case WebGLTexelFormat::R8: + return 1; + case WebGLTexelFormat::A16F: + case WebGLTexelFormat::R16F: + case WebGLTexelFormat::RA8: + case WebGLTexelFormat::RG8: + case WebGLTexelFormat::RGB565: + case WebGLTexelFormat::RGBA4444: + case WebGLTexelFormat::RGBA5551: + return 2; + case WebGLTexelFormat::RGB8: + return 3; + case WebGLTexelFormat::A32F: + case WebGLTexelFormat::R32F: + case WebGLTexelFormat::RA16F: + case WebGLTexelFormat::RG16F: + case WebGLTexelFormat::RGB11F11F10F: + case WebGLTexelFormat::RGBA8: + case WebGLTexelFormat::BGRX8: + case WebGLTexelFormat::BGRA8: + return 4; + case WebGLTexelFormat::RGB16F: + return 6; + case WebGLTexelFormat::RA32F: + case WebGLTexelFormat::RG32F: + case WebGLTexelFormat::RGBA16F: + return 8; + case WebGLTexelFormat::RGB32F: + return 12; + case WebGLTexelFormat::RGBA32F: + return 16; + default: + MOZ_ASSERT(false, "Unknown texel format. Coding mistake?"); + return 0; + } +} + +MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) { + return (format == WebGLTexelFormat::A8 || + format == WebGLTexelFormat::A16F || + format == WebGLTexelFormat::A32F || + format == WebGLTexelFormat::RA8 || + format == WebGLTexelFormat::RA16F || + format == WebGLTexelFormat::RA32F || + format == WebGLTexelFormat::RGBA4444 || + format == WebGLTexelFormat::RGBA5551 || + format == WebGLTexelFormat::RGBA8 || + format == WebGLTexelFormat::RGBA16F || + format == WebGLTexelFormat::RGBA32F || + format == WebGLTexelFormat::BGRA8); +} + +MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) { + return (format == WebGLTexelFormat::R8 || + format == WebGLTexelFormat::R16F || + format == WebGLTexelFormat::R32F || + format == WebGLTexelFormat::RA8 || + format == WebGLTexelFormat::RA16F || + format == WebGLTexelFormat::RA32F || + format == WebGLTexelFormat::RG8 || + format == WebGLTexelFormat::RG16F || + format == WebGLTexelFormat::RG32F || + format == WebGLTexelFormat::RGB565 || + format == WebGLTexelFormat::RGB8 || + format == WebGLTexelFormat::RGB11F11F10F || + format == WebGLTexelFormat::RGB16F || + format == WebGLTexelFormat::RGB32F || + format == WebGLTexelFormat::RGBA4444 || + format == WebGLTexelFormat::RGBA5551 || + format == WebGLTexelFormat::RGBA8 || + format == WebGLTexelFormat::RGBA16F || + format == WebGLTexelFormat::RGBA32F || + format == WebGLTexelFormat::BGRX8 || + format == WebGLTexelFormat::BGRA8); +} + +/****** BEGIN CODE SHARED WITH WEBKIT ******/ + +// the pack/unpack functions here are originally from this file: +// http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp + +//---------------------------------------------------------------------- +// Pixel unpacking routines. + +template<WebGLTexelFormat Format, typename SrcType, typename DstType> +MOZ_ALWAYS_INLINE void +unpack(const SrcType* __restrict src, + DstType* __restrict dst) +{ + MOZ_ASSERT(false, "Unimplemented texture format conversion"); +} + +//////////////////////////////////////////////////////////////////////////////// +// 1-channel formats +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + dst[3] = src[0]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::A16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = kFloat16Value_Zero; + dst[1] = kFloat16Value_Zero; + dst[2] = kFloat16Value_Zero; + dst[3] = src[0]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::A32F, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + dst[3] = src[0]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = 0xFF; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::R16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = kFloat16Value_One; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::R32F, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////////////////// +// 2-channel formats +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = src[1]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RA16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = src[1]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RA32F, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + dst[3] = src[1]; +} + +//////////////////////////////////////////////////////////////////////////////// +// 3-channel formats +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst) +{ + uint16_t packedValue = src[0]; + uint8_t r = (packedValue >> 11) & 0x1F; + uint8_t g = (packedValue >> 5) & 0x3F; + uint8_t b = packedValue & 0x1F; + dst[0] = (r << 3) | (r & 0x7); + dst[1] = (g << 2) | (g & 0x3); + dst[2] = (b << 3) | (b & 0x7); + dst[3] = 0xFF; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 0xFF; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGB16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = kFloat16Value_One; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGB32F, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////////////////// +// 4-channel formats +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst) +{ + uint16_t packedValue = src[0]; + uint8_t r = (packedValue >> 12) & 0x0F; + uint8_t g = (packedValue >> 8) & 0x0F; + uint8_t b = (packedValue >> 4) & 0x0F; + uint8_t a = packedValue & 0x0F; + dst[0] = (r << 4) | r; + dst[1] = (g << 4) | g; + dst[2] = (b << 4) | b; + dst[3] = (a << 4) | a; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst) +{ + uint16_t packedValue = src[0]; + uint8_t r = (packedValue >> 11) & 0x1F; + uint8_t g = (packedValue >> 6) & 0x1F; + uint8_t b = (packedValue >> 1) & 0x1F; + dst[0] = (r << 3) | (r & 0x7); + dst[1] = (g << 3) | (g & 0x7); + dst[2] = (b << 3) | (b & 0x7); + dst[3] = (packedValue & 0x1) ? 0xFF : 0; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGBA16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::RGBA32F, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +//////////////////////////////////////////////////////////////////////////////// +// DOM element formats +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = 0xFF; +} + +template<> MOZ_ALWAYS_INLINE void +unpack<WebGLTexelFormat::BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[3]; +} + +//---------------------------------------------------------------------- +// Pixel packing routines. +// + +template<WebGLTexelFormat Format, + WebGLTexelPremultiplicationOp PremultiplicationOp, + typename SrcType, + typename DstType> +MOZ_ALWAYS_INLINE void +pack(const SrcType* __restrict src, + DstType* __restrict dst) +{ + MOZ_CRASH("GFX: Unimplemented texture format conversion"); +} + +//////////////////////////////////////////////////////////////////////////////// +// 1-channel formats +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + dst[0] = srcR; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + dst[0] = srcR; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = unpackFromFloat16(src[3]); + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3]; + dst[0] = src[0] * scaleFactor; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; +} + +//////////////////////////////////////////////////////////////////////////////// +// 2-channel formats +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + dst[0] = srcR; + dst[1] = src[3]; +} + +// FIXME: this routine is lossy and must be removed. +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + dst[0] = srcR; + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = unpackFromFloat16(src[3]); + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3]; + dst[0] = src[0] * scaleFactor; + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + dst[0] = srcR; + dst[1] = srcG; +} + +// FIXME: this routine is lossy and must be removed. +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + dst[0] = srcR; + dst[1] = srcG; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = unpackFromFloat16(src[3]); + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3]; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RG32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; +} + +//////////////////////////////////////////////////////////////////////////////// +// 3-channel formats +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + *dst = ( ((src[0] & 0xF8) << 8) + | ((src[1] & 0xFC) << 3) + | ((src[2] & 0xF8) >> 3)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + *dst = ( ((srcR & 0xF8) << 8) + | ((srcG & 0xFC) << 3) + | ((srcB & 0xF8) >> 3)); +} + +// FIXME: this routine is lossy and must be removed. +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + *dst = ( ((srcR & 0xF8) << 8) + | ((srcG & 0xFC) << 3) + | ((srcB & 0xF8) >> 3)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + dst[0] = srcR; + dst[1] = srcG; + dst[2] = srcB; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + dst[0] = srcR; + dst[1] = srcG; + dst[2] = srcB; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::None, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst) +{ + dst[0] = ((packToFloat11(src[0]) << 0) | + (packToFloat11(src[1]) << 11) | + (packToFloat10(src[2]) << 22)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::Premultiply, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst) +{ + float scaleFactor = src[3]; + dst[0] = ((packToFloat11(src[0] * scaleFactor) << 0) | + (packToFloat11(src[1] * scaleFactor) << 11) | + (packToFloat10(src[2] * scaleFactor) << 22)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::Unpremultiply, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = ((packToFloat11(src[0] * scaleFactor) << 0) | + (packToFloat11(src[1] * scaleFactor) << 11) | + (packToFloat10(src[2] * scaleFactor) << 22)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = unpackFromFloat16(src[3]); + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); + dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); + dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3]; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; +} + +//////////////////////////////////////////////////////////////////////////////// +// 4-channel formats +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + *dst = ( ((src[0] & 0xF0) << 8) + | ((src[1] & 0xF0) << 4) + | (src[2] & 0xF0) + | (src[3] >> 4) ); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + *dst = ( ((srcR & 0xF0) << 8) + | ((srcG & 0xF0) << 4) + | (srcB & 0xF0) + | (src[3] >> 4)); +} + +// FIXME: this routine is lossy and must be removed. +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + *dst = ( ((srcR & 0xF0) << 8) + | ((srcG & 0xF0) << 4) + | (srcB & 0xF0) + | (src[3] >> 4)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + *dst = ( ((src[0] & 0xF8) << 8) + | ((src[1] & 0xF8) << 3) + | ((src[2] & 0xF8) >> 2) + | (src[3] >> 7)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + *dst = ( ((srcR & 0xF8) << 8) + | ((srcG & 0xF8) << 3) + | ((srcB & 0xF8) >> 2) + | (src[3] >> 7)); +} + +// FIXME: this routine is lossy and must be removed. +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + *dst = ( ((srcR & 0xF8) << 8) + | ((srcG & 0xF8) << 3) + | ((srcB & 0xF8) >> 2) + | (src[3] >> 7)); +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] / 255.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + dst[0] = srcR; + dst[1] = srcG; + dst[2] = srcB; + dst[3] = src[3]; +} + +// FIXME: this routine is lossy and must be removed. +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; + uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor); + uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor); + uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor); + dst[0] = srcR; + dst[1] = srcG; + dst[2] = srcB; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float scaleFactor = unpackFromFloat16(src[3]); + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); + dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); + dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3]; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; + dst[3] = src[3]; +} + +/****** END CODE SHARED WITH WEBKIT ******/ + +template<typename SrcType, typename DstType> MOZ_ALWAYS_INLINE void +convertType(const SrcType* __restrict src, DstType* __restrict dst) +{ + MOZ_ASSERT(false, "Unimplemented texture format conversion"); +} + +template<> MOZ_ALWAYS_INLINE void +convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +convertType<uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +convertType<float, float>(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +template<> MOZ_ALWAYS_INLINE void +convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst) +{ + const float scaleFactor = 1.f / 255.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; + dst[3] = src[3] * scaleFactor; +} + +template<> MOZ_ALWAYS_INLINE void +convertType<uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) +{ + const float scaleFactor = 1.f / 255.0f; + dst[0] = packToFloat16(src[0] * scaleFactor); + dst[1] = packToFloat16(src[1] * scaleFactor); + dst[2] = packToFloat16(src[2] * scaleFactor); + dst[3] = packToFloat16(src[3] * scaleFactor); +} + +} // end namespace WebGLTexelConversions + +} // end namespace mozilla + +#endif // WEBGLTEXELCONVERSIONS_H_ |