1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 2010 Mozilla Corporation. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "core/platform/graphics/GraphicsContext3D.h" 29 30 #include "core/html/ImageData.h" 31 #include "core/html/canvas/CheckedInt.h" 32 #include "core/platform/graphics/ImageObserver.h" 33 #include "core/platform/graphics/cpu/arm/GraphicsContext3DNEON.h" 34 #include "core/platform/image-decoders/ImageDecoder.h" 35 36 namespace WebCore { 37 38 namespace { 39 40 GraphicsContext3D::DataFormat getDataFormat(GC3Denum destinationFormat, GC3Denum destinationType) 41 { 42 GraphicsContext3D::DataFormat dstFormat = GraphicsContext3D::DataFormatRGBA8; 43 switch (destinationType) { 44 case GraphicsContext3D::UNSIGNED_BYTE: 45 switch (destinationFormat) { 46 case GraphicsContext3D::RGB: 47 dstFormat = GraphicsContext3D::DataFormatRGB8; 48 break; 49 case GraphicsContext3D::RGBA: 50 dstFormat = GraphicsContext3D::DataFormatRGBA8; 51 break; 52 case GraphicsContext3D::ALPHA: 53 dstFormat = GraphicsContext3D::DataFormatA8; 54 break; 55 case GraphicsContext3D::LUMINANCE: 56 dstFormat = GraphicsContext3D::DataFormatR8; 57 break; 58 case GraphicsContext3D::LUMINANCE_ALPHA: 59 dstFormat = GraphicsContext3D::DataFormatRA8; 60 break; 61 default: 62 ASSERT_NOT_REACHED(); 63 } 64 break; 65 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: 66 dstFormat = GraphicsContext3D::DataFormatRGBA4444; 67 break; 68 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: 69 dstFormat = GraphicsContext3D::DataFormatRGBA5551; 70 break; 71 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: 72 dstFormat = GraphicsContext3D::DataFormatRGB565; 73 break; 74 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float 75 switch (destinationFormat) { 76 case GraphicsContext3D::RGB: 77 dstFormat = GraphicsContext3D::DataFormatRGB16F; 78 break; 79 case GraphicsContext3D::RGBA: 80 dstFormat = GraphicsContext3D::DataFormatRGBA16F; 81 break; 82 case GraphicsContext3D::ALPHA: 83 dstFormat = GraphicsContext3D::DataFormatA16F; 84 break; 85 case GraphicsContext3D::LUMINANCE: 86 dstFormat = GraphicsContext3D::DataFormatR16F; 87 break; 88 case GraphicsContext3D::LUMINANCE_ALPHA: 89 dstFormat = GraphicsContext3D::DataFormatRA16F; 90 break; 91 default: 92 ASSERT_NOT_REACHED(); 93 } 94 break; 95 case GraphicsContext3D::FLOAT: // OES_texture_float 96 switch (destinationFormat) { 97 case GraphicsContext3D::RGB: 98 dstFormat = GraphicsContext3D::DataFormatRGB32F; 99 break; 100 case GraphicsContext3D::RGBA: 101 dstFormat = GraphicsContext3D::DataFormatRGBA32F; 102 break; 103 case GraphicsContext3D::ALPHA: 104 dstFormat = GraphicsContext3D::DataFormatA32F; 105 break; 106 case GraphicsContext3D::LUMINANCE: 107 dstFormat = GraphicsContext3D::DataFormatR32F; 108 break; 109 case GraphicsContext3D::LUMINANCE_ALPHA: 110 dstFormat = GraphicsContext3D::DataFormatRA32F; 111 break; 112 default: 113 ASSERT_NOT_REACHED(); 114 } 115 break; 116 default: 117 ASSERT_NOT_REACHED(); 118 } 119 return dstFormat; 120 } 121 122 // Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf, 123 // "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010). 124 // Specially, the basetable[512] and shifttable[512] are generated as follows: 125 /* 126 unsigned short basetable[512]; 127 unsigned char shifttable[512]; 128 129 void generatetables(){ 130 unsigned int i; 131 int e; 132 for (i = 0; i < 256; ++i){ 133 e = i - 127; 134 if (e < -24){ // Very small numbers map to zero 135 basetable[i | 0x000] = 0x0000; 136 basetable[i | 0x100] = 0x8000; 137 shifttable[i | 0x000] = 24; 138 shifttable[i | 0x100] = 24; 139 } 140 else if (e < -14) { // Small numbers map to denorms 141 basetable[i | 0x000] = (0x0400>>(-e-14)); 142 basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000; 143 shifttable[i | 0x000] = -e-1; 144 shifttable[i | 0x100] = -e-1; 145 } 146 else if (e <= 15){ // Normal numbers just lose precision 147 basetable[i | 0x000] = ((e+15)<<10); 148 basetable[i| 0x100] = ((e+15)<<10) | 0x8000; 149 shifttable[i|0x000] = 13; 150 shifttable[i|0x100] = 13; 151 } 152 else if (e<128){ // Large numbers map to Infinity 153 basetable[i|0x000] = 0x7C00; 154 basetable[i|0x100] = 0xFC00; 155 shifttable[i|0x000] = 24; 156 shifttable[i|0x100] = 24; 157 } 158 else { // Infinity and NaN's stay Infinity and NaN's 159 basetable[i|0x000] = 0x7C00; 160 basetable[i|0x100] = 0xFC00; 161 shifttable[i|0x000] = 13; 162 shifttable[i|0x100] = 13; 163 } 164 } 165 } 166 */ 167 168 unsigned short baseTable[512] = { 169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 176 512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 177 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744, 178 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 179 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 180 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 181 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 182 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 183 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 184 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 185 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 186 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 187 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 188 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 189 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 190 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 191 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776, 32784, 32800, 32832, 32896, 33024, 192 33280, 33792, 34816, 35840, 36864, 37888, 38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, 193 49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416, 61440, 62464, 63488, 64512, 194 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 195 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 196 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 197 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 198 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 199 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 200 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512 201 }; 202 203 unsigned char shiftTable[512] = { 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, 24, 24, 24, 24, 24, 24, 24, 24, 24, 206 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 207 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 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, 23, 22, 21, 20, 19, 18, 17, 16, 15, 211 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 212 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 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, 24, 215 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 216 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 217 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 218 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 219 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13, 220 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 221 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 222 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 223 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 224 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 225 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 226 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 227 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 228 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 229 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 230 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 231 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 232 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 233 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 234 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 235 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 236 }; 237 238 unsigned short convertFloatToHalfFloat(float f) 239 { 240 unsigned temp = *(reinterpret_cast<unsigned *>(&f)); 241 unsigned signexp = (temp >> 23) & 0x1ff; 242 return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]); 243 } 244 245 /* BEGIN CODE SHARED WITH MOZILLA FIREFOX */ 246 247 // The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup. 248 // Explicit template specializations correspond to the cases that would occur. 249 // Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h 250 251 //---------------------------------------------------------------------- 252 // Pixel unpacking routines. 253 template<int format, typename SourceType, typename DstType> 254 void unpack(const SourceType*, DstType*, unsigned) 255 { 256 ASSERT_NOT_REACHED(); 257 } 258 259 template<> void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 260 { 261 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 262 destination[0] = source[0]; 263 destination[1] = source[1]; 264 destination[2] = source[2]; 265 destination[3] = 0xFF; 266 source += 3; 267 destination += 4; 268 } 269 } 270 271 template<> void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 272 { 273 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 274 destination[0] = source[2]; 275 destination[1] = source[1]; 276 destination[2] = source[0]; 277 destination[3] = 0xFF; 278 source += 3; 279 destination += 4; 280 } 281 } 282 283 template<> void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 284 { 285 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 286 destination[0] = source[1]; 287 destination[1] = source[2]; 288 destination[2] = source[3]; 289 destination[3] = source[0]; 290 source += 4; 291 destination += 4; 292 } 293 } 294 295 template<> void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 296 { 297 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 298 destination[0] = source[3]; 299 destination[1] = source[2]; 300 destination[2] = source[1]; 301 destination[3] = source[0]; 302 source += 4; 303 destination += 4; 304 } 305 } 306 307 template<> void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 308 { 309 const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source); 310 uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination); 311 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 312 uint32_t bgra = source32[i]; 313 #if CPU(BIG_ENDIAN) 314 uint32_t brMask = 0xff00ff00; 315 uint32_t gaMask = 0x00ff00ff; 316 #else 317 uint32_t brMask = 0x00ff00ff; 318 uint32_t gaMask = 0xff00ff00; 319 #endif 320 uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask); 321 destination32[i] = rgba; 322 } 323 } 324 325 template<> void unpack<GraphicsContext3D::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 326 { 327 #if HAVE(ARM_NEON_INTRINSICS) 328 SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow); 329 #endif 330 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 331 uint16_t packedValue = source[0]; 332 uint8_t r = packedValue >> 11; 333 uint8_t g = (packedValue >> 6) & 0x1F; 334 uint8_t b = (packedValue >> 1) & 0x1F; 335 destination[0] = (r << 3) | (r & 0x7); 336 destination[1] = (g << 3) | (g & 0x7); 337 destination[2] = (b << 3) | (b & 0x7); 338 destination[3] = (packedValue & 0x1) ? 0xFF : 0x0; 339 source += 1; 340 destination += 4; 341 } 342 } 343 344 template<> void unpack<GraphicsContext3D::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 345 { 346 #if HAVE(ARM_NEON_INTRINSICS) 347 SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow); 348 #endif 349 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 350 uint16_t packedValue = source[0]; 351 uint8_t r = packedValue >> 12; 352 uint8_t g = (packedValue >> 8) & 0x0F; 353 uint8_t b = (packedValue >> 4) & 0x0F; 354 uint8_t a = packedValue & 0x0F; 355 destination[0] = r << 4 | r; 356 destination[1] = g << 4 | g; 357 destination[2] = b << 4 | b; 358 destination[3] = a << 4 | a; 359 source += 1; 360 destination += 4; 361 } 362 } 363 364 template<> void unpack<GraphicsContext3D::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 365 { 366 #if HAVE(ARM_NEON_INTRINSICS) 367 SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow); 368 #endif 369 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 370 uint16_t packedValue = source[0]; 371 uint8_t r = packedValue >> 11; 372 uint8_t g = (packedValue >> 5) & 0x3F; 373 uint8_t b = packedValue & 0x1F; 374 destination[0] = (r << 3) | (r & 0x7); 375 destination[1] = (g << 2) | (g & 0x3); 376 destination[2] = (b << 3) | (b & 0x7); 377 destination[3] = 0xFF; 378 source += 1; 379 destination += 4; 380 } 381 } 382 383 template<> void unpack<GraphicsContext3D::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 384 { 385 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 386 destination[0] = source[0]; 387 destination[1] = source[0]; 388 destination[2] = source[0]; 389 destination[3] = 0xFF; 390 source += 1; 391 destination += 4; 392 } 393 } 394 395 template<> void unpack<GraphicsContext3D::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 396 { 397 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 398 destination[0] = source[0]; 399 destination[1] = source[0]; 400 destination[2] = source[0]; 401 destination[3] = source[1]; 402 source += 2; 403 destination += 4; 404 } 405 } 406 407 template<> void unpack<GraphicsContext3D::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 408 { 409 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 410 destination[0] = source[1]; 411 destination[1] = source[1]; 412 destination[2] = source[1]; 413 destination[3] = source[0]; 414 source += 2; 415 destination += 4; 416 } 417 } 418 419 template<> void unpack<GraphicsContext3D::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 420 { 421 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 422 destination[0] = 0x0; 423 destination[1] = 0x0; 424 destination[2] = 0x0; 425 destination[3] = source[0]; 426 source += 1; 427 destination += 4; 428 } 429 } 430 431 template<> void unpack<GraphicsContext3D::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 432 { 433 const float scaleFactor = 1.0f / 255.0f; 434 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 435 destination[0] = source[0] * scaleFactor; 436 destination[1] = source[1] * scaleFactor; 437 destination[2] = source[2] * scaleFactor; 438 destination[3] = source[3] * scaleFactor; 439 source += 4; 440 destination += 4; 441 } 442 } 443 444 template<> void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 445 { 446 const float scaleFactor = 1.0f / 255.0f; 447 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 448 destination[0] = source[2] * scaleFactor; 449 destination[1] = source[1] * scaleFactor; 450 destination[2] = source[0] * scaleFactor; 451 destination[3] = source[3] * scaleFactor; 452 source += 4; 453 destination += 4; 454 } 455 } 456 457 template<> void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 458 { 459 const float scaleFactor = 1.0f / 255.0f; 460 for (unsigned i = 0; i < pixelsPerRow; ++i) { 461 destination[0] = source[3] * scaleFactor; 462 destination[1] = source[2] * scaleFactor; 463 destination[2] = source[1] * scaleFactor; 464 destination[3] = source[0] * scaleFactor; 465 source += 4; 466 destination += 4; 467 } 468 } 469 470 template<> void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 471 { 472 const float scaleFactor = 1.0f / 255.0f; 473 for (unsigned i = 0; i < pixelsPerRow; ++i) { 474 destination[0] = source[1] * scaleFactor; 475 destination[1] = source[2] * scaleFactor; 476 destination[2] = source[3] * scaleFactor; 477 destination[3] = source[0] * scaleFactor; 478 source += 4; 479 destination += 4; 480 } 481 } 482 483 template<> void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 484 { 485 const float scaleFactor = 1.0f / 255.0f; 486 for (unsigned i = 0; i < pixelsPerRow; ++i) { 487 destination[0] = source[0] * scaleFactor; 488 destination[1] = source[1] * scaleFactor; 489 destination[2] = source[2] * scaleFactor; 490 destination[3] = 1; 491 source += 3; 492 destination += 4; 493 } 494 } 495 496 template<> void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 497 { 498 const float scaleFactor = 1.0f / 255.0f; 499 for (unsigned i = 0; i < pixelsPerRow; ++i) { 500 destination[0] = source[2] * scaleFactor; 501 destination[1] = source[1] * scaleFactor; 502 destination[2] = source[0] * scaleFactor; 503 destination[3] = 1; 504 source += 3; 505 destination += 4; 506 } 507 } 508 509 template<> void unpack<GraphicsContext3D::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 510 { 511 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 512 destination[0] = source[0]; 513 destination[1] = source[1]; 514 destination[2] = source[2]; 515 destination[3] = 1; 516 source += 3; 517 destination += 4; 518 } 519 } 520 521 template<> void unpack<GraphicsContext3D::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 522 { 523 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 524 destination[0] = source[0]; 525 destination[1] = source[0]; 526 destination[2] = source[0]; 527 destination[3] = 1; 528 source += 1; 529 destination += 4; 530 } 531 } 532 533 template<> void unpack<GraphicsContext3D::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 534 { 535 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 536 destination[0] = source[0]; 537 destination[1] = source[0]; 538 destination[2] = source[0]; 539 destination[3] = source[1]; 540 source += 2; 541 destination += 4; 542 } 543 } 544 545 template<> void unpack<GraphicsContext3D::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 546 { 547 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 548 destination[0] = 0; 549 destination[1] = 0; 550 destination[2] = 0; 551 destination[3] = source[0]; 552 source += 1; 553 destination += 4; 554 } 555 } 556 557 //---------------------------------------------------------------------- 558 // Pixel packing routines. 559 // 560 561 template<int format, int alphaOp, typename SourceType, typename DstType> 562 void pack(const SourceType*, DstType*, unsigned) 563 { 564 ASSERT_NOT_REACHED(); 565 } 566 567 template<> void pack<GraphicsContext3D::DataFormatA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 568 { 569 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 570 destination[0] = source[3]; 571 source += 4; 572 destination += 1; 573 } 574 } 575 576 template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 577 { 578 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 579 destination[0] = source[0]; 580 source += 4; 581 destination += 1; 582 } 583 } 584 585 template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 586 { 587 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 588 float scaleFactor = source[3] / 255.0f; 589 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 590 destination[0] = sourceR; 591 source += 4; 592 destination += 1; 593 } 594 } 595 596 // FIXME: this routine is lossy and must be removed. 597 template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 598 { 599 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 600 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 601 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 602 destination[0] = sourceR; 603 source += 4; 604 destination += 1; 605 } 606 } 607 608 template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 609 { 610 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 611 destination[0] = source[0]; 612 destination[1] = source[3]; 613 source += 4; 614 destination += 2; 615 } 616 } 617 618 template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 619 { 620 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 621 float scaleFactor = source[3] / 255.0f; 622 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 623 destination[0] = sourceR; 624 destination[1] = source[3]; 625 source += 4; 626 destination += 2; 627 } 628 } 629 630 // FIXME: this routine is lossy and must be removed. 631 template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 632 { 633 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 634 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 635 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 636 destination[0] = sourceR; 637 destination[1] = source[3]; 638 source += 4; 639 destination += 2; 640 } 641 } 642 643 template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 644 { 645 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 646 destination[0] = source[0]; 647 destination[1] = source[1]; 648 destination[2] = source[2]; 649 source += 4; 650 destination += 3; 651 } 652 } 653 654 template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 655 { 656 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 657 float scaleFactor = source[3] / 255.0f; 658 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 659 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 660 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 661 destination[0] = sourceR; 662 destination[1] = sourceG; 663 destination[2] = sourceB; 664 source += 4; 665 destination += 3; 666 } 667 } 668 669 // FIXME: this routine is lossy and must be removed. 670 template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 671 { 672 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 673 float scaleFactor = source[3] ? 255.0f / source[3] : 1.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 source += 4; 681 destination += 3; 682 } 683 } 684 685 686 template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 687 { 688 memcpy(destination, source, pixelsPerRow * 4); 689 } 690 691 template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 692 { 693 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 694 float scaleFactor = source[3] / 255.0f; 695 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 696 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 697 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 698 destination[0] = sourceR; 699 destination[1] = sourceG; 700 destination[2] = sourceB; 701 destination[3] = source[3]; 702 source += 4; 703 destination += 4; 704 } 705 } 706 707 // FIXME: this routine is lossy and must be removed. 708 template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 709 { 710 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 711 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 712 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 713 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 714 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 715 destination[0] = sourceR; 716 destination[1] = sourceG; 717 destination[2] = sourceB; 718 destination[3] = source[3]; 719 source += 4; 720 destination += 4; 721 } 722 } 723 724 template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 725 { 726 #if HAVE(ARM_NEON_INTRINSICS) 727 SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow); 728 #endif 729 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 730 *destination = (((source[0] & 0xF0) << 8) 731 | ((source[1] & 0xF0) << 4) 732 | (source[2] & 0xF0) 733 | (source[3] >> 4)); 734 source += 4; 735 destination += 1; 736 } 737 } 738 739 template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 740 { 741 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 742 float scaleFactor = source[3] / 255.0f; 743 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 744 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 745 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 746 *destination = (((sourceR & 0xF0) << 8) 747 | ((sourceG & 0xF0) << 4) 748 | (sourceB & 0xF0) 749 | (source[3] >> 4)); 750 source += 4; 751 destination += 1; 752 } 753 } 754 755 // FIXME: this routine is lossy and must be removed. 756 template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 757 { 758 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 759 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 760 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 761 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 762 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 763 *destination = (((sourceR & 0xF0) << 8) 764 | ((sourceG & 0xF0) << 4) 765 | (sourceB & 0xF0) 766 | (source[3] >> 4)); 767 source += 4; 768 destination += 1; 769 } 770 } 771 772 template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 773 { 774 #if HAVE(ARM_NEON_INTRINSICS) 775 SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow); 776 #endif 777 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 778 *destination = (((source[0] & 0xF8) << 8) 779 | ((source[1] & 0xF8) << 3) 780 | ((source[2] & 0xF8) >> 2) 781 | (source[3] >> 7)); 782 source += 4; 783 destination += 1; 784 } 785 } 786 787 template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 788 { 789 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 790 float scaleFactor = source[3] / 255.0f; 791 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 792 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 793 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 794 *destination = (((sourceR & 0xF8) << 8) 795 | ((sourceG & 0xF8) << 3) 796 | ((sourceB & 0xF8) >> 2) 797 | (source[3] >> 7)); 798 source += 4; 799 destination += 1; 800 } 801 } 802 803 // FIXME: this routine is lossy and must be removed. 804 template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 805 { 806 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 807 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 808 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 809 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 810 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 811 *destination = (((sourceR & 0xF8) << 8) 812 | ((sourceG & 0xF8) << 3) 813 | ((sourceB & 0xF8) >> 2) 814 | (source[3] >> 7)); 815 source += 4; 816 destination += 1; 817 } 818 } 819 820 template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 821 { 822 #if HAVE(ARM_NEON_INTRINSICS) 823 SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow); 824 #endif 825 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 826 *destination = (((source[0] & 0xF8) << 8) 827 | ((source[1] & 0xFC) << 3) 828 | ((source[2] & 0xF8) >> 3)); 829 source += 4; 830 destination += 1; 831 } 832 } 833 834 template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 835 { 836 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 837 float scaleFactor = source[3] / 255.0f; 838 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 839 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 840 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 841 *destination = (((sourceR & 0xF8) << 8) 842 | ((sourceG & 0xFC) << 3) 843 | ((sourceB & 0xF8) >> 3)); 844 source += 4; 845 destination += 1; 846 } 847 } 848 849 // FIXME: this routine is lossy and must be removed. 850 template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 851 { 852 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 853 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 854 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 855 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 856 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 857 *destination = (((sourceR & 0xF8) << 8) 858 | ((sourceG & 0xFC) << 3) 859 | ((sourceB & 0xF8) >> 3)); 860 source += 4; 861 destination += 1; 862 } 863 } 864 865 template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 866 { 867 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 868 destination[0] = source[0]; 869 destination[1] = source[1]; 870 destination[2] = source[2]; 871 source += 4; 872 destination += 3; 873 } 874 } 875 876 template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 877 { 878 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 879 float scaleFactor = source[3]; 880 destination[0] = source[0] * scaleFactor; 881 destination[1] = source[1] * scaleFactor; 882 destination[2] = source[2] * scaleFactor; 883 source += 4; 884 destination += 3; 885 } 886 } 887 888 template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 889 { 890 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 891 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 892 destination[0] = source[0] * scaleFactor; 893 destination[1] = source[1] * scaleFactor; 894 destination[2] = source[2] * scaleFactor; 895 source += 4; 896 destination += 3; 897 } 898 } 899 900 // Used only during RGBA8 or BGRA8 -> floating-point uploads. 901 template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 902 { 903 memcpy(destination, source, pixelsPerRow * 4 * sizeof(float)); 904 } 905 906 template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 907 { 908 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 909 float scaleFactor = source[3]; 910 destination[0] = source[0] * scaleFactor; 911 destination[1] = source[1] * scaleFactor; 912 destination[2] = source[2] * scaleFactor; 913 destination[3] = source[3]; 914 source += 4; 915 destination += 4; 916 } 917 } 918 919 template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 920 { 921 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 922 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 923 destination[0] = source[0] * scaleFactor; 924 destination[1] = source[1] * scaleFactor; 925 destination[2] = source[2] * scaleFactor; 926 destination[3] = source[3]; 927 source += 4; 928 destination += 4; 929 } 930 } 931 932 template<> void pack<GraphicsContext3D::DataFormatA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 933 { 934 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 935 destination[0] = source[3]; 936 source += 4; 937 destination += 1; 938 } 939 } 940 941 template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 942 { 943 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 944 destination[0] = source[0]; 945 source += 4; 946 destination += 1; 947 } 948 } 949 950 template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 951 { 952 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 953 float scaleFactor = source[3]; 954 destination[0] = source[0] * scaleFactor; 955 source += 4; 956 destination += 1; 957 } 958 } 959 960 template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 961 { 962 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 963 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 964 destination[0] = source[0] * scaleFactor; 965 source += 4; 966 destination += 1; 967 } 968 } 969 970 template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 971 { 972 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 973 destination[0] = source[0]; 974 destination[1] = source[3]; 975 source += 4; 976 destination += 2; 977 } 978 } 979 980 template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 981 { 982 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 983 float scaleFactor = source[3]; 984 destination[0] = source[0] * scaleFactor; 985 destination[1] = source[3]; 986 source += 4; 987 destination += 2; 988 } 989 } 990 991 template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 992 { 993 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 994 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 995 destination[0] = source[0] * scaleFactor; 996 destination[1] = source[3]; 997 source += 4; 998 destination += 2; 999 } 1000 } 1001 1002 template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1003 { 1004 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1005 destination[0] = convertFloatToHalfFloat(source[0]); 1006 destination[1] = convertFloatToHalfFloat(source[1]); 1007 destination[2] = convertFloatToHalfFloat(source[2]); 1008 destination[3] = convertFloatToHalfFloat(source[3]); 1009 source += 4; 1010 destination += 4; 1011 } 1012 } 1013 1014 template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1015 { 1016 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1017 float scaleFactor = source[3]; 1018 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1019 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1020 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1021 destination[3] = convertFloatToHalfFloat(source[3]); 1022 source += 4; 1023 destination += 4; 1024 } 1025 } 1026 1027 template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1028 { 1029 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1030 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1031 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1032 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1033 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1034 destination[3] = convertFloatToHalfFloat(source[3]); 1035 source += 4; 1036 destination += 4; 1037 } 1038 } 1039 1040 template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1041 { 1042 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1043 destination[0] = convertFloatToHalfFloat(source[0]); 1044 destination[1] = convertFloatToHalfFloat(source[1]); 1045 destination[2] = convertFloatToHalfFloat(source[2]); 1046 source += 4; 1047 destination += 3; 1048 } 1049 } 1050 1051 template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1052 { 1053 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1054 float scaleFactor = source[3]; 1055 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1056 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1057 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1058 source += 4; 1059 destination += 3; 1060 } 1061 } 1062 1063 template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1064 { 1065 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1066 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1067 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1068 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 1069 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 1070 source += 4; 1071 destination += 3; 1072 } 1073 } 1074 1075 template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1076 { 1077 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1078 destination[0] = convertFloatToHalfFloat(source[0]); 1079 destination[1] = convertFloatToHalfFloat(source[3]); 1080 source += 4; 1081 destination += 2; 1082 } 1083 } 1084 1085 template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1086 { 1087 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1088 float scaleFactor = source[3]; 1089 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1090 destination[1] = convertFloatToHalfFloat(source[3]); 1091 source += 4; 1092 destination += 2; 1093 } 1094 } 1095 1096 template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1097 { 1098 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1099 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1100 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1101 destination[1] = convertFloatToHalfFloat(source[3]); 1102 source += 4; 1103 destination += 2; 1104 } 1105 } 1106 1107 template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1108 { 1109 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1110 destination[0] = convertFloatToHalfFloat(source[0]); 1111 source += 4; 1112 destination += 1; 1113 } 1114 } 1115 1116 template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1117 { 1118 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1119 float scaleFactor = source[3]; 1120 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1121 source += 4; 1122 destination += 1; 1123 } 1124 } 1125 1126 template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1127 { 1128 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1129 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1130 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1131 source += 4; 1132 destination += 1; 1133 } 1134 } 1135 1136 template<> void pack<GraphicsContext3D::DataFormatA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1137 { 1138 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1139 destination[0] = convertFloatToHalfFloat(source[3]); 1140 source += 4; 1141 destination += 1; 1142 } 1143 } 1144 1145 bool HasAlpha(int format) 1146 { 1147 return format == GraphicsContext3D::DataFormatA8 1148 || format == GraphicsContext3D::DataFormatA16F 1149 || format == GraphicsContext3D::DataFormatA32F 1150 || format == GraphicsContext3D::DataFormatRA8 1151 || format == GraphicsContext3D::DataFormatAR8 1152 || format == GraphicsContext3D::DataFormatRA16F 1153 || format == GraphicsContext3D::DataFormatRA32F 1154 || format == GraphicsContext3D::DataFormatRGBA8 1155 || format == GraphicsContext3D::DataFormatBGRA8 1156 || format == GraphicsContext3D::DataFormatARGB8 1157 || format == GraphicsContext3D::DataFormatABGR8 1158 || format == GraphicsContext3D::DataFormatRGBA16F 1159 || format == GraphicsContext3D::DataFormatRGBA32F 1160 || format == GraphicsContext3D::DataFormatRGBA4444 1161 || format == GraphicsContext3D::DataFormatRGBA5551; 1162 } 1163 1164 bool HasColor(int format) 1165 { 1166 return format == GraphicsContext3D::DataFormatRGBA8 1167 || format == GraphicsContext3D::DataFormatRGBA16F 1168 || format == GraphicsContext3D::DataFormatRGBA32F 1169 || format == GraphicsContext3D::DataFormatRGB8 1170 || format == GraphicsContext3D::DataFormatRGB16F 1171 || format == GraphicsContext3D::DataFormatRGB32F 1172 || format == GraphicsContext3D::DataFormatBGR8 1173 || format == GraphicsContext3D::DataFormatBGRA8 1174 || format == GraphicsContext3D::DataFormatARGB8 1175 || format == GraphicsContext3D::DataFormatABGR8 1176 || format == GraphicsContext3D::DataFormatRGBA5551 1177 || format == GraphicsContext3D::DataFormatRGBA4444 1178 || format == GraphicsContext3D::DataFormatRGB565 1179 || format == GraphicsContext3D::DataFormatR8 1180 || format == GraphicsContext3D::DataFormatR16F 1181 || format == GraphicsContext3D::DataFormatR32F 1182 || format == GraphicsContext3D::DataFormatRA8 1183 || format == GraphicsContext3D::DataFormatRA16F 1184 || format == GraphicsContext3D::DataFormatRA32F 1185 || format == GraphicsContext3D::DataFormatAR8; 1186 } 1187 1188 template<int Format> 1189 struct IsFloatFormat { 1190 static const bool Value = 1191 Format == GraphicsContext3D::DataFormatRGBA32F 1192 || Format == GraphicsContext3D::DataFormatRGB32F 1193 || Format == GraphicsContext3D::DataFormatRA32F 1194 || Format == GraphicsContext3D::DataFormatR32F 1195 || Format == GraphicsContext3D::DataFormatA32F; 1196 }; 1197 1198 template<int Format> 1199 struct IsHalfFloatFormat { 1200 static const bool Value = 1201 Format == GraphicsContext3D::DataFormatRGBA16F 1202 || Format == GraphicsContext3D::DataFormatRGB16F 1203 || Format == GraphicsContext3D::DataFormatRA16F 1204 || Format == GraphicsContext3D::DataFormatR16F 1205 || Format == GraphicsContext3D::DataFormatA16F; 1206 }; 1207 1208 template<int Format> 1209 struct Is16bppFormat { 1210 static const bool Value = 1211 Format == GraphicsContext3D::DataFormatRGBA5551 1212 || Format == GraphicsContext3D::DataFormatRGBA4444 1213 || Format == GraphicsContext3D::DataFormatRGB565; 1214 }; 1215 1216 template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value> 1217 struct DataTypeForFormat { 1218 typedef uint8_t Type; 1219 }; 1220 1221 template<int Format> 1222 struct DataTypeForFormat<Format, true, false, false> { 1223 typedef float Type; 1224 }; 1225 1226 template<int Format> 1227 struct DataTypeForFormat<Format, false, true, false> { 1228 typedef uint16_t Type; 1229 }; 1230 1231 template<int Format> 1232 struct DataTypeForFormat<Format, false, false, true> { 1233 typedef uint16_t Type; 1234 }; 1235 1236 template<int Format> 1237 struct IntermediateFormat { 1238 static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? GraphicsContext3D::DataFormatRGBA32F : GraphicsContext3D::DataFormatRGBA8; 1239 }; 1240 1241 unsigned TexelBytesForFormat(GraphicsContext3D::DataFormat format) 1242 { 1243 switch (format) { 1244 case GraphicsContext3D::DataFormatR8: 1245 case GraphicsContext3D::DataFormatA8: 1246 return 1; 1247 case GraphicsContext3D::DataFormatRA8: 1248 case GraphicsContext3D::DataFormatAR8: 1249 case GraphicsContext3D::DataFormatRGBA5551: 1250 case GraphicsContext3D::DataFormatRGBA4444: 1251 case GraphicsContext3D::DataFormatRGB565: 1252 case GraphicsContext3D::DataFormatA16F: 1253 case GraphicsContext3D::DataFormatR16F: 1254 return 2; 1255 case GraphicsContext3D::DataFormatRGB8: 1256 case GraphicsContext3D::DataFormatBGR8: 1257 return 3; 1258 case GraphicsContext3D::DataFormatRGBA8: 1259 case GraphicsContext3D::DataFormatARGB8: 1260 case GraphicsContext3D::DataFormatABGR8: 1261 case GraphicsContext3D::DataFormatBGRA8: 1262 case GraphicsContext3D::DataFormatR32F: 1263 case GraphicsContext3D::DataFormatA32F: 1264 case GraphicsContext3D::DataFormatRA16F: 1265 return 4; 1266 case GraphicsContext3D::DataFormatRGB16F: 1267 return 6; 1268 case GraphicsContext3D::DataFormatRA32F: 1269 case GraphicsContext3D::DataFormatRGBA16F: 1270 return 8; 1271 case GraphicsContext3D::DataFormatRGB32F: 1272 return 12; 1273 case GraphicsContext3D::DataFormatRGBA32F: 1274 return 16; 1275 default: 1276 return 0; 1277 } 1278 } 1279 1280 /* END CODE SHARED WITH MOZILLA FIREFOX */ 1281 1282 class FormatConverter { 1283 public: 1284 FormatConverter(unsigned width, unsigned height, 1285 const void* srcStart, void* dstStart, int srcStride, int dstStride) 1286 : m_width(width), m_height(height), m_srcStart(srcStart), m_dstStart(dstStart), m_srcStride(srcStride), m_dstStride(dstStride), m_success(false) 1287 { 1288 const unsigned MaxNumberOfComponents = 4; 1289 const unsigned MaxBytesPerComponent = 4; 1290 m_unpackedIntermediateSrcData = adoptArrayPtr(new uint8_t[m_width * MaxNumberOfComponents *MaxBytesPerComponent]); 1291 ASSERT(m_unpackedIntermediateSrcData.get()); 1292 } 1293 1294 void convert(GraphicsContext3D::DataFormat srcFormat, GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp); 1295 bool Success() const { return m_success; } 1296 1297 private: 1298 template<GraphicsContext3D::DataFormat SrcFormat> 1299 void convert(GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp); 1300 1301 template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat> 1302 void convert(GraphicsContext3D::AlphaOp); 1303 1304 template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat, GraphicsContext3D::AlphaOp alphaOp> 1305 void convert(); 1306 1307 const unsigned m_width, m_height; 1308 const void* const m_srcStart; 1309 void* const m_dstStart; 1310 const int m_srcStride, m_dstStride; 1311 bool m_success; 1312 OwnArrayPtr<uint8_t> m_unpackedIntermediateSrcData; 1313 }; 1314 1315 void FormatConverter::convert(GraphicsContext3D::DataFormat srcFormat, GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp) 1316 { 1317 #define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \ 1318 case SrcFormat: \ 1319 return convert<SrcFormat>(dstFormat, alphaOp); 1320 1321 switch (srcFormat) { 1322 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR8) 1323 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA8) 1324 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR32F) 1325 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA32F) 1326 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA8) 1327 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA32F) 1328 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB8) 1329 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGR8) 1330 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB565) 1331 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB32F) 1332 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA8) 1333 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatARGB8) 1334 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatABGR8) 1335 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatAR8) 1336 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGRA8) 1337 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA5551) 1338 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA4444) 1339 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA32F) 1340 default: 1341 ASSERT_NOT_REACHED(); 1342 } 1343 #undef FORMATCONVERTER_CASE_SRCFORMAT 1344 } 1345 1346 template<GraphicsContext3D::DataFormat SrcFormat> 1347 void FormatConverter::convert(GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp) 1348 { 1349 #define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \ 1350 case DstFormat: \ 1351 return convert<SrcFormat, DstFormat>(alphaOp); 1352 1353 switch (dstFormat) { 1354 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR8) 1355 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR16F) 1356 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR32F) 1357 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA8) 1358 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA16F) 1359 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA32F) 1360 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA8) 1361 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA16F) 1362 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA32F) 1363 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB8) 1364 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB565) 1365 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB16F) 1366 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB32F) 1367 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA8) 1368 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA5551) 1369 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA4444) 1370 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA16F) 1371 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA32F) 1372 default: 1373 ASSERT_NOT_REACHED(); 1374 } 1375 1376 #undef FORMATCONVERTER_CASE_DSTFORMAT 1377 } 1378 1379 template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat> 1380 void FormatConverter::convert(GraphicsContext3D::AlphaOp alphaOp) 1381 { 1382 #define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \ 1383 case alphaOp: \ 1384 return convert<SrcFormat, DstFormat, alphaOp>(); 1385 1386 switch (alphaOp) { 1387 FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoNothing) 1388 FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoPremultiply) 1389 FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoUnmultiply) 1390 default: 1391 ASSERT_NOT_REACHED(); 1392 } 1393 #undef FORMATCONVERTER_CASE_ALPHAOP 1394 } 1395 1396 template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat, GraphicsContext3D::AlphaOp alphaOp> 1397 void FormatConverter::convert() 1398 { 1399 // Many instantiations of this template function will never be entered, so we try 1400 // to return immediately in these cases to avoid the compiler to generate useless code. 1401 if (SrcFormat == DstFormat && alphaOp == GraphicsContext3D::AlphaDoNothing) { 1402 ASSERT_NOT_REACHED(); 1403 return; 1404 } 1405 if (!IsFloatFormat<DstFormat>::Value && IsFloatFormat<SrcFormat>::Value) { 1406 ASSERT_NOT_REACHED(); 1407 return; 1408 } 1409 1410 // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat. 1411 const bool srcFormatComesFromDOMElementOrImageData = GraphicsContext3D::srcFormatComeFromDOMElementOrImageData(SrcFormat); 1412 if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) { 1413 ASSERT_NOT_REACHED(); 1414 return; 1415 } 1416 // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied. 1417 if (!srcFormatComesFromDOMElementOrImageData && alphaOp == GraphicsContext3D::AlphaDoUnmultiply) { 1418 ASSERT_NOT_REACHED(); 1419 return; 1420 } 1421 if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && alphaOp != GraphicsContext3D::AlphaDoNothing) { 1422 ASSERT_NOT_REACHED(); 1423 return; 1424 } 1425 1426 typedef typename DataTypeForFormat<SrcFormat>::Type SrcType; 1427 typedef typename DataTypeForFormat<DstFormat>::Type DstType; 1428 const int IntermediateSrcFormat = IntermediateFormat<DstFormat>::Value; 1429 typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType; 1430 const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType); 1431 const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType); 1432 const bool trivialUnpack = (SrcFormat == GraphicsContext3D::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == GraphicsContext3D::DataFormatRGBA32F; 1433 const bool trivialPack = (DstFormat == GraphicsContext3D::DataFormatRGBA8 || DstFormat == GraphicsContext3D::DataFormatRGBA32F) && alphaOp == GraphicsContext3D::AlphaDoNothing && m_dstStride > 0; 1434 ASSERT(!trivialUnpack || !trivialPack); 1435 1436 const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart); 1437 DstType* dstRowStart = static_cast<DstType*>(m_dstStart); 1438 if (!trivialUnpack && trivialPack) { 1439 for (size_t i = 0; i < m_height; ++i) { 1440 unpack<SrcFormat>(srcRowStart, dstRowStart, m_width); 1441 srcRowStart += srcStrideInElements; 1442 dstRowStart += dstStrideInElements; 1443 } 1444 } else if (!trivialUnpack && !trivialPack) { 1445 for (size_t i = 0; i < m_height; ++i) { 1446 unpack<SrcFormat>(srcRowStart, reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), m_width); 1447 pack<DstFormat, alphaOp>(reinterpret_cast<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), dstRowStart, m_width); 1448 srcRowStart += srcStrideInElements; 1449 dstRowStart += dstStrideInElements; 1450 } 1451 } else { 1452 for (size_t i = 0; i < m_height; ++i) { 1453 pack<DstFormat, alphaOp>(srcRowStart, dstRowStart, m_width); 1454 srcRowStart += srcStrideInElements; 1455 dstRowStart += dstStrideInElements; 1456 } 1457 } 1458 m_success = true; 1459 return; 1460 } 1461 1462 } // anonymous namespace 1463 1464 bool GraphicsContext3D::packImageData( 1465 Image* image, 1466 const void* pixels, 1467 GC3Denum format, 1468 GC3Denum type, 1469 bool flipY, 1470 AlphaOp alphaOp, 1471 DataFormat sourceFormat, 1472 unsigned width, 1473 unsigned height, 1474 unsigned sourceUnpackAlignment, 1475 Vector<uint8_t>& data) 1476 { 1477 if (!pixels) 1478 return false; 1479 1480 unsigned packedSize; 1481 // Output data is tightly packed (alignment == 1). 1482 if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR) 1483 return false; 1484 data.resize(packedSize); 1485 1486 if (!packPixels(reinterpret_cast<const uint8_t*>(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY)) 1487 return false; 1488 if (ImageObserver *observer = image->imageObserver()) 1489 observer->didDraw(image); 1490 return true; 1491 } 1492 1493 bool GraphicsContext3D::extractImageData( 1494 ImageData* imageData, 1495 GC3Denum format, 1496 GC3Denum type, 1497 bool flipY, 1498 bool premultiplyAlpha, 1499 Vector<uint8_t>& data) 1500 { 1501 if (!imageData) 1502 return false; 1503 int width = imageData->width(); 1504 int height = imageData->height(); 1505 1506 unsigned packedSize; 1507 // Output data is tightly packed (alignment == 1). 1508 if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR) 1509 return false; 1510 data.resize(packedSize); 1511 1512 if (!packPixels(imageData->data()->data(), DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY)) 1513 return false; 1514 1515 return true; 1516 } 1517 1518 bool GraphicsContext3D::extractTextureData( 1519 unsigned width, 1520 unsigned height, 1521 GC3Denum format, GC3Denum type, 1522 unsigned unpackAlignment, 1523 bool flipY, bool premultiplyAlpha, 1524 const void* pixels, 1525 Vector<uint8_t>& data) 1526 { 1527 // Assumes format, type, etc. have already been validated. 1528 DataFormat sourceDataFormat = getDataFormat(format, type); 1529 1530 // Resize the output buffer. 1531 unsigned int componentsPerPixel, bytesPerComponent; 1532 if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) 1533 return false; 1534 unsigned bytesPerPixel = componentsPerPixel * bytesPerComponent; 1535 data.resize(width * height * bytesPerPixel); 1536 1537 if (!packPixels(static_cast<const uint8_t*>(pixels), sourceDataFormat, width, height, unpackAlignment, format, type, (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data(), flipY)) 1538 return false; 1539 1540 return true; 1541 } 1542 1543 bool GraphicsContext3D::packPixels( 1544 const uint8_t* sourceData, 1545 DataFormat sourceDataFormat, 1546 unsigned width, 1547 unsigned height, 1548 unsigned sourceUnpackAlignment, 1549 unsigned destinationFormat, 1550 unsigned destinationType, 1551 AlphaOp alphaOp, 1552 void* destinationData, 1553 bool flipY) 1554 { 1555 int validSrc = width * TexelBytesForFormat(sourceDataFormat); 1556 int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0; 1557 int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc; 1558 1559 DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType); 1560 int dstStride = width * TexelBytesForFormat(dstDataFormat); 1561 if (flipY) { 1562 destinationData = static_cast<uint8_t*>(destinationData) + dstStride*(height - 1); 1563 dstStride = -dstStride; 1564 } 1565 if (!HasAlpha(sourceDataFormat) || !HasColor(sourceDataFormat) || !HasColor(dstDataFormat)) 1566 alphaOp = AlphaDoNothing; 1567 1568 if (sourceDataFormat == dstDataFormat && alphaOp == AlphaDoNothing) { 1569 const uint8_t* ptr = sourceData; 1570 const uint8_t* ptrEnd = sourceData + srcStride * height; 1571 unsigned rowSize = (dstStride > 0) ? dstStride: -dstStride; 1572 uint8_t* dst = static_cast<uint8_t*>(destinationData); 1573 while (ptr < ptrEnd) { 1574 memcpy(dst, ptr, rowSize); 1575 ptr += srcStride; 1576 dst += dstStride; 1577 } 1578 return true; 1579 } 1580 1581 FormatConverter converter(width, height, sourceData, destinationData, srcStride, dstStride); 1582 converter.convert(sourceDataFormat, dstDataFormat, alphaOp); 1583 if (!converter.Success()) 1584 return false; 1585 return true; 1586 } 1587 1588 } // namespace WebCore 1589 1590