/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "CAD3DRenderer.h"

#include "Image.h"
#include "ImageConversion.h"
#include "InvertColorPS.h"
#include <CoreGraphics/CGSRegion.h>
#include <QuartzCore/CACFContext.h>
#include <QuartzCore/CARenderOGL.h>
#include <limits>
#include <string>
#include <wtf/RefPtr.h>

// Define strings from the HLSL effect that are referenced later
#define HLSL_TECHNIQUE "InvertColor"
#define SCENE_TEXTURE "sceneTexture"

typedef HRESULT (CALLBACK *LPFNDLL_Direct3DCreate9Ex)(UINT, void **);

namespace WKQCA {

static const DWORD customVertexFormat = D3DFVF_XYZRHW | D3DFVF_TEX1;

D3DPostProcessingContext::D3DPostProcessingContext(const CComPtr<IDirect3DTexture9>& sceneTexture, const CComPtr<IDirect3DVertexBuffer9>& overlayQuad)
    : m_sceneTexture(sceneTexture)
    , m_overlayQuad(overlayQuad)
{
}

static IDirect3D9* s_d3d;
static IDirect3D9* d3d()
{
    static bool initialized;

    if (initialized)
        return s_d3d;
    initialized = true;

    HMODULE d3dLibHandle = LoadLibrary(TEXT("d3d9.dll"));
    if (!d3dLibHandle)
        return nullptr;

    // AVFoundationCF requires us to create an IDirect3DDevice9Ex instead of an IDirect3DDevice9 for HW
    // video decoding to work, because  IDirect3DDevice9Ex::ResetEx() allows the HW decoder to persist
    // during a reset, while IDirect3DDevice9::Reset() requires that the HW decoder be destroyed.
    LPFNDLL_Direct3DCreate9Ex d3dCreate9Ex = (LPFNDLL_Direct3DCreate9Ex)GetProcAddress(d3dLibHandle, "Direct3DCreate9Ex");
    if (d3dCreate9Ex) {
        d3dCreate9Ex(D3D_SDK_VERSION, (void **)&s_d3d);

        if (s_d3d) {
            D3DCAPS9 caps;
            HRESULT hr = s_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
    
            // HW video decoding requires D3DCAPS2_DYNAMICTEXTURES, which not all d3d9 devices support,
            // so fall back to plain old IDirect3DDevice9 if it isn't available.
            if (!FAILED(hr) && (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES))
                return s_d3d;

            // Release the IDirect3DDevice9Ex, it doesn't have the features we require so we should 
            // allocate and use a plain old IDirect3D9.
            s_d3d->Release();
        }
    }

    s_d3d = Direct3DCreate9(D3D_SDK_VERSION);

    return s_d3d;
}

static D3DPRESENT_PARAMETERS initialPresentationParameters(const CGSize& size)
{
    D3DPRESENT_PARAMETERS parameters = {0};
    parameters.Windowed = TRUE;
    parameters.SwapEffect = D3DSWAPEFFECT_COPY;
    parameters.BackBufferCount = 1;
    parameters.BackBufferFormat = D3DFMT_UNKNOWN;
    parameters.BackBufferHeight = size.height;
    parameters.BackBufferWidth = size.width;
    parameters.MultiSampleType = D3DMULTISAMPLE_NONE;

    return parameters;
}

CAD3DRenderer& CAD3DRenderer::shared()
{
    static CAD3DRenderer& shared = *new CAD3DRenderer;
    return shared;
}

CAD3DRenderer::CAD3DRenderer()
{
}

CComPtr<IDirect3DSwapChain9> CAD3DRenderer::swapChain(CWindow window, const CGSize& size)
{
    auto locker = holdLock(m_lock);

    bool useDefaultSwapChain = false;

    if (!m_d3dDevice) {
        if (!initialize(window, size))
            return nullptr;
        ASSERT(m_d3dDevice);
        // Since we used this window to initialize the device, the device's default swap chain
        // should be associated with this window.
        useDefaultSwapChain = true;
    }

    if (m_deviceIsLost) {
        if (!resetD3DDevice(window, size))
            return nullptr;
        ASSERT(!m_deviceIsLost);
        // Since we used this window to reset the device, the device's default swap chain should be
        // associated with this window.
        useDefaultSwapChain = true;
    }

    if (useDefaultSwapChain) {
        CComPtr<IDirect3DSwapChain9> defaultSwapChain;
        if (SUCCEEDED(m_d3dDevice->GetSwapChain(0, &defaultSwapChain))) {
#if !ASSERT_DISABLED
            // Since we just initialized or reset the device, its default swap chain should be
            // associated with and sized to match this window.
            D3DPRESENT_PARAMETERS parameters;
            ASSERT(SUCCEEDED(defaultSwapChain->GetPresentParameters(&parameters)));
            ASSERT(parameters.hDeviceWindow == window);
            CRect clientRect;
            ASSERT(window.GetClientRect(clientRect));
            ASSERT(parameters.BackBufferHeight == clientRect.Height());
            ASSERT(parameters.BackBufferWidth == clientRect.Width());
#endif
            return defaultSwapChain;
        }
    }

    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters(size);
    parameters.hDeviceWindow = window;

    CComPtr<IDirect3DSwapChain9> result;
    if (FAILED(m_d3dDevice->CreateAdditionalSwapChain(&parameters, &result)))
        return nullptr;

    return result;
}

struct CustomVertex {
    // position
    float x;
    float y;
    float z;
    float rhw; // indicates that the position is already transformed to screen coordinates

    // texture coordinates
    float tu;
    float tv;
};

std::unique_ptr<D3DPostProcessingContext> CAD3DRenderer::createD3DPostProcessingContext(IDirect3DSwapChain9* swapChain, const CGSize& size)
{
    ASSERT_ARG(swapChain, swapChain);

    // Get the back buffer format of the swap chain; we want to create the scene texture using the same format.
    D3DPRESENT_PARAMETERS swapChainParameters;
    if (FAILED(swapChain->GetPresentParameters(&swapChainParameters)))
        return nullptr;

    // FIXME: We should fall back to software rendering if CreateTexture() returns D3DERR_OUTOFVIDEOMEMORY.
    CComPtr<IDirect3DTexture9> sceneTexture;
    HRESULT hr = m_d3dDevice->CreateTexture(size.width, size.height, 1, D3DUSAGE_RENDERTARGET, swapChainParameters.BackBufferFormat, D3DPOOL_DEFAULT, &sceneTexture, 0);
    if (FAILED(hr)) {
        ASSERT(hr != D3DERR_OUTOFVIDEOMEMORY);
        return nullptr;
    }

    // Create a quad in screen coordinates onto which sceneTexture will be
    // applied. In D3D, pixels are referenced from the center of a 1x1 cell, so
    // to properly encapsulate the cell we need to offset the quad boundaries by
    // 0.5 pixels.
    const float left = -0.5;
    const float right = size.width - 0.5;
    const float top = -0.5;
    const float bottom = size.height - 0.5;
    const float z = 1;
    const float rhw = 1;
    CustomVertex overlayQuadVertices[4] = {
        { left,  top,    z, rhw, 0, 0 },
        { right, top,    z, rhw, 1, 0 },
        { left,  bottom, z, rhw, 0, 1 },
        { right, bottom, z, rhw, 1, 1 }
    };

    CComPtr<IDirect3DVertexBuffer9> overlayQuad;
    if (FAILED(m_d3dDevice->CreateVertexBuffer(sizeof(overlayQuadVertices), D3DUSAGE_WRITEONLY, customVertexFormat, D3DPOOL_DEFAULT, &overlayQuad, 0)))
        return nullptr;

    void* overlayQuadBuffer;
    if (FAILED(overlayQuad->Lock(0, 0, &overlayQuadBuffer, 0)))
        return nullptr;

    memcpy(overlayQuadBuffer, overlayQuadVertices, sizeof(overlayQuadVertices));
    overlayQuad->Unlock();

    return makeUnique<D3DPostProcessingContext>(sceneTexture, overlayQuad);
}

// FIXME: <rdar://6507851> Share this code with CoreAnimation's
// CA::OGL::DX9Context::update function.
static bool hardwareCapabilitiesIndicateCoreAnimationSupport(const D3DCAPS9& caps)
{
    // CoreAnimation needs two or more texture units.
    if (caps.MaxTextureBlendStages < 2)
        return false;

    // CoreAnimation needs non-power-of-two textures.
    if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
        return false;

    // CoreAnimation needs vertex shader 2.0 or greater.
    if (D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 2)
        return false;

    // CoreAnimation needs pixel shader 2.0 or greater.
    if (D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion) < 2)
        return false;

    return true;
}

bool CAD3DRenderer::initialize(CWindow window, const CGSize& size)
{
#if !ASSERT_DISABLED
    if (!m_deviceThreadID)
        m_deviceThreadID = ::GetCurrentThreadId();
    // MSDN says that IDirect3D9::CreateDevice must "be called from the same thread that handles
    // window messages." <http://msdn.microsoft.com/en-us/library/bb147224(VS.85).aspx>.
    ASSERT(::GetCurrentThreadId() == m_deviceThreadID);
    ASSERT(::GetCurrentThreadId() == window.GetWindowThreadID());
#endif

    if (m_initialized)
        return m_d3dDevice;
    m_initialized = true;

    if (!d3d())
        return false;

    D3DCAPS9 d3dCaps;
    if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
        return false;

    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED;
    if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps)
        behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters(size);
    parameters.hDeviceWindow = window;

    CComPtr<IDirect3DDevice9> device;
    CComQIPtr<IDirect3D9Ex> d3d9Ex = d3d();
    HRESULT hr;

    if (d3d9Ex)
        hr = d3d9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, behaviorFlags, &parameters, 0, (IDirect3DDevice9Ex **)&device);
    else
        hr = s_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, behaviorFlags, &parameters, &device);
    if (FAILED(hr))
        return false;

    // Now that we've created the IDirect3DDevice9 based on the capabilities we
    // got from the IDirect3D9 global object, we requery the device for its
    // actual capabilities. The capabilities returned by the device can
    // sometimes be more complete, for example when using software vertex
    // processing.
    D3DCAPS9 deviceCaps;
    if (FAILED(device->GetDeviceCaps(&deviceCaps)))
        return false;

    if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))
        return false;

    m_d3dDevice.Attach(device.Detach());
    m_usingDirect3D9Ex = d3d9Ex;
    m_renderOGLContext = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice, 0);

    return true;
}

static void D3DMatrixOrthoOffCenterRH(D3DMATRIX* pOut, float l, float r, float b, float t, float zn, float zf)
{
    pOut->_11 = 2 / (r-l);
    pOut->_12 = 0;
    pOut->_13 = 0;
    pOut->_14 = 0;

    pOut->_21 = 0;
    pOut->_22 = 2 / (t-b);
    pOut->_23 = 0;
    pOut->_24 = 0;

    pOut->_31 = 0;
    pOut->_32 = 0;
    pOut->_33 = 1 / (zn-zf);
    pOut->_34 = 0;

    pOut->_41 = (l+r) / (l-r);
    pOut->_42 = (t+b) / (b-t);
    pOut->_43 = zn / (zn-zf);
    pOut->_44 = 1;
}

static bool prepareDevice(IDirect3DDevice9* device, const CGRect& bounds, IDirect3DSwapChain9* swapChain, D3DPostProcessingContext* postProcessingContext)
{
    CComPtr<IDirect3DSurface9> backBuffer;

    // If we will post-process the scene, we want to render to the scene texture rather than the back buffer.
    if (postProcessingContext) {
        if (FAILED(postProcessingContext->sceneTexture()->GetSurfaceLevel(0, &backBuffer)))
            return false;
    } else {
        if (FAILED(swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer)))
            return false;
    }

    CComPtr<IDirect3DSurface9> currentRenderTarget;
    if (FAILED(device->GetRenderTarget(0, &currentRenderTarget)))
        return false;

    if (backBuffer != currentRenderTarget && FAILED(device->SetRenderTarget(0, backBuffer)))
        return false;

    float x0 = bounds.origin.x;
    float y0 = bounds.origin.y;
    float x1 = x0 + bounds.size.width;
    float y1 = y0 + bounds.size.height;

    D3DMATRIX projection;
    D3DMatrixOrthoOffCenterRH(&projection, x0, x1, y0, y1, -1.0f, 1.0f);

    if (FAILED(device->SetTransform(D3DTS_PROJECTION, &projection)))
        return false;

    return true;
}

static CGRect updateBounds(CARenderUpdate* update)
{
    CGSRegionObj rgn = CARenderUpdateCopyRegion(update);
    if (!rgn)
        return CGRectZero;

    CGRect result;
    CGError error = CGSGetRegionBounds(rgn, &result);
    CGSReleaseRegion(rgn);

    return error == kCGErrorSuccess ? result : CGRectZero;
}

CAD3DRenderer::RenderResult CAD3DRenderer::renderAndPresent(const CGRect& bounds, IDirect3DSwapChain9* swapChain, D3DPostProcessingContext* postProcessingContext, CACFContextRef context, CFTimeInterval& nextRenderTime)
{
    ASSERT_ARG(swapChain, swapChain);
    ASSERT_ARG(context, context);

    auto locker = holdLock(m_lock);

    CGRect unusedDirtyRect;
    RenderResult result = renderInternal(bounds, swapChain, postProcessingContext, context, unusedDirtyRect, nextRenderTime);
    switch (result) {
    case DeviceBecameLost:
        ASSERT_NOT_REACHED();
    case DeviceIsLost:
    case OtherFailure:
        return result;
    case NoRenderingRequired:
    case Success:
        break;
    }

    // Note that we only use the bounds size, not its origin, when deciding where in the
    // window to render. As with NSViews, the bounds origin determines where content is
    // positioned within the view, not where the view is positioned in its parent.
    CRect destinationRect(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds));

    // FIXME: Passing a pDirtyRegion based on the CARenderUpdate's dirty region to
    // IDirect3DSwapChain9::Present might increase performance.
    if (swapChain->Present(0, destinationRect, 0, 0, 0) != D3DERR_DEVICELOST)
        return Success;

    // The device was lost. Record that this happened so that we'll try to reset it before
    // we try to create a new swap chain.
    setDeviceIsLost(true);

    // We can't render until the device is reset, which the caller will have to take care of.
    nextRenderTime = std::numeric_limits<CFTimeInterval>::infinity();

    return DeviceBecameLost;
}

CAD3DRenderer::RenderResult CAD3DRenderer::renderToImage(const CGRect& bounds, IDirect3DSwapChain9* swapChain, D3DPostProcessingContext* postProcessingContext, CACFContextRef context, RefPtr<Image>& outImage, CGPoint& imageOrigin, CFTimeInterval& nextRenderTime)
{
    ASSERT_ARG(swapChain, swapChain);
    ASSERT_ARG(context, context);

    auto locker = holdLock(m_lock);

    CGRect dirtyRect;
    RenderResult result = renderInternal(bounds, swapChain, postProcessingContext, context, dirtyRect, nextRenderTime);
    switch (result) {
    case DeviceBecameLost:
        ASSERT_NOT_REACHED();
    case DeviceIsLost:
    case OtherFailure:
    case NoRenderingRequired:
        return result;
    case Success:
        break;
    }

    ASSERT(!CGRectIsEmpty(dirtyRect));

    dirtyRect = CGRectIntersection(dirtyRect, bounds);
    CRect dirtyWinRect(CPoint(CGRectGetMinX(dirtyRect), CGRectGetHeight(bounds) - CGRectGetMaxY(dirtyRect)), CSize(CGRectGetWidth(dirtyRect), CGRectGetHeight(dirtyRect)));

    RefPtr<Image> image;
    HRESULT hr = getBackBufferRectAsImage(m_d3dDevice, swapChain, dirtyWinRect, image);
    if (SUCCEEDED(hr)) {
        outImage = WTFMove(image);
        imageOrigin = dirtyRect.origin;
        return Success;
    }

    if (hr != D3DERR_DEVICELOST)
        return OtherFailure;

    // The device was lost. Record that this happened so that we'll try to reset it before
    // we try to create a new swap chain.
    setDeviceIsLost(true);

    // We can't render until the device is reset, which the caller will have to take care of.
    nextRenderTime = std::numeric_limits<CFTimeInterval>::infinity();

    return DeviceBecameLost;
}

void CAD3DRenderer::setDeviceIsLost(bool lost)
{
    ASSERT_WITH_MESSAGE(!m_lock.tryLock(), "m_lock must be held when calling this function");

    if (m_deviceIsLost == lost)
        return;

    m_deviceIsLost = lost;

    if (!m_deviceIsLost)
        return;

    // We have to release any existing D3D resources before we try to reset the device.
    // We'll reallocate them as needed. See
    // <http://msdn.microsoft.com/en-us/library/bb174425(v=VS.85).aspx>.

    // This will cause CA to release its D3D resources.
    CARenderOGLPurge(m_renderOGLContext);
}

CAD3DRenderer::RenderResult CAD3DRenderer::renderInternal(const CGRect& bounds, IDirect3DSwapChain9* swapChain, D3DPostProcessingContext* postProcessingContext, CACFContextRef context, CGRect& dirtyRect, CFTimeInterval& nextRenderTime)
{
    ASSERT_ARG(swapChain, swapChain);
    ASSERT_ARG(context, context);

    ASSERT_WITH_MESSAGE(!m_lock.tryLock(), "m_lock must be held when calling this function");
    ASSERT(m_d3dDevice);
    ASSERT(m_renderOGLContext);

    nextRenderTime = std::numeric_limits<CFTimeInterval>::infinity();

    if (m_deviceIsLost)
        return DeviceIsLost;

    if (!prepareDevice(m_d3dDevice, bounds, swapChain, postProcessingContext))
        return OtherFailure;

    char space[4096];
    CARenderUpdate* u = CARenderUpdateBegin(space, sizeof(space), CACurrentMediaTime(), 0, 0, &bounds);
    if (!u)
        return OtherFailure;

    CARenderContext* renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(context));
    CARenderContextLock(renderContext);
    CARenderUpdateAddContext(u, renderContext);
    CARenderContextUnlock(renderContext);

    nextRenderTime = CARenderUpdateGetNextTime(u);

    bool didRender = false;

    dirtyRect = updateBounds(u);
    if (!CGRectIsEmpty(dirtyRect)) {
        m_d3dDevice->BeginScene();
        CARenderOGLRender(m_renderOGLContext, u);
        if (postProcessingContext)
            postProcess(bounds, swapChain, postProcessingContext);
        m_d3dDevice->EndScene();
        didRender = true;
    }

    CARenderUpdateFinish(u);

    return didRender ? Success : NoRenderingRequired;
}

void CAD3DRenderer::postProcess(const CGRect& bounds, IDirect3DSwapChain9* swapChain, D3DPostProcessingContext* context)
{
    // The scene has been rendered to the scene texture, so now draw a quad to
    // the back buffer and apply the scene texture to the quad with the
    // InvertColor HLSL technique.

    ASSERT_ARG(swapChain, swapChain);
    ASSERT_ARG(context, context);

    CComPtr<IDirect3DSurface9> backBuffer;
    if (FAILED(swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer)))
        return;

    if (FAILED(m_d3dDevice->SetRenderTarget(0, backBuffer)))
        return;

    if (FAILED(m_d3dDevice->SetFVF(customVertexFormat)))
        return;

    if (FAILED(m_d3dDevice->SetStreamSource(0, context->overlayQuad(), 0, sizeof(CustomVertex))))
        return;

    createShaderIfNeeded();

    m_d3dDevice->SetTexture(0, context->sceneTexture());
    m_d3dDevice->SetPixelShader(m_pixelShader);
    m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
    m_d3dDevice->SetPixelShader(nullptr);
}

bool CAD3DRenderer::resetD3DDevice(CWindow window, const CGSize& size)
{
    ASSERT(m_d3dDevice);
    ASSERT(m_renderOGLContext);
    ASSERT(m_deviceIsLost);

    // MSDN says that IDirect3DDevice9::Reset must "be called from the same thread that handles
    // window messages." <http://msdn.microsoft.com/en-us/library/bb147224(VS.85).aspx>.
    ASSERT(::GetCurrentThreadId() == m_deviceThreadID);
    ASSERT(::GetCurrentThreadId() == window.GetWindowThreadID());

    HRESULT hr = m_d3dDevice->TestCooperativeLevel();

    if (hr == D3DERR_DEVICELOST || hr == D3DERR_DRIVERINTERNALERROR) {
        // The device cannot be reset at this time. We'll try again later.
        return false;
    }

    setDeviceIsLost(false);

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

    // We can reset the device.

    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters(size);
    parameters.hDeviceWindow = window;
    if (m_usingDirect3D9Ex) {
        CComQIPtr<IDirect3DDevice9Ex> d3d9Ex = m_d3dDevice;
        ASSERT(d3d9Ex);
        hr = d3d9Ex->ResetEx(&parameters, nullptr);
    } else
        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);

    return true;
}


void CAD3DRenderer::createShaderIfNeeded()
{
    if (m_pixelShader)
        return;

    m_d3dDevice->CreatePixelShader(reinterpret_cast<const DWORD*>(g_ps20_InvertColorPS), &m_pixelShader);
}

void CAD3DRenderer::release()
{
    if (m_renderOGLContext)
        CARenderOGLDestroy(m_renderOGLContext);
    m_d3dDevice = nullptr;
    if (s_d3d)
        s_d3d->Release();
}

} // namespace WKQCA
