⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286160 in webkit


Ignore:
Timestamp:
Nov 25, 2021, 1:17:45 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

ANGLE Metal: The memory backing IOSurfaces of former client buffer pbuffers is leaked
https://bugs.webkit.org/show_bug.cgi?id=233328
<rdar://problem/85563187>

Patch by Kimmo Kinnunen <kkinnunen@apple.com> on 2021-11-25
Reviewed by Antti Koivisto.

Source/WebCore:

Fix a bug where recycling GraphicsContextGLOpenGL display buffers would
leak the spare buffer pbuffer handle. This would happen if the
display buffer was marked as "in use", so that the IOSurface reference
would be dropped immediately in order to not use it as next drawing buffer.
However, the IOSurface is still bound in ANGLE and as such, the pbuffer handle
must be returned during GraphicsContextGLIOSurfaceSwapChain::recycleBuffer`
call.

Adds API tests for testing the leak.

  • platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp:

(WebCore::GraphicsContextGLIOSurfaceSwapChain::recycleBuffer):
(WebCore::GraphicsContextGLIOSurfaceSwapChain::present):

Source/WebCore/PAL:

Add prototype for IOSurfaceIncrementUseCount.
Currently used for a test, in simulating CA behavior.

  • pal/spi/cocoa/IOSurfaceSPI.h:

Tools:

Add tests testing Cocoa GraphicsContextGLOpenGL drawing buffer
recycling behavior.

  • TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
  • TestWebKitAPI/Sources.txt:
  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebCore/ImageBufferTests.cpp:

(TestWebKitAPI::imageBufferPixelIs):
(TestWebKitAPI::memoryFootprintChangedBy): Deleted.

  • TestWebKitAPI/Tests/WebCore/cocoa/TestGraphicsContextGLOpenGLCocoa.mm:

(TestWebKitAPI::createDefaultTestContext):
(TestWebKitAPI::changeContextContents):
(TestWebKitAPI::TEST):

  • TestWebKitAPI/TestUtilities.h: Added.
  • TestWebKitAPI/TestUtilities.cpp: Added.

Add few useful functions to TestUtilities.h so that different
tests can use them.

Location:
trunk
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286156 r286160  
     12021-11-25  Kimmo Kinnunen  <kkinnunen@apple.com>
     2
     3        ANGLE Metal: The memory backing IOSurfaces of former client buffer pbuffers is leaked
     4        https://bugs.webkit.org/show_bug.cgi?id=233328
     5        <rdar://problem/85563187>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Fix a bug where recycling GraphicsContextGLOpenGL display buffers would
     10        leak the spare buffer pbuffer handle. This would happen if the
     11        display buffer was marked as "in use", so that the IOSurface reference
     12        would be dropped immediately in order to not use it as next drawing buffer.
     13        However, the IOSurface is still bound in ANGLE and as such, the pbuffer handle
     14        must be returned during `GraphicsContextGLIOSurfaceSwapChain::recycleBuffer``
     15        call.
     16
     17        Adds API tests for testing the leak.
     18
     19        * platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp:
     20        (WebCore::GraphicsContextGLIOSurfaceSwapChain::recycleBuffer):
     21        (WebCore::GraphicsContextGLIOSurfaceSwapChain::present):
     22
    1232021-11-24  David Kilzer  <ddkilzer@apple.com>
    224
  • trunk/Source/WebCore/PAL/ChangeLog

    r286124 r286160  
     12021-11-25  Kimmo Kinnunen  <kkinnunen@apple.com>
     2
     3        ANGLE Metal: The memory backing IOSurfaces of former client buffer pbuffers is leaked
     4        https://bugs.webkit.org/show_bug.cgi?id=233328
     5        <rdar://problem/85563187>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Add prototype for IOSurfaceIncrementUseCount.
     10        Currently used for a test, in simulating CA behavior.
     11
     12        * pal/spi/cocoa/IOSurfaceSPI.h:
     13
    1142021-11-22  Myles C. Maxfield  <mmaxfield@apple.com>
    215
  • trunk/Source/WebCore/PAL/pal/spi/cocoa/IOSurfaceSPI.h

    r283483 r286160  
    7272size_t IOSurfaceGetWidth(IOSurfaceRef buffer);
    7373OSType IOSurfaceGetPixelFormat(IOSurfaceRef buffer);
     74void IOSurfaceIncrementUseCount(IOSurfaceRef buffer);
    7475Boolean IOSurfaceIsInUse(IOSurfaceRef buffer);
    7576IOReturn IOSurfaceLock(IOSurfaceRef buffer, uint32_t options, uint32_t *seed);
  • trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp

    r283238 r286160  
    4848        if (m_spareBuffer.surface->isInUse())
    4949            m_spareBuffer.surface.reset();
    50         return WTFMove(m_spareBuffer);
    5150    }
    52     return { };
     51    return std::exchange(m_spareBuffer, { });
    5352}
    5453
     
    6160void GraphicsContextGLIOSurfaceSwapChain::present(Buffer&& buffer)
    6261{
     62    ASSERT(!m_spareBuffer.surface);
     63    ASSERT(!m_spareBuffer.handle);
    6364    m_spareBuffer = std::exchange(m_displayBuffer, WTFMove(buffer));
    6465    if (m_displayBufferInUse) {
  • trunk/Tools/ChangeLog

    r286141 r286160  
     12021-11-25  Kimmo Kinnunen  <kkinnunen@apple.com>
     2
     3        ANGLE Metal: The memory backing IOSurfaces of former client buffer pbuffers is leaked
     4        https://bugs.webkit.org/show_bug.cgi?id=233328
     5        <rdar://problem/85563187>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Add tests testing Cocoa GraphicsContextGLOpenGL drawing buffer
     10        recycling behavior.
     11
     12        * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
     13        * TestWebKitAPI/Sources.txt:
     14        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     15        * TestWebKitAPI/Tests/WebCore/ImageBufferTests.cpp:
     16        (TestWebKitAPI::imageBufferPixelIs):
     17        (TestWebKitAPI::memoryFootprintChangedBy): Deleted.
     18        * TestWebKitAPI/Tests/WebCore/cocoa/TestGraphicsContextGLOpenGLCocoa.mm:
     19        (TestWebKitAPI::createDefaultTestContext):
     20        (TestWebKitAPI::changeContextContents):
     21        (TestWebKitAPI::TEST):
     22        * TestWebKitAPI/TestUtilities.h: Added.
     23        * TestWebKitAPI/TestUtilities.cpp: Added.
     24        Add few useful functions to TestUtilities.h so that different
     25        tests can use them.
     26
    1272021-11-23  Lauro Moura  <lmoura@igalia.com>
    228
  • trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig

    r285799 r286160  
    9494OTHER_CPLUSPLUSFLAGS = $(inherited) -isystem $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders;
    9595
    96 OTHER_LDFLAGS = $(inherited) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework JavaScriptCore -framework WebKit -lWebCoreTestSupport -framework Metal $(WK_APPSERVERSUPPORT_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SYSTEM_LDFLAGS) $(WK_UIKITMACHELPER_LDFLAGS) $(WK_VISIONKITCORE_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
     96OTHER_LDFLAGS = $(inherited) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework JavaScriptCore -framework WebKit -lWebCoreTestSupport -framework Metal -framework IOSurface $(WK_APPSERVERSUPPORT_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SYSTEM_LDFLAGS) $(WK_UIKITMACHELPER_LDFLAGS) $(WK_VISIONKITCORE_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
    9797OTHER_LDFLAGS_PLATFORM_ = -framework Cocoa -framework Carbon;
    9898
  • trunk/Tools/TestWebKitAPI/Sources.txt

    r285547 r286160  
    2626PlatformUtilities.cpp
    2727TestsController.cpp
     28TestUtilities.cpp
    2829
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r286106 r286160  
    23732373                7BA3936B271EDFCA0015911C /* TestGraphicsContextGLOpenGLCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestGraphicsContextGLOpenGLCocoa.mm; sourceTree = "<group>"; };
    23742374                7BA3936D271EEC530015911C /* WebCoreUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreUtilities.h; sourceTree = "<group>"; };
     2375                7BB754AF274E39A100D00EC1 /* TestUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestUtilities.h; sourceTree = "<group>"; };
     2376                7BB754B0274E39A100D00EC1 /* TestUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestUtilities.cpp; sourceTree = "<group>"; };
    23752377                7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PrepareForMoveToWindow.mm; sourceTree = "<group>"; };
    23762378                7C3965051CDD74F90094DBB8 /* ColorTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorTests.cpp; sourceTree = "<group>"; };
     
    31823184                                BC131AA8117131FC00B69727 /* TestsController.cpp */,
    31833185                                BCB9E7C711234E3A00A137E0 /* TestsController.h */,
     3186                                7BB754B0274E39A100D00EC1 /* TestUtilities.cpp */,
     3187                                7BB754AF274E39A100D00EC1 /* TestUtilities.h */,
    31843188                                7C83E0361D0A5F7000FEBCF3 /* Utilities.h */,
    31853189                                7BA3936D271EEC530015911C /* WebCoreUtilities.h */,
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/ImageBufferTests.cpp

    r285644 r286160  
    2626#include "config.h"
    2727
     28#include "TestUtilities.h"
    2829#include <WebCore/Color.h>
    2930#include <WebCore/ImageBuffer.h>
     
    3536using namespace WebCore;
    3637
    37 static ::testing::AssertionResult memoryFootprintChangedBy(size_t& lastFootprint, double expectedChange, double error)
    38 {
    39     WTF::releaseFastMallocFreeMemory();
    40     size_t newFootprint = memoryFootprint();
    41     size_t oldFootprint = std::exchange(lastFootprint, newFootprint);
    42     double change = static_cast<double>(newFootprint) - oldFootprint;
    43     if (change - expectedChange > error)
    44         return ::testing::AssertionFailure() << "Footprint changed by " << change << ". Expected at most " << expectedChange << "+-" << error;
    45     return ::testing::AssertionSuccess();
    46 }
    47 
    4838static ::testing::AssertionResult imageBufferPixelIs(Color expected, ImageBuffer& imageBuffer, int x, int y)
    4939{
     
    5343    auto got = Color { SRGBA<uint8_t> { data.item(0), data.item(1), data.item(2), data.item(3) } };
    5444    if (got != expected)
    55         return ::testing::AssertionFailure() << "color is not expected."; // FIXME: implement Color <<.
     45        return ::testing::AssertionFailure() << "color is not expected. Got: " << got << ", expected: " << expected << ".";
    5646    return ::testing::AssertionSuccess();
    5747}
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/TestGraphicsContextGLOpenGLCocoa.mm

    r284669 r286160  
    2828
    2929#if PLATFORM(COCOA) && ENABLE(WEBGL)
     30#import "TestUtilities.h"
    3031#import "WebCoreUtilities.h"
    3132#import <Metal/Metal.h>
     33#import <WebCore/Color.h>
    3234#import <WebCore/GraphicsContextGLOpenGL.h>
     35#import <optional>
     36#import <wtf/HashSet.h>
     37#import <wtf/MemoryFootprint.h>
    3338
    3439namespace TestWebKitAPI {
    35 using namespace WebCore;
    3640
    3741namespace {
    38 class TestedGraphicsContextGLOpenGL : public GraphicsContextGLOpenGL {
     42
     43class TestedGraphicsContextGLOpenGL : public WebCore::GraphicsContextGLOpenGL {
    3944public:
    40     static RefPtr<TestedGraphicsContextGLOpenGL> create(GraphicsContextGLAttributes attributes)
     45    static RefPtr<TestedGraphicsContextGLOpenGL> create(WebCore::GraphicsContextGLAttributes attributes)
    4146    {
    4247        auto context = adoptRef(*new TestedGraphicsContextGLOpenGL(WTFMove(attributes)));
    4348        return context;
    4449    }
     50    WebCore::IOSurface* displayBuffer()
     51    {
     52        return m_swapChain.displayBuffer().surface.get();
     53    }
     54    void markDisplayBufferInUse()
     55    {
     56        m_swapChain.markDisplayBufferInUse();
     57    }
    4558private:
    46     TestedGraphicsContextGLOpenGL(GraphicsContextGLAttributes attributes)
    47         : GraphicsContextGLOpenGL(WTFMove(attributes))
     59    TestedGraphicsContextGLOpenGL(WebCore::GraphicsContextGLAttributes attributes)
     60        : WebCore::GraphicsContextGLOpenGL(WTFMove(attributes))
    4861    {
    4962    }
    5063};
     64
     65class GraphicsContextGLOpenGLCocoaTest : public ::testing::Test {
     66public:
     67    void SetUp() override // NOLINT
     68    {
     69        m_scopedProcessType = ScopedSetAuxiliaryProcessTypeForTesting { WebCore::AuxiliaryProcessType::GPU };
     70    }
     71    void TearDown() override // NOLINT
     72    {
     73        m_scopedProcessType = std::nullopt;
     74    }
     75private:
     76    std::optional<ScopedSetAuxiliaryProcessTypeForTesting> m_scopedProcessType;
     77};
     78
     79}
     80
     81static const int expectedDisplayBufferPoolSize = 3;
     82
     83static RefPtr<TestedGraphicsContextGLOpenGL> createDefaultTestContext(WebCore::IntSize contextSize)
     84{
     85    WebCore::GraphicsContextGLAttributes attributes;
     86    attributes.useMetal = true;
     87    attributes.antialias = false;
     88    attributes.depth = false;
     89    attributes.stencil = false;
     90    attributes.alpha = true;
     91    attributes.preserveDrawingBuffer = false;
     92    auto context = TestedGraphicsContextGLOpenGL::create(attributes);
     93    if (!context)
     94        return nullptr;
     95    context->reshape(contextSize.width(), contextSize.height());
     96    return context;
     97}
     98
     99static ::testing::AssertionResult changeContextContents(TestedGraphicsContextGLOpenGL& context, int iteration)
     100{
     101    context.markContextChanged();
     102    WebCore::Color expected { iteration % 2 ? WebCore::Color::green : WebCore::Color::yellow };
     103    auto [colorSpace, components] = expected.colorSpaceAndComponents();
     104    UNUSED_VARIABLE(colorSpace);
     105    context.clearColor(components[0], components[1], components[2], components[3]);
     106    context.clear(WebCore::GraphicsContextGL::COLOR_BUFFER_BIT);
     107    uint8_t gotValues[4] = { };
     108    auto sampleAt = context.getInternalFramebufferSize();
     109    sampleAt.contract(2, 3);
     110    sampleAt.clampNegativeToZero();
     111    context.readnPixels(sampleAt.width(), sampleAt.height(), 1, 1, WebCore::GraphicsContextGL::RGBA, WebCore::GraphicsContextGL::UNSIGNED_BYTE, gotValues);
     112    WebCore::Color got { WebCore::SRGBA<uint8_t> { gotValues[0], gotValues[1], gotValues[2], gotValues[3] } };
     113    if (got != expected)
     114        return ::testing::AssertionFailure() << "Failed to verify draw to context. Got: " << got << ", expected: " << expected << ".";
     115    return ::testing::AssertionSuccess();
    51116}
    52117
     
    69134// context was created first. Test is applicable only for Metal, since GPU selection for OpenGL is
    70135// very different.
    71 TEST(GraphicsContextGLOpenGLCocoaTest, MAYBE_MultipleGPUsDifferentPowerPreferenceMetal)
     136TEST_F(GraphicsContextGLOpenGLCocoaTest, MAYBE_MultipleGPUsDifferentPowerPreferenceMetal)
    72137{
    73138    if (!hasMultipleGPUs())
    74139        return;
    75     ScopedSetAuxiliaryProcessTypeForTesting scopedProcessType { AuxiliaryProcessType::GPU };
    76 
    77     GraphicsContextGLAttributes attributes;
     140
     141    WebCore::GraphicsContextGLAttributes attributes;
    78142    attributes.useMetal = true;
    79     EXPECT_EQ(attributes.powerPreference, GraphicsContextGLPowerPreference::Default);
     143    EXPECT_EQ(attributes.powerPreference, WebCore::GraphicsContextGLPowerPreference::Default);
    80144    auto defaultContext = TestedGraphicsContextGLOpenGL::create(attributes);
    81     EXPECT_NE(defaultContext, nullptr);
    82 
    83     attributes.powerPreference = GraphicsContextGLPowerPreference::LowPower;
     145    ASSERT_NE(defaultContext, nullptr);
     146
     147    attributes.powerPreference = WebCore::GraphicsContextGLPowerPreference::LowPower;
    84148    auto lowPowerContext = TestedGraphicsContextGLOpenGL::create(attributes);
    85     EXPECT_NE(lowPowerContext, nullptr);
    86 
    87     attributes.powerPreference = GraphicsContextGLPowerPreference::HighPerformance;
     149    ASSERT_NE(lowPowerContext, nullptr);
     150
     151    attributes.powerPreference = WebCore::GraphicsContextGLPowerPreference::HighPerformance;
    88152    auto highPerformanceContext = TestedGraphicsContextGLOpenGL::create(attributes);
    89     EXPECT_NE(highPerformanceContext, nullptr);
    90 
    91     EXPECT_NE(lowPowerContext->getString(GraphicsContextGL::RENDERER), highPerformanceContext->getString(GraphicsContextGL::RENDERER));
    92     EXPECT_EQ(defaultContext->getString(GraphicsContextGL::RENDERER), lowPowerContext->getString(GraphicsContextGL::RENDERER));
    93 }
    94 
    95 }
     153    ASSERT_NE(highPerformanceContext, nullptr);
     154
     155    EXPECT_NE(lowPowerContext->getString(WebCore::GraphicsContextGL::RENDERER), highPerformanceContext->getString(WebCore::GraphicsContextGL::RENDERER));
     156    EXPECT_EQ(defaultContext->getString(WebCore::GraphicsContextGL::RENDERER), lowPowerContext->getString(WebCore::GraphicsContextGL::RENDERER));
     157}
     158
     159TEST_F(GraphicsContextGLOpenGLCocoaTest, DisplayBuffersAreRecycled)
     160{
     161    auto context = createDefaultTestContext({ 20, 20 });
     162    ASSERT_NE(context, nullptr);
     163    RetainPtr<IOSurfaceRef> expectedDisplayBuffers[expectedDisplayBufferPoolSize];
     164    for (int i = 0; i < 50; ++i) {
     165        EXPECT_TRUE(changeContextContents(*context, i));
     166        context->prepareForDisplay();
     167        auto* surface = context->displayBuffer();
     168        ASSERT_NE(surface, nullptr);
     169        int slot = i % expectedDisplayBufferPoolSize;
     170        if (!expectedDisplayBuffers[slot])
     171            expectedDisplayBuffers[slot] = surface->surface();
     172        EXPECT_EQ(expectedDisplayBuffers[slot].get(), surface->surface()) << "for i:" << i << " slot: " << slot;
     173    }
     174    for (int i = 0; i < expectedDisplayBufferPoolSize - 1; ++i) {
     175        for (int j = i + 1; j < expectedDisplayBufferPoolSize; ++j)
     176            EXPECT_NE(expectedDisplayBuffers[i].get(), expectedDisplayBuffers[j].get()) << "for i: " << i << " j:" << j;
     177    }
     178}
     179
     180// Test that drawing buffers are not recycled if `GraphicsContextGLOpenGL::markDisplayBufferInUse()`
     181// is called.
     182TEST_F(GraphicsContextGLOpenGLCocoaTest, DisplayBuffersAreNotRecycledWhenMarkedInUse)
     183{
     184    auto context = createDefaultTestContext({ 20, 20 });
     185    ASSERT_NE(context, nullptr);
     186    HashSet<RetainPtr<IOSurfaceRef>> seenSurfaceRefs;
     187    for (int i = 0; i < 50; ++i) {
     188        EXPECT_TRUE(changeContextContents(*context, i));
     189        context->prepareForDisplay();
     190        WebCore::IOSurface* surface = context->displayBuffer();
     191        ASSERT_NE(surface, nullptr);
     192        IOSurfaceRef surfaceRef = surface->surface();
     193        EXPECT_NE(surfaceRef, nullptr);
     194        EXPECT_FALSE(seenSurfaceRefs.contains(surfaceRef));
     195        seenSurfaceRefs.add(surfaceRef);
     196
     197        context->markDisplayBufferInUse();
     198    }
     199    ASSERT_EQ(seenSurfaceRefs.size(), 50u);
     200}
     201
     202// Test that drawing buffers are not recycled if the use count of the underlying IOSurface
     203// changes. Use count is modified for example by CoreAnimation when the IOSurface is attached
     204// to the contents.
     205TEST_F(GraphicsContextGLOpenGLCocoaTest, DisplayBuffersAreNotRecycledWhedInUse)
     206{
     207    auto context = createDefaultTestContext({ 20, 20 });
     208    ASSERT_NE(context, nullptr);
     209    HashSet<RetainPtr<IOSurfaceRef>> seenSurfaceRefs;
     210    for (int i = 0; i < 50; ++i) {
     211        EXPECT_TRUE(changeContextContents(*context, i));
     212        context->prepareForDisplay();
     213        WebCore::IOSurface* surface = context->displayBuffer();
     214        ASSERT_NE(surface, nullptr);
     215        IOSurfaceRef surfaceRef = surface->surface();
     216        EXPECT_NE(surfaceRef, nullptr);
     217        EXPECT_FALSE(seenSurfaceRefs.contains(surfaceRef));
     218        seenSurfaceRefs.add(surfaceRef);
     219
     220        IOSurfaceIncrementUseCount(surfaceRef);
     221    }
     222    ASSERT_EQ(seenSurfaceRefs.size(), 50u);
     223}
     224
     225// Test that drawing to GraphicsContextGL and marking the display buffer in use does not leak big
     226// amounts of memory for each displayed buffer.
     227TEST_F(GraphicsContextGLOpenGLCocoaTest, UnrecycledDisplayBuffersNoLeaks)
     228{
     229    // The test detects the leak by observing memory footprint. However, some of the freed IOSurface
     230    // memory (130mb) stays resident, presumably by intention of IOKit. The test would originally leak
     231    // 2.7gb so the intended bug would be detected with 150mb error range.
     232    size_t footprintError = 150 * 1024 * 1024;
     233    size_t footprintChange = 0;
     234
     235    auto context = createDefaultTestContext({ 2048, 2048 });
     236    ASSERT_NE(context, nullptr);
     237
     238    WTF::releaseFastMallocFreeMemory();
     239    auto lastFootprint = memoryFootprint();
     240
     241    for (int i = 0; i < 50; ++i) {
     242        EXPECT_TRUE(changeContextContents(*context, i));
     243        context->prepareForDisplay();
     244        EXPECT_NE(context->displayBuffer(), nullptr);
     245        context->markDisplayBufferInUse();
     246    }
     247
     248    EXPECT_TRUE(memoryFootprintChangedBy(lastFootprint, footprintChange, footprintError));
     249}
     250
     251}
     252
    96253#endif
Note: See TracChangeset for help on using the changeset viewer.