1814 lines
78 KiB
C++
1814 lines
78 KiB
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 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 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.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#if ENABLE(WEBGL)
|
|
|
|
#include "FormatConverter.h"
|
|
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
#include "GraphicsContextGLNEON.h"
|
|
#endif
|
|
|
|
#if USE(ACCELERATE)
|
|
#include <Accelerate/Accelerate.h>
|
|
#endif
|
|
|
|
namespace WebCore {
|
|
|
|
namespace {
|
|
|
|
const float MaxInt8Value = INT8_MAX;
|
|
const float MaxUInt8Value = UINT8_MAX;
|
|
const float MaxInt16Value = INT16_MAX;
|
|
const float MaxUInt16Value = UINT16_MAX;
|
|
const double MaxInt32Value = INT32_MAX;
|
|
const double MaxUInt32Value = UINT32_MAX;
|
|
|
|
int8_t clampMin(int8_t value)
|
|
{
|
|
const int8_t MinInt8Value = INT8_MIN + 1;
|
|
return value < MinInt8Value ? MinInt8Value : value;
|
|
}
|
|
|
|
int16_t clampMin(int16_t value)
|
|
{
|
|
const int16_t MinInt16Value = INT16_MIN + 1;
|
|
return value < MinInt16Value ? MinInt16Value : value;
|
|
}
|
|
|
|
int32_t clampMin(int32_t value)
|
|
{
|
|
const int32_t MinInt32Value = INT32_MIN + 1;
|
|
return value < MinInt32Value ? MinInt32Value : value;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
// Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf,
|
|
// "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010).
|
|
// Specially, the basetable[512] and shifttable[512] are generated as follows:
|
|
/*
|
|
unsigned short basetable[512];
|
|
unsigned char shifttable[512];
|
|
|
|
void generatetables(){
|
|
unsigned int i;
|
|
int e;
|
|
for (i = 0; i < 256; ++i){
|
|
e = i - 127;
|
|
if (e < -24){ // Very small numbers map to zero
|
|
basetable[i | 0x000] = 0x0000;
|
|
basetable[i | 0x100] = 0x8000;
|
|
shifttable[i | 0x000] = 24;
|
|
shifttable[i | 0x100] = 24;
|
|
}
|
|
else if (e < -14) { // Small numbers map to denorms
|
|
basetable[i | 0x000] = (0x0400>>(-e-14));
|
|
basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000;
|
|
shifttable[i | 0x000] = -e-1;
|
|
shifttable[i | 0x100] = -e-1;
|
|
}
|
|
else if (e <= 15){ // Normal numbers just lose precision
|
|
basetable[i | 0x000] = ((e+15)<<10);
|
|
basetable[i| 0x100] = ((e+15)<<10) | 0x8000;
|
|
shifttable[i|0x000] = 13;
|
|
shifttable[i|0x100] = 13;
|
|
}
|
|
else if (e<128){ // Large numbers map to Infinity
|
|
basetable[i|0x000] = 0x7C00;
|
|
basetable[i|0x100] = 0xFC00;
|
|
shifttable[i|0x000] = 24;
|
|
shifttable[i|0x100] = 24;
|
|
}
|
|
else { // Infinity and NaN's stay Infinity and NaN's
|
|
basetable[i|0x000] = 0x7C00;
|
|
basetable[i|0x100] = 0xFC00;
|
|
shifttable[i|0x000] = 13;
|
|
shifttable[i|0x100] = 13;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
static const unsigned short baseTable[512] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256,
|
|
512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360,
|
|
16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
|
|
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776, 32784, 32800, 32832, 32896, 33024,
|
|
33280, 33792, 34816, 35840, 36864, 37888, 38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128,
|
|
49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416, 61440, 62464, 63488, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512,
|
|
64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512
|
|
};
|
|
|
|
static const unsigned char shiftTable[512] = {
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15,
|
|
14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
|
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15,
|
|
14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
|
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13
|
|
};
|
|
|
|
inline unsigned short convertFloatToHalfFloat(float f)
|
|
{
|
|
unsigned temp = *(reinterpret_cast<unsigned *>(&f));
|
|
unsigned signexp = (temp >> 23) & 0x1ff;
|
|
return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]);
|
|
}
|
|
|
|
/* BEGIN CODE SHARED WITH MOZILLA FIREFOX */
|
|
|
|
// The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup.
|
|
// Explicit template specializations correspond to the cases that would occur.
|
|
// Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h
|
|
|
|
//----------------------------------------------------------------------
|
|
// Pixel unpacking routines.
|
|
template<GraphicsContextGL::DataFormat format, typename SourceType, typename DstType>
|
|
ALWAYS_INLINE void unpack(const SourceType*, DstType*, unsigned)
|
|
{
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::ARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[1];
|
|
destination[1] = source[2];
|
|
destination[2] = source[3];
|
|
destination[3] = source[0];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::ABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[3];
|
|
destination[1] = source[2];
|
|
destination[2] = source[1];
|
|
destination[3] = source[0];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::BGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
|
|
uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
uint32_t bgra = source32[i];
|
|
#if CPU(BIG_ENDIAN)
|
|
uint32_t brMask = 0xff00ff00;
|
|
uint32_t gaMask = 0x00ff00ff;
|
|
#else
|
|
uint32_t brMask = 0x00ff00ff;
|
|
uint32_t gaMask = 0xff00ff00;
|
|
#endif
|
|
uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask);
|
|
destination32[i] = rgba;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow);
|
|
#endif
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
uint16_t packedValue = source[0];
|
|
uint8_t r = packedValue >> 11;
|
|
uint8_t g = (packedValue >> 6) & 0x1F;
|
|
uint8_t b = (packedValue >> 1) & 0x1F;
|
|
destination[0] = (r << 3) | (r & 0x7);
|
|
destination[1] = (g << 3) | (g & 0x7);
|
|
destination[2] = (b << 3) | (b & 0x7);
|
|
destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow);
|
|
#endif
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
uint16_t packedValue = source[0];
|
|
uint8_t r = packedValue >> 12;
|
|
uint8_t g = (packedValue >> 8) & 0x0F;
|
|
uint8_t b = (packedValue >> 4) & 0x0F;
|
|
uint8_t a = packedValue & 0x0F;
|
|
destination[0] = r << 4 | r;
|
|
destination[1] = g << 4 | g;
|
|
destination[2] = b << 4 | b;
|
|
destination[3] = a << 4 | a;
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[0];
|
|
destination[2] = source[0];
|
|
destination[3] = source[1];
|
|
source += 2;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::AR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[1];
|
|
destination[1] = source[1];
|
|
destination[2] = source[1];
|
|
destination[3] = source[0];
|
|
source += 2;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
const float scaleFactor = 1.0f / 255.0f;
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
destination[2] = source[2] * scaleFactor;
|
|
destination[3] = source[3] * scaleFactor;
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::BGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
const float scaleFactor = 1.0f / 255.0f;
|
|
for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[2] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
destination[2] = source[0] * scaleFactor;
|
|
destination[3] = source[3] * scaleFactor;
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::ABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
const float scaleFactor = 1.0f / 255.0f;
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[3] * scaleFactor;
|
|
destination[1] = source[2] * scaleFactor;
|
|
destination[2] = source[1] * scaleFactor;
|
|
destination[3] = source[0] * scaleFactor;
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::ARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
const float scaleFactor = 1.0f / 255.0f;
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[1] * scaleFactor;
|
|
destination[1] = source[2] * scaleFactor;
|
|
destination[2] = source[3] * scaleFactor;
|
|
destination[3] = source[0] * scaleFactor;
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[0];
|
|
destination[2] = source[0];
|
|
destination[3] = source[1];
|
|
source += 2;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGBA2_10_10_10, uint32_t, float>(const uint32_t* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
const float rgbScaleFactor = 1.0f / 1023.0f;
|
|
const float alphaScaleFactor = 1.0f / 3.0f;
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
uint32_t packedValue = source[0];
|
|
destination[0] = static_cast<float>(packedValue & 0x3FF) * rgbScaleFactor;
|
|
destination[1] = static_cast<float>((packedValue >> 10) & 0x3FF) * rgbScaleFactor;
|
|
destination[2] = static_cast<float>((packedValue >> 20) & 0x3FF) * rgbScaleFactor;
|
|
destination[3] = static_cast<float>(packedValue >> 30) * alphaScaleFactor;
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
// Unpacking routines needed by various WebKit ports, for example to
|
|
// handle the internal representations of grayscale PNGs.
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::R8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[0];
|
|
destination[2] = source[0];
|
|
destination[3] = 0xFF;
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::A8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = 0x0;
|
|
destination[1] = 0x0;
|
|
destination[2] = 0x0;
|
|
destination[3] = source[0];
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::R32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[0];
|
|
destination[2] = source[0];
|
|
destination[3] = 1;
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::A32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = 0;
|
|
destination[1] = 0;
|
|
destination[2] = 0;
|
|
destination[3] = source[0];
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[1];
|
|
destination[2] = source[2];
|
|
destination[3] = 0xFF;
|
|
source += 3;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::BGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[2];
|
|
destination[1] = source[1];
|
|
destination[2] = source[0];
|
|
destination[3] = 0xFF;
|
|
source += 3;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow);
|
|
#endif
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
uint16_t packedValue = source[0];
|
|
uint8_t r = packedValue >> 11;
|
|
uint8_t g = (packedValue >> 5) & 0x3F;
|
|
uint8_t b = packedValue & 0x1F;
|
|
destination[0] = (r << 3) | (r & 0x7);
|
|
destination[1] = (g << 2) | (g & 0x3);
|
|
destination[2] = (b << 3) | (b & 0x7);
|
|
destination[3] = 0xFF;
|
|
source += 1;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void unpack<GraphicsContextGL::DataFormat::RGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[1];
|
|
destination[2] = source[2];
|
|
destination[3] = 1;
|
|
source += 3;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Pixel packing routines.
|
|
//
|
|
|
|
template<GraphicsContextGL::DataFormat format, int alphaOp, typename SourceType, typename DstType>
|
|
ALWAYS_INLINE void pack(const SourceType*, DstType*, unsigned)
|
|
{
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::A8, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[3];
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R8, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R8, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R8, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA8, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[3];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA8, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
destination[1] = source[3];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA8, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
destination[1] = source[3];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB8, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[1];
|
|
destination[2] = source[2];
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB8, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
destination[1] = sourceG;
|
|
destination[2] = sourceB;
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB8, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
destination[1] = sourceG;
|
|
destination[2] = sourceB;
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA8, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
destination[1] = sourceG;
|
|
destination[2] = sourceB;
|
|
destination[3] = source[3];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA8, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
destination[0] = sourceR;
|
|
destination[1] = sourceG;
|
|
destination[2] = sourceB;
|
|
destination[3] = source[3];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA4444, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow);
|
|
#endif
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
*destination = (((source[0] & 0xF0) << 8)
|
|
| ((source[1] & 0xF0) << 4)
|
|
| (source[2] & 0xF0)
|
|
| (source[3] >> 4));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA4444, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
*destination = (((sourceR & 0xF0) << 8)
|
|
| ((sourceG & 0xF0) << 4)
|
|
| (sourceB & 0xF0)
|
|
| (source[3] >> 4));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA4444, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
*destination = (((sourceR & 0xF0) << 8)
|
|
| ((sourceG & 0xF0) << 4)
|
|
| (sourceB & 0xF0)
|
|
| (source[3] >> 4));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA5551, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow);
|
|
#endif
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
*destination = (((source[0] & 0xF8) << 8)
|
|
| ((source[1] & 0xF8) << 3)
|
|
| ((source[2] & 0xF8) >> 2)
|
|
| (source[3] >> 7));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA5551, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
*destination = (((sourceR & 0xF8) << 8)
|
|
| ((sourceG & 0xF8) << 3)
|
|
| ((sourceB & 0xF8) >> 2)
|
|
| (source[3] >> 7));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA5551, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
*destination = (((sourceR & 0xF8) << 8)
|
|
| ((sourceG & 0xF8) << 3)
|
|
| ((sourceB & 0xF8) >> 2)
|
|
| (source[3] >> 7));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB565, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
#if HAVE(ARM_NEON_INTRINSICS)
|
|
SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow);
|
|
#endif
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
*destination = (((source[0] & 0xF8) << 8)
|
|
| ((source[1] & 0xFC) << 3)
|
|
| ((source[2] & 0xF8) >> 3));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB565, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] / 255.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
*destination = (((sourceR & 0xF8) << 8)
|
|
| ((sourceG & 0xFC) << 3)
|
|
| ((sourceB & 0xF8) >> 3));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB565, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
|
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
*destination = (((sourceR & 0xF8) << 8)
|
|
| ((sourceG & 0xFC) << 3)
|
|
| ((sourceB & 0xF8) >> 3));
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB32F, GraphicsContextGL::AlphaOp::DoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[1];
|
|
destination[2] = source[2];
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB32F, GraphicsContextGL::AlphaOp::DoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
destination[2] = source[2] * scaleFactor;
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB32F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
destination[2] = source[2] * scaleFactor;
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA32F, GraphicsContextGL::AlphaOp::DoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
destination[2] = source[2] * scaleFactor;
|
|
destination[3] = source[3];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA32F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
destination[2] = source[2] * scaleFactor;
|
|
destination[3] = source[3];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::A32F, GraphicsContextGL::AlphaOp::DoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[3];
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R32F, GraphicsContextGL::AlphaOp::DoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R32F, GraphicsContextGL::AlphaOp::DoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = source[0] * scaleFactor;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R32F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = source[0] * scaleFactor;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA32F, GraphicsContextGL::AlphaOp::DoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[3];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA32F, GraphicsContextGL::AlphaOp::DoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[3];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA32F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[3];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA16F, GraphicsContextGL::AlphaOp::DoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = convertFloatToHalfFloat(source[0]);
|
|
destination[1] = convertFloatToHalfFloat(source[1]);
|
|
destination[2] = convertFloatToHalfFloat(source[2]);
|
|
destination[3] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA16F, GraphicsContextGL::AlphaOp::DoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
|
|
destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
|
|
destination[3] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGBA16F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
|
|
destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
|
|
destination[3] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB16F, GraphicsContextGL::AlphaOp::DoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = convertFloatToHalfFloat(source[0]);
|
|
destination[1] = convertFloatToHalfFloat(source[1]);
|
|
destination[2] = convertFloatToHalfFloat(source[2]);
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB16F, GraphicsContextGL::AlphaOp::DoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
|
|
destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RGB16F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
|
|
destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor);
|
|
source += 4;
|
|
destination += 3;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA16F, GraphicsContextGL::AlphaOp::DoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = convertFloatToHalfFloat(source[0]);
|
|
destination[1] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA16F, GraphicsContextGL::AlphaOp::DoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::RA16F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R16F, GraphicsContextGL::AlphaOp::DoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = convertFloatToHalfFloat(source[0]);
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R16F, GraphicsContextGL::AlphaOp::DoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::R16F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE void pack<GraphicsContextGL::DataFormat::A16F, GraphicsContextGL::AlphaOp::DoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
|
|
{
|
|
for (unsigned i = 0; i < pixelsPerRow; ++i) {
|
|
destination[0] = convertFloatToHalfFloat(source[3]);
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA8_S, GraphicsContextGL::AlphaOp::DoPremultiply, int8_t, int8_t>(const int8_t* source, int8_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
destination[3] = clampMin(source[3]);
|
|
float scaleFactor = static_cast<float>(destination[3]) / MaxInt8Value;
|
|
destination[0] = static_cast<int8_t>(static_cast<float>(clampMin(source[0])) * scaleFactor);
|
|
destination[1] = static_cast<int8_t>(static_cast<float>(clampMin(source[1])) * scaleFactor);
|
|
destination[2] = static_cast<int8_t>(static_cast<float>(clampMin(source[2])) * scaleFactor);
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA16, GraphicsContextGL::AlphaOp::DoPremultiply, uint16_t, uint16_t>(const uint16_t* source, uint16_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = static_cast<float>(source[3]) / MaxUInt16Value;
|
|
destination[0] = static_cast<uint16_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[1] = static_cast<uint16_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
destination[2] = static_cast<uint16_t>(static_cast<float>(source[2]) * scaleFactor);
|
|
destination[3] = source[3];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA16_S, GraphicsContextGL::AlphaOp::DoPremultiply, int16_t, int16_t>(const int16_t* source, int16_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
destination[3] = clampMin(source[3]);
|
|
float scaleFactor = static_cast<float>(destination[3]) / MaxInt16Value;
|
|
destination[0] = static_cast<int16_t>(static_cast<float>(clampMin(source[0])) * scaleFactor);
|
|
destination[1] = static_cast<int16_t>(static_cast<float>(clampMin(source[1])) * scaleFactor);
|
|
destination[2] = static_cast<int16_t>(static_cast<float>(clampMin(source[2])) * scaleFactor);
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA32, GraphicsContextGL::AlphaOp::DoPremultiply, uint32_t, uint32_t>(const uint32_t* source, uint32_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
double scaleFactor = static_cast<double>(source[3]) / MaxUInt32Value;
|
|
destination[0] = static_cast<uint32_t>(static_cast<double>(source[0]) * scaleFactor);
|
|
destination[1] = static_cast<uint32_t>(static_cast<double>(source[1]) * scaleFactor);
|
|
destination[2] = static_cast<uint32_t>(static_cast<double>(source[2]) * scaleFactor);
|
|
destination[3] = source[3];
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA32_S, GraphicsContextGL::AlphaOp::DoPremultiply, int32_t, int32_t>(const int32_t* source, int32_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
destination[3] = clampMin(source[3]);
|
|
double scaleFactor = static_cast<double>(destination[3]) / MaxInt32Value;
|
|
destination[0] = static_cast<int32_t>(static_cast<double>(clampMin(source[0])) * scaleFactor);
|
|
destination[1] = static_cast<int32_t>(static_cast<double>(clampMin(source[1])) * scaleFactor);
|
|
destination[2] = static_cast<int32_t>(static_cast<double>(clampMin(source[2])) * scaleFactor);
|
|
source += 4;
|
|
destination += 4;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA2_10_10_10, GraphicsContextGL::AlphaOp::DoNothing, float, uint32_t>(const float* source, uint32_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
uint32_t r = static_cast<uint32_t>(source[0] * 1023.0f);
|
|
uint32_t g = static_cast<uint32_t>(source[1] * 1023.0f);
|
|
uint32_t b = static_cast<uint32_t>(source[2] * 1023.0f);
|
|
uint32_t a = static_cast<uint32_t>(source[3] * 3.0f);
|
|
destination[0] = (a << 30) | (b << 20) | (g << 10) | r;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA2_10_10_10, GraphicsContextGL::AlphaOp::DoPremultiply, float, uint32_t>(const float* source, uint32_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
uint32_t r = static_cast<uint32_t>(source[0] * source[3] * 1023.0f);
|
|
uint32_t g = static_cast<uint32_t>(source[1] * source[3] * 1023.0f);
|
|
uint32_t b = static_cast<uint32_t>(source[2] * source[3] * 1023.0f);
|
|
uint32_t a = static_cast<uint32_t>(source[3] * 3.0f);
|
|
destination[0] = (a << 30) | (b << 20) | (g << 10) | r;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RGBA2_10_10_10, GraphicsContextGL::AlphaOp::DoUnmultiply, float, uint32_t>(const float* source, uint32_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = source[3] ? 1023.0f / source[3] : 1023.0f;
|
|
uint32_t r = static_cast<uint32_t>(source[0] * scaleFactor);
|
|
uint32_t g = static_cast<uint32_t>(source[1] * scaleFactor);
|
|
uint32_t b = static_cast<uint32_t>(source[2] * scaleFactor);
|
|
uint32_t a = static_cast<uint32_t>(source[3] * 3.0f);
|
|
destination[0] = (a << 30) | (b << 20) | (g << 10) | r;
|
|
source += 4;
|
|
destination += 1;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG8, GraphicsContextGL::AlphaOp::DoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[1];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG8, GraphicsContextGL::AlphaOp::DoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = static_cast<float>(source[3]) / MaxUInt8Value;
|
|
destination[0] = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[1] = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG8, GraphicsContextGL::AlphaOp::DoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = source[3] ? MaxUInt8Value / static_cast<float>(source[3]) : 1.0f;
|
|
destination[0] = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
|
destination[1] = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG16F, GraphicsContextGL::AlphaOp::DoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
destination[0] = convertFloatToHalfFloat(source[0]);
|
|
destination[1] = convertFloatToHalfFloat(source[1]);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG16F, GraphicsContextGL::AlphaOp::DoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG16F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor);
|
|
destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor);
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG32F, GraphicsContextGL::AlphaOp::DoNothing, float, float>(const float* source, float* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
destination[0] = source[0];
|
|
destination[1] = source[1];
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG32F, GraphicsContextGL::AlphaOp::DoPremultiply, float, float>(const float* source, float* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = source[3];
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
// FIXME: this routine is lossy and must be removed.
|
|
template<> ALWAYS_INLINE
|
|
void pack<GraphicsContextGL::DataFormat::RG32F, GraphicsContextGL::AlphaOp::DoUnmultiply, float, float>(const float* source, float* destination, unsigned pixels_per_row)
|
|
{
|
|
for (unsigned i = 0; i < pixels_per_row; ++i) {
|
|
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
|
destination[0] = source[0] * scaleFactor;
|
|
destination[1] = source[1] * scaleFactor;
|
|
source += 4;
|
|
destination += 2;
|
|
}
|
|
}
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IsInt8Format {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA8_S
|
|
|| Format == GraphicsContextGL::DataFormat::RGB8_S
|
|
|| Format == GraphicsContextGL::DataFormat::RG8_S
|
|
|| Format == GraphicsContextGL::DataFormat::R8_S;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IsInt16Format {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA16_S
|
|
|| Format == GraphicsContextGL::DataFormat::RGB16_S
|
|
|| Format == GraphicsContextGL::DataFormat::RG16_S
|
|
|| Format == GraphicsContextGL::DataFormat::R16_S;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IsInt32Format {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA32_S
|
|
|| Format == GraphicsContextGL::DataFormat::RGB32_S
|
|
|| Format == GraphicsContextGL::DataFormat::RG32_S
|
|
|| Format == GraphicsContextGL::DataFormat::R32_S;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IsUInt8Format {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA8
|
|
|| Format == GraphicsContextGL::DataFormat::RGB8
|
|
|| Format == GraphicsContextGL::DataFormat::RG8
|
|
|| Format == GraphicsContextGL::DataFormat::R8
|
|
|| Format == GraphicsContextGL::DataFormat::BGRA8
|
|
|| Format == GraphicsContextGL::DataFormat::BGR8
|
|
|| Format == GraphicsContextGL::DataFormat::ARGB8
|
|
|| Format == GraphicsContextGL::DataFormat::ABGR8
|
|
|| Format == GraphicsContextGL::DataFormat::RA8
|
|
|| Format == GraphicsContextGL::DataFormat::AR8
|
|
|| Format == GraphicsContextGL::DataFormat::A8;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IsUInt16Format {
|
|
static const bool Value = Format == GraphicsContextGL::DataFormat::RGBA16
|
|
|| Format == GraphicsContextGL::DataFormat::RGB16
|
|
|| Format == GraphicsContextGL::DataFormat::RG16
|
|
|| Format == GraphicsContextGL::DataFormat::R16;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IsUInt32Format {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA32
|
|
|| Format == GraphicsContextGL::DataFormat::RGB32
|
|
|| Format == GraphicsContextGL::DataFormat::RG32
|
|
|| Format == GraphicsContextGL::DataFormat::R32;
|
|
};
|
|
|
|
template<GraphicsContextGL::DataFormat Format>
|
|
struct IsFloatFormat {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA32F
|
|
|| Format == GraphicsContextGL::DataFormat::RGB32F
|
|
|| Format == GraphicsContextGL::DataFormat::RA32F
|
|
|| Format == GraphicsContextGL::DataFormat::R32F
|
|
|| Format == GraphicsContextGL::DataFormat::A32F
|
|
|| Format == GraphicsContextGL::DataFormat::RG32F;
|
|
};
|
|
|
|
template<GraphicsContextGL::DataFormat Format>
|
|
struct IsHalfFloatFormat {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA16F
|
|
|| Format == GraphicsContextGL::DataFormat::RGB16F
|
|
|| Format == GraphicsContextGL::DataFormat::RA16F
|
|
|| Format == GraphicsContextGL::DataFormat::R16F
|
|
|| Format == GraphicsContextGL::DataFormat::A16F
|
|
|| Format == GraphicsContextGL::DataFormat::RG16F;
|
|
};
|
|
|
|
template<GraphicsContextGL::DataFormat Format>
|
|
struct Is32bppFormat {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA2_10_10_10
|
|
|| Format == GraphicsContextGL::DataFormat::RGB5999
|
|
|| Format == GraphicsContextGL::DataFormat::RGB10F11F11F;
|
|
};
|
|
|
|
template<GraphicsContextGL::DataFormat Format>
|
|
struct Is16bppFormat {
|
|
static const bool Value =
|
|
Format == GraphicsContextGL::DataFormat::RGBA5551
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA4444
|
|
|| Format == GraphicsContextGL::DataFormat::RGB565;
|
|
};
|
|
|
|
template<GraphicsContextGL::DataFormat Format,
|
|
bool IsInt8Format = IsInt8Format<Format>::Value,
|
|
bool IsUInt8Format = IsUInt8Format<Format>::Value,
|
|
bool IsInt16Format = IsInt16Format<Format>::Value,
|
|
bool IsUInt16Format = IsUInt16Format<Format>::Value,
|
|
bool IsInt32Format = IsInt32Format<Format>::Value,
|
|
bool IsUInt32Format = IsUInt32Format<Format>::Value,
|
|
bool IsFloat = IsFloatFormat<Format>::Value,
|
|
bool IsHalfFloat = IsHalfFloatFormat<Format>::Value,
|
|
bool Is16bpp = Is16bppFormat<Format>::Value,
|
|
bool Is32bpp = Is32bppFormat<Format>::Value>
|
|
struct DataTypeForFormat {
|
|
typedef double Type; // Use a type that's not used in unpack/pack.
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef int8_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef uint8_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef int16_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef uint16_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef int32_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef uint32_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false> {
|
|
typedef float Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false,
|
|
false> {
|
|
typedef uint16_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false> {
|
|
typedef uint16_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct DataTypeForFormat<Format,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true> {
|
|
typedef uint32_t Type;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct UsesFloatIntermediateFormat {
|
|
static const bool Value =
|
|
IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA2_10_10_10
|
|
|| Format == GraphicsContextGL::DataFormat::RGB10F11F11F
|
|
|| Format == GraphicsContextGL::DataFormat::RGB5999;
|
|
};
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct IntermediateFormat {
|
|
static const GraphicsContextGL::DataFormat Value =
|
|
UsesFloatIntermediateFormat<Format>::Value
|
|
? GraphicsContextGL::DataFormat::RGBA32F
|
|
: IsInt32Format<Format>::Value
|
|
? GraphicsContextGL::DataFormat::RGBA32_S
|
|
: IsUInt32Format<Format>::Value
|
|
? GraphicsContextGL::DataFormat::RGBA32
|
|
: IsInt16Format<Format>::Value
|
|
? GraphicsContextGL::DataFormat::RGBA16_S
|
|
: (IsUInt16Format<Format>::Value || Is32bppFormat<Format>::Value)
|
|
? GraphicsContextGL::DataFormat::RGBA16
|
|
: IsInt8Format<Format>::Value
|
|
? GraphicsContextGL::DataFormat::RGBA8_S
|
|
: GraphicsContextGL::DataFormat::RGBA8;
|
|
};
|
|
|
|
/* END CODE SHARED WITH MOZILLA FIREFOX */
|
|
|
|
void FormatConverter::convert(GraphicsContextGL::DataFormat srcFormat, GraphicsContextGL::DataFormat dstFormat, GraphicsContextGL::AlphaOp alphaOp)
|
|
{
|
|
#define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \
|
|
case SrcFormat: \
|
|
return convert<SrcFormat>(dstFormat, alphaOp);
|
|
|
|
switch (srcFormat) {
|
|
// These are all of the input formats that potentially have to apply a non-trivial AlphaOp.
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RA8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RA32F)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGBA8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::ARGB8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::ABGR8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::AR8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::BGRA8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGBA5551)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGBA4444)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGBA32F)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGBA2_10_10_10)
|
|
// Additional input formats needed by various WebKit ports.
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::R8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::A8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::R32F)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::A32F)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGB8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::BGR8)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGB565)
|
|
FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContextGL::DataFormat::RGB32F)
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
#undef FORMATCONVERTER_CASE_SRCFORMAT
|
|
}
|
|
|
|
template<GraphicsContextGL::DataFormat SrcFormat>
|
|
ALWAYS_INLINE void FormatConverter::convert(GraphicsContextGL::DataFormat dstFormat, GraphicsContextGL::AlphaOp alphaOp)
|
|
{
|
|
#define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \
|
|
case DstFormat: \
|
|
return convert<SrcFormat, DstFormat>(alphaOp);
|
|
|
|
switch (dstFormat) {
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::R8)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::R16F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::R32F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::A8)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::A16F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::A32F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RA8)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RA16F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RA32F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGB8)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGB565)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGB16F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGB32F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA8)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA5551)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA4444)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA16F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA32F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA8_S)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA16)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA16_S)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA32)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA32_S)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RGBA2_10_10_10)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RG8)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RG16F)
|
|
FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContextGL::DataFormat::RG32F)
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
#undef FORMATCONVERTER_CASE_DSTFORMAT
|
|
}
|
|
|
|
template<GraphicsContextGL::DataFormat SrcFormat, GraphicsContextGL::DataFormat DstFormat>
|
|
ALWAYS_INLINE void FormatConverter::convert(GraphicsContextGL::AlphaOp alphaOp)
|
|
{
|
|
#define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \
|
|
case alphaOp: \
|
|
return convert<SrcFormat, DstFormat, alphaOp>();
|
|
|
|
switch (alphaOp) {
|
|
FORMATCONVERTER_CASE_ALPHAOP(GraphicsContextGL::AlphaOp::DoNothing)
|
|
FORMATCONVERTER_CASE_ALPHAOP(GraphicsContextGL::AlphaOp::DoPremultiply)
|
|
FORMATCONVERTER_CASE_ALPHAOP(GraphicsContextGL::AlphaOp::DoUnmultiply)
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
#undef FORMATCONVERTER_CASE_ALPHAOP
|
|
}
|
|
|
|
template <GraphicsContextGL::DataFormat Format>
|
|
struct SupportsConversionFromDomElements {
|
|
static const bool Value = (Format == GraphicsContextGL::DataFormat::RGBA8
|
|
|| Format == GraphicsContextGL::DataFormat::RGB8
|
|
|| Format == GraphicsContextGL::DataFormat::RG8
|
|
|| Format == GraphicsContextGL::DataFormat::RA8
|
|
|| Format == GraphicsContextGL::DataFormat::R8
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA32F
|
|
|| Format == GraphicsContextGL::DataFormat::RGB32F
|
|
|| Format == GraphicsContextGL::DataFormat::RG32F
|
|
|| Format == GraphicsContextGL::DataFormat::RA32F
|
|
|| Format == GraphicsContextGL::DataFormat::R32F
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA16F
|
|
|| Format == GraphicsContextGL::DataFormat::RGB16F
|
|
|| Format == GraphicsContextGL::DataFormat::RG16F
|
|
|| Format == GraphicsContextGL::DataFormat::RA16F
|
|
|| Format == GraphicsContextGL::DataFormat::R16F
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA5551
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA4444
|
|
|| Format == GraphicsContextGL::DataFormat::RGB565
|
|
|| Format == GraphicsContextGL::DataFormat::RGBA2_10_10_10);
|
|
};
|
|
|
|
// Visual Studio crashes with a C1063 Fatal Error if everything is inlined.
|
|
template<GraphicsContextGL::DataFormat SrcFormat, GraphicsContextGL::DataFormat DstFormat, GraphicsContextGL::AlphaOp alphaOp>
|
|
ALWAYS_INLINE_EXCEPT_MSVC void FormatConverter::convert()
|
|
{
|
|
// Many instantiations of this template function will never be entered, so we
|
|
// try to return immediately in these cases to avoid generating useless code.
|
|
if (SrcFormat == DstFormat && alphaOp == GraphicsContextGL::AlphaOp::DoNothing) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
if (!IsFloatFormat<DstFormat>::Value && IsFloatFormat<SrcFormat>::Value) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
|
|
// Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat.
|
|
const bool srcFormatComesFromDOMElementOrImageData = GraphicsContextGL::srcFormatComesFromDOMElementOrImageData(SrcFormat);
|
|
if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
// Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
|
|
if (!srcFormatComesFromDOMElementOrImageData && alphaOp == GraphicsContextGL::AlphaOp::DoUnmultiply) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
if (srcFormatComesFromDOMElementOrImageData && alphaOp == GraphicsContextGL::AlphaOp::DoUnmultiply && !SupportsConversionFromDomElements<DstFormat>::Value) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
if ((!GraphicsContextGL::hasAlpha(SrcFormat) || !GraphicsContextGL::hasColor(SrcFormat) || !GraphicsContextGL::hasColor(DstFormat)) && alphaOp != GraphicsContextGL::AlphaOp::DoNothing) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
// If converting DOM element data to UNSIGNED_INT_5_9_9_9_REV or
|
|
// UNSIGNED_INT_10F_11F_11F_REV, we should always switch to FLOAT instead to
|
|
// avoid unpacking/packing these two types.
|
|
if (srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat
|
|
&& (DstFormat == GraphicsContextGL::DataFormat::RGB5999 || DstFormat == GraphicsContextGL::DataFormat::RGB10F11F11F)) {
|
|
ASSERT_NOT_REACHED();
|
|
return;
|
|
}
|
|
|
|
typedef typename DataTypeForFormat<SrcFormat>::Type SrcType;
|
|
typedef typename DataTypeForFormat<DstFormat>::Type DstType;
|
|
const GraphicsContextGL::DataFormat IntermediateSrcFormat = IntermediateFormat<DstFormat>::Value;
|
|
typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType;
|
|
// Stride here could be negative.
|
|
const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType);
|
|
const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType);
|
|
const bool trivialUnpack = SrcFormat == IntermediateSrcFormat;
|
|
const bool trivialPack = DstFormat == IntermediateSrcFormat && alphaOp == GraphicsContextGL::AlphaOp::DoNothing;
|
|
ASSERT(!trivialUnpack || !trivialPack);
|
|
|
|
const SrcType* srcRowStart =
|
|
static_cast<const SrcType*>(static_cast<const void*>(
|
|
static_cast<const uint8_t*>(m_srcStart) +
|
|
((m_srcStride * m_srcSubRectangle.y()) + m_srcRowOffset)));
|
|
|
|
// If packing multiple images into a 3D texture, and flipY is true,
|
|
// then the sub-rectangle is pointing at the start of the
|
|
// "bottommost" of those images. Since the source pointer strides in
|
|
// the positive direction, we need to back it up to point at the
|
|
// last, or "topmost", of these images.
|
|
if (m_dstStride < 0 && m_depth > 1)
|
|
srcRowStart -= (m_depth - 1) * srcStrideInElements * m_unpackImageHeight;
|
|
|
|
DstType* dstRowStart = static_cast<DstType*>(m_dstStart);
|
|
if (trivialUnpack) {
|
|
for (int d = 0; d < m_depth; ++d) {
|
|
for (int i = 0; i < m_srcSubRectangle.height(); ++i) {
|
|
pack<DstFormat, alphaOp>(srcRowStart, dstRowStart,
|
|
m_srcSubRectangle.width());
|
|
srcRowStart += srcStrideInElements;
|
|
dstRowStart += dstStrideInElements;
|
|
}
|
|
srcRowStart += srcStrideInElements * (m_unpackImageHeight - m_srcSubRectangle.height());
|
|
}
|
|
} else if (trivialPack) {
|
|
for (int d = 0; d < m_depth; ++d) {
|
|
for (int i = 0; i < m_srcSubRectangle.height(); ++i) {
|
|
unpack<SrcFormat>(srcRowStart, dstRowStart,
|
|
m_srcSubRectangle.width());
|
|
srcRowStart += srcStrideInElements;
|
|
dstRowStart += dstStrideInElements;
|
|
}
|
|
srcRowStart += srcStrideInElements * (m_unpackImageHeight - m_srcSubRectangle.height());
|
|
}
|
|
} else {
|
|
for (int d = 0; d < m_depth; ++d) {
|
|
for (int i = 0; i < m_srcSubRectangle.height(); ++i) {
|
|
unpack<SrcFormat>(srcRowStart,
|
|
reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()),
|
|
m_srcSubRectangle.width());
|
|
pack<DstFormat, alphaOp>(reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()),
|
|
dstRowStart, m_srcSubRectangle.width());
|
|
srcRowStart += srcStrideInElements;
|
|
dstRowStart += dstStrideInElements;
|
|
}
|
|
srcRowStart += srcStrideInElements * (m_unpackImageHeight - m_srcSubRectangle.height());
|
|
}
|
|
}
|
|
m_success = true;
|
|
}
|
|
|
|
} // namespace WebCore
|
|
|
|
#endif // ENABLE(WEBGL)
|