Home | History | Annotate | Download | only in graphics
      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