Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/canvas/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 46 kB image not shown  

Quelle  WebGLTexelConversions.h   Sprache: C

 
/*
 * 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 {

namespace gl {
enum class OriginPos : uint8_t;
}

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,
                  dom::PredefinedColorSpace srcColorSpace,
                  dom::PredefinedColorSpace dstColorSpace,
                  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 {
  using Type = uint8_t;
};

template <WebGLTexelFormat Format>
struct DataTypeForFormat<Format, truefalsefalse> {
  using Type = float;
};

template <WebGLTexelFormat Format>
struct DataTypeForFormat<Format, falsetruefalse> {
  using Type = uint16_t;
};

template <WebGLTexelFormat Format>
struct DataTypeForFormat<Format, falsefalsetrue> {
  using Type = uint16_t;
};

template <>
struct DataTypeForFormat<WebGLTexelFormat::RGB11F11F10F, truefalsefalse> {
  using Type = uint32_t;
};

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, floatfloat>(
    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, floatfloat>(
    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, floatfloat>(
    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] = uint8_t(r << 3) | (r & 0x7);
  dst[1] = uint8_t(g << 2) | (g & 0x3);
  dst[2] = uint8_t(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, floatfloat>(
    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] = uint8_t(r << 4) | r;
  dst[1] = uint8_t(g << 4) | g;
  dst[2] = uint8_t(b << 4) | b;
  dst[3] = uint8_t(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] = uint8_t(r << 3) | (r & 0x7);
  dst[1] = uint8_t(g << 3) | (g & 0x7);
  dst[2] = uint8_t(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, floatfloat>(
    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, floatfloat>(
    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,
     floatfloat>(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, floatfloat>(
    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,
     floatfloat>(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, floatfloat>(
    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,
     floatfloat>(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, floatfloat>(
    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,
     floatfloat>(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 = uint16_t(((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 = uint16_t(((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 = uint16_t(((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, floatfloat>(
    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,
     floatfloat>(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,
     floatfloat>(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 = uint16_t(((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 = uint16_t(((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 = uint16_t(((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 = uint16_t(((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 = uint16_t(((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 = uint16_t(((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::BGRA8, WebGLTexelPremultiplicationOp::None, 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];
}

template <>
MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::BGRA8, 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] = srcB;
  dst[1] = srcG;
  dst[2] = srcR;
  dst[3] = src[3];
}

// FIXME: this routine is lossy and must be removed.
template <>
MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::BGRA8, 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] = srcB;
  dst[1] = srcG;
  dst[2] = srcR;
  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, floatfloat>(
    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,
     floatfloat>(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,
     floatfloat>(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<floatfloat>(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<float, uint8_t>(const float* __restrict src,
                                                   uint8_t* __restrict dst) {
  const float scaleFactor = 255.0f;
  dst[0] = uint8_t(src[0] * scaleFactor);
  dst[1] = uint8_t(src[1] * scaleFactor);
  dst[2] = uint8_t(src[2] * scaleFactor);
  dst[3] = uint8_t(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_

Messung V0.5
C=94 H=99 G=96

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.