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