tagging audio streams and changing audio sink to pulseaudio
[profile/ivi/webkit-efl.git] / Source / WebCore / platform / graphics / GraphicsContext3D.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Google Inc. 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
29 #if ENABLE(WEBGL) || ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
30
31 #include "GraphicsContext3D.h"
32
33 #include "CheckedInt.h"
34 #include "DrawingBuffer.h"
35 #include "Extensions3D.h"
36 #include "Image.h"
37 #include "ImageData.h"
38 #include "ImageObserver.h"
39
40 #include <wtf/ArrayBufferView.h>
41 #include <wtf/OwnArrayPtr.h>
42 #include <wtf/PassOwnArrayPtr.h>
43
44 namespace WebCore {
45
46 namespace {
47
48 uint8_t convertColor16LittleTo8(uint16_t value)
49 {
50     return value >> 8;
51 }
52
53 uint8_t convertColor16BigTo8(uint16_t value)
54 {
55     return static_cast<uint8_t>(value & 0x00FF);
56 }
57
58 } // anonymous namespace
59
60 bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
61 {
62     ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
63     OwnArrayPtr<unsigned char> zero;
64     if (!isResourceSafe() && width > 0 && height > 0) {
65         unsigned int size;
66         GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, 0);
67         if (error != GraphicsContext3D::NO_ERROR) {
68             synthesizeGLError(error);
69             return false;
70         }
71         zero = adoptArrayPtr(new unsigned char[size]);
72         if (!zero) {
73             synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
74             return false;
75         }
76         memset(zero.get(), 0, size);
77     }
78     return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get());
79 }
80
81 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format,
82                                                        GC3Denum type,
83                                                        unsigned int* componentsPerPixel,
84                                                        unsigned int* bytesPerComponent)
85 {
86     switch (format) {
87     case GraphicsContext3D::ALPHA:
88     case GraphicsContext3D::LUMINANCE:
89     case GraphicsContext3D::DEPTH_COMPONENT:
90     case GraphicsContext3D::DEPTH_STENCIL:
91         *componentsPerPixel = 1;
92         break;
93     case GraphicsContext3D::LUMINANCE_ALPHA:
94         *componentsPerPixel = 2;
95         break;
96     case GraphicsContext3D::RGB:
97         *componentsPerPixel = 3;
98         break;
99     case GraphicsContext3D::RGBA:
100     case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
101         *componentsPerPixel = 4;
102         break;
103     default:
104         return false;
105     }
106     switch (type) {
107     case GraphicsContext3D::UNSIGNED_BYTE:
108         *bytesPerComponent = sizeof(GC3Dubyte);
109         break;
110     case GraphicsContext3D::UNSIGNED_SHORT:
111         *bytesPerComponent = sizeof(GC3Dushort);
112         break;
113     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
114     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
115     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
116         *componentsPerPixel = 1;
117         *bytesPerComponent = sizeof(GC3Dushort);
118         break;
119     case GraphicsContext3D::UNSIGNED_INT_24_8:
120     case GraphicsContext3D::UNSIGNED_INT:
121         *bytesPerComponent = sizeof(GC3Duint);
122         break;
123     case GraphicsContext3D::FLOAT: // OES_texture_float
124         *bytesPerComponent = sizeof(GC3Dfloat);
125         break;
126     default:
127         return false;
128     }
129     return true;
130 }
131
132 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment,
133                                                     unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
134 {
135     ASSERT(imageSizeInBytes);
136     ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
137     if (width < 0 || height < 0)
138         return GraphicsContext3D::INVALID_VALUE;
139     unsigned int bytesPerComponent, componentsPerPixel;
140     if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
141         return GraphicsContext3D::INVALID_ENUM;
142     if (!width || !height) {
143         *imageSizeInBytes = 0;
144         if (paddingInBytes)
145             *paddingInBytes = 0;
146         return GraphicsContext3D::NO_ERROR;
147     }
148     CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
149     checkedValue *=  width;
150     if (!checkedValue.valid())
151         return GraphicsContext3D::INVALID_VALUE;
152     unsigned int validRowSize = checkedValue.value();
153     unsigned int padding = 0;
154     unsigned int residual = validRowSize % alignment;
155     if (residual) {
156         padding = alignment - residual;
157         checkedValue += padding;
158     }
159     // Last row needs no padding.
160     checkedValue *= (height - 1);
161     checkedValue += validRowSize;
162     if (!checkedValue.valid())
163         return GraphicsContext3D::INVALID_VALUE;
164     *imageSizeInBytes = checkedValue.value();
165     if (paddingInBytes)
166         *paddingInBytes = padding;
167     return GraphicsContext3D::NO_ERROR;
168 }
169
170 bool GraphicsContext3D::extractImageData(Image* image,
171                                          GC3Denum format,
172                                          GC3Denum type,
173                                          bool flipY,
174                                          bool premultiplyAlpha,
175                                          bool ignoreGammaAndColorProfile,
176                                          Vector<uint8_t>& data)
177 {
178     if (!image)
179         return false;
180     if (!getImageData(image, format, type, premultiplyAlpha, ignoreGammaAndColorProfile, data))
181         return false;
182     if (flipY) {
183         unsigned int componentsPerPixel, bytesPerComponent;
184         if (!computeFormatAndTypeParameters(format, type,
185                                             &componentsPerPixel,
186                                             &bytesPerComponent))
187             return false;
188         // The image data is tightly packed, and we upload it as such.
189         unsigned int unpackAlignment = 1;
190 #if ENABLE(TIZEN_JPEG_IMAGE_SCALE_DECODING)
191         int dataSize = data.size() / (componentsPerPixel * bytesPerComponent);
192         int imageSize = image->width() * image->height();
193         if (dataSize != imageSize) {
194             double scale = sqrt(static_cast<double> (dataSize) / imageSize);
195             flipVertically(data.data(), image->width()*scale, image->height()*scale,
196                            componentsPerPixel * bytesPerComponent,
197                            unpackAlignment);
198         } else
199 #endif
200         flipVertically(data.data(), image->width(), image->height(),
201                        componentsPerPixel * bytesPerComponent,
202                        unpackAlignment);
203     }
204     if (ImageObserver *observer = image->imageObserver())
205         observer->didDraw(image);
206     return true;
207 }
208
209 bool GraphicsContext3D::extractImageData(ImageData* imageData,
210                                          GC3Denum format,
211                                          GC3Denum type,
212                                          bool flipY,
213                                          bool premultiplyAlpha,
214                                          Vector<uint8_t>& data)
215 {
216     if (!imageData)
217         return false;
218     int width = imageData->width();
219     int height = imageData->height();
220
221     unsigned int packedSize;
222     // Output data is tightly packed (alignment == 1).
223     if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
224         return false;
225     data.resize(packedSize);
226
227     if (!packPixels(imageData->data()->data(),
228                     SourceFormatRGBA8,
229                     width,
230                     height,
231                     0,
232                     format,
233                     type,
234                     premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing,
235                     data.data()))
236         return false;
237     if (flipY) {
238         unsigned int componentsPerPixel, bytesPerComponent;
239         if (!computeFormatAndTypeParameters(format, type,
240                                             &componentsPerPixel,
241                                             &bytesPerComponent))
242             return false;
243         // The image data is tightly packed, and we upload it as such.
244         unsigned int unpackAlignment = 1;
245         flipVertically(data.data(), width, height,
246                        componentsPerPixel * bytesPerComponent,
247                        unpackAlignment);
248     }
249     return true;
250 }
251
252 bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int height,
253                                            GC3Denum format, GC3Denum type,
254                                            unsigned int unpackAlignment,
255                                            bool flipY, bool premultiplyAlpha,
256                                            const void* pixels,
257                                            Vector<uint8_t>& data)
258 {
259     // Assumes format, type, etc. have already been validated.
260     SourceDataFormat sourceDataFormat = SourceFormatRGBA8;
261     switch (type) {
262     case UNSIGNED_BYTE:
263         switch (format) {
264         case RGBA:
265             sourceDataFormat = SourceFormatRGBA8;
266             break;
267         case RGB:
268             sourceDataFormat = SourceFormatRGB8;
269             break;
270         case ALPHA:
271             sourceDataFormat = SourceFormatA8;
272             break;
273         case LUMINANCE:
274             sourceDataFormat = SourceFormatR8;
275             break;
276         case LUMINANCE_ALPHA:
277             sourceDataFormat = SourceFormatRA8;
278             break;
279         default:
280             ASSERT_NOT_REACHED();
281         }
282         break;
283     case FLOAT: // OES_texture_float
284         switch (format) {
285         case RGBA:
286             sourceDataFormat = SourceFormatRGBA32F;
287             break;
288         case RGB:
289             sourceDataFormat = SourceFormatRGB32F;
290             break;
291         case ALPHA:
292             sourceDataFormat = SourceFormatA32F;
293             break;
294         case LUMINANCE:
295             sourceDataFormat = SourceFormatR32F;
296             break;
297         case LUMINANCE_ALPHA:
298             sourceDataFormat = SourceFormatRA32F;
299             break;
300         default:
301             ASSERT_NOT_REACHED();
302         }
303         break;
304     case UNSIGNED_SHORT_5_5_5_1:
305         sourceDataFormat = SourceFormatRGBA5551;
306         break;
307     case UNSIGNED_SHORT_4_4_4_4:
308         sourceDataFormat = SourceFormatRGBA4444;
309         break;
310     case UNSIGNED_SHORT_5_6_5:
311         sourceDataFormat = SourceFormatRGB565;
312         break;
313     default:
314         ASSERT_NOT_REACHED();
315     }
316
317     // Resize the output buffer.
318     unsigned int componentsPerPixel, bytesPerComponent;
319     if (!computeFormatAndTypeParameters(format, type,
320                                         &componentsPerPixel,
321                                         &bytesPerComponent))
322         return false;
323     unsigned int bytesPerPixel = componentsPerPixel * bytesPerComponent;
324     data.resize(width * height * bytesPerPixel);
325
326     if (!packPixels(static_cast<const uint8_t*>(pixels),
327                     sourceDataFormat,
328                     width, height, unpackAlignment,
329                     format, type,
330                     (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing),
331                     data.data()))
332         return false;
333     // The pixel data is now tightly packed.
334     if (flipY)
335         flipVertically(data.data(), width, height, bytesPerPixel, 1);
336     return true;
337 }
338
339 void GraphicsContext3D::flipVertically(void* imageData,
340                                        unsigned int width,
341                                        unsigned int height,
342                                        unsigned int bytesPerPixel,
343                                        unsigned int unpackAlignment)
344 {
345     if (!width || !height)
346         return;
347     unsigned int validRowBytes = width * bytesPerPixel;
348     unsigned int totalRowBytes = validRowBytes;
349     unsigned int remainder = validRowBytes % unpackAlignment;
350     if (remainder)
351         totalRowBytes += (unpackAlignment - remainder);
352     uint8_t* tempRow = new uint8_t[validRowBytes];
353     uint8_t* data = static_cast<uint8_t*>(imageData);
354     for (unsigned i = 0; i < height / 2; i++) {
355         uint8_t* lowRow = data + (totalRowBytes * i);
356         uint8_t* highRow = data + (totalRowBytes * (height - i - 1));
357         memcpy(tempRow, lowRow, validRowBytes);
358         memcpy(lowRow, highRow, validRowBytes);
359         memcpy(highRow, tempRow, validRowBytes);
360     }
361     delete[] tempRow;
362 }
363
364 // The following packing and unpacking routines are expressed in terms
365 // of line-by-line operations, and passed by function pointer rather
366 // than template parameter, to achieve the majority of the speedups of
367 // having them inlined while reducing code size.
368
369 namespace {
370
371 //----------------------------------------------------------------------
372 // Pixel unpacking routines.
373
374 void unpackOneRowOfRGBA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
375 {
376     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
377         destination[0] = convertColor16LittleTo8(source[0]);
378         destination[1] = convertColor16LittleTo8(source[1]);
379         destination[2] = convertColor16LittleTo8(source[2]);
380         destination[3] = convertColor16LittleTo8(source[3]);
381         source += 4;
382         destination += 4;
383     }
384 }
385
386 void unpackOneRowOfRGBA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
387 {
388     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
389         destination[0] = convertColor16BigTo8(source[0]);
390         destination[1] = convertColor16BigTo8(source[1]);
391         destination[2] = convertColor16BigTo8(source[2]);
392         destination[3] = convertColor16BigTo8(source[3]);
393         source += 4;
394         destination += 4;
395     }
396 }
397
398 void unpackOneRowOfRGB8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
399 {
400     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
401         destination[0] = source[0];
402         destination[1] = source[1];
403         destination[2] = source[2];
404         destination[3] = 0xFF;
405         source += 3;
406         destination += 4;
407     }
408 }
409
410 void unpackOneRowOfRGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
411 {
412     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
413         destination[0] = convertColor16LittleTo8(source[0]);
414         destination[1] = convertColor16LittleTo8(source[1]);
415         destination[2] = convertColor16LittleTo8(source[2]);
416         destination[3] = 0xFF;
417         source += 3;
418         destination += 4;
419     }
420 }
421
422 void unpackOneRowOfRGB16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
423 {
424     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
425         destination[0] = convertColor16BigTo8(source[0]);
426         destination[1] = convertColor16BigTo8(source[1]);
427         destination[2] = convertColor16BigTo8(source[2]);
428         destination[3] = 0xFF;
429         source += 3;
430         destination += 4;
431     }
432 }
433
434 void unpackOneRowOfBGR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
435 {
436     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
437         destination[0] = source[2];
438         destination[1] = source[1];
439         destination[2] = source[0];
440         destination[3] = 0xFF;
441         source += 3;
442         destination += 4;
443     }
444 }
445
446 void unpackOneRowOfARGB8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
447 {
448     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
449         destination[0] = source[1];
450         destination[1] = source[2];
451         destination[2] = source[3];
452         destination[3] = source[0];
453         source += 4;
454         destination += 4;
455     }
456 }
457
458 void unpackOneRowOfARGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
459 {
460     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
461         destination[0] = convertColor16LittleTo8(source[1]);
462         destination[1] = convertColor16LittleTo8(source[2]);
463         destination[2] = convertColor16LittleTo8(source[3]);
464         destination[3] = convertColor16LittleTo8(source[0]);
465         source += 4;
466         destination += 4;
467     }
468 }
469
470 void unpackOneRowOfARGB16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
471 {
472     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
473         destination[0] = convertColor16BigTo8(source[1]);
474         destination[1] = convertColor16BigTo8(source[2]);
475         destination[2] = convertColor16BigTo8(source[3]);
476         destination[3] = convertColor16BigTo8(source[0]);
477         source += 4;
478         destination += 4;
479     }
480 }
481
482 void unpackOneRowOfABGR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
483 {
484     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
485         destination[0] = source[3];
486         destination[1] = source[2];
487         destination[2] = source[1];
488         destination[3] = source[0];
489         source += 4;
490         destination += 4;
491     }
492 }
493
494 void unpackOneRowOfBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
495 {
496     const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
497     uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
498     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
499         uint32_t bgra = source32[i];
500 #if CPU(BIG_ENDIAN)
501         uint32_t brMask = 0xff00ff00;
502         uint32_t gaMask = 0x00ff00ff;
503 #else
504         uint32_t brMask = 0x00ff00ff;
505         uint32_t gaMask = 0xff00ff00;
506 #endif
507         uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask);
508         destination32[i] = rgba;
509     }
510 }
511
512 void unpackOneRowOfBGRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
513 {
514     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
515         destination[0] = convertColor16LittleTo8(source[2]);
516         destination[1] = convertColor16LittleTo8(source[1]);
517         destination[2] = convertColor16LittleTo8(source[0]);
518         destination[3] = convertColor16LittleTo8(source[3]);
519         source += 4;
520         destination += 4;
521     }
522 }
523
524 void unpackOneRowOfBGRA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
525 {
526     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
527         destination[0] = convertColor16BigTo8(source[2]);
528         destination[1] = convertColor16BigTo8(source[1]);
529         destination[2] = convertColor16BigTo8(source[0]);
530         destination[3] = convertColor16BigTo8(source[3]);
531         source += 4;
532         destination += 4;
533     }
534 }
535
536 void unpackOneRowOfRGBA5551ToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
537 {
538     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
539         uint16_t packedValue = source[0];
540         uint8_t r = packedValue >> 11;
541         uint8_t g = (packedValue >> 6) & 0x1F;
542         uint8_t b = (packedValue >> 1) & 0x1F;
543         destination[0] = (r << 3) | (r & 0x7);
544         destination[1] = (g << 3) | (g & 0x7);
545         destination[2] = (b << 3) | (b & 0x7);
546         destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
547         source += 1;
548         destination += 4;
549     }
550 }
551
552 void unpackOneRowOfRGBA4444ToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
553 {
554     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
555         uint16_t packedValue = source[0];
556         uint8_t r = packedValue >> 12;
557         uint8_t g = (packedValue >> 8) & 0x0F;
558         uint8_t b = (packedValue >> 4) & 0x0F;
559         uint8_t a = packedValue & 0x0F;
560         destination[0] = r << 4 | r;
561         destination[1] = g << 4 | g;
562         destination[2] = b << 4 | b;
563         destination[3] = a << 4 | a;
564         source += 1;
565         destination += 4;
566     }
567 }
568
569 void unpackOneRowOfRGB565ToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
570 {
571     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
572         uint16_t packedValue = source[0];
573         uint8_t r = packedValue >> 11;
574         uint8_t g = (packedValue >> 5) & 0x3F;
575         uint8_t b = packedValue & 0x1F;
576         destination[0] = (r << 3) | (r & 0x7);
577         destination[1] = (g << 2) | (g & 0x3);
578         destination[2] = (b << 3) | (b & 0x7);
579         destination[3] = 0xFF;
580         source += 1;
581         destination += 4;
582     }
583 }
584
585 void unpackOneRowOfR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
586 {
587     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
588         destination[0] = source[0];
589         destination[1] = source[0];
590         destination[2] = source[0];
591         destination[3] = 0xFF;
592         source += 1;
593         destination += 4;
594     }
595 }
596
597 void unpackOneRowOfR16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
598 {
599     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
600         destination[0] = convertColor16LittleTo8(source[0]);
601         destination[1] = convertColor16LittleTo8(source[0]);
602         destination[2] = convertColor16LittleTo8(source[0]);
603         destination[3] = 0xFF;
604         source += 1;
605         destination += 4;
606     }
607 }
608
609 void unpackOneRowOfR16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
610 {
611     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
612         destination[0] = convertColor16BigTo8(source[0]);
613         destination[1] = convertColor16BigTo8(source[0]);
614         destination[2] = convertColor16BigTo8(source[0]);
615         destination[3] = 0xFF;
616         source += 1;
617         destination += 4;
618     }
619 }
620
621 void unpackOneRowOfRA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
622 {
623     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
624         destination[0] = source[0];
625         destination[1] = source[0];
626         destination[2] = source[0];
627         destination[3] = source[1];
628         source += 2;
629         destination += 4;
630     }
631 }
632
633 void unpackOneRowOfRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
634 {
635     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
636         destination[0] = convertColor16LittleTo8(source[0]);
637         destination[1] = convertColor16LittleTo8(source[0]);
638         destination[2] = convertColor16LittleTo8(source[0]);
639         destination[3] = convertColor16LittleTo8(source[1]);
640         source += 2;
641         destination += 4;
642     }
643 }
644
645 void unpackOneRowOfRA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
646 {
647     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
648         destination[0] = convertColor16BigTo8(source[0]);
649         destination[1] = convertColor16BigTo8(source[0]);
650         destination[2] = convertColor16BigTo8(source[0]);
651         destination[3] = convertColor16BigTo8(source[1]);
652         source += 2;
653         destination += 4;
654     }
655 }
656
657 void unpackOneRowOfAR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
658 {
659     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
660         destination[0] = source[1];
661         destination[1] = source[1];
662         destination[2] = source[1];
663         destination[3] = source[0];
664         source += 2;
665         destination += 4;
666     }
667 }
668
669 void unpackOneRowOfAR16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
670 {
671     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
672         destination[0] = convertColor16LittleTo8(source[1]);
673         destination[1] = convertColor16LittleTo8(source[1]);
674         destination[2] = convertColor16LittleTo8(source[1]);
675         destination[3] = convertColor16LittleTo8(source[0]);
676         source += 2;
677         destination += 4;
678     }
679 }
680
681 void unpackOneRowOfAR16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
682 {
683     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
684         destination[0] = convertColor16BigTo8(source[1]);
685         destination[1] = convertColor16BigTo8(source[1]);
686         destination[2] = convertColor16BigTo8(source[1]);
687         destination[3] = convertColor16BigTo8(source[0]);
688         source += 2;
689         destination += 4;
690     }
691 }
692
693 void unpackOneRowOfA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
694 {
695     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
696         destination[0] = 0x0;
697         destination[1] = 0x0;
698         destination[2] = 0x0;
699         destination[3] = source[0];
700         source += 1;
701         destination += 4;
702     }
703 }
704
705 void unpackOneRowOfA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
706 {
707     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
708         destination[0] = 0x0;
709         destination[1] = 0x0;
710         destination[2] = 0x0;
711         destination[3] = convertColor16LittleTo8(source[0]);
712         source += 1;
713         destination += 4;
714     }
715 }
716
717 void unpackOneRowOfA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
718 {
719     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
720         destination[0] = 0x0;
721         destination[1] = 0x0;
722         destination[2] = 0x0;
723         destination[3] = convertColor16BigTo8(source[0]);
724         source += 1;
725         destination += 4;
726     }
727 }
728
729 void unpackOneRowOfRGBA8ToRGBA32F(const uint8_t* source, float* destination, unsigned int pixelsPerRow)
730 {
731     const float scaleFactor = 1.0f / 255.0f;
732     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
733         destination[0] = source[0] * scaleFactor;
734         destination[1] = source[1] * scaleFactor;
735         destination[2] = source[2] * scaleFactor;
736         destination[3] = source[3] * scaleFactor;
737         source += 4;
738         destination += 4;
739     }
740 }
741
742 void unpackOneRowOfBGRA8ToRGBA32F(const uint8_t* source, float* destination, unsigned int pixelsPerRow)
743 {
744     const float scaleFactor = 1.0f / 255.0f;
745     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
746         destination[0] = source[2] * scaleFactor;
747         destination[1] = source[1] * scaleFactor;
748         destination[2] = source[0] * scaleFactor;
749         destination[3] = source[3] * scaleFactor;
750         source += 4;
751         destination += 4;
752     }
753 }
754
755 void unpackOneRowOfRGB32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
756 {
757     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
758         destination[0] = source[0];
759         destination[1] = source[1];
760         destination[2] = source[2];
761         destination[3] = 1;
762         source += 3;
763         destination += 4;
764     }
765 }
766
767 void unpackOneRowOfR32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
768 {
769     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
770         destination[0] = source[0];
771         destination[1] = source[0];
772         destination[2] = source[0];
773         destination[3] = 1;
774         source += 1;
775         destination += 4;
776     }
777 }
778
779 void unpackOneRowOfRA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
780 {
781     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
782         destination[0] = source[0];
783         destination[1] = source[0];
784         destination[2] = source[0];
785         destination[3] = source[1];
786         source += 2;
787         destination += 4;
788     }
789 }
790
791 void unpackOneRowOfA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
792 {
793     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
794         destination[0] = 0;
795         destination[1] = 0;
796         destination[2] = 0;
797         destination[3] = source[0];
798         source += 1;
799         destination += 4;
800     }
801 }
802
803 //----------------------------------------------------------------------
804 // Pixel packing routines.
805 //
806
807 void packOneRowOfRGBA8ToA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
808 {
809     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
810         destination[0] = source[3];
811         source += 4;
812         destination += 1;
813     }
814 }
815
816 void packOneRowOfRGBA8ToR8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
817 {
818     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
819         destination[0] = source[0];
820         source += 4;
821         destination += 1;
822     }
823 }
824
825 void packOneRowOfRGBA8ToR8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
826 {
827     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
828         float scaleFactor = source[3] / 255.0f;
829         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
830         destination[0] = sourceR;
831         source += 4;
832         destination += 1;
833     }
834 }
835
836 // FIXME: this routine is lossy and must be removed.
837 void packOneRowOfRGBA8ToR8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
838 {
839     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
840         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
841         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
842         destination[0] = sourceR;
843         source += 4;
844         destination += 1;
845     }
846 }
847
848 void packOneRowOfRGBA8ToRA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
849 {
850     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
851         destination[0] = source[0];
852         destination[1] = source[3];
853         source += 4;
854         destination += 2;
855     }
856 }
857
858 void packOneRowOfRGBA8ToRA8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
859 {
860     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
861         float scaleFactor = source[3] / 255.0f;
862         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
863         destination[0] = sourceR;
864         destination[1] = source[3];
865         source += 4;
866         destination += 2;
867     }
868 }
869
870 // FIXME: this routine is lossy and must be removed.
871 void packOneRowOfRGBA8ToRA8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
872 {
873     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
874         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
875         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
876         destination[0] = sourceR;
877         destination[1] = source[3];
878         source += 4;
879         destination += 2;
880     }
881 }
882
883 void packOneRowOfRGBA8ToRGB8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
884 {
885     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
886         destination[0] = source[0];
887         destination[1] = source[1];
888         destination[2] = source[2];
889         source += 4;
890         destination += 3;
891     }
892 }
893
894 void packOneRowOfRGBA8ToRGB8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
895 {
896     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
897         float scaleFactor = source[3] / 255.0f;
898         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
899         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
900         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
901         destination[0] = sourceR;
902         destination[1] = sourceG;
903         destination[2] = sourceB;
904         source += 4;
905         destination += 3;
906     }
907 }
908
909 // FIXME: this routine is lossy and must be removed.
910 void packOneRowOfRGBA8ToRGB8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
911 {
912     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
913         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
914         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
915         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
916         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
917         destination[0] = sourceR;
918         destination[1] = sourceG;
919         destination[2] = sourceB;
920         source += 4;
921         destination += 3;
922     }
923 }
924
925 void packOneRowOfRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
926 {
927     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
928         float scaleFactor = source[3] / 255.0f;
929         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
930         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
931         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
932         destination[0] = sourceR;
933         destination[1] = sourceG;
934         destination[2] = sourceB;
935         destination[3] = source[3];
936         source += 4;
937         destination += 4;
938     }
939 }
940
941 // FIXME: this routine is lossy and must be removed.
942 void packOneRowOfRGBA8ToRGBA8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
943 {
944     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
945         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
946         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
947         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
948         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
949         destination[0] = sourceR;
950         destination[1] = sourceG;
951         destination[2] = sourceB;
952         destination[3] = source[3];
953         source += 4;
954         destination += 4;
955     }
956 }
957
958 void packOneRowOfRGBA8ToUnsignedShort4444(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
959 {
960     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
961         *destination = (((source[0] & 0xF0) << 8)
962                         | ((source[1] & 0xF0) << 4)
963                         | (source[2] & 0xF0)
964                         | (source[3] >> 4));
965         source += 4;
966         destination += 1;
967     }
968 }
969
970 void packOneRowOfRGBA8ToUnsignedShort4444Premultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
971 {
972     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
973         float scaleFactor = source[3] / 255.0f;
974         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
975         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
976         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
977         *destination = (((sourceR & 0xF0) << 8)
978                         | ((sourceG & 0xF0) << 4)
979                         | (sourceB & 0xF0)
980                         | (source[3] >> 4));
981         source += 4;
982         destination += 1;
983     }
984 }
985
986 // FIXME: this routine is lossy and must be removed.
987 void packOneRowOfRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
988 {
989     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
990         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
991         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
992         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
993         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
994         *destination = (((sourceR & 0xF0) << 8)
995                         | ((sourceG & 0xF0) << 4)
996                         | (sourceB & 0xF0)
997                         | (source[3] >> 4));
998         source += 4;
999         destination += 1;
1000     }
1001 }
1002
1003 void packOneRowOfRGBA8ToUnsignedShort5551(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1004 {
1005     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1006         *destination = (((source[0] & 0xF8) << 8)
1007                         | ((source[1] & 0xF8) << 3)
1008                         | ((source[2] & 0xF8) >> 2)
1009                         | (source[3] >> 7));
1010         source += 4;
1011         destination += 1;
1012     }
1013 }
1014
1015 void packOneRowOfRGBA8ToUnsignedShort5551Premultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1016 {
1017     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1018         float scaleFactor = source[3] / 255.0f;
1019         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
1020         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1021         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1022         *destination = (((sourceR & 0xF8) << 8)
1023                         | ((sourceG & 0xF8) << 3)
1024                         | ((sourceB & 0xF8) >> 2)
1025                         | (source[3] >> 7));
1026         source += 4;
1027         destination += 1;
1028     }
1029 }
1030
1031 // FIXME: this routine is lossy and must be removed.
1032 void packOneRowOfRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1033 {
1034     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1035         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
1036         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
1037         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1038         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1039         *destination = (((sourceR & 0xF8) << 8)
1040                         | ((sourceG & 0xF8) << 3)
1041                         | ((sourceB & 0xF8) >> 2)
1042                         | (source[3] >> 7));
1043         source += 4;
1044         destination += 1;
1045     }
1046 }
1047
1048 void packOneRowOfRGBA8ToUnsignedShort565(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1049 {
1050     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1051         *destination = (((source[0] & 0xF8) << 8)
1052                         | ((source[1] & 0xFC) << 3)
1053                         | ((source[2] & 0xF8) >> 3));
1054         source += 4;
1055         destination += 1;
1056     }
1057 }
1058
1059 void packOneRowOfRGBA8ToUnsignedShort565Premultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1060 {
1061     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1062         float scaleFactor = source[3] / 255.0f;
1063         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
1064         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1065         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1066         *destination = (((sourceR & 0xF8) << 8)
1067                         | ((sourceG & 0xFC) << 3)
1068                         | ((sourceB & 0xF8) >> 3));
1069         source += 4;
1070         destination += 1;
1071     }
1072 }
1073
1074 // FIXME: this routine is lossy and must be removed.
1075 void packOneRowOfRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1076 {
1077     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1078         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
1079         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
1080         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1081         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1082         *destination = (((sourceR & 0xF8) << 8)
1083                         | ((sourceG & 0xFC) << 3)
1084                         | ((sourceB & 0xF8) >> 3));
1085         source += 4;
1086         destination += 1;
1087     }
1088 }
1089
1090 void packOneRowOfRGBA32FToRGB32F(const float* source, float* destination, unsigned int pixelsPerRow)
1091 {
1092     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1093         destination[0] = source[0];
1094         destination[1] = source[1];
1095         destination[2] = source[2];
1096         source += 4;
1097         destination += 3;
1098     }
1099 }
1100
1101 void packOneRowOfRGBA32FToRGB32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1102 {
1103     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1104         float scaleFactor = source[3];
1105         destination[0] = source[0] * scaleFactor;
1106         destination[1] = source[1] * scaleFactor;
1107         destination[2] = source[2] * scaleFactor;
1108         source += 4;
1109         destination += 3;
1110     }
1111 }
1112
1113 void packOneRowOfRGBA32FToRGB32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1114 {
1115     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1116         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1117         destination[0] = source[0] * scaleFactor;
1118         destination[1] = source[1] * scaleFactor;
1119         destination[2] = source[2] * scaleFactor;
1120         source += 4;
1121         destination += 3;
1122     }
1123 }
1124
1125 // Used only during RGBA8 or BGRA8 -> floating-point uploads.
1126 void packOneRowOfRGBA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
1127 {
1128     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1129         destination[0] = source[0];
1130         destination[1] = source[1];
1131         destination[2] = source[2];
1132         destination[3] = source[3];
1133         source += 4;
1134         destination += 4;
1135     }
1136 }
1137
1138 void packOneRowOfRGBA32FToRGBA32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1139 {
1140     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1141         float scaleFactor = source[3];
1142         destination[0] = source[0] * scaleFactor;
1143         destination[1] = source[1] * scaleFactor;
1144         destination[2] = source[2] * scaleFactor;
1145         destination[3] = source[3];
1146         source += 4;
1147         destination += 4;
1148     }
1149 }
1150
1151 void packOneRowOfRGBA32FToRGBA32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1152 {
1153     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1154         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1155         destination[0] = source[0] * scaleFactor;
1156         destination[1] = source[1] * scaleFactor;
1157         destination[2] = source[2] * scaleFactor;
1158         destination[3] = source[3];
1159         source += 4;
1160         destination += 4;
1161     }
1162 }
1163
1164 void packOneRowOfRGBA32FToA32F(const float* source, float* destination, unsigned int pixelsPerRow)
1165 {
1166     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1167         destination[0] = source[3];
1168         source += 4;
1169         destination += 1;
1170     }
1171 }
1172
1173 void packOneRowOfRGBA32FToR32F(const float* source, float* destination, unsigned int pixelsPerRow)
1174 {
1175     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1176         destination[0] = source[0];
1177         source += 4;
1178         destination += 1;
1179     }
1180 }
1181
1182 void packOneRowOfRGBA32FToR32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1183 {
1184     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1185         float scaleFactor = source[3];
1186         destination[0] = source[0] * scaleFactor;
1187         source += 4;
1188         destination += 1;
1189     }
1190 }
1191
1192 void packOneRowOfRGBA32FToR32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1193 {
1194     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1195         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1196         destination[0] = source[0] * scaleFactor;
1197         source += 4;
1198         destination += 1;
1199     }
1200 }
1201
1202 void packOneRowOfRGBA32FToRA32F(const float* source, float* destination, unsigned int pixelsPerRow)
1203 {
1204     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1205         destination[0] = source[0];
1206         destination[1] = source[3];
1207         source += 4;
1208         destination += 2;
1209     }
1210 }
1211
1212 void packOneRowOfRGBA32FToRA32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1213 {
1214     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1215         float scaleFactor = source[3];
1216         destination[0] = source[0] * scaleFactor;
1217         destination[1] = source[3];
1218         source += 4;
1219         destination += 2;
1220     }
1221 }
1222
1223 void packOneRowOfRGBA32FToRA32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1224 {
1225     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1226         float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
1227         destination[0] = source[0] * scaleFactor;
1228         destination[1] = source[3];
1229         source += 4;
1230         destination += 2;
1231     }
1232 }
1233
1234 } // anonymous namespace
1235
1236 // This is used whenever unpacking is necessary; i.e., the source data
1237 // is not in RGBA8/RGBA32F format, or the unpack alignment specifies
1238 // that rows are not tightly packed.
1239 template<typename SourceType, typename IntermediateType, typename DestType>
1240 static void doUnpackingAndPacking(const SourceType* sourceData,
1241                                   void (*rowUnpackingFunc)(const SourceType*, IntermediateType*, unsigned int),
1242                                   unsigned int width,
1243                                   unsigned int height,
1244                                   unsigned int sourceElementsPerRow,
1245                                   DestType* destinationData,
1246                                   void (*rowPackingFunc)(const IntermediateType*, DestType*, unsigned int),
1247                                   unsigned int destinationElementsPerPixel)
1248 {
1249     if (!rowPackingFunc) {
1250         // The row packing is trivial, so don't bother with a temporary buffer.
1251         const SourceType* endPointer = sourceData + height * sourceElementsPerRow;
1252         unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1253         while (sourceData < endPointer) {
1254             rowUnpackingFunc(sourceData, reinterpret_cast<IntermediateType*>(destinationData), width);
1255             sourceData += sourceElementsPerRow;
1256             destinationData += destinationElementsPerRow;
1257         }
1258     } else {
1259         OwnArrayPtr<IntermediateType> temporaryRGBAData = adoptArrayPtr(new IntermediateType[width * 4]);
1260         const SourceType* endPointer = sourceData + height * sourceElementsPerRow;
1261         unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1262         while (sourceData < endPointer) {
1263             rowUnpackingFunc(sourceData, temporaryRGBAData.get(), width);
1264             rowPackingFunc(temporaryRGBAData.get(), destinationData, width);
1265             sourceData += sourceElementsPerRow;
1266             destinationData += destinationElementsPerRow;
1267         }
1268     }
1269 }
1270
1271 template<typename SourceType>
1272 static unsigned int computeSourceElementsPerRow(unsigned int width,
1273                                                 unsigned int bytesPerPixel,
1274                                                 unsigned int unpackAlignment)
1275 {
1276     unsigned int elementSizeInBytes = sizeof(SourceType);
1277     ASSERT(elementSizeInBytes <= bytesPerPixel);
1278     ASSERT(!(bytesPerPixel % elementSizeInBytes));
1279     unsigned int validRowBytes = width * bytesPerPixel;
1280     unsigned int totalRowBytes = validRowBytes;
1281     if (unpackAlignment) {
1282         unsigned int remainder = validRowBytes % unpackAlignment;
1283         if (remainder)
1284             totalRowBytes += (unpackAlignment - remainder);
1285     }
1286     return totalRowBytes / elementSizeInBytes;
1287 }
1288
1289 // This handles all conversions with a faster path for tightly packed RGBA8 source data.
1290 template<typename DestType>
1291 static void doPacking(const void* sourceData,
1292                       GraphicsContext3D::SourceDataFormat sourceDataFormat,
1293                       unsigned int width,
1294                       unsigned int height,
1295                       unsigned int sourceUnpackAlignment,
1296                       DestType* destinationData,
1297                       void (*rowPackingFunc)(const uint8_t*, DestType*, unsigned int),
1298                       unsigned int destinationElementsPerPixel)
1299 {
1300     switch (sourceDataFormat) {
1301     case GraphicsContext3D::SourceFormatRGBA8: {
1302         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1303         const uint8_t* source = static_cast<const uint8_t*>(sourceData);
1304         const uint8_t* endPointer = source + height * sourceElementsPerRow;
1305         unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1306         while (source < endPointer) {
1307             if (rowPackingFunc)
1308                 rowPackingFunc(source, destinationData, width);
1309             else
1310                 memcpy(destinationData, source, width * 4);
1311             source += sourceElementsPerRow;
1312             destinationData += destinationElementsPerRow;
1313         }
1314         break;
1315     }
1316     case GraphicsContext3D::SourceFormatRGBA16Little: {
1317         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1318         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1319         break;
1320     }
1321     case GraphicsContext3D::SourceFormatRGBA16Big: {
1322         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1323         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1324         break;
1325     }
1326     case GraphicsContext3D::SourceFormatRGB8: {
1327         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 3, sourceUnpackAlignment);
1328         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRGB8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1329         break;
1330     }
1331     case GraphicsContext3D::SourceFormatRGB16Little: {
1332         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 6, sourceUnpackAlignment);
1333         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGB16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1334         break;
1335     }
1336     case GraphicsContext3D::SourceFormatRGB16Big: {
1337         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 6, sourceUnpackAlignment);
1338         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGB16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1339         break;
1340     }
1341     case GraphicsContext3D::SourceFormatBGR8: {
1342         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 3, sourceUnpackAlignment);
1343         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1344         break;
1345     }
1346     case GraphicsContext3D::SourceFormatARGB8: {
1347         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1348         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfARGB8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1349         break;
1350     }
1351     case GraphicsContext3D::SourceFormatARGB16Little: {
1352         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1353         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfARGB16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1354         break;
1355     }
1356     case GraphicsContext3D::SourceFormatARGB16Big: {
1357         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1358         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfARGB16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1359         break;
1360     }
1361     case GraphicsContext3D::SourceFormatABGR8: {
1362         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1363         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfABGR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1364         break;
1365     }
1366     case GraphicsContext3D::SourceFormatBGRA8: {
1367         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1368         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGRA8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1369         break;
1370     }
1371     case GraphicsContext3D::SourceFormatBGRA16Little: {
1372         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1373         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfBGRA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1374         break;
1375     }
1376     case GraphicsContext3D::SourceFormatBGRA16Big: {
1377         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1378         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfBGRA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1379         break;
1380     }
1381     case GraphicsContext3D::SourceFormatRGBA5551: {
1382         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1383         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA5551ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1384         break;
1385     }
1386     case GraphicsContext3D::SourceFormatRGBA4444: {
1387         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1388         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA4444ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1389         break;
1390     }
1391     case GraphicsContext3D::SourceFormatRGB565: {
1392         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1393         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGB565ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1394         break;
1395     }
1396     case GraphicsContext3D::SourceFormatR8: {
1397         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 1, sourceUnpackAlignment);
1398         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1399         break;
1400     }
1401     case GraphicsContext3D::SourceFormatR16Little: {
1402         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1403         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfR16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1404         break;
1405     }
1406     case GraphicsContext3D::SourceFormatR16Big: {
1407         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1408         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfR16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1409         break;
1410     }
1411     case GraphicsContext3D::SourceFormatRA8: {
1412         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 2, sourceUnpackAlignment);
1413         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRA8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1414         break;
1415     }
1416     case GraphicsContext3D::SourceFormatRA16Little: {
1417         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1418         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1419         break;
1420     }
1421     case GraphicsContext3D::SourceFormatRA16Big: {
1422         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1423         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1424         break;
1425     }
1426     case GraphicsContext3D::SourceFormatAR8: {
1427         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 2, sourceUnpackAlignment);
1428         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfAR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1429         break;
1430     }
1431     case GraphicsContext3D::SourceFormatAR16Little: {
1432         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1433         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfAR16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1434         break;
1435     }
1436     case GraphicsContext3D::SourceFormatAR16Big: {
1437         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1438         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfAR16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1439         break;
1440     }
1441     case GraphicsContext3D::SourceFormatA8: {
1442         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 1, sourceUnpackAlignment);
1443         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfA8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1444         break;
1445     }
1446     case GraphicsContext3D::SourceFormatA16Little: {
1447         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1448         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1449         break;
1450     }
1451     case GraphicsContext3D::SourceFormatA16Big: {
1452         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1453         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1454         break;
1455     }
1456     default:
1457         ASSERT_NOT_REACHED();
1458     }
1459 }
1460
1461 // This specialized routine is used only for floating-point texture uploads. It
1462 // does not need to be as general as doPacking, above; because there are
1463 // currently no native floating-point image formats in WebKit, there are only a
1464 // few upload paths.
1465 static void doFloatingPointPacking(const void* sourceData,
1466                                    GraphicsContext3D::SourceDataFormat sourceDataFormat,
1467                                    unsigned int width,
1468                                    unsigned int height,
1469                                    unsigned int sourceUnpackAlignment,
1470                                    float* destinationData,
1471                                    void rowPackingFunc(const float*, float*, unsigned int),
1472                                    unsigned int destinationElementsPerPixel)
1473 {
1474     switch (sourceDataFormat) {
1475     case GraphicsContext3D::SourceFormatRGBA8: {
1476         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1477         doUnpackingAndPacking<uint8_t, float, float>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRGBA8ToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1478         break;
1479     }
1480     case GraphicsContext3D::SourceFormatBGRA8: {
1481         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1482         doUnpackingAndPacking<uint8_t, float, float>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGRA8ToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1483         break;
1484     }
1485     case GraphicsContext3D::SourceFormatRGBA32F: {
1486         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 4, sourceUnpackAlignment);
1487         const float* source = static_cast<const float*>(sourceData);
1488         const float* endPointer = source + height * sourceElementsPerRow;
1489         unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1490         while (source < endPointer) {
1491             rowPackingFunc(source, destinationData, width);
1492             source += sourceElementsPerRow;
1493             destinationData += destinationElementsPerRow;
1494         }
1495         break;
1496     }
1497     case GraphicsContext3D::SourceFormatRGB32F: {
1498         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 3, sourceUnpackAlignment);
1499         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfRGB32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1500         break;
1501     }
1502     case GraphicsContext3D::SourceFormatR32F: {
1503         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 1, sourceUnpackAlignment);
1504         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfR32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1505         break;
1506     }
1507     case GraphicsContext3D::SourceFormatRA32F: {
1508         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 2, sourceUnpackAlignment);
1509         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfRA32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1510         break;
1511     }
1512     case GraphicsContext3D::SourceFormatA32F: {
1513         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 1, sourceUnpackAlignment);
1514         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfA32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1515         break;
1516     }
1517     default:
1518         ASSERT_NOT_REACHED();
1519     }
1520 }
1521
1522
1523 #if !ASSERT_DISABLED
1524 static bool isFloatingPointSource(GraphicsContext3D::SourceDataFormat format)
1525 {
1526     switch (format) {
1527     case GraphicsContext3D::SourceFormatRGBA32F:
1528     case GraphicsContext3D::SourceFormatRGB32F:
1529     case GraphicsContext3D::SourceFormatRA32F:
1530     case GraphicsContext3D::SourceFormatR32F:
1531     case GraphicsContext3D::SourceFormatA32F:
1532         return true;
1533     default:
1534         return false;
1535     }
1536 }
1537 #endif
1538
1539 bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
1540                                    GraphicsContext3D::SourceDataFormat sourceDataFormat,
1541                                    unsigned int width,
1542                                    unsigned int height,
1543                                    unsigned int sourceUnpackAlignment,
1544                                    unsigned int destinationFormat,
1545                                    unsigned int destinationType,
1546                                    AlphaOp alphaOp,
1547                                    void* destinationData)
1548 {
1549     switch (destinationType) {
1550     case UNSIGNED_BYTE: {
1551         uint8_t* destination = static_cast<uint8_t*>(destinationData);
1552         if (sourceDataFormat == SourceFormatRGBA8 && destinationFormat == RGBA && sourceUnpackAlignment <= 4 && alphaOp == AlphaDoNothing) {
1553             // No conversion necessary.
1554             memcpy(destinationData, sourceData, width * height * 4);
1555             break;
1556         }
1557         switch (destinationFormat) {
1558         case RGB:
1559             switch (alphaOp) {
1560             case AlphaDoNothing:
1561                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGB8, 3);
1562                 break;
1563             case AlphaDoPremultiply:
1564                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGB8Premultiply, 3);
1565                 break;
1566             case AlphaDoUnmultiply:
1567                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGB8Unmultiply, 3);
1568                 break;
1569             }
1570             break;
1571         case RGBA:
1572             switch (alphaOp) {
1573             case AlphaDoNothing:
1574                 ASSERT(sourceDataFormat != SourceFormatRGBA8 || sourceUnpackAlignment > 4); // Handled above with fast case.
1575                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 0, 4);
1576                 break;
1577             case AlphaDoPremultiply:
1578                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGBA8Premultiply, 4);
1579                 break;
1580             case AlphaDoUnmultiply:
1581                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGBA8Unmultiply, 4);
1582                 break;
1583             default:
1584                 ASSERT_NOT_REACHED();
1585             }
1586             break;
1587         case ALPHA:
1588             // From the desktop OpenGL conversion rules (OpenGL 2.1
1589             // specification, Table 3.15), the alpha channel is chosen
1590             // from the RGBA data.
1591             doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToA8, 1);
1592             break;
1593         case LUMINANCE:
1594             // From the desktop OpenGL conversion rules (OpenGL 2.1
1595             // specification, Table 3.15), the red channel is chosen
1596             // from the RGBA data.
1597             switch (alphaOp) {
1598             case AlphaDoNothing:
1599                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToR8, 1);
1600                 break;
1601             case AlphaDoPremultiply:
1602                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToR8Premultiply, 1);
1603                 break;
1604             case AlphaDoUnmultiply:
1605                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToR8Unmultiply, 1);
1606                 break;
1607             }
1608             break;
1609         case LUMINANCE_ALPHA:
1610             // From the desktop OpenGL conversion rules (OpenGL 2.1
1611             // specification, Table 3.15), the red and alpha channels
1612             // are chosen from the RGBA data.
1613             switch (alphaOp) {
1614             case AlphaDoNothing:
1615                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRA8, 2);
1616                 break;
1617             case AlphaDoPremultiply:
1618                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRA8Premultiply, 2);
1619                 break;
1620             case AlphaDoUnmultiply:
1621                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRA8Unmultiply, 2);
1622                 break;
1623             }
1624             break;
1625         }
1626         break;
1627     }
1628     case UNSIGNED_SHORT_4_4_4_4: {
1629         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1630         switch (alphaOp) {
1631         case AlphaDoNothing:
1632             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort4444, 1);
1633             break;
1634         case AlphaDoPremultiply:
1635             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort4444Premultiply, 1);
1636             break;
1637         case AlphaDoUnmultiply:
1638             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort4444Unmultiply, 1);
1639             break;
1640         }
1641         break;
1642     }
1643     case UNSIGNED_SHORT_5_5_5_1: {
1644         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1645         switch (alphaOp) {
1646         case AlphaDoNothing:
1647             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort5551, 1);
1648             break;
1649         case AlphaDoPremultiply:
1650             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort5551Premultiply, 1);
1651             break;
1652         case AlphaDoUnmultiply:
1653             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort5551Unmultiply, 1);
1654             break;
1655         }
1656         break;
1657     }
1658     case UNSIGNED_SHORT_5_6_5: {
1659         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1660         switch (alphaOp) {
1661         case AlphaDoNothing:
1662             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort565, 1);
1663             break;
1664         case AlphaDoPremultiply:
1665             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort565Premultiply, 1);
1666             break;
1667         case AlphaDoUnmultiply:
1668             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort565Unmultiply, 1);
1669             break;
1670         }
1671         break;
1672     }
1673     case FLOAT: {
1674         // OpenGL ES, and therefore WebGL, require that the format and
1675         // internalformat be identical. This means that whenever the
1676         // developer supplies an ArrayBufferView on this code path,
1677         // the source data will be in a floating-point format.
1678         //
1679         // The only time the source data will not be floating-point is
1680         // when uploading a DOM element or ImageData as a
1681         // floating-point texture. Only RGBA8 and BGRA8 are handled in
1682         // this case.
1683         ASSERT(isFloatingPointSource(sourceDataFormat)
1684                || sourceDataFormat == SourceFormatRGBA8
1685                || sourceDataFormat == SourceFormatBGRA8);
1686         // When uploading a canvas into a floating-point texture,
1687         // unmultiplication may be necessary.
1688         ASSERT((alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply)
1689                || !isFloatingPointSource(sourceDataFormat));
1690         // For the source formats with an even number of channels (RGBA32F,
1691         // RA32F) it is guaranteed that the pixel data is tightly packed because
1692         // unpack alignment <= sizeof(float) * number of channels.
1693         float* destination = static_cast<float*>(destinationData);
1694         if (alphaOp == AlphaDoNothing
1695             && ((sourceDataFormat == SourceFormatRGBA32F && destinationFormat == RGBA)
1696                 || (sourceDataFormat == SourceFormatRA32F && destinationFormat == LUMINANCE_ALPHA))) {
1697             // No conversion necessary.
1698             int numChannels = (sourceDataFormat == SourceFormatRGBA32F ? 4 : 2);
1699             memcpy(destinationData, sourceData, width * height * numChannels * sizeof(float));
1700             break;
1701         }
1702         switch (destinationFormat) {
1703         case RGB:
1704             switch (alphaOp) {
1705             case AlphaDoNothing:
1706                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32F, 3);
1707                 break;
1708             case AlphaDoPremultiply:
1709                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FPremultiply, 3);
1710                 break;
1711             case AlphaDoUnmultiply:
1712                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FUnmultiply, 3);
1713                 break;
1714             }
1715             break;
1716         case RGBA:
1717             // AlphaDoNothing for RGBA32F -> RGBA is handled above with fast path.
1718             ASSERT(alphaOp != AlphaDoNothing || sourceDataFormat != SourceFormatRGBA32F);
1719             switch (alphaOp) {
1720             case AlphaDoNothing:
1721                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32F, 4);
1722                 break;
1723             case AlphaDoPremultiply:
1724                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FPremultiply, 4);
1725                 break;
1726             case AlphaDoUnmultiply:
1727                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FUnmultiply, 4);
1728                 break;
1729             }
1730             break;
1731         case ALPHA:
1732             // From the desktop OpenGL conversion rules (OpenGL 2.1
1733             // specification, Table 3.15), the alpha channel is chosen
1734             // from the RGBA data.
1735             doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToA32F, 1);
1736             break;
1737         case LUMINANCE:
1738             // From the desktop OpenGL conversion rules (OpenGL 2.1
1739             // specification, Table 3.15), the red channel is chosen
1740             // from the RGBA data.
1741             switch (alphaOp) {
1742             case AlphaDoNothing:
1743                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32F, 1);
1744                 break;
1745             case AlphaDoPremultiply:
1746                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FPremultiply, 1);
1747                 break;
1748             case AlphaDoUnmultiply:
1749                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FUnmultiply, 1);
1750                 break;
1751             }
1752             break;
1753         case LUMINANCE_ALPHA:
1754             // From the desktop OpenGL conversion rules (OpenGL 2.1
1755             // specification, Table 3.15), the red and alpha channels
1756             // are chosen from the RGBA data.
1757             switch (alphaOp) {
1758             case AlphaDoNothing:
1759                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32F, 2);
1760                 break;
1761             case AlphaDoPremultiply:
1762                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FPremultiply, 2);
1763                 break;
1764             case AlphaDoUnmultiply:
1765                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FUnmultiply, 2);
1766                 break;
1767             }
1768             break;
1769         }
1770         break;
1771     }
1772     }
1773     return true;
1774 }
1775
1776 unsigned GraphicsContext3D::getClearBitsByAttachmentType(GC3Denum attachment)
1777 {
1778     switch (attachment) {
1779     case GraphicsContext3D::COLOR_ATTACHMENT0:
1780         return GraphicsContext3D::COLOR_BUFFER_BIT;
1781     case GraphicsContext3D::DEPTH_ATTACHMENT:
1782         return GraphicsContext3D::DEPTH_BUFFER_BIT;
1783     case GraphicsContext3D::STENCIL_ATTACHMENT:
1784         return GraphicsContext3D::STENCIL_BUFFER_BIT;
1785     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
1786         return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT;
1787     default:
1788         return 0;
1789     }
1790 }
1791
1792 unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
1793 {
1794     switch (format) {
1795     case GraphicsContext3D::ALPHA:
1796     case GraphicsContext3D::LUMINANCE:
1797     case GraphicsContext3D::LUMINANCE_ALPHA:
1798     case GraphicsContext3D::RGB:
1799     case GraphicsContext3D::RGB565:
1800     case GraphicsContext3D::RGBA:
1801     case GraphicsContext3D::RGBA4:
1802     case GraphicsContext3D::RGB5_A1:
1803         return GraphicsContext3D::COLOR_BUFFER_BIT;
1804     case GraphicsContext3D::DEPTH_COMPONENT16:
1805     case GraphicsContext3D::DEPTH_COMPONENT:
1806         return GraphicsContext3D::DEPTH_BUFFER_BIT;
1807     case GraphicsContext3D::STENCIL_INDEX8:
1808         return GraphicsContext3D::STENCIL_BUFFER_BIT;
1809     case GraphicsContext3D::DEPTH_STENCIL:
1810         return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT;
1811     default:
1812         return 0;
1813     }
1814 }
1815
1816 unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format)
1817 {
1818     switch (format) {
1819     case GraphicsContext3D::ALPHA:
1820         return ChannelAlpha;
1821     case GraphicsContext3D::LUMINANCE:
1822         return ChannelRGB;
1823     case GraphicsContext3D::LUMINANCE_ALPHA:
1824         return ChannelRGBA;
1825     case GraphicsContext3D::RGB:
1826     case GraphicsContext3D::RGB565:
1827         return ChannelRGB;
1828     case GraphicsContext3D::RGBA:
1829     case GraphicsContext3D::RGBA4:
1830     case GraphicsContext3D::RGB5_A1:
1831         return ChannelRGBA;
1832     case GraphicsContext3D::DEPTH_COMPONENT16:
1833     case GraphicsContext3D::DEPTH_COMPONENT:
1834         return ChannelDepth;
1835     case GraphicsContext3D::STENCIL_INDEX8:
1836         return ChannelStencil;
1837     case GraphicsContext3D::DEPTH_STENCIL:
1838         return ChannelDepth | ChannelStencil;
1839     default:
1840         return 0;
1841     }
1842 }
1843
1844 } // namespace WebCore
1845
1846 #endif // USE(3D_GRAPHICS)