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