Changeset 117191 in webkit


Ignore:
Timestamp:
May 15, 2012 5:00:52 PM (12 years ago)
Author:
kbr@google.com
Message:

Assertion failure running Mozilla's WebGL performance regression tests
https://bugs.webkit.org/show_bug.cgi?id=85942

Reviewed by Stephen White.

Fixed incorrect assumptions about source formats and buffer sizes
when uploading to floating-point textures. Added code paths
supporting the necessary conversions.

Tests have been added to the WebGL conformance suite which cover
these new code paths; they verify uploads of HTMLCanvasElement,
HTMLImageElement, HTMLVideoElement, and ImageData to
floating-point textures. However, because floating-point texture
support is optional, and generally only supported on bots which
run with real GPUs and not in virtual machines, it isn't feasible
to incorporate these tests as layout tests.

Ran the new WebGL conformance tests in Chromium on Linux; all
pass.

  • platform/graphics/GraphicsContext3D.cpp:

(WebCore::GraphicsContext3D::extractImageData):
Properly compute size of destination buffer.

(WebCore):
Add pack/unpack routines for converting RGBA8/BGRA8 to floating point.

(WebCore::doFloatingPointPacking):
Support RGBA8 and BGRA8 source formats.

(WebCore::isFloatingPointSource):
Factored out logic for assertions.

(WebCore::GraphicsContext3D::packPixels):
Generalized assertions and logic.

  • platform/graphics/cairo/GraphicsContext3DCairo.cpp:

(WebCore::GraphicsContext3D::getImageData):
Properly compute size of destination buffer.

  • platform/graphics/cg/GraphicsContext3DCG.cpp:

(WebCore::GraphicsContext3D::getImageData):
Properly compute size of destination buffer.

  • platform/graphics/qt/GraphicsContext3DQt.cpp:

(WebCore::GraphicsContext3D::getImageData):
Properly compute size of destination buffer.

  • platform/graphics/skia/GraphicsContext3DSkia.cpp:

(WebCore::GraphicsContext3D::getImageData):
Properly compute size of destination buffer.

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r117190 r117191  
     12012-05-15  Kenneth Russell  <kbr@google.com>
     2
     3        Assertion failure running Mozilla's WebGL performance regression tests
     4        https://bugs.webkit.org/show_bug.cgi?id=85942
     5
     6        Reviewed by Stephen White.
     7
     8        Fixed incorrect assumptions about source formats and buffer sizes
     9        when uploading to floating-point textures. Added code paths
     10        supporting the necessary conversions.
     11
     12        Tests have been added to the WebGL conformance suite which cover
     13        these new code paths; they verify uploads of HTMLCanvasElement,
     14        HTMLImageElement, HTMLVideoElement, and ImageData to
     15        floating-point textures. However, because floating-point texture
     16        support is optional, and generally only supported on bots which
     17        run with real GPUs and not in virtual machines, it isn't feasible
     18        to incorporate these tests as layout tests.
     19
     20        Ran the new WebGL conformance tests in Chromium on Linux; all
     21        pass.
     22
     23        * platform/graphics/GraphicsContext3D.cpp:
     24        (WebCore::GraphicsContext3D::extractImageData):
     25        Properly compute size of destination buffer.
     26
     27        (WebCore):
     28        Add pack/unpack routines for converting RGBA8/BGRA8 to floating point.
     29
     30        (WebCore::doFloatingPointPacking):
     31        Support RGBA8 and BGRA8 source formats.
     32
     33        (WebCore::isFloatingPointSource):
     34        Factored out logic for assertions.
     35
     36        (WebCore::GraphicsContext3D::packPixels):
     37        Generalized assertions and logic.
     38
     39        * platform/graphics/cairo/GraphicsContext3DCairo.cpp:
     40        (WebCore::GraphicsContext3D::getImageData):
     41        Properly compute size of destination buffer.
     42
     43        * platform/graphics/cg/GraphicsContext3DCG.cpp:
     44        (WebCore::GraphicsContext3D::getImageData):
     45        Properly compute size of destination buffer.
     46
     47        * platform/graphics/qt/GraphicsContext3DQt.cpp:
     48        (WebCore::GraphicsContext3D::getImageData):
     49        Properly compute size of destination buffer.
     50
     51        * platform/graphics/skia/GraphicsContext3DSkia.cpp:
     52        (WebCore::GraphicsContext3D::getImageData):
     53        Properly compute size of destination buffer.
     54
    1552012-05-15  James Robinson  <jamesr@chromium.org>
    256
  • trunk/Source/WebCore/platform/graphics/GraphicsContext3D.cpp

    r116198 r117191  
    201201    int width = imageData->width();
    202202    int height = imageData->height();
    203     int dataBytes = width * height * 4;
    204     data.resize(dataBytes);
     203
     204    unsigned int packedSize;
     205    // Output data is tightly packed (alignment == 1).
     206    if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
     207        return false;
     208    data.resize(packedSize);
     209
    205210    if (!packPixels(imageData->data()->data(),
    206211                    SourceFormatRGBA8,
     
    705710}
    706711
     712void unpackOneRowOfRGBA8ToRGBA32F(const uint8_t* source, float* destination, unsigned int pixelsPerRow)
     713{
     714    const float scaleFactor = 1.0f / 255.0f;
     715    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     716        destination[0] = source[0] * scaleFactor;
     717        destination[1] = source[1] * scaleFactor;
     718        destination[2] = source[2] * scaleFactor;
     719        destination[3] = source[3] * scaleFactor;
     720        source += 4;
     721        destination += 4;
     722    }
     723}
     724
     725void unpackOneRowOfBGRA8ToRGBA32F(const uint8_t* source, float* destination, unsigned int pixelsPerRow)
     726{
     727    const float scaleFactor = 1.0f / 255.0f;
     728    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     729        destination[0] = source[2] * scaleFactor;
     730        destination[1] = source[1] * scaleFactor;
     731        destination[2] = source[0] * scaleFactor;
     732        destination[3] = source[3] * scaleFactor;
     733        source += 4;
     734        destination += 4;
     735    }
     736}
     737
    707738void unpackOneRowOfRGB32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
    708739{
     
    10631094}
    10641095
     1096void packOneRowOfRGBA32FToRGB32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
     1097{
     1098    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     1099        float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
     1100        destination[0] = source[0] * scaleFactor;
     1101        destination[1] = source[1] * scaleFactor;
     1102        destination[2] = source[2] * scaleFactor;
     1103        source += 4;
     1104        destination += 3;
     1105    }
     1106}
     1107
     1108// Used only during RGBA8 or BGRA8 -> floating-point uploads.
     1109void packOneRowOfRGBA32FToRGBA32F(const float* source, float* destination, unsigned int pixelsPerRow)
     1110{
     1111    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     1112        destination[0] = source[0];
     1113        destination[1] = source[1];
     1114        destination[2] = source[2];
     1115        destination[3] = source[3];
     1116        source += 4;
     1117        destination += 4;
     1118    }
     1119}
     1120
    10651121void packOneRowOfRGBA32FToRGBA32FPremultiply(const float* source, float* destination, unsigned int pixelsPerRow)
    10661122{
     
    10761132}
    10771133
     1134void packOneRowOfRGBA32FToRGBA32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
     1135{
     1136    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     1137        float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
     1138        destination[0] = source[0] * scaleFactor;
     1139        destination[1] = source[1] * scaleFactor;
     1140        destination[2] = source[2] * scaleFactor;
     1141        destination[3] = source[3];
     1142        source += 4;
     1143        destination += 4;
     1144    }
     1145}
     1146
    10781147void packOneRowOfRGBA32FToA32F(const float* source, float* destination, unsigned int pixelsPerRow)
    10791148{
     
    11041173}
    11051174
     1175void packOneRowOfRGBA32FToR32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
     1176{
     1177    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     1178        float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
     1179        destination[0] = source[0] * scaleFactor;
     1180        source += 4;
     1181        destination += 1;
     1182    }
     1183}
    11061184
    11071185void packOneRowOfRGBA32FToRA32F(const float* source, float* destination, unsigned int pixelsPerRow)
     
    11201198        float scaleFactor = source[3];
    11211199        destination[0] = source[0] * scaleFactor;
    1122         destination[1] = scaleFactor;
     1200        destination[1] = source[3];
     1201        source += 4;
     1202        destination += 2;
     1203    }
     1204}
     1205
     1206void packOneRowOfRGBA32FToRA32FUnmultiply(const float* source, float* destination, unsigned int pixelsPerRow)
     1207{
     1208    for (unsigned int i = 0; i < pixelsPerRow; ++i) {
     1209        float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
     1210        destination[0] = source[0] * scaleFactor;
     1211        destination[1] = source[3];
    11231212        source += 4;
    11241213        destination += 2;
     
    13681457    switch (sourceDataFormat) {
    13691458    case GraphicsContext3D::SourceFormatRGBA8: {
     1459        unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
     1460        doUnpackingAndPacking<uint8_t, float, float>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfRGBA8ToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
     1461        break;
     1462    }
     1463    case GraphicsContext3D::SourceFormatBGRA8: {
     1464        unsigned int sourceElementsPerRow = computeSourceElementsPerRow<uint8_t>(width, 4, sourceUnpackAlignment);
     1465        doUnpackingAndPacking<uint8_t, float, float>(static_cast<const uint8_t*>(sourceData), unpackOneRowOfBGRA8ToRGBA32F, width, height, sourceElementsPerRow, destinationData, rowPackingFunc, destinationElementsPerPixel);
     1466        break;
     1467    }
     1468    case GraphicsContext3D::SourceFormatRGBA32F: {
    13701469        unsigned int sourceElementsPerRow = computeSourceElementsPerRow<float>(width, 4, sourceUnpackAlignment);
    13711470        const float* source = static_cast<const float*>(sourceData);
     
    14041503}
    14051504
     1505
     1506#if !ASSERT_DISABLED
     1507static bool isFloatingPointSource(GraphicsContext3D::SourceDataFormat format)
     1508{
     1509    switch (format) {
     1510    case GraphicsContext3D::SourceFormatRGBA32F:
     1511    case GraphicsContext3D::SourceFormatRGB32F:
     1512    case GraphicsContext3D::SourceFormatRA32F:
     1513    case GraphicsContext3D::SourceFormatR32F:
     1514    case GraphicsContext3D::SourceFormatA32F:
     1515        return true;
     1516    default:
     1517        return false;
     1518    }
     1519}
     1520#endif
     1521
    14061522bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
    14071523                                   GraphicsContext3D::SourceDataFormat sourceDataFormat,
     
    15401656    case FLOAT: {
    15411657        // OpenGL ES, and therefore WebGL, require that the format and
    1542         // internalformat be identical, which implies that the source and
    1543         // destination formats will both be floating-point in this branch -- at
    1544         // least, until WebKit supports floating-point image formats natively.
    1545         ASSERT(sourceDataFormat == SourceFormatRGBA32F || sourceDataFormat == SourceFormatRGB32F
    1546                || sourceDataFormat == SourceFormatRA32F || sourceDataFormat == SourceFormatR32F
    1547                || sourceDataFormat == SourceFormatA32F);
    1548         // Because WebKit doesn't use floating-point color channels for anything
    1549         // internally, there's no chance we have to do a (lossy) unmultiply
    1550         // operation.
    1551         ASSERT(alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply);
     1658        // internalformat be identical. This means that whenever the
     1659        // developer supplies an ArrayBufferView on this code path,
     1660        // the source data will be in a floating-point format.
     1661        //
     1662        // The only time the source data will not be floating-point is
     1663        // when uploading a DOM element or ImageData as a
     1664        // floating-point texture. Only RGBA8 and BGRA8 are handled in
     1665        // this case.
     1666        ASSERT(isFloatingPointSource(sourceDataFormat)
     1667               || sourceDataFormat == SourceFormatRGBA8
     1668               || sourceDataFormat == SourceFormatBGRA8);
     1669        // When uploading a canvas into a floating-point texture,
     1670        // unmultiplication may be necessary.
     1671        ASSERT((alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply)
     1672               || !isFloatingPointSource(sourceDataFormat));
    15521673        // For the source formats with an even number of channels (RGBA32F,
    15531674        // RA32F) it is guaranteed that the pixel data is tightly packed because
     
    15711692                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FPremultiply, 3);
    15721693                break;
    1573             default:
    1574                 ASSERT_NOT_REACHED();
     1694            case AlphaDoUnmultiply:
     1695                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGB32FUnmultiply, 3);
     1696                break;
    15751697            }
    15761698            break;
    15771699        case RGBA:
    1578             // AlphaDoNothing is handled above with fast path.
    1579             ASSERT(alphaOp == AlphaDoPremultiply);
    1580             doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FPremultiply, 4);
     1700            // AlphaDoNothing for RGBA32F -> RGBA is handled above with fast path.
     1701            ASSERT(alphaOp != AlphaDoNothing || sourceDataFormat != SourceFormatRGBA32F);
     1702            switch (alphaOp) {
     1703            case AlphaDoNothing:
     1704                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32F, 4);
     1705                break;
     1706            case AlphaDoPremultiply:
     1707                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FPremultiply, 4);
     1708                break;
     1709            case AlphaDoUnmultiply:
     1710                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRGBA32FUnmultiply, 4);
     1711                break;
     1712            }
    15811713            break;
    15821714        case ALPHA:
     
    15971729                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FPremultiply, 1);
    15981730                break;
    1599             default:
    1600                 ASSERT_NOT_REACHED();
     1731            case AlphaDoUnmultiply:
     1732                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToR32FUnmultiply, 1);
     1733                break;
    16011734            }
    16021735            break;
     
    16121745                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FPremultiply, 2);
    16131746                break;
    1614             default:
    1615                 ASSERT_NOT_REACHED();
     1747            case AlphaDoUnmultiply:
     1748                doFloatingPointPacking(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, packOneRowOfRGBA32FToRA32FUnmultiply, 2);
     1749                break;
    16161750            }
    16171751            break;
  • trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp

    r115385 r117191  
    186186    }
    187187
    188     outputVector.resize(width * height * 4);
     188    unsigned int packedSize;
     189    // Output data is tightly packed (alignment == 1).
     190    if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
     191        return false;
     192    outputVector.resize(packedSize);
     193
    189194    return packPixels(cairo_image_surface_get_data(imageSurface.get()), SourceFormatBGRA8,
    190195                      width, height, srcUnpackAlignment, format, type, alphaOp, outputVector.data());
  • trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp

    r95901 r117191  
    241241        return false;
    242242    const UInt8* rgba = CFDataGetBytePtr(pixelData.get());
    243     outputVector.resize(width * height * 4);
     243
     244    unsigned int packedSize;
     245    // Output data is tightly packed (alignment == 1).
     246    if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
     247        return false;
     248    outputVector.resize(packedSize);
     249
    244250    unsigned int srcUnpackAlignment = 0;
    245251    size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
  • trunk/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp

    r113733 r117191  
    16151615    if (premultiplyAlpha)
    16161616        neededAlphaOp = AlphaDoPremultiply;
    1617     outputVector.resize(nativeImage.byteCount());
     1617
     1618    unsigned int packedSize;
     1619    // Output data is tightly packed (alignment == 1).
     1620    if (computeImageSizeInBytes(format, type, image->width(), image->height(), 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
     1621        return false;
     1622    outputVector.resize(packedSize);
     1623
    16181624    return packPixels(nativeImage.bits(), SourceFormatBGRA8, image->width(), image->height(), 0, format, type, neededAlphaOp, outputVector.data());
    16191625}
  • trunk/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp

    r95901 r117191  
    8080    SkAutoLockPixels lock(skiaImageRef);
    8181    ASSERT(skiaImageRef.rowBytes() == skiaImageRef.width() * 4);
    82     outputVector.resize(skiaImageRef.rowBytes() * skiaImageRef.height());
     82    unsigned int packedSize;
     83    // Output data is tightly packed (alignment == 1).
     84    if (computeImageSizeInBytes(format, type, skiaImageRef.width(), skiaImageRef.height(), 1, &packedSize, 0) != GraphicsContext3D::NO_ERROR)
     85        return false;
     86    outputVector.resize(packedSize);
    8387    return packPixels(reinterpret_cast<const uint8_t*>(skiaImageRef.getPixels()),
    8488                      SK_B32_SHIFT ? SourceFormatRGBA8 : SourceFormatBGRA8,
Note: See TracChangeset for help on using the changeset viewer.