1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 Google Inc. All rights reserved. 4 * Copyright (C) 2010 Mozilla Corporation. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "config.h" 29 30#if USE(3D_GRAPHICS) 31 32#include "FormatConverter.h" 33 34#if HAVE(ARM_NEON_INTRINSICS) 35#include "GraphicsContext3DNEON.h" 36#endif 37 38// Visual Studio crashes with a C1063 Fatal Error if everything is inlined. 39#if COMPILER(MSVC) 40#define ALWAYS_INLINE_EXCEPT_MSVC 41#else 42#define ALWAYS_INLINE_EXCEPT_MSVC ALWAYS_INLINE 43#endif 44 45namespace WebCore { 46 47 48// Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf, 49// "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010). 50// Specially, the basetable[512] and shifttable[512] are generated as follows: 51/* 52unsigned short basetable[512]; 53unsigned char shifttable[512]; 54 55void generatetables(){ 56 unsigned int i; 57 int e; 58 for (i = 0; i < 256; ++i){ 59 e = i - 127; 60 if (e < -24){ // Very small numbers map to zero 61 basetable[i | 0x000] = 0x0000; 62 basetable[i | 0x100] = 0x8000; 63 shifttable[i | 0x000] = 24; 64 shifttable[i | 0x100] = 24; 65 } 66 else if (e < -14) { // Small numbers map to denorms 67 basetable[i | 0x000] = (0x0400>>(-e-14)); 68 basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000; 69 shifttable[i | 0x000] = -e-1; 70 shifttable[i | 0x100] = -e-1; 71 } 72 else if (e <= 15){ // Normal numbers just lose precision 73 basetable[i | 0x000] = ((e+15)<<10); 74 basetable[i| 0x100] = ((e+15)<<10) | 0x8000; 75 shifttable[i|0x000] = 13; 76 shifttable[i|0x100] = 13; 77 } 78 else if (e<128){ // Large numbers map to Infinity 79 basetable[i|0x000] = 0x7C00; 80 basetable[i|0x100] = 0xFC00; 81 shifttable[i|0x000] = 24; 82 shifttable[i|0x100] = 24; 83 } 84 else { // Infinity and NaN's stay Infinity and NaN's 85 basetable[i|0x000] = 0x7C00; 86 basetable[i|0x100] = 0xFC00; 87 shifttable[i|0x000] = 13; 88 shifttable[i|0x100] = 13; 89 } 90 } 91} 92*/ 93 94unsigned short baseTable[512] = { 950, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 960, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 970, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 980, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 990, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1010, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 102512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 10316384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744, 10431744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 10531744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 10631744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 10731744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 10831744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 10931744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 11031744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 11132768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 11232768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 11332768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 11432768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 11532768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 11632768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 11732768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776, 32784, 32800, 32832, 32896, 33024, 11833280, 33792, 34816, 35840, 36864, 37888, 38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, 11949152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416, 61440, 62464, 63488, 64512, 12064512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 12164512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 12264512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 12364512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 12464512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 12564512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 12664512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512 127}; 128 129unsigned char shiftTable[512] = { 13024, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13124, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13224, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13324, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13424, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13524, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13624, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 13714, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13813, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 13924, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14024, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14124, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14224, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14324, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14424, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14524, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13, 14624, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14724, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14824, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 14924, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15024, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15124, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15224, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 15314, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15413, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 15524, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15624, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15724, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15824, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 15924, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 16024, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 16124, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 162}; 163 164inline unsigned short convertFloatToHalfFloat(float f) 165{ 166 unsigned temp = *(reinterpret_cast<unsigned *>(&f)); 167 unsigned signexp = (temp >> 23) & 0x1ff; 168 return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]); 169} 170 171/* BEGIN CODE SHARED WITH MOZILLA FIREFOX */ 172 173// The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup. 174// Explicit template specializations correspond to the cases that would occur. 175// Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h 176 177//---------------------------------------------------------------------- 178// Pixel unpacking routines. 179template<int format, typename SourceType, typename DstType> 180ALWAYS_INLINE void unpack(const SourceType*, DstType*, unsigned) 181{ 182 ASSERT_NOT_REACHED(); 183} 184 185template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 186{ 187 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 188 destination[0] = source[0]; 189 destination[1] = source[1]; 190 destination[2] = source[2]; 191 destination[3] = 0xFF; 192 source += 3; 193 destination += 4; 194 } 195} 196 197template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 198{ 199 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 200 destination[0] = source[2]; 201 destination[1] = source[1]; 202 destination[2] = source[0]; 203 destination[3] = 0xFF; 204 source += 3; 205 destination += 4; 206 } 207} 208 209template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 210{ 211 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 212 destination[0] = source[1]; 213 destination[1] = source[2]; 214 destination[2] = source[3]; 215 destination[3] = source[0]; 216 source += 4; 217 destination += 4; 218 } 219} 220 221template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 222{ 223 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 224 destination[0] = source[3]; 225 destination[1] = source[2]; 226 destination[2] = source[1]; 227 destination[3] = source[0]; 228 source += 4; 229 destination += 4; 230 } 231} 232 233template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 234{ 235 const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source); 236 uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination); 237 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 238 uint32_t bgra = source32[i]; 239#if CPU(BIG_ENDIAN) 240 uint32_t brMask = 0xff00ff00; 241 uint32_t gaMask = 0x00ff00ff; 242#else 243 uint32_t brMask = 0x00ff00ff; 244 uint32_t gaMask = 0xff00ff00; 245#endif 246 uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask); 247 destination32[i] = rgba; 248 } 249} 250 251template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 252{ 253#if HAVE(ARM_NEON_INTRINSICS) 254 SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow); 255#endif 256 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 257 uint16_t packedValue = source[0]; 258 uint8_t r = packedValue >> 11; 259 uint8_t g = (packedValue >> 6) & 0x1F; 260 uint8_t b = (packedValue >> 1) & 0x1F; 261 destination[0] = (r << 3) | (r & 0x7); 262 destination[1] = (g << 3) | (g & 0x7); 263 destination[2] = (b << 3) | (b & 0x7); 264 destination[3] = (packedValue & 0x1) ? 0xFF : 0x0; 265 source += 1; 266 destination += 4; 267 } 268} 269 270template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 271{ 272#if HAVE(ARM_NEON_INTRINSICS) 273 SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow); 274#endif 275 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 276 uint16_t packedValue = source[0]; 277 uint8_t r = packedValue >> 12; 278 uint8_t g = (packedValue >> 8) & 0x0F; 279 uint8_t b = (packedValue >> 4) & 0x0F; 280 uint8_t a = packedValue & 0x0F; 281 destination[0] = r << 4 | r; 282 destination[1] = g << 4 | g; 283 destination[2] = b << 4 | b; 284 destination[3] = a << 4 | a; 285 source += 1; 286 destination += 4; 287 } 288} 289 290template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) 291{ 292#if HAVE(ARM_NEON_INTRINSICS) 293 SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow); 294#endif 295 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 296 uint16_t packedValue = source[0]; 297 uint8_t r = packedValue >> 11; 298 uint8_t g = (packedValue >> 5) & 0x3F; 299 uint8_t b = packedValue & 0x1F; 300 destination[0] = (r << 3) | (r & 0x7); 301 destination[1] = (g << 2) | (g & 0x3); 302 destination[2] = (b << 3) | (b & 0x7); 303 destination[3] = 0xFF; 304 source += 1; 305 destination += 4; 306 } 307} 308 309template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 310{ 311 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 312 destination[0] = source[0]; 313 destination[1] = source[0]; 314 destination[2] = source[0]; 315 destination[3] = 0xFF; 316 source += 1; 317 destination += 4; 318 } 319} 320 321template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 322{ 323 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 324 destination[0] = source[0]; 325 destination[1] = source[0]; 326 destination[2] = source[0]; 327 destination[3] = source[1]; 328 source += 2; 329 destination += 4; 330 } 331} 332 333template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 334{ 335 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 336 destination[0] = source[1]; 337 destination[1] = source[1]; 338 destination[2] = source[1]; 339 destination[3] = source[0]; 340 source += 2; 341 destination += 4; 342 } 343} 344 345template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 346{ 347 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 348 destination[0] = 0x0; 349 destination[1] = 0x0; 350 destination[2] = 0x0; 351 destination[3] = source[0]; 352 source += 1; 353 destination += 4; 354 } 355} 356 357template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 358{ 359 const float scaleFactor = 1.0f / 255.0f; 360 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 361 destination[0] = source[0] * scaleFactor; 362 destination[1] = source[1] * scaleFactor; 363 destination[2] = source[2] * scaleFactor; 364 destination[3] = source[3] * scaleFactor; 365 source += 4; 366 destination += 4; 367 } 368} 369 370template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 371{ 372 const float scaleFactor = 1.0f / 255.0f; 373 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 374 destination[0] = source[2] * scaleFactor; 375 destination[1] = source[1] * scaleFactor; 376 destination[2] = source[0] * scaleFactor; 377 destination[3] = source[3] * scaleFactor; 378 source += 4; 379 destination += 4; 380 } 381} 382 383template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 384{ 385 const float scaleFactor = 1.0f / 255.0f; 386 for (unsigned i = 0; i < pixelsPerRow; ++i) { 387 destination[0] = source[3] * scaleFactor; 388 destination[1] = source[2] * scaleFactor; 389 destination[2] = source[1] * scaleFactor; 390 destination[3] = source[0] * scaleFactor; 391 source += 4; 392 destination += 4; 393 } 394} 395 396template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 397{ 398 const float scaleFactor = 1.0f / 255.0f; 399 for (unsigned i = 0; i < pixelsPerRow; ++i) { 400 destination[0] = source[1] * scaleFactor; 401 destination[1] = source[2] * scaleFactor; 402 destination[2] = source[3] * scaleFactor; 403 destination[3] = source[0] * scaleFactor; 404 source += 4; 405 destination += 4; 406 } 407} 408 409template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 410{ 411 const float scaleFactor = 1.0f / 255.0f; 412 for (unsigned i = 0; i < pixelsPerRow; ++i) { 413 destination[0] = source[0] * scaleFactor; 414 destination[1] = source[1] * scaleFactor; 415 destination[2] = source[2] * scaleFactor; 416 destination[3] = 1; 417 source += 3; 418 destination += 4; 419 } 420} 421 422template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow) 423{ 424 const float scaleFactor = 1.0f / 255.0f; 425 for (unsigned i = 0; i < pixelsPerRow; ++i) { 426 destination[0] = source[2] * scaleFactor; 427 destination[1] = source[1] * scaleFactor; 428 destination[2] = source[0] * scaleFactor; 429 destination[3] = 1; 430 source += 3; 431 destination += 4; 432 } 433} 434 435template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 436{ 437 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 438 destination[0] = source[0]; 439 destination[1] = source[1]; 440 destination[2] = source[2]; 441 destination[3] = 1; 442 source += 3; 443 destination += 4; 444 } 445} 446 447template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 448{ 449 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 450 destination[0] = source[0]; 451 destination[1] = source[0]; 452 destination[2] = source[0]; 453 destination[3] = 1; 454 source += 1; 455 destination += 4; 456 } 457} 458 459template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 460{ 461 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 462 destination[0] = source[0]; 463 destination[1] = source[0]; 464 destination[2] = source[0]; 465 destination[3] = source[1]; 466 source += 2; 467 destination += 4; 468 } 469} 470 471template<> ALWAYS_INLINE void unpack<GraphicsContext3D::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 472{ 473 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 474 destination[0] = 0; 475 destination[1] = 0; 476 destination[2] = 0; 477 destination[3] = source[0]; 478 source += 1; 479 destination += 4; 480 } 481} 482 483//---------------------------------------------------------------------- 484// Pixel packing routines. 485// 486 487template<int format, int alphaOp, typename SourceType, typename DstType> 488ALWAYS_INLINE void pack(const SourceType*, DstType*, unsigned) 489{ 490 ASSERT_NOT_REACHED(); 491} 492 493template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 494{ 495 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 496 destination[0] = source[3]; 497 source += 4; 498 destination += 1; 499 } 500} 501 502template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 503{ 504 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 505 destination[0] = source[0]; 506 source += 4; 507 destination += 1; 508 } 509} 510 511template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 512{ 513 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 514 float scaleFactor = source[3] / 255.0f; 515 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 516 destination[0] = sourceR; 517 source += 4; 518 destination += 1; 519 } 520} 521 522// FIXME: this routine is lossy and must be removed. 523template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 524{ 525 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 526 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 527 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 528 destination[0] = sourceR; 529 source += 4; 530 destination += 1; 531 } 532} 533 534template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 535{ 536 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 537 destination[0] = source[0]; 538 destination[1] = source[3]; 539 source += 4; 540 destination += 2; 541 } 542} 543 544template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 545{ 546 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 547 float scaleFactor = source[3] / 255.0f; 548 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 549 destination[0] = sourceR; 550 destination[1] = source[3]; 551 source += 4; 552 destination += 2; 553 } 554} 555 556// FIXME: this routine is lossy and must be removed. 557template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 558{ 559 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 560 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 561 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 562 destination[0] = sourceR; 563 destination[1] = source[3]; 564 source += 4; 565 destination += 2; 566 } 567} 568 569template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 570{ 571 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 572 destination[0] = source[0]; 573 destination[1] = source[1]; 574 destination[2] = source[2]; 575 source += 4; 576 destination += 3; 577 } 578} 579 580template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 581{ 582 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 583 float scaleFactor = source[3] / 255.0f; 584 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 585 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 586 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 587 destination[0] = sourceR; 588 destination[1] = sourceG; 589 destination[2] = sourceB; 590 source += 4; 591 destination += 3; 592 } 593} 594 595// FIXME: this routine is lossy and must be removed. 596template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 597{ 598 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 599 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 600 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 601 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 602 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 603 destination[0] = sourceR; 604 destination[1] = sourceG; 605 destination[2] = sourceB; 606 source += 4; 607 destination += 3; 608 } 609} 610 611 612template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 613{ 614 memcpy(destination, source, pixelsPerRow * 4); 615} 616 617template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 618{ 619 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 620 float scaleFactor = source[3] / 255.0f; 621 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 622 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 623 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 624 destination[0] = sourceR; 625 destination[1] = sourceG; 626 destination[2] = sourceB; 627 destination[3] = source[3]; 628 source += 4; 629 destination += 4; 630 } 631} 632 633// FIXME: this routine is lossy and must be removed. 634template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) 635{ 636 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 637 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 638 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 639 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 640 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 641 destination[0] = sourceR; 642 destination[1] = sourceG; 643 destination[2] = sourceB; 644 destination[3] = source[3]; 645 source += 4; 646 destination += 4; 647 } 648} 649 650template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 651{ 652#if HAVE(ARM_NEON_INTRINSICS) 653 SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow); 654#endif 655 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 656 *destination = (((source[0] & 0xF0) << 8) 657 | ((source[1] & 0xF0) << 4) 658 | (source[2] & 0xF0) 659 | (source[3] >> 4)); 660 source += 4; 661 destination += 1; 662 } 663} 664 665template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 666{ 667 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 668 float scaleFactor = source[3] / 255.0f; 669 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 670 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 671 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 672 *destination = (((sourceR & 0xF0) << 8) 673 | ((sourceG & 0xF0) << 4) 674 | (sourceB & 0xF0) 675 | (source[3] >> 4)); 676 source += 4; 677 destination += 1; 678 } 679} 680 681// FIXME: this routine is lossy and must be removed. 682template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 683{ 684 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 685 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 686 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 687 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 688 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 689 *destination = (((sourceR & 0xF0) << 8) 690 | ((sourceG & 0xF0) << 4) 691 | (sourceB & 0xF0) 692 | (source[3] >> 4)); 693 source += 4; 694 destination += 1; 695 } 696} 697 698template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 699{ 700#if HAVE(ARM_NEON_INTRINSICS) 701 SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow); 702#endif 703 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 704 *destination = (((source[0] & 0xF8) << 8) 705 | ((source[1] & 0xF8) << 3) 706 | ((source[2] & 0xF8) >> 2) 707 | (source[3] >> 7)); 708 source += 4; 709 destination += 1; 710 } 711} 712 713template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 714{ 715 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 716 float scaleFactor = source[3] / 255.0f; 717 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 718 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 719 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 720 *destination = (((sourceR & 0xF8) << 8) 721 | ((sourceG & 0xF8) << 3) 722 | ((sourceB & 0xF8) >> 2) 723 | (source[3] >> 7)); 724 source += 4; 725 destination += 1; 726 } 727} 728 729// FIXME: this routine is lossy and must be removed. 730template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 731{ 732 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 733 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 734 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 735 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 736 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 737 *destination = (((sourceR & 0xF8) << 8) 738 | ((sourceG & 0xF8) << 3) 739 | ((sourceB & 0xF8) >> 2) 740 | (source[3] >> 7)); 741 source += 4; 742 destination += 1; 743 } 744} 745 746template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 747{ 748#if HAVE(ARM_NEON_INTRINSICS) 749 SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow); 750#endif 751 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 752 *destination = (((source[0] & 0xF8) << 8) 753 | ((source[1] & 0xFC) << 3) 754 | ((source[2] & 0xF8) >> 3)); 755 source += 4; 756 destination += 1; 757 } 758} 759 760template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 761{ 762 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 763 float scaleFactor = source[3] / 255.0f; 764 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 765 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 766 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 767 *destination = (((sourceR & 0xF8) << 8) 768 | ((sourceG & 0xFC) << 3) 769 | ((sourceB & 0xF8) >> 3)); 770 source += 4; 771 destination += 1; 772 } 773} 774 775// FIXME: this routine is lossy and must be removed. 776template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) 777{ 778 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 779 float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; 780 uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); 781 uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); 782 uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); 783 *destination = (((sourceR & 0xF8) << 8) 784 | ((sourceG & 0xFC) << 3) 785 | ((sourceB & 0xF8) >> 3)); 786 source += 4; 787 destination += 1; 788 } 789} 790 791template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 792{ 793 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 794 destination[0] = source[0]; 795 destination[1] = source[1]; 796 destination[2] = source[2]; 797 source += 4; 798 destination += 3; 799 } 800} 801 802template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 803{ 804 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 805 float scaleFactor = source[3]; 806 destination[0] = source[0] * scaleFactor; 807 destination[1] = source[1] * scaleFactor; 808 destination[2] = source[2] * scaleFactor; 809 source += 4; 810 destination += 3; 811 } 812} 813 814template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 815{ 816 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 817 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 818 destination[0] = source[0] * scaleFactor; 819 destination[1] = source[1] * scaleFactor; 820 destination[2] = source[2] * scaleFactor; 821 source += 4; 822 destination += 3; 823 } 824} 825 826// Used only during RGBA8 or BGRA8 -> floating-point uploads. 827template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 828{ 829 memcpy(destination, source, pixelsPerRow * 4 * sizeof(float)); 830} 831 832template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 833{ 834 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 835 float scaleFactor = source[3]; 836 destination[0] = source[0] * scaleFactor; 837 destination[1] = source[1] * scaleFactor; 838 destination[2] = source[2] * scaleFactor; 839 destination[3] = source[3]; 840 source += 4; 841 destination += 4; 842 } 843} 844 845template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 846{ 847 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 848 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 849 destination[0] = source[0] * scaleFactor; 850 destination[1] = source[1] * scaleFactor; 851 destination[2] = source[2] * scaleFactor; 852 destination[3] = source[3]; 853 source += 4; 854 destination += 4; 855 } 856} 857 858template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 859{ 860 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 861 destination[0] = source[3]; 862 source += 4; 863 destination += 1; 864 } 865} 866 867template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 868{ 869 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 870 destination[0] = source[0]; 871 source += 4; 872 destination += 1; 873 } 874} 875 876template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR32F, 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 source += 4; 882 destination += 1; 883 } 884} 885 886template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 887{ 888 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 889 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 890 destination[0] = source[0] * scaleFactor; 891 source += 4; 892 destination += 1; 893 } 894} 895 896template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 897{ 898 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 899 destination[0] = source[0]; 900 destination[1] = source[3]; 901 source += 4; 902 destination += 2; 903 } 904} 905 906template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA32F, 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[3]; 912 source += 4; 913 destination += 2; 914 } 915} 916 917template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow) 918{ 919 for (unsigned int i = 0; i < pixelsPerRow; ++i) { 920 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 921 destination[0] = source[0] * scaleFactor; 922 destination[1] = source[3]; 923 source += 4; 924 destination += 2; 925 } 926} 927 928template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 929{ 930 for (unsigned i = 0; i < pixelsPerRow; ++i) { 931 destination[0] = convertFloatToHalfFloat(source[0]); 932 destination[1] = convertFloatToHalfFloat(source[1]); 933 destination[2] = convertFloatToHalfFloat(source[2]); 934 destination[3] = convertFloatToHalfFloat(source[3]); 935 source += 4; 936 destination += 4; 937 } 938} 939 940template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 941{ 942 for (unsigned i = 0; i < pixelsPerRow; ++i) { 943 float scaleFactor = source[3]; 944 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 945 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 946 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 947 destination[3] = convertFloatToHalfFloat(source[3]); 948 source += 4; 949 destination += 4; 950 } 951} 952 953template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 954{ 955 for (unsigned i = 0; i < pixelsPerRow; ++i) { 956 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 957 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 958 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 959 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 960 destination[3] = convertFloatToHalfFloat(source[3]); 961 source += 4; 962 destination += 4; 963 } 964} 965 966template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 967{ 968 for (unsigned i = 0; i < pixelsPerRow; ++i) { 969 destination[0] = convertFloatToHalfFloat(source[0]); 970 destination[1] = convertFloatToHalfFloat(source[1]); 971 destination[2] = convertFloatToHalfFloat(source[2]); 972 source += 4; 973 destination += 3; 974 } 975} 976 977template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 978{ 979 for (unsigned i = 0; i < pixelsPerRow; ++i) { 980 float scaleFactor = source[3]; 981 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 982 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 983 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 984 source += 4; 985 destination += 3; 986 } 987} 988 989template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 990{ 991 for (unsigned i = 0; i < pixelsPerRow; ++i) { 992 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 993 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 994 destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); 995 destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); 996 source += 4; 997 destination += 3; 998 } 999} 1000 1001template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1002{ 1003 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1004 destination[0] = convertFloatToHalfFloat(source[0]); 1005 destination[1] = convertFloatToHalfFloat(source[3]); 1006 source += 4; 1007 destination += 2; 1008 } 1009} 1010 1011template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1012{ 1013 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1014 float scaleFactor = source[3]; 1015 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1016 destination[1] = convertFloatToHalfFloat(source[3]); 1017 source += 4; 1018 destination += 2; 1019 } 1020} 1021 1022template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1023{ 1024 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1025 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1026 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1027 destination[1] = convertFloatToHalfFloat(source[3]); 1028 source += 4; 1029 destination += 2; 1030 } 1031} 1032 1033template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1034{ 1035 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1036 destination[0] = convertFloatToHalfFloat(source[0]); 1037 source += 4; 1038 destination += 1; 1039 } 1040} 1041 1042template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoPremultiply, 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]; 1046 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1047 source += 4; 1048 destination += 1; 1049 } 1050} 1051 1052template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1053{ 1054 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1055 float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; 1056 destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); 1057 source += 4; 1058 destination += 1; 1059 } 1060} 1061 1062template<> ALWAYS_INLINE void pack<GraphicsContext3D::DataFormatA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow) 1063{ 1064 for (unsigned i = 0; i < pixelsPerRow; ++i) { 1065 destination[0] = convertFloatToHalfFloat(source[3]); 1066 source += 4; 1067 destination += 1; 1068 } 1069} 1070 1071template<int Format> 1072struct IsFloatFormat { 1073 static const bool Value = 1074 Format == GraphicsContext3D::DataFormatRGBA32F 1075 || Format == GraphicsContext3D::DataFormatRGB32F 1076 || Format == GraphicsContext3D::DataFormatRA32F 1077 || Format == GraphicsContext3D::DataFormatR32F 1078 || Format == GraphicsContext3D::DataFormatA32F; 1079}; 1080 1081template<int Format> 1082struct IsHalfFloatFormat { 1083 static const bool Value = 1084 Format == GraphicsContext3D::DataFormatRGBA16F 1085 || Format == GraphicsContext3D::DataFormatRGB16F 1086 || Format == GraphicsContext3D::DataFormatRA16F 1087 || Format == GraphicsContext3D::DataFormatR16F 1088 || Format == GraphicsContext3D::DataFormatA16F; 1089}; 1090 1091template<int Format> 1092struct Is16bppFormat { 1093 static const bool Value = 1094 Format == GraphicsContext3D::DataFormatRGBA5551 1095 || Format == GraphicsContext3D::DataFormatRGBA4444 1096 || Format == GraphicsContext3D::DataFormatRGB565; 1097}; 1098 1099template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value> 1100struct DataTypeForFormat { 1101 typedef uint8_t Type; 1102}; 1103 1104template<int Format> 1105struct DataTypeForFormat<Format, true, false, false> { 1106 typedef float Type; 1107}; 1108 1109template<int Format> 1110struct DataTypeForFormat<Format, false, true, false> { 1111 typedef uint16_t Type; 1112}; 1113 1114template<int Format> 1115struct DataTypeForFormat<Format, false, false, true> { 1116 typedef uint16_t Type; 1117}; 1118 1119template<int Format> 1120struct IntermediateFormat { 1121 static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? GraphicsContext3D::DataFormatRGBA32F : GraphicsContext3D::DataFormatRGBA8; 1122}; 1123 1124 1125/* END CODE SHARED WITH MOZILLA FIREFOX */ 1126 1127void FormatConverter::convert(GraphicsContext3D::DataFormat srcFormat, GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp) 1128{ 1129#define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \ 1130 case SrcFormat: \ 1131 return convert<SrcFormat>(dstFormat, alphaOp); 1132 1133 switch (srcFormat) { 1134 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR8) 1135 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA8) 1136 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR32F) 1137 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA32F) 1138 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA8) 1139 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA32F) 1140 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB8) 1141 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGR8) 1142 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB565) 1143 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB32F) 1144 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA8) 1145 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatARGB8) 1146 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatABGR8) 1147 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatAR8) 1148 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGRA8) 1149 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA5551) 1150 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA4444) 1151 FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA32F) 1152 default: 1153 ASSERT_NOT_REACHED(); 1154 } 1155#undef FORMATCONVERTER_CASE_SRCFORMAT 1156} 1157 1158template<GraphicsContext3D::DataFormat SrcFormat> 1159ALWAYS_INLINE void FormatConverter::convert(GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp) 1160{ 1161#define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \ 1162 case DstFormat: \ 1163 return convert<SrcFormat, DstFormat>(alphaOp); 1164 1165 switch (dstFormat) { 1166 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR8) 1167 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR16F) 1168 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR32F) 1169 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA8) 1170 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA16F) 1171 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA32F) 1172 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA8) 1173 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA16F) 1174 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA32F) 1175 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB8) 1176 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB565) 1177 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB16F) 1178 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB32F) 1179 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA8) 1180 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA5551) 1181 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA4444) 1182 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA16F) 1183 FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA32F) 1184 default: 1185 ASSERT_NOT_REACHED(); 1186 } 1187 1188#undef FORMATCONVERTER_CASE_DSTFORMAT 1189} 1190 1191template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat> 1192ALWAYS_INLINE void FormatConverter::convert(GraphicsContext3D::AlphaOp alphaOp) 1193{ 1194#define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \ 1195 case alphaOp: \ 1196 return convert<SrcFormat, DstFormat, alphaOp>(); 1197 1198 switch (alphaOp) { 1199 FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoNothing) 1200 FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoPremultiply) 1201 FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoUnmultiply) 1202 default: 1203 ASSERT_NOT_REACHED(); 1204 } 1205#undef FORMATCONVERTER_CASE_ALPHAOP 1206} 1207 1208template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat, GraphicsContext3D::AlphaOp alphaOp> 1209ALWAYS_INLINE_EXCEPT_MSVC void FormatConverter::convert() 1210{ 1211 // Many instantiations of this template function will never be entered, so we try 1212 // to return immediately in these cases to avoid the compiler to generate useless code. 1213 if (SrcFormat == DstFormat && alphaOp == GraphicsContext3D::AlphaDoNothing) { 1214 ASSERT_NOT_REACHED(); 1215 return; 1216 } 1217 if (!IsFloatFormat<DstFormat>::Value && IsFloatFormat<SrcFormat>::Value) { 1218 ASSERT_NOT_REACHED(); 1219 return; 1220 } 1221 1222 // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat. 1223 const bool srcFormatComesFromDOMElementOrImageData = GraphicsContext3D::srcFormatComesFromDOMElementOrImageData(SrcFormat); 1224 if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) { 1225 ASSERT_NOT_REACHED(); 1226 return; 1227 } 1228 // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied. 1229 if (!srcFormatComesFromDOMElementOrImageData && alphaOp == GraphicsContext3D::AlphaDoUnmultiply) { 1230 ASSERT_NOT_REACHED(); 1231 return; 1232 } 1233 if ((!GraphicsContext3D::hasAlpha(SrcFormat) || !GraphicsContext3D::hasColor(SrcFormat) || !GraphicsContext3D::hasColor(DstFormat)) && alphaOp != GraphicsContext3D::AlphaDoNothing) { 1234 ASSERT_NOT_REACHED(); 1235 return; 1236 } 1237 1238 typedef typename DataTypeForFormat<SrcFormat>::Type SrcType; 1239 typedef typename DataTypeForFormat<DstFormat>::Type DstType; 1240 const int IntermediateSrcFormat = IntermediateFormat<DstFormat>::Value; 1241 typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType; 1242 const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType); 1243 const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType); 1244 const bool trivialUnpack = (SrcFormat == GraphicsContext3D::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == GraphicsContext3D::DataFormatRGBA32F; 1245 const bool trivialPack = (DstFormat == GraphicsContext3D::DataFormatRGBA8 || DstFormat == GraphicsContext3D::DataFormatRGBA32F) && alphaOp == GraphicsContext3D::AlphaDoNothing && m_dstStride > 0; 1246 ASSERT(!trivialUnpack || !trivialPack); 1247 1248 const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart); 1249 DstType* dstRowStart = static_cast<DstType*>(m_dstStart); 1250 if (!trivialUnpack && trivialPack) { 1251 for (size_t i = 0; i < m_height; ++i) { 1252 unpack<SrcFormat>(srcRowStart, dstRowStart, m_width); 1253 srcRowStart += srcStrideInElements; 1254 dstRowStart += dstStrideInElements; 1255 } 1256 } else if (!trivialUnpack && !trivialPack) { 1257 for (size_t i = 0; i < m_height; ++i) { 1258 unpack<SrcFormat>(srcRowStart, reinterpret_cast_ptr<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), m_width); 1259 pack<DstFormat, alphaOp>(reinterpret_cast_ptr<IntermediateSrcType*>(m_unpackedIntermediateSrcData.get()), dstRowStart, m_width); 1260 srcRowStart += srcStrideInElements; 1261 dstRowStart += dstStrideInElements; 1262 } 1263 } else { 1264 for (size_t i = 0; i < m_height; ++i) { 1265 pack<DstFormat, alphaOp>(srcRowStart, dstRowStart, m_width); 1266 srcRowStart += srcStrideInElements; 1267 dstRowStart += dstStrideInElements; 1268 } 1269 } 1270 m_success = true; 1271 return; 1272} 1273 1274} // namespace WebCore 1275 1276#endif // USE(3D_GRAPHICS) 1277