/*
* 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 **);

using namespace std;

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 std::make_unique<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 = 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 = 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 = 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
