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 // 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
unpackRGBA8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackRGBA16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGBA16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGB8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackRGB16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGB16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackBGR8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackARGB8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackARGB16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackARGB16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackABGR8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackBGRA8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackBGRA16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackBGRA16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGBA5551ToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGBA4444ToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGB565ToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackR8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackR16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackR16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRA8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackRA16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRA16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackAR8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackAR16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackAR16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackA8ToRGBA8(const uint8_t * source,uint8_t * destination)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
unpackA16LittleToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackA16BigToRGBA8(const uint16_t * source,uint8_t * destination)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
unpackRGB32FToRGBA32F(const float * source,float * destination)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
unpackR32FToRGBA32F(const float * source,float * destination)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
unpackRA32FToRGBA32F(const float * source,float * destination)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
unpackA32FToRGBA32F(const float * source,float * destination)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
packRGBA8ToA8(const uint8_t * source,uint8_t * destination)634 void packRGBA8ToA8(const uint8_t* source, uint8_t* destination)
635 {
636 destination[0] = source[3];
637 }
638
packRGBA8ToR8(const uint8_t * source,uint8_t * destination)639 void packRGBA8ToR8(const uint8_t* source, uint8_t* destination)
640 {
641 destination[0] = source[0];
642 }
643
packRGBA8ToR8Premultiply(const uint8_t * source,uint8_t * destination)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.
packRGBA8ToR8Unmultiply(const uint8_t * source,uint8_t * destination)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
packRGBA8ToRA8(const uint8_t * source,uint8_t * destination)659 void packRGBA8ToRA8(const uint8_t* source, uint8_t* destination)
660 {
661 destination[0] = source[0];
662 destination[1] = source[3];
663 }
664
packRGBA8ToRA8Premultiply(const uint8_t * source,uint8_t * destination)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.
packRGBA8ToRA8Unmultiply(const uint8_t * source,uint8_t * destination)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
packRGBA8ToRGB8(const uint8_t * source,uint8_t * destination)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
packRGBA8ToRGB8Premultiply(const uint8_t * source,uint8_t * destination)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.
packRGBA8ToRGB8Unmultiply(const uint8_t * source,uint8_t * destination)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.
packRGBA8ToRGBA8(const uint8_t * source,uint8_t * destination)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
packRGBA8ToRGBA8Premultiply(const uint8_t * source,uint8_t * destination)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.
packRGBA8ToRGBA8Unmultiply(const uint8_t * source,uint8_t * destination)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
packRGBA8ToUnsignedShort4444(const uint8_t * source,uint16_t * destination)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
packRGBA8ToUnsignedShort4444Premultiply(const uint8_t * source,uint16_t * destination)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.
packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t * source,uint16_t * destination)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
packRGBA8ToUnsignedShort5551(const uint8_t * source,uint16_t * destination)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
packRGBA8ToUnsignedShort5551Premultiply(const uint8_t * source,uint16_t * destination)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.
packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t * source,uint16_t * destination)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
packRGBA8ToUnsignedShort565(const uint8_t * source,uint16_t * destination)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
packRGBA8ToUnsignedShort565Premultiply(const uint8_t * source,uint16_t * destination)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.
packRGBA8ToUnsignedShort565Unmultiply(const uint8_t * source,uint16_t * destination)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
packRGBA32FToRGB32F(const float * source,float * destination)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
packRGBA32FToRGB32FPremultiply(const float * source,float * destination)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
packRGBA32FToRGBA32FPremultiply(const float * source,float * destination)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
packRGBA32FToA32F(const float * source,float * destination)866 void packRGBA32FToA32F(const float* source, float* destination)
867 {
868 destination[0] = source[3];
869 }
870
packRGBA32FToR32F(const float * source,float * destination)871 void packRGBA32FToR32F(const float* source, float* destination)
872 {
873 destination[0] = source[0];
874 }
875
packRGBA32FToR32FPremultiply(const float * source,float * destination)876 void packRGBA32FToR32FPremultiply(const float* source, float* destination)
877 {
878 float scaleFactor = source[3];
879 destination[0] = source[0] * scaleFactor;
880 }
881
882
packRGBA32FToRA32F(const float * source,float * destination)883 void packRGBA32FToRA32F(const float* source, float* destination)
884 {
885 destination[0] = source[0];
886 destination[1] = source[3];
887 }
888
packRGBA32FToRA32FPremultiply(const float * source,float * destination)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*)>
doUnpackingAndPacking(const SourceType * sourceData,unsigned int width,unsigned int height,unsigned int sourceElementsPerPixel,unsigned int sourceElementsPerRow,DestType * destinationData,unsigned int destinationElementsPerPixel)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>
computeIncrementParameters(unsigned int width,unsigned int bytesPerPixel,unsigned int unpackAlignment,unsigned int * sourceElementsPerPixel,unsigned int * sourceElementsPerRow)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*)>
doPacking(const void * sourceData,GraphicsContext3D::SourceDataFormat sourceDataFormat,unsigned int width,unsigned int height,unsigned int sourceUnpackAlignment,DestType * destinationData,unsigned int destinationElementsPerPixel)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*)>
doFloatingPointPacking(const void * sourceData,GraphicsContext3D::SourceDataFormat sourceDataFormat,unsigned int width,unsigned int height,unsigned int sourceUnpackAlignment,float * destinationData,unsigned int destinationElementsPerPixel)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
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)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)
1441