/*
 * IDirect3D8 implementation
 *
 * Copyright 2002-2004 Jason Edmeades
 * Copyright 2003-2004 Raphael Junqueira
 * Copyright 2004 Christian Costa
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <stdarg.h>

#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
#include "wine/unicode.h"

#include "d3d8_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d8);

static inline struct d3d8 *impl_from_IDirect3D8(IDirect3D8 *iface)
{
    return CONTAINING_RECORD(iface, struct d3d8, IDirect3D8_iface);
}

static HRESULT WINAPI d3d8_QueryInterface(IDirect3D8 *iface, REFIID riid, void **out)
{
    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);

    if (IsEqualGUID(riid, &IID_IDirect3D8)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
        IDirect3D8_AddRef(iface);
        *out = iface;
        return S_OK;
    }

    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));

    *out = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI d3d8_AddRef(IDirect3D8 *iface)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    ULONG refcount = InterlockedIncrement(&d3d8->refcount);

    TRACE("%p increasing refcount to %u.\n", iface, refcount);

    return refcount;
}

static ULONG WINAPI d3d8_Release(IDirect3D8 *iface)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    ULONG refcount = InterlockedDecrement(&d3d8->refcount);

    TRACE("%p decreasing refcount to %u.\n", iface, refcount);

    if (!refcount)
    {
        wined3d_mutex_lock();
        wined3d_decref(d3d8->wined3d);
        wined3d_mutex_unlock();

        HeapFree(GetProcessHeap(), 0, d3d8);
    }

    return refcount;
}

static HRESULT WINAPI d3d8_RegisterSoftwareDevice(IDirect3D8 *iface, void *init_function)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HRESULT hr;

    TRACE("iface %p, init_function %p.\n", iface, init_function);

    wined3d_mutex_lock();
    hr = wined3d_register_software_device(d3d8->wined3d, init_function);
    wined3d_mutex_unlock();

    return hr;
}

static UINT WINAPI d3d8_GetAdapterCount(IDirect3D8 *iface)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HRESULT hr;

    TRACE("iface %p.\n", iface);

    wined3d_mutex_lock();
    hr = wined3d_get_adapter_count(d3d8->wined3d);
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_GetAdapterIdentifier(IDirect3D8 *iface, UINT adapter,
        DWORD flags, D3DADAPTER_IDENTIFIER8 *identifier)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    struct wined3d_adapter_identifier adapter_id;
    HRESULT hr;

    TRACE("iface %p, adapter %u, flags %#x, identifier %p.\n",
            iface, adapter, flags, identifier);

    adapter_id.driver = identifier->Driver;
    adapter_id.driver_size = sizeof(identifier->Driver);
    adapter_id.description = identifier->Description;
    adapter_id.description_size = sizeof(identifier->Description);
    adapter_id.device_name = NULL; /* d3d9 only */
    adapter_id.device_name_size = 0; /* d3d9 only */

    wined3d_mutex_lock();
    hr = wined3d_get_adapter_identifier(d3d8->wined3d, adapter, flags, &adapter_id);
    wined3d_mutex_unlock();

    identifier->DriverVersion = adapter_id.driver_version;
    identifier->VendorId = adapter_id.vendor_id;
    identifier->DeviceId = adapter_id.device_id;
    identifier->SubSysId = adapter_id.subsystem_id;
    identifier->Revision = adapter_id.revision;
    memcpy(&identifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(identifier->DeviceIdentifier));
    identifier->WHQLLevel = adapter_id.whql_level;

    return hr;
}

static UINT WINAPI d3d8_GetAdapterModeCount(IDirect3D8 *iface, UINT adapter)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HRESULT hr;

    TRACE("iface %p, adapter %u.\n", iface, adapter);

    wined3d_mutex_lock();
    hr = wined3d_get_adapter_mode_count(d3d8->wined3d, adapter,
            WINED3DFMT_UNKNOWN, WINED3D_SCANLINE_ORDERING_UNKNOWN);
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_EnumAdapterModes(IDirect3D8 *iface, UINT adapter, UINT mode_idx, D3DDISPLAYMODE *mode)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    struct wined3d_display_mode wined3d_mode;
    HRESULT hr;

    TRACE("iface %p, adapter %u, mode_idx %u, mode %p.\n",
            iface, adapter, mode_idx, mode);

    wined3d_mutex_lock();
    hr = wined3d_enum_adapter_modes(d3d8->wined3d, adapter, WINED3DFMT_UNKNOWN,
            WINED3D_SCANLINE_ORDERING_UNKNOWN, mode_idx, &wined3d_mode);
    wined3d_mutex_unlock();

    if (SUCCEEDED(hr))
    {
        mode->Width = wined3d_mode.width;
        mode->Height = wined3d_mode.height;
        mode->RefreshRate = wined3d_mode.refresh_rate;
        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
    }

    return hr;
}

static HRESULT WINAPI d3d8_GetAdapterDisplayMode(IDirect3D8 *iface, UINT adapter, D3DDISPLAYMODE *mode)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    struct wined3d_display_mode wined3d_mode;
    HRESULT hr;

    TRACE("iface %p, adapter %u, mode %p.\n",
            iface, adapter, mode);

    wined3d_mutex_lock();
    hr = wined3d_get_adapter_display_mode(d3d8->wined3d, adapter, &wined3d_mode, NULL);
    wined3d_mutex_unlock();

    if (SUCCEEDED(hr))
    {
        mode->Width = wined3d_mode.width;
        mode->Height = wined3d_mode.height;
        mode->RefreshRate = wined3d_mode.refresh_rate;
        mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
    }

    return hr;
}

static HRESULT WINAPI d3d8_CheckDeviceType(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
        D3DFORMAT display_format, D3DFORMAT backbuffer_format, BOOL windowed)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HRESULT hr;

    TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n",
            iface, adapter, device_type, display_format, backbuffer_format, windowed);

    wined3d_mutex_lock();
    hr = wined3d_check_device_type(d3d8->wined3d, adapter, device_type, wined3dformat_from_d3dformat(display_format),
            wined3dformat_from_d3dformat(backbuffer_format), windowed);
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_CheckDeviceFormat(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
        D3DFORMAT adapter_format, DWORD usage, D3DRESOURCETYPE resource_type, D3DFORMAT format)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    enum wined3d_resource_type wined3d_rtype;
    HRESULT hr;

    TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n",
            iface, adapter, device_type, adapter_format, usage, resource_type, format);

    switch (resource_type)
    {
        case D3DRTYPE_VERTEXBUFFER:
        case D3DRTYPE_INDEXBUFFER:
            wined3d_rtype = WINED3D_RTYPE_BUFFER;
            break;

        default:
            wined3d_rtype = resource_type;
            break;
    }

    wined3d_mutex_lock();
    hr = wined3d_check_device_format(d3d8->wined3d, adapter, device_type, wined3dformat_from_d3dformat(adapter_format),
            usage, wined3d_rtype, wined3dformat_from_d3dformat(format), WINED3D_SURFACE_TYPE_OPENGL);
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_CheckDeviceMultiSampleType(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
        D3DFORMAT format, BOOL windowed, D3DMULTISAMPLE_TYPE multisample_type)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HRESULT hr;

    TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x.\n",
            iface, adapter, device_type, format, windowed, multisample_type);

    wined3d_mutex_lock();
    hr = wined3d_check_device_multisample_type(d3d8->wined3d, adapter, device_type,
            wined3dformat_from_d3dformat(format), windowed,
            (enum wined3d_multisample_type)multisample_type, NULL);
    wined3d_mutex_unlock();

    return hr;
}

static HRESULT WINAPI d3d8_CheckDepthStencilMatch(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type,
        D3DFORMAT adapter_format, D3DFORMAT rt_format, D3DFORMAT ds_format)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HRESULT hr;

    TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n",
            iface, adapter, device_type, adapter_format, rt_format, ds_format);

    wined3d_mutex_lock();
    hr = wined3d_check_depth_stencil_match(d3d8->wined3d, adapter, device_type,
            wined3dformat_from_d3dformat(adapter_format), wined3dformat_from_d3dformat(rt_format),
            wined3dformat_from_d3dformat(ds_format));
    wined3d_mutex_unlock();

    return hr;
}

void fixup_caps(WINED3DCAPS *caps)
{
    /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */
    if (caps->PixelShaderVersion)
        caps->PixelShaderVersion = D3DPS_VERSION(1,4);
    else
        caps->PixelShaderVersion = D3DPS_VERSION(0,0);
    if (caps->VertexShaderVersion)
        caps->VertexShaderVersion = D3DVS_VERSION(1,1);
    else
        caps->VertexShaderVersion = D3DVS_VERSION(0,0);
    caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst);

    caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED;
}

static HRESULT WINAPI d3d8_GetDeviceCaps(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, D3DCAPS8 *caps)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    WINED3DCAPS *wined3d_caps;
    HRESULT hr;

    TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface, adapter, device_type, caps);

    if (!caps)
        return D3DERR_INVALIDCALL;

    if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps))))
        return D3DERR_INVALIDCALL;

    wined3d_mutex_lock();
    hr = wined3d_get_device_caps(d3d8->wined3d, adapter, device_type, wined3d_caps);
    wined3d_mutex_unlock();

    fixup_caps(wined3d_caps);
    WINECAPSTOD3D8CAPS(caps, wined3d_caps)
    HeapFree(GetProcessHeap(), 0, wined3d_caps);

    return hr;
}

static HMONITOR WINAPI d3d8_GetAdapterMonitor(IDirect3D8 *iface, UINT adapter)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    HMONITOR ret;

    TRACE("iface %p, adapter %u.\n", iface, adapter);

    wined3d_mutex_lock();
    ret = wined3d_get_adapter_monitor(d3d8->wined3d, adapter);
    wined3d_mutex_unlock();

    return ret;
}

static HRESULT WINAPI d3d8_CreateDevice(IDirect3D8 *iface, UINT adapter,
        D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters,
        IDirect3DDevice8 **device)
{
    struct d3d8 *d3d8 = impl_from_IDirect3D8(iface);
    struct d3d8_device *object;
    HRESULT hr;

    TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, device %p.\n",
            iface, adapter, device_type, focus_window, flags, parameters, device);

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate device memory.\n");
        return E_OUTOFMEMORY;
    }

    hr = device_init(object, d3d8, d3d8->wined3d, adapter, device_type, focus_window, flags, parameters);
    if (FAILED(hr))
    {
        WARN("Failed to initialize device, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created device %p.\n", object);
    *device = &object->IDirect3DDevice8_iface;

    return D3D_OK;
}

static const struct IDirect3D8Vtbl d3d8_vtbl =
{
    /* IUnknown */
    d3d8_QueryInterface,
    d3d8_AddRef,
    d3d8_Release,
    /* IDirect3D8 */
    d3d8_RegisterSoftwareDevice,
    d3d8_GetAdapterCount,
    d3d8_GetAdapterIdentifier,
    d3d8_GetAdapterModeCount,
    d3d8_EnumAdapterModes,
    d3d8_GetAdapterDisplayMode,
    d3d8_CheckDeviceType,
    d3d8_CheckDeviceFormat,
    d3d8_CheckDeviceMultiSampleType,
    d3d8_CheckDepthStencilMatch,
    d3d8_GetDeviceCaps,
    d3d8_GetAdapterMonitor,
    d3d8_CreateDevice,
};

BOOL d3d8_init(struct d3d8 *d3d8)
{
    d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl;
    d3d8->refcount = 1;

    wined3d_mutex_lock();
    d3d8->wined3d = wined3d_create(8, WINED3D_LEGACY_DEPTH_BIAS);
    wined3d_mutex_unlock();
    if (!d3d8->wined3d)
        return FALSE;

    return TRUE;
}
