Changeset 76372 in webkit


Ignore:
Timestamp:
Jan 21, 2011 11:35:43 AM (13 years ago)
Author:
Adam Roben
Message:

Separate flushing layer changes from rendering in CACFLayerTreeHost

Old model:

1) A change is made to a GraphicsLayer.
2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which schedules the

render timer.

3) The timer fires, which calls through to CACFLayerTreeHost::render, which performs the

flush and then renders.

New model:

1) A change is made to a GraphicsLayer.
2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which tells the new

LayerChangesFlusher singleton that this host has changes that need to be flushed.

3) LayerChangesFlusher sets up a Windows hook that will get called on the next iteration

of the message loop.

4) LayerChangesFlusher's hook is called, which calls through to

CACFLayerTreeHost::flushPendingLayerChangesNow.

5) CACFLayerTreeHost::flushPendingLayerChangesNow schedules the render timer so the changes

that were just flushed to the context will be rendered.

When a change is made to a PlatformCALayer that doesn't have a corresponding GraphicsLayer
(e.g., for rendering <video>), CACFLayerTreeHost::layerTreeDidChange takes care of
scheduling the flush.

This change has three advantages:

1) Whenever we flush layer changes, we first update layout. This can cause the page to

leave compositing mode, which in turn can cause all references to the CACFLayerTreeHost
to be dropped. By separating flushing (and thus updating layout) from rendering, we no
longer have to worry about this happen during rendering.

2) The new model is much more similar to how things work on the Mac, so will hopefully

reduce the number of platform-specific bugs.

3) CACFLayerTreeHost::shouldRender, which was used to make sure we didn't render while a

layout was pending, is no longer needed. It actually hasn't been needed since at least
r75987, but removing it before now would have resulted in a crash whenever a page came
out of compositing mode due to (1).

Fixes <http://webkit.org/b/52852> Flushing layer changes and rendering are intertwined in
CACFLayerTreeHost, but shouldn't be

Reviewed by Simon Fraser.

Source/WebCore:

  • WebCore.vcproj/WebCore.vcproj: Added LayerChangesFlusher.
  • platform/graphics/ca/win/CACFLayerTreeHost.cpp: Added new #include, sorted existing #includes.

(WebCore::CACFLayerTreeHost::CACFLayerTreeHost): Initialize new member.
(WebCore::CACFLayerTreeHost::layerTreeDidChange): If we aren't already flushing changes,
schedule a flush. Removed the call to renderSoon(), which now happens when the flush is
finished.
(WebCore::CACFLayerTreeHost::destroyRenderer): Cancel any pending flush we had scheduled. Also
fixed a bug where we'd fail to clear the context's layer.
(WebCore::CACFLayerTreeHost::render): Removed code to ask the client if we should render, which
is no longer needed. Moved code to flush layer changes from here to
flushPendingLayerChangesNow, which is called via the above-described mechanism.
(WebCore::CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon): Schedule a flush. Removed
code to schedule a render, which now happens after we've flushed.
(WebCore::CACFLayerTreeHost::flushPendingLayerChangesNow): Added. Some of this code came from
render(). First we flush GraphicsLayer changes from GraphicsLayers to their underlying
PlatformCALayers, then we flush changes from PlatformCALayers to the context, then we
schedule a render so that the changes will be rendered to the screen.

  • platform/graphics/ca/win/CACFLayerTreeHost.h: Removed

CACFLayerTreeHostClient::shouldRender. Added flushPendingLayerChangesNow and
m_isFlushingLayerChanges.

  • platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.

(WebCore::LayerChangesFlusher::shared):
(WebCore::LayerChangesFlusher::LayerChangesFlusher):
(WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon):
(WebCore::LayerChangesFlusher::cancelPendingFlush):
(WebCore::LayerChangesFlusher::hookCallback):
(WebCore::LayerChangesFlusher::hookFired):
(WebCore::LayerChangesFlusher::setHook):
(WebCore::LayerChangesFlusher::removeHook):

  • platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.

(WebCore::LayerChangesFlusher::shared): Returns the singleton.
(WebCore::LayerChangesFlusher::LayerChangesFlusher): Initialize our members.
(WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon): Add the host to the set of
hosts with changes that need to be flushed, and set up our hook if we haven't already.
(WebCore::LayerChangesFlusher::cancelPendingFlush): Remove the host from the set of hosts
with changes that need to be flushed. If we have no more such hosts, remove our hook, unless
we're currently in the process of calling out to our hosts, in which case we'll take care of
the hook once we're done calling out.
(WebCore::LayerChangesFlusher::hookCallback): This is the function that Windows calls when
our hook fires. Just calls through to hookFired on the singleton.
(WebCore::LayerChangesFlusher::hookFired): Tell all the hosts with changes that needed to be
flushed that it's time to flush. If no hosts re-added themselves to our set during this
process, remove our hook.
(WebCore::LayerChangesFlusher::setHook): Calls through to ::SetWindowsHookExW.
(WebCore::LayerChangesFlusher::removeHook): Calls through to ::UnhookWindowsHookEx.

  • platform/graphics/ca/win/LayerChangesFlusher.h: Added.

Source/WebKit/win:

Update for CACFLayerTreeHost changes

  • WebView.cpp:

(WebView::paint): Changed to flush layer changes via CACFLayerTreeHost, which will call back
to our own flushing function if needed.

  • WebView.h: Removed shouldRender, which is no longer used or needed.
Location:
trunk/Source
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r76371 r76372  
     12011-01-21  Adam Roben  <aroben@apple.com>
     2
     3        Separate flushing layer changes from rendering in CACFLayerTreeHost
     4
     5        Old model:
     6          1) A change is made to a GraphicsLayer.
     7          2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which schedules the
     8             render timer.
     9          3) The timer fires, which calls through to CACFLayerTreeHost::render, which performs the
     10             flush and then renders.
     11
     12        New model:
     13          1) A change is made to a GraphicsLayer.
     14          2) CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon is called, which tells the new
     15             LayerChangesFlusher singleton that this host has changes that need to be flushed.
     16          3) LayerChangesFlusher sets up a Windows hook that will get called on the next iteration
     17             of the message loop.
     18          4) LayerChangesFlusher's hook is called, which calls through to
     19             CACFLayerTreeHost::flushPendingLayerChangesNow.
     20          5) CACFLayerTreeHost::flushPendingLayerChangesNow schedules the render timer so the changes
     21             that were just flushed to the context will be rendered.
     22
     23        When a change is made to a PlatformCALayer that doesn't have a corresponding GraphicsLayer
     24        (e.g., for rendering <video>), CACFLayerTreeHost::layerTreeDidChange takes care of
     25        scheduling the flush.
     26
     27        This change has three advantages:
     28          1) Whenever we flush layer changes, we first update layout. This can cause the page to
     29             leave compositing mode, which in turn can cause all references to the CACFLayerTreeHost
     30             to be dropped. By separating flushing (and thus updating layout) from rendering, we no
     31             longer have to worry about this happen during rendering.
     32          2) The new model is much more similar to how things work on the Mac, so will hopefully
     33             reduce the number of platform-specific bugs.
     34          3) CACFLayerTreeHost::shouldRender, which was used to make sure we didn't render while a
     35             layout was pending, is no longer needed. It actually hasn't been needed since at least
     36             r75987, but removing it before now would have resulted in a crash whenever a page came
     37             out of compositing mode due to (1).
     38
     39        Fixes <http://webkit.org/b/52852> Flushing layer changes and rendering are intertwined in
     40        CACFLayerTreeHost, but shouldn't be
     41
     42        Reviewed by Simon Fraser.
     43
     44        * WebCore.vcproj/WebCore.vcproj: Added LayerChangesFlusher.
     45
     46        * platform/graphics/ca/win/CACFLayerTreeHost.cpp: Added new #include, sorted existing
     47        #includes.
     48        (WebCore::CACFLayerTreeHost::CACFLayerTreeHost): Initialize new member.
     49        (WebCore::CACFLayerTreeHost::layerTreeDidChange): If we aren't already flushing changes,
     50        schedule a flush. Removed the call to renderSoon(), which now happens when the flush is
     51        finished.
     52        (WebCore::CACFLayerTreeHost::destroyRenderer): Cancel any pending flush we had scheduled. Also
     53        fixed a bug where we'd fail to clear the context's layer.
     54        (WebCore::CACFLayerTreeHost::render): Removed code to ask the client if we should render, which
     55        is no longer needed. Moved code to flush layer changes from here to
     56        flushPendingLayerChangesNow, which is called via the above-described mechanism.
     57        (WebCore::CACFLayerTreeHost::flushPendingGraphicsLayerChangesSoon): Schedule a flush. Removed
     58        code to schedule a render, which now happens after we've flushed.
     59        (WebCore::CACFLayerTreeHost::flushPendingLayerChangesNow): Added. Some of this code came from
     60        render(). First we flush GraphicsLayer changes from GraphicsLayers to their underlying
     61        PlatformCALayers, then we flush changes from PlatformCALayers to the context, then we
     62        schedule a render so that the changes will be rendered to the screen.
     63
     64        * platform/graphics/ca/win/CACFLayerTreeHost.h: Removed
     65        CACFLayerTreeHostClient::shouldRender. Added flushPendingLayerChangesNow and
     66        m_isFlushingLayerChanges.
     67
     68        * platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.
     69        (WebCore::LayerChangesFlusher::shared):
     70        (WebCore::LayerChangesFlusher::LayerChangesFlusher):
     71        (WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon):
     72        (WebCore::LayerChangesFlusher::cancelPendingFlush):
     73        (WebCore::LayerChangesFlusher::hookCallback):
     74        (WebCore::LayerChangesFlusher::hookFired):
     75        (WebCore::LayerChangesFlusher::setHook):
     76        (WebCore::LayerChangesFlusher::removeHook):
     77
     78        * platform/graphics/ca/win/LayerChangesFlusher.cpp: Added.
     79        (WebCore::LayerChangesFlusher::shared): Returns the singleton.
     80        (WebCore::LayerChangesFlusher::LayerChangesFlusher): Initialize our members.
     81        (WebCore::LayerChangesFlusher::flushPendingLayerChangesSoon): Add the host to the set of
     82        hosts with changes that need to be flushed, and set up our hook if we haven't already.
     83        (WebCore::LayerChangesFlusher::cancelPendingFlush): Remove the host from the set of hosts
     84        with changes that need to be flushed. If we have no more such hosts, remove our hook, unless
     85        we're currently in the process of calling out to our hosts, in which case we'll take care of
     86        the hook once we're done calling out.
     87        (WebCore::LayerChangesFlusher::hookCallback): This is the function that Windows calls when
     88        our hook fires. Just calls through to hookFired on the singleton.
     89        (WebCore::LayerChangesFlusher::hookFired): Tell all the hosts with changes that needed to be
     90        flushed that it's time to flush. If no hosts re-added themselves to our set during this
     91        process, remove our hook.
     92        (WebCore::LayerChangesFlusher::setHook): Calls through to ::SetWindowsHookExW.
     93        (WebCore::LayerChangesFlusher::removeHook): Calls through to ::UnhookWindowsHookEx.
     94
     95        * platform/graphics/ca/win/LayerChangesFlusher.h: Added.
     96
    1972011-01-21  Simon Fraser  <simon.fraser@apple.com>
    298
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r76370 r76372  
    2889628896                                                </File>
    2889728897                                                <File
     28898                                                        RelativePath="..\platform\graphics\ca\win\LayerChangesFlusher.cpp"
     28899                                                        >
     28900                                                        <FileConfiguration
     28901                                                                Name="Debug_Cairo_CFLite|Win32"
     28902                                                                ExcludedFromBuild="true"
     28903                                                                >
     28904                                                                <Tool
     28905                                                                        Name="VCCLCompilerTool"
     28906                                                                />
     28907                                                        </FileConfiguration>
     28908                                                        <FileConfiguration
     28909                                                                Name="Release_Cairo_CFLite|Win32"
     28910                                                                ExcludedFromBuild="true"
     28911                                                                >
     28912                                                                <Tool
     28913                                                                        Name="VCCLCompilerTool"
     28914                                                                />
     28915                                                        </FileConfiguration>
     28916                                                </File>
     28917                                                <File
     28918                                                        RelativePath="..\platform\graphics\ca\win\LayerChangesFlusher.h"
     28919                                                        >
     28920                                                        <FileConfiguration
     28921                                                                Name="Debug_Cairo_CFLite|Win32"
     28922                                                                ExcludedFromBuild="true"
     28923                                                                >
     28924                                                                <Tool
     28925                                                                        Name="VCCustomBuildTool"
     28926                                                                />
     28927                                                        </FileConfiguration>
     28928                                                        <FileConfiguration
     28929                                                                Name="Release_Cairo_CFLite|Win32"
     28930                                                                ExcludedFromBuild="true"
     28931                                                                >
     28932                                                                <Tool
     28933                                                                        Name="VCCustomBuildTool"
     28934                                                                />
     28935                                                        </FileConfiguration>
     28936                                                </File>
     28937                                                <File
    2889828938                                                        RelativePath="..\platform\graphics\ca\win\PlatformCAAnimationWin.cpp"
    2889928939                                                        >
  • trunk/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.cpp

    r76370 r76372  
    2525
    2626#include "config.h"
     27#include "CACFLayerTreeHost.h"
    2728
    2829#if USE(ACCELERATED_COMPOSITING)
    2930
    30 #ifndef NDEBUG
    31 #define D3D_DEBUG_INFO
    32 #endif
    33 
    34 #include "CACFLayerTreeHost.h"
    35 
     31#include "LayerChangesFlusher.h"
    3632#include "PlatformCALayer.h"
    3733#include "WebCoreInstanceHandle.h"
     
    4440#include <wtf/PassOwnPtr.h>
    4541#include <wtf/StdLibExtras.h>
     42
     43#ifndef NDEBUG
     44#define D3D_DEBUG_INFO
     45#endif
     46
    4647#include <d3d9.h>
    4748#include <d3dx9.h>
     
    189190    , m_mustResetLostDeviceBeforeRendering(false)
    190191    , m_shouldFlushPendingGraphicsLayerChanges(false)
     192    , m_isFlushingLayerChanges(false)
    191193{
    192194    // Point the CACFContext to this
     
    261263void CACFLayerTreeHost::layerTreeDidChange()
    262264{
    263     renderSoon();
     265    if (m_isFlushingLayerChanges) {
     266        // The layer tree is changing as a result of flushing GraphicsLayer changes to their
     267        // underlying PlatformCALayers. We'll flush those changes to the context as part of that
     268        // process, so there's no need to schedule another flush here.
     269        return;
     270    }
     271
     272    // The layer tree is changing as a result of someone modifying a PlatformCALayer that doesn't
     273    // have a corresponding GraphicsLayer. Schedule a flush since we won't schedule one through the
     274    // normal GraphicsLayer mechanisms.
     275    LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
    264276}
    265277
     
    338350void CACFLayerTreeHost::destroyRenderer()
    339351{
    340     wkCACFContextSetLayer(m_context, m_rootLayer->platformLayer());
     352    LayerChangesFlusher::shared().cancelPendingFlush(this);
     353
     354    wkCACFContextSetLayer(m_context, 0);
    341355
    342356    wkCACFContextSetD3DDevice(m_context, 0);
     
    425439        return;
    426440    }
    427 
    428     if (m_client && !m_client->shouldRender()) {
    429         renderSoon();
    430         return;
    431     }
    432 
    433     if (m_shouldFlushPendingGraphicsLayerChanges) {
    434         m_client->flushPendingGraphicsLayerChanges();
    435         m_shouldFlushPendingGraphicsLayerChanges = false;
    436     }
    437 
    438     // Flush the root layer to the render tree.
    439     wkCACFContextFlush(m_context);
    440441
    441442    // All pending animations will have been started with the flush. Fire the animationStarted calls
     
    527528{
    528529    m_shouldFlushPendingGraphicsLayerChanges = true;
     530    LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
     531}
     532
     533void CACFLayerTreeHost::flushPendingLayerChangesNow()
     534{
     535    // Calling out to the client could cause our last reference to go away.
     536    RefPtr<CACFLayerTreeHost> protector(this);
     537
     538    m_isFlushingLayerChanges = true;
     539
     540    // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
     541    // requested.
     542    if (m_client && m_shouldFlushPendingGraphicsLayerChanges) {
     543        m_shouldFlushPendingGraphicsLayerChanges = false;
     544        m_client->flushPendingGraphicsLayerChanges();
     545    }
     546
     547    // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
     548    wkCACFContextFlush(m_context);
     549
    529550    renderSoon();
     551
     552    m_isFlushingLayerChanges = false;
    530553}
    531554
  • trunk/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h

    r76370 r76372  
    5353public:
    5454    virtual ~CACFLayerTreeHostClient() { }
    55     virtual bool shouldRender() const = 0;
    5655    virtual void flushPendingGraphicsLayerChanges() { }
    5756};
     
    7776    void resize();
    7877    void flushPendingGraphicsLayerChangesSoon();
     78    void flushPendingLayerChangesNow();
    7979
    8080protected:
     
    112112    bool m_mustResetLostDeviceBeforeRendering;
    113113    bool m_shouldFlushPendingGraphicsLayerChanges;
     114    bool m_isFlushingLayerChanges;
    114115    HashSet<RefPtr<PlatformCALayer> > m_pendingAnimatedLayers;
    115116
  • trunk/Source/WebKit/win/ChangeLog

    r76370 r76372  
     12011-01-20  Adam Roben  <aroben@apple.com>
     2
     3        Update for CACFLayerTreeHost changes
     4
     5        Fixes <http://webkit.org/b/52852> Flushing layer changes and rendering are intertwined in
     6        CACFLayerTreeHost, but shouldn't be
     7
     8        Reviewed by Simon Fraser.
     9
     10        * WebView.cpp:
     11        (WebView::paint): Changed to flush layer changes via CACFLayerTreeHost, which will call back
     12        to our own flushing function if needed.
     13
     14        * WebView.h: Removed shouldRender, which is no longer used or needed.
     15
    1162011-01-21  Adam Roben  <aroben@apple.com>
    217
  • trunk/Source/WebKit/win/WebView.cpp

    r76370 r76372  
    991991#if USE(ACCELERATED_COMPOSITING)
    992992    if (isAcceleratedCompositing()) {
    993         flushPendingGraphicsLayerChanges();
     993        m_layerTreeHost->flushPendingLayerChangesNow();
    994994        // Flushing might have taken us out of compositing mode.
    995995        if (isAcceleratedCompositing()) {
     
    65076507}
    65086508
    6509 bool WebView::shouldRender() const
    6510 {
    6511     Frame* coreFrame = core(m_mainFrame);
    6512     if (!coreFrame)
    6513         return true;
    6514     FrameView* frameView = coreFrame->view();
    6515     if (!frameView)
    6516         return true;
    6517 
    6518     return !frameView->layoutPending();
    6519 }
    6520 
    65216509void WebView::flushPendingGraphicsLayerChanges()
    65226510{
  • trunk/Source/WebKit/win/WebView.h

    r76370 r76372  
    949949
    950950    // CACFLayerTreeHostClient
    951     virtual bool shouldRender() const;
    952951    virtual void flushPendingGraphicsLayerChanges();
    953952#endif
Note: See TracChangeset for help on using the changeset viewer.