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