Example #1
0
bool WKCACFLayerRenderer::resetDevice(ResetReason reason)
{
    ASSERT(m_d3dDevice);
    ASSERT(m_renderContext);

    HRESULT hr = m_d3dDevice->TestCooperativeLevel();

    if (hr == D3DERR_DEVICELOST || hr == D3DERR_DRIVERINTERNALERROR) {
        // The device cannot be reset at this time. Try again soon.
        m_mustResetLostDeviceBeforeRendering = true;
        return false;
    }

    m_mustResetLostDeviceBeforeRendering = false;

    if (reason == LostDevice && hr == D3D_OK) {
        // The device wasn't lost after all.
        return true;
    }

    // We can reset the device.

    // We have to purge the CARenderOGLContext whenever we reset the IDirect3DDevice9 in order to
    // destroy any D3DPOOL_DEFAULT resources that Core Animation has allocated (e.g., textures used
    // for mask layers). See <http://msdn.microsoft.com/en-us/library/bb174425(v=VS.85).aspx>.
    CARenderOGLPurge(m_renderer);

    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
    hr = m_d3dDevice->Reset(&parameters);

    // TestCooperativeLevel told us the device may be reset now, so we should
    // not be told here that the device is lost.
    ASSERT(hr != D3DERR_DEVICELOST);

    initD3DGeometry();

    return true;
}
void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
{
    ASSERT(m_d3dDevice);

    // Flush the root layer to the render tree.
    WKCACFContextFlusher::shared().flushAllContexts();

    CGRect bounds = this->bounds();

    CFTimeInterval t = CACurrentMediaTime();

    // Give the renderer some space to use. This needs to be valid until the
    // CARenderUpdateFinish() call below.
    char space[4096];
    CARenderUpdate* u = CARenderUpdateBegin(space, sizeof(space), t, 0, 0, &bounds);
    if (!u)
        return;

    CARenderContextLock(m_renderContext);
    CARenderUpdateAddContext(u, m_renderContext);
    CARenderContextUnlock(m_renderContext);

    for (size_t i = 0; i < dirtyRects.size(); ++i)
        CARenderUpdateAddRect(u, &dirtyRects[i]);

    HRESULT err = S_OK;
    do {
        CGSRegionObj rgn = CARenderUpdateCopyRegion(u);

        if (!rgn)
            break;

        // FIXME: don't need to clear dirty region if layer tree is opaque.

        Vector<D3DRECT, 64> rects;
        CGSRegionEnumeratorObj e = CGSRegionEnumerator(rgn);
        for (const CGRect* r = CGSNextRect(e); r; r = CGSNextRect(e)) {
            D3DRECT rect;
            rect.x1 = r->origin.x;
            rect.x2 = rect.x1 + r->size.width;
            rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height);
            rect.y2 = rect.y1 + r->size.height;

            rects.append(rect);
        }
        CGSReleaseRegionEnumerator(e);
        CGSReleaseRegion(rgn);

        if (rects.isEmpty())
            break;

        m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);

        m_d3dDevice->BeginScene();
        CARenderOGLRender(m_renderer, u);
        m_d3dDevice->EndScene();

        err = m_d3dDevice->Present(0, 0, 0, 0);

        if (err == D3DERR_DEVICELOST) {
            // Lost device situation.
            CARenderOGLPurge(m_renderer);
            resetDevice();
            CARenderUpdateAddRect(u, &bounds);
        }
    } while (err == D3DERR_DEVICELOST);

    CARenderUpdateFinish(u);

#ifndef NDEBUG
    if (m_printTree)
        m_rootLayer->printTree();
#endif
}