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 
convertColor16LittleTo8(uint16_t value)47 uint8_t convertColor16LittleTo8(uint16_t value)
48 {
49     return value >> 8;
50 }
51 
convertColor16BigTo8(uint16_t value)52 uint8_t convertColor16BigTo8(uint16_t value)
53 {
54     return static_cast<uint8_t>(value & 0x00FF);
55 }
56 
57 } // anonymous namespace
58 
59 
createDrawingBuffer(const IntSize & size)60 PassRefPtr<DrawingBuffer> GraphicsContext3D::createDrawingBuffer(const IntSize& size)
61 {
62     return DrawingBuffer::create(this, size);
63 }
64 
texImage2DResourceSafe(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type,GC3Dint unpackAlignment)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 
computeFormatAndTypeParameters(GC3Denum format,GC3Denum type,unsigned int * componentsPerPixel,unsigned int * bytesPerComponent)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 
computeImageSizeInBytes(GC3Denum format,GC3Denum type,GC3Dsizei width,GC3Dsizei height,GC3Dint alignment,unsigned int * imageSizeInBytes,unsigned int * paddingInBytes)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 
extractImageData(Image * image,GC3Denum format,GC3Denum type,bool flipY,bool premultiplyAlpha,bool ignoreGammaAndColorProfile,Vector<uint8_t> & data)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 
extractImageData(ImageData * imageData,GC3Denum format,GC3Denum type,bool flipY,bool premultiplyAlpha,Vector<uint8_t> & data)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 
extractTextureData(unsigned int width,unsigned int height,GC3Denum format,GC3Denum type,unsigned int unpackAlignment,bool flipY,bool premultiplyAlpha,const void * pixels,Vector<uint8_t> & data)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 
flipVertically(void * imageData,unsigned int width,unsigned int height,unsigned int bytesPerPixel,unsigned int unpackAlignment)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 // The following packing and unpacking routines are expressed in terms
346 // of line-by-line operations, and passed by function pointer rather
347 // than template parameter, to achieve the majority of the speedups of
348 // having them inlined while reducing code size.
349 
350 namespace {
351 
352 //----------------------------------------------------------------------
353 // Pixel unpacking routines.
354 
unpackOneRowOfRGBA16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)355 void unpackOneRowOfRGBA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
356 {
357     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
358         destination[0] = convertColor16LittleTo8(source[0]);
359         destination[1] = convertColor16LittleTo8(source[1]);
360         destination[2] = convertColor16LittleTo8(source[2]);
361         destination[3] = convertColor16LittleTo8(source[3]);
362         source += 4;
363         destination += 4;
364     }
365 }
366 
unpackOneRowOfRGBA16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)367 void unpackOneRowOfRGBA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
368 {
369     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
370         destination[0] = convertColor16BigTo8(source[0]);
371         destination[1] = convertColor16BigTo8(source[1]);
372         destination[2] = convertColor16BigTo8(source[2]);
373         destination[3] = convertColor16BigTo8(source[3]);
374         source += 4;
375         destination += 4;
376     }
377 }
378 
unpackOneRowOfRGB8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)379 void unpackOneRowOfRGB8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
380 {
381     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
382         destination[0] = source[0];
383         destination[1] = source[1];
384         destination[2] = source[2];
385         destination[3] = 0xFF;
386         source += 3;
387         destination += 4;
388     }
389 }
390 
unpackOneRowOfRGB16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)391 void unpackOneRowOfRGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
392 {
393     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
394         destination[0] = convertColor16LittleTo8(source[0]);
395         destination[1] = convertColor16LittleTo8(source[1]);
396         destination[2] = convertColor16LittleTo8(source[2]);
397         destination[3] = 0xFF;
398         source += 3;
399         destination += 4;
400     }
401 }
402 
unpackOneRowOfRGB16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)403 void unpackOneRowOfRGB16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
404 {
405     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
406         destination[0] = convertColor16BigTo8(source[0]);
407         destination[1] = convertColor16BigTo8(source[1]);
408         destination[2] = convertColor16BigTo8(source[2]);
409         destination[3] = 0xFF;
410         source += 3;
411         destination += 4;
412     }
413 }
414 
unpackOneRowOfBGR8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)415 void unpackOneRowOfBGR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
416 {
417     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
418         destination[0] = source[2];
419         destination[1] = source[1];
420         destination[2] = source[0];
421         destination[3] = 0xFF;
422         source += 3;
423         destination += 4;
424     }
425 }
426 
unpackOneRowOfARGB8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)427 void unpackOneRowOfARGB8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
428 {
429     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
430         destination[0] = source[1];
431         destination[1] = source[2];
432         destination[2] = source[3];
433         destination[3] = source[0];
434         source += 4;
435         destination += 4;
436     }
437 }
438 
unpackOneRowOfARGB16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)439 void unpackOneRowOfARGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
440 {
441     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
442         destination[0] = convertColor16LittleTo8(source[1]);
443         destination[1] = convertColor16LittleTo8(source[2]);
444         destination[2] = convertColor16LittleTo8(source[3]);
445         destination[3] = convertColor16LittleTo8(source[0]);
446         source += 4;
447         destination += 4;
448     }
449 }
450 
unpackOneRowOfARGB16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)451 void unpackOneRowOfARGB16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
452 {
453     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
454         destination[0] = convertColor16BigTo8(source[1]);
455         destination[1] = convertColor16BigTo8(source[2]);
456         destination[2] = convertColor16BigTo8(source[3]);
457         destination[3] = convertColor16BigTo8(source[0]);
458         source += 4;
459         destination += 4;
460     }
461 }
462 
unpackOneRowOfABGR8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)463 void unpackOneRowOfABGR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
464 {
465     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
466         destination[0] = source[3];
467         destination[1] = source[2];
468         destination[2] = source[1];
469         destination[3] = source[0];
470         source += 4;
471         destination += 4;
472     }
473 }
474 
unpackOneRowOfBGRA8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)475 void unpackOneRowOfBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
476 {
477     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
478         destination[0] = source[2];
479         destination[1] = source[1];
480         destination[2] = source[0];
481         destination[3] = source[3];
482         source += 4;
483         destination += 4;
484     }
485 }
486 
unpackOneRowOfBGRA16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)487 void unpackOneRowOfBGRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
488 {
489     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
490         destination[0] = convertColor16LittleTo8(source[2]);
491         destination[1] = convertColor16LittleTo8(source[1]);
492         destination[2] = convertColor16LittleTo8(source[0]);
493         destination[3] = convertColor16LittleTo8(source[3]);
494         source += 4;
495         destination += 4;
496     }
497 }
498 
unpackOneRowOfBGRA16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)499 void unpackOneRowOfBGRA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
500 {
501     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
502         destination[0] = convertColor16BigTo8(source[2]);
503         destination[1] = convertColor16BigTo8(source[1]);
504         destination[2] = convertColor16BigTo8(source[0]);
505         destination[3] = convertColor16BigTo8(source[3]);
506         source += 4;
507         destination += 4;
508     }
509 }
510 
unpackOneRowOfRGBA5551ToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)511 void unpackOneRowOfRGBA5551ToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
512 {
513     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
514         uint16_t packedValue = source[0];
515         uint8_t r = packedValue >> 11;
516         uint8_t g = (packedValue >> 6) & 0x1F;
517         uint8_t b = (packedValue >> 1) & 0x1F;
518         destination[0] = (r << 3) | (r & 0x7);
519         destination[1] = (g << 3) | (g & 0x7);
520         destination[2] = (b << 3) | (b & 0x7);
521         destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
522         source += 1;
523         destination += 4;
524     }
525 }
526 
unpackOneRowOfRGBA4444ToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)527 void unpackOneRowOfRGBA4444ToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
528 {
529     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
530         uint16_t packedValue = source[0];
531         uint8_t r = packedValue >> 12;
532         uint8_t g = (packedValue >> 8) & 0x0F;
533         uint8_t b = (packedValue >> 4) & 0x0F;
534         uint8_t a = packedValue & 0x0F;
535         destination[0] = r << 4 | r;
536         destination[1] = g << 4 | g;
537         destination[2] = b << 4 | b;
538         destination[3] = a << 4 | a;
539         source += 1;
540         destination += 4;
541     }
542 }
543 
unpackOneRowOfRGB565ToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)544 void unpackOneRowOfRGB565ToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
545 {
546     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
547         uint16_t packedValue = source[0];
548         uint8_t r = packedValue >> 11;
549         uint8_t g = (packedValue >> 5) & 0x3F;
550         uint8_t b = packedValue & 0x1F;
551         destination[0] = (r << 3) | (r & 0x7);
552         destination[1] = (g << 2) | (g & 0x3);
553         destination[2] = (b << 3) | (b & 0x7);
554         destination[3] = 0xFF;
555         source += 1;
556         destination += 4;
557     }
558 }
559 
unpackOneRowOfR8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)560 void unpackOneRowOfR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
561 {
562     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
563         destination[0] = source[0];
564         destination[1] = source[0];
565         destination[2] = source[0];
566         destination[3] = 0xFF;
567         source += 1;
568         destination += 4;
569     }
570 }
571 
unpackOneRowOfR16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)572 void unpackOneRowOfR16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
573 {
574     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
575         destination[0] = convertColor16LittleTo8(source[0]);
576         destination[1] = convertColor16LittleTo8(source[0]);
577         destination[2] = convertColor16LittleTo8(source[0]);
578         destination[3] = 0xFF;
579         source += 1;
580         destination += 4;
581     }
582 }
583 
unpackOneRowOfR16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)584 void unpackOneRowOfR16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
585 {
586     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
587         destination[0] = convertColor16BigTo8(source[0]);
588         destination[1] = convertColor16BigTo8(source[0]);
589         destination[2] = convertColor16BigTo8(source[0]);
590         destination[3] = 0xFF;
591         source += 1;
592         destination += 4;
593     }
594 }
595 
unpackOneRowOfRA8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)596 void unpackOneRowOfRA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
597 {
598     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
599         destination[0] = source[0];
600         destination[1] = source[0];
601         destination[2] = source[0];
602         destination[3] = source[1];
603         source += 2;
604         destination += 4;
605     }
606 }
607 
unpackOneRowOfRA16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)608 void unpackOneRowOfRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
609 {
610     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
611         destination[0] = convertColor16LittleTo8(source[0]);
612         destination[1] = convertColor16LittleTo8(source[0]);
613         destination[2] = convertColor16LittleTo8(source[0]);
614         destination[3] = convertColor16LittleTo8(source[1]);
615         source += 2;
616         destination += 4;
617     }
618 }
619 
unpackOneRowOfRA16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)620 void unpackOneRowOfRA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
621 {
622     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
623         destination[0] = convertColor16BigTo8(source[0]);
624         destination[1] = convertColor16BigTo8(source[0]);
625         destination[2] = convertColor16BigTo8(source[0]);
626         destination[3] = convertColor16BigTo8(source[1]);
627         source += 2;
628         destination += 4;
629     }
630 }
631 
unpackOneRowOfAR8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)632 void unpackOneRowOfAR8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
633 {
634     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
635         destination[0] = source[1];
636         destination[1] = source[1];
637         destination[2] = source[1];
638         destination[3] = source[0];
639         source += 2;
640         destination += 4;
641     }
642 }
643 
unpackOneRowOfAR16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)644 void unpackOneRowOfAR16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
645 {
646     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
647         destination[0] = convertColor16LittleTo8(source[1]);
648         destination[1] = convertColor16LittleTo8(source[1]);
649         destination[2] = convertColor16LittleTo8(source[1]);
650         destination[3] = convertColor16LittleTo8(source[0]);
651         source += 2;
652         destination += 4;
653     }
654 }
655 
unpackOneRowOfAR16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)656 void unpackOneRowOfAR16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
657 {
658     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
659         destination[0] = convertColor16BigTo8(source[1]);
660         destination[1] = convertColor16BigTo8(source[1]);
661         destination[2] = convertColor16BigTo8(source[1]);
662         destination[3] = convertColor16BigTo8(source[0]);
663         source += 2;
664         destination += 4;
665     }
666 }
667 
unpackOneRowOfA8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)668 void unpackOneRowOfA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
669 {
670     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
671         destination[0] = 0x0;
672         destination[1] = 0x0;
673         destination[2] = 0x0;
674         destination[3] = source[0];
675         source += 1;
676         destination += 4;
677     }
678 }
679 
unpackOneRowOfA16LittleToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)680 void unpackOneRowOfA16LittleToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
681 {
682     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
683         destination[0] = 0x0;
684         destination[1] = 0x0;
685         destination[2] = 0x0;
686         destination[3] = convertColor16LittleTo8(source[0]);
687         source += 1;
688         destination += 4;
689     }
690 }
691 
unpackOneRowOfA16BigToRGBA8(const uint16_t * source,uint8_t * destination,unsigned int pixelsPerRow)692 void unpackOneRowOfA16BigToRGBA8(const uint16_t* source, uint8_t* destination, unsigned int pixelsPerRow)
693 {
694     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
695         destination[0] = 0x0;
696         destination[1] = 0x0;
697         destination[2] = 0x0;
698         destination[3] = convertColor16BigTo8(source[0]);
699         source += 1;
700         destination += 4;
701     }
702 }
703 
unpackOneRowOfRGB32FToRGBA32F(const float * source,float * destination,unsigned int pixelsPerRow)704 void unpackOneRowOfRGB32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
705 {
706     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
707         destination[0] = source[0];
708         destination[1] = source[1];
709         destination[2] = source[2];
710         destination[3] = 1;
711         source += 3;
712         destination += 4;
713     }
714 }
715 
unpackOneRowOfR32FToRGBA32F(const float * source,float * destination,unsigned int pixelsPerRow)716 void unpackOneRowOfR32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
717 {
718     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
719         destination[0] = source[0];
720         destination[1] = source[0];
721         destination[2] = source[0];
722         destination[3] = 1;
723         source += 1;
724         destination += 4;
725     }
726 }
727 
unpackOneRowOfRA32FToRGBA32F(const float * source,float * destination,unsigned int pixelsPerRow)728 void unpackOneRowOfRA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
729 {
730     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
731         destination[0] = source[0];
732         destination[1] = source[0];
733         destination[2] = source[0];
734         destination[3] = source[1];
735         source += 2;
736         destination += 4;
737     }
738 }
739 
unpackOneRowOfA32FToRGBA32F(const float * source,float * destination,unsigned int pixelsPerRow)740 void unpackOneRowOfA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
741 {
742     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
743         destination[0] = 0;
744         destination[1] = 0;
745         destination[2] = 0;
746         destination[3] = source[0];
747         source += 1;
748         destination += 4;
749     }
750 }
751 
752 //----------------------------------------------------------------------
753 // Pixel packing routines.
754 //
755 
packOneRowOfRGBA8ToA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)756 void packOneRowOfRGBA8ToA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
757 {
758     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
759         destination[0] = source[3];
760         source += 4;
761         destination += 1;
762     }
763 }
764 
packOneRowOfRGBA8ToR8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)765 void packOneRowOfRGBA8ToR8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
766 {
767     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
768         destination[0] = source[0];
769         source += 4;
770         destination += 1;
771     }
772 }
773 
packOneRowOfRGBA8ToR8Premultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)774 void packOneRowOfRGBA8ToR8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
775 {
776     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
777         float scaleFactor = source[3] / 255.0f;
778         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
779         destination[0] = sourceR;
780         source += 4;
781         destination += 1;
782     }
783 }
784 
785 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToR8Unmultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)786 void packOneRowOfRGBA8ToR8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
787 {
788     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
789         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
790         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
791         destination[0] = sourceR;
792         source += 4;
793         destination += 1;
794     }
795 }
796 
packOneRowOfRGBA8ToRA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)797 void packOneRowOfRGBA8ToRA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
798 {
799     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
800         destination[0] = source[0];
801         destination[1] = source[3];
802         source += 4;
803         destination += 2;
804     }
805 }
806 
packOneRowOfRGBA8ToRA8Premultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)807 void packOneRowOfRGBA8ToRA8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
808 {
809     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
810         float scaleFactor = source[3] / 255.0f;
811         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
812         destination[0] = sourceR;
813         destination[1] = source[3];
814         source += 4;
815         destination += 2;
816     }
817 }
818 
819 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToRA8Unmultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)820 void packOneRowOfRGBA8ToRA8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
821 {
822     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
823         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
824         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
825         destination[0] = sourceR;
826         destination[1] = source[3];
827         source += 4;
828         destination += 2;
829     }
830 }
831 
packOneRowOfRGBA8ToRGB8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)832 void packOneRowOfRGBA8ToRGB8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
833 {
834     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
835         destination[0] = source[0];
836         destination[1] = source[1];
837         destination[2] = source[2];
838         source += 4;
839         destination += 3;
840     }
841 }
842 
packOneRowOfRGBA8ToRGB8Premultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)843 void packOneRowOfRGBA8ToRGB8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
844 {
845     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
846         float scaleFactor = source[3] / 255.0f;
847         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
848         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
849         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
850         destination[0] = sourceR;
851         destination[1] = sourceG;
852         destination[2] = sourceB;
853         source += 4;
854         destination += 3;
855     }
856 }
857 
858 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToRGB8Unmultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)859 void packOneRowOfRGBA8ToRGB8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
860 {
861     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
862         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
863         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
864         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
865         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
866         destination[0] = sourceR;
867         destination[1] = sourceG;
868         destination[2] = sourceB;
869         source += 4;
870         destination += 3;
871     }
872 }
873 
874 // This is only used when the source format is different than SourceFormatRGBA8.
packOneRowOfRGBA8ToRGBA8(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)875 void packOneRowOfRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
876 {
877     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
878         destination[0] = source[0];
879         destination[1] = source[1];
880         destination[2] = source[2];
881         destination[3] = source[3];
882         source += 4;
883         destination += 4;
884     }
885 }
886 
packOneRowOfRGBA8ToRGBA8Premultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)887 void packOneRowOfRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
888 {
889     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
890         float scaleFactor = source[3] / 255.0f;
891         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
892         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
893         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
894         destination[0] = sourceR;
895         destination[1] = sourceG;
896         destination[2] = sourceB;
897         destination[3] = source[3];
898         source += 4;
899         destination += 4;
900     }
901 }
902 
903 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToRGBA8Unmultiply(const uint8_t * source,uint8_t * destination,unsigned int pixelsPerRow)904 void packOneRowOfRGBA8ToRGBA8Unmultiply(const uint8_t* source, uint8_t* destination, unsigned int pixelsPerRow)
905 {
906     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
907         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
908         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
909         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
910         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
911         destination[0] = sourceR;
912         destination[1] = sourceG;
913         destination[2] = sourceB;
914         destination[3] = source[3];
915         source += 4;
916         destination += 4;
917     }
918 }
919 
packOneRowOfRGBA8ToUnsignedShort4444(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)920 void packOneRowOfRGBA8ToUnsignedShort4444(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
921 {
922     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
923         *destination = (((source[0] & 0xF0) << 8)
924                         | ((source[1] & 0xF0) << 4)
925                         | (source[2] & 0xF0)
926                         | (source[3] >> 4));
927         source += 4;
928         destination += 1;
929     }
930 }
931 
packOneRowOfRGBA8ToUnsignedShort4444Premultiply(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)932 void packOneRowOfRGBA8ToUnsignedShort4444Premultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
933 {
934     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
935         float scaleFactor = source[3] / 255.0f;
936         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
937         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
938         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
939         *destination = (((sourceR & 0xF0) << 8)
940                         | ((sourceG & 0xF0) << 4)
941                         | (sourceB & 0xF0)
942                         | (source[3] >> 4));
943         source += 4;
944         destination += 1;
945     }
946 }
947 
948 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToUnsignedShort4444Unmultiply(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)949 void packOneRowOfRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
950 {
951     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
952         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
953         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
954         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
955         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
956         *destination = (((sourceR & 0xF0) << 8)
957                         | ((sourceG & 0xF0) << 4)
958                         | (sourceB & 0xF0)
959                         | (source[3] >> 4));
960         source += 4;
961         destination += 1;
962     }
963 }
964 
packOneRowOfRGBA8ToUnsignedShort5551(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)965 void packOneRowOfRGBA8ToUnsignedShort5551(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
966 {
967     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
968         *destination = (((source[0] & 0xF8) << 8)
969                         | ((source[1] & 0xF8) << 3)
970                         | ((source[2] & 0xF8) >> 2)
971                         | (source[3] >> 7));
972         source += 4;
973         destination += 1;
974     }
975 }
976 
packOneRowOfRGBA8ToUnsignedShort5551Premultiply(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)977 void packOneRowOfRGBA8ToUnsignedShort5551Premultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
978 {
979     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
980         float scaleFactor = source[3] / 255.0f;
981         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
982         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
983         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
984         *destination = (((sourceR & 0xF8) << 8)
985                         | ((sourceG & 0xF8) << 3)
986                         | ((sourceB & 0xF8) >> 2)
987                         | (source[3] >> 7));
988         source += 4;
989         destination += 1;
990     }
991 }
992 
993 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToUnsignedShort5551Unmultiply(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)994 void packOneRowOfRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
995 {
996     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
997         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
998         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
999         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1000         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1001         *destination = (((sourceR & 0xF8) << 8)
1002                         | ((sourceG & 0xF8) << 3)
1003                         | ((sourceB & 0xF8) >> 2)
1004                         | (source[3] >> 7));
1005         source += 4;
1006         destination += 1;
1007     }
1008 }
1009 
packOneRowOfRGBA8ToUnsignedShort565(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)1010 void packOneRowOfRGBA8ToUnsignedShort565(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1011 {
1012     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1013         *destination = (((source[0] & 0xF8) << 8)
1014                         | ((source[1] & 0xFC) << 3)
1015                         | ((source[2] & 0xF8) >> 3));
1016         source += 4;
1017         destination += 1;
1018     }
1019 }
1020 
packOneRowOfRGBA8ToUnsignedShort565Premultiply(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)1021 void packOneRowOfRGBA8ToUnsignedShort565Premultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1022 {
1023     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1024         float scaleFactor = source[3] / 255.0f;
1025         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
1026         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1027         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1028         *destination = (((sourceR & 0xF8) << 8)
1029                         | ((sourceG & 0xFC) << 3)
1030                         | ((sourceB & 0xF8) >> 3));
1031         source += 4;
1032         destination += 1;
1033     }
1034 }
1035 
1036 // FIXME: this routine is lossy and must be removed.
packOneRowOfRGBA8ToUnsignedShort565Unmultiply(const uint8_t * source,uint16_t * destination,unsigned int pixelsPerRow)1037 void packOneRowOfRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* destination, unsigned int pixelsPerRow)
1038 {
1039     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1040         float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f);
1041         uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
1042         uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
1043         uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
1044         *destination = (((sourceR & 0xF8) << 8)
1045                         | ((sourceG & 0xFC) << 3)
1046                         | ((sourceB & 0xF8) >> 3));
1047         source += 4;
1048         destination += 1;
1049     }
1050 }
1051 
packOneRowOfRGBA32FToRGB32F(const float * source,float * destination,unsigned int pixelsPerRow)1052 void packOneRowOfRGBA32FToRGB32F(const float* source, float* destination, unsigned int pixelsPerRow)
1053 {
1054     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1055         destination[0] = source[0];
1056         destination[1] = source[1];
1057         destination[2] = source[2];
1058         source += 4;
1059         destination += 3;
1060     }
1061 }
1062 
packOneRowOfRGBA32FToRGB32FPremultiply(const float * source,float * destination,unsigned int pixelsPerRow)1063 void packOneRowOfRGBA32FToRGB32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1064 {
1065     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1066         float scaleFactor = source[3];
1067         destination[0] = source[0] * scaleFactor;
1068         destination[1] = source[1] * scaleFactor;
1069         destination[2] = source[2] * scaleFactor;
1070         source += 4;
1071         destination += 3;
1072     }
1073 }
1074 
packOneRowOfRGBA32FToRGBA32FPremultiply(const float * source,float * destination,unsigned int pixelsPerRow)1075 void packOneRowOfRGBA32FToRGBA32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1076 {
1077     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1078         float scaleFactor = source[3];
1079         destination[0] = source[0] * scaleFactor;
1080         destination[1] = source[1] * scaleFactor;
1081         destination[2] = source[2] * scaleFactor;
1082         destination[3] = source[3];
1083         source += 4;
1084         destination += 4;
1085     }
1086 }
1087 
packOneRowOfRGBA32FToA32F(const float * source,float * destination,unsigned int pixelsPerRow)1088 void packOneRowOfRGBA32FToA32F(const float* source, float* destination, unsigned int pixelsPerRow)
1089 {
1090     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1091         destination[0] = source[3];
1092         source += 4;
1093         destination += 1;
1094     }
1095 }
1096 
packOneRowOfRGBA32FToR32F(const float * source,float * destination,unsigned int pixelsPerRow)1097 void packOneRowOfRGBA32FToR32F(const float* source, float* destination, unsigned int pixelsPerRow)
1098 {
1099     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1100         destination[0] = source[0];
1101         source += 4;
1102         destination += 1;
1103     }
1104 }
1105 
packOneRowOfRGBA32FToR32FPremultiply(const float * source,float * destination,unsigned int pixelsPerRow)1106 void packOneRowOfRGBA32FToR32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1107 {
1108     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1109         float scaleFactor = source[3];
1110         destination[0] = source[0] * scaleFactor;
1111         source += 4;
1112         destination += 1;
1113     }
1114 }
1115 
1116 
packOneRowOfRGBA32FToRA32F(const float * source,float * destination,unsigned int pixelsPerRow)1117 void packOneRowOfRGBA32FToRA32F(const float* source, float* destination, unsigned int pixelsPerRow)
1118 {
1119     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1120         destination[0] = source[0];
1121         destination[1] = source[3];
1122         source += 4;
1123         destination += 2;
1124     }
1125 }
1126 
packOneRowOfRGBA32FToRA32FPremultiply(const float * source,float * destination,unsigned int pixelsPerRow)1127 void packOneRowOfRGBA32FToRA32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
1128 {
1129     for (unsigned int i = 0; i < pixelsPerRow; ++i) {
1130         float scaleFactor = source[3];
1131         destination[0] = source[0] * scaleFactor;
1132         destination[1] = scaleFactor;
1133         source += 4;
1134         destination += 2;
1135     }
1136 }
1137 
1138 } // anonymous namespace
1139 
1140 // This is used whenever unpacking is necessary; i.e., the source data
1141 // is not in RGBA8/RGBA32F format, or the unpack alignment specifies
1142 // that rows are not tightly packed.
1143 template<typename SourceType, typename IntermediateType, typename DestType>
doUnpackingAndPacking(const SourceType * sourceData,void (* rowUnpackingFunc)(const SourceType *,IntermediateType *,unsigned int),unsigned int width,unsigned int height,unsigned int sourceElementsPerRow,DestType * destinationData,void (* rowPackingFunc)(const IntermediateType *,DestType *,unsigned int),unsigned int destinationElementsPerPixel)1144 static void doUnpackingAndPacking(const SourceType* sourceData,
1145                                   void (*rowUnpackingFunc)(const SourceType*, IntermediateType*, unsigned int),
1146                                   unsigned int width,
1147                                   unsigned int height,
1148                                   unsigned int sourceElementsPerRow,
1149                                   DestType* destinationData,
1150                                   void (*rowPackingFunc)(const IntermediateType*, DestType*, unsigned int),
1151                                   unsigned int destinationElementsPerPixel)
1152 {
1153     OwnArrayPtr<IntermediateType> temporaryRGBAData = adoptArrayPtr(new IntermediateType[width * 4]);
1154     const SourceType* endPointer = sourceData + height * sourceElementsPerRow;
1155     unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1156     while (sourceData < endPointer) {
1157         rowUnpackingFunc(sourceData, temporaryRGBAData.get(), width);
1158         rowPackingFunc(temporaryRGBAData.get(), destinationData, width);
1159         sourceData += sourceElementsPerRow;
1160         destinationData += destinationElementsPerRow;
1161     }
1162 }
1163 
1164 template<typename SourceType>
computeSourceElementsPerRow(unsigned int width,unsigned int bytesPerPixel,unsigned int unpackAlignment)1165 static unsigned int computeSourceElementsPerRow(unsigned int width,
1166                                                 unsigned int bytesPerPixel,
1167                                                 unsigned int unpackAlignment)
1168 {
1169     unsigned int elementSizeInBytes = sizeof(SourceType);
1170     ASSERT(elementSizeInBytes <= bytesPerPixel);
1171     ASSERT(!(bytesPerPixel % elementSizeInBytes));
1172     unsigned int validRowBytes = width * bytesPerPixel;
1173     unsigned int totalRowBytes = validRowBytes;
1174     if (unpackAlignment) {
1175         unsigned int remainder = validRowBytes % unpackAlignment;
1176         if (remainder)
1177             totalRowBytes += (unpackAlignment - remainder);
1178     }
1179     return totalRowBytes / elementSizeInBytes;
1180 }
1181 
1182 // This handles all conversions with a faster path for tightly packed RGBA8 source data.
1183 template<typename DestType>
doPacking(const void * sourceData,GraphicsContext3D::SourceDataFormat sourceDataFormat,unsigned int width,unsigned int height,unsigned int sourceUnpackAlignment,DestType * destinationData,void (* rowPackingFunc)(const uint8_t *,DestType *,unsigned int),unsigned int destinationElementsPerPixel)1184 static void doPacking(const void* sourceData,
1185                       GraphicsContext3D::SourceDataFormat sourceDataFormat,
1186                       unsigned int width,
1187                       unsigned int height,
1188                       unsigned int sourceUnpackAlignment,
1189                       DestType* destinationData,
1190                       void (*rowPackingFunc)(const uint8_t*, DestType*, unsigned int),
1191                       unsigned int destinationElementsPerPixel)
1192 {
1193     switch (sourceDataFormat) {
1194     case GraphicsContext3D::SourceFormatRGBA8: {
1195         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1196         const uint8_t* source = static_cast<const uint8_t*>(sourceData);
1197         const uint8_t* endPointer = source + height * sourceElementsPerRow;
1198         unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1199         while (source < endPointer) {
1200             rowPackingFunc(source, destinationData, width);
1201             source += sourceElementsPerRow;
1202             destinationData += destinationElementsPerRow;
1203         }
1204         break;
1205     }
1206     case GraphicsContext3D::SourceFormatRGBA16Little: {
1207         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1208         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1209         break;
1210     }
1211     case GraphicsContext3D::SourceFormatRGBA16Big: {
1212         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1213         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1214         break;
1215     }
1216     case GraphicsContext3D::SourceFormatRGB8: {
1217         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 3, sourceUnpackAlignment);
1218         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRGB8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1219         break;
1220     }
1221     case GraphicsContext3D::SourceFormatRGB16Little: {
1222         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 6, sourceUnpackAlignment);
1223         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGB16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1224         break;
1225     }
1226     case GraphicsContext3D::SourceFormatRGB16Big: {
1227         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 6, sourceUnpackAlignment);
1228         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGB16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1229         break;
1230     }
1231     case GraphicsContext3D::SourceFormatBGR8: {
1232         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 3, sourceUnpackAlignment);
1233         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1234         break;
1235     }
1236     case GraphicsContext3D::SourceFormatARGB8: {
1237         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1238         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfARGB8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1239         break;
1240     }
1241     case GraphicsContext3D::SourceFormatARGB16Little: {
1242         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1243         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfARGB16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1244         break;
1245     }
1246     case GraphicsContext3D::SourceFormatARGB16Big: {
1247         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1248         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfARGB16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1249         break;
1250     }
1251     case GraphicsContext3D::SourceFormatABGR8: {
1252         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1253         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfABGR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1254         break;
1255     }
1256     case GraphicsContext3D::SourceFormatBGRA8: {
1257         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
1258         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGRA8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1259         break;
1260     }
1261     case GraphicsContext3D::SourceFormatBGRA16Little: {
1262         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1263         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfBGRA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1264         break;
1265     }
1266     case GraphicsContext3D::SourceFormatBGRA16Big: {
1267         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 8, sourceUnpackAlignment);
1268         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfBGRA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1269         break;
1270     }
1271     case GraphicsContext3D::SourceFormatRGBA5551: {
1272         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1273         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA5551ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1274         break;
1275     }
1276     case GraphicsContext3D::SourceFormatRGBA4444: {
1277         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1278         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGBA4444ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1279         break;
1280     }
1281     case GraphicsContext3D::SourceFormatRGB565: {
1282         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1283         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRGB565ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1284         break;
1285     }
1286     case GraphicsContext3D::SourceFormatR8: {
1287         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 1, sourceUnpackAlignment);
1288         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1289         break;
1290     }
1291     case GraphicsContext3D::SourceFormatR16Little: {
1292         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1293         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfR16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1294         break;
1295     }
1296     case GraphicsContext3D::SourceFormatR16Big: {
1297         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1298         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfR16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1299         break;
1300     }
1301     case GraphicsContext3D::SourceFormatRA8: {
1302         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 2, sourceUnpackAlignment);
1303         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRA8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1304         break;
1305     }
1306     case GraphicsContext3D::SourceFormatRA16Little: {
1307         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1308         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1309         break;
1310     }
1311     case GraphicsContext3D::SourceFormatRA16Big: {
1312         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1313         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfRA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1314         break;
1315     }
1316     case GraphicsContext3D::SourceFormatAR8: {
1317         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 2, sourceUnpackAlignment);
1318         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfAR8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1319         break;
1320     }
1321     case GraphicsContext3D::SourceFormatAR16Little: {
1322         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1323         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfAR16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1324         break;
1325     }
1326     case GraphicsContext3D::SourceFormatAR16Big: {
1327         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 4, sourceUnpackAlignment);
1328         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfAR16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1329         break;
1330     }
1331     case GraphicsContext3D::SourceFormatA8: {
1332         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 1, sourceUnpackAlignment);
1333         doUnpackingAndPacking<uint8_t, uint8_t, DestType>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfA8ToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1334         break;
1335     }
1336     case GraphicsContext3D::SourceFormatA16Little: {
1337         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1338         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfA16LittleToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1339         break;
1340     }
1341     case GraphicsContext3D::SourceFormatA16Big: {
1342         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint16_t>(width, 2, sourceUnpackAlignment);
1343         doUnpackingAndPacking<uint16_t, uint8_t, DestType>(static_cast<const uint16_t*>(sourceData), unpackOneRowOfA16BigToRGBA8, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1344         break;
1345     }
1346     default:
1347         ASSERT(false);
1348     }
1349 }
1350 
1351 // This specialized routine is used only for floating-point texture uploads. It
1352 // does not need to be as general as doPacking, above; because there are
1353 // currently no native floating-point image formats in WebKit, there are only a
1354 // few upload paths.
doFloatingPointPacking(const void * sourceData,GraphicsContext3D::SourceDataFormat sourceDataFormat,unsigned int width,unsigned int height,unsigned int sourceUnpackAlignment,float * destinationData,void rowPackingFunc (const float *,float *,unsigned int),unsigned int destinationElementsPerPixel)1355 static void doFloatingPointPacking(const void* sourceData,
1356                                    GraphicsContext3D::SourceDataFormat sourceDataFormat,
1357                                    unsigned int width,
1358                                    unsigned int height,
1359                                    unsigned int sourceUnpackAlignment,
1360                                    float* destinationData,
1361                                    void rowPackingFunc(const float*, float*, unsigned int),
1362                                    unsigned int destinationElementsPerPixel)
1363 {
1364     switch (sourceDataFormat) {
1365     case GraphicsContext3D::SourceFormatRGBA8: {
1366         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 4, sourceUnpackAlignment);
1367         const float* source = static_cast<const float*>(sourceData);
1368         const float* endPointer = source + height * sourceElementsPerRow;
1369         unsigned int destinationElementsPerRow = width * destinationElementsPerPixel;
1370         while (source < endPointer) {
1371             rowPackingFunc(source, destinationData, width);
1372             source += sourceElementsPerRow;
1373             destinationData += destinationElementsPerRow;
1374         }
1375         break;
1376     }
1377     case GraphicsContext3D::SourceFormatRGB32F: {
1378         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 3, sourceUnpackAlignment);
1379         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfRGB32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1380         break;
1381     }
1382     case GraphicsContext3D::SourceFormatR32F: {
1383         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 1, sourceUnpackAlignment);
1384         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfR32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1385         break;
1386     }
1387     case GraphicsContext3D::SourceFormatRA32F: {
1388         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 2, sourceUnpackAlignment);
1389         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfRA32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1390         break;
1391     }
1392     case GraphicsContext3D::SourceFormatA32F: {
1393         unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 1, sourceUnpackAlignment);
1394         doUnpackingAndPacking<float, float, float>(static_cast<const float*>(sourceData), unpackOneRowOfA32FToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
1395         break;
1396     }
1397     default:
1398         ASSERT_NOT_REACHED();
1399     }
1400 }
1401 
packPixels(const uint8_t * sourceData,GraphicsContext3D::SourceDataFormat sourceDataFormat,unsigned int width,unsigned int height,unsigned int sourceUnpackAlignment,unsigned int destinationFormat,unsigned int destinationType,AlphaOp alphaOp,void * destinationData)1402 bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
1403                                    GraphicsContext3D::SourceDataFormat sourceDataFormat,
1404                                    unsigned int width,
1405                                    unsigned int height,
1406                                    unsigned int sourceUnpackAlignment,
1407                                    unsigned int destinationFormat,
1408                                    unsigned int destinationType,
1409                                    AlphaOp alphaOp,
1410                                    void* destinationData)
1411 {
1412     switch (destinationType) {
1413     case UNSIGNED_BYTE: {
1414         uint8_t* destination = static_cast<uint8_t*>(destinationData);
1415         if (sourceDataFormat == SourceFormatRGBA8 && destinationFormat == RGBA && sourceUnpackAlignment <= 4 && alphaOp == AlphaDoNothing) {
1416             // No conversion necessary.
1417             memcpy(destinationData, sourceData, width * height * 4);
1418             break;
1419         }
1420         switch (destinationFormat) {
1421         case RGB:
1422             switch (alphaOp) {
1423             case AlphaDoNothing:
1424                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGB8, 3);
1425                 break;
1426             case AlphaDoPremultiply:
1427                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGB8Premultiply, 3);
1428                 break;
1429             case AlphaDoUnmultiply:
1430                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGB8Unmultiply, 3);
1431                 break;
1432             }
1433             break;
1434         case RGBA:
1435             switch (alphaOp) {
1436             case AlphaDoNothing:
1437                 ASSERT(sourceDataFormat != SourceFormatRGBA8 || sourceUnpackAlignment > 4); // Handled above with fast case.
1438                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGBA8, 4);
1439                 break;
1440             case AlphaDoPremultiply:
1441                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGBA8Premultiply, 4);
1442                 break;
1443             case AlphaDoUnmultiply:
1444                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRGBA8Unmultiply, 4);
1445                 break;
1446             default:
1447                 ASSERT_NOT_REACHED();
1448             }
1449             break;
1450         case ALPHA:
1451             // From the desktop OpenGL conversion rules (OpenGL 2.1
1452             // specification, Table 3.15), the alpha channel is chosen
1453             // from the RGBA data.
1454             doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToA8, 1);
1455             break;
1456         case LUMINANCE:
1457             // From the desktop OpenGL conversion rules (OpenGL 2.1
1458             // specification, Table 3.15), the red channel is chosen
1459             // from the RGBA data.
1460             switch (alphaOp) {
1461             case AlphaDoNothing:
1462                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToR8, 1);
1463                 break;
1464             case AlphaDoPremultiply:
1465                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToR8Premultiply, 1);
1466                 break;
1467             case AlphaDoUnmultiply:
1468                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToR8Unmultiply, 1);
1469                 break;
1470             }
1471             break;
1472         case LUMINANCE_ALPHA:
1473             // From the desktop OpenGL conversion rules (OpenGL 2.1
1474             // specification, Table 3.15), the red and alpha channels
1475             // are chosen from the RGBA data.
1476             switch (alphaOp) {
1477             case AlphaDoNothing:
1478                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRA8, 2);
1479                 break;
1480             case AlphaDoPremultiply:
1481                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRA8Premultiply, 2);
1482                 break;
1483             case AlphaDoUnmultiply:
1484                 doPacking<uint8_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToRA8Unmultiply, 2);
1485                 break;
1486             }
1487             break;
1488         }
1489         break;
1490     }
1491     case UNSIGNED_SHORT_4_4_4_4: {
1492         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1493         switch (alphaOp) {
1494         case AlphaDoNothing:
1495             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort4444, 1);
1496             break;
1497         case AlphaDoPremultiply:
1498             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort4444Premultiply, 1);
1499             break;
1500         case AlphaDoUnmultiply:
1501             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort4444Unmultiply, 1);
1502             break;
1503         }
1504         break;
1505     }
1506     case UNSIGNED_SHORT_5_5_5_1: {
1507         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1508         switch (alphaOp) {
1509         case AlphaDoNothing:
1510             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort5551, 1);
1511             break;
1512         case AlphaDoPremultiply:
1513             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort5551Premultiply, 1);
1514             break;
1515         case AlphaDoUnmultiply:
1516             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort5551Unmultiply, 1);
1517             break;
1518         }
1519         break;
1520     }
1521     case UNSIGNED_SHORT_5_6_5: {
1522         uint16_t* destination = static_cast<uint16_t*>(destinationData);
1523         switch (alphaOp) {
1524         case AlphaDoNothing:
1525             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort565, 1);
1526             break;
1527         case AlphaDoPremultiply:
1528             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort565Premultiply, 1);
1529             break;
1530         case AlphaDoUnmultiply:
1531             doPacking<uint16_t>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA8ToUnsignedShort565Unmultiply, 1);
1532             break;
1533         }
1534         break;
1535     }
1536     case FLOAT: {
1537         // OpenGL ES, and therefore WebGL, require that the format and
1538         // internalformat be identical, which implies that the source and
1539         // destination formats will both be floating-point in this branch -- at
1540         // least, until WebKit supports floating-point image formats natively.
1541         ASSERT(sourceDataFormat == SourceFormatRGBA32F || sourceDataFormat == SourceFormatRGB32F
1542                || sourceDataFormat == SourceFormatRA32F || sourceDataFormat == SourceFormatR32F
1543                || sourceDataFormat == SourceFormatA32F);
1544         // Because WebKit doesn't use floating-point color channels for anything
1545         // internally, there's no chance we have to do a (lossy) unmultiply
1546         // operation.
1547         ASSERT(alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply);
1548         // For the source formats with an even number of channels (RGBA32F,
1549         // RA32F) it is guaranteed that the pixel data is tightly packed because
1550         // unpack alignment <= sizeof(float) * number of channels.
1551         float* destination = static_cast<float*>(destinationData);
1552         if (alphaOp == AlphaDoNothing
1553             && ((sourceDataFormat == SourceFormatRGBA32F && destinationFormat == RGBA)
1554                 || (sourceDataFormat == SourceFormatRA32F && destinationFormat == LUMINANCE_ALPHA))) {
1555             // No conversion necessary.
1556             int numChannels = (sourceDataFormat == SourceFormatRGBA32F ? 4 : 2);
1557             memcpy(destinationData, sourceData, width * height * numChannels * sizeof(float));
1558             break;
1559         }
1560         switch (destinationFormat) {
1561         case RGB:
1562             switch (alphaOp) {
1563             case AlphaDoNothing:
1564                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32F, 3);
1565                 break;
1566             case AlphaDoPremultiply:
1567                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FPremultiply, 3);
1568                 break;
1569             default:
1570                 ASSERT_NOT_REACHED();
1571             }
1572             break;
1573         case RGBA:
1574             // AlphaDoNothing is handled above with fast path.
1575             ASSERT(alphaOp == AlphaDoPremultiply);
1576             doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FPremultiply, 4);
1577             break;
1578         case ALPHA:
1579             // From the desktop OpenGL conversion rules (OpenGL 2.1
1580             // specification, Table 3.15), the alpha channel is chosen
1581             // from the RGBA data.
1582             doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToA32F, 1);
1583             break;
1584         case LUMINANCE:
1585             // From the desktop OpenGL conversion rules (OpenGL 2.1
1586             // specification, Table 3.15), the red channel is chosen
1587             // from the RGBA data.
1588             switch (alphaOp) {
1589             case AlphaDoNothing:
1590                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32F, 1);
1591                 break;
1592             case AlphaDoPremultiply:
1593                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FPremultiply, 1);
1594                 break;
1595             default:
1596                 ASSERT_NOT_REACHED();
1597             }
1598             break;
1599         case LUMINANCE_ALPHA:
1600             // From the desktop OpenGL conversion rules (OpenGL 2.1
1601             // specification, Table 3.15), the red and alpha channels
1602             // are chosen from the RGBA data.
1603             switch (alphaOp) {
1604             case AlphaDoNothing:
1605                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32F, 2);
1606                 break;
1607             case AlphaDoPremultiply:
1608                 doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FPremultiply, 2);
1609                 break;
1610             default:
1611                 ASSERT_NOT_REACHED();
1612             }
1613             break;
1614         }
1615         break;
1616     }
1617     }
1618     return true;
1619 }
1620 
1621 } // namespace WebCore
1622 
1623 #endif // ENABLE(WEBGL)
1624