2 * Copyright 2000 Marcus Meissner
3 * Copyright 2000 Peter Hunnisett
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
36 #include "ddraw_private.h"
37 #include "d3d_private.h"
38 #include "mesa_private.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
46 GL_IDirect3DImpl_1_EnumDevices(LPDIRECT3D iface,
47 LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
50 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D, iface);
51 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
53 /* Call functions defined in d3ddevices.c */
54 if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 1) != D3DENUMRET_OK)
61 GL_IDirect3DImpl_3_2T_EnumDevices(LPDIRECT3D3 iface,
62 LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
65 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
66 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
68 /* Call functions defined in d3ddevices.c */
69 if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 3) != D3DENUMRET_OK)
76 GL_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
77 LPDIRECT3DLIGHT* lplpDirect3DLight,
80 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
81 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
83 IDirect3DLightImpl *d3dlimpl;
86 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DLight, pUnkOuter);
87 for (fl = 0; fl < MAX_LIGHTS; fl++) {
88 if ((glThis->free_lights & (0x01 << fl)) != 0) {
89 glThis->free_lights &= ~(0x01 << fl);
93 if (fl == MAX_LIGHTS) {
94 return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */
96 ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl);
97 *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);
103 GL_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
104 LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
107 IDirect3DMaterialImpl *D3Dmat_impl;
109 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
111 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
112 ret_value = d3dmaterial_create(&D3Dmat_impl, This);
114 *lplpDirect3DMaterial3 = ICOM_INTERFACE(D3Dmat_impl, IDirect3DMaterial3);
120 GL_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
121 LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
124 IDirect3DViewportImpl *D3Dvp_impl;
126 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
128 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpD3DViewport3, pUnkOuter);
129 ret_value = d3dviewport_create(&D3Dvp_impl, This);
131 *lplpD3DViewport3 = ICOM_INTERFACE(D3Dvp_impl, IDirect3DViewport3);
137 create_device_helper(IDirect3DImpl *This,
139 IDirectDrawSurfaceImpl *lpDDS,
142 IDirect3DDeviceImpl *lpd3ddev;
145 ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS);
146 if (FAILED(ret_value)) return ret_value;
149 (IsEqualGUID(&IID_D3DDEVICE_OpenGL, iid)) ||
150 (IsEqualGUID(&IID_IDirect3DHALDevice, iid)) ||
151 (IsEqualGUID(&IID_IDirect3DTnLHalDevice, iid)) ||
152 (IsEqualGUID(&IID_IDirect3DRefDevice, iid))) {
155 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice);
156 TRACE(" returning OpenGL D3DDevice %p.\n", *obj);
160 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice2);
161 TRACE(" returning OpenGL D3DDevice2 %p.\n", *obj);
165 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice3);
166 TRACE(" returning OpenGL D3DDevice3 %p.\n", *obj);
170 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7);
171 TRACE(" returning OpenGL D3DDevice7 %p.\n", *obj);
177 ERR(" Interface unknown when creating D3DDevice (%s)\n", debugstr_guid(iid));
178 IDirect3DDevice7_Release(ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7));
179 return DDERR_INVALIDPARAMS;
184 GL_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
186 LPDIRECTDRAWSURFACE lpDDS,
187 LPDIRECT3DDEVICE2* lplpD3DDevice2)
189 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D2, iface);
190 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, lpDDS);
191 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice2);
192 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice2, 2);
196 GL_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
198 LPDIRECTDRAWSURFACE4 lpDDS,
199 LPDIRECT3DDEVICE3* lplpD3DDevice3,
202 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
203 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
204 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice3);
205 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice3, 3);
209 GL_IDirect3DImpl_3_2T_1T_FindDevice(LPDIRECT3D3 iface,
210 LPD3DFINDDEVICESEARCH lpD3DDFS,
211 LPD3DFINDDEVICERESULT lpD3DFDR)
213 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
214 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DDFS, lpD3DFDR);
215 return d3ddevice_find(This, lpD3DDFS, lpD3DFDR);
219 GL_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
221 LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
224 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
225 DDPIXELFORMAT pformat;
227 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
229 memset(&pformat, 0, sizeof(pformat));
230 pformat.dwSize = sizeof(DDPIXELFORMAT);
231 pformat.dwFourCC = 0;
232 TRACE("Enumerating dummy ZBuffer format (16 bits)\n");
233 pformat.dwFlags = DDPF_ZBUFFER;
234 pformat.u1.dwZBufferBitDepth = 16;
235 pformat.u3.dwZBitMask = 0x0000FFFF;
236 pformat.u5.dwRGBZBitMask = 0x0000FFFF;
238 /* Whatever the return value, stop here.. */
239 lpEnumCallback(&pformat, lpContext);
245 GL_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
246 LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
249 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
250 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
252 if (d3ddevice_enumerate7(lpEnumDevicesCallback, lpUserArg) != D3DENUMRET_OK)
259 GL_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
261 LPDIRECTDRAWSURFACE7 lpDDS,
262 LPDIRECT3DDEVICE7* lplpD3DDevice)
264 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
265 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
266 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice);
267 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice, 7);
271 GL_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
272 LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
273 LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
276 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
277 IDirect3DVertexBufferImpl *vbimpl;
280 TRACE("(%p/%p)->(%p,%p,%08lx)\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);
282 res = d3dvertexbuffer_create(&vbimpl, This, lpD3DVertBufDesc, dwFlags);
284 *lplpD3DVertBuf = ICOM_INTERFACE(vbimpl, IDirect3DVertexBuffer7);
289 static void light_released(IDirect3DImpl *This, GLenum light_num)
291 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
292 glThis->free_lights |= (light_num - GL_LIGHT0);
295 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
296 # define XCAST(fun) (typeof(VTABLE_IDirect3D7.fun))
298 # define XCAST(fun) (void*)
301 ICOM_VTABLE(IDirect3D7) VTABLE_IDirect3D7 =
303 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
304 XCAST(QueryInterface) Main_IDirect3DImpl_7_3T_2T_1T_QueryInterface,
305 XCAST(AddRef) Main_IDirect3DImpl_7_3T_2T_1T_AddRef,
306 XCAST(Release) Main_IDirect3DImpl_7_3T_2T_1T_Release,
307 XCAST(EnumDevices) GL_IDirect3DImpl_7_EnumDevices,
308 XCAST(CreateDevice) GL_IDirect3DImpl_7_CreateDevice,
309 XCAST(CreateVertexBuffer) GL_IDirect3DImpl_7_3T_CreateVertexBuffer,
310 XCAST(EnumZBufferFormats) GL_IDirect3DImpl_7_3T_EnumZBufferFormats,
311 XCAST(EvictManagedTextures) Main_IDirect3DImpl_7_3T_EvictManagedTextures,
314 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
319 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
320 # define XCAST(fun) (typeof(VTABLE_IDirect3D3.fun))
322 # define XCAST(fun) (void*)
325 ICOM_VTABLE(IDirect3D3) VTABLE_IDirect3D3 =
327 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
328 XCAST(QueryInterface) Thunk_IDirect3DImpl_3_QueryInterface,
329 XCAST(AddRef) Thunk_IDirect3DImpl_3_AddRef,
330 XCAST(Release) Thunk_IDirect3DImpl_3_Release,
331 XCAST(EnumDevices) GL_IDirect3DImpl_3_2T_EnumDevices,
332 XCAST(CreateLight) GL_IDirect3DImpl_3_2T_1T_CreateLight,
333 XCAST(CreateMaterial) GL_IDirect3DImpl_3_2T_1T_CreateMaterial,
334 XCAST(CreateViewport) GL_IDirect3DImpl_3_2T_1T_CreateViewport,
335 XCAST(FindDevice) GL_IDirect3DImpl_3_2T_1T_FindDevice,
336 XCAST(CreateDevice) GL_IDirect3DImpl_3_CreateDevice,
337 XCAST(CreateVertexBuffer) Thunk_IDirect3DImpl_3_CreateVertexBuffer,
338 XCAST(EnumZBufferFormats) Thunk_IDirect3DImpl_3_EnumZBufferFormats,
339 XCAST(EvictManagedTextures) Thunk_IDirect3DImpl_3_EvictManagedTextures,
342 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
347 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
348 # define XCAST(fun) (typeof(VTABLE_IDirect3D2.fun))
350 # define XCAST(fun) (void*)
353 ICOM_VTABLE(IDirect3D2) VTABLE_IDirect3D2 =
355 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
356 XCAST(QueryInterface) Thunk_IDirect3DImpl_2_QueryInterface,
357 XCAST(AddRef) Thunk_IDirect3DImpl_2_AddRef,
358 XCAST(Release) Thunk_IDirect3DImpl_2_Release,
359 XCAST(EnumDevices) Thunk_IDirect3DImpl_2_EnumDevices,
360 XCAST(CreateLight) Thunk_IDirect3DImpl_2_CreateLight,
361 XCAST(CreateMaterial) Thunk_IDirect3DImpl_2_CreateMaterial,
362 XCAST(CreateViewport) Thunk_IDirect3DImpl_2_CreateViewport,
363 XCAST(FindDevice) Thunk_IDirect3DImpl_2_FindDevice,
364 XCAST(CreateDevice) GL_IDirect3DImpl_2_CreateDevice,
367 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
372 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
373 # define XCAST(fun) (typeof(VTABLE_IDirect3D.fun))
375 # define XCAST(fun) (void*)
378 ICOM_VTABLE(IDirect3D) VTABLE_IDirect3D =
380 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
381 XCAST(QueryInterface) Thunk_IDirect3DImpl_1_QueryInterface,
382 XCAST(AddRef) Thunk_IDirect3DImpl_1_AddRef,
383 XCAST(Release) Thunk_IDirect3DImpl_1_Release,
384 XCAST(Initialize) Main_IDirect3DImpl_1_Initialize,
385 XCAST(EnumDevices) GL_IDirect3DImpl_1_EnumDevices,
386 XCAST(CreateLight) Thunk_IDirect3DImpl_1_CreateLight,
387 XCAST(CreateMaterial) Thunk_IDirect3DImpl_1_CreateMaterial,
388 XCAST(CreateViewport) Thunk_IDirect3DImpl_1_CreateViewport,
389 XCAST(FindDevice) Thunk_IDirect3DImpl_1_FindDevice,
392 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
396 static HRESULT d3d_add_device(IDirect3DImpl *This, IDirect3DDeviceImpl *device)
398 if (This->current_device == NULL) {
399 /* Create delayed textures now that we have an OpenGL context...
400 For that, go through all surface attached to our DDraw object and create
401 OpenGL textures for all textures.. */
402 IDirectDrawSurfaceImpl *surf = This->ddraw->surfaces;
404 while (surf != NULL) {
405 if (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
406 /* Found a texture.. Now create the OpenGL part */
407 d3dtexture_create(This, surf, FALSE, surf->mip_main);
409 surf = surf->next_ddraw;
412 /* For the moment, only one device 'supported'... */
413 This->current_device = device;
418 static HRESULT d3d_remove_device(IDirect3DImpl *This, IDirect3DDeviceImpl *device)
420 This->current_device = NULL;
424 HRESULT direct3d_create(IDirect3DImpl **obj, IDirectDrawImpl *ddraw)
426 IDirect3DImpl *object;
427 IDirect3DGLImpl *globject;
429 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DGLImpl));
430 if (object == NULL) return DDERR_OUTOFMEMORY;
433 object->ddraw = ddraw;
434 object->create_texture = d3dtexture_create;
435 object->added_device = d3d_add_device;
436 object->removed_device = d3d_remove_device;
438 ICOM_INIT_INTERFACE(object, IDirect3D, VTABLE_IDirect3D);
439 ICOM_INIT_INTERFACE(object, IDirect3D2, VTABLE_IDirect3D2);
440 ICOM_INIT_INTERFACE(object, IDirect3D3, VTABLE_IDirect3D3);
441 ICOM_INIT_INTERFACE(object, IDirect3D7, VTABLE_IDirect3D7);
443 globject = (IDirect3DGLImpl *) object;
444 globject->free_lights = (0x01 << MAX_LIGHTS) - 1; /* There are, in total, 8 lights in OpenGL */
445 globject->light_released = light_released;
449 TRACE(" creating implementation at %p.\n", *obj);