| Index: Source/WebCore/platform/graphics/GraphicsContext3D.cpp
|
| ===================================================================
|
| --- Source/WebCore/platform/graphics/GraphicsContext3D.cpp (revision 118409)
|
| +++ Source/WebCore/platform/graphics/GraphicsContext3D.cpp (working copy)
|
| @@ -200,8 +200,13 @@
|
| return false;
|
| int width = imageData->width();
|
| int height = imageData->height();
|
| - int dataBytes = width * height * 4;
|
| - data.resize(dataBytes);
|
| +
|
| + unsigned int packedSize;
|
| + // Output data is tightly packed (alignment == 1).
|
| + if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
|
| + return false;
|
| + data.resize(packedSize);
|
| +
|
| if (!packPixels(imageData->data()->data(),
|
| SourceFormatRGBA8,
|
| width,
|
| @@ -704,6 +709,32 @@
|
| }
|
| }
|
|
|
| +void unpackOneRowOfRGBA8ToRGBA32F(const uint8_t* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + const float scaleFactor = 1.0f / 255.0f;
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + destination[0] = source[0] * scaleFactor;
|
| + destination[1] = source[1] * scaleFactor;
|
| + destination[2] = source[2] * scaleFactor;
|
| + destination[3] = source[3] * scaleFactor;
|
| + source += 4;
|
| + destination += 4;
|
| + }
|
| +}
|
| +
|
| +void unpackOneRowOfBGRA8ToRGBA32F(const uint8_t* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + const float scaleFactor = 1.0f / 255.0f;
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + destination[0] = source[2] * scaleFactor;
|
| + destination[1] = source[1] * scaleFactor;
|
| + destination[2] = source[0] * scaleFactor;
|
| + destination[3] = source[3] * scaleFactor;
|
| + source += 4;
|
| + destination += 4;
|
| + }
|
| +}
|
| +
|
| void unpackOneRowOfRGB32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
|
| {
|
| for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| @@ -1062,6 +1093,31 @@
|
| }
|
| }
|
|
|
| +void packOneRowOfRGBA32FToRGB32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
| + destination[0] = source[0] * scaleFactor;
|
| + destination[1] = source[1] * scaleFactor;
|
| + destination[2] = source[2] * scaleFactor;
|
| + source += 4;
|
| + destination += 3;
|
| + }
|
| +}
|
| +
|
| +// Used only during RGBA8 or BGRA8 -> floating-point uploads.
|
| +void packOneRowOfRGBA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + destination[0] = source[0];
|
| + destination[1] = source[1];
|
| + destination[2] = source[2];
|
| + destination[3] = source[3];
|
| + source += 4;
|
| + destination += 4;
|
| + }
|
| +}
|
| +
|
| void packOneRowOfRGBA32FToRGBA32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
|
| {
|
| for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| @@ -1075,6 +1131,19 @@
|
| }
|
| }
|
|
|
| +void packOneRowOfRGBA32FToRGBA32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
| + destination[0] = source[0] * scaleFactor;
|
| + destination[1] = source[1] * scaleFactor;
|
| + destination[2] = source[2] * scaleFactor;
|
| + destination[3] = source[3];
|
| + source += 4;
|
| + destination += 4;
|
| + }
|
| +}
|
| +
|
| void packOneRowOfRGBA32FToA32F(const float* source, float* destination, unsigned int pixelsPerRow)
|
| {
|
| for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| @@ -1103,6 +1172,15 @@
|
| }
|
| }
|
|
|
| +void packOneRowOfRGBA32FToR32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
| + destination[0] = source[0] * scaleFactor;
|
| + source += 4;
|
| + destination += 1;
|
| + }
|
| +}
|
|
|
| void packOneRowOfRGBA32FToRA32F(const float* source, float* destination, unsigned int pixelsPerRow)
|
| {
|
| @@ -1119,12 +1197,23 @@
|
| for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| float scaleFactor = source[3];
|
| destination[0] = source[0] * scaleFactor;
|
| - destination[1] = scaleFactor;
|
| + destination[1] = source[3];
|
| source += 4;
|
| destination += 2;
|
| }
|
| }
|
|
|
| +void packOneRowOfRGBA32FToRA32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
|
| +{
|
| + for (unsigned int i = 0; i < pixelsPerRow; ++i) {
|
| + float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
|
| + destination[0] = source[0] * scaleFactor;
|
| + destination[1] = source[3];
|
| + source += 4;
|
| + destination += 2;
|
| + }
|
| +}
|
| +
|
| } // anonymous namespace
|
|
|
| // This is used whenever unpacking is necessary; i.e., the source data
|
| @@ -1367,6 +1456,16 @@
|
| {
|
| switch (sourceDataFormat) {
|
| case GraphicsContext3D::SourceFormatRGBA8: {
|
| + unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
|
| + doUnpackingAndPacking<uint8_t, float, float>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRGBA8ToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
|
| + break;
|
| + }
|
| + case GraphicsContext3D::SourceFormatBGRA8: {
|
| + unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
|
| + doUnpackingAndPacking<uint8_t, float, float>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGRA8ToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
|
| + break;
|
| + }
|
| + case GraphicsContext3D::SourceFormatRGBA32F: {
|
| unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 4, sourceUnpackAlignment);
|
| const float* source = static_cast<const float*>(sourceData);
|
| const float* endPointer = source + height * sourceElementsPerRow;
|
| @@ -1403,6 +1502,23 @@
|
| }
|
| }
|
|
|
| +
|
| +#if !ASSERT_DISABLED
|
| +static bool isFloatingPointSource(GraphicsContext3D::SourceDataFormat format)
|
| +{
|
| + switch (format) {
|
| + case GraphicsContext3D::SourceFormatRGBA32F:
|
| + case GraphicsContext3D::SourceFormatRGB32F:
|
| + case GraphicsContext3D::SourceFormatRA32F:
|
| + case GraphicsContext3D::SourceFormatR32F:
|
| + case GraphicsContext3D::SourceFormatA32F:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +#endif
|
| +
|
| bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
|
| GraphicsContext3D::SourceDataFormat sourceDataFormat,
|
| unsigned int width,
|
| @@ -1539,16 +1655,21 @@
|
| }
|
| case FLOAT: {
|
| // OpenGL ES, and therefore WebGL, require that the format and
|
| - // internalformat be identical, which implies that the source and
|
| - // destination formats will both be floating-point in this branch -- at
|
| - // least, until WebKit supports floating-point image formats natively.
|
| - ASSERT(sourceDataFormat == SourceFormatRGBA32F || sourceDataFormat == SourceFormatRGB32F
|
| - || sourceDataFormat == SourceFormatRA32F || sourceDataFormat == SourceFormatR32F
|
| - || sourceDataFormat == SourceFormatA32F);
|
| - // Because WebKit doesn't use floating-point color channels for anything
|
| - // internally, there's no chance we have to do a (lossy) unmultiply
|
| - // operation.
|
| - ASSERT(alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply);
|
| + // internalformat be identical. This means that whenever the
|
| + // developer supplies an ArrayBufferView on this code path,
|
| + // the source data will be in a floating-point format.
|
| + //
|
| + // The only time the source data will not be floating-point is
|
| + // when uploading a DOM element or ImageData as a
|
| + // floating-point texture. Only RGBA8 and BGRA8 are handled in
|
| + // this case.
|
| + ASSERT(isFloatingPointSource(sourceDataFormat)
|
| + || sourceDataFormat == SourceFormatRGBA8
|
| + || sourceDataFormat == SourceFormatBGRA8);
|
| + // When uploading a canvas into a floating-point texture,
|
| + // unmultiplication may be necessary.
|
| + ASSERT((alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply)
|
| + || !isFloatingPointSource(sourceDataFormat));
|
| // For the source formats with an even number of channels (RGBA32F,
|
| // RA32F) it is guaranteed that the pixel data is tightly packed because
|
| // unpack alignment <= sizeof(float) * number of channels.
|
| @@ -1570,14 +1691,25 @@
|
| case AlphaDoPremultiply:
|
| doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FPremultiply, 3);
|
| break;
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| + case AlphaDoUnmultiply:
|
| + doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FUnmultiply, 3);
|
| + break;
|
| }
|
| break;
|
| case RGBA:
|
| - // AlphaDoNothing is handled above with fast path.
|
| - ASSERT(alphaOp == AlphaDoPremultiply);
|
| - doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FPremultiply, 4);
|
| + // AlphaDoNothing for RGBA32F -> RGBA is handled above with fast path.
|
| + ASSERT(alphaOp != AlphaDoNothing || sourceDataFormat != SourceFormatRGBA32F);
|
| + switch (alphaOp) {
|
| + case AlphaDoNothing:
|
| + doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32F, 4);
|
| + break;
|
| + case AlphaDoPremultiply:
|
| + doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FPremultiply, 4);
|
| + break;
|
| + case AlphaDoUnmultiply:
|
| + doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FUnmultiply, 4);
|
| + break;
|
| + }
|
| break;
|
| case ALPHA:
|
| // From the desktop OpenGL conversion rules (OpenGL 2.1
|
| @@ -1596,8 +1728,9 @@
|
| case AlphaDoPremultiply:
|
| doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FPremultiply, 1);
|
| break;
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| + case AlphaDoUnmultiply:
|
| + doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FUnmultiply, 1);
|
| + break;
|
| }
|
| break;
|
| case LUMINANCE_ALPHA:
|
| @@ -1611,8 +1744,9 @@
|
| case AlphaDoPremultiply:
|
| doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FPremultiply, 2);
|
| break;
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| + case AlphaDoUnmultiply:
|
| + doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FUnmultiply, 2);
|
| + break;
|
| }
|
| break;
|
| }
|
|
|