| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "platform/graphics/gpu/WebGLImageConversion.h" |
| |
| #include <memory> |
| #include "build/build_config.h" |
| #include "platform/graphics/ImageObserver.h" |
| #include "platform/graphics/cpu/arm/WebGLImageConversionNEON.h" |
| #include "platform/graphics/cpu/mips/WebGLImageConversionMSA.h" |
| #include "platform/graphics/cpu/x86/WebGLImageConversionSSE.h" |
| #include "platform/graphics/skia/SkiaUtils.h" |
| #include "platform/image-decoders/ImageDecoder.h" |
| #include "platform/wtf/CheckedNumeric.h" |
| #include "platform/wtf/PtrUtil.h" |
| #include "third_party/skia/include/core/SkImage.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| const float kMaxInt8Value = INT8_MAX; |
| const float kMaxUInt8Value = UINT8_MAX; |
| const float kMaxInt16Value = INT16_MAX; |
| const float kMaxUInt16Value = UINT16_MAX; |
| const double kMaxInt32Value = INT32_MAX; |
| const double kMaxUInt32Value = UINT32_MAX; |
| |
| int8_t ClampMin(int8_t value) { |
| const static int8_t kMinInt8Value = INT8_MIN + 1; |
| return value < kMinInt8Value ? kMinInt8Value : value; |
| } |
| |
| int16_t ClampMin(int16_t value) { |
| const static int16_t kMinInt16Value = INT16_MIN + 1; |
| return value < kMinInt16Value ? kMinInt16Value : value; |
| } |
| |
| int32_t ClampMin(int32_t value) { |
| const static int32_t kMinInt32Value = INT32_MIN + 1; |
| return value < kMinInt32Value ? kMinInt32Value : value; |
| } |
| |
| // Return kDataFormatNumFormats if format/type combination is invalid. |
| WebGLImageConversion::DataFormat GetDataFormat(GLenum destination_format, |
| GLenum destination_type) { |
| WebGLImageConversion::DataFormat dst_format = |
| WebGLImageConversion::kDataFormatRGBA8; |
| switch (destination_type) { |
| case GL_BYTE: |
| switch (destination_format) { |
| case GL_RED: |
| case GL_RED_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatR8_S; |
| break; |
| case GL_RG: |
| case GL_RG_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRG8_S; |
| break; |
| case GL_RGB: |
| case GL_RGB_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGB8_S; |
| break; |
| case GL_RGBA: |
| case GL_RGBA_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGBA8_S; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_UNSIGNED_BYTE: |
| switch (destination_format) { |
| case GL_RGB: |
| case GL_RGB_INTEGER: |
| case GL_SRGB_EXT: |
| dst_format = WebGLImageConversion::kDataFormatRGB8; |
| break; |
| case GL_RGBA: |
| case GL_RGBA_INTEGER: |
| case GL_SRGB_ALPHA_EXT: |
| dst_format = WebGLImageConversion::kDataFormatRGBA8; |
| break; |
| case GL_ALPHA: |
| dst_format = WebGLImageConversion::kDataFormatA8; |
| break; |
| case GL_LUMINANCE: |
| case GL_RED: |
| case GL_RED_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatR8; |
| break; |
| case GL_RG: |
| case GL_RG_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRG8; |
| break; |
| case GL_LUMINANCE_ALPHA: |
| dst_format = WebGLImageConversion::kDataFormatRA8; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_SHORT: |
| switch (destination_format) { |
| case GL_RED_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatR16_S; |
| break; |
| case GL_RG_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRG16_S; |
| break; |
| case GL_RGB_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGB16_S; |
| case GL_RGBA_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGBA16_S; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_UNSIGNED_SHORT: |
| switch (destination_format) { |
| case GL_RED_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatR16; |
| break; |
| case GL_DEPTH_COMPONENT: |
| dst_format = WebGLImageConversion::kDataFormatD16; |
| break; |
| case GL_RG_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRG16; |
| break; |
| case GL_RGB_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGB16; |
| break; |
| case GL_RGBA_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGBA16; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_INT: |
| switch (destination_format) { |
| case GL_RED_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatR32_S; |
| break; |
| case GL_RG_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRG32_S; |
| break; |
| case GL_RGB_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGB32_S; |
| break; |
| case GL_RGBA_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGBA32_S; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_UNSIGNED_INT: |
| switch (destination_format) { |
| case GL_RED_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatR32; |
| break; |
| case GL_DEPTH_COMPONENT: |
| dst_format = WebGLImageConversion::kDataFormatD32; |
| break; |
| case GL_RG_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRG32; |
| break; |
| case GL_RGB_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGB32; |
| break; |
| case GL_RGBA_INTEGER: |
| dst_format = WebGLImageConversion::kDataFormatRGBA32; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_HALF_FLOAT_OES: // OES_texture_half_float |
| case GL_HALF_FLOAT: |
| switch (destination_format) { |
| case GL_RGBA: |
| dst_format = WebGLImageConversion::kDataFormatRGBA16F; |
| break; |
| case GL_RGB: |
| dst_format = WebGLImageConversion::kDataFormatRGB16F; |
| break; |
| case GL_RG: |
| dst_format = WebGLImageConversion::kDataFormatRG16F; |
| break; |
| case GL_ALPHA: |
| dst_format = WebGLImageConversion::kDataFormatA16F; |
| break; |
| case GL_LUMINANCE: |
| case GL_RED: |
| dst_format = WebGLImageConversion::kDataFormatR16F; |
| break; |
| case GL_LUMINANCE_ALPHA: |
| dst_format = WebGLImageConversion::kDataFormatRA16F; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_FLOAT: // OES_texture_float |
| switch (destination_format) { |
| case GL_RGBA: |
| dst_format = WebGLImageConversion::kDataFormatRGBA32F; |
| break; |
| case GL_RGB: |
| dst_format = WebGLImageConversion::kDataFormatRGB32F; |
| break; |
| case GL_RG: |
| dst_format = WebGLImageConversion::kDataFormatRG32F; |
| break; |
| case GL_ALPHA: |
| dst_format = WebGLImageConversion::kDataFormatA32F; |
| break; |
| case GL_LUMINANCE: |
| case GL_RED: |
| dst_format = WebGLImageConversion::kDataFormatR32F; |
| break; |
| case GL_DEPTH_COMPONENT: |
| dst_format = WebGLImageConversion::kDataFormatD32F; |
| break; |
| case GL_LUMINANCE_ALPHA: |
| dst_format = WebGLImageConversion::kDataFormatRA32F; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| break; |
| case GL_UNSIGNED_SHORT_4_4_4_4: |
| dst_format = WebGLImageConversion::kDataFormatRGBA4444; |
| break; |
| case GL_UNSIGNED_SHORT_5_5_5_1: |
| dst_format = WebGLImageConversion::kDataFormatRGBA5551; |
| break; |
| case GL_UNSIGNED_SHORT_5_6_5: |
| dst_format = WebGLImageConversion::kDataFormatRGB565; |
| break; |
| case GL_UNSIGNED_INT_5_9_9_9_REV: |
| dst_format = WebGLImageConversion::kDataFormatRGB5999; |
| break; |
| case GL_UNSIGNED_INT_24_8: |
| dst_format = WebGLImageConversion::kDataFormatDS24_8; |
| break; |
| case GL_UNSIGNED_INT_10F_11F_11F_REV: |
| dst_format = WebGLImageConversion::kDataFormatRGB10F11F11F; |
| break; |
| case GL_UNSIGNED_INT_2_10_10_10_REV: |
| dst_format = WebGLImageConversion::kDataFormatRGBA2_10_10_10; |
| break; |
| default: |
| return WebGLImageConversion::kDataFormatNumFormats; |
| } |
| return dst_format; |
| } |
| |
| // The following Float to Half-Float conversion 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; |
| } |
| } |
| } |
| */ |
| |
| unsigned short g_base_table[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}; |
| |
| unsigned char g_shift_table[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}; |
| |
| unsigned short ConvertFloatToHalfFloat(float f) { |
| unsigned temp = *(reinterpret_cast<unsigned*>(&f)); |
| unsigned signexp = (temp >> 23) & 0x1ff; |
| return g_base_table[signexp] + |
| ((temp & 0x007fffff) >> g_shift_table[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 <int format, typename SourceType, typename DstType> |
| void Unpack(const SourceType*, DstType*, unsigned) { |
| NOTREACHED(); |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatARGB8, 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[1]; |
| destination[1] = source[2]; |
| destination[2] = source[3]; |
| destination[3] = source[0]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatABGR8, 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[3]; |
| destination[1] = source[2]; |
| destination[2] = source[1]; |
| destination[3] = source[0]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatBGRA8, uint8_t, uint8_t>( |
| const uint8_t* source, |
| uint8_t* destination, |
| unsigned pixels_per_row) { |
| const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source); |
| uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination); |
| |
| #if defined(ARCH_CPU_X86_FAMILY) |
| SIMD::UnpackOneRowOfBGRA8LittleToRGBA8(source32, destination32, |
| pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::unpackOneRowOfBGRA8LittleToRGBA8MSA(source32, destination32, |
| pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| uint32_t bgra = source32[i]; |
| #if defined(ARCH_CPU_BIG_ENDIAN) |
| uint32_t brMask = 0xff00ff00; |
| uint32_t gaMask = 0x00ff00ff; |
| #else |
| uint32_t br_mask = 0x00ff00ff; |
| uint32_t ga_mask = 0xff00ff00; |
| #endif |
| uint32_t rgba = |
| (((bgra >> 16) | (bgra << 16)) & br_mask) | (bgra & ga_mask); |
| destination32[i] = rgba; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatRGBA5551, uint16_t, uint8_t>( |
| const uint16_t* source, |
| uint8_t* destination, |
| unsigned pixels_per_row) { |
| #if defined(ARCH_CPU_X86_FAMILY) |
| SIMD::UnpackOneRowOfRGBA5551LittleToRGBA8(source, destination, |
| pixels_per_row); |
| #endif |
| #if WTF_CPU_ARM_NEON |
| SIMD::UnpackOneRowOfRGBA5551ToRGBA8(source, destination, pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::unpackOneRowOfRGBA5551ToRGBA8MSA(source, destination, pixels_per_row); |
| #endif |
| |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| uint16_t packed_value = source[0]; |
| uint8_t r = packed_value >> 11; |
| uint8_t g = (packed_value >> 6) & 0x1F; |
| uint8_t b = (packed_value >> 1) & 0x1F; |
| destination[0] = (r << 3) | (r & 0x7); |
| destination[1] = (g << 3) | (g & 0x7); |
| destination[2] = (b << 3) | (b & 0x7); |
| destination[3] = (packed_value & 0x1) ? 0xFF : 0x0; |
| source += 1; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatRGBA4444, uint16_t, uint8_t>( |
| const uint16_t* source, |
| uint8_t* destination, |
| unsigned pixels_per_row) { |
| #if defined(ARCH_CPU_X86_FAMILY) |
| SIMD::UnpackOneRowOfRGBA4444LittleToRGBA8(source, destination, |
| pixels_per_row); |
| #endif |
| #if WTF_CPU_ARM_NEON |
| SIMD::UnpackOneRowOfRGBA4444ToRGBA8(source, destination, pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::unpackOneRowOfRGBA4444ToRGBA8MSA(source, destination, pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| uint16_t packed_value = source[0]; |
| uint8_t r = packed_value >> 12; |
| uint8_t g = (packed_value >> 8) & 0x0F; |
| uint8_t b = (packed_value >> 4) & 0x0F; |
| uint8_t a = packed_value & 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 <> |
| void Unpack<WebGLImageConversion::kDataFormatRA8, 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[0]; |
| destination[2] = source[0]; |
| destination[3] = source[1]; |
| source += 2; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatAR8, 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[1]; |
| destination[1] = source[1]; |
| destination[2] = source[1]; |
| destination[3] = source[0]; |
| source += 2; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatRGBA8, uint8_t, float>( |
| const uint8_t* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| const float kScaleFactor = 1.0f / 255.0f; |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| destination[0] = source[0] * kScaleFactor; |
| destination[1] = source[1] * kScaleFactor; |
| destination[2] = source[2] * kScaleFactor; |
| destination[3] = source[3] * kScaleFactor; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatBGRA8, uint8_t, float>( |
| const uint8_t* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| const float kScaleFactor = 1.0f / 255.0f; |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| destination[0] = source[2] * kScaleFactor; |
| destination[1] = source[1] * kScaleFactor; |
| destination[2] = source[0] * kScaleFactor; |
| destination[3] = source[3] * kScaleFactor; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatABGR8, uint8_t, float>( |
| const uint8_t* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| const float kScaleFactor = 1.0f / 255.0f; |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| destination[0] = source[3] * kScaleFactor; |
| destination[1] = source[2] * kScaleFactor; |
| destination[2] = source[1] * kScaleFactor; |
| destination[3] = source[0] * kScaleFactor; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatARGB8, uint8_t, float>( |
| const uint8_t* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| const float kScaleFactor = 1.0f / 255.0f; |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| destination[0] = source[1] * kScaleFactor; |
| destination[1] = source[2] * kScaleFactor; |
| destination[2] = source[3] * kScaleFactor; |
| destination[3] = source[0] * kScaleFactor; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatRA32F, 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[0]; |
| destination[2] = source[0]; |
| destination[3] = source[1]; |
| source += 2; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Unpack<WebGLImageConversion::kDataFormatRGBA2_10_10_10, uint32_t, float>( |
| const uint32_t* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| static const float kRgbScaleFactor = 1.0f / 1023.0f; |
| static const float kAlphaScaleFactor = 1.0f / 3.0f; |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| uint32_t packed_value = source[0]; |
| destination[0] = static_cast<float>(packed_value & 0x3FF) * kRgbScaleFactor; |
| destination[1] = |
| static_cast<float>((packed_value >> 10) & 0x3FF) * kRgbScaleFactor; |
| destination[2] = |
| static_cast<float>((packed_value >> 20) & 0x3FF) * kRgbScaleFactor; |
| destination[3] = static_cast<float>(packed_value >> 30) * kAlphaScaleFactor; |
| source += 1; |
| destination += 4; |
| } |
| } |
| |
| //---------------------------------------------------------------------- |
| // Pixel packing routines. |
| // |
| |
| template <int format, int alphaOp, typename SourceType, typename DstType> |
| void Pack(const SourceType*, DstType*, unsigned) { |
| NOTREACHED(); |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatA8, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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[3]; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR8, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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]; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR8, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[0] = source_r; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR8, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| uint8_t, |
| uint8_t>(const uint8_t* source, |
| uint8_t* destination, |
| unsigned pixels_per_row) { |
| #if defined(ARCH_CPU_X86_FAMILY) |
| SIMD::PackOneRowOfRGBA8LittleToR8(source, destination, pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::packOneRowOfRGBA8LittleToR8MSA(source, destination, pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[0] = source_r; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA8, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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[3]; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA8, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[0] = source_r; |
| destination[1] = source[3]; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA8, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| uint8_t, |
| uint8_t>(const uint8_t* source, |
| uint8_t* destination, |
| unsigned pixels_per_row) { |
| #if defined(ARCH_CPU_X86_FAMILY) |
| SIMD::PackOneRowOfRGBA8LittleToRA8(source, destination, pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::packOneRowOfRGBA8LittleToRA8MSA(source, destination, pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[0] = source_r; |
| destination[1] = source[3]; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB8, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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]; |
| destination[2] = source[2]; |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB8, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| destination[0] = source_r; |
| destination[1] = source_g; |
| destination[2] = source_b; |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB8, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| 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 scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| destination[0] = source_r; |
| destination[1] = source_g; |
| destination[2] = source_b; |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA8, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| destination[0] = source_r; |
| destination[1] = source_g; |
| destination[2] = source_b; |
| destination[3] = source[3]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA8, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| uint8_t, |
| uint8_t>(const uint8_t* source, |
| uint8_t* destination, |
| unsigned pixels_per_row) { |
| #if defined(ARCH_CPU_X86_FAMILY) |
| SIMD::PackOneRowOfRGBA8LittleToRGBA8(source, destination, pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::packOneRowOfRGBA8LittleToRGBA8MSA(source, destination, pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| destination[0] = source_r; |
| destination[1] = source_g; |
| destination[2] = source_b; |
| destination[3] = source[3]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA4444, |
| WebGLImageConversion::kAlphaDoNothing, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| #if WTF_CPU_ARM_NEON |
| SIMD::PackOneRowOfRGBA8ToUnsignedShort4444(source, destination, |
| pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::packOneRowOfRGBA8ToUnsignedShort4444MSA(source, destination, |
| pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| *destination = (((source[0] & 0xF0) << 8) | ((source[1] & 0xF0) << 4) | |
| (source[2] & 0xF0) | (source[3] >> 4)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA4444, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| *destination = (((source_r & 0xF0) << 8) | ((source_g & 0xF0) << 4) | |
| (source_b & 0xF0) | (source[3] >> 4)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA4444, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| *destination = (((source_r & 0xF0) << 8) | ((source_g & 0xF0) << 4) | |
| (source_b & 0xF0) | (source[3] >> 4)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA5551, |
| WebGLImageConversion::kAlphaDoNothing, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| #if WTF_CPU_ARM_NEON |
| SIMD::PackOneRowOfRGBA8ToUnsignedShort5551(source, destination, |
| pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::packOneRowOfRGBA8ToUnsignedShort5551MSA(source, destination, |
| pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| *destination = (((source[0] & 0xF8) << 8) | ((source[1] & 0xF8) << 3) | |
| ((source[2] & 0xF8) >> 2) | (source[3] >> 7)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA5551, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xF8) << 3) | |
| ((source_b & 0xF8) >> 2) | (source[3] >> 7)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA5551, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xF8) << 3) | |
| ((source_b & 0xF8) >> 2) | (source[3] >> 7)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB565, |
| WebGLImageConversion::kAlphaDoNothing, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| #if WTF_CPU_ARM_NEON |
| SIMD::PackOneRowOfRGBA8ToUnsignedShort565(source, destination, |
| pixels_per_row); |
| #endif |
| #if HAVE_MIPS_MSA_INTRINSICS |
| SIMD::packOneRowOfRGBA8ToUnsignedShort565MSA(source, destination, |
| pixels_per_row); |
| #endif |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| *destination = (((source[0] & 0xF8) << 8) | ((source[1] & 0xFC) << 3) | |
| ((source[2] & 0xF8) >> 3)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB565, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] / 255.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xFC) << 3) | |
| ((source_b & 0xF8) >> 3)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB565, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| uint8_t, |
| uint16_t>(const uint8_t* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 255.0f / source[3] : 1.0f; |
| uint8_t source_r = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| uint8_t source_g = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| uint8_t source_b = |
| static_cast<uint8_t>(static_cast<float>(source[2]) * scale_factor); |
| *destination = (((source_r & 0xF8) << 8) | ((source_g & 0xFC) << 3) | |
| ((source_b & 0xF8) >> 3)); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB32F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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]; |
| destination[2] = source[2]; |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB32F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[1] * scale_factor; |
| destination[2] = source[2] * scale_factor; |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB32F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[1] * scale_factor; |
| destination[2] = source[2] * scale_factor; |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA32F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[1] * scale_factor; |
| destination[2] = source[2] * scale_factor; |
| destination[3] = source[3]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA32F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[1] * scale_factor; |
| destination[2] = source[2] * scale_factor; |
| destination[3] = source[3]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatA32F, |
| WebGLImageConversion::kAlphaDoNothing, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| destination[0] = source[3]; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR32F, |
| WebGLImageConversion::kAlphaDoNothing, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| destination[0] = source[0]; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR32F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = source[0] * scale_factor; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR32F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = source[0] * scale_factor; |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA32F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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[3]; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA32F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[3]; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA32F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[3]; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA16F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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]); |
| destination[2] = ConvertFloatToHalfFloat(source[2]); |
| destination[3] = ConvertFloatToHalfFloat(source[3]); |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA16F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor); |
| destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor); |
| destination[3] = ConvertFloatToHalfFloat(source[3]); |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA16F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor); |
| destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor); |
| destination[3] = ConvertFloatToHalfFloat(source[3]); |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB16F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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]); |
| destination[2] = ConvertFloatToHalfFloat(source[2]); |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB16F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor); |
| destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor); |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGB16F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor); |
| destination[2] = ConvertFloatToHalfFloat(source[2] * scale_factor); |
| source += 4; |
| destination += 3; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA16F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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[3]); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA16F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[3]); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRA16F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[3]); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR16F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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]); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR16F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatR16F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatA16F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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[3]); |
| source += 4; |
| destination += 1; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA8_S, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = static_cast<float>(destination[3]) / kMaxInt8Value; |
| destination[0] = static_cast<int8_t>( |
| static_cast<float>(ClampMin(source[0])) * scale_factor); |
| destination[1] = static_cast<int8_t>( |
| static_cast<float>(ClampMin(source[1])) * scale_factor); |
| destination[2] = static_cast<int8_t>( |
| static_cast<float>(ClampMin(source[2])) * scale_factor); |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA16, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = static_cast<float>(source[3]) / kMaxUInt16Value; |
| destination[0] = |
| static_cast<uint16_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[1] = |
| static_cast<uint16_t>(static_cast<float>(source[1]) * scale_factor); |
| destination[2] = |
| static_cast<uint16_t>(static_cast<float>(source[2]) * scale_factor); |
| destination[3] = source[3]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA16_S, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = static_cast<float>(destination[3]) / kMaxInt16Value; |
| destination[0] = static_cast<int16_t>( |
| static_cast<float>(ClampMin(source[0])) * scale_factor); |
| destination[1] = static_cast<int16_t>( |
| static_cast<float>(ClampMin(source[1])) * scale_factor); |
| destination[2] = static_cast<int16_t>( |
| static_cast<float>(ClampMin(source[2])) * scale_factor); |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA32, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = static_cast<double>(source[3]) / kMaxUInt32Value; |
| destination[0] = |
| static_cast<uint32_t>(static_cast<double>(source[0]) * scale_factor); |
| destination[1] = |
| static_cast<uint32_t>(static_cast<double>(source[1]) * scale_factor); |
| destination[2] = |
| static_cast<uint32_t>(static_cast<double>(source[2]) * scale_factor); |
| destination[3] = source[3]; |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA32_S, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = static_cast<double>(destination[3]) / kMaxInt32Value; |
| destination[0] = static_cast<int32_t>( |
| static_cast<double>(ClampMin(source[0])) * scale_factor); |
| destination[1] = static_cast<int32_t>( |
| static_cast<double>(ClampMin(source[1])) * scale_factor); |
| destination[2] = static_cast<int32_t>( |
| static_cast<double>(ClampMin(source[2])) * scale_factor); |
| source += 4; |
| destination += 4; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA2_10_10_10, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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 <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA2_10_10_10, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 <> |
| void Pack<WebGLImageConversion::kDataFormatRGBA2_10_10_10, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| uint32_t>(const float* source, |
| uint32_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1023.0f / source[3] : 1023.0f; |
| uint32_t r = static_cast<uint32_t>(source[0] * scale_factor); |
| uint32_t g = static_cast<uint32_t>(source[1] * scale_factor); |
| uint32_t b = static_cast<uint32_t>(source[2] * scale_factor); |
| 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 <> |
| void Pack<WebGLImageConversion::kDataFormatRG8, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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 <> |
| void Pack<WebGLImageConversion::kDataFormatRG8, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| 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 scale_factor = static_cast<float>(source[3]) / kMaxUInt8Value; |
| destination[0] = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[1] = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRG8, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| 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 scale_factor = |
| source[3] ? kMaxUInt8Value / static_cast<float>(source[3]) : 1.0f; |
| destination[0] = |
| static_cast<uint8_t>(static_cast<float>(source[0]) * scale_factor); |
| destination[1] = |
| static_cast<uint8_t>(static_cast<float>(source[1]) * scale_factor); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRG16F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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 <> |
| void Pack<WebGLImageConversion::kDataFormatRG16F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRG16F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| uint16_t>(const float* source, |
| uint16_t* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = ConvertFloatToHalfFloat(source[0] * scale_factor); |
| destination[1] = ConvertFloatToHalfFloat(source[1] * scale_factor); |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRG32F, |
| WebGLImageConversion::kAlphaDoNothing, |
| 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 <> |
| void Pack<WebGLImageConversion::kDataFormatRG32F, |
| WebGLImageConversion::kAlphaDoPremultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3]; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[1] * scale_factor; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| // FIXME: this routine is lossy and must be removed. |
| template <> |
| void Pack<WebGLImageConversion::kDataFormatRG32F, |
| WebGLImageConversion::kAlphaDoUnmultiply, |
| float, |
| float>(const float* source, |
| float* destination, |
| unsigned pixels_per_row) { |
| for (unsigned i = 0; i < pixels_per_row; ++i) { |
| float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; |
| destination[0] = source[0] * scale_factor; |
| destination[1] = source[1] * scale_factor; |
| source += 4; |
| destination += 2; |
| } |
| } |
| |
| bool HasAlpha(int format) { |
| return format == WebGLImageConversion::kDataFormatA8 || |
| format == WebGLImageConversion::kDataFormatA16F || |
| format == WebGLImageConversion::kDataFormatA32F || |
| format == WebGLImageConversion::kDataFormatRA8 || |
| format == WebGLImageConversion::kDataFormatAR8 || |
| format == WebGLImageConversion::kDataFormatRA16F || |
| format == WebGLImageConversion::kDataFormatRA32F || |
| format == WebGLImageConversion::kDataFormatRGBA8 || |
| format == WebGLImageConversion::kDataFormatBGRA8 || |
| format == WebGLImageConversion::kDataFormatARGB8 || |
| format == WebGLImageConversion::kDataFormatABGR8 || |
| format == WebGLImageConversion::kDataFormatRGBA16F || |
| format == WebGLImageConversion::kDataFormatRGBA32F || |
| format == WebGLImageConversion::kDataFormatRGBA4444 || |
| format == WebGLImageConversion::kDataFormatRGBA5551 || |
| format == WebGLImageConversion::kDataFormatRGBA8_S || |
| format == WebGLImageConversion::kDataFormatRGBA16 || |
| format == WebGLImageConversion::kDataFormatRGBA16_S || |
| format == WebGLImageConversion::kDataFormatRGBA32 || |
| format == WebGLImageConversion::kDataFormatRGBA32_S || |
| format == WebGLImageConversion::kDataFormatRGBA2_10_10_10; |
| } |
| |
| bool HasColor(int format) { |
| return format == WebGLImageConversion::kDataFormatRGBA8 || |
| format == WebGLImageConversion::kDataFormatRGBA16F || |
| format == WebGLImageConversion::kDataFormatRGBA32F || |
| format == WebGLImageConversion::kDataFormatRGB8 || |
| format == WebGLImageConversion::kDataFormatRGB16F || |
| format == WebGLImageConversion::kDataFormatRGB32F || |
| format == WebGLImageConversion::kDataFormatBGR8 || |
| format == WebGLImageConversion::kDataFormatBGRA8 || |
| format == WebGLImageConversion::kDataFormatARGB8 || |
| format == WebGLImageConversion::kDataFormatABGR8 || |
| format == WebGLImageConversion::kDataFormatRGBA5551 || |
| format == WebGLImageConversion::kDataFormatRGBA4444 || |
| format == WebGLImageConversion::kDataFormatRGB565 || |
| format == WebGLImageConversion::kDataFormatR8 || |
| format == WebGLImageConversion::kDataFormatR16F || |
| format == WebGLImageConversion::kDataFormatR32F || |
| format == WebGLImageConversion::kDataFormatRA8 || |
| format == WebGLImageConversion::kDataFormatRA16F || |
| format == WebGLImageConversion::kDataFormatRA32F || |
| format == WebGLImageConversion::kDataFormatAR8 || |
| format == WebGLImageConversion::kDataFormatRGBA8_S || |
| format == WebGLImageConversion::kDataFormatRGBA16 || |
| format == WebGLImageConversion::kDataFormatRGBA16_S || |
| format == WebGLImageConversion::kDataFormatRGBA32 || |
| format == WebGLImageConversion::kDataFormatRGBA32_S || |
| format == WebGLImageConversion::kDataFormatRGBA2_10_10_10 || |
| format == WebGLImageConversion::kDataFormatRGB8_S || |
| format == WebGLImageConversion::kDataFormatRGB16 || |
| format == WebGLImageConversion::kDataFormatRGB16_S || |
| format == WebGLImageConversion::kDataFormatRGB32 || |
| format == WebGLImageConversion::kDataFormatRGB32_S || |
| format == WebGLImageConversion::kDataFormatRGB10F11F11F || |
| format == WebGLImageConversion::kDataFormatRGB5999 || |
| format == WebGLImageConversion::kDataFormatRG8 || |
| format == WebGLImageConversion::kDataFormatRG8_S || |
| format == WebGLImageConversion::kDataFormatRG16 || |
| format == WebGLImageConversion::kDataFormatRG16_S || |
| format == WebGLImageConversion::kDataFormatRG32 || |
| format == WebGLImageConversion::kDataFormatRG32_S || |
| format == WebGLImageConversion::kDataFormatRG16F || |
| format == WebGLImageConversion::kDataFormatRG32F || |
| format == WebGLImageConversion::kDataFormatR8_S || |
| format == WebGLImageConversion::kDataFormatR16 || |
| format == WebGLImageConversion::kDataFormatR16_S || |
| format == WebGLImageConversion::kDataFormatR32 || |
| format == WebGLImageConversion::kDataFormatR32_S; |
| } |
| |
| template <int Format> |
| struct IsInt8Format { |
| STATIC_ONLY(IsInt8Format); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA8_S || |
| Format == WebGLImageConversion::kDataFormatRGB8_S || |
| Format == WebGLImageConversion::kDataFormatRG8_S || |
| Format == WebGLImageConversion::kDataFormatR8_S; |
| }; |
| |
| template <int Format> |
| struct IsInt16Format { |
| STATIC_ONLY(IsInt16Format); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA16_S || |
| Format == WebGLImageConversion::kDataFormatRGB16_S || |
| Format == WebGLImageConversion::kDataFormatRG16_S || |
| Format == WebGLImageConversion::kDataFormatR16_S; |
| }; |
| |
| template <int Format> |
| struct IsInt32Format { |
| STATIC_ONLY(IsInt32Format); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA32_S || |
| Format == WebGLImageConversion::kDataFormatRGB32_S || |
| Format == WebGLImageConversion::kDataFormatRG32_S || |
| Format == WebGLImageConversion::kDataFormatR32_S; |
| }; |
| |
| template <int Format> |
| struct IsUInt8Format { |
| STATIC_ONLY(IsUInt8Format); |
| static const bool value = Format == WebGLImageConversion::kDataFormatRGBA8 || |
| Format == WebGLImageConversion::kDataFormatRGB8 || |
| Format == WebGLImageConversion::kDataFormatRG8 || |
| Format == WebGLImageConversion::kDataFormatR8 || |
| Format == WebGLImageConversion::kDataFormatBGRA8 || |
| Format == WebGLImageConversion::kDataFormatBGR8 || |
| Format == WebGLImageConversion::kDataFormatARGB8 || |
| Format == WebGLImageConversion::kDataFormatABGR8 || |
| Format == WebGLImageConversion::kDataFormatRA8 || |
| Format == WebGLImageConversion::kDataFormatAR8 || |
| Format == WebGLImageConversion::kDataFormatA8; |
| }; |
| |
| template <int Format> |
| struct IsUInt16Format { |
| STATIC_ONLY(IsUInt16Format); |
| static const bool value = Format == WebGLImageConversion::kDataFormatRGBA16 || |
| Format == WebGLImageConversion::kDataFormatRGB16 || |
| Format == WebGLImageConversion::kDataFormatRG16 || |
| Format == WebGLImageConversion::kDataFormatR16; |
| }; |
| |
| template <int Format> |
| struct IsUInt32Format { |
| STATIC_ONLY(IsUInt32Format); |
| static const bool value = Format == WebGLImageConversion::kDataFormatRGBA32 || |
| Format == WebGLImageConversion::kDataFormatRGB32 || |
| Format == WebGLImageConversion::kDataFormatRG32 || |
| Format == WebGLImageConversion::kDataFormatR32; |
| }; |
| |
| template <int Format> |
| struct IsFloatFormat { |
| STATIC_ONLY(IsFloatFormat); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA32F || |
| Format == WebGLImageConversion::kDataFormatRGB32F || |
| Format == WebGLImageConversion::kDataFormatRA32F || |
| Format == WebGLImageConversion::kDataFormatR32F || |
| Format == WebGLImageConversion::kDataFormatA32F || |
| Format == WebGLImageConversion::kDataFormatRG32F; |
| }; |
| |
| template <int Format> |
| struct IsHalfFloatFormat { |
| STATIC_ONLY(IsHalfFloatFormat); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA16F || |
| Format == WebGLImageConversion::kDataFormatRGB16F || |
| Format == WebGLImageConversion::kDataFormatRA16F || |
| Format == WebGLImageConversion::kDataFormatR16F || |
| Format == WebGLImageConversion::kDataFormatA16F || |
| Format == WebGLImageConversion::kDataFormatRG16F; |
| }; |
| |
| template <int Format> |
| struct Is32bppFormat { |
| STATIC_ONLY(Is32bppFormat); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA2_10_10_10 || |
| Format == WebGLImageConversion::kDataFormatRGB5999 || |
| Format == WebGLImageConversion::kDataFormatRGB10F11F11F; |
| }; |
| |
| template <int Format> |
| struct Is16bppFormat { |
| STATIC_ONLY(Is16bppFormat); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA5551 || |
| Format == WebGLImageConversion::kDataFormatRGBA4444 || |
| Format == WebGLImageConversion::kDataFormatRGB565; |
| }; |
| |
| template <int 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 { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef double Type; // Use a type that's not used in unpack/pack. |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| true, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef int8_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| true, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef uint8_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| true, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef int16_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| true, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef uint16_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| false, |
| true, |
| false, |
| false, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef int32_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| false, |
| false, |
| true, |
| false, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef uint32_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| true, |
| false, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef float Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| true, |
| false, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef uint16_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| true, |
| false> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef uint16_t Type; |
| }; |
| |
| template <int Format> |
| struct DataTypeForFormat<Format, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| false, |
| true> { |
| STATIC_ONLY(DataTypeForFormat); |
| typedef uint32_t Type; |
| }; |
| |
| template <int Format> |
| struct UsesFloatIntermediateFormat { |
| STATIC_ONLY(UsesFloatIntermediateFormat); |
| static const bool value = |
| IsFloatFormat<Format>::value || IsHalfFloatFormat<Format>::value || |
| Format == WebGLImageConversion::kDataFormatRGBA2_10_10_10 || |
| Format == WebGLImageConversion::kDataFormatRGB10F11F11F || |
| Format == WebGLImageConversion::kDataFormatRGB5999; |
| }; |
| |
| template <int Format> |
| struct IntermediateFormat { |
| STATIC_ONLY(IntermediateFormat); |
| static const int value = |
| UsesFloatIntermediateFormat<Format>::value |
| ? WebGLImageConversion::kDataFormatRGBA32F |
| : IsInt32Format<Format>::value |
| ? WebGLImageConversion::kDataFormatRGBA32_S |
| : IsUInt32Format<Format>::value |
| ? WebGLImageConversion::kDataFormatRGBA32 |
| : IsInt16Format<Format>::value |
| ? WebGLImageConversion::kDataFormatRGBA16_S |
| : (IsUInt16Format<Format>::value || |
| Is32bppFormat<Format>::value) |
| ? WebGLImageConversion::kDataFormatRGBA16 |
| : IsInt8Format<Format>::value |
| ? WebGLImageConversion:: |
| kDataFormatRGBA8_S |
| : WebGLImageConversion:: |
| kDataFormatRGBA8; |
| }; |
| |
| unsigned TexelBytesForFormat(WebGLImageConversion::DataFormat format) { |
| switch (format) { |
| case WebGLImageConversion::kDataFormatR8: |
| case WebGLImageConversion::kDataFormatR8_S: |
| case WebGLImageConversion::kDataFormatA8: |
| return 1; |
| case WebGLImageConversion::kDataFormatRG8: |
| case WebGLImageConversion::kDataFormatRG8_S: |
| case WebGLImageConversion::kDataFormatRA8: |
| case WebGLImageConversion::kDataFormatAR8: |
| case WebGLImageConversion::kDataFormatRGBA5551: |
| case WebGLImageConversion::kDataFormatRGBA4444: |
| case WebGLImageConversion::kDataFormatRGB565: |
| case WebGLImageConversion::kDataFormatA16F: |
| case WebGLImageConversion::kDataFormatR16: |
| case WebGLImageConversion::kDataFormatR16_S: |
| case WebGLImageConversion::kDataFormatR16F: |
| case WebGLImageConversion::kDataFormatD16: |
| return 2; |
| case WebGLImageConversion::kDataFormatRGB8: |
| case WebGLImageConversion::kDataFormatRGB8_S: |
| case WebGLImageConversion::kDataFormatBGR8: |
| return 3; |
| case WebGLImageConversion::kDataFormatRGBA8: |
| case WebGLImageConversion::kDataFormatRGBA8_S: |
| case WebGLImageConversion::kDataFormatARGB8: |
| case WebGLImageConversion::kDataFormatABGR8: |
| case WebGLImageConversion::kDataFormatBGRA8: |
| case WebGLImageConversion::kDataFormatR32: |
| case WebGLImageConversion::kDataFormatR32_S: |
| case WebGLImageConversion::kDataFormatR32F: |
| case WebGLImageConversion::kDataFormatA32F: |
| case WebGLImageConversion::kDataFormatRA16F: |
| case WebGLImageConversion::kDataFormatRGBA2_10_10_10: |
| case WebGLImageConversion::kDataFormatRGB10F11F11F: |
| case WebGLImageConversion::kDataFormatRGB5999: |
| case WebGLImageConversion::kDataFormatRG16: |
| case WebGLImageConversion::kDataFormatRG16_S: |
| case WebGLImageConversion::kDataFormatRG16F: |
| case WebGLImageConversion::kDataFormatD32: |
| case WebGLImageConversion::kDataFormatD32F: |
| case WebGLImageConversion::kDataFormatDS24_8: |
| return 4; |
| case WebGLImageConversion::kDataFormatRGB16: |
| case WebGLImageConversion::kDataFormatRGB16_S: |
| case WebGLImageConversion::kDataFormatRGB16F: |
| return 6; |
| case WebGLImageConversion::kDataFormatRGBA16: |
| case WebGLImageConversion::kDataFormatRGBA16_S: |
| case WebGLImageConversion::kDataFormatRA32F: |
| case WebGLImageConversion::kDataFormatRGBA16F: |
| case WebGLImageConversion::kDataFormatRG32: |
| case WebGLImageConversion::kDataFormatRG32_S: |
| case WebGLImageConversion::kDataFormatRG32F: |
| return 8; |
| case WebGLImageConversion::kDataFormatRGB32: |
| case WebGLImageConversion::kDataFormatRGB32_S: |
| case WebGLImageConversion::kDataFormatRGB32F: |
| return 12; |
| case WebGLImageConversion::kDataFormatRGBA32: |
| case WebGLImageConversion::kDataFormatRGBA32_S: |
| case WebGLImageConversion::kDataFormatRGBA32F: |
| return 16; |
| default: |
| return 0; |
| } |
| } |
| |
| /* END CODE SHARED WITH MOZILLA FIREFOX */ |
| |
| class FormatConverter { |
| STACK_ALLOCATED(); |
| |
| public: |
| FormatConverter(const IntRect& source_data_sub_rectangle, |
| int depth, |
| int unpack_image_height, |
| const void* src_start, |
| void* dst_start, |
| int src_stride, |
| int src_row_offset, |
| int dst_stride) |
| : src_sub_rectangle_(source_data_sub_rectangle), |
| depth_(depth), |
| unpack_image_height_(unpack_image_height), |
| src_start_(src_start), |
| dst_start_(dst_start), |
| src_stride_(src_stride), |
| src_row_offset_(src_row_offset), |
| dst_stride_(dst_stride), |
| success_(false) { |
| const unsigned kMaxNumberOfComponents = 4; |
| const unsigned kMaxBytesPerComponent = 4; |
| unpacked_intermediate_src_data_ = WrapArrayUnique( |
| new uint8_t[src_sub_rectangle_.Width() * kMaxNumberOfComponents * |
| kMaxBytesPerComponent]); |
| DCHECK(unpacked_intermediate_src_data_.get()); |
| } |
| |
| void Convert(WebGLImageConversion::DataFormat src_format, |
| WebGLImageConversion::DataFormat dst_format, |
| WebGLImageConversion::AlphaOp); |
| bool Success() const { return success_; } |
| |
| private: |
| template <WebGLImageConversion::DataFormat SrcFormat> |
| void Convert(WebGLImageConversion::DataFormat dst_format, |
| WebGLImageConversion::AlphaOp); |
| |
| template <WebGLImageConversion::DataFormat SrcFormat, |
| WebGLImageConversion::DataFormat DstFormat> |
| void Convert(WebGLImageConversion::AlphaOp); |
| |
| template <WebGLImageConversion::DataFormat SrcFormat, |
| WebGLImageConversion::DataFormat DstFormat, |
| WebGLImageConversion::AlphaOp alphaOp> |
| void Convert(); |
| |
| const IntRect& src_sub_rectangle_; |
| const int depth_; |
| const int unpack_image_height_; |
| const void* const src_start_; |
| void* const dst_start_; |
| const int src_stride_, src_row_offset_, dst_stride_; |
| bool success_; |
| std::unique_ptr<uint8_t[]> unpacked_intermediate_src_data_; |
| }; |
| |
| void FormatConverter::Convert(WebGLImageConversion::DataFormat src_format, |
| WebGLImageConversion::DataFormat dst_format, |
| WebGLImageConversion::AlphaOp alpha_op) { |
| #define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \ |
| case SrcFormat: \ |
| return Convert<SrcFormat>(dst_format, alpha_op); |
| |
| switch (src_format) { |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRA8) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRA32F) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA8) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatARGB8) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatABGR8) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatAR8) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatBGRA8) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA5551) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA4444) |
| FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA32F) |
| FORMATCONVERTER_CASE_SRCFORMAT( |
| WebGLImageConversion::kDataFormatRGBA2_10_10_10) |
| default: |
| NOTREACHED(); |
| } |
| #undef FORMATCONVERTER_CASE_SRCFORMAT |
| } |
| |
| template <WebGLImageConversion::DataFormat SrcFormat> |
| void FormatConverter::Convert(WebGLImageConversion::DataFormat dst_format, |
| WebGLImageConversion::AlphaOp alpha_op) { |
| #define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \ |
| case DstFormat: \ |
| return Convert<SrcFormat, DstFormat>(alpha_op); |
| |
| switch (dst_format) { |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatR8) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatR16F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatR32F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatA8) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatA16F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatA32F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRA8) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRA16F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRA32F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB8) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB565) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB16F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGB32F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA8) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA5551) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA4444) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA16F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA32F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA8_S) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA16) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA16_S) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA32) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRGBA32_S) |
| FORMATCONVERTER_CASE_DSTFORMAT( |
| WebGLImageConversion::kDataFormatRGBA2_10_10_10) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRG8) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRG16F) |
| FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::kDataFormatRG32F) |
| default: |
| NOTREACHED(); |
| } |
| |
| #undef FORMATCONVERTER_CASE_DSTFORMAT |
| } |
| |
| template <WebGLImageConversion::DataFormat SrcFormat, |
| WebGLImageConversion::DataFormat DstFormat> |
| void FormatConverter::Convert(WebGLImageConversion::AlphaOp alpha_op) { |
| #define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \ |
| case alphaOp: \ |
| return Convert<SrcFormat, DstFormat, alphaOp>(); |
| |
| switch (alpha_op) { |
| FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::kAlphaDoNothing) |
| FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::kAlphaDoPremultiply) |
| FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::kAlphaDoUnmultiply) |
| default: |
| NOTREACHED(); |
| } |
| #undef FORMATCONVERTER_CASE_ALPHAOP |
| } |
| |
| template <int Format> |
| struct SupportsConversionFromDomElements { |
| STATIC_ONLY(SupportsConversionFromDomElements); |
| static const bool value = |
| Format == WebGLImageConversion::kDataFormatRGBA8 || |
| Format == WebGLImageConversion::kDataFormatRGB8 || |
| Format == WebGLImageConversion::kDataFormatRG8 || |
| Format == WebGLImageConversion::kDataFormatRA8 || |
| Format == WebGLImageConversion::kDataFormatR8 || |
| Format == WebGLImageConversion::kDataFormatRGBA32F || |
| Format == WebGLImageConversion::kDataFormatRGB32F || |
| Format == WebGLImageConversion::kDataFormatRG32F || |
| Format == WebGLImageConversion::kDataFormatRA32F || |
| Format == WebGLImageConversion::kDataFormatR32F || |
| Format == WebGLImageConversion::kDataFormatRGBA16F || |
| Format == WebGLImageConversion::kDataFormatRGB16F || |
| Format == WebGLImageConversion::kDataFormatRG16F || |
| Format == WebGLImageConversion::kDataFormatRA16F || |
| Format == WebGLImageConversion::kDataFormatR16F || |
| Format == WebGLImageConversion::kDataFormatRGBA5551 || |
| Format == WebGLImageConversion::kDataFormatRGBA4444 || |
| Format == WebGLImageConversion::kDataFormatRGB565 || |
| Format == WebGLImageConversion::kDataFormatRGBA2_10_10_10; |
| }; |
| |
| template <WebGLImageConversion::DataFormat SrcFormat, |
| WebGLImageConversion::DataFormat DstFormat, |
| WebGLImageConversion::AlphaOp alphaOp> |
| 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 == WebGLImageConversion::kAlphaDoNothing) { |
| NOTREACHED(); |
| return; |
| } |
| if (!IsFloatFormat<DstFormat>::value && IsFloatFormat<SrcFormat>::value) { |
| NOTREACHED(); |
| return; |
| } |
| |
| // Only textures uploaded from DOM elements or ImageData can allow DstFormat |
| // != SrcFormat. |
| const bool src_format_comes_from_dom_element_or_image_data = |
| WebGLImageConversion::SrcFormatComeFromDOMElementOrImageData(SrcFormat); |
| if (!src_format_comes_from_dom_element_or_image_data && |
| SrcFormat != DstFormat) { |
| NOTREACHED(); |
| return; |
| } |
| // Likewise, only textures uploaded from DOM elements or ImageData can |
| // possibly need to be unpremultiplied. |
| if (!src_format_comes_from_dom_element_or_image_data && |
| alphaOp == WebGLImageConversion::kAlphaDoUnmultiply) { |
| NOTREACHED(); |
| return; |
| } |
| if (src_format_comes_from_dom_element_or_image_data && |
| alphaOp == WebGLImageConversion::kAlphaDoUnmultiply && |
| !SupportsConversionFromDomElements<DstFormat>::value) { |
| NOTREACHED(); |
| return; |
| } |
| if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && |
| alphaOp != WebGLImageConversion::kAlphaDoNothing) { |
| NOTREACHED(); |
| 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 (src_format_comes_from_dom_element_or_image_data && |
| SrcFormat != DstFormat && |
| (DstFormat == WebGLImageConversion::kDataFormatRGB5999 || |
| DstFormat == WebGLImageConversion::kDataFormatRGB10F11F11F)) { |
| NOTREACHED(); |
| return; |
| } |
| |
| typedef typename DataTypeForFormat<SrcFormat>::Type SrcType; |
| typedef typename DataTypeForFormat<DstFormat>::Type DstType; |
| const int kIntermFormat = IntermediateFormat<DstFormat>::value; |
| typedef typename DataTypeForFormat<kIntermFormat>::Type IntermType; |
| const ptrdiff_t src_stride_in_elements = src_stride_ / sizeof(SrcType); |
| const ptrdiff_t dst_stride_in_elements = dst_stride_ / sizeof(DstType); |
| const bool kTrivialUnpack = SrcFormat == kIntermFormat; |
| const bool kTrivialPack = DstFormat == kIntermFormat && |
| alphaOp == WebGLImageConversion::kAlphaDoNothing; |
| DCHECK(!kTrivialUnpack || !kTrivialPack); |
| |
| const SrcType* src_row_start = |
| static_cast<const SrcType*>(static_cast<const void*>( |
| static_cast<const uint8_t*>(src_start_) + |
| ((src_stride_ * src_sub_rectangle_.Y()) + src_row_offset_))); |
| |
| // 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 (dst_stride_ < 0 && depth_ > 1) { |
| src_row_start -= |
| (depth_ - 1) * src_stride_in_elements * unpack_image_height_; |
| } |
| |
| DstType* dst_row_start = static_cast<DstType*>(dst_start_); |
| if (kTrivialUnpack) { |
| for (int d = 0; d < depth_; ++d) { |
| for (int i = 0; i < src_sub_rectangle_.Height(); ++i) { |
| Pack<DstFormat, alphaOp>(src_row_start, dst_row_start, |
| src_sub_rectangle_.Width()); |
| src_row_start += src_stride_in_elements; |
| dst_row_start += dst_stride_in_elements; |
| } |
| src_row_start += src_stride_in_elements * |
| (unpack_image_height_ - src_sub_rectangle_.Height()); |
| } |
| } else if (kTrivialPack) { |
| for (int d = 0; d < depth_; ++d) { |
| for (int i = 0; i < src_sub_rectangle_.Height(); ++i) { |
| Unpack<SrcFormat>(src_row_start, dst_row_start, |
| src_sub_rectangle_.Width()); |
| src_row_start += src_stride_in_elements; |
| dst_row_start += dst_stride_in_elements; |
| } |
| src_row_start += src_stride_in_elements * |
| (unpack_image_height_ - src_sub_rectangle_.Height()); |
| } |
| } else { |
| for (int d = 0; d < depth_; ++d) { |
| for (int i = 0; i < src_sub_rectangle_.Height(); ++i) { |
| Unpack<SrcFormat>(src_row_start, |
| reinterpret_cast<IntermType*>( |
| unpacked_intermediate_src_data_.get()), |
| src_sub_rectangle_.Width()); |
| Pack<DstFormat, alphaOp>(reinterpret_cast<IntermType*>( |
| unpacked_intermediate_src_data_.get()), |
| dst_row_start, src_sub_rectangle_.Width()); |
| src_row_start += src_stride_in_elements; |
| dst_row_start += dst_stride_in_elements; |
| } |
| src_row_start += src_stride_in_elements * |
| (unpack_image_height_ - src_sub_rectangle_.Height()); |
| } |
| } |
| success_ = true; |
| return; |
| } |
| |
| bool FrameIsValid(const SkBitmap& frame_bitmap) { |
| return !frame_bitmap.isNull() && !frame_bitmap.empty() && |
| frame_bitmap.colorType() == kN32_SkColorType; |
| } |
| |
| } // anonymous namespace |
| |
| WebGLImageConversion::PixelStoreParams::PixelStoreParams() |
| : alignment(4), |
| row_length(0), |
| image_height(0), |
| skip_pixels(0), |
| skip_rows(0), |
| skip_images(0) {} |
| |
| bool WebGLImageConversion::ComputeFormatAndTypeParameters( |
| GLenum format, |
| GLenum type, |
| unsigned* components_per_pixel, |
| unsigned* bytes_per_component) { |
| switch (format) { |
| case GL_ALPHA: |
| case GL_LUMINANCE: |
| case GL_RED: |
| case GL_RED_INTEGER: |
| case GL_DEPTH_COMPONENT: |
| case GL_DEPTH_STENCIL: // Treat it as one component. |
| *components_per_pixel = 1; |
| break; |
| case GL_LUMINANCE_ALPHA: |
| case GL_RG: |
| case GL_RG_INTEGER: |
| *components_per_pixel = 2; |
| break; |
| case GL_RGB: |
| case GL_RGB_INTEGER: |
| case GL_SRGB_EXT: // GL_EXT_sRGB |
| *components_per_pixel = 3; |
| break; |
| case GL_RGBA: |
| case GL_RGBA_INTEGER: |
| case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888 |
| case GL_SRGB_ALPHA_EXT: // GL_EXT_sRGB |
| *components_per_pixel = 4; |
| break; |
| default: |
| return false; |
| } |
| switch (type) { |
| case GL_BYTE: |
| *bytes_per_component = sizeof(GLbyte); |
| break; |
| case GL_UNSIGNED_BYTE: |
| *bytes_per_component = sizeof(GLubyte); |
| break; |
| case GL_SHORT: |
| *bytes_per_component = sizeof(GLshort); |
| break; |
| case GL_UNSIGNED_SHORT: |
| *bytes_per_component = sizeof(GLushort); |
| break; |
| case GL_UNSIGNED_SHORT_5_6_5: |
| case GL_UNSIGNED_SHORT_4_4_4_4: |
| case GL_UNSIGNED_SHORT_5_5_5_1: |
| *components_per_pixel = 1; |
| *bytes_per_component = sizeof(GLushort); |
| break; |
| case GL_INT: |
| *bytes_per_component = sizeof(GLint); |
| break; |
| case GL_UNSIGNED_INT: |
| *bytes_per_component = sizeof(GLuint); |
| break; |
| case GL_UNSIGNED_INT_24_8_OES: |
| case GL_UNSIGNED_INT_10F_11F_11F_REV: |
| case GL_UNSIGNED_INT_5_9_9_9_REV: |
| case GL_UNSIGNED_INT_2_10_10_10_REV: |
| *components_per_pixel = 1; |
| *bytes_per_component = sizeof(GLuint); |
| break; |
| case GL_FLOAT: // OES_texture_float |
| *bytes_per_component = sizeof(GLfloat); |
| break; |
| case GL_HALF_FLOAT: |
| case GL_HALF_FLOAT_OES: // OES_texture_half_float |
| *bytes_per_component = sizeof(GLushort); |
| break; |
| default: |
| return false; |
| } |
| return true; |
| } |
| |
| GLenum WebGLImageConversion::ComputeImageSizeInBytes( |
| GLenum format, |
| GLenum type, |
| GLsizei width, |
| GLsizei height, |
| GLsizei depth, |
| const PixelStoreParams& params, |
| unsigned* image_size_in_bytes, |
| unsigned* padding_in_bytes, |
| unsigned* skip_size_in_bytes) { |
| DCHECK(image_size_in_bytes); |
| DCHECK(params.alignment == 1 || params.alignment == 2 || |
| params.alignment == 4 || params.alignment == 8); |
| DCHECK_GE(params.row_length, 0); |
| DCHECK_GE(params.image_height, 0); |
| DCHECK_GE(params.skip_pixels, 0); |
| DCHECK_GE(params.skip_rows, 0); |
| DCHECK_GE(params.skip_images, 0); |
| if (width < 0 || height < 0 || depth < 0) |
| return GL_INVALID_VALUE; |
| if (!width || !height || !depth) { |
| *image_size_in_bytes = 0; |
| if (padding_in_bytes) |
| *padding_in_bytes = 0; |
| if (skip_size_in_bytes) |
| *skip_size_in_bytes = 0; |
| return GL_NO_ERROR; |
| } |
| |
| int row_length = params.row_length > 0 ? params.row_length : width; |
| int image_height = params.image_height > 0 ? params.image_height : height; |
| |
| unsigned bytes_per_component, components_per_pixel; |
| if (!ComputeFormatAndTypeParameters(format, type, &bytes_per_component, |
| &components_per_pixel)) |
| return GL_INVALID_ENUM; |
| unsigned bytes_per_group = bytes_per_component * components_per_pixel; |
| CheckedNumeric<uint32_t> checked_value = static_cast<uint32_t>(row_length); |
| checked_value *= bytes_per_group; |
| if (!checked_value.IsValid()) |
| return GL_INVALID_VALUE; |
| |
| unsigned last_row_size; |
| if (params.row_length > 0 && params.row_length != width) { |
| CheckedNumeric<uint32_t> tmp = width; |
| tmp *= bytes_per_group; |
| if (!tmp.IsValid()) |
| return GL_INVALID_VALUE; |
| last_row_size = tmp.ValueOrDie(); |
| } else { |
| last_row_size = checked_value.ValueOrDie(); |
| } |
| |
| unsigned padding = 0; |
| CheckedNumeric<uint32_t> checked_residual = checked_value % params.alignment; |
| if (!checked_residual.IsValid()) { |
| return GL_INVALID_VALUE; |
| } |
| unsigned residual = checked_residual.ValueOrDie(); |
| if (residual) { |
| padding = params.alignment - residual; |
| checked_value += padding; |
| } |
| if (!checked_value.IsValid()) |
| return GL_INVALID_VALUE; |
| unsigned padded_row_size = checked_value.ValueOrDie(); |
| |
| CheckedNumeric<uint32_t> rows = image_height; |
| rows *= (depth - 1); |
| // Last image is not affected by IMAGE_HEIGHT parameter. |
| rows += height; |
| if (!rows.IsValid()) |
| return GL_INVALID_VALUE; |
| checked_value *= (rows - 1); |
| // Last row is not affected by ROW_LENGTH parameter. |
| checked_value += last_row_size; |
| if (!checked_value.IsValid()) |
| return GL_INVALID_VALUE; |
| *image_size_in_bytes = checked_value.ValueOrDie(); |
| if (padding_in_bytes) |
| *padding_in_bytes = padding; |
| |
| CheckedNumeric<uint32_t> skip_size = 0; |
| if (params.skip_images > 0) { |
| CheckedNumeric<uint32_t> tmp = padded_row_size; |
| tmp *= image_height; |
| tmp *= params.skip_images; |
| if (!tmp.IsValid()) |
| return GL_INVALID_VALUE; |
| skip_size += tmp.ValueOrDie(); |
| } |
| if (params.skip_rows > 0) { |
| CheckedNumeric<uint32_t> tmp = padded_row_size; |
| tmp *= params.skip_rows; |
| if (!tmp.IsValid()) |
| return GL_INVALID_VALUE; |
| skip_size += tmp.ValueOrDie(); |
| } |
| if (params.skip_pixels > 0) { |
| CheckedNumeric<uint32_t> tmp = bytes_per_group; |
| tmp *= params.skip_pixels; |
| if (!tmp.IsValid()) |
| return GL_INVALID_VALUE; |
| skip_size += tmp.ValueOrDie(); |
| } |
| if (!skip_size.IsValid()) |
| return GL_INVALID_VALUE; |
| if (skip_size_in_bytes) |
| *skip_size_in_bytes = skip_size.ValueOrDie(); |
| |
| checked_value += skip_size.ValueOrDie(); |
| if (!checked_value.IsValid()) |
| return GL_INVALID_VALUE; |
| return GL_NO_ERROR; |
| } |
| |
| WebGLImageConversion::ImageExtractor::ImageExtractor( |
| Image* image, |
| ImageHtmlDomSource image_html_dom_source, |
| bool premultiply_alpha, |
| bool ignore_color_space) { |
| image_ = image; |
| image_html_dom_source_ = image_html_dom_source; |
| ExtractImage(premultiply_alpha, ignore_color_space); |
| } |
| |
| void WebGLImageConversion::ImageExtractor::ExtractImage( |
| bool premultiply_alpha, |
| bool ignore_color_space) { |
| DCHECK(!image_pixel_locker_); |
| |
| if (!image_) |
| return; |
| |
| sk_sp<SkImage> skia_image = image_->PaintImageForCurrentFrame().GetSkImage(); |
| SkImageInfo info = |
| skia_image ? SkImageInfo::MakeN32Premul(image_->width(), image_->height()) |
| : SkImageInfo::MakeUnknown(); |
| alpha_op_ = kAlphaDoNothing; |
| bool has_alpha = skia_image ? !skia_image->isOpaque() : true; |
| |
| if ((!skia_image || ignore_color_space || |
| (has_alpha && !premultiply_alpha)) && |
| image_->Data()) { |
| // Attempt to get raw unpremultiplied image data. |
| std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create( |
| image_->Data(), true, ImageDecoder::kAlphaNotPremultiplied, |
| ignore_color_space ? ColorBehavior::Ignore() |
| : ColorBehavior::TransformToSRGB())); |
| if (!decoder || !decoder->FrameCount()) |
| return; |
| ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); |
| if (!frame || frame->GetStatus() != ImageFrame::kFrameComplete) |
| return; |
| has_alpha = frame->HasAlpha(); |
| SkBitmap bitmap = frame->Bitmap(); |
| if (!FrameIsValid(bitmap)) |
| return; |
| |
| // TODO(fmalita): Partial frames are not supported currently: only fully |
| // decoded frames make it through. We could potentially relax this and |
| // use SkImage::MakeFromBitmap(bitmap) to make a copy. |
| skia_image = frame->FinalizePixelsAndGetImage(); |
| info = bitmap.info(); |
| |
| if (has_alpha && premultiply_alpha) |
| alpha_op_ = kAlphaDoPremultiply; |
| } else if (!premultiply_alpha && has_alpha) { |
| // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha |
| // had been applied and the alpha value for each pixel is 0xFF. This is |
| // true at present; if it is changed in the future it will need |
| // adjustment accordingly. |
| // 2. For texImage2D with HTMLCanvasElement input in which alpha is already |
| // premultiplied in this port, do AlphaDoUnmultiply if |
| // UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false. |
| if (image_html_dom_source_ != kHtmlDomVideo) |
| alpha_op_ = kAlphaDoUnmultiply; |
| } |
| |
| if (!skia_image) |
| return; |
| |
| image_source_format_ = SK_B32_SHIFT ? kDataFormatRGBA8 : kDataFormatBGRA8; |
| image_source_unpack_alignment_ = |
| 0; // FIXME: this seems to always be zero - why use at all? |
| |
| DCHECK(skia_image->width()); |
| DCHECK(skia_image->height()); |
| image_width_ = skia_image->width(); |
| image_height_ = skia_image->height(); |
| |
| // Fail if the image was downsampled because of memory limits. |
| if (image_width_ != (unsigned)image_->width() || |
| image_height_ != (unsigned)image_->height()) |
| return; |
| |
| image_pixel_locker_.emplace(std::move(skia_image), info.alphaType(), |
| kN32_SkColorType); |
| } |
| |
| unsigned WebGLImageConversion::GetChannelBitsByFormat(GLenum format) { |
| switch (format) { |
| case GL_ALPHA: |
| return kChannelAlpha; |
| case GL_RED: |
| case GL_RED_INTEGER: |
| case GL_R8: |
| case GL_R8_SNORM: |
| case GL_R8UI: |
| case GL_R8I: |
| case GL_R16UI: |
| case GL_R16I: |
| case GL_R32UI: |
| case GL_R32I: |
| case GL_R16F: |
| case GL_R32F: |
| return kChannelRed; |
| case GL_RG: |
| case GL_RG_INTEGER: |
| case GL_RG8: |
| case GL_RG8_SNORM: |
| case GL_RG8UI: |
| case GL_RG8I: |
| case GL_RG16UI: |
| case GL_RG16I: |
| case GL_RG32UI: |
| case GL_RG32I: |
| case GL_RG16F: |
| case GL_RG32F: |
| return kChannelRG; |
| case GL_LUMINANCE: |
| return kChannelRGB; |
| case GL_LUMINANCE_ALPHA: |
| return kChannelRGBA; |
| case GL_RGB: |
| case GL_RGB_INTEGER: |
| case GL_RGB8: |
| case GL_RGB8_SNORM: |
| case GL_RGB8UI: |
| case GL_RGB8I: |
| case GL_RGB16UI: |
| case GL_RGB16I: |
| case GL_RGB32UI: |
| case GL_RGB32I: |
| case GL_RGB16F: |
| case GL_RGB32F: |
| case GL_RGB565: |
| case GL_R11F_G11F_B10F: |
| case GL_RGB9_E5: |
| case GL_SRGB_EXT: |
| case GL_SRGB8: |
| return kChannelRGB; |
| case GL_RGBA: |
| case GL_RGBA_INTEGER: |
| case GL_RGBA8: |
| case GL_RGBA8_SNORM: |
| case GL_RGBA8UI: |
| case GL_RGBA8I: |
| case GL_RGBA16UI: |
| case GL_RGBA16I: |
| case GL_RGBA32UI: |
| case GL_RGBA32I: |
| case GL_RGBA16F: |
| case GL_RGBA32F: |
| case GL_RGBA4: |
| case GL_RGB5_A1: |
| case GL_RGB10_A2: |
| case GL_RGB10_A2UI: |
| case GL_SRGB_ALPHA_EXT: |
| case GL_SRGB8_ALPHA8: |
| return kChannelRGBA; |
| case GL_DEPTH_COMPONENT: |
| case GL_DEPTH_COMPONENT16: |
| case GL_DEPTH_COMPONENT24: |
| case GL_DEPTH_COMPONENT32F: |
| return kChannelDepth; |
| case GL_STENCIL: |
| case GL_STENCIL_INDEX8: |
| return kChannelStencil; |
| case GL_DEPTH_STENCIL: |
| case GL_DEPTH24_STENCIL8: |
| case GL_DEPTH32F_STENCIL8: |
| return kChannelDepthStencil; |
| default: |
| return 0; |
| } |
| } |
| |
| bool WebGLImageConversion::PackImageData( |
| Image* image, |
| const void* pixels, |
| GLenum format, |
| GLenum type, |
| bool flip_y, |
| AlphaOp alpha_op, |
| DataFormat source_format, |
| unsigned source_image_width, |
| unsigned source_image_height, |
| const IntRect& source_image_sub_rectangle, |
| int depth, |
| unsigned source_unpack_alignment, |
| int unpack_image_height, |
| Vector<uint8_t>& data) { |
| if (!pixels) |
| return false; |
| |
| unsigned packed_size; |
| // Output data is tightly packed (alignment == 1). |
| PixelStoreParams params; |
| params.alignment = 1; |
| if (ComputeImageSizeInBytes(format, type, source_image_sub_rectangle.Width(), |
| source_image_sub_rectangle.Height(), depth, |
| params, &packed_size, nullptr, |
| nullptr) != GL_NO_ERROR) |
| return false; |
| data.resize(packed_size); |
| |
| return PackPixels(reinterpret_cast<const uint8_t*>(pixels), source_format, |
| source_image_width, source_image_height, |
| source_image_sub_rectangle, depth, source_unpack_alignment, |
| unpack_image_height, format, type, alpha_op, data.data(), |
| flip_y); |
| } |
| |
| bool WebGLImageConversion::ExtractImageData( |
| const uint8_t* image_data, |
| DataFormat source_data_format, |
| const IntSize& image_data_size, |
| const IntRect& source_image_sub_rectangle, |
| int depth, |
| int unpack_image_height, |
| GLenum format, |
| GLenum type, |
| bool flip_y, |
| bool premultiply_alpha, |
| Vector<uint8_t>& data) { |
| if (!image_data) |
| return false; |
| int width = image_data_size.Width(); |
| int height = image_data_size.Height(); |
| |
| unsigned packed_size; |
| // Output data is tightly packed (alignment == 1). |
| PixelStoreParams params; |
| params.alignment = 1; |
| if (ComputeImageSizeInBytes(format, type, source_image_sub_rectangle.Width(), |
| source_image_sub_rectangle.Height(), depth, |
| params, &packed_size, nullptr, |
| nullptr) != GL_NO_ERROR) |
| return false; |
| data.resize(packed_size); |
| |
| if (!PackPixels(image_data, source_data_format, width, height, |
| source_image_sub_rectangle, depth, 0, unpack_image_height, |
| format, type, |
| premultiply_alpha ? kAlphaDoPremultiply : kAlphaDoNothing, |
| data.data(), flip_y)) |
| return false; |
| |
| return true; |
| } |
| |
| bool WebGLImageConversion::ExtractTextureData( |
| unsigned width, |
| unsigned height, |
| GLenum format, |
| GLenum type, |
| const PixelStoreParams& unpack_params, |
| bool flip_y, |
| bool premultiply_alpha, |
| const void* pixels, |
| Vector<uint8_t>& data) { |
| // Assumes format, type, etc. have already been validated. |
| DataFormat source_data_format = GetDataFormat(format, type); |
| if (source_data_format == kDataFormatNumFormats) |
| return false; |
| |
| // Resize the output buffer. |
| unsigned int components_per_pixel, bytes_per_component; |
| if (!ComputeFormatAndTypeParameters(format, type, &components_per_pixel, |
| &bytes_per_component)) |
| return false; |
| unsigned bytes_per_pixel = components_per_pixel * bytes_per_component; |
| data.resize(width * height * bytes_per_pixel); |
| |
| unsigned image_size_in_bytes, skip_size_in_bytes; |
| ComputeImageSizeInBytes(format, type, width, height, 1, unpack_params, |
| &image_size_in_bytes, nullptr, &skip_size_in_bytes); |
| const uint8_t* src_data = static_cast<const uint8_t*>(pixels); |
| if (skip_size_in_bytes) { |
| src_data += skip_size_in_bytes; |
| } |
| |
| if (!PackPixels(src_data, source_data_format, |
| unpack_params.row_length ? unpack_params.row_length : width, |
| height, IntRect(0, 0, width, height), 1, |
| unpack_params.alignment, 0, format, type, |
| (premultiply_alpha ? kAlphaDoPremultiply : kAlphaDoNothing), |
| data.data(), flip_y)) |
| return false; |
| |
| return true; |
| } |
| |
| bool WebGLImageConversion::PackPixels(const uint8_t* source_data, |
| DataFormat source_data_format, |
| unsigned source_data_width, |
| unsigned source_data_height, |
| const IntRect& source_data_sub_rectangle, |
| int depth, |
| unsigned source_unpack_alignment, |
| int unpack_image_height, |
| unsigned destination_format, |
| unsigned destination_type, |
| AlphaOp alpha_op, |
| void* destination_data, |
| bool flip_y) { |
| DCHECK_GE(depth, 1); |
| if (unpack_image_height == 0) { |
| unpack_image_height = source_data_sub_rectangle.Height(); |
| } |
| int valid_src = source_data_width * TexelBytesForFormat(source_data_format); |
| int remainder = |
| source_unpack_alignment ? (valid_src % source_unpack_alignment) : 0; |
| int src_stride = |
| remainder ? (valid_src + source_unpack_alignment - remainder) : valid_src; |
| int src_row_offset = |
| source_data_sub_rectangle.X() * TexelBytesForFormat(source_data_format); |
| |
| DataFormat dst_data_format = |
| GetDataFormat(destination_format, destination_type); |
| if (dst_data_format == kDataFormatNumFormats) |
| return false; |
| int dst_stride = |
| source_data_sub_rectangle.Width() * TexelBytesForFormat(dst_data_format); |
| if (flip_y) { |
| destination_data = |
| static_cast<uint8_t*>(destination_data) + |
| dst_stride * ((depth * source_data_sub_rectangle.Height()) - 1); |
| dst_stride = -dst_stride; |
| } |
| if (!HasAlpha(source_data_format) || !HasColor(source_data_format) || |
| !HasColor(dst_data_format)) |
| alpha_op = kAlphaDoNothing; |
| |
| if (source_data_format == dst_data_format && alpha_op == kAlphaDoNothing) { |
| const uint8_t* base_ptr = |
| source_data + src_stride * source_data_sub_rectangle.Y(); |
| const uint8_t* base_end = |
| source_data + src_stride * source_data_sub_rectangle.MaxY(); |
| |
| // 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 (flip_y && depth > 1) { |
| const ptrdiff_t distance_to_top_image = |
| (depth - 1) * src_stride * unpack_image_height; |
| base_ptr -= distance_to_top_image; |
| base_end -= distance_to_top_image; |
| } |
| |
| unsigned row_size = (dst_stride > 0) ? dst_stride : -dst_stride; |
| uint8_t* dst = static_cast<uint8_t*>(destination_data); |
| |
| for (int i = 0; i < depth; ++i) { |
| const uint8_t* ptr = base_ptr; |
| const uint8_t* ptr_end = base_end; |
| while (ptr < ptr_end) { |
| memcpy(dst, ptr + src_row_offset, row_size); |
| ptr += src_stride; |
| dst += dst_stride; |
| } |
| base_ptr += unpack_image_height * src_stride; |
| base_end += unpack_image_height * src_stride; |
| } |
| return true; |
| } |
| |
| FormatConverter converter(source_data_sub_rectangle, depth, |
| unpack_image_height, source_data, destination_data, |
| src_stride, src_row_offset, dst_stride); |
| converter.Convert(source_data_format, dst_data_format, alpha_op); |
| if (!converter.Success()) |
| return false; |
| return true; |
| } |
| |
| void WebGLImageConversion::UnpackPixels(const uint16_t* source_data, |
| DataFormat source_data_format, |
| unsigned pixels_per_row, |
| uint8_t* destination_data) { |
| switch (source_data_format) { |
| case kDataFormatRGBA4444: { |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA4444>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| Unpack<WebGLImageConversion::kDataFormatRGBA4444>( |
| src_row_start, destination_data, pixels_per_row); |
| } break; |
| case kDataFormatRGBA5551: { |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA5551>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| Unpack<WebGLImageConversion::kDataFormatRGBA5551>( |
| src_row_start, destination_data, pixels_per_row); |
| } break; |
| case kDataFormatBGRA8: { |
| const uint8_t* psrc = (const uint8_t*)source_data; |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatBGRA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(psrc); |
| Unpack<WebGLImageConversion::kDataFormatBGRA8>( |
| src_row_start, destination_data, pixels_per_row); |
| } break; |
| default: |
| break; |
| } |
| } |
| |
| void WebGLImageConversion::PackPixels(const uint8_t* source_data, |
| DataFormat source_data_format, |
| unsigned pixels_per_row, |
| uint8_t* destination_data) { |
| switch (source_data_format) { |
| case kDataFormatRA8: { |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| Pack<WebGLImageConversion::kDataFormatRA8, |
| WebGLImageConversion::kAlphaDoUnmultiply>( |
| src_row_start, destination_data, pixels_per_row); |
| } break; |
| case kDataFormatR8: { |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| Pack<WebGLImageConversion::kDataFormatR8, |
| WebGLImageConversion::kAlphaDoUnmultiply>( |
| src_row_start, destination_data, pixels_per_row); |
| } break; |
| case kDataFormatRGBA8: { |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| Pack<WebGLImageConversion::kDataFormatRGBA8, |
| WebGLImageConversion::kAlphaDoUnmultiply>( |
| src_row_start, destination_data, pixels_per_row); |
| } break; |
| case kDataFormatRGBA4444: { |
| uint16_t* pdst = (uint16_t*)destination_data; |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA4444>::Type DstType; |
| DstType* dst_row_start = static_cast<DstType*>(pdst); |
| Pack<WebGLImageConversion::kDataFormatRGBA4444, |
| WebGLImageConversion::kAlphaDoNothing>(src_row_start, dst_row_start, |
| pixels_per_row); |
| } break; |
| case kDataFormatRGBA5551: { |
| uint16_t* pdst = (uint16_t*)destination_data; |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA5551>::Type DstType; |
| DstType* dst_row_start = static_cast<DstType*>(pdst); |
| Pack<WebGLImageConversion::kDataFormatRGBA5551, |
| WebGLImageConversion::kAlphaDoNothing>(src_row_start, dst_row_start, |
| pixels_per_row); |
| } break; |
| case kDataFormatRGB565: { |
| uint16_t* pdst = (uint16_t*)destination_data; |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGBA8>::Type SrcType; |
| const SrcType* src_row_start = static_cast<const SrcType*>(source_data); |
| typedef typename DataTypeForFormat< |
| WebGLImageConversion::kDataFormatRGB565>::Type DstType; |
| DstType* dst_row_start = static_cast<DstType*>(pdst); |
| Pack<WebGLImageConversion::kDataFormatRGB565, |
| WebGLImageConversion::kAlphaDoNothing>(src_row_start, dst_row_start, |
| pixels_per_row); |
| } break; |
| default: |
| break; |
| } |
| } |
| |
| } // namespace blink |