2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
31 #include "GraphicsContext3D.h"
33 #include "ArrayBufferView.h"
34 #include "CheckedInt.h"
35 #include "DrawingBuffer.h"
36 #include "Extensions3D.h"
38 #include "ImageData.h"
40 #include <wtf/OwnArrayPtr.h>
41 #include <wtf/PassOwnArrayPtr.h>
47 uint8_t convertColor16LittleTo8(uint16_t value)
52 uint8_t convertColor16BigTo8(uint16_t value)
54 return static_cast<uint8_t>(value & 0x00FF);
57 } // anonymous namespace
60 PassRefPtr<DrawingBuffer> GraphicsContext3D::createDrawingBuffer(const IntSize& size)
62 return DrawingBuffer::create(this, size);
65 bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
67 ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
68 OwnArrayPtr<unsigned char> zero;
69 if (width > 0 && height > 0) {
71 GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, 0);
72 if (error != GraphicsContext3D::NO_ERROR) {
73 synthesizeGLError(error);
76 zero = adoptArrayPtr(new unsigned char[size]);
78 synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
81 memset(zero.get(), 0, size);
83 return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get());
86 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format,
88 unsigned int* componentsPerPixel,
89 unsigned int* bytesPerComponent)
92 case GraphicsContext3D::ALPHA:
93 *componentsPerPixel = 1;
95 case GraphicsContext3D::LUMINANCE:
96 *componentsPerPixel = 1;
98 case GraphicsContext3D::LUMINANCE_ALPHA:
99 *componentsPerPixel = 2;
101 case GraphicsContext3D::RGB:
102 *componentsPerPixel = 3;
104 case GraphicsContext3D::RGBA:
105 case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
106 *componentsPerPixel = 4;
112 case GraphicsContext3D::UNSIGNED_BYTE:
113 *bytesPerComponent = sizeof(GC3Dubyte);
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);
121 case GraphicsContext3D::FLOAT: // OES_texture_float
122 *bytesPerComponent = sizeof(GC3Dfloat);
130 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment,
131 unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
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;
144 return GraphicsContext3D::NO_ERROR;
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;
154 padding = alignment - residual;
155 checkedValue += padding;
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();
164 *paddingInBytes = padding;
165 return GraphicsContext3D::NO_ERROR;
168 bool GraphicsContext3D::extractImageData(Image* image,
172 bool premultiplyAlpha,
173 bool ignoreGammaAndColorProfile,
174 Vector<uint8_t>& data)
178 if (!getImageData(image, format, type, premultiplyAlpha, ignoreGammaAndColorProfile, data))
181 unsigned int componentsPerPixel, bytesPerComponent;
182 if (!computeFormatAndTypeParameters(format, type,
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,
195 bool GraphicsContext3D::extractImageData(ImageData* imageData,
199 bool premultiplyAlpha,
200 Vector<uint8_t>& data)
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(),
215 premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing,
219 unsigned int componentsPerPixel, bytesPerComponent;
220 if (!computeFormatAndTypeParameters(format, type,
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,
233 bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int height,
234 GC3Denum format, GC3Denum type,
235 unsigned int unpackAlignment,
236 bool flipY, bool premultiplyAlpha,
238 Vector<uint8_t>& data)
240 // Assumes format, type, etc. have already been validated.
241 SourceDataFormat sourceDataFormat = SourceFormatRGBA8;
246 sourceDataFormat = SourceFormatRGBA8;
249 sourceDataFormat = SourceFormatRGB8;
252 sourceDataFormat = SourceFormatA8;
255 sourceDataFormat = SourceFormatR8;
257 case LUMINANCE_ALPHA:
258 sourceDataFormat = SourceFormatRA8;
261 ASSERT_NOT_REACHED();
264 case FLOAT: // OES_texture_float
267 sourceDataFormat = SourceFormatRGBA32F;
270 sourceDataFormat = SourceFormatRGB32F;
273 sourceDataFormat = SourceFormatA32F;
276 sourceDataFormat = SourceFormatR32F;
278 case LUMINANCE_ALPHA:
279 sourceDataFormat = SourceFormatRA32F;
282 ASSERT_NOT_REACHED();
285 case UNSIGNED_SHORT_5_5_5_1:
286 sourceDataFormat = SourceFormatRGBA5551;
288 case UNSIGNED_SHORT_4_4_4_4:
289 sourceDataFormat = SourceFormatRGBA4444;
291 case UNSIGNED_SHORT_5_6_5:
292 sourceDataFormat = SourceFormatRGB565;
295 ASSERT_NOT_REACHED();
298 // Resize the output buffer.
299 unsigned int componentsPerPixel, bytesPerComponent;
300 if (!computeFormatAndTypeParameters(format, type,
304 unsigned int bytesPerPixel = componentsPerPixel * bytesPerComponent;
305 data.resize(width * height * bytesPerPixel);
307 if (!packPixels(static_cast<const uint8_t*>(pixels),
309 width, height, unpackAlignment,
311 (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing),
314 // The pixel data is now tightly packed.
316 flipVertically(data.data(), width, height, bytesPerPixel, 1);
320 void GraphicsContext3D::flipVertically(void* imageData,
323 unsigned int bytesPerPixel,
324 unsigned int unpackAlignment)
326 if (!width || !height)
328 unsigned int validRowBytes = width * bytesPerPixel;
329 unsigned int totalRowBytes = validRowBytes;
330 unsigned int remainder = validRowBytes % unpackAlignment;
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);
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.
350 //----------------------------------------------------------------------
351 // Pixel unpacking routines.
353 void unpackRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination)
355 destination[0] = source[0];
356 destination[1] = source[1];
357 destination[2] = source[2];
358 destination[3] = source[3];
361 void unpackRGBA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
363 destination[0] = convertColor16LittleTo8(source[0]);
364 destination[1] = convertColor16LittleTo8(source[1]);
365 destination[2] = convertColor16LittleTo8(source[2]);
366 destination[3] = convertColor16LittleTo8(source[3]);
369 void unpackRGBA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
371 destination[0] = convertColor16BigTo8(source[0]);
372 destination[1] = convertColor16BigTo8(source[1]);
373 destination[2] = convertColor16BigTo8(source[2]);
374 destination[3] = convertColor16BigTo8(source[3]);
377 void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
379 destination[0] = source[0];
380 destination[1] = source[1];
381 destination[2] = source[2];
382 destination[3] = 0xFF;
385 void unpackRGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
387 destination[0] = convertColor16LittleTo8(source[0]);
388 destination[1] = convertColor16LittleTo8(source[1]);
389 destination[2] = convertColor16LittleTo8(source[2]);
390 destination[3] = 0xFF;
393 void unpackRGB16BigToRGBA8(const uint16_t* source, uint8_t* destination)
395 destination[0] = convertColor16BigTo8(source[0]);
396 destination[1] = convertColor16BigTo8(source[1]);
397 destination[2] = convertColor16BigTo8(source[2]);
398 destination[3] = 0xFF;
401 void unpackBGR8ToRGBA8(const uint8_t* source, uint8_t* destination)
403 destination[0] = source[2];
404 destination[1] = source[1];
405 destination[2] = source[0];
406 destination[3] = 0xFF;
409 void unpackARGB8ToRGBA8(const uint8_t* source, uint8_t* destination)
411 destination[0] = source[1];
412 destination[1] = source[2];
413 destination[2] = source[3];
414 destination[3] = source[0];
417 void unpackARGB16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
419 destination[0] = convertColor16LittleTo8(source[1]);
420 destination[1] = convertColor16LittleTo8(source[2]);
421 destination[2] = convertColor16LittleTo8(source[3]);
422 destination[3] = convertColor16LittleTo8(source[0]);
425 void unpackARGB16BigToRGBA8(const uint16_t* source, uint8_t* destination)
427 destination[0] = convertColor16BigTo8(source[1]);
428 destination[1] = convertColor16BigTo8(source[2]);
429 destination[2] = convertColor16BigTo8(source[3]);
430 destination[3] = convertColor16BigTo8(source[0]);
433 void unpackABGR8ToRGBA8(const uint8_t* source, uint8_t* destination)
435 destination[0] = source[3];
436 destination[1] = source[2];
437 destination[2] = source[1];
438 destination[3] = source[0];
441 void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
443 destination[0] = source[2];
444 destination[1] = source[1];
445 destination[2] = source[0];
446 destination[3] = source[3];
449 void unpackBGRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
451 destination[0] = convertColor16LittleTo8(source[2]);
452 destination[1] = convertColor16LittleTo8(source[1]);
453 destination[2] = convertColor16LittleTo8(source[0]);
454 destination[3] = convertColor16LittleTo8(source[3]);
457 void unpackBGRA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
459 destination[0] = convertColor16BigTo8(source[2]);
460 destination[1] = convertColor16BigTo8(source[1]);
461 destination[2] = convertColor16BigTo8(source[0]);
462 destination[3] = convertColor16BigTo8(source[3]);
465 void unpackRGBA5551ToRGBA8(const uint16_t* source, uint8_t* destination)
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;
477 void unpackRGBA4444ToRGBA8(const uint16_t* source, uint8_t* destination)
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;
490 void unpackRGB565ToRGBA8(const uint16_t* source, uint8_t* destination)
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;
502 void unpackR8ToRGBA8(const uint8_t* source, uint8_t* destination)
504 destination[0] = source[0];
505 destination[1] = source[0];
506 destination[2] = source[0];
507 destination[3] = 0xFF;
510 void unpackR16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
512 destination[0] = convertColor16LittleTo8(source[0]);
513 destination[1] = convertColor16LittleTo8(source[0]);
514 destination[2] = convertColor16LittleTo8(source[0]);
515 destination[3] = 0xFF;
518 void unpackR16BigToRGBA8(const uint16_t* source, uint8_t* destination)
520 destination[0] = convertColor16BigTo8(source[0]);
521 destination[1] = convertColor16BigTo8(source[0]);
522 destination[2] = convertColor16BigTo8(source[0]);
523 destination[3] = 0xFF;
526 void unpackRA8ToRGBA8(const uint8_t* source, uint8_t* destination)
528 destination[0] = source[0];
529 destination[1] = source[0];
530 destination[2] = source[0];
531 destination[3] = source[1];
534 void unpackRA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
536 destination[0] = convertColor16LittleTo8(source[0]);
537 destination[1] = convertColor16LittleTo8(source[0]);
538 destination[2] = convertColor16LittleTo8(source[0]);
539 destination[3] = convertColor16LittleTo8(source[1]);
542 void unpackRA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
544 destination[0] = convertColor16BigTo8(source[0]);
545 destination[1] = convertColor16BigTo8(source[0]);
546 destination[2] = convertColor16BigTo8(source[0]);
547 destination[3] = convertColor16BigTo8(source[1]);
550 void unpackAR8ToRGBA8(const uint8_t* source, uint8_t* destination)
552 destination[0] = source[1];
553 destination[1] = source[1];
554 destination[2] = source[1];
555 destination[3] = source[0];
558 void unpackAR16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
560 destination[0] = convertColor16LittleTo8(source[1]);
561 destination[1] = convertColor16LittleTo8(source[1]);
562 destination[2] = convertColor16LittleTo8(source[1]);
563 destination[3] = convertColor16LittleTo8(source[0]);
566 void unpackAR16BigToRGBA8(const uint16_t* source, uint8_t* destination)
568 destination[0] = convertColor16BigTo8(source[1]);
569 destination[1] = convertColor16BigTo8(source[1]);
570 destination[2] = convertColor16BigTo8(source[1]);
571 destination[3] = convertColor16BigTo8(source[0]);
574 void unpackA8ToRGBA8(const uint8_t* source, uint8_t* destination)
576 destination[0] = 0x0;
577 destination[1] = 0x0;
578 destination[2] = 0x0;
579 destination[3] = source[0];
582 void unpackA16LittleToRGBA8(const uint16_t* source, uint8_t* destination)
584 destination[0] = 0x0;
585 destination[1] = 0x0;
586 destination[2] = 0x0;
587 destination[3] = convertColor16LittleTo8(source[0]);
590 void unpackA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
592 destination[0] = 0x0;
593 destination[1] = 0x0;
594 destination[2] = 0x0;
595 destination[3] = convertColor16BigTo8(source[0]);
598 void unpackRGB32FToRGBA32F(const float* source, float* destination)
600 destination[0] = source[0];
601 destination[1] = source[1];
602 destination[2] = source[2];
606 void unpackR32FToRGBA32F(const float* source, float* destination)
608 destination[0] = source[0];
609 destination[1] = source[0];
610 destination[2] = source[0];
614 void unpackRA32FToRGBA32F(const float* source, float* destination)
616 destination[0] = source[0];
617 destination[1] = source[0];
618 destination[2] = source[0];
619 destination[3] = source[1];
622 void unpackA32FToRGBA32F(const float* source, float* destination)
627 destination[3] = source[0];
630 //----------------------------------------------------------------------
631 // Pixel packing routines.
634 void packRGBA8ToA8(const uint8_t* source, uint8_t* destination)
636 destination[0] = source[3];
639 void packRGBA8ToR8(const uint8_t* source, uint8_t* destination)
641 destination[0] = source[0];
644 void packRGBA8ToR8Premultiply(const uint8_t* source, uint8_t* destination)
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;
651 // FIXME: this routine is lossy and must be removed.
652 void packRGBA8ToR8Unmultiply(const uint8_t* source, uint8_t* destination)
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;
659 void packRGBA8ToRA8(const uint8_t* source, uint8_t* destination)
661 destination[0] = source[0];
662 destination[1] = source[3];
665 void packRGBA8ToRA8Premultiply(const uint8_t* source, uint8_t* destination)
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];
673 // FIXME: this routine is lossy and must be removed.
674 void packRGBA8ToRA8Unmultiply(const uint8_t* source, uint8_t* destination)
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];
682 void packRGBA8ToRGB8(const uint8_t* source, uint8_t* destination)
684 destination[0] = source[0];
685 destination[1] = source[1];
686 destination[2] = source[2];
689 void packRGBA8ToRGB8Premultiply(const uint8_t* source, uint8_t* destination)
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;
700 // FIXME: this routine is lossy and must be removed.
701 void packRGBA8ToRGB8Unmultiply(const uint8_t* source, uint8_t* destination)
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;
712 // This is only used when the source format is different than SourceFormatRGBA8.
713 void packRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination)
715 destination[0] = source[0];
716 destination[1] = source[1];
717 destination[2] = source[2];
718 destination[3] = source[3];
721 void packRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination)
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];
733 // FIXME: this routine is lossy and must be removed.
734 void packRGBA8ToRGBA8Unmultiply(const uint8_t* source, uint8_t* destination)
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];
746 void packRGBA8ToUnsignedShort4444(const uint8_t* source, uint16_t* destination)
748 *destination = (((source[0] & 0xF0) << 8)
749 | ((source[1] & 0xF0) << 4)
754 void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* source, uint16_t* destination)
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)
766 // FIXME: this routine is lossy and must be removed.
767 void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* source, uint16_t* destination)
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)
779 void packRGBA8ToUnsignedShort5551(const uint8_t* source, uint16_t* destination)
781 *destination = (((source[0] & 0xF8) << 8)
782 | ((source[1] & 0xF8) << 3)
783 | ((source[2] & 0xF8) >> 2)
787 void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* source, uint16_t* destination)
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)
799 // FIXME: this routine is lossy and must be removed.
800 void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* source, uint16_t* destination)
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)
812 void packRGBA8ToUnsignedShort565(const uint8_t* source, uint16_t* destination)
814 *destination = (((source[0] & 0xF8) << 8)
815 | ((source[1] & 0xFC) << 3)
816 | ((source[2] & 0xF8) >> 3));
819 void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* source, uint16_t* destination)
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));
830 // FIXME: this routine is lossy and must be removed.
831 void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* destination)
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));
842 void packRGBA32FToRGB32F(const float* source, float* destination)
844 destination[0] = source[0];
845 destination[1] = source[1];
846 destination[2] = source[2];
849 void packRGBA32FToRGB32FPremultiply(const float* source, float* destination)
851 float scaleFactor = source[3];
852 destination[0] = source[0] * scaleFactor;
853 destination[1] = source[1] * scaleFactor;
854 destination[2] = source[2] * scaleFactor;
857 void packRGBA32FToRGBA32FPremultiply(const float* source, float* destination)
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];
866 void packRGBA32FToA32F(const float* source, float* destination)
868 destination[0] = source[3];
871 void packRGBA32FToR32F(const float* source, float* destination)
873 destination[0] = source[0];
876 void packRGBA32FToR32FPremultiply(const float* source, float* destination)
878 float scaleFactor = source[3];
879 destination[0] = source[0] * scaleFactor;
883 void packRGBA32FToRA32F(const float* source, float* destination)
885 destination[0] = source[0];
886 destination[1] = source[3];
889 void packRGBA32FToRA32FPremultiply(const float* source, float* destination)
891 float scaleFactor = source[3];
892 destination[0] = source[0] * scaleFactor;
893 destination[1] = scaleFactor;
896 } // anonymous namespace
898 // This is used whenever unpacking is necessary; i.e., the source data
899 // is not in RGBA8/RGBA32F format, or the unpack alignment specifies
900 // that rows are not tightly packed.
901 template<typename SourceType, typename IntermediateType, typename DestType,
902 void unpackingFunc(const SourceType*, IntermediateType*),
903 void packingFunc(const IntermediateType*, DestType*)>
904 static void doUnpackingAndPacking(const SourceType* sourceData,
907 unsigned int sourceElementsPerPixel,
908 unsigned int sourceElementsPerRow,
909 DestType* destinationData,
910 unsigned int destinationElementsPerPixel)
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;
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;
932 sourceData += sourceElementsPerRow;
937 template<typename SourceType>
938 static void computeIncrementParameters(unsigned int width,
939 unsigned int bytesPerPixel,
940 unsigned int unpackAlignment,
941 unsigned int* sourceElementsPerPixel,
942 unsigned int* sourceElementsPerRow)
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;
952 totalRowBytes += (unpackAlignment - remainder);
954 *sourceElementsPerPixel = bytesPerPixel / elementSizeInBytes;
955 if (validRowBytes == totalRowBytes)
956 *sourceElementsPerRow = 0;
958 *sourceElementsPerRow = totalRowBytes / elementSizeInBytes;
961 // This handles all conversions with a faster path for tightly packed RGBA8 source data.
962 template<typename DestType, void packingFunc(const uint8_t*, DestType*)>
963 static void doPacking(const void* sourceData,
964 GraphicsContext3D::SourceDataFormat sourceDataFormat,
967 unsigned int sourceUnpackAlignment,
968 DestType* destinationData,
969 unsigned int destinationElementsPerPixel)
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;
985 doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRGBA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1162 // This specialized routine is used only for floating-point texture uploads. It
1163 // does not need to be as general as doPacking, above; because there are
1164 // currently no native floating-point image formats in WebKit, there are only a
1165 // few upload paths.
1166 template<void packingFunc(const float*, float*)>
1167 static void doFloatingPointPacking(const void* sourceData,
1168 GraphicsContext3D::SourceDataFormat sourceDataFormat,
1170 unsigned int height,
1171 unsigned int sourceUnpackAlignment,
1172 float* destinationData,
1173 unsigned int destinationElementsPerPixel)
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;
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);
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);
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);
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);
1215 ASSERT_NOT_REACHED();
1219 bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
1220 GraphicsContext3D::SourceDataFormat sourceDataFormat,
1222 unsigned int height,
1223 unsigned int sourceUnpackAlignment,
1224 unsigned int destinationFormat,
1225 unsigned int destinationType,
1227 void* destinationData)
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);
1237 switch (destinationFormat) {
1240 case AlphaDoNothing:
1241 doPacking<uint8_t, packRGBA8ToRGB8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1243 case AlphaDoPremultiply:
1244 doPacking<uint8_t, packRGBA8ToRGB8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1246 case AlphaDoUnmultiply:
1247 doPacking<uint8_t, packRGBA8ToRGB8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
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);
1257 case AlphaDoPremultiply:
1258 doPacking<uint8_t, packRGBA8ToRGBA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
1260 case AlphaDoUnmultiply:
1261 doPacking<uint8_t, packRGBA8ToRGBA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
1264 ASSERT_NOT_REACHED();
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);
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.
1278 case AlphaDoNothing:
1279 doPacking<uint8_t, packRGBA8ToR8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1281 case AlphaDoPremultiply:
1282 doPacking<uint8_t, packRGBA8ToR8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1284 case AlphaDoUnmultiply:
1285 doPacking<uint8_t, packRGBA8ToR8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
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.
1294 case AlphaDoNothing:
1295 doPacking<uint8_t, packRGBA8ToRA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1297 case AlphaDoPremultiply:
1298 doPacking<uint8_t, packRGBA8ToRA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1300 case AlphaDoUnmultiply:
1301 doPacking<uint8_t, packRGBA8ToRA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1308 case UNSIGNED_SHORT_4_4_4_4: {
1309 uint16_t* destination = static_cast<uint16_t*>(destinationData);
1311 case AlphaDoNothing:
1312 doPacking<uint16_t, packRGBA8ToUnsignedShort4444>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1314 case AlphaDoPremultiply:
1315 doPacking<uint16_t, packRGBA8ToUnsignedShort4444Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1317 case AlphaDoUnmultiply:
1318 doPacking<uint16_t, packRGBA8ToUnsignedShort4444Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1323 case UNSIGNED_SHORT_5_5_5_1: {
1324 uint16_t* destination = static_cast<uint16_t*>(destinationData);
1326 case AlphaDoNothing:
1327 doPacking<uint16_t, packRGBA8ToUnsignedShort5551>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1329 case AlphaDoPremultiply:
1330 doPacking<uint16_t, packRGBA8ToUnsignedShort5551Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1332 case AlphaDoUnmultiply:
1333 doPacking<uint16_t, packRGBA8ToUnsignedShort5551Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1338 case UNSIGNED_SHORT_5_6_5: {
1339 uint16_t* destination = static_cast<uint16_t*>(destinationData);
1341 case AlphaDoNothing:
1342 doPacking<uint16_t, packRGBA8ToUnsignedShort565>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1344 case AlphaDoPremultiply:
1345 doPacking<uint16_t, packRGBA8ToUnsignedShort565Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1347 case AlphaDoUnmultiply:
1348 doPacking<uint16_t, packRGBA8ToUnsignedShort565Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
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
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));
1377 switch (destinationFormat) {
1380 case AlphaDoNothing:
1381 doFloatingPointPacking<packRGBA32FToRGB32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1383 case AlphaDoPremultiply:
1384 doFloatingPointPacking<packRGBA32FToRGB32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
1387 ASSERT_NOT_REACHED();
1391 // AlphaDoNothing is handled above with fast path.
1392 ASSERT(alphaOp == AlphaDoPremultiply);
1393 doFloatingPointPacking<packRGBA32FToRGBA32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
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);
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.
1406 case AlphaDoNothing:
1407 doFloatingPointPacking<packRGBA32FToR32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1409 case AlphaDoPremultiply:
1410 doFloatingPointPacking<packRGBA32FToR32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
1413 ASSERT_NOT_REACHED();
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.
1421 case AlphaDoNothing:
1422 doFloatingPointPacking<packRGBA32FToRA32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1424 case AlphaDoPremultiply:
1425 doFloatingPointPacking<packRGBA32FToRA32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
1428 ASSERT_NOT_REACHED();
1438 } // namespace WebCore
1440 #endif // ENABLE(WEBGL)