michael@0: /* michael@0: * Copyright (C) 2010 Apple Inc. All rights reserved. michael@0: * Copyright (C) 2010 Google Inc. All rights reserved. michael@0: * Copyright (C) 2010 Mozilla Corporation. All rights reserved. michael@0: * michael@0: * Redistribution and use in source and binary forms, with or without michael@0: * modification, are permitted provided that the following conditions michael@0: * are met: michael@0: * 1. Redistributions of source code must retain the above copyright michael@0: * notice, this list of conditions and the following disclaimer. michael@0: * 2. Redistributions in binary form must reproduce the above copyright michael@0: * notice, this list of conditions and the following disclaimer in the michael@0: * documentation and/or other materials provided with the distribution. michael@0: * michael@0: * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY michael@0: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE michael@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR michael@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR michael@0: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, michael@0: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, michael@0: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR michael@0: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY michael@0: * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: michael@0: #ifndef WEBGLTEXELCONVERSIONS_H_ michael@0: #define WEBGLTEXELCONVERSIONS_H_ michael@0: michael@0: #ifdef __SUNPRO_CC michael@0: #define __restrict michael@0: #endif michael@0: michael@0: #include "WebGLTypes.h" michael@0: #include michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: // single precision float michael@0: // seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm michael@0: michael@0: // half precision float michael@0: // seeeeemmmmmmmmmm michael@0: michael@0: // IEEE 16bits floating point: michael@0: const uint16_t kFloat16Value_Zero = 0x0000; // = 0000000000000000b michael@0: const uint16_t kFloat16Value_One = 0x3C00; // = 0011110000000000b michael@0: const uint16_t kFloat16Value_Infinity = 0x7C00; // = 0111110000000000b michael@0: const uint16_t kFloat16Value_NaN = 0x7FFF; // = 011111yyyyyyyyyyb (nonzero y) michael@0: michael@0: MOZ_ALWAYS_INLINE uint16_t michael@0: packToFloat16(float v) michael@0: { michael@0: union { michael@0: float f32Value; michael@0: uint32_t f32Bits; michael@0: }; michael@0: michael@0: f32Value = v; michael@0: michael@0: // pull the sign from v into f16bits michael@0: uint16_t f16Bits = uint16_t(f32Bits >> 16) & 0x8000; michael@0: michael@0: // handle +/- 0 michael@0: if ((f32Bits & 0x7FFFFFFF) == 0x00000000) { michael@0: return f16Bits; michael@0: } michael@0: michael@0: // handle NaN michael@0: if (f32Value != f32Value) { michael@0: return f16Bits | kFloat16Value_NaN; michael@0: } michael@0: michael@0: int32_t exp = int32_t(f32Bits >> 23) - 127; michael@0: michael@0: // too small, we clamp it to -0 or +0 michael@0: if (exp < -14) { michael@0: return f16Bits; michael@0: } michael@0: michael@0: // too big, we clamp it to -inf/+inf michael@0: if (exp > 15) { michael@0: return f16Bits | kFloat16Value_Infinity; michael@0: } michael@0: michael@0: f16Bits |= uint16_t(exp + 15) << 10; michael@0: f16Bits |= uint16_t(f32Bits >> 13) & 0x03FF; michael@0: michael@0: return f16Bits; michael@0: } michael@0: michael@0: MOZ_ALWAYS_INLINE float michael@0: unpackFromFloat16(uint16_t v) michael@0: { michael@0: union michael@0: { michael@0: float f32Value; michael@0: uint32_t f32Bits; michael@0: }; michael@0: michael@0: // grab sign bit michael@0: f32Bits = uint32_t(v & 0x8000) << 16; michael@0: michael@0: if ((v & 0x7FFF) == 0x0000) { michael@0: // +0 or -0 michael@0: return f32Value; michael@0: } michael@0: michael@0: uint16_t exp = (v >> 10) & 0x001F; michael@0: if (exp == 0x001F) { michael@0: if (v & 0x03FF) { michael@0: // this is a NaN michael@0: f32Bits |= 0x7FFFFFFF; michael@0: } else { michael@0: // this is -inf or +inf michael@0: f32Bits |= 0x7F800000; michael@0: } michael@0: return f32Value; michael@0: } michael@0: michael@0: f32Bits |= uint32_t(exp + (-15 + 127)) << 10; michael@0: f32Bits |= uint32_t(v & 0x03FF) << 13; michael@0: michael@0: return f32Value; michael@0: } michael@0: michael@0: MOZ_BEGIN_ENUM_CLASS(WebGLTexelPremultiplicationOp, int) michael@0: None, michael@0: Premultiply, michael@0: Unpremultiply michael@0: MOZ_END_ENUM_CLASS(WebGLTexelPremultiplicationOp) michael@0: michael@0: namespace WebGLTexelConversions { michael@0: michael@0: template michael@0: struct IsFloatFormat michael@0: { michael@0: static const bool Value = michael@0: Format == WebGLTexelFormat::RGBA32F || michael@0: Format == WebGLTexelFormat::RGB32F || michael@0: Format == WebGLTexelFormat::RA32F || michael@0: Format == WebGLTexelFormat::R32F || michael@0: Format == WebGLTexelFormat::A32F; michael@0: }; michael@0: michael@0: template michael@0: struct IsHalfFloatFormat michael@0: { michael@0: static const bool Value = michael@0: Format == WebGLTexelFormat::RGBA16F || michael@0: Format == WebGLTexelFormat::RGB16F || michael@0: Format == WebGLTexelFormat::RA16F || michael@0: Format == WebGLTexelFormat::R16F || michael@0: Format == WebGLTexelFormat::A16F; michael@0: }; michael@0: michael@0: template michael@0: struct Is16bppFormat michael@0: { michael@0: static const bool Value = michael@0: Format == WebGLTexelFormat::RGBA4444 || michael@0: Format == WebGLTexelFormat::RGBA5551 || michael@0: Format == WebGLTexelFormat::RGB565; michael@0: }; michael@0: michael@0: template::Value, michael@0: bool Is16bpp = Is16bppFormat::Value, michael@0: bool IsHalfFloat = IsHalfFloatFormat::Value> michael@0: struct DataTypeForFormat michael@0: { michael@0: typedef uint8_t Type; michael@0: }; michael@0: michael@0: template michael@0: struct DataTypeForFormat michael@0: { michael@0: typedef float Type; michael@0: }; michael@0: michael@0: template michael@0: struct DataTypeForFormat michael@0: { michael@0: typedef uint16_t Type; michael@0: }; michael@0: michael@0: template michael@0: struct DataTypeForFormat michael@0: { michael@0: typedef uint16_t Type; michael@0: }; michael@0: michael@0: template michael@0: struct IntermediateFormat michael@0: { michael@0: static const MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Value michael@0: = IsFloatFormat::Value michael@0: ? WebGLTexelFormat::RGBA32F michael@0: : IsHalfFloatFormat::Value ? WebGLTexelFormat::RGBA16F michael@0: : WebGLTexelFormat::RGBA8; michael@0: }; michael@0: michael@0: inline GLenum michael@0: GLFormatForTexelFormat(WebGLTexelFormat format) { michael@0: switch (format) { michael@0: case WebGLTexelFormat::R8: return LOCAL_GL_LUMINANCE; michael@0: case WebGLTexelFormat::A8: return LOCAL_GL_ALPHA; michael@0: case WebGLTexelFormat::RA8: return LOCAL_GL_LUMINANCE_ALPHA; michael@0: case WebGLTexelFormat::RGBA5551: return LOCAL_GL_RGBA; michael@0: case WebGLTexelFormat::RGBA4444: return LOCAL_GL_RGBA; michael@0: case WebGLTexelFormat::RGB565: return LOCAL_GL_RGB; michael@0: case WebGLTexelFormat::D16: return LOCAL_GL_DEPTH_COMPONENT; michael@0: case WebGLTexelFormat::RGB8: return LOCAL_GL_RGB; michael@0: case WebGLTexelFormat::RGBA8: return LOCAL_GL_RGBA; michael@0: case WebGLTexelFormat::BGRA8: return LOCAL_GL_BGRA; michael@0: case WebGLTexelFormat::BGRX8: return LOCAL_GL_BGR; michael@0: case WebGLTexelFormat::R32F: return LOCAL_GL_LUMINANCE; michael@0: case WebGLTexelFormat::A32F: return LOCAL_GL_ALPHA; michael@0: case WebGLTexelFormat::D32: return LOCAL_GL_DEPTH_COMPONENT; michael@0: case WebGLTexelFormat::D24S8: return LOCAL_GL_DEPTH_STENCIL; michael@0: case WebGLTexelFormat::RA32F: return LOCAL_GL_LUMINANCE_ALPHA; michael@0: case WebGLTexelFormat::RGB32F: return LOCAL_GL_RGB; michael@0: case WebGLTexelFormat::RGBA32F: return LOCAL_GL_RGBA; michael@0: case WebGLTexelFormat::R16F: return LOCAL_GL_LUMINANCE; michael@0: case WebGLTexelFormat::A16F: return LOCAL_GL_ALPHA; michael@0: case WebGLTexelFormat::RA16F: return LOCAL_GL_LUMINANCE_ALPHA; michael@0: case WebGLTexelFormat::RGB16F: return LOCAL_GL_RGB; michael@0: case WebGLTexelFormat::RGBA16F: return LOCAL_GL_RGBA; michael@0: default: michael@0: MOZ_CRASH("Unknown texel format. Coding mistake?"); michael@0: return LOCAL_GL_INVALID_ENUM; michael@0: } michael@0: } michael@0: michael@0: inline size_t TexelBytesForFormat(WebGLTexelFormat format) { michael@0: switch (format) { michael@0: case WebGLTexelFormat::R8: michael@0: case WebGLTexelFormat::A8: michael@0: return 1; michael@0: case WebGLTexelFormat::RA8: michael@0: case WebGLTexelFormat::RGBA5551: michael@0: case WebGLTexelFormat::RGBA4444: michael@0: case WebGLTexelFormat::RGB565: michael@0: case WebGLTexelFormat::R16F: michael@0: case WebGLTexelFormat::A16F: michael@0: case WebGLTexelFormat::D16: michael@0: return 2; michael@0: case WebGLTexelFormat::RGB8: michael@0: return 3; michael@0: case WebGLTexelFormat::RGBA8: michael@0: case WebGLTexelFormat::BGRA8: michael@0: case WebGLTexelFormat::BGRX8: michael@0: case WebGLTexelFormat::R32F: michael@0: case WebGLTexelFormat::A32F: michael@0: case WebGLTexelFormat::D32: michael@0: case WebGLTexelFormat::D24S8: michael@0: case WebGLTexelFormat::RA16F: michael@0: return 4; michael@0: case WebGLTexelFormat::RGB16F: michael@0: return 6; michael@0: case WebGLTexelFormat::RGBA16F: michael@0: case WebGLTexelFormat::RA32F: michael@0: return 8; michael@0: case WebGLTexelFormat::RGB32F: michael@0: return 12; michael@0: case WebGLTexelFormat::RGBA32F: michael@0: return 16; michael@0: default: michael@0: MOZ_ASSERT(false, "Unknown texel format. Coding mistake?"); michael@0: return 0; michael@0: } michael@0: } michael@0: michael@0: MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) { michael@0: return format == WebGLTexelFormat::A8 || michael@0: format == WebGLTexelFormat::A16F || michael@0: format == WebGLTexelFormat::A32F || michael@0: format == WebGLTexelFormat::RA8 || michael@0: format == WebGLTexelFormat::RA16F || michael@0: format == WebGLTexelFormat::RA32F || michael@0: format == WebGLTexelFormat::RGBA8 || michael@0: format == WebGLTexelFormat::BGRA8 || michael@0: format == WebGLTexelFormat::RGBA16F || michael@0: format == WebGLTexelFormat::RGBA32F || michael@0: format == WebGLTexelFormat::RGBA4444 || michael@0: format == WebGLTexelFormat::RGBA5551; michael@0: } michael@0: michael@0: MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) { michael@0: return format == WebGLTexelFormat::R8 || michael@0: format == WebGLTexelFormat::R16F || michael@0: format == WebGLTexelFormat::R32F || michael@0: format == WebGLTexelFormat::RA8 || michael@0: format == WebGLTexelFormat::RA16F || michael@0: format == WebGLTexelFormat::RA32F || michael@0: format == WebGLTexelFormat::RGB8 || michael@0: format == WebGLTexelFormat::BGRX8 || michael@0: format == WebGLTexelFormat::RGB565 || michael@0: format == WebGLTexelFormat::RGB16F || michael@0: format == WebGLTexelFormat::RGB32F || michael@0: format == WebGLTexelFormat::RGBA8 || michael@0: format == WebGLTexelFormat::BGRA8 || michael@0: format == WebGLTexelFormat::RGBA16F || michael@0: format == WebGLTexelFormat::RGBA32F || michael@0: format == WebGLTexelFormat::RGBA4444 || michael@0: format == WebGLTexelFormat::RGBA5551; michael@0: } michael@0: michael@0: michael@0: /****** BEGIN CODE SHARED WITH WEBKIT ******/ michael@0: michael@0: // the pack/unpack functions here are originally from this file: michael@0: // http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Pixel unpacking routines. michael@0: michael@0: template michael@0: MOZ_ALWAYS_INLINE void michael@0: unpack(const SrcType* __restrict src, michael@0: DstType* __restrict dst) michael@0: { michael@0: MOZ_ASSERT(false, "Unimplemented texture format conversion"); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = 0xFF; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[2]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[0]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[2]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[0]; michael@0: dst[3] = 0xFF; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: uint16_t packedValue = src[0]; michael@0: uint8_t r = (packedValue >> 11) & 0x1F; michael@0: uint8_t g = (packedValue >> 6) & 0x1F; michael@0: uint8_t b = (packedValue >> 1) & 0x1F; michael@0: dst[0] = (r << 3) | (r & 0x7); michael@0: dst[1] = (g << 3) | (g & 0x7); michael@0: dst[2] = (b << 3) | (b & 0x7); michael@0: dst[3] = (packedValue & 0x1) ? 0xFF : 0; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: uint16_t packedValue = src[0]; michael@0: uint8_t r = (packedValue >> 12) & 0x0F; michael@0: uint8_t g = (packedValue >> 8) & 0x0F; michael@0: uint8_t b = (packedValue >> 4) & 0x0F; michael@0: uint8_t a = packedValue & 0x0F; michael@0: dst[0] = (r << 4) | r; michael@0: dst[1] = (g << 4) | g; michael@0: dst[2] = (b << 4) | b; michael@0: dst[3] = (a << 4) | a; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: uint16_t packedValue = src[0]; michael@0: uint8_t r = (packedValue >> 11) & 0x1F; michael@0: uint8_t g = (packedValue >> 5) & 0x3F; michael@0: uint8_t b = packedValue & 0x1F; michael@0: dst[0] = (r << 3) | (r & 0x7); michael@0: dst[1] = (g << 2) | (g & 0x3); michael@0: dst[2] = (b << 3) | (b & 0x7); michael@0: dst[3] = 0xFF; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[0]; michael@0: dst[2] = src[0]; michael@0: dst[3] = 0xFF; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[0]; michael@0: dst[2] = src[0]; michael@0: dst[3] = src[1]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = 0; michael@0: dst[1] = 0; michael@0: dst[2] = 0; michael@0: dst[3] = src[0]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = 1.0f; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[0]; michael@0: dst[2] = src[0]; michael@0: dst[3] = 1.0f; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[0]; michael@0: dst[2] = src[0]; michael@0: dst[3] = src[1]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = 0; michael@0: dst[1] = 0; michael@0: dst[2] = 0; michael@0: dst[3] = src[0]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = kFloat16Value_One; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[0]; michael@0: dst[2] = src[0]; michael@0: dst[3] = kFloat16Value_One; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[0]; michael@0: dst[2] = src[0]; michael@0: dst[3] = src[1]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: unpack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = kFloat16Value_Zero; michael@0: dst[1] = kFloat16Value_Zero; michael@0: dst[2] = kFloat16Value_Zero; michael@0: dst[3] = src[0]; michael@0: } michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Pixel packing routines. michael@0: // michael@0: michael@0: template michael@0: MOZ_ALWAYS_INLINE void michael@0: pack(const SrcType* __restrict src, michael@0: DstType* __restrict dst) michael@0: { michael@0: MOZ_ASSERT(false, "Unimplemented texture format conversion"); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: dst[0] = srcR; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: dst[0] = srcR; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: dst[0] = srcR; michael@0: dst[1] = src[3]; michael@0: } michael@0: michael@0: // FIXME: this routine is lossy and must be removed. michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: dst[0] = srcR; michael@0: dst[1] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: dst[0] = srcR; michael@0: dst[1] = srcG; michael@0: dst[2] = srcB; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: dst[0] = srcR; michael@0: dst[1] = srcG; michael@0: dst[2] = srcB; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: dst[0] = srcR; michael@0: dst[1] = srcG; michael@0: dst[2] = srcB; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: // FIXME: this routine is lossy and must be removed. michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: dst[0] = srcR; michael@0: dst[1] = srcG; michael@0: dst[2] = srcB; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: *dst = ( ((src[0] & 0xF0) << 8) michael@0: | ((src[1] & 0xF0) << 4) michael@0: | (src[2] & 0xF0) michael@0: | (src[3] >> 4) ); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: *dst = ( ((srcR & 0xF0) << 8) michael@0: | ((srcG & 0xF0) << 4) michael@0: | (srcB & 0xF0) michael@0: | (src[3] >> 4)); michael@0: } michael@0: michael@0: // FIXME: this routine is lossy and must be removed. michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: *dst = ( ((srcR & 0xF0) << 8) michael@0: | ((srcG & 0xF0) << 4) michael@0: | (srcB & 0xF0) michael@0: | (src[3] >> 4)); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: *dst = ( ((src[0] & 0xF8) << 8) michael@0: | ((src[1] & 0xF8) << 3) michael@0: | ((src[2] & 0xF8) >> 2) michael@0: | (src[3] >> 7)); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: *dst = ( ((srcR & 0xF8) << 8) michael@0: | ((srcG & 0xF8) << 3) michael@0: | ((srcB & 0xF8) >> 2) michael@0: | (src[3] >> 7)); michael@0: } michael@0: michael@0: // FIXME: this routine is lossy and must be removed. michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: *dst = ( ((srcR & 0xF8) << 8) michael@0: | ((srcG & 0xF8) << 3) michael@0: | ((srcB & 0xF8) >> 2) michael@0: | (src[3] >> 7)); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: *dst = ( ((src[0] & 0xF8) << 8) michael@0: | ((src[1] & 0xFC) << 3) michael@0: | ((src[2] & 0xF8) >> 3)); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] / 255.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: *dst = ( ((srcR & 0xF8) << 8) michael@0: | ((srcG & 0xFC) << 3) michael@0: | ((srcB & 0xF8) >> 3)); michael@0: } michael@0: michael@0: // FIXME: this routine is lossy and must be removed. michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f; michael@0: uint8_t srcR = static_cast(src[0] * scaleFactor); michael@0: uint8_t srcG = static_cast(src[1] * scaleFactor); michael@0: uint8_t srcB = static_cast(src[2] * scaleFactor); michael@0: *dst = ( ((srcR & 0xF8) << 8) michael@0: | ((srcG & 0xFC) << 3) michael@0: | ((srcB & 0xF8) >> 3)); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3]; michael@0: dst[0] = src[0] * scaleFactor; michael@0: dst[1] = src[1] * scaleFactor; michael@0: dst[2] = src[2] * scaleFactor; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3]; michael@0: dst[0] = src[0] * scaleFactor; michael@0: dst[1] = src[1] * scaleFactor; michael@0: dst[2] = src[2] * scaleFactor; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3]; michael@0: dst[0] = src[0] * scaleFactor; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: float scaleFactor = src[3]; michael@0: dst[0] = src[0] * scaleFactor; michael@0: dst[1] = scaleFactor; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = unpackFromFloat16(src[3]); michael@0: dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); michael@0: dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); michael@0: dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = unpackFromFloat16(src[3]); michael@0: dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); michael@0: dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); michael@0: dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = unpackFromFloat16(src[3]); michael@0: dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: pack(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: float scaleFactor = unpackFromFloat16(src[3]); michael@0: dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); michael@0: dst[1] = scaleFactor; michael@0: } michael@0: michael@0: /****** END CODE SHARED WITH WEBKIT ******/ michael@0: michael@0: template MOZ_ALWAYS_INLINE void michael@0: convertType(const SrcType* __restrict src, DstType* __restrict dst) michael@0: { michael@0: MOZ_ASSERT(false, "Unimplemented texture format conversion"); michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: convertType(const uint8_t* __restrict src, uint8_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: convertType(const uint16_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: convertType(const float* __restrict src, float* __restrict dst) michael@0: { michael@0: dst[0] = src[0]; michael@0: dst[1] = src[1]; michael@0: dst[2] = src[2]; michael@0: dst[3] = src[3]; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: convertType(const uint8_t* __restrict src, float* __restrict dst) michael@0: { michael@0: const float scaleFactor = 1.f / 255.0f; michael@0: dst[0] = src[0] * scaleFactor; michael@0: dst[1] = src[1] * scaleFactor; michael@0: dst[2] = src[2] * scaleFactor; michael@0: dst[3] = src[3] * scaleFactor; michael@0: } michael@0: michael@0: template<> MOZ_ALWAYS_INLINE void michael@0: convertType(const uint8_t* __restrict src, uint16_t* __restrict dst) michael@0: { michael@0: const float scaleFactor = 1.f / 255.0f; michael@0: dst[0] = packToFloat16(src[0] * scaleFactor); michael@0: dst[1] = packToFloat16(src[1] * scaleFactor); michael@0: dst[2] = packToFloat16(src[2] * scaleFactor); michael@0: dst[3] = packToFloat16(src[3] * scaleFactor); michael@0: } michael@0: michael@0: } // end namespace WebGLTexelConversions michael@0: michael@0: } // end namespace mozilla michael@0: michael@0: #endif // WEBGLTEXELCONVERSIONS_H_