OSDN Git Service

HW accelate button focus rings
[android-x86/external-webkit.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)
30
31 #include "GraphicsContext3D.h"
32
33 #include "ArrayBufferView.h"
34 #include "CheckedInt.h"
35 #include "DrawingBuffer.h"
36 #include "Extensions3D.h"
37 #include "Image.h"
38 #include "ImageData.h"
39
40 #include <wtf/OwnArrayPtr.h>
41 #include <wtf/PassOwnArrayPtr.h>
42
43 namespace WebCore {
44
45 namespace {
46
47     uint8_t convertColor16LittleTo8(uint16_t value)
48     {
49         return value >> 8;
50     }
51
52     uint8_t convertColor16BigTo8(uint16_t value)
53     {
54         return static_cast<uint8_t>(value & 0x00FF);
55     }
56
57 } // anonymous namespace
58
59
60 PassRefPtr<DrawingBuffer> GraphicsContext3D::createDrawingBuffer(const IntSize& size)
61 {
62     return DrawingBuffer::create(this, size);
63 }
64
65 bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
66 {
67     ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
68     OwnArrayPtr<unsigned char> zero;
69     if (width > 0 && height > 0) {
70         unsigned int size;
71         GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, 0);
72         if (error != GraphicsContext3D::NO_ERROR) {
73             synthesizeGLError(error);
74             return false;
75         }
76         zero = adoptArrayPtr(new unsigned char[size]);
77         if (!zero) {
78             synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
79             return false;
80         }
81         memset(zero.get(), 0, size);
82     }
83     return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get());
84 }
85
86 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format,
87                                                        GC3Denum type,
88                                                        unsigned int* componentsPerPixel,
89                                                        unsigned int* bytesPerComponent)
90 {
91     switch (format) {
92     case GraphicsContext3D::ALPHA:
93         *componentsPerPixel = 1;
94         break;
95     case GraphicsContext3D::LUMINANCE:
96         *componentsPerPixel = 1;
97         break;
98     case GraphicsContext3D::LUMINANCE_ALPHA:
99         *componentsPerPixel = 2;
100         break;
101     case GraphicsContext3D::RGB:
102         *componentsPerPixel = 3;
103         break;
104     case GraphicsContext3D::RGBA:
105     case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
106         *componentsPerPixel = 4;
107         break;
108     default:
109         return false;
110     }
111     switch (type) {
112     case GraphicsContext3D::UNSIGNED_BYTE:
113         *bytesPerComponent = sizeof(GC3Dubyte);
114         break;
115     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
116     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
117     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
118         *componentsPerPixel = 1;
119         *bytesPerComponent = sizeof(GC3Dushort);
120         break;
121     case GraphicsContext3D::FLOAT: // OES_texture_float
122         *bytesPerComponent = sizeof(GC3Dfloat);
123         break;
124     default:
125         return false;
126     }
127     return true;
128 }
129
130 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment,
131                                                     unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
132 {
133     ASSERT(imageSizeInBytes);
134     ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
135     if (width < 0 || height < 0)
136         return GraphicsContext3D::INVALID_VALUE;
137     unsigned int bytesPerComponent, componentsPerPixel;
138     if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
139         return GraphicsContext3D::INVALID_ENUM;
140     if (!width || !height) {
141         *imageSizeInBytes = 0;
142         if (paddingInBytes)
143             *paddingInBytes = 0;
144         return GraphicsContext3D::NO_ERROR;
145     }
146     CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
147     checkedValue *=  width;
148     if (!checkedValue.valid())
149         return GraphicsContext3D::INVALID_VALUE;
150     unsigned int validRowSize = checkedValue.value();
151     unsigned int padding = 0;
152     unsigned int residual = validRowSize % alignment;
153     if (residual) {
154         padding = alignment - residual;
155         checkedValue += padding;
156     }
157     // Last row needs no padding.
158     checkedValue *= (height - 1);
159     checkedValue += validRowSize;
160     if (!checkedValue.valid())
161         return GraphicsContext3D::INVALID_VALUE;
162     *imageSizeInBytes = checkedValue.value();
163     if (paddingInBytes)
164         *paddingInBytes = padding;
165     return GraphicsContext3D::NO_ERROR;
166 }
167
168 bool GraphicsContext3D::extractImageData(Image* image,
169                                          GC3Denum format,
170                                          GC3Denum type,
171                                          bool flipY,
172                                          bool premultiplyAlpha,
173                                          bool ignoreGammaAndColorProfile,
174                                          Vector<uint8_t>& data)
175 {
176     if (!image)
177         return false;
178     if (!getImageData(image, format, type, premultiplyAlpha, ignoreGammaAndColorProfile, data))
179         return false;
180     if (flipY) {
181         unsigned int componentsPerPixel, bytesPerComponent;
182         if (!computeFormatAndTypeParameters(format, type,
183                                             &componentsPerPixel,
184                                             &bytesPerComponent))
185             return false;
186         // The image data is tightly packed, and we upload it as such.
187         unsigned int unpackAlignment = 1;
188         flipVertically(data.data(), image->width(), image->height(),
189                        componentsPerPixel * bytesPerComponent,
190                        unpackAlignment);
191     }
192     return true;
193 }
194
195 bool GraphicsContext3D::extractImageData(ImageData* imageData,
196                                          GC3Denum format,
197                                          GC3Denum type,
198                                          bool flipY,
199                                          bool premultiplyAlpha,
200                                          Vector<uint8_t>& data)
201 {
202     if (!imageData)
203         return false;
204     int width = imageData->width();
205     int height = imageData->height();
206     int dataBytes = width * height * 4;
207     data.resize(dataBytes);
208     if (!packPixels(imageData->data()->data()->data(),
209                     SourceFormatRGBA8,
210                     width,
211                     height,
212                     0,
213                     format,
214                     type,
215                     premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing,
216                     data.data()))
217         return false;
218     if (flipY) {
219         unsigned int componentsPerPixel, bytesPerComponent;
220         if (!computeFormatAndTypeParameters(format, type,
221                                             &componentsPerPixel,
222                                             &bytesPerComponent))
223             return false;
224         // The image data is tightly packed, and we upload it as such.
225         unsigned int unpackAlignment = 1;
226         flipVertically(data.data(), width, height,
227                        componentsPerPixel * bytesPerComponent,
228                        unpackAlignment);
229     }
230     return true;
231 }
232
233 bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int height,
234                                            GC3Denum format, GC3Denum type,
235                                            unsigned int unpackAlignment,
236                                            bool flipY, bool premultiplyAlpha,
237                                            const void* pixels,
238                                            Vector<uint8_t>& data)
239 {
240     // Assumes format, type, etc. have already been validated.
241     SourceDataFormat sourceDataFormat = SourceFormatRGBA8;
242     switch (type) {
243     case UNSIGNED_BYTE:
244         switch (format) {
245         case RGBA:
246             sourceDataFormat = SourceFormatRGBA8;
247             break;
248         case RGB:
249             sourceDataFormat = SourceFormatRGB8;
250             break;
251         case ALPHA:
252             sourceDataFormat = SourceFormatA8;
253             break;
254         case LUMINANCE:
255             sourceDataFormat = SourceFormatR8;
256             break;
257         case LUMINANCE_ALPHA:
258             sourceDataFormat = SourceFormatRA8;
259             break;
260         default:
261             ASSERT_NOT_REACHED();
262         }
263         break;
264     case FLOAT: // OES_texture_float
265         switch (format) {
266         case RGBA:
267             sourceDataFormat = SourceFormatRGBA32F;
268             break;
269         case RGB:
270             sourceDataFormat = SourceFormatRGB32F;
271             break;
272         case ALPHA:
273             sourceDataFormat = SourceFormatA32F;
274             break;
275         case LUMINANCE:
276             sourceDataFormat = SourceFormatR32F;
277             break;
278         case LUMINANCE_ALPHA:
279             sourceDataFormat = SourceFormatRA32F;
280             break;
281         default:
282             ASSERT_NOT_REACHED();
283         }
284         break;
285     case UNSIGNED_SHORT_5_5_5_1:
286         sourceDataFormat = SourceFormatRGBA5551;
287         break;
288     case UNSIGNED_SHORT_4_4_4_4:
289         sourceDataFormat = SourceFormatRGBA4444;
290         break;
291     case UNSIGNED_SHORT_5_6_5:
292         sourceDataFormat = SourceFormatRGB565;
293         break;
294     default:
295         ASSERT_NOT_REACHED();
296     }
297
298     // Resize the output buffer.
299     unsigned int componentsPerPixel, bytesPerComponent;
300     if (!computeFormatAndTypeParameters(format, type,
301                                         &componentsPerPixel,
302                                         &bytesPerComponent))
303         return false;
304     unsigned int bytesPerPixel = componentsPerPixel * bytesPerComponent;
305     data.resize(width * height * bytesPerPixel);
306
307     if (!packPixels(static_cast<const uint8_t*>(pixels),
308                     sourceDataFormat,
309                     width, height, unpackAlignment,
310                     format, type,
311                     (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing),
312                     data.data()))
313         return false;
314     // The pixel data is now tightly packed.
315     if (flipY)
316         flipVertically(data.data(), width, height, bytesPerPixel, 1);
317     return true;
318 }
319
320 void GraphicsContext3D::flipVertically(void* imageData,
321                                        unsigned int width,
322                                        unsigned int height,
323                                        unsigned int bytesPerPixel,
324                                        unsigned int unpackAlignment)
325 {
326     if (!width || !height)
327         return;
328     unsigned int validRowBytes = width * bytesPerPixel;
329     unsigned int totalRowBytes = validRowBytes;
330     unsigned int remainder = validRowBytes % unpackAlignment;
331     if (remainder)
332         totalRowBytes += (unpackAlignment - remainder);
333     uint8_t* tempRow = new uint8_t[validRowBytes];
334     uint8_t* data = static_cast<uint8_t*>(imageData);
335     for (unsigned i = 0; i < height / 2; i++) {
336         uint8_t* lowRow = data + (totalRowBytes * i);
337         uint8_t* highRow = data + (totalRowBytes * (height - i - 1));
338         memcpy(tempRow, lowRow, validRowBytes);
339         memcpy(lowRow, highRow, validRowBytes);
340         memcpy(highRow, tempRow, validRowBytes);
341     }
342     delete[] tempRow;
343 }
344
345 // These functions can not be static, or gcc will not allow them to be
346 // used as template parameters. Use an anonymous namespace to prevent
347 // the need to declare prototypes for them.
348 namespace {
349
350 //----------------------------------------------------------------------
351 // Pixel unpacking routines.
352
353 void unpackRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination)
354 {
355     destination[0] = source[0];
356     destination[1] = source[1];
357     destination[2] = source[2];
358     destination[3] = source[3];
359 }
360
361 void unpackRGBA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
362 {
363     destination[0] = convertColor16LittleTo8(source[0]);
364     destination[1] = convertColor16LittleTo8(source[1]);
365     destination[2] = convertColor16LittleTo8(source[2]);
366     destination[3] = convertColor16LittleTo8(source[3]);
367 }
368
369 void unpackRGBA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
370 {
371     destination[0] = convertColor16BigTo8(source[0]);
372     destination[1] = convertColor16BigTo8(source[1]);
373     destination[2] = convertColor16BigTo8(source[2]);
374     destination[3] = convertColor16BigTo8(source[3]);
375 }
376
377 void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
378 {
379     destination[0] = source[0];
380     destination[1] = source[1];
381     destination[2] = source[2];
382     destination[3] = 0xFF;
383 }
384
385 void unpackRGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
386 {
387     destination[0] = convertColor16LittleTo8(source[0]);
388     destination[1] = convertColor16LittleTo8(source[1]);
389     destination[2] = convertColor16LittleTo8(source[2]);
390     destination[3] = 0xFF;
391 }
392
393 void unpackRGB16BigToRGBA8(const uint16_t* source, uint8_t* destination)
394 {
395     destination[0] = convertColor16BigTo8(source[0]);
396     destination[1] = convertColor16BigTo8(source[1]);
397     destination[2] = convertColor16BigTo8(source[2]);
398     destination[3] = 0xFF;
399 }
400
401 void unpackBGR8ToRGBA8(const uint8_t* source, uint8_t* destination)
402 {
403     destination[0] = source[2];
404     destination[1] = source[1];
405     destination[2] = source[0];
406     destination[3] = 0xFF;
407 }
408
409 void unpackARGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
410 {
411     destination[0] = source[1];
412     destination[1] = source[2];
413     destination[2] = source[3];
414     destination[3] = source[0];
415 }
416
417 void unpackARGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
418 {
419     destination[0] = convertColor16LittleTo8(source[1]);
420     destination[1] = convertColor16LittleTo8(source[2]);
421     destination[2] = convertColor16LittleTo8(source[3]);
422     destination[3] = convertColor16LittleTo8(source[0]);
423 }
424
425 void unpackARGB16BigToRGBA8(const uint16_t* source, uint8_t* destination)
426 {
427     destination[0] = convertColor16BigTo8(source[1]);
428     destination[1] = convertColor16BigTo8(source[2]);
429     destination[2] = convertColor16BigTo8(source[3]);
430     destination[3] = convertColor16BigTo8(source[0]);
431 }
432
433 void unpackABGR8ToRGBA8(const uint8_t* source, uint8_t* destination)
434 {
435     destination[0] = source[3];
436     destination[1] = source[2];
437     destination[2] = source[1];
438     destination[3] = source[0];
439 }
440
441 void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
442 {
443     destination[0] = source[2];
444     destination[1] = source[1];
445     destination[2] = source[0];
446     destination[3] = source[3];
447 }
448
449 void unpackBGRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
450 {
451     destination[0] = convertColor16LittleTo8(source[2]);
452     destination[1] = convertColor16LittleTo8(source[1]);
453     destination[2] = convertColor16LittleTo8(source[0]);
454     destination[3] = convertColor16LittleTo8(source[3]);
455 }
456
457 void unpackBGRA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
458 {
459     destination[0] = convertColor16BigTo8(source[2]);
460     destination[1] = convertColor16BigTo8(source[1]);
461     destination[2] = convertColor16BigTo8(source[0]);
462     destination[3] = convertColor16BigTo8(source[3]);
463 }
464
465 void unpackRGBA5551ToRGBA8(const uint16_t* source, uint8_t* destination)
466 {
467     uint16_t packedValue = source[0];
468     uint8_t r = packedValue >> 11;
469     uint8_t g = (packedValue >> 6) & 0x1F;
470     uint8_t b = (packedValue >> 1) & 0x1F;
471     destination[0] = (r << 3) | (r & 0x7);
472     destination[1] = (g << 3) | (g & 0x7);
473     destination[2] = (b << 3) | (b & 0x7);
474     destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
475 }
476
477 void unpackRGBA4444ToRGBA8(const uint16_t* source, uint8_t* destination)
478 {
479     uint16_t packedValue = source[0];
480     uint8_t r = packedValue >> 12;
481     uint8_t g = (packedValue >> 8) & 0x0F;
482     uint8_t b = (packedValue >> 4) & 0x0F;
483     uint8_t a = packedValue & 0x0F;
484     destination[0] = r << 4 | r;
485     destination[1] = g << 4 | g;
486     destination[2] = b << 4 | b;
487     destination[3] = a << 4 | a;
488 }
489
490 void unpackRGB565ToRGBA8(const uint16_t* source, uint8_t* destination)
491 {
492     uint16_t packedValue = source[0];
493     uint8_t r = packedValue >> 11;
494     uint8_t g = (packedValue >> 5) & 0x3F;
495     uint8_t b = packedValue & 0x1F;
496     destination[0] = (r << 3) | (r & 0x7);
497     destination[1] = (g << 2) | (g & 0x3);
498     destination[2] = (b << 3) | (b & 0x7);
499     destination[3] = 0xFF;
500 }
501
502 void unpackR8ToRGBA8(const uint8_t* source, uint8_t* destination)
503 {
504     destination[0] = source[0];
505     destination[1] = source[0];
506     destination[2] = source[0];
507     destination[3] = 0xFF;
508 }
509
510 void unpackR16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
511 {
512     destination[0] = convertColor16LittleTo8(source[0]);
513     destination[1] = convertColor16LittleTo8(source[0]);
514     destination[2] = convertColor16LittleTo8(source[0]);
515     destination[3] = 0xFF;
516 }
517
518 void unpackR16BigToRGBA8(const uint16_t* source, uint8_t* destination)
519 {
520     destination[0] = convertColor16BigTo8(source[0]);
521     destination[1] = convertColor16BigTo8(source[0]);
522     destination[2] = convertColor16BigTo8(source[0]);
523     destination[3] = 0xFF;
524 }
525
526 void unpackRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
527 {
528     destination[0] = source[0];
529     destination[1] = source[0];
530     destination[2] = source[0];
531     destination[3] = source[1];
532 }
533
534 void unpackRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
535 {
536     destination[0] = convertColor16LittleTo8(source[0]);
537     destination[1] = convertColor16LittleTo8(source[0]);
538     destination[2] = convertColor16LittleTo8(source[0]);
539     destination[3] = convertColor16LittleTo8(source[1]);
540 }
541
542 void unpackRA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
543 {
544     destination[0] = convertColor16BigTo8(source[0]);
545     destination[1] = convertColor16BigTo8(source[0]);
546     destination[2] = convertColor16BigTo8(source[0]);
547     destination[3] = convertColor16BigTo8(source[1]);
548 }
549
550 void unpackAR8ToRGBA8(const uint8_t* source, uint8_t* destination)
551 {
552     destination[0] = source[1];
553     destination[1] = source[1];
554     destination[2] = source[1];
555     destination[3] = source[0];
556 }
557
558 void unpackAR16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
559 {
560     destination[0] = convertColor16LittleTo8(source[1]);
561     destination[1] = convertColor16LittleTo8(source[1]);
562     destination[2] = convertColor16LittleTo8(source[1]);
563     destination[3] = convertColor16LittleTo8(source[0]);
564 }
565
566 void unpackAR16BigToRGBA8(const uint16_t* source, uint8_t* destination)
567 {
568     destination[0] = convertColor16BigTo8(source[1]);
569     destination[1] = convertColor16BigTo8(source[1]);
570     destination[2] = convertColor16BigTo8(source[1]);
571     destination[3] = convertColor16BigTo8(source[0]);
572 }
573
574 void unpackA8ToRGBA8(const uint8_t* source, uint8_t* destination)
575 {
576     destination[0] = 0x0;
577     destination[1] = 0x0;
578     destination[2] = 0x0;
579     destination[3] = source[0];
580 }
581
582 void unpackA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
583 {
584     destination[0] = 0x0;
585     destination[1] = 0x0;
586     destination[2] = 0x0;
587     destination[3] = convertColor16LittleTo8(source[0]);
588 }
589
590 void unpackA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
591 {
592     destination[0] = 0x0;
593     destination[1] = 0x0;
594     destination[2] = 0x0;
595     destination[3] = convertColor16BigTo8(source[0]);
596 }
597
598 void unpackRGB32FToRGBA32F(const float* source, float* destination)
599 {
600     destination[0] = source[0];
601     destination[1] = source[1];
602     destination[2] = source[2];
603     destination[3] = 1;
604 }
605
606 void unpackR32FToRGBA32F(const float* source, float* destination)
607 {
608     destination[0] = source[0];
609     destination[1] = source[0];
610     destination[2] = source[0];
611     destination[3] = 1;
612 }
613
614 void unpackRA32FToRGBA32F(const float* source, float* destination)
615 {
616     destination[0] = source[0];
617     destination[1] = source[0];
618     destination[2] = source[0];
619     destination[3] = source[1];
620 }
621
622 void unpackA32FToRGBA32F(const float* source, float* destination)
623 {
624     destination[0] = 0;
625     destination[1] = 0;
626     destination[2] = 0;
627     destination[3] = source[0];
628 }
629
630 //----------------------------------------------------------------------
631 // Pixel packing routines.
632 //
633
634 void packRGBA8ToA8(const uint8_t* source, uint8_t* destination)
635 {
636     destination[0] = source[3];
637 }
638
639 void packRGBA8ToR8(const uint8_t* source, uint8_t* destination)
640 {
641     destination[0] = source[0];
642 }
643
644 void packRGBA8ToR8Premultiply(const uint8_t* source, uint8_t* destination)
645 {
646     float scaleFactor = source[3] / 255.0f;
647     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
648     destination[0] = sourceR;
649 }
650
651 // FIXME: this routine is lossy and must be removed.
652 void packRGBA8ToR8Unmultiply(const uint8_t* source, uint8_t* destination)
653 {
654     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
655     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
656     destination[0] = sourceR;
657 }
658
659 void packRGBA8ToRA8(const uint8_t* source, uint8_t* destination)
660 {
661     destination[0] = source[0];
662     destination[1] = source[3];
663 }
664
665 void packRGBA8ToRA8Premultiply(const uint8_t* source, uint8_t* destination)
666 {
667     float scaleFactor = source[3] / 255.0f;
668     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
669     destination[0] = sourceR;
670     destination[1] = source[3];
671 }
672
673 // FIXME: this routine is lossy and must be removed.
674 void packRGBA8ToRA8Unmultiply(const uint8_t* source, uint8_t* destination)
675 {
676     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
677     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
678     destination[0] = sourceR;
679     destination[1] = source[3];
680 }
681
682 void packRGBA8ToRGB8(const uint8_t* source, uint8_t* destination)
683 {
684     destination[0] = source[0];
685     destination[1] = source[1];
686     destination[2] = source[2];
687 }
688
689 void packRGBA8ToRGB8Premultiply(const uint8_t* source, uint8_t* destination)
690 {
691     float scaleFactor = source[3] / 255.0f;
692     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
693     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
694     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
695     destination[0] = sourceR;
696     destination[1] = sourceG;
697     destination[2] = sourceB;
698 }
699
700 // FIXME: this routine is lossy and must be removed.
701 void packRGBA8ToRGB8Unmultiply(const uint8_t* source, uint8_t* destination)
702 {
703     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
704     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
705     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
706     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
707     destination[0] = sourceR;
708     destination[1] = sourceG;
709     destination[2] = sourceB;
710 }
711
712 // This is only used when the source format is different than SourceFormatRGBA8.
713 void packRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination)
714 {
715     destination[0] = source[0];
716     destination[1] = source[1];
717     destination[2] = source[2];
718     destination[3] = source[3];
719 }
720
721 void packRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination)
722 {
723     float scaleFactor = source[3] / 255.0f;
724     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
725     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
726     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
727     destination[0] = sourceR;
728     destination[1] = sourceG;
729     destination[2] = sourceB;
730     destination[3] = source[3];
731 }
732
733 // FIXME: this routine is lossy and must be removed.
734 void packRGBA8ToRGBA8Unmultiply(const uint8_t* source, uint8_t* destination)
735 {
736     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
737     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
738     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
739     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
740     destination[0] = sourceR;
741     destination[1] = sourceG;
742     destination[2] = sourceB;
743     destination[3] = source[3];
744 }
745
746 void packRGBA8ToUnsignedShort4444(const uint8_t* source, uint16_t* destination)
747 {
748     *destination = (((source[0] & 0xF0) << 8)
749                     | ((source[1] & 0xF0) << 4)
750                     | (source[2] & 0xF0)
751                     | (source[3] >> 4));
752 }
753
754 void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* source, uint16_t* destination)
755 {
756     float scaleFactor = source[3] / 255.0f;
757     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
758     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
759     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
760     *destination = (((sourceR & 0xF0) << 8)
761                     | ((sourceG & 0xF0) << 4)
762                     | (sourceB & 0xF0)
763                     | (source[3] >> 4));
764 }
765
766 // FIXME: this routine is lossy and must be removed.
767 void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* source, uint16_t* destination)
768 {
769     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
770     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
771     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
772     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
773     *destination = (((sourceR & 0xF0) << 8)
774                     | ((sourceG & 0xF0) << 4)
775                     | (sourceB & 0xF0)
776                     | (source[3] >> 4));
777 }
778
779 void packRGBA8ToUnsignedShort5551(const uint8_t* source, uint16_t* destination)
780 {
781     *destination = (((source[0] & 0xF8) << 8)
782                     | ((source[1] & 0xF8) << 3)
783                     | ((source[2] & 0xF8) >> 2)
784                     | (source[3] >> 7));
785 }
786
787 void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* source, uint16_t* destination)
788 {
789     float scaleFactor = source[3] / 255.0f;
790     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
791     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
792     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
793     *destination = (((sourceR & 0xF8) << 8)
794                     | ((sourceG & 0xF8) << 3)
795                     | ((sourceB & 0xF8) >> 2)
796                     | (source[3] >> 7));
797 }
798
799 // FIXME: this routine is lossy and must be removed.
800 void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* source, uint16_t* destination)
801 {
802     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
803     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
804     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
805     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
806     *destination = (((sourceR & 0xF8) << 8)
807                     | ((sourceG & 0xF8) << 3)
808                     | ((sourceB & 0xF8) >> 2)
809                     | (source[3] >> 7));
810 }
811
812 void packRGBA8ToUnsignedShort565(const uint8_t* source, uint16_t* destination)
813 {
814     *destination = (((source[0] & 0xF8) << 8)
815                     | ((source[1] & 0xFC) << 3)
816                     | ((source[2] & 0xF8) >> 3));
817 }
818
819 void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* source, uint16_t* destination)
820 {
821     float scaleFactor = source[3] / 255.0f;
822     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
823     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
824     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
825     *destination = (((sourceR & 0xF8) << 8)
826                     | ((sourceG & 0xFC) << 3)
827                     | ((sourceB & 0xF8) >> 3));
828 }
829
830 // FIXME: this routine is lossy and must be removed.
831 void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* destination)
832 {
833     float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
834     uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
835     uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
836     uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
837     *destination = (((sourceR & 0xF8) << 8)
838                     | ((sourceG & 0xFC) << 3)
839                     | ((sourceB & 0xF8) >> 3));
840 }
841
842 void packRGBA32FToRGB32F(const float* source, float* destination)
843 {
844     destination[0] = source[0];
845     destination[1] = source[1];
846     destination[2] = source[2];
847 }
848
849 void packRGBA32FToRGB32FPremultiply(const float* source, float* destination)
850 {
851     float scaleFactor = source[3];
852     destination[0] = source[0] * scaleFactor;
853     destination[1] = source[1] * scaleFactor;
854     destination[2] = source[2] * scaleFactor;
855 }
856
857 void packRGBA32FToRGBA32FPremultiply(const float* source, float* destination)
858 {
859     float scaleFactor = source[3];
860     destination[0] = source[0] * scaleFactor;
861     destination[1] = source[1] * scaleFactor;
862     destination[2] = source[2] * scaleFactor;
863     destination[3] = source[3];
864 }
865
866 void packRGBA32FToA32F(const float* source, float* destination)
867 {
868     destination[0] = source[3];
869 }
870
871 void packRGBA32FToR32F(const float* source, float* destination)
872 {
873     destination[0] = source[0];
874 }
875
876 void packRGBA32FToR32FPremultiply(const float* source, float* destination)
877 {
878     float scaleFactor = source[3];
879     destination[0] = source[0] * scaleFactor;
880 }
881
882
883 void packRGBA32FToRA32F(const float* source, float* destination)
884 {
885     destination[0] = source[0];
886     destination[1] = source[3];
887 }
888
889 void packRGBA32FToRA32FPremultiply(const float* source, float* destination)
890 {
891     float scaleFactor = source[3];
892     destination[0] = source[0] * scaleFactor;
893     destination[1] = scaleFactor;
894 }
895
896 } // anonymous namespace
897
898 // This is used whenever unpacking is necessary; i.e., the source data
899 // is not in RGBA8/RGBA32F format, or the unpack alignment specifies
900 // that rows are not tightly packed.
901 template<typename SourceType, typename IntermediateType, typename DestType,
902          void unpackingFunc(const SourceType*, IntermediateType*),
903          void packingFunc(const IntermediateType*, DestType*)>
904 static void doUnpackingAndPacking(const SourceType* sourceData,
905                                   unsigned int width,
906                                   unsigned int height,
907                                   unsigned int sourceElementsPerPixel,
908                                   unsigned int sourceElementsPerRow,
909                                   DestType* destinationData,
910                                   unsigned int destinationElementsPerPixel)
911 {
912     if (!sourceElementsPerRow) {
913         unsigned int numElements = width * height * sourceElementsPerPixel;
914         const SourceType* endPointer = sourceData + numElements;
915         IntermediateType temporaryRGBAData[4];
916         while (sourceData < endPointer) {
917             unpackingFunc(sourceData, temporaryRGBAData);
918             packingFunc(temporaryRGBAData, destinationData);
919             sourceData += sourceElementsPerPixel;
920             destinationData += destinationElementsPerPixel;
921         }
922     } else {
923         IntermediateType temporaryRGBAData[4];
924         for (unsigned int y = 0; y < height; ++y) {
925             const SourceType* currentSource = sourceData;
926             for (unsigned int x = 0; x < width; ++x) {
927                 unpackingFunc(currentSource, temporaryRGBAData);
928                 packingFunc(temporaryRGBAData, destinationData);
929                 currentSource += sourceElementsPerPixel;
930                 destinationData += destinationElementsPerPixel;
931             }
932             sourceData += sourceElementsPerRow;
933         }
934     }
935 }
936
937 template<typename SourceType>
938 static void computeIncrementParameters(unsigned int width,
939                                        unsigned int bytesPerPixel,
940                                        unsigned int unpackAlignment,
941                                        unsigned int* sourceElementsPerPixel,
942                                        unsigned int* sourceElementsPerRow)
943 {
944     unsigned int elementSizeInBytes = sizeof(SourceType);
945     ASSERT(elementSizeInBytes <= bytesPerPixel);
946     ASSERT(!(bytesPerPixel % elementSizeInBytes));
947     unsigned int validRowBytes = width * bytesPerPixel;
948     unsigned int totalRowBytes = validRowBytes;
949     if (unpackAlignment) {
950         unsigned int remainder = validRowBytes % unpackAlignment;
951         if (remainder)
952             totalRowBytes += (unpackAlignment - remainder);
953     }
954     *sourceElementsPerPixel = bytesPerPixel / elementSizeInBytes;
955     if (validRowBytes == totalRowBytes)
956         *sourceElementsPerRow = 0;
957     else
958         *sourceElementsPerRow = totalRowBytes / elementSizeInBytes;
959 }
960
961 // This handles all conversions with a faster path for tightly packed RGBA8 source data.
962 template<typename DestType, void packingFunc(const uint8_t*, DestType*)>
963 static void doPacking(const void* sourceData,
964                       GraphicsContext3D::SourceDataFormat sourceDataFormat,
965                       unsigned int width,
966                       unsigned int height,
967                       unsigned int sourceUnpackAlignment,
968                       DestType* destinationData,
969                       unsigned int destinationElementsPerPixel)
970 {
971     switch (sourceDataFormat) {
972     case GraphicsContext3D::SourceFormatRGBA8: {
973         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
974         computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
975         if (!sourceElementsPerRow) {
976             const uint8_t* source = static_cast<const uint8_t*>(sourceData);
977             unsigned int numElements = width * height * 4;
978             const uint8_t* endPointer = source + numElements;
979             while (source < endPointer) {
980                 packingFunc(source, destinationData);
981                 source += sourceElementsPerPixel;
982                 destinationData += destinationElementsPerPixel;
983             }
984         } else {
985             doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRGBA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
986         }
987         break;
988     }
989     case GraphicsContext3D::SourceFormatRGBA16Little: {
990         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
991         computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
992         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
993         break;
994     }
995     case GraphicsContext3D::SourceFormatRGBA16Big: {
996         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
997         computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
998         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
999         break;
1000     }
1001     case GraphicsContext3D::SourceFormatRGB8: {
1002         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1003         computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1004         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1005         break;
1006     }
1007     case GraphicsContext3D::SourceFormatRGB16Little: {
1008         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1009         computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1010         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1011         break;
1012     }
1013     case GraphicsContext3D::SourceFormatRGB16Big: {
1014         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1015         computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1016         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1017         break;
1018     }
1019     case GraphicsContext3D::SourceFormatBGR8: {
1020         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1021         computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1022         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackBGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1023         break;
1024     }
1025     case GraphicsContext3D::SourceFormatARGB8: {
1026         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1027         computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1028         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackARGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1029         break;
1030     }
1031     case GraphicsContext3D::SourceFormatARGB16Little: {
1032         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1033         computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1034         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackARGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1035         break;
1036     }
1037     case GraphicsContext3D::SourceFormatARGB16Big: {
1038         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1039         computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1040         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackARGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1041         break;
1042     }
1043     case GraphicsContext3D::SourceFormatABGR8: {
1044         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1045         computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1046         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackABGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1047         break;
1048     }
1049     case GraphicsContext3D::SourceFormatBGRA8: {
1050         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1051         computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1052         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackBGRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1053         break;
1054     }
1055     case GraphicsContext3D::SourceFormatBGRA16Little: {
1056         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1057         computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1058         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackBGRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1059         break;
1060     }
1061     case GraphicsContext3D::SourceFormatBGRA16Big: {
1062         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1063         computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1064         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackBGRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1065         break;
1066     }
1067     case GraphicsContext3D::SourceFormatRGBA5551: {
1068         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1069         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1070         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA5551ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1071         break;
1072     }
1073     case GraphicsContext3D::SourceFormatRGBA4444: {
1074         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1075         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1076         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA4444ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1077         break;
1078     }
1079     case GraphicsContext3D::SourceFormatRGB565: {
1080         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1081         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1082         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGB565ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1083         break;
1084     }
1085     case GraphicsContext3D::SourceFormatR8: {
1086         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1087         computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1088         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1089         break;
1090     }
1091     case GraphicsContext3D::SourceFormatR16Little: {
1092         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1093         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1094         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1095         break;
1096     }
1097     case GraphicsContext3D::SourceFormatR16Big: {
1098         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1099         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1100         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1101         break;
1102     }
1103     case GraphicsContext3D::SourceFormatRA8: {
1104         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1105         computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1106         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1107         break;
1108     }
1109     case GraphicsContext3D::SourceFormatRA16Little: {
1110         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1111         computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1112         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1113         break;
1114     }
1115     case GraphicsContext3D::SourceFormatRA16Big: {
1116         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1117         computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1118         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1119         break;
1120     }
1121     case GraphicsContext3D::SourceFormatAR8: {
1122         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1123         computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1124         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackAR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1125         break;
1126     }
1127     case GraphicsContext3D::SourceFormatAR16Little: {
1128         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1129         computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1130         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackAR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1131         break;
1132     }
1133     case GraphicsContext3D::SourceFormatAR16Big: {
1134         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1135         computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1136         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackAR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1137         break;
1138     }
1139     case GraphicsContext3D::SourceFormatA8: {
1140         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1141         computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1142         doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1143         break;
1144     }
1145     case GraphicsContext3D::SourceFormatA16Little: {
1146         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1147         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1148         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1149         break;
1150     }
1151     case GraphicsContext3D::SourceFormatA16Big: {
1152         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1153         computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1154         doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1155         break;
1156     }
1157     default:
1158         ASSERT(false);
1159     }
1160 }
1161
1162 // This specialized routine is used only for floating-point texture uploads. It
1163 // does not need to be as general as doPacking, above; because there are
1164 // currently no native floating-point image formats in WebKit, there are only a
1165 // few upload paths.
1166 template<void packingFunc(const float*, float*)>
1167 static void doFloatingPointPacking(const void* sourceData,
1168                                    GraphicsContext3D::SourceDataFormat sourceDataFormat,
1169                                    unsigned int width,
1170                                    unsigned int height,
1171                                    unsigned int sourceUnpackAlignment,
1172                                    float* destinationData,
1173                                    unsigned int destinationElementsPerPixel)
1174 {
1175     switch (sourceDataFormat) {
1176     case GraphicsContext3D::SourceFormatRGBA8: {
1177         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1178         computeIncrementParameters<float>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1179         ASSERT(!sourceElementsPerRow); // Guaranteed because each color channel is sizeof(float) bytes.
1180         const float* source = static_cast<const float*>(sourceData);
1181         unsigned int numElements = width * height * 4;
1182         const float* endPointer = source + numElements;
1183         while (source < endPointer) {
1184             packingFunc(source, destinationData);
1185             source += sourceElementsPerPixel;
1186             destinationData += destinationElementsPerPixel;
1187         }
1188         break;
1189     }
1190     case GraphicsContext3D::SourceFormatRGB32F: {
1191         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1192         computeIncrementParameters<float>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1193         doUnpackingAndPacking<float, float, float, unpackRGB32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1194         break;
1195     }
1196     case GraphicsContext3D::SourceFormatR32F: {
1197         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1198         computeIncrementParameters<float>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1199         doUnpackingAndPacking<float, float, float, unpackR32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1200         break;
1201     }
1202     case GraphicsContext3D::SourceFormatRA32F: {
1203         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1204         computeIncrementParameters<float>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1205         doUnpackingAndPacking<float, float, float, unpackRA32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1206         break;
1207     }
1208     case GraphicsContext3D::SourceFormatA32F: {
1209         unsigned int sourceElementsPerPixel, sourceElementsPerRow;
1210         computeIncrementParameters<float>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
1211         doUnpackingAndPacking<float, float, float, unpackA32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
1212         break;
1213     }
1214     default:
1215         ASSERT_NOT_REACHED();
1216     }
1217 }
1218
1219 bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
1220                                    GraphicsContext3D::SourceDataFormat sourceDataFormat,
1221                                    unsigned int width,
1222                                    unsigned int height,
1223                                    unsigned int sourceUnpackAlignment,
1224                                    unsigned int destinationFormat,
1225                                    unsigned int destinationType,
1226                                    AlphaOp alphaOp,
1227                                    void* destinationData)
1228 {
1229     switch (destinationType) {
1230     case UNSIGNED_BYTE: {
1231         uint8_t* destination = static_cast<uint8_t*>(destinationData);
1232         if (sourceDataFormat == SourceFormatRGBA8 && destinationFormat == RGBA && sourceUnpackAlignment <= 4 && alphaOp == AlphaDoNothing) {
1233             // No conversion necessary.
1234             memcpy(destinationData, sourceData, width * height * 4);
1235             break;
1236         }
1237         switch (destinationFormat) {
1238         case RGB:
1239             switch (alphaOp) {
1240             case AlphaDoNothing:
1241                 doPacking<uint8_t, packRGBA8ToRGB8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1242                 break;
1243             case AlphaDoPremultiply:
1244                 doPacking<uint8_t, packRGBA8ToRGB8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1245                 break;
1246             case AlphaDoUnmultiply:
1247                 doPacking<uint8_t, packRGBA8ToRGB8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1248                 break;
1249             }
1250             break;
1251         case RGBA:
1252             switch (alphaOp) {
1253             case AlphaDoNothing:
1254                 ASSERT(sourceDataFormat != SourceFormatRGBA8 || sourceUnpackAlignment > 4); // Handled above with fast case.
1255                 doPacking<uint8_t, packRGBA8ToRGBA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
1256                 break;
1257             case AlphaDoPremultiply:
1258                 doPacking<uint8_t, packRGBA8ToRGBA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
1259                 break;
1260             case AlphaDoUnmultiply:
1261                 doPacking<uint8_t, packRGBA8ToRGBA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
1262                 break;
1263             default:
1264                 ASSERT_NOT_REACHED();
1265             }
1266             break;
1267         case ALPHA:
1268             // From the desktop OpenGL conversion rules (OpenGL 2.1
1269             // specification, Table 3.15), the alpha channel is chosen
1270             // from the RGBA data.
1271             doPacking<uint8_t, packRGBA8ToA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1272             break;
1273         case LUMINANCE:
1274             // From the desktop OpenGL conversion rules (OpenGL 2.1
1275             // specification, Table 3.15), the red channel is chosen
1276             // from the RGBA data.
1277             switch (alphaOp) {
1278             case AlphaDoNothing:
1279                 doPacking<uint8_t, packRGBA8ToR8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1280                 break;
1281             case AlphaDoPremultiply:
1282                 doPacking<uint8_t, packRGBA8ToR8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1283                 break;
1284             case AlphaDoUnmultiply:
1285                 doPacking<uint8_t, packRGBA8ToR8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1286                 break;
1287             }
1288             break;
1289         case LUMINANCE_ALPHA:
1290             // From the desktop OpenGL conversion rules (OpenGL 2.1
1291             // specification, Table 3.15), the red and alpha channels
1292             // are chosen from the RGBA data.
1293             switch (alphaOp) {
1294             case AlphaDoNothing:
1295                 doPacking<uint8_t, packRGBA8ToRA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1296                 break;
1297             case AlphaDoPremultiply:
1298                 doPacking<uint8_t, packRGBA8ToRA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1299                 break;
1300             case AlphaDoUnmultiply:
1301                 doPacking<uint8_t, packRGBA8ToRA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1302                 break;
1303             }
1304             break;
1305         }
1306         break;
1307     }
1308     case UNSIGNED_SHORT_4_4_4_4: {
1309         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1310         switch (alphaOp) {
1311         case AlphaDoNothing:
1312             doPacking<uint16_t, packRGBA8ToUnsignedShort4444>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1313             break;
1314         case AlphaDoPremultiply:
1315             doPacking<uint16_t, packRGBA8ToUnsignedShort4444Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1316             break;
1317         case AlphaDoUnmultiply:
1318             doPacking<uint16_t, packRGBA8ToUnsignedShort4444Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1319             break;
1320         }
1321         break;
1322     }
1323     case UNSIGNED_SHORT_5_5_5_1: {
1324         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1325         switch (alphaOp) {
1326         case AlphaDoNothing:
1327             doPacking<uint16_t, packRGBA8ToUnsignedShort5551>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1328             break;
1329         case AlphaDoPremultiply:
1330             doPacking<uint16_t, packRGBA8ToUnsignedShort5551Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1331             break;
1332         case AlphaDoUnmultiply:
1333             doPacking<uint16_t, packRGBA8ToUnsignedShort5551Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1334             break;
1335         }
1336         break;
1337     }
1338     case UNSIGNED_SHORT_5_6_5: {
1339         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1340         switch (alphaOp) {
1341         case AlphaDoNothing:
1342             doPacking<uint16_t, packRGBA8ToUnsignedShort565>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1343             break;
1344         case AlphaDoPremultiply:
1345             doPacking<uint16_t, packRGBA8ToUnsignedShort565Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1346             break;
1347         case AlphaDoUnmultiply:
1348             doPacking<uint16_t, packRGBA8ToUnsignedShort565Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1349             break;
1350         }
1351         break;
1352     }
1353     case FLOAT: {
1354         // OpenGL ES, and therefore WebGL, require that the format and
1355         // internalformat be identical, which implies that the source and
1356         // destination formats will both be floating-point in this branch -- at
1357         // least, until WebKit supports floating-point image formats natively.
1358         ASSERT(sourceDataFormat == SourceFormatRGBA32F || sourceDataFormat == SourceFormatRGB32F
1359                || sourceDataFormat == SourceFormatRA32F || sourceDataFormat == SourceFormatR32F
1360                || sourceDataFormat == SourceFormatA32F);
1361         // Because WebKit doesn't use floating-point color channels for anything
1362         // internally, there's no chance we have to do a (lossy) unmultiply
1363         // operation.
1364         ASSERT(alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply);
1365         // For the source formats with an even number of channels (RGBA32F,
1366         // RA32F) it is guaranteed that the pixel data is tightly packed because
1367         // unpack alignment <= sizeof(float) * number of channels.
1368         float* destination = static_cast<float*>(destinationData);
1369         if (alphaOp == AlphaDoNothing
1370             && ((sourceDataFormat == SourceFormatRGBA32F && destinationFormat == RGBA)
1371                 || (sourceDataFormat == SourceFormatRA32F && destinationFormat == LUMINANCE_ALPHA))) {
1372             // No conversion necessary.
1373             int numChannels = (sourceDataFormat == SourceFormatRGBA32F ? 4 : 2);
1374             memcpy(destinationData, sourceData, width * height * numChannels * sizeof(float));
1375             break;
1376         }
1377         switch (destinationFormat) {
1378         case RGB:
1379             switch (alphaOp) {
1380             case AlphaDoNothing:
1381                 doFloatingPointPacking<packRGBA32FToRGB32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1382                 break;
1383             case AlphaDoPremultiply:
1384                 doFloatingPointPacking<packRGBA32FToRGB32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1385                 break;
1386             default:
1387                 ASSERT_NOT_REACHED();
1388             }
1389             break;
1390         case RGBA:
1391             // AlphaDoNothing is handled above with fast path.
1392             ASSERT(alphaOp == AlphaDoPremultiply);
1393             doFloatingPointPacking<packRGBA32FToRGBA32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
1394             break;
1395         case ALPHA:
1396             // From the desktop OpenGL conversion rules (OpenGL 2.1
1397             // specification, Table 3.15), the alpha channel is chosen
1398             // from the RGBA data.
1399             doFloatingPointPacking<packRGBA32FToA32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1400             break;
1401         case LUMINANCE:
1402             // From the desktop OpenGL conversion rules (OpenGL 2.1
1403             // specification, Table 3.15), the red channel is chosen
1404             // from the RGBA data.
1405             switch (alphaOp) {
1406             case AlphaDoNothing:
1407                 doFloatingPointPacking<packRGBA32FToR32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1408                 break;
1409             case AlphaDoPremultiply:
1410                 doFloatingPointPacking<packRGBA32FToR32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1411                 break;
1412             default:
1413                 ASSERT_NOT_REACHED();
1414             }
1415             break;
1416         case LUMINANCE_ALPHA:
1417             // From the desktop OpenGL conversion rules (OpenGL 2.1
1418             // specification, Table 3.15), the red and alpha channels
1419             // are chosen from the RGBA data.
1420             switch (alphaOp) {
1421             case AlphaDoNothing:
1422                 doFloatingPointPacking<packRGBA32FToRA32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1423                 break;
1424             case AlphaDoPremultiply:
1425                 doFloatingPointPacking<packRGBA32FToRA32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1426                 break;
1427             default:
1428                 ASSERT_NOT_REACHED();
1429             }
1430             break;
1431         }
1432         break;
1433     }
1434     }
1435     return true;
1436 }
1437
1438 } // namespace WebCore
1439
1440 #endif // ENABLE(WEBGL)