/*
 * Copyright 2000 Marcus Meissner
 * Copyright 2000 Peter Hunnisett
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"

#include <assert.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "d3d.h"
#include "ddraw.h"
#include "winerror.h"

#include "ddraw_private.h"
#include "d3d_private.h"
#include "mesa_private.h"
#include "main.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(ddraw);

HRESULT WINAPI
GL_IDirect3DImpl_1_EnumDevices(LPDIRECT3D iface,
			       LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
			       LPVOID lpUserArg)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);

    /* Call functions defined in d3ddevices.c */
    if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 1) != D3DENUMRET_OK)
	return D3D_OK;

    return D3D_OK;
}

HRESULT WINAPI
GL_IDirect3DImpl_3_2T_EnumDevices(LPDIRECT3D3 iface,
				  LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
				  LPVOID lpUserArg)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);

    /* Call functions defined in d3ddevices.c */
    if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 3) != D3DENUMRET_OK)
	return D3D_OK;

    return D3D_OK;
}

HRESULT WINAPI
GL_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
				     LPDIRECT3DLIGHT* lplpDirect3DLight,
				     IUnknown* pUnkOuter)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
    IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
    int fl;
    IDirect3DLightImpl *d3dlimpl;
    HRESULT ret_value;
    
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DLight, pUnkOuter);
    for (fl = 0; fl < MAX_LIGHTS; fl++) {
        if ((glThis->free_lights & (0x01 << fl)) != 0) {
	    glThis->free_lights &= ~(0x01 << fl);
	    break;
	}
    }
    if (fl == MAX_LIGHTS) {
        return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */
    }
    ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl);
    *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);

    return ret_value;
}

HRESULT WINAPI
GL_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
					LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
					IUnknown* pUnkOuter)
{
    IDirect3DMaterialImpl *D3Dmat_impl;
    HRESULT ret_value;
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
    
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
    ret_value = d3dmaterial_create(&D3Dmat_impl, This);

    *lplpDirect3DMaterial3 = ICOM_INTERFACE(D3Dmat_impl, IDirect3DMaterial3);

    return ret_value;
}

HRESULT WINAPI
GL_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
					LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
					IUnknown* pUnkOuter)
{
    IDirect3DViewportImpl *D3Dvp_impl;
    HRESULT ret_value;
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
    
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpD3DViewport3, pUnkOuter);
    ret_value = d3dviewport_create(&D3Dvp_impl, This);

    *lplpD3DViewport3 = ICOM_INTERFACE(D3Dvp_impl, IDirect3DViewport3);

    return ret_value;
}

static HRESULT
create_device_helper(IDirectDrawImpl *This,
		     REFCLSID iid,
		     IDirectDrawSurfaceImpl *lpDDS,
		     void **obj,
		     int version) {
    IDirect3DDeviceImpl *lpd3ddev;
    HRESULT ret_value;

    ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS);
    if (FAILED(ret_value)) return ret_value;
    
    if ((iid == NULL) ||
	(IsEqualGUID(&IID_D3DDEVICE_OpenGL, iid)) ||
	(IsEqualGUID(&IID_IDirect3DHALDevice, iid)) ||
	(IsEqualGUID(&IID_IDirect3DTnLHalDevice, iid)) ||
	(IsEqualGUID(&IID_IDirect3DRefDevice, iid))) {
        switch (version) {
	    case 1:
		*obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice);
	        TRACE(" returning OpenGL D3DDevice %p.\n", *obj);
		return D3D_OK;

	    case 2:
		*obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice2);
	        TRACE(" returning OpenGL D3DDevice2 %p.\n", *obj);
		return D3D_OK;

	    case 3:
		*obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice3);
	        TRACE(" returning OpenGL D3DDevice3 %p.\n", *obj);
		return D3D_OK;

	    case 7:
		*obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7);
	        TRACE(" returning OpenGL D3DDevice7 %p.\n", *obj);
		return D3D_OK;
        }
    }

    *obj = NULL;
    ERR(" Interface unknown when creating D3DDevice (%s)\n", debugstr_guid(iid));
    IDirect3DDevice7_Release(ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7));
    return DDERR_INVALIDPARAMS;
}
     

HRESULT WINAPI
GL_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
				REFCLSID rclsid,
				LPDIRECTDRAWSURFACE lpDDS,
				LPDIRECT3DDEVICE2* lplpD3DDevice2)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
    IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, lpDDS);
    TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice2);
    return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice2, 2);
}

HRESULT WINAPI
GL_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
				REFCLSID rclsid,
				LPDIRECTDRAWSURFACE4 lpDDS,
				LPDIRECT3DDEVICE3* lplpD3DDevice3,
				LPUNKNOWN lpUnk)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
    IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
    TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice3);
    return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice3, 3);
}

HRESULT WINAPI
GL_IDirect3DImpl_3_2T_1T_FindDevice(LPDIRECT3D3 iface,
				    LPD3DFINDDEVICESEARCH lpD3DDFS,
				    LPD3DFINDDEVICERESULT lpD3DFDR)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DDFS, lpD3DFDR);
    return d3ddevice_find(This, lpD3DDFS, lpD3DFDR);
}

HRESULT WINAPI
GL_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
					 REFCLSID riidDevice,
					 LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
					 LPVOID lpContext)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
    DDPIXELFORMAT pformat;
    
    TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);

    memset(&pformat, 0, sizeof(pformat));
    pformat.dwSize = sizeof(DDPIXELFORMAT);
    pformat.dwFourCC = 0;   
    TRACE("Enumerating dummy ZBuffer format (16 bits)\n");
    pformat.dwFlags = DDPF_ZBUFFER;
    pformat.u1.dwZBufferBitDepth = 16;
    pformat.u3.dwZBitMask =    0x0000FFFF;
    pformat.u5.dwRGBZBitMask = 0x0000FFFF;

    /* Whatever the return value, stop here.. */
    lpEnumCallback(&pformat, lpContext);
    
    return D3D_OK;
}

HRESULT WINAPI
GL_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
			       LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
			       LPVOID lpUserArg)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);

    if (d3ddevice_enumerate7(lpEnumDevicesCallback, lpUserArg) != D3DENUMRET_OK)
	return D3D_OK;
    
    return D3D_OK;
}

HRESULT WINAPI
GL_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
				REFCLSID rclsid,
				LPDIRECTDRAWSURFACE7 lpDDS,
				LPDIRECT3DDEVICE7* lplpD3DDevice)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
    IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
    TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice);
    return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice, 7);
}

HRESULT WINAPI
GL_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
					 LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
					 LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
					 DWORD dwFlags)
{
    ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
    IDirect3DVertexBufferImpl *vbimpl;
    HRESULT res;
    
    TRACE("(%p/%p)->(%p,%p,%08lx)\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);

    res = d3dvertexbuffer_create(&vbimpl, This, lpD3DVertBufDesc, dwFlags);

    *lplpD3DVertBuf = ICOM_INTERFACE(vbimpl, IDirect3DVertexBuffer7);
    
    return res;
}

static void light_released(IDirectDrawImpl *This, GLenum light_num)
{
    IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
    glThis->free_lights |= (light_num - GL_LIGHT0);
}

#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun)     (typeof(VTABLE_IDirect3D7.fun))
#else
# define XCAST(fun)     (void*)
#endif

ICOM_VTABLE(IDirect3D7) VTABLE_IDirect3D7 =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    XCAST(QueryInterface) Thunk_IDirect3DImpl_7_QueryInterface,
    XCAST(AddRef) Thunk_IDirect3DImpl_7_AddRef,
    XCAST(Release) Thunk_IDirect3DImpl_7_Release,
    XCAST(EnumDevices) GL_IDirect3DImpl_7_EnumDevices,
    XCAST(CreateDevice) GL_IDirect3DImpl_7_CreateDevice,
    XCAST(CreateVertexBuffer) GL_IDirect3DImpl_7_3T_CreateVertexBuffer,
    XCAST(EnumZBufferFormats) GL_IDirect3DImpl_7_3T_EnumZBufferFormats,
    XCAST(EvictManagedTextures) Main_IDirect3DImpl_7_3T_EvictManagedTextures,
};

#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
#undef XCAST
#endif


#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun)     (typeof(VTABLE_IDirect3D3.fun))
#else
# define XCAST(fun)     (void*)
#endif

ICOM_VTABLE(IDirect3D3) VTABLE_IDirect3D3 =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    XCAST(QueryInterface) Thunk_IDirect3DImpl_3_QueryInterface,
    XCAST(AddRef) Thunk_IDirect3DImpl_3_AddRef,
    XCAST(Release) Thunk_IDirect3DImpl_3_Release,
    XCAST(EnumDevices) GL_IDirect3DImpl_3_2T_EnumDevices,
    XCAST(CreateLight) GL_IDirect3DImpl_3_2T_1T_CreateLight,
    XCAST(CreateMaterial) GL_IDirect3DImpl_3_2T_1T_CreateMaterial,
    XCAST(CreateViewport) GL_IDirect3DImpl_3_2T_1T_CreateViewport,
    XCAST(FindDevice) GL_IDirect3DImpl_3_2T_1T_FindDevice,
    XCAST(CreateDevice) GL_IDirect3DImpl_3_CreateDevice,
    XCAST(CreateVertexBuffer) Thunk_IDirect3DImpl_3_CreateVertexBuffer,
    XCAST(EnumZBufferFormats) Thunk_IDirect3DImpl_3_EnumZBufferFormats,
    XCAST(EvictManagedTextures) Thunk_IDirect3DImpl_3_EvictManagedTextures,
};

#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
#undef XCAST
#endif


#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun)     (typeof(VTABLE_IDirect3D2.fun))
#else
# define XCAST(fun)     (void*)
#endif

ICOM_VTABLE(IDirect3D2) VTABLE_IDirect3D2 =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    XCAST(QueryInterface) Thunk_IDirect3DImpl_2_QueryInterface,
    XCAST(AddRef) Thunk_IDirect3DImpl_2_AddRef,
    XCAST(Release) Thunk_IDirect3DImpl_2_Release,
    XCAST(EnumDevices) Thunk_IDirect3DImpl_2_EnumDevices,
    XCAST(CreateLight) Thunk_IDirect3DImpl_2_CreateLight,
    XCAST(CreateMaterial) Thunk_IDirect3DImpl_2_CreateMaterial,
    XCAST(CreateViewport) Thunk_IDirect3DImpl_2_CreateViewport,
    XCAST(FindDevice) Thunk_IDirect3DImpl_2_FindDevice,
    XCAST(CreateDevice) GL_IDirect3DImpl_2_CreateDevice,
};

#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
#undef XCAST
#endif


#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun)     (typeof(VTABLE_IDirect3D.fun))
#else
# define XCAST(fun)     (void*)
#endif

ICOM_VTABLE(IDirect3D) VTABLE_IDirect3D =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    XCAST(QueryInterface) Thunk_IDirect3DImpl_1_QueryInterface,
    XCAST(AddRef) Thunk_IDirect3DImpl_1_AddRef,
    XCAST(Release) Thunk_IDirect3DImpl_1_Release,
    XCAST(Initialize) Main_IDirect3DImpl_1_Initialize,
    XCAST(EnumDevices) GL_IDirect3DImpl_1_EnumDevices,
    XCAST(CreateLight) Thunk_IDirect3DImpl_1_CreateLight,
    XCAST(CreateMaterial) Thunk_IDirect3DImpl_1_CreateMaterial,
    XCAST(CreateViewport) Thunk_IDirect3DImpl_1_CreateViewport,
    XCAST(FindDevice) Thunk_IDirect3DImpl_1_FindDevice,
};

#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
#undef XCAST
#endif

static HRESULT d3d_add_device(IDirectDrawImpl *This, IDirect3DDeviceImpl *device)
{
    if  (This->current_device == NULL) {
        /* Create delayed textures now that we have an OpenGL context...
	   For that, go through all surface attached to our DDraw object and create
	   OpenGL textures for all textures.. */
        IDirectDrawSurfaceImpl *surf = This->surfaces;

	while (surf != NULL) {
	    if (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
	        /* Found a texture.. Now create the OpenGL part */
	        d3dtexture_create(This, surf, FALSE, surf->mip_main);
	    }
	    surf = surf->next_ddraw;
	}
    }
    /* For the moment, only one device 'supported'... */
    This->current_device = device;

    return DD_OK;
}

static HRESULT d3d_remove_device(IDirectDrawImpl *This, IDirect3DDeviceImpl *device)
{
    This->current_device = NULL;
    return DD_OK;
}

HRESULT direct3d_create(IDirectDrawImpl *This)
{
    IDirect3DGLImpl *globject;
    
    globject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DGLImpl));
    if (globject == NULL) return DDERR_OUTOFMEMORY;

    This->d3d_create_texture = d3dtexture_create;
    This->d3d_added_device = d3d_add_device;
    This->d3d_removed_device = d3d_remove_device;

    ICOM_INIT_INTERFACE(This, IDirect3D,  VTABLE_IDirect3D);
    ICOM_INIT_INTERFACE(This, IDirect3D2, VTABLE_IDirect3D2);
    ICOM_INIT_INTERFACE(This, IDirect3D3, VTABLE_IDirect3D3);
    ICOM_INIT_INTERFACE(This, IDirect3D7, VTABLE_IDirect3D7);

    globject->free_lights = (0x01 << MAX_LIGHTS) - 1; /* There are, in total, 8 lights in OpenGL */
    globject->light_released = light_released;

    This->d3d_private = globject;

    TRACE(" creating Mesa private storage at %p.\n", globject);
    
    return D3D_OK;
}
