Changeset 122252 in webkit


Ignore:
Timestamp:
Jul 10, 2012 1:14:36 PM (12 years ago)
Author:
danakj@chromium.org
Message:

[chromium] Avoid allocating render pass textures that have no content
https://bugs.webkit.org/show_bug.cgi?id=90702

Reviewed by Adrienne Walker.

Source/WebCore:

When OOM conditions are hit, textures are not allocated for some layers
which can prevent any quads from being present for a render surface.
This is used as a signal to prevent the RenderPass from allocating a
texture.

Replace the CCLayerTreeHostImpl::removePassesWithCachedTextures() method
with a general removeRenderPasses() which takes a culling control object
and will remove passes based on the inputs from the control object.

This new method is used for the old purpose of removing passes with cached
textures, as well as to remove passes that do not have any quad inputs.

Test: CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit

  • platform/graphics/chromium/LayerRendererChromium.cpp:

(WebCore::LayerRendererChromium::drawRenderPassQuad):

  • platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:

(WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
(WebCore):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass):
(WebCore::CCLayerTreeHostImpl::removeRenderPasses):

  • platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:

(WebCore):
(CullRenderPassesWithCachedTextures):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::renderPassListBegin):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::renderPassListEnd):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::renderPassListNext):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::CullRenderPassesWithCachedTextures):
(CCLayerTreeHostImpl):
(CullRenderPassesWithNoQuads):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::renderPassListBegin):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::renderPassListEnd):
(WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::renderPassListNext):

Source/WebKit/chromium:

  • tests/CCLayerTreeHostImplTest.cpp:
  • tests/CCLayerTreeHostTest.cpp:

(WTF::ContentLayerChromiumWithUpdateTracking::ContentLayerChromiumWithUpdateTracking):
(CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit):
(WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit):
(WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::beginTest):
(WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::didCommit):
(WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::afterTest):
(WTF):

Location:
trunk/Source
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r122250 r122252  
     12012-07-10  Dana Jansens  <danakj@chromium.org>
     2
     3        [chromium] Avoid allocating render pass textures that have no content
     4        https://bugs.webkit.org/show_bug.cgi?id=90702
     5
     6        Reviewed by Adrienne Walker.
     7
     8        When OOM conditions are hit, textures are not allocated for some layers
     9        which can prevent any quads from being present for a render surface.
     10        This is used as a signal to prevent the RenderPass from allocating a
     11        texture.
     12
     13        Replace the CCLayerTreeHostImpl::removePassesWithCachedTextures() method
     14        with a general removeRenderPasses() which takes a culling control object
     15        and will remove passes based on the inputs from the control object.
     16
     17        This new method is used for the old purpose of removing passes with cached
     18        textures, as well as to remove passes that do not have any quad inputs.
     19
     20        Test: CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
     21
     22        * platform/graphics/chromium/LayerRendererChromium.cpp:
     23        (WebCore::LayerRendererChromium::drawRenderPassQuad):
     24        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
     25        (WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
     26        (WebCore):
     27        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass):
     28        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass):
     29        (WebCore::CCLayerTreeHostImpl::removeRenderPasses):
     30        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
     31        (WebCore):
     32        (CullRenderPassesWithCachedTextures):
     33        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::renderPassListBegin):
     34        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::renderPassListEnd):
     35        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::renderPassListNext):
     36        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::CullRenderPassesWithCachedTextures):
     37        (CCLayerTreeHostImpl):
     38        (CullRenderPassesWithNoQuads):
     39        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::renderPassListBegin):
     40        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::renderPassListEnd):
     41        (WebCore::CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::renderPassListNext):
     42
    1432012-07-10  Joshua Netterfield  <jnetterfield@rim.com>
    244        Make GC3D and E3D more maintainable for GLES platforms
  • trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp

    r122196 r122252  
    613613void LayerRendererChromium::drawRenderPassQuad(const CCRenderPassDrawQuad* quad)
    614614{
     615    ManagedTexture* contentsTexture = m_renderPassTextures.get(quad->renderPassId());
     616    if (!contentsTexture || !contentsTexture->textureId())
     617        return;
     618
    615619    WebTransformationMatrix renderTransform = quad->layerTransform();
    616620    // Apply a scaling factor to size the quad from 1x1 to its intended size.
     
    621625    if (!contentsDeviceTransform.isInvertible())
    622626        return;
    623 
    624     ManagedTexture* contentsTexture = m_renderPassTextures.get(quad->renderPassId());
    625     ASSERT(contentsTexture && contentsTexture->textureId());
    626627
    627628    OwnPtr<ManagedTexture> backgroundTexture = drawBackgroundFilters(quad, contentsDeviceTransform);
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp

    r122160 r122252  
    354354        occlusionTracker.overdrawMetrics().recordMetrics(this);
    355355
     356    removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
    356357    m_layerRenderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
    357     removePassesWithCachedTextures(frame.renderPasses, frame.skippedPasses, m_layerRenderer.get());
     358    removeRenderPasses(CullRenderPassesWithCachedTextures(*m_layerRenderer), frame);
    358359
    359360    return drawFrame;
     
    406407}
    407408
     409// static
    408410void CCLayerTreeHostImpl::removeRenderPassesRecursive(CCRenderPassList& passes, size_t bottomPass, const CCRenderPass* firstToRemove, CCRenderPassList& skippedPasses)
    409411{
     
    435437}
    436438
    437 void CCLayerTreeHostImpl::removePassesWithCachedTextures(CCRenderPassList& passes, CCRenderPassList& skippedPasses, const CCRenderer* renderer)
    438 {
    439     for (int passIndex = passes.size() - 1; passIndex >= 0; --passIndex) {
    440         CCRenderPass* currentPass = passes[passIndex].get();
     439bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassList&, const CCRenderPassDrawQuad& quad) const
     440{
     441    return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId());
     442}
     443
     444bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassList& passList, const CCRenderPassDrawQuad& quad) const
     445{
     446    size_t passIndex = passList.find(quad.renderPass());
     447    ASSERT(passIndex != notFound);
     448
     449    // If any quad or RenderPass draws into this RenderPass, then keep it.
     450    const CCQuadList& quadList = passList[passIndex]->quadList();
     451    for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
     452        CCDrawQuad* currentQuad = quadListIterator->get();
     453
     454        if (currentQuad->material() != CCDrawQuad::RenderPass)
     455            return false;
     456
     457        const CCRenderPassDrawQuad* quadInPass = static_cast<CCRenderPassDrawQuad*>(currentQuad);
     458        if (passList.contains(quadInPass->renderPass()))
     459            return false;
     460    }
     461    return true;
     462}
     463
     464// Defined for linking tests.
     465template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
     466template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
     467
     468// static
     469template<typename RenderPassCuller>
     470void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
     471{
     472    for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
     473        CCRenderPass* currentPass = frame.renderPasses[it].get();
    441474        const CCQuadList& quadList = currentPass->quadList();
    442475        CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
     
    449482
    450483            CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad);
    451             if (!renderPassQuad->contentsChangedSinceLastFrame().isEmpty())
     484            if (!culler.shouldRemoveRenderPass(frame.renderPasses, *renderPassQuad))
    452485                continue;
    453             if (!renderer->haveCachedResourcesForRenderPassId(renderPassQuad->renderPassId()))
    454                 continue;
    455 
    456             // We are changing the vector in the middle of reverse iteration.
    457             // We are guaranteed that any data from iterator to the end will not change.
    458             // Capture the iterator position from the end, and restore it after the change.
    459             int positionFromEnd = passes.size() - passIndex;
    460             removeRenderPassesRecursive(passes, passIndex, renderPassQuad->renderPass(), skippedPasses);
    461             passIndex = passes.size() - positionFromEnd;
    462             ASSERT(passIndex >= 0);
     486
     487            // We are changing the vector in the middle of iteration. Because we
     488            // delete render passes that draw into the current pass, we are
     489            // guaranteed that any data from the iterator to the end will not
     490            // change. So, capture the iterator position from the end of the
     491            // list, and restore it after the change.
     492            int positionFromEnd = frame.renderPasses.size() - it;
     493            removeRenderPassesRecursive(frame.renderPasses, it, renderPassQuad->renderPass(), frame.skippedPasses);
     494            it = frame.renderPasses.size() - positionFromEnd;
     495            ASSERT(it >= 0);
    463496        }
    464497    }
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h

    r122160 r122252  
    4343class CCFrameRateCounter;
    4444class CCHeadsUpDisplay;
    45 class CCPageScaleAnimation;
    4645class CCLayerImpl;
    4746class CCLayerTreeHostImplTimeSourceAdapter;
     47class CCPageScaleAnimation;
     48class CCRenderPassDrawQuad;
    4849class LayerRendererChromium;
    4950class TextureAllocator;
     
    178179    CCDebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); }
    179180
    180     // Removes all render passes for which we have cached textures, and which did not change their content.
    181     static void removePassesWithCachedTextures(CCRenderPassList& passes, CCRenderPassList& skippedPasses, const CCRenderer*);
     181    class CullRenderPassesWithCachedTextures {
     182    public:
     183        bool shouldRemoveRenderPass(const CCRenderPassList&, const CCRenderPassDrawQuad&) const;
     184
     185        // Iterates from the root first, in order to remove the surfaces closest
     186        // to the root with cached textures, and all surfaces that draw into
     187        // them.
     188        size_t renderPassListBegin(const CCRenderPassList& list) const { return list.size() - 1; }
     189        size_t renderPassListEnd(const CCRenderPassList&) const { return 0 - 1; }
     190        size_t renderPassListNext(size_t it) const { return it - 1; }
     191
     192        CullRenderPassesWithCachedTextures(CCRenderer& renderer) : m_renderer(renderer) { }
     193    private:
     194        CCRenderer& m_renderer;
     195    };
     196
     197    class CullRenderPassesWithNoQuads {
     198    public:
     199        bool shouldRemoveRenderPass(const CCRenderPassList&, const CCRenderPassDrawQuad&) const;
     200
     201        // Iterates in draw order, so that when a surface is removed, and its
     202        // target becomes empty, then its target can be removed also.
     203        size_t renderPassListBegin(const CCRenderPassList&) const { return 0; }
     204        size_t renderPassListEnd(const CCRenderPassList& list) const { return list.size(); }
     205        size_t renderPassListNext(size_t it) const { return it + 1; }
     206    };
     207
     208    template<typename RenderPassCuller>
     209    static void removeRenderPasses(RenderPassCuller, FrameData&);
    182210
    183211protected:
  • trunk/Source/WebKit/chromium/ChangeLog

    r122230 r122252  
     12012-07-10  Dana Jansens  <danakj@chromium.org>
     2
     3        [chromium] Avoid allocating render pass textures that have no content
     4        https://bugs.webkit.org/show_bug.cgi?id=90702
     5
     6        Reviewed by Adrienne Walker.
     7
     8        * tests/CCLayerTreeHostImplTest.cpp:
     9        * tests/CCLayerTreeHostTest.cpp:
     10        (WTF::ContentLayerChromiumWithUpdateTracking::ContentLayerChromiumWithUpdateTracking):
     11        (CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit):
     12        (WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit):
     13        (WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::beginTest):
     14        (WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::didCommit):
     15        (WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::drawLayersOnCCThread):
     16        (WTF::CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit::afterTest):
     17        (WTF):
     18
    1192012-07-10  Leandro Gracia Gil  <leandrogracia@chromium.org>
    220
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp

    r122160 r122252  
    28782878};
    28792879
    2880 struct RenderPassRemovalTestData {
    2881     CCRenderPassList renderPassList;
     2880struct RenderPassRemovalTestData : public CCLayerTreeHostImpl::FrameData {
    28822881    std::map<char, RenderPassCacheEntry> renderPassCache;
    28832882    std::map<const CCRenderPass*, char> renderPassId;
     
    30203019            }
    30213020        }
    3022         testData.renderPassList.insert(0, renderPass.release());
     3021        testData.renderPasses.insert(0, renderPass.release());
    30233022        if (*currentChar)
    30243023            currentChar++;
     
    30293028{
    30303029    char* pos = buffer;
    3031     CCRenderPassList::const_reverse_iterator it = testData.renderPassList.rbegin();
    3032     while (it != testData.renderPassList.rend()) {
     3030    for (CCRenderPassList::const_reverse_iterator it = testData.renderPasses.rbegin(); it != testData.renderPasses.rend(); ++it) {
    30333031        CCRenderPass* currentPass = it->get();
    30343032        char passId = testData.renderPassId.find(currentPass)->second;
     
    30623060        *pos = '\n';
    30633061        pos++;
    3064         it++;
    30653062    }
    30663063    *pos = '\0';
     
    32253222    while (removeRenderPassesCases[testCaseIndex].name) {
    32263223        RenderPassRemovalTestData testData;
    3227         CCRenderPassList skippedPasses;
    32283224        configureRenderPassTestData(removeRenderPassesCases[testCaseIndex].initScript, testData, renderer.get());
    3229         CCLayerTreeHostImpl::removePassesWithCachedTextures(testData.renderPassList, skippedPasses, renderer.get());
     3225        CCLayerTreeHostImpl::removeRenderPasses(CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures(*renderer), testData);
    32303226        verifyRenderPassTestData(removeRenderPassesCases[testCaseIndex], testData);
    32313227        testCaseIndex++;
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp

    r122185 r122252  
    11721172        , m_paintContentsCount(0)
    11731173    {
     1174        setAnchorPoint(FloatPoint(0, 0));
    11741175        setBounds(IntSize(10, 10));
    11751176        setIsDrawable(true);
     
    22622263SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestCompositeAndReadbackCleanup)
    22632264
     2265class CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit : public CCLayerTreeHostTest {
     2266public:
     2267    CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit()
     2268        : m_rootLayer(ContentLayerChromiumWithUpdateTracking::create(&m_mockDelegate))
     2269        , m_surfaceLayer1(ContentLayerChromiumWithUpdateTracking::create(&m_mockDelegate))
     2270        , m_surfaceLayer2(ContentLayerChromiumWithUpdateTracking::create(&m_mockDelegate))
     2271    {
     2272    }
     2273
     2274    virtual void beginTest()
     2275    {
     2276        m_layerTreeHost->setViewportSize(IntSize(100, 100));
     2277
     2278        m_rootLayer->setBounds(IntSize(100, 100));
     2279        m_surfaceLayer1->setBounds(IntSize(100, 100));
     2280        m_surfaceLayer1->setForceRenderSurface(true);
     2281        m_surfaceLayer1->setOpacity(0.5);
     2282        m_surfaceLayer2->setBounds(IntSize(100, 100));
     2283        m_surfaceLayer2->setForceRenderSurface(true);
     2284        m_surfaceLayer2->setOpacity(0.5);
     2285
     2286        m_rootLayer->addChild(m_surfaceLayer1);
     2287        m_surfaceLayer1->addChild(m_surfaceLayer2);
     2288        m_layerTreeHost->setRootLayer(m_rootLayer);
     2289    }
     2290
     2291    virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* hostImpl)
     2292    {
     2293        CCRenderer* renderer = hostImpl->layerRenderer();
     2294        unsigned surface1RenderPassId = hostImpl->rootLayer()->children()[0]->id();
     2295        unsigned surface2RenderPassId = hostImpl->rootLayer()->children()[0]->children()[0]->id();
     2296
     2297        switch (hostImpl->sourceFrameNumber()) {
     2298        case 0:
     2299            EXPECT_TRUE(renderer->haveCachedResourcesForRenderPassId(surface1RenderPassId));
     2300            EXPECT_TRUE(renderer->haveCachedResourcesForRenderPassId(surface2RenderPassId));
     2301
     2302            // Reduce the memory limit to only fit the root layer and one render surface. This
     2303            // prevents any contents drawing into surfaces from being allocated.
     2304            hostImpl->setMemoryAllocationLimitBytes(100 * 100 * 4 * 2);
     2305            break;
     2306        case 1:
     2307            EXPECT_FALSE(renderer->haveCachedResourcesForRenderPassId(surface1RenderPassId));
     2308            EXPECT_FALSE(renderer->haveCachedResourcesForRenderPassId(surface2RenderPassId));
     2309
     2310            endTest();
     2311            break;
     2312        }
     2313    }
     2314
     2315    virtual void afterTest()
     2316    {
     2317        EXPECT_EQ(2, m_rootLayer->paintContentsCount());
     2318        EXPECT_EQ(2, m_surfaceLayer1->paintContentsCount());
     2319        EXPECT_EQ(2, m_surfaceLayer2->paintContentsCount());
     2320
     2321        // Clear layer references so CCLayerTreeHost dies.
     2322        m_rootLayer.clear();
     2323        m_surfaceLayer1.clear();
     2324        m_surfaceLayer2.clear();
     2325    }
     2326
     2327private:
     2328    MockContentLayerDelegate m_mockDelegate;
     2329    RefPtr<ContentLayerChromiumWithUpdateTracking> m_rootLayer;
     2330    RefPtr<ContentLayerChromiumWithUpdateTracking> m_surfaceLayer1;
     2331    RefPtr<ContentLayerChromiumWithUpdateTracking> m_surfaceLayer2;
     2332};
     2333
     2334SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit)
     2335
    22642336} // namespace
Note: See TracChangeset for help on using the changeset viewer.