12fc2651226baac27029e38c9d6ef883fa32084dbSteve Block/*
22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2011 Apple Inc. All rights reserved.
32fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *
42fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Redistribution and use in source and binary forms, with or without
52fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * modification, are permitted provided that the following conditions
62fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * are met:
72fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 1. Redistributions of source code must retain the above copyright
82fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *    notice, this list of conditions and the following disclaimer.
92fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 2. Redistributions in binary form must reproduce the above copyright
102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *    notice, this list of conditions and the following disclaimer in the
112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *    documentation and/or other materials provided with the distribution.
122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *
132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block */
252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "config.h"
272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "LegacyCACFLayerTreeHost.h"
282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#if USE(ACCELERATED_COMPOSITING)
302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "PlatformCALayer.h"
3281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include <QuartzCore/CABase.h>
332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <WebKitSystemInterface/WebKitSystemInterface.h>
342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#ifndef NDEBUG
362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#define D3D_DEBUG_INFO
372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif
382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <d3d9.h>
402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <d3dx9.h>
412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#pragma comment(lib, "d3d9")
432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#pragma comment(lib, "d3dx9")
442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
452fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockusing namespace std;
462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
472fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocknamespace WebCore {
482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
492fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic IDirect3D9* s_d3d = 0;
502fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic IDirect3D9* d3d()
512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (s_d3d)
532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return s_d3d;
542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!LoadLibrary(TEXT("d3d9.dll")))
562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return 0;
572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    s_d3d = Direct3DCreate9(D3D_SDK_VERSION);
592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return s_d3d;
612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
632fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic D3DPRESENT_PARAMETERS initialPresentationParameters()
642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DPRESENT_PARAMETERS parameters = {0};
662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    parameters.Windowed = TRUE;
672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    parameters.SwapEffect = D3DSWAPEFFECT_COPY;
682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    parameters.BackBufferCount = 1;
692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    parameters.MultiSampleType = D3DMULTISAMPLE_NONE;
712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return parameters;
732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// FIXME: <rdar://6507851> Share this code with CoreAnimation.
762fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic bool hardwareCapabilitiesIndicateCoreAnimationSupport(const D3DCAPS9& caps)
772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // CoreAnimation needs two or more texture units.
792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (caps.MaxTextureBlendStages < 2)
802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // CoreAnimation needs non-power-of-two textures.
832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // CoreAnimation needs vertex shader 2.0 or greater.
872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 2)
882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // CoreAnimation needs pixel shader 2.0 or greater.
912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion) < 2)
922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return true;
952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
972fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockPassRefPtr<LegacyCACFLayerTreeHost> LegacyCACFLayerTreeHost::create()
982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return adoptRef(new LegacyCACFLayerTreeHost);
1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1022fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockLegacyCACFLayerTreeHost::LegacyCACFLayerTreeHost()
1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    : m_renderTimer(this, &LegacyCACFLayerTreeHost::renderTimerFired)
1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_context(wkCACFContextCreate())
1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_mightBeAbleToCreateDeviceLater(true)
1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_mustResetLostDeviceBeforeRendering(false)
1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#ifndef NDEBUG
1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    char* printTreeFlag = getenv("CA_PRINT_TREE");
1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_printTree = printTreeFlag && atoi(printTreeFlag);
1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif
1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1142fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockLegacyCACFLayerTreeHost::~LegacyCACFLayerTreeHost()
1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextDestroy(m_context);
1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::initializeContext(void* userData, PlatformCALayer* layer)
1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextSetUserData(m_context, userData);
1222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextSetLayer(m_context, layer->platformLayer());
1232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool LegacyCACFLayerTreeHost::createRenderer()
1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_d3dDevice || !m_mightBeAbleToCreateDeviceLater)
1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return m_d3dDevice;
1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_mightBeAbleToCreateDeviceLater = false;
1312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
1322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!d3d() || !::IsWindow(window()))
1342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
1382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // size eventually, and then the backbuffer size will get reset.
1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RECT rect;
1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    GetClientRect(window(), &rect);
1412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {
1432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        parameters.BackBufferWidth = 1;
1442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        parameters.BackBufferHeight = 1;
1452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DCAPS9 d3dCaps;
1482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
1502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE;
1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps)
1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    else
1552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
1562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    COMPtr<IDirect3DDevice9> device;
1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window(), behaviorFlags, &parameters, &device))) {
1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // In certain situations (e.g., shortly after waking from sleep), Direct3DCreate9() will
1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // return an IDirect3D9 for which IDirect3D9::CreateDevice will always fail. In case we
1612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // have one of these bad IDirect3D9s, get rid of it so we'll fetch a new one the next time
1622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // we want to call CreateDevice.
1632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        s_d3d->Release();
1642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        s_d3d = 0;
1652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // Even if we don't have a bad IDirect3D9, in certain situations (e.g., shortly after
1672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // waking from sleep), CreateDevice will fail, but will later succeed if called again.
1682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_mightBeAbleToCreateDeviceLater = true;
1692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Now that we've created the IDirect3DDevice9 based on the capabilities we
1742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // got from the IDirect3D9 global object, we requery the device for its
1752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // actual capabilities. The capabilities returned by the device can
1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // sometimes be more complete, for example when using software vertex
1772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // processing.
1782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DCAPS9 deviceCaps;
1792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (FAILED(device->GetDeviceCaps(&deviceCaps)))
1802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
1812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))
1832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
1842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_d3dDevice = device;
1862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    initD3DGeometry();
1882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextSetD3DDevice(m_context, m_d3dDevice.get());
1902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (IsWindow(window())) {
1922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        rootLayer()->setBounds(bounds());
1932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        flushContext();
1942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return true;
1972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1992fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::destroyRenderer()
2002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextSetLayer(m_context, 0);
2022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextSetD3DDevice(m_context, 0);
2042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_d3dDevice = 0;
2052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (s_d3d)
2062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        s_d3d->Release();
2072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    s_d3d = 0;
2092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_mightBeAbleToCreateDeviceLater = true;
2102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    CACFLayerTreeHost::destroyRenderer();
2122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2142fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::resize()
2152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!m_d3dDevice)
2172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
2182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Resetting the device might fail here. But that's OK, because if it does it we will attempt to
2202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // reset the device the next time we try to render.
2212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    resetDevice(ChangedWindowSize);
2222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (rootLayer()) {
2242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        rootLayer()->setBounds(bounds());
2252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        flushContext();
2262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
2272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2292fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::renderTimerFired(Timer<LegacyCACFLayerTreeHost>*)
2302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    paint();
2322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2342fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::paint()
2352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    createRenderer();
2372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!m_d3dDevice) {
2382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (m_mightBeAbleToCreateDeviceLater)
2392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            renderSoon();
2402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
2412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
2422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    CACFLayerTreeHost::paint();
2442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2462fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::render(const Vector<CGRect>& windowDirtyRects)
2472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(m_d3dDevice);
2492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) {
2512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // We can't reset the device right now. Try again soon.
2522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        renderSoon();
2532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
2542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
2552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    CGRect bounds = this->bounds();
2572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Give the renderer some space to use. This needs to be valid until the
2592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // wkCACFContextFinishUpdate() call below.
2602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    char space[4096];
2612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), CACurrentMediaTime(), bounds, windowDirtyRects.data(), windowDirtyRects.size()))
2622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
2632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    HRESULT err = S_OK;
2652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    CFTimeInterval timeToNextRender = numeric_limits<CFTimeInterval>::infinity();
2662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    do {
2682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // FIXME: don't need to clear dirty region if layer tree is opaque.
2692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context);
2712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!e)
2722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            break;
2732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        Vector<D3DRECT, 64> rects;
2752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) {
2762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            D3DRECT rect;
2772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            rect.x1 = r->origin.x;
2782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            rect.x2 = rect.x1 + r->size.width;
2792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height);
2802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            rect.y2 = rect.y1 + r->size.height;
2812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            rects.append(rect);
2832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
2842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        wkCACFUpdateRectEnumeratorRelease(e);
2852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        timeToNextRender = wkCACFContextGetNextUpdateTime(m_context);
2872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (rects.isEmpty())
2892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            break;
2902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);
2922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_d3dDevice->BeginScene();
2942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        wkCACFContextRenderUpdate(m_context);
2952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_d3dDevice->EndScene();
2962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        err = m_d3dDevice->Present(0, 0, 0, 0);
2982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (err == D3DERR_DEVICELOST) {
3002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            wkCACFContextAddUpdateRect(m_context, bounds);
3012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (!resetDevice(LostDevice)) {
3022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                // We can't reset the device right now. Try again soon.
3032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                renderSoon();
3042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                return;
3052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            }
3062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
3072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    } while (err == D3DERR_DEVICELOST);
3082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextFinishUpdate(m_context);
3102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#ifndef NDEBUG
3122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_printTree)
3132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        rootLayer()->printTree();
3142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif
3152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // If timeToNextRender is not infinity, it means animations are running, so queue up to render again
3172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (timeToNextRender != numeric_limits<CFTimeInterval>::infinity())
3182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        renderSoon();
3192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3212fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::renderSoon()
3222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!m_renderTimer.isActive())
3242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_renderTimer.startOneShot(0);
3252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3272fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::flushContext()
3282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextFlush(m_context);
3302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    contextDidChange();
3312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3332fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::contextDidChange()
3342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    renderSoon();
3362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    CACFLayerTreeHost::contextDidChange();
3372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3392fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockCFTimeInterval LegacyCACFLayerTreeHost::lastCommitTime() const
3402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return wkCACFContextGetLastCommitTime(m_context);
3422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3442fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid LegacyCACFLayerTreeHost::initD3DGeometry()
3452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(m_d3dDevice);
3472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    CGRect bounds = this->bounds();
3492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float x0 = bounds.origin.x;
3512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float y0 = bounds.origin.y;
3522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float x1 = x0 + bounds.size.width;
3532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float y1 = y0 + bounds.size.height;
3542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DXMATRIXA16 projection;
3562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DXMatrixOrthoOffCenterRH(&projection, x0, x1, y0, y1, -1.0f, 1.0f);
3572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
3592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3612fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool LegacyCACFLayerTreeHost::resetDevice(ResetReason reason)
3622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(m_d3dDevice);
3642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(m_context);
3652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    HRESULT hr = m_d3dDevice->TestCooperativeLevel();
3672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (hr == D3DERR_DEVICELOST || hr == D3DERR_DRIVERINTERNALERROR) {
3692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // The device cannot be reset at this time. Try again soon.
3702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_mustResetLostDeviceBeforeRendering = true;
3712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return false;
3722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
3732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_mustResetLostDeviceBeforeRendering = false;
3752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (reason == LostDevice && hr == D3D_OK) {
3772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // The device wasn't lost after all.
3782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return true;
3792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
3802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // We can reset the device.
3822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // We have to release the context's D3D resrouces whenever we reset the IDirect3DDevice9 in order to
3842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // destroy any D3DPOOL_DEFAULT resources that Core Animation has allocated (e.g., textures used
3852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // for mask layers). See <http://msdn.microsoft.com/en-us/library/bb174425(v=VS.85).aspx>.
3862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    wkCACFContextReleaseD3DResources(m_context);
3872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
3892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    hr = m_d3dDevice->Reset(&parameters);
3902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // TestCooperativeLevel told us the device may be reset now, so we should
3922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // not be told here that the device is lost.
3932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(hr != D3DERR_DEVICELOST);
3942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    initD3DGeometry();
3962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return true;
3982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
4002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} // namespace WebCore
4012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
4022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif // USE(ACCELERATED_COMPOSITING)
403