Changeset 59610 in webkit


Ignore:
Timestamp:
May 17, 2010 8:04:36 AM (14 years ago)
Author:
Adam Roben
Message:

Periodically try to reset a lost IDirect3DDevice9 until we succeed

This is how MSDN says we must respond to a lost device (see
<http://msdn.microsoft.com/en-us/library/bb174714(v=VS.85).aspx>).

Only testable by a manual test, unfortunately.

Fixes <rdar://problem/7986906> <http://webkit.org/b/39139> Pages that
use hardware acceleration don't repaint after waking computer from
sleep

Reviewed by John Sullivan.

  • manual-tests/no-repaint-after-wake-from-sleep.html: Added. This is

the Poster Circle demo from webkit.org/blog, but with instructions for
putting the computer to sleep and waking it up again.

  • platform/graphics/win/WKCACFLayerRenderer.cpp:

(WebCore::WKCACFLayerRenderer::WKCACFLayerRenderer): Initialize new
member that tells us whether we need to try to reset the device before
rendering.
(WebCore::WKCACFLayerRenderer::resize): Changed to tell resetDevice
the reason why the device needs to be reset (which is because the
window's size has changed).
(WebCore::WKCACFLayerRenderer::render): Before we do anything else,
check if we need to reset the device before rendering. If we do, try
to reset it. If that fails, bail out and set a timer to try again
later. If we discover that the device is lost when calling
IDirect3DDevice9::Present and resetting the device fails, bail out and
set a timer to try again later.
(WebCore::WKCACFLayerRenderer::resetDevice): Changed to return a
boolean indicating whether resetting succeeded or not. Added a
ResetReason parameter so callers can specify whey the device needs to
be reset. Before trying to do anything, we call
IDirect3DDevice9::TestCooperativeLevel to find out whether the device
can be reset currently. If it can't, we set a flag to tell ourselves
that the device must be reset before we next render, and indicate to
the caller that the reset failed. If we thought the device was lost
but it turns out not to be, we don't have to do anything and can tell
the caller that the reset succeeded. Otherwise we go ahead and reset
the device as before, and indicate to the caller that the reset
succeeded.

  • platform/graphics/win/WKCACFLayerRenderer.h: Changed resetDevice to

return a boolean and take a ResetReason parameter. Added a comment
about when and why this function should be called. And added
m_mustResetLostDeviceBeforeRendering.

Location:
trunk/WebCore
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r59609 r59610  
     12010-05-15  Adam Roben  <aroben@apple.com>
     2
     3        Periodically try to reset a lost IDirect3DDevice9 until we succeed
     4
     5        This is how MSDN says we must respond to a lost device (see
     6        <http://msdn.microsoft.com/en-us/library/bb174714(v=VS.85).aspx>).
     7
     8        Only testable by a manual test, unfortunately.
     9
     10        Fixes <rdar://problem/7986906> <http://webkit.org/b/39139> Pages that
     11        use hardware acceleration don't repaint after waking computer from
     12        sleep
     13
     14        Reviewed by John Sullivan.
     15
     16        * manual-tests/no-repaint-after-wake-from-sleep.html: Added. This is
     17        the Poster Circle demo from webkit.org/blog, but with instructions for
     18        putting the computer to sleep and waking it up again.
     19
     20        * platform/graphics/win/WKCACFLayerRenderer.cpp:
     21        (WebCore::WKCACFLayerRenderer::WKCACFLayerRenderer): Initialize new
     22        member that tells us whether we need to try to reset the device before
     23        rendering.
     24        (WebCore::WKCACFLayerRenderer::resize): Changed to tell resetDevice
     25        the reason why the device needs to be reset (which is because the
     26        window's size has changed).
     27        (WebCore::WKCACFLayerRenderer::render): Before we do anything else,
     28        check if we need to reset the device before rendering. If we do, try
     29        to reset it. If that fails, bail out and set a timer to try again
     30        later. If we discover that the device is lost when calling
     31        IDirect3DDevice9::Present and resetting the device fails, bail out and
     32        set a timer to try again later.
     33        (WebCore::WKCACFLayerRenderer::resetDevice): Changed to return a
     34        boolean indicating whether resetting succeeded or not. Added a
     35        ResetReason parameter so callers can specify whey the device needs to
     36        be reset. Before trying to do anything, we call
     37        IDirect3DDevice9::TestCooperativeLevel to find out whether the device
     38        can be reset currently. If it can't, we set a flag to tell ourselves
     39        that the device must be reset before we next render, and indicate to
     40        the caller that the reset failed. If we thought the device was lost
     41        but it turns out not to be, we don't have to do anything and can tell
     42        the caller that the reset succeeded. Otherwise we go ahead and reset
     43        the device as before, and indicate to the caller that the reset
     44        succeeded.
     45
     46        * platform/graphics/win/WKCACFLayerRenderer.h: Changed resetDevice to
     47        return a boolean and take a ResetReason parameter. Added a comment
     48        about when and why this function should be called. And added
     49        m_mustResetLostDeviceBeforeRendering.
     50
    1512010-05-15  Adam Roben  <aroben@apple.com>
    252
  • trunk/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp

    r59609 r59610  
    232232    , m_scrollSize(1, 1)
    233233    , m_backingStoreDirty(false)
     234    , m_mustResetLostDeviceBeforeRendering(false)
    234235{
    235236#ifndef NDEBUG
     
    423424        return;
    424425
    425     resetDevice();
     426    // Resetting the device might fail here. But that's OK, because if it does it we will attempt to
     427    // reset the device the next time we try to render.
     428    resetDevice(ChangedWindowSize);
    426429
    427430    if (m_rootLayer) {
     
    491494{
    492495    ASSERT(m_d3dDevice);
     496
     497    if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) {
     498        // We can't reset the device right now. Try again soon.
     499        renderSoon();
     500        return;
     501    }
    493502
    494503    // Flush the root layer to the render tree.
     
    548557
    549558        if (err == D3DERR_DEVICELOST) {
    550             // Lost device situation.
    551             resetDevice();
    552559            CARenderUpdateAddRect(u, &bounds);
     560            if (!resetDevice(LostDevice)) {
     561                // We can't reset the device right now. Try again soon.
     562                renderSoon();
     563                return;
     564            }
    553565        }
    554566    } while (err == D3DERR_DEVICELOST);
     
    593605}
    594606
    595 void WKCACFLayerRenderer::resetDevice()
     607bool WKCACFLayerRenderer::resetDevice(ResetReason reason)
    596608{
    597609    ASSERT(m_d3dDevice);
     610    ASSERT(m_renderContext);
     611
     612    HRESULT hr = m_d3dDevice->TestCooperativeLevel();
     613
     614    if (hr == D3DERR_DEVICELOST || hr == D3DERR_DRIVERINTERNALERROR) {
     615        // The device cannot be reset at this time. Try again soon.
     616        m_mustResetLostDeviceBeforeRendering = true;
     617        return false;
     618    }
     619
     620    m_mustResetLostDeviceBeforeRendering = false;
     621
     622    if (reason == LostDevice && hr == D3D_OK) {
     623        // The device wasn't lost after all.
     624        return true;
     625    }
     626
     627    // We can reset the device.
    598628
    599629    // We have to purge the CARenderOGLContext whenever we reset the IDirect3DDevice9 in order to
     
    603633
    604634    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
    605     m_d3dDevice->Reset(&parameters);
     635    hr = m_d3dDevice->Reset(&parameters);
     636
     637    // TestCooperativeLevel told us the device may be reset now, so we should
     638    // not be told here that the device is lost.
     639    ASSERT(hr != D3DERR_DEVICELOST);
     640
    606641    initD3DGeometry();
     642
     643    return true;
    607644}
    608645
  • trunk/WebCore/platform/graphics/win/WKCACFLayerRenderer.h

    r58423 r59610  
    8585
    8686    void initD3DGeometry();
    87     void resetDevice();
     87
     88    // Call this when the device window has changed size or when IDirect3DDevice9::Present returns
     89    // D3DERR_DEVICELOST. Returns true if the device was recovered, false if rendering must be
     90    // aborted and reattempted soon.
     91    enum ResetReason { ChangedWindowSize, LostDevice };
     92    bool resetDevice(ResetReason);
    8893
    8994    void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
     
    105110    IntSize m_scrollSize;
    106111    bool m_backingStoreDirty;
     112    bool m_mustResetLostDeviceBeforeRendering;
    107113#ifndef NDEBUG
    108114    bool m_printTree;
Note: See TracChangeset for help on using the changeset viewer.