1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "config.h" 6#include "platform/graphics/gpu/WebGLImageConversion.h" 7 8#include "platform/CheckedInt.h" 9#include "platform/graphics/ImageObserver.h" 10#include "platform/graphics/cpu/arm/WebGLImageConversionNEON.h" 11#include "platform/image-decoders/ImageDecoder.h" 12#include "wtf/OwnPtr.h" 13#include "wtf/PassOwnPtr.h" 14 15namespace blink { 16 17namespace { 18 19WebGLImageConversion::DataFormat getDataFormat(GLenum destinationFormat, GLenum destinationType) 20{ 21 WebGLImageConversion::DataFormat dstFormat = WebGLImageConversion::DataFormatRGBA8; 22 switch (destinationType) { 23 case GL_UNSIGNED_BYTE: 24 switch (destinationFormat) { 25 case GL_RGB: 26 dstFormat = WebGLImageConversion::DataFormatRGB8; 27 break; 28 case GL_RGBA: 29 dstFormat = WebGLImageConversion::DataFormatRGBA8; 30 break; 31 case GL_ALPHA: 32 dstFormat = WebGLImageConversion::DataFormatA8; 33 break; 34 case GL_LUMINANCE: 35 dstFormat = WebGLImageConversion::DataFormatR8; 36 break; 37 case GL_LUMINANCE_ALPHA: 38 dstFormat = WebGLImageConversion::DataFormatRA8; 39 break; 40 default: 41 ASSERT_NOT_REACHED(); 42 } 43 break; 44 case GL_UNSIGNED_SHORT_4_4_4_4: 45 dstFormat = WebGLImageConversion::DataFormatRGBA4444; 46 break; 47 case GL_UNSIGNED_SHORT_5_5_5_1: 48 dstFormat = WebGLImageConversion::DataFormatRGBA5551; 49 break; 50 case GL_UNSIGNED_SHORT_5_6_5: 51 dstFormat = WebGLImageConversion::DataFormatRGB565; 52 break; 53 case GL_HALF_FLOAT_OES: // OES_texture_half_float 54 switch (destinationFormat) { 55 case GL_RGB: 56 dstFormat = WebGLImageConversion::DataFormatRGB16F; 57 break; 58 case GL_RGBA: 59 dstFormat = WebGLImageConversion::DataFormatRGBA16F; 60 break; 61 case GL_ALPHA: 62 dstFormat = WebGLImageConversion::DataFormatA16F; 63 break; 64 case GL_LUMINANCE: 65 dstFormat = WebGLImageConversion::DataFormatR16F; 66 break; 67 case GL_LUMINANCE_ALPHA: 68 dstFormat = WebGLImageConversion::DataFormatRA16F; 69 break; 70 default: 71 ASSERT_NOT_REACHED(); 72 } 73 break; 74 case GL_FLOAT: // OES_texture_float 75 switch (destinationFormat) { 76 case GL_RGB: 77 dstFormat = WebGLImageConversion::DataFormatRGB32F; 78 break; 79 case GL_RGBA: 80 dstFormat = WebGLImageConversion::DataFormatRGBA32F; 81 break; 82 case GL_ALPHA: 83 dstFormat = WebGLImageConversion::DataFormatA32F; 84 break; 85 case GL_LUMINANCE: 86 dstFormat = WebGLImageConversion::DataFormatR32F; 87 break; 88 case GL_LUMINANCE_ALPHA: 89 dstFormat = WebGLImageConversion::DataFormatRA32F; 90 break; 91 default: 92 ASSERT_NOT_REACHED(); 93 } 94 break; 95 default: 96 ASSERT_NOT_REACHED(); 97 } 98 return dstFormat; 99} 100 101// Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf, 102// "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010). 103// Specially, the basetable[512] and shifttable[512] are generated as follows: 104/* 105unsigned short basetable[512]; 106unsigned char shifttable[512]; 107 108void generatetables(){ 109 unsigned int i; 110 int e; 111 for (i = 0; i < 256; ++i){ 112 e = i - 127; 113 if (e < -24){ // Very small numbers map to zero 114 basetable[i | 0x000] = 0x0000; 115 basetable[i | 0x100] = 0x8000; 116 shifttable[i | 0x000] = 24; 117 shifttable[i | 0x100] = 24; 118 } 119 else if (e < -14) { // Small numbers map to denorms 120 basetable[i | 0x000] = (0x0400>>(-e-14)); 121 basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000; 122 shifttable[i | 0x000] = -e-1; 123 shifttable[i | 0x100] = -e-1; 124 } 125 else if (e <= 15){ // Normal numbers just lose precision 126 basetable[i | 0x000] = ((e+15)<<10); 127 basetable[i| 0x100] = ((e+15)<<10) | 0x8000; 128 shifttable[i|0x000] = 13; 129 shifttable[i|0x100] = 13; 130 } 131 else if (e<128){ // Large numbers map to Infinity 132 basetable[i|0x000] = 0x7C00; 133 basetable[i|0x100] = 0xFC00; 134 shifttable[i|0x000] = 24; 135 shifttable[i|0x100] = 24; 136 } 137 else { // Infinity and NaN's stay Infinity and NaN's 138 basetable[i|0x000] = 0x7C00; 139 basetable[i|0x100] = 0xFC00; 140 shifttable[i|0x000] = 13; 141 shifttable[i|0x100] = 13; 142 } 143 } 144} 145*/ 146 147unsigned short baseTable[512] = { 1480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1540, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 155512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 15616384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744, 15731744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 15831744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 15931744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 16031744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 16131744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 16231744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 16331744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 16432768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 16532768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 16632768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 16732768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 16832768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 16932768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 17032768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776, 32784, 32800, 32832, 32896, 33024, 17133280, 33792, 34816, 35840, 36864, 37888, 38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, 17249152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416, 61440, 62464, 63488, 64512, 17364512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 17464512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 17564512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 17664512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 17764512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 17864512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 17964512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512 180}; 181 182unsigned char shiftTable[512] = { 18324, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 18424, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 18524, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 18624, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 18724, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 18824, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 18924, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 19014, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 19113, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 19224, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19324, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19424, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19524, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19624, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19724, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19824, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13, 19924, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20024, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20124, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20224, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20324, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20424, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20524, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 20614, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 20713, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 20824, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 20924, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21024, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21124, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21224, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21324, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21424, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 215}; 216 217unsigned short convertFloatToHalfFloat(float f) 218{ 219 unsigned temp = *(reinterpret_cast<unsigned *>(&f)); 220 unsigned signexp = (temp >> 23) & 0x1ff; 221 return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]); 222} 223 224/* BEGIN CODE SHARED WITH MOZILLA FIREFOX */ 225 226// The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup. 227// Explicit template specializations correspond to the cases that would occur. 228// Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h 229 230//---------------------------------------------------------------------- 231// Pixel unpacking routines. 232template<int format, typename SourceType, typename DstType> 233void unpack(const SourceType*, DstType*, unsigned) 234{ 235 ASSERT_NOT_REACHED(); 236} 237 238template<> void unpack<WebGLImageConversion::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 239{ 240 for (unsigned i = 0; i < pixelsPerRow; ++i) { 241 destination[0] = source[0]; 242 destination[1] = source[1]; 243 destination[2] = source[2]; 244 destination[3] = 0xFF; 245 source += 3; 246 destination += 4; 247 } 248} 249 250template<> void unpack<WebGLImageConversion::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 251{ 252 for (unsigned i = 0; i < pixelsPerRow; ++i) { 253 destination[0] = source[2]; 254 destination[1] = source[1]; 255 destination[2] = source[0]; 256 destination[3] = 0xFF; 257 source += 3; 258 destination += 4; 259 } 260} 261 262template<> void unpack<WebGLImageConversion::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 263{ 264 for (unsigned i = 0; i < pixelsPerRow; ++i) { 265 destination[0] = source[1]; 266 destination[1] = source[2]; 267 destination[2] = source[3]; 268 destination[3] = source[0]; 269 source += 4; 270 destination += 4; 271 } 272} 273 274template<> void unpack<WebGLImageConversion::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 275{ 276 for (unsigned i = 0; i < pixelsPerRow; ++i) { 277 destination[0] = source[3]; 278 destination[1] = source[2]; 279 destination[2] = source[1]; 280 destination[3] = source[0]; 281 source += 4; 282 destination += 4; 283 } 284} 285 286template<> void unpack<WebGLImageConversion::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 287{ 288 const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source); 289 uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination); 290 for (unsigned i = 0; i < pixelsPerRow; ++i) { 291 uint32_t bgra = source32[i]; 292#if CPU(BIG_ENDIAN) 293 uint32_t brMask = 0xff00ff00; 294 uint32_t gaMask = 0x00ff00ff; 295#else 296 uint32_t brMask = 0x00ff00ff; 297 uint32_t gaMask = 0xff00ff00; 298#endif 299 uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask); 300 destination32[i] = rgba; 301 } 302} 303 304template<> void unpack<WebGLImageConversion::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 305{ 306#if HAVE(ARM_NEON_INTRINSICS) 307 SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow); 308#endif 309 for (unsigned i = 0; i < pixelsPerRow; ++i) { 310 uint16_t packedValue = source[0]; 311 uint8_t r = packedValue >> 11; 312 uint8_t g = (packedValue >> 6) & 0x1F; 313 uint8_t b = (packedValue >> 1) & 0x1F; 314 destination[0] = (r << 3) | (r & 0x7); 315 destination[1] = (g << 3) | (g & 0x7); 316 destination[2] = (b << 3) | (b & 0x7); 317 destination[3] = (packedValue & 0x1) ? 0xFF : 0x0; 318 source += 1; 319 destination += 4; 320 } 321} 322 323template<> void unpack<WebGLImageConversion::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 324{ 325#if HAVE(ARM_NEON_INTRINSICS) 326 SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow); 327#endif 328 for (unsigned i = 0; i < pixelsPerRow; ++i) { 329 uint16_t packedValue = source[0]; 330 uint8_t r = packedValue >> 12; 331 uint8_t g = (packedValue >> 8) & 0x0F; 332 uint8_t b = (packedValue >> 4) & 0x0F; 333 uint8_t a = packedValue & 0x0F; 334 destination[0] = r << 4 | r; 335 destination[1] = g << 4 | g; 336 destination[2] = b << 4 | b; 337 destination[3] = a << 4 | a; 338 source += 1; 339 destination += 4; 340 } 341} 342 343template<> void unpack<WebGLImageConversion::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 344{ 345#if HAVE(ARM_NEON_INTRINSICS) 346 SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow); 347#endif 348 for (unsigned i = 0; i < pixelsPerRow; ++i) { 349 uint16_t packedValue = source[0]; 350 uint8_t r = packedValue >> 11; 351 uint8_t g = (packedValue >> 5) & 0x3F; 352 uint8_t b = packedValue & 0x1F; 353 destination[0] = (r << 3) | (r & 0x7); 354 destination[1] = (g << 2) | (g & 0x3); 355 destination[2] = (b << 3) | (b & 0x7); 356 destination[3] = 0xFF; 357 source += 1; 358 destination += 4; 359 } 360} 361 362template<> void unpack<WebGLImageConversion::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 363{ 364 for (unsigned i = 0; i < pixelsPerRow; ++i) { 365 destination[0] = source[0]; 366 destination[1] = source[0]; 367 destination[2] = source[0]; 368 destination[3] = 0xFF; 369 source += 1; 370 destination += 4; 371 } 372} 373 374template<> void unpack<WebGLImageConversion::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 375{ 376 for (unsigned i = 0; i < pixelsPerRow; ++i) { 377 destination[0] = source[0]; 378 destination[1] = source[0]; 379 destination[2] = source[0]; 380 destination[3] = source[1]; 381 source += 2; 382 destination += 4; 383 } 384} 385 386template<> void unpack<WebGLImageConversion::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 387{ 388 for (unsigned i = 0; i < pixelsPerRow; ++i) { 389 destination[0] = source[1]; 390 destination[1] = source[1]; 391 destination[2] = source[1]; 392 destination[3] = source[0]; 393 source += 2; 394 destination += 4; 395 } 396} 397 398template<> void unpack<WebGLImageConversion::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 399{ 400 for (unsigned i = 0; i < pixelsPerRow; ++i) { 401 destination[0] = 0x0; 402 destination[1] = 0x0; 403 destination[2] = 0x0; 404 destination[3] = source[0]; 405 source += 1; 406 destination += 4; 407 } 408} 409 410template<> void unpack<WebGLImageConversion::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 411{ 412 const float scaleFactor = 1.0f / 255.0f; 413 for (unsigned i = 0; i < pixelsPerRow; ++i) { 414 destination[0] = source[0] * scaleFactor; 415 destination[1] = source[1] * scaleFactor; 416 destination[2] = source[2] * scaleFactor; 417 destination[3] = source[3] * scaleFactor; 418 source += 4; 419 destination += 4; 420 } 421} 422 423template<> void unpack<WebGLImageConversion::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 424{ 425 const float scaleFactor = 1.0f / 255.0f; 426 for (unsigned i = 0; i < pixelsPerRow; ++i) { 427 destination[0] = source[2] * scaleFactor; 428 destination[1] = source[1] * scaleFactor; 429 destination[2] = source[0] * scaleFactor; 430 destination[3] = source[3] * scaleFactor; 431 source += 4; 432 destination += 4; 433 } 434} 435 436template<> void unpack<WebGLImageConversion::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 437{ 438 const float scaleFactor = 1.0f / 255.0f; 439 for (unsigned i = 0; i < pixelsPerRow; ++i) { 440 destination[0] = source[3] * scaleFactor; 441 destination[1] = source[2] * scaleFactor; 442 destination[2] = source[1] * scaleFactor; 443 destination[3] = source[0] * scaleFactor; 444 source += 4; 445 destination += 4; 446 } 447} 448 449template<> void unpack<WebGLImageConversion::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 450{ 451 const float scaleFactor = 1.0f / 255.0f; 452 for (unsigned i = 0; i < pixelsPerRow; ++i) { 453 destination[0] = source[1] * scaleFactor; 454 destination[1] = source[2] * scaleFactor; 455 destination[2] = source[3] * scaleFactor; 456 destination[3] = source[0] * scaleFactor; 457 source += 4; 458 destination += 4; 459 } 460} 461 462template<> void unpack<WebGLImageConversion::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 463{ 464 const float scaleFactor = 1.0f / 255.0f; 465 for (unsigned i = 0; i < pixelsPerRow; ++i) { 466 destination[0] = source[0] * scaleFactor; 467 destination[1] = source[1] * scaleFactor; 468 destination[2] = source[2] * scaleFactor; 469 destination[3] = 1; 470 source += 3; 471 destination += 4; 472 } 473} 474 475template<> void unpack<WebGLImageConversion::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 476{ 477 const float scaleFactor = 1.0f / 255.0f; 478 for (unsigned i = 0; i < pixelsPerRow; ++i) { 479 destination[0] = source[2] * scaleFactor; 480 destination[1] = source[1] * scaleFactor; 481 destination[2] = source[0] * scaleFactor; 482 destination[3] = 1; 483 source += 3; 484 destination += 4; 485 } 486} 487 488template<> void unpack<WebGLImageConversion::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 489{ 490 for (unsigned i = 0; i < pixelsPerRow; ++i) { 491 destination[0] = source[0]; 492 destination[1] = source[1]; 493 destination[2] = source[2]; 494 destination[3] = 1; 495 source += 3; 496 destination += 4; 497 } 498} 499 500template<> void unpack<WebGLImageConversion::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 501{ 502 for (unsigned i = 0; i < pixelsPerRow; ++i) { 503 destination[0] = source[0]; 504 destination[1] = source[0]; 505 destination[2] = source[0]; 506 destination[3] = 1; 507 source += 1; 508 destination += 4; 509 } 510} 511 512template<> void unpack<WebGLImageConversion::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 513{ 514 for (unsigned i = 0; i < pixelsPerRow; ++i) { 515 destination[0] = source[0]; 516 destination[1] = source[0]; 517 destination[2] = source[0]; 518 destination[3] = source[1]; 519 source += 2; 520 destination += 4; 521 } 522} 523 524template<> void unpack<WebGLImageConversion::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 525{ 526 for (unsigned i = 0; i < pixelsPerRow; ++i) { 527 destination[0] = 0; 528 destination[1] = 0; 529 destination[2] = 0; 530 destination[3] = source[0]; 531 source += 1; 532 destination += 4; 533 } 534} 535 536//---------------------------------------------------------------------- 537// Pixel packing routines. 538// 539 540template<int format, int alphaOp, typename SourceType, typename DstType> 541void pack(const SourceType*, DstType*, unsigned) 542{ 543 ASSERT_NOT_REACHED(); 544} 545 546template<> void pack<WebGLImageConversion::DataFormatA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 547{ 548 for (unsigned i = 0; i < pixelsPerRow; ++i) { 549 destination[0] = source[3]; 550 source += 4; 551 destination += 1; 552 } 553} 554 555template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 556{ 557 for (unsigned i = 0; i < pixelsPerRow; ++i) { 558 destination[0] = source[0]; 559 source += 4; 560 destination += 1; 561 } 562} 563 564template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 565{ 566 for (unsigned i = 0; i < pixelsPerRow; ++i) { 567 float scaleFactor = source[3] / 255.0f; 568 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 569 destination[0] = sourceR; 570 source += 4; 571 destination += 1; 572 } 573} 574 575// FIXME: this routine is lossy and must be removed. 576template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 577{ 578 for (unsigned i = 0; i < pixelsPerRow; ++i) { 579 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 580 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 581 destination[0] = sourceR; 582 source += 4; 583 destination += 1; 584 } 585} 586 587template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 588{ 589 for (unsigned i = 0; i < pixelsPerRow; ++i) { 590 destination[0] = source[0]; 591 destination[1] = source[3]; 592 source += 4; 593 destination += 2; 594 } 595} 596 597template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 598{ 599 for (unsigned i = 0; i < pixelsPerRow; ++i) { 600 float scaleFactor = source[3] / 255.0f; 601 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 602 destination[0] = sourceR; 603 destination[1] = source[3]; 604 source += 4; 605 destination += 2; 606 } 607} 608 609// FIXME: this routine is lossy and must be removed. 610template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 611{ 612 for (unsigned i = 0; i < pixelsPerRow; ++i) { 613 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 614 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 615 destination[0] = sourceR; 616 destination[1] = source[3]; 617 source += 4; 618 destination += 2; 619 } 620} 621 622template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 623{ 624 for (unsigned i = 0; i < pixelsPerRow; ++i) { 625 destination[0] = source[0]; 626 destination[1] = source[1]; 627 destination[2] = source[2]; 628 source += 4; 629 destination += 3; 630 } 631} 632 633template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 634{ 635 for (unsigned i = 0; i < pixelsPerRow; ++i) { 636 float scaleFactor = source[3] / 255.0f; 637 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 638 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 639 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 640 destination[0] = sourceR; 641 destination[1] = sourceG; 642 destination[2] = sourceB; 643 source += 4; 644 destination += 3; 645 } 646} 647 648// FIXME: this routine is lossy and must be removed. 649template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 650{ 651 for (unsigned i = 0; i < pixelsPerRow; ++i) { 652 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 653 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 654 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 655 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 656 destination[0] = sourceR; 657 destination[1] = sourceG; 658 destination[2] = sourceB; 659 source += 4; 660 destination += 3; 661 } 662} 663 664 665template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 666{ 667 memcpy(destination, source, pixelsPerRow * 4); 668} 669 670template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 671{ 672 for (unsigned i = 0; i < pixelsPerRow; ++i) { 673 float scaleFactor = source[3] / 255.0f; 674 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 675 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 676 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 677 destination[0] = sourceR; 678 destination[1] = sourceG; 679 destination[2] = sourceB; 680 destination[3] = source[3]; 681 source += 4; 682 destination += 4; 683 } 684} 685 686// FIXME: this routine is lossy and must be removed. 687template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 688{ 689 for (unsigned i = 0; i < pixelsPerRow; ++i) { 690 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 691 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 692 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 693 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 694 destination[0] = sourceR; 695 destination[1] = sourceG; 696 destination[2] = sourceB; 697 destination[3] = source[3]; 698 source += 4; 699 destination += 4; 700 } 701} 702 703template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 704{ 705#if HAVE(ARM_NEON_INTRINSICS) 706 SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow); 707#endif 708 for (unsigned i = 0; i < pixelsPerRow; ++i) { 709 *destination = (((source[0] & 0xF0) << 8) 710 | ((source[1] & 0xF0) << 4) 711 | (source[2] & 0xF0) 712 | (source[3] >> 4)); 713 source += 4; 714 destination += 1; 715 } 716} 717 718template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 719{ 720 for (unsigned i = 0; i < pixelsPerRow; ++i) { 721 float scaleFactor = source[3] / 255.0f; 722 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 723 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 724 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 725 *destination = (((sourceR & 0xF0) << 8) 726 | ((sourceG & 0xF0) << 4) 727 | (sourceB & 0xF0) 728 | (source[3] >> 4)); 729 source += 4; 730 destination += 1; 731 } 732} 733 734// FIXME: this routine is lossy and must be removed. 735template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 736{ 737 for (unsigned i = 0; i < pixelsPerRow; ++i) { 738 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 739 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 740 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 741 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 742 *destination = (((sourceR & 0xF0) << 8) 743 | ((sourceG & 0xF0) << 4) 744 | (sourceB & 0xF0) 745 | (source[3] >> 4)); 746 source += 4; 747 destination += 1; 748 } 749} 750 751template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 752{ 753#if HAVE(ARM_NEON_INTRINSICS) 754 SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow); 755#endif 756 for (unsigned i = 0; i < pixelsPerRow; ++i) { 757 *destination = (((source[0] & 0xF8) << 8) 758 | ((source[1] & 0xF8) << 3) 759 | ((source[2] & 0xF8) >> 2) 760 | (source[3] >> 7)); 761 source += 4; 762 destination += 1; 763 } 764} 765 766template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 767{ 768 for (unsigned i = 0; i < pixelsPerRow; ++i) { 769 float scaleFactor = source[3] / 255.0f; 770 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 771 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 772 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 773 *destination = (((sourceR & 0xF8) << 8) 774 | ((sourceG & 0xF8) << 3) 775 | ((sourceB & 0xF8) >> 2) 776 | (source[3] >> 7)); 777 source += 4; 778 destination += 1; 779 } 780} 781 782// FIXME: this routine is lossy and must be removed. 783template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 784{ 785 for (unsigned i = 0; i < pixelsPerRow; ++i) { 786 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 787 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 788 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 789 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 790 *destination = (((sourceR & 0xF8) << 8) 791 | ((sourceG & 0xF8) << 3) 792 | ((sourceB & 0xF8) >> 2) 793 | (source[3] >> 7)); 794 source += 4; 795 destination += 1; 796 } 797} 798 799template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 800{ 801#if HAVE(ARM_NEON_INTRINSICS) 802 SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow); 803#endif 804 for (unsigned i = 0; i < pixelsPerRow; ++i) { 805 *destination = (((source[0] & 0xF8) << 8) 806 | ((source[1] & 0xFC) << 3) 807 | ((source[2] & 0xF8) >> 3)); 808 source += 4; 809 destination += 1; 810 } 811} 812 813template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 814{ 815 for (unsigned i = 0; i < pixelsPerRow; ++i) { 816 float scaleFactor = source[3] / 255.0f; 817 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 818 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 819 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 820 *destination = (((sourceR & 0xF8) << 8) 821 | ((sourceG & 0xFC) << 3) 822 | ((sourceB & 0xF8) >> 3)); 823 source += 4; 824 destination += 1; 825 } 826} 827 828// FIXME: this routine is lossy and must be removed. 829template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 830{ 831 for (unsigned i = 0; i < pixelsPerRow; ++i) { 832 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 833 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 834 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 835 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 836 *destination = (((sourceR & 0xF8) << 8) 837 | ((sourceG & 0xFC) << 3) 838 | ((sourceB & 0xF8) >> 3)); 839 source += 4; 840 destination += 1; 841 } 842} 843 844template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 845{ 846 for (unsigned i = 0; i < pixelsPerRow; ++i) { 847 destination[0] = source[0]; 848 destination[1] = source[1]; 849 destination[2] = source[2]; 850 source += 4; 851 destination += 3; 852 } 853} 854 855template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 856{ 857 for (unsigned i = 0; i < pixelsPerRow; ++i) { 858 float scaleFactor = source[3]; 859 destination[0] = source[0] * scaleFactor; 860 destination[1] = source[1] * scaleFactor; 861 destination[2] = source[2] * scaleFactor; 862 source += 4; 863 destination += 3; 864 } 865} 866 867template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 868{ 869 for (unsigned i = 0; i < pixelsPerRow; ++i) { 870 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 871 destination[0] = source[0] * scaleFactor; 872 destination[1] = source[1] * scaleFactor; 873 destination[2] = source[2] * scaleFactor; 874 source += 4; 875 destination += 3; 876 } 877} 878 879// Used only during RGBA8 or BGRA8 -> floating-point uploads. 880template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 881{ 882 memcpy(destination, source, pixelsPerRow * 4 * sizeof(float)); 883} 884 885template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 886{ 887 for (unsigned i = 0; i < pixelsPerRow; ++i) { 888 float scaleFactor = source[3]; 889 destination[0] = source[0] * scaleFactor; 890 destination[1] = source[1] * scaleFactor; 891 destination[2] = source[2] * scaleFactor; 892 destination[3] = source[3]; 893 source += 4; 894 destination += 4; 895 } 896} 897 898template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 899{ 900 for (unsigned i = 0; i < pixelsPerRow; ++i) { 901 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 902 destination[0] = source[0] * scaleFactor; 903 destination[1] = source[1] * scaleFactor; 904 destination[2] = source[2] * scaleFactor; 905 destination[3] = source[3]; 906 source += 4; 907 destination += 4; 908 } 909} 910 911template<> void pack<WebGLImageConversion::DataFormatA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 912{ 913 for (unsigned i = 0; i < pixelsPerRow; ++i) { 914 destination[0] = source[3]; 915 source += 4; 916 destination += 1; 917 } 918} 919 920template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 921{ 922 for (unsigned i = 0; i < pixelsPerRow; ++i) { 923 destination[0] = source[0]; 924 source += 4; 925 destination += 1; 926 } 927} 928 929template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 930{ 931 for (unsigned i = 0; i < pixelsPerRow; ++i) { 932 float scaleFactor = source[3]; 933 destination[0] = source[0] * scaleFactor; 934 source += 4; 935 destination += 1; 936 } 937} 938 939template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 940{ 941 for (unsigned i = 0; i < pixelsPerRow; ++i) { 942 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 943 destination[0] = source[0] * scaleFactor; 944 source += 4; 945 destination += 1; 946 } 947} 948 949template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 950{ 951 for (unsigned i = 0; i < pixelsPerRow; ++i) { 952 destination[0] = source[0]; 953 destination[1] = source[3]; 954 source += 4; 955 destination += 2; 956 } 957} 958 959template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 960{ 961 for (unsigned i = 0; i < pixelsPerRow; ++i) { 962 float scaleFactor = source[3]; 963 destination[0] = source[0] * scaleFactor; 964 destination[1] = source[3]; 965 source += 4; 966 destination += 2; 967 } 968} 969 970template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 971{ 972 for (unsigned i = 0; i < pixelsPerRow; ++i) { 973 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 974 destination[0] = source[0] * scaleFactor; 975 destination[1] = source[3]; 976 source += 4; 977 destination += 2; 978 } 979} 980 981template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 982{ 983 for (unsigned i = 0; i < pixelsPerRow; ++i) { 984 destination[0] = convertFloatToHalfFloat(source[0]); 985 destination[1] = convertFloatToHalfFloat(source[1]); 986 destination[2] = convertFloatToHalfFloat(source[2]); 987 destination[3] = convertFloatToHalfFloat(source[3]); 988 source += 4; 989 destination += 4; 990 } 991} 992 993template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 994{ 995 for (unsigned i = 0; i < pixelsPerRow; ++i) { 996 float scaleFactor = source[3]; 997 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 998 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 999 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1000 destination[3] = convertFloatToHalfFloat(source[3]); 1001 source += 4; 1002 destination += 4; 1003 } 1004} 1005 1006template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1007{ 1008 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1009 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1010 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1011 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1012 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1013 destination[3] = convertFloatToHalfFloat(source[3]); 1014 source += 4; 1015 destination += 4; 1016 } 1017} 1018 1019template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1020{ 1021 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1022 destination[0] = convertFloatToHalfFloat(source[0]); 1023 destination[1] = convertFloatToHalfFloat(source[1]); 1024 destination[2] = convertFloatToHalfFloat(source[2]); 1025 source += 4; 1026 destination += 3; 1027 } 1028} 1029 1030template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1031{ 1032 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1033 float scaleFactor = source[3]; 1034 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1035 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1036 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1037 source += 4; 1038 destination += 3; 1039 } 1040} 1041 1042template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1043{ 1044 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1045 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1046 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1047 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1048 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1049 source += 4; 1050 destination += 3; 1051 } 1052} 1053 1054template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1055{ 1056 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1057 destination[0] = convertFloatToHalfFloat(source[0]); 1058 destination[1] = convertFloatToHalfFloat(source[3]); 1059 source += 4; 1060 destination += 2; 1061 } 1062} 1063 1064template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1065{ 1066 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1067 float scaleFactor = source[3]; 1068 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1069 destination[1] = convertFloatToHalfFloat(source[3]); 1070 source += 4; 1071 destination += 2; 1072 } 1073} 1074 1075template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1076{ 1077 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1078 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1079 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1080 destination[1] = convertFloatToHalfFloat(source[3]); 1081 source += 4; 1082 destination += 2; 1083 } 1084} 1085 1086template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1087{ 1088 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1089 destination[0] = convertFloatToHalfFloat(source[0]); 1090 source += 4; 1091 destination += 1; 1092 } 1093} 1094 1095template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1096{ 1097 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1098 float scaleFactor = source[3]; 1099 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1100 source += 4; 1101 destination += 1; 1102 } 1103} 1104 1105template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1106{ 1107 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1108 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1109 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1110 source += 4; 1111 destination += 1; 1112 } 1113} 1114 1115template<> void pack<WebGLImageConversion::DataFormatA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1116{ 1117 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1118 destination[0] = convertFloatToHalfFloat(source[3]); 1119 source += 4; 1120 destination += 1; 1121 } 1122} 1123 1124bool HasAlpha(int format) 1125{ 1126 return format == WebGLImageConversion::DataFormatA8 1127 || format == WebGLImageConversion::DataFormatA16F 1128 || format == WebGLImageConversion::DataFormatA32F 1129 || format == WebGLImageConversion::DataFormatRA8 1130 || format == WebGLImageConversion::DataFormatAR8 1131 || format == WebGLImageConversion::DataFormatRA16F 1132 || format == WebGLImageConversion::DataFormatRA32F 1133 || format == WebGLImageConversion::DataFormatRGBA8 1134 || format == WebGLImageConversion::DataFormatBGRA8 1135 || format == WebGLImageConversion::DataFormatARGB8 1136 || format == WebGLImageConversion::DataFormatABGR8 1137 || format == WebGLImageConversion::DataFormatRGBA16F 1138 || format == WebGLImageConversion::DataFormatRGBA32F 1139 || format == WebGLImageConversion::DataFormatRGBA4444 1140 || format == WebGLImageConversion::DataFormatRGBA5551; 1141} 1142 1143bool HasColor(int format) 1144{ 1145 return format == WebGLImageConversion::DataFormatRGBA8 1146 || format == WebGLImageConversion::DataFormatRGBA16F 1147 || format == WebGLImageConversion::DataFormatRGBA32F 1148 || format == WebGLImageConversion::DataFormatRGB8 1149 || format == WebGLImageConversion::DataFormatRGB16F 1150 || format == WebGLImageConversion::DataFormatRGB32F 1151 || format == WebGLImageConversion::DataFormatBGR8 1152 || format == WebGLImageConversion::DataFormatBGRA8 1153 || format == WebGLImageConversion::DataFormatARGB8 1154 || format == WebGLImageConversion::DataFormatABGR8 1155 || format == WebGLImageConversion::DataFormatRGBA5551 1156 || format == WebGLImageConversion::DataFormatRGBA4444 1157 || format == WebGLImageConversion::DataFormatRGB565 1158 || format == WebGLImageConversion::DataFormatR8 1159 || format == WebGLImageConversion::DataFormatR16F 1160 || format == WebGLImageConversion::DataFormatR32F 1161 || format == WebGLImageConversion::DataFormatRA8 1162 || format == WebGLImageConversion::DataFormatRA16F 1163 || format == WebGLImageConversion::DataFormatRA32F 1164 || format == WebGLImageConversion::DataFormatAR8; 1165} 1166 1167template<int Format> 1168struct IsFloatFormat { 1169 static const bool Value = 1170 Format == WebGLImageConversion::DataFormatRGBA32F 1171 || Format == WebGLImageConversion::DataFormatRGB32F 1172 || Format == WebGLImageConversion::DataFormatRA32F 1173 || Format == WebGLImageConversion::DataFormatR32F 1174 || Format == WebGLImageConversion::DataFormatA32F; 1175}; 1176 1177template<int Format> 1178struct IsHalfFloatFormat { 1179 static const bool Value = 1180 Format == WebGLImageConversion::DataFormatRGBA16F 1181 || Format == WebGLImageConversion::DataFormatRGB16F 1182 || Format == WebGLImageConversion::DataFormatRA16F 1183 || Format == WebGLImageConversion::DataFormatR16F 1184 || Format == WebGLImageConversion::DataFormatA16F; 1185}; 1186 1187template<int Format> 1188struct Is16bppFormat { 1189 static const bool Value = 1190 Format == WebGLImageConversion::DataFormatRGBA5551 1191 || Format == WebGLImageConversion::DataFormatRGBA4444 1192 || Format == WebGLImageConversion::DataFormatRGB565; 1193}; 1194 1195template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value> 1196struct DataTypeForFormat { 1197 typedef uint8_t Type; 1198}; 1199 1200template<int Format> 1201struct DataTypeForFormat<Format, true, false, false> { 1202 typedef float Type; 1203}; 1204 1205template<int Format> 1206struct DataTypeForFormat<Format, false, true, false> { 1207 typedef uint16_t Type; 1208}; 1209 1210template<int Format> 1211struct DataTypeForFormat<Format, false, false, true> { 1212 typedef uint16_t Type; 1213}; 1214 1215template<int Format> 1216struct IntermediateFormat { 1217 static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? WebGLImageConversion::DataFormatRGBA32F : WebGLImageConversion::DataFormatRGBA8; 1218}; 1219 1220unsigned TexelBytesForFormat(WebGLImageConversion::DataFormat format) 1221{ 1222 switch (format) { 1223 case WebGLImageConversion::DataFormatR8: 1224 case WebGLImageConversion::DataFormatA8: 1225 return 1; 1226 case WebGLImageConversion::DataFormatRA8: 1227 case WebGLImageConversion::DataFormatAR8: 1228 case WebGLImageConversion::DataFormatRGBA5551: 1229 case WebGLImageConversion::DataFormatRGBA4444: 1230 case WebGLImageConversion::DataFormatRGB565: 1231 case WebGLImageConversion::DataFormatA16F: 1232 case WebGLImageConversion::DataFormatR16F: 1233 return 2; 1234 case WebGLImageConversion::DataFormatRGB8: 1235 case WebGLImageConversion::DataFormatBGR8: 1236 return 3; 1237 case WebGLImageConversion::DataFormatRGBA8: 1238 case WebGLImageConversion::DataFormatARGB8: 1239 case WebGLImageConversion::DataFormatABGR8: 1240 case WebGLImageConversion::DataFormatBGRA8: 1241 case WebGLImageConversion::DataFormatR32F: 1242 case WebGLImageConversion::DataFormatA32F: 1243 case WebGLImageConversion::DataFormatRA16F: 1244 return 4; 1245 case WebGLImageConversion::DataFormatRGB16F: 1246 return 6; 1247 case WebGLImageConversion::DataFormatRA32F: 1248 case WebGLImageConversion::DataFormatRGBA16F: 1249 return 8; 1250 case WebGLImageConversion::DataFormatRGB32F: 1251 return 12; 1252 case WebGLImageConversion::DataFormatRGBA32F: 1253 return 16; 1254 default: 1255 return 0; 1256 } 1257} 1258 1259/* END CODE SHARED WITH MOZILLA FIREFOX */ 1260 1261class FormatConverter { 1262public: 1263 FormatConverter(unsigned width, unsigned height, 1264 const void* srcStart, void* dstStart, int srcStride, int dstStride) 1265 : m_width(width), m_height(height), m_srcStart(srcStart), m_dstStart(dstStart), m_srcStride(srcStride), m_dstStride(dstStride), m_success(false) 1266 { 1267 const unsigned MaxNumberOfComponents = 4; 1268 const unsigned MaxBytesPerComponent = 4; 1269 m_unpackedIntermediateSrcData = adoptArrayPtr(new uint8_t[m_width * MaxNumberOfComponents *MaxBytesPerComponent]); 1270 ASSERT(m_unpackedIntermediateSrcData.get()); 1271 } 1272 1273 void convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp); 1274 bool Success() const { return m_success; } 1275 1276private: 1277 template<WebGLImageConversion::DataFormat SrcFormat> 1278 void convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp); 1279 1280 template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat> 1281 void convert(WebGLImageConversion::AlphaOp); 1282 1283 template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp> 1284 void convert(); 1285 1286 const unsigned m_width, m_height; 1287 const void* const m_srcStart; 1288 void* const m_dstStart; 1289 const int m_srcStride, m_dstStride; 1290 bool m_success; 1291 OwnPtr<uint8_t[]> m_unpackedIntermediateSrcData; 1292}; 1293 1294void FormatConverter::convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp) 1295{ 1296#define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \ 1297 case SrcFormat: \ 1298 return convert<SrcFormat>(dstFormat, alphaOp); 1299 1300 switch (srcFormat) { 1301 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR8) 1302 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA8) 1303 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR32F) 1304 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA32F) 1305 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA8) 1306 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA32F) 1307 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB8) 1308 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGR8) 1309 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB565) 1310 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB32F) 1311 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA8) 1312 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatARGB8) 1313 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatABGR8) 1314 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatAR8) 1315 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGRA8) 1316 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA5551) 1317 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA4444) 1318 FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA32F) 1319 default: 1320 ASSERT_NOT_REACHED(); 1321 } 1322#undef FORMATCONVERTER_CASE_SRCFORMAT 1323} 1324 1325template<WebGLImageConversion::DataFormat SrcFormat> 1326void FormatConverter::convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp) 1327{ 1328#define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \ 1329 case DstFormat: \ 1330 return convert<SrcFormat, DstFormat>(alphaOp); 1331 1332 switch (dstFormat) { 1333 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR8) 1334 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR16F) 1335 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR32F) 1336 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA8) 1337 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA16F) 1338 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA32F) 1339 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA8) 1340 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA16F) 1341 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA32F) 1342 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB8) 1343 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB565) 1344 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB16F) 1345 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB32F) 1346 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA8) 1347 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA5551) 1348 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA4444) 1349 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA16F) 1350 FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA32F) 1351 default: 1352 ASSERT_NOT_REACHED(); 1353 } 1354 1355#undef FORMATCONVERTER_CASE_DSTFORMAT 1356} 1357 1358template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat> 1359void FormatConverter::convert(WebGLImageConversion::AlphaOp alphaOp) 1360{ 1361#define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \ 1362 case alphaOp: \ 1363 return convert<SrcFormat, DstFormat, alphaOp>(); 1364 1365 switch (alphaOp) { 1366 FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoNothing) 1367 FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoPremultiply) 1368 FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoUnmultiply) 1369 default: 1370 ASSERT_NOT_REACHED(); 1371 } 1372#undef FORMATCONVERTER_CASE_ALPHAOP 1373} 1374 1375template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp> 1376void FormatConverter::convert() 1377{ 1378 // Many instantiations of this template function will never be entered, so we try 1379 // to return immediately in these cases to avoid the compiler to generate useless code. 1380 if (SrcFormat == DstFormat && alphaOp == WebGLImageConversion::AlphaDoNothing) { 1381 ASSERT_NOT_REACHED(); 1382 return; 1383 } 1384 if (!IsFloatFormat<DstFormat>::Value && IsFloatFormat<SrcFormat>::Value) { 1385 ASSERT_NOT_REACHED(); 1386 return; 1387 } 1388 1389 // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat. 1390 const bool srcFormatComesFromDOMElementOrImageData = WebGLImageConversion::srcFormatComeFromDOMElementOrImageData(SrcFormat); 1391 if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) { 1392 ASSERT_NOT_REACHED(); 1393 return; 1394 } 1395 // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied. 1396 if (!srcFormatComesFromDOMElementOrImageData && alphaOp == WebGLImageConversion::AlphaDoUnmultiply) { 1397 ASSERT_NOT_REACHED(); 1398 return; 1399 } 1400 if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && alphaOp != WebGLImageConversion::AlphaDoNothing) { 1401 ASSERT_NOT_REACHED(); 1402 return; 1403 } 1404 1405 typedef typename DataTypeForFormat<SrcFormat>::Type SrcType; 1406 typedef typename DataTypeForFormat<DstFormat>::Type DstType; 1407 const int IntermediateSrcFormat = IntermediateFormat<DstFormat>::Value; 1408 typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType; 1409 const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType); 1410 const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType); 1411 const bool trivialUnpack = (SrcFormat == WebGLImageConversion::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == WebGLImageConversion::DataFormatRGBA32F; 1412 const bool trivialPack = (DstFormat == WebGLImageConversion::DataFormatRGBA8 || DstFormat == WebGLImageConversion::DataFormatRGBA32F) && alphaOp == WebGLImageConversion::AlphaDoNothing && m_dstStride > 0; 1413 ASSERT(!trivialUnpack || !trivialPack); 1414 1415 const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart); 1416 DstType* dstRowStart = static_cast<DstType*>(m_dstStart); 1417 if (!trivialUnpack && trivialPack) { 1418 for (size_t i = 0; i < m_height; ++i) { 1419 unpack<SrcFormat>(srcRowStart, dstRowStart, m_width); 1420 srcRowStart += srcStrideInElements; 1421 dstRowStart += dstStrideInElements; 1422 } 1423 } else if (!trivialUnpack && !trivialPack) { 1424 for (size_t i = 0; i < m_height; ++i) { 1425 unpack<SrcFormat>(srcRowStart, reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), m_width); 1426 pack<DstFormat, alphaOp>(reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), dstRowStart, m_width); 1427 srcRowStart += srcStrideInElements; 1428 dstRowStart += dstStrideInElements; 1429 } 1430 } else { 1431 for (size_t i = 0; i < m_height; ++i) { 1432 pack<DstFormat, alphaOp>(srcRowStart, dstRowStart, m_width); 1433 srcRowStart += srcStrideInElements; 1434 dstRowStart += dstStrideInElements; 1435 } 1436 } 1437 m_success = true; 1438 return; 1439} 1440 1441} // anonymous namespace 1442 1443bool WebGLImageConversion::computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent) 1444{ 1445 switch (format) { 1446 case GL_ALPHA: 1447 case GL_LUMINANCE: 1448 case GL_DEPTH_COMPONENT: 1449 case GL_DEPTH_STENCIL_OES: 1450 *componentsPerPixel = 1; 1451 break; 1452 case GL_LUMINANCE_ALPHA: 1453 *componentsPerPixel = 2; 1454 break; 1455 case GL_RGB: 1456 *componentsPerPixel = 3; 1457 break; 1458 case GL_RGBA: 1459 case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888 1460 *componentsPerPixel = 4; 1461 break; 1462 default: 1463 return false; 1464 } 1465 switch (type) { 1466 case GL_UNSIGNED_BYTE: 1467 *bytesPerComponent = sizeof(GLubyte); 1468 break; 1469 case GL_UNSIGNED_SHORT: 1470 *bytesPerComponent = sizeof(GLushort); 1471 break; 1472 case GL_UNSIGNED_SHORT_5_6_5: 1473 case GL_UNSIGNED_SHORT_4_4_4_4: 1474 case GL_UNSIGNED_SHORT_5_5_5_1: 1475 *componentsPerPixel = 1; 1476 *bytesPerComponent = sizeof(GLushort); 1477 break; 1478 case GL_UNSIGNED_INT_24_8_OES: 1479 case GL_UNSIGNED_INT: 1480 *bytesPerComponent = sizeof(GLuint); 1481 break; 1482 case GL_FLOAT: // OES_texture_float 1483 *bytesPerComponent = sizeof(GLfloat); 1484 break; 1485 case GL_HALF_FLOAT_OES: // OES_texture_half_float 1486 *bytesPerComponent = sizeof(GLushort); 1487 break; 1488 default: 1489 return false; 1490 } 1491 return true; 1492} 1493 1494GLenum WebGLImageConversion::computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes) 1495{ 1496 ASSERT(imageSizeInBytes); 1497 ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8); 1498 if (width < 0 || height < 0) 1499 return GL_INVALID_VALUE; 1500 unsigned bytesPerComponent, componentsPerPixel; 1501 if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel)) 1502 return GL_INVALID_ENUM; 1503 if (!width || !height) { 1504 *imageSizeInBytes = 0; 1505 if (paddingInBytes) 1506 *paddingInBytes = 0; 1507 return GL_NO_ERROR; 1508 } 1509 CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel); 1510 checkedValue *= width; 1511 if (!checkedValue.isValid()) 1512 return GL_INVALID_VALUE; 1513 unsigned validRowSize = checkedValue.value(); 1514 unsigned padding = 0; 1515 unsigned residual = validRowSize % alignment; 1516 if (residual) { 1517 padding = alignment - residual; 1518 checkedValue += padding; 1519 } 1520 // Last row needs no padding. 1521 checkedValue *= (height - 1); 1522 checkedValue += validRowSize; 1523 if (!checkedValue.isValid()) 1524 return GL_INVALID_VALUE; 1525 *imageSizeInBytes = checkedValue.value(); 1526 if (paddingInBytes) 1527 *paddingInBytes = padding; 1528 return GL_NO_ERROR; 1529} 1530 1531WebGLImageConversion::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile) 1532{ 1533 m_image = image; 1534 m_imageHtmlDomSource = imageHtmlDomSource; 1535 m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile); 1536} 1537 1538WebGLImageConversion::ImageExtractor::~ImageExtractor() 1539{ 1540 if (m_skiaImage) 1541 m_skiaImage->bitmap().unlockPixels(); 1542} 1543 1544bool WebGLImageConversion::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) 1545{ 1546 if (!m_image) 1547 return false; 1548 m_skiaImage = m_image->nativeImageForCurrentFrame(); 1549 m_alphaOp = AlphaDoNothing; 1550 bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true; 1551 if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) { 1552 // Attempt to get raw unpremultiplied image data. 1553 OwnPtr<ImageDecoder> decoder(ImageDecoder::create( 1554 *(m_image->data()), ImageSource::AlphaNotPremultiplied, 1555 ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied)); 1556 if (!decoder) 1557 return false; 1558 decoder->setData(m_image->data(), true); 1559 if (!decoder->frameCount()) 1560 return false; 1561 ImageFrame* frame = decoder->frameBufferAtIndex(0); 1562 if (!frame || frame->status() != ImageFrame::FrameComplete) 1563 return false; 1564 hasAlpha = frame->hasAlpha(); 1565 m_nativeImage = frame->asNewNativeImage(); 1566 if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height()) 1567 return false; 1568 if (m_nativeImage->bitmap().colorType() != kN32_SkColorType) 1569 return false; 1570 m_skiaImage = m_nativeImage.get(); 1571 if (hasAlpha && premultiplyAlpha) 1572 m_alphaOp = AlphaDoPremultiply; 1573 } else if (!premultiplyAlpha && hasAlpha) { 1574 // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF 1575 // which is true at present and may be changed in the future and needs adjustment accordingly. 1576 // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port, 1577 // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false. 1578 if (m_imageHtmlDomSource != HtmlDomVideo) 1579 m_alphaOp = AlphaDoUnmultiply; 1580 } 1581 if (!m_skiaImage) 1582 return false; 1583 1584 m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8; 1585 m_imageWidth = m_skiaImage->bitmap().width(); 1586 m_imageHeight = m_skiaImage->bitmap().height(); 1587 if (!m_imageWidth || !m_imageHeight) { 1588 m_skiaImage.clear(); 1589 return false; 1590 } 1591 // Fail if the image was downsampled because of memory limits. 1592 if (m_imageWidth != (unsigned)m_image->size().width() || m_imageHeight != (unsigned)m_image->size().height()) { 1593 m_skiaImage.clear(); 1594 return false; 1595 } 1596 m_imageSourceUnpackAlignment = 0; 1597 m_skiaImage->bitmap().lockPixels(); 1598 m_imagePixelData = m_skiaImage->bitmap().getPixels(); 1599 return true; 1600} 1601 1602unsigned WebGLImageConversion::getClearBitsByFormat(GLenum format) 1603{ 1604 switch (format) { 1605 case GL_ALPHA: 1606 case GL_LUMINANCE: 1607 case GL_LUMINANCE_ALPHA: 1608 case GL_RGB: 1609 case GL_RGB565: 1610 case GL_RGBA: 1611 case GL_RGBA4: 1612 case GL_RGB5_A1: 1613 return GL_COLOR_BUFFER_BIT; 1614 case GL_DEPTH_COMPONENT16: 1615 case GL_DEPTH_COMPONENT: 1616 return GL_DEPTH_BUFFER_BIT; 1617 case GL_STENCIL_INDEX8: 1618 return GL_STENCIL_BUFFER_BIT; 1619 case GL_DEPTH_STENCIL_OES: 1620 return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; 1621 default: 1622 return 0; 1623 } 1624} 1625 1626unsigned WebGLImageConversion::getChannelBitsByFormat(GLenum format) 1627{ 1628 switch (format) { 1629 case GL_ALPHA: 1630 return ChannelAlpha; 1631 case GL_LUMINANCE: 1632 return ChannelRGB; 1633 case GL_LUMINANCE_ALPHA: 1634 return ChannelRGBA; 1635 case GL_RGB: 1636 case GL_RGB565: 1637 return ChannelRGB; 1638 case GL_RGBA: 1639 case GL_RGBA4: 1640 case GL_RGB5_A1: 1641 return ChannelRGBA; 1642 case GL_DEPTH_COMPONENT16: 1643 case GL_DEPTH_COMPONENT: 1644 return ChannelDepth; 1645 case GL_STENCIL_INDEX8: 1646 return ChannelStencil; 1647 case GL_DEPTH_STENCIL_OES: 1648 return ChannelDepth | ChannelStencil; 1649 default: 1650 return 0; 1651 } 1652} 1653 1654bool WebGLImageConversion::packImageData( 1655 Image* image, 1656 const void* pixels, 1657 GLenum format, 1658 GLenum type, 1659 bool flipY, 1660 AlphaOp alphaOp, 1661 DataFormat sourceFormat, 1662 unsigned width, 1663 unsigned height, 1664 unsigned sourceUnpackAlignment, 1665 Vector<uint8_t>& data) 1666{ 1667 if (!pixels) 1668 return false; 1669 1670 unsigned packedSize; 1671 // Output data is tightly packed (alignment == 1). 1672 if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GL_NO_ERROR) 1673 return false; 1674 data.resize(packedSize); 1675 1676 if (!packPixels(reinterpret_cast<const uint8_t*>(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY)) 1677 return false; 1678 if (ImageObserver *observer = image->imageObserver()) 1679 observer->didDraw(image); 1680 return true; 1681} 1682 1683bool WebGLImageConversion::extractImageData( 1684 const uint8_t* imageData, 1685 const IntSize& imageDataSize, 1686 GLenum format, 1687 GLenum type, 1688 bool flipY, 1689 bool premultiplyAlpha, 1690 Vector<uint8_t>& data) 1691{ 1692 if (!imageData) 1693 return false; 1694 int width = imageDataSize.width(); 1695 int height = imageDataSize.height(); 1696 1697 unsigned packedSize; 1698 // Output data is tightly packed (alignment == 1). 1699 if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GL_NO_ERROR) 1700 return false; 1701 data.resize(packedSize); 1702 1703 if (!packPixels(imageData, DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY)) 1704 return false; 1705 1706 return true; 1707} 1708 1709bool WebGLImageConversion::extractTextureData( 1710 unsigned width, 1711 unsigned height, 1712 GLenum format, GLenum type, 1713 unsigned unpackAlignment, 1714 bool flipY, bool premultiplyAlpha, 1715 const void* pixels, 1716 Vector<uint8_t>& data) 1717{ 1718 // Assumes format, type, etc. have already been validated. 1719 DataFormat sourceDataFormat = getDataFormat(format, type); 1720 1721 // Resize the output buffer. 1722 unsigned int componentsPerPixel, bytesPerComponent; 1723 if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) 1724 return false; 1725 unsigned bytesPerPixel = componentsPerPixel * bytesPerComponent; 1726 data.resize(width * height * bytesPerPixel); 1727 1728 if (!packPixels(static_cast<const uint8_t*>(pixels), sourceDataFormat, width, height, unpackAlignment, format, type, (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data(), flipY)) 1729 return false; 1730 1731 return true; 1732} 1733 1734bool WebGLImageConversion::packPixels( 1735 const uint8_t* sourceData, 1736 DataFormat sourceDataFormat, 1737 unsigned width, 1738 unsigned height, 1739 unsigned sourceUnpackAlignment, 1740 unsigned destinationFormat, 1741 unsigned destinationType, 1742 AlphaOp alphaOp, 1743 void* destinationData, 1744 bool flipY) 1745{ 1746 int validSrc = width * TexelBytesForFormat(sourceDataFormat); 1747 int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0; 1748 int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc; 1749 1750 DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType); 1751 int dstStride = width * TexelBytesForFormat(dstDataFormat); 1752 if (flipY) { 1753 destinationData = static_cast<uint8_t*>(destinationData) + dstStride*(height - 1); 1754 dstStride = -dstStride; 1755 } 1756 if (!HasAlpha(sourceDataFormat) || !HasColor(sourceDataFormat) || !HasColor(dstDataFormat)) 1757 alphaOp = AlphaDoNothing; 1758 1759 if (sourceDataFormat == dstDataFormat && alphaOp == AlphaDoNothing) { 1760 const uint8_t* ptr = sourceData; 1761 const uint8_t* ptrEnd = sourceData + srcStride * height; 1762 unsigned rowSize = (dstStride > 0) ? dstStride: -dstStride; 1763 uint8_t* dst = static_cast<uint8_t*>(destinationData); 1764 while (ptr < ptrEnd) { 1765 memcpy(dst, ptr, rowSize); 1766 ptr += srcStride; 1767 dst += dstStride; 1768 } 1769 return true; 1770 } 1771 1772 FormatConverter converter(width, height, sourceData, destinationData, srcStride, dstStride); 1773 converter.convert(sourceDataFormat, dstDataFormat, alphaOp); 1774 if (!converter.Success()) 1775 return false; 1776 return true; 1777} 1778 1779} // namespace blink 1780