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 15 namespace WebCore { 16 17 namespace { 18 19 WebGLImageConversion::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 /* 105 unsigned short basetable[512]; 106 unsigned char shifttable[512]; 107 108 void 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 147 unsigned short baseTable[512] = { 148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 155 512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 156 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744, 157 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 158 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 159 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 160 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 161 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 162 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 163 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 164 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 165 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 166 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 167 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 168 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 169 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 170 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776, 32784, 32800, 32832, 32896, 33024, 171 33280, 33792, 34816, 35840, 36864, 37888, 38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, 172 49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416, 61440, 62464, 63488, 64512, 173 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 174 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 175 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 176 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 177 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 178 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 179 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512 180 }; 181 182 unsigned char shiftTable[512] = { 183 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 184 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 185 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 186 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 187 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 188 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 189 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 190 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 191 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 192 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 193 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 194 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 195 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 196 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 197 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 198 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13, 199 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 200 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 201 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 202 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 203 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 204 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 205 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 206 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 207 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 208 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 209 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 210 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 211 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 212 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 213 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 214 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 215 }; 216 217 unsigned 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. 232 template<int format, typename SourceType, typename DstType> 233 void unpack(const SourceType*, DstType*, unsigned) 234 { 235 ASSERT_NOT_REACHED(); 236 } 237 238 template<> 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 250 template<> 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 262 template<> 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 274 template<> 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 286 template<> 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 304 template<> 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 323 template<> 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 343 template<> 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 362 template<> 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 374 template<> 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 386 template<> 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 398 template<> 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 410 template<> 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 423 template<> 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 436 template<> 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 449 template<> 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 462 template<> 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 475 template<> 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 488 template<> 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 500 template<> 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 512 template<> 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 524 template<> 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 540 template<int format, int alphaOp, typename SourceType, typename DstType> 541 void pack(const SourceType*, DstType*, unsigned) 542 { 543 ASSERT_NOT_REACHED(); 544 } 545 546 template<> 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 555 template<> 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 564 template<> 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. 576 template<> 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 587 template<> 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 597 template<> 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. 610 template<> 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 622 template<> 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 633 template<> 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. 649 template<> 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 665 template<> 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 670 template<> 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. 687 template<> 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 703 template<> 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 718 template<> 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. 735 template<> 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 751 template<> 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 766 template<> 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. 783 template<> 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 799 template<> 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 813 template<> 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. 829 template<> 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 844 template<> 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 855 template<> 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 867 template<> 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. 880 template<> 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 885 template<> 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 898 template<> 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 911 template<> 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 920 template<> 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 929 template<> 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 939 template<> 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 949 template<> 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 959 template<> 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 970 template<> 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 981 template<> 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 993 template<> 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 1006 template<> 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 1019 template<> 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 1030 template<> 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 1042 template<> 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 1054 template<> 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 1064 template<> 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 1075 template<> 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 1086 template<> 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 1095 template<> 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 1105 template<> 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 1115 template<> 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 1124 bool 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 1143 bool 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 1167 template<int Format> 1168 struct 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 1177 template<int Format> 1178 struct 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 1187 template<int Format> 1188 struct Is16bppFormat { 1189 static const bool Value = 1190 Format == WebGLImageConversion::DataFormatRGBA5551 1191 || Format == WebGLImageConversion::DataFormatRGBA4444 1192 || Format == WebGLImageConversion::DataFormatRGB565; 1193 }; 1194 1195 template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value> 1196 struct DataTypeForFormat { 1197 typedef uint8_t Type; 1198 }; 1199 1200 template<int Format> 1201 struct DataTypeForFormat<Format, true, false, false> { 1202 typedef float Type; 1203 }; 1204 1205 template<int Format> 1206 struct DataTypeForFormat<Format, false, true, false> { 1207 typedef uint16_t Type; 1208 }; 1209 1210 template<int Format> 1211 struct DataTypeForFormat<Format, false, false, true> { 1212 typedef uint16_t Type; 1213 }; 1214 1215 template<int Format> 1216 struct IntermediateFormat { 1217 static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? WebGLImageConversion::DataFormatRGBA32F : WebGLImageConversion::DataFormatRGBA8; 1218 }; 1219 1220 unsigned 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 1261 class FormatConverter { 1262 public: 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 1276 private: 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 1294 void 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 1325 template<WebGLImageConversion::DataFormat SrcFormat> 1326 void 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 1358 template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat> 1359 void 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 1375 template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp> 1376 void 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 1443 bool 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 1494 GLenum 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 1531 WebGLImageConversion::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 1538 WebGLImageConversion::ImageExtractor::~ImageExtractor() 1539 { 1540 if (m_skiaImage) 1541 m_skiaImage->bitmap().unlockPixels(); 1542 } 1543 1544 bool 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() != kPMColor_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 1602 unsigned 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 1626 unsigned 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 1654 bool 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 1683 bool 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 1709 bool 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 1734 bool 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 WebCore 1780