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
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
41 #include "ddraw_private.h"
42 #include "d3d_private.h"
43 #include "opengl_private.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
50 GL_IDirect3DImpl_1_EnumDevices(LPDIRECT3D iface,
51 LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
54 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
55 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
57 /* Call functions defined in d3ddevices.c */
58 if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 1) != D3DENUMRET_OK)
65 GL_IDirect3DImpl_2_EnumDevices(LPDIRECT3D2 iface,
66 LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
69 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
70 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
72 /* Call functions defined in d3ddevices.c */
73 if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 2) != D3DENUMRET_OK)
80 GL_IDirect3DImpl_3_EnumDevices(LPDIRECT3D3 iface,
81 LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
84 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
85 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
87 /* Call functions defined in d3ddevices.c */
88 if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 3) != D3DENUMRET_OK)
95 GL_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
96 LPDIRECT3DLIGHT* lplpDirect3DLight,
99 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
100 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This->d3d_private;
102 IDirect3DLightImpl *d3dlimpl;
105 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DLight, pUnkOuter);
106 for (fl = 0; fl < MAX_LIGHTS; fl++) {
107 if ((glThis->free_lights & (0x01 << fl)) != 0) {
108 glThis->free_lights &= ~(0x01 << fl);
112 if (fl == MAX_LIGHTS) {
113 return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */
115 ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl);
116 *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);
122 GL_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
123 LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
126 IDirect3DMaterialImpl *D3Dmat_impl;
128 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
130 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
131 ret_value = d3dmaterial_create(&D3Dmat_impl, This);
133 *lplpDirect3DMaterial3 = ICOM_INTERFACE(D3Dmat_impl, IDirect3DMaterial3);
139 GL_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
140 LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
143 IDirect3DViewportImpl *D3Dvp_impl;
145 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
147 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpD3DViewport3, pUnkOuter);
148 ret_value = d3dviewport_create(&D3Dvp_impl, This);
150 *lplpD3DViewport3 = ICOM_INTERFACE(D3Dvp_impl, IDirect3DViewport3);
156 create_device_helper(IDirectDrawImpl *This,
158 IDirectDrawSurfaceImpl *lpDDS,
161 IDirect3DDeviceImpl *lpd3ddev;
164 ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS, version);
165 if (FAILED(ret_value)) return ret_value;
168 (IsEqualGUID(&IID_D3DDEVICE_OpenGL, iid)) ||
169 (IsEqualGUID(&IID_IDirect3DHALDevice, iid)) ||
170 (IsEqualGUID(&IID_IDirect3DTnLHalDevice, iid)) ||
171 (IsEqualGUID(&IID_IDirect3DRGBDevice, iid)) ||
172 (IsEqualGUID(&IID_IDirect3DRefDevice, iid))) {
175 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice);
176 TRACE(" returning OpenGL D3DDevice %p.\n", *obj);
180 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice2);
181 TRACE(" returning OpenGL D3DDevice2 %p.\n", *obj);
185 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice3);
186 TRACE(" returning OpenGL D3DDevice3 %p.\n", *obj);
190 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7);
191 TRACE(" returning OpenGL D3DDevice7 %p.\n", *obj);
197 ERR(" Interface unknown when creating D3DDevice (%s)\n", debugstr_guid(iid));
198 IDirect3DDevice7_Release(ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7));
199 return DDERR_INVALIDPARAMS;
204 GL_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
206 LPDIRECTDRAWSURFACE lpDDS,
207 LPDIRECT3DDEVICE2* lplpD3DDevice2)
209 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
210 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, lpDDS);
211 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice2);
212 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice2, 2);
216 GL_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
218 LPDIRECTDRAWSURFACE4 lpDDS,
219 LPDIRECT3DDEVICE3* lplpD3DDevice3,
222 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
223 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
224 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice3);
225 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice3, 3);
229 GL_IDirect3DImpl_3_2T_1T_FindDevice(LPDIRECT3D3 iface,
230 LPD3DFINDDEVICESEARCH lpD3DDFS,
231 LPD3DFINDDEVICERESULT lpD3DFDR)
233 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
234 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DDFS, lpD3DFDR);
235 return d3ddevice_find(This, lpD3DDFS, lpD3DFDR);
239 GL_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
241 LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
244 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
245 DDPIXELFORMAT pformat;
247 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
249 memset(&pformat, 0, sizeof(pformat));
250 pformat.dwSize = sizeof(DDPIXELFORMAT);
251 pformat.dwFourCC = 0;
252 TRACE("Enumerating dummy ZBuffer format (16 bits)\n");
253 pformat.dwFlags = DDPF_ZBUFFER;
254 pformat.u1.dwZBufferBitDepth = 16;
255 pformat.u3.dwZBitMask = 0x0000FFFF;
256 pformat.u5.dwRGBZBitMask = 0x0000FFFF;
258 /* Whatever the return value, stop here.. */
259 lpEnumCallback(&pformat, lpContext);
265 GL_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
266 LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
269 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
270 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
272 if (d3ddevice_enumerate7(lpEnumDevicesCallback, lpUserArg) != D3DENUMRET_OK)
279 GL_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
281 LPDIRECTDRAWSURFACE7 lpDDS,
282 LPDIRECT3DDEVICE7* lplpD3DDevice)
284 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
285 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
286 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice);
287 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice, 7);
291 GL_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
292 LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
293 LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
296 ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
297 IDirect3DVertexBufferImpl *vbimpl;
300 TRACE("(%p/%p)->(%p,%p,%08lx)\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);
302 res = d3dvertexbuffer_create(&vbimpl, This, lpD3DVertBufDesc, dwFlags);
304 *lplpD3DVertBuf = ICOM_INTERFACE(vbimpl, IDirect3DVertexBuffer7);
309 static void light_released(IDirectDrawImpl *This, GLenum light_num)
311 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This->d3d_private;
312 glThis->free_lights |= (light_num - GL_LIGHT0);
315 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
316 # define XCAST(fun) (typeof(VTABLE_IDirect3D7.fun))
318 # define XCAST(fun) (void*)
321 static const IDirect3D7Vtbl VTABLE_IDirect3D7 =
323 XCAST(QueryInterface) Thunk_IDirect3DImpl_7_QueryInterface,
324 XCAST(AddRef) Thunk_IDirect3DImpl_7_AddRef,
325 XCAST(Release) Thunk_IDirect3DImpl_7_Release,
326 XCAST(EnumDevices) GL_IDirect3DImpl_7_EnumDevices,
327 XCAST(CreateDevice) GL_IDirect3DImpl_7_CreateDevice,
328 XCAST(CreateVertexBuffer) GL_IDirect3DImpl_7_3T_CreateVertexBuffer,
329 XCAST(EnumZBufferFormats) GL_IDirect3DImpl_7_3T_EnumZBufferFormats,
330 XCAST(EvictManagedTextures) Main_IDirect3DImpl_7_3T_EvictManagedTextures,
333 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
338 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
339 # define XCAST(fun) (typeof(VTABLE_IDirect3D3.fun))
341 # define XCAST(fun) (void*)
344 static const IDirect3D3Vtbl VTABLE_IDirect3D3 =
346 XCAST(QueryInterface) Thunk_IDirect3DImpl_3_QueryInterface,
347 XCAST(AddRef) Thunk_IDirect3DImpl_3_AddRef,
348 XCAST(Release) Thunk_IDirect3DImpl_3_Release,
349 XCAST(EnumDevices) GL_IDirect3DImpl_3_EnumDevices,
350 XCAST(CreateLight) GL_IDirect3DImpl_3_2T_1T_CreateLight,
351 XCAST(CreateMaterial) GL_IDirect3DImpl_3_2T_1T_CreateMaterial,
352 XCAST(CreateViewport) GL_IDirect3DImpl_3_2T_1T_CreateViewport,
353 XCAST(FindDevice) GL_IDirect3DImpl_3_2T_1T_FindDevice,
354 XCAST(CreateDevice) GL_IDirect3DImpl_3_CreateDevice,
355 XCAST(CreateVertexBuffer) Thunk_IDirect3DImpl_3_CreateVertexBuffer,
356 XCAST(EnumZBufferFormats) Thunk_IDirect3DImpl_3_EnumZBufferFormats,
357 XCAST(EvictManagedTextures) Thunk_IDirect3DImpl_3_EvictManagedTextures,
360 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
365 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
366 # define XCAST(fun) (typeof(VTABLE_IDirect3D2.fun))
368 # define XCAST(fun) (void*)
371 static const IDirect3D2Vtbl VTABLE_IDirect3D2 =
373 XCAST(QueryInterface) Thunk_IDirect3DImpl_2_QueryInterface,
374 XCAST(AddRef) Thunk_IDirect3DImpl_2_AddRef,
375 XCAST(Release) Thunk_IDirect3DImpl_2_Release,
376 XCAST(EnumDevices) GL_IDirect3DImpl_2_EnumDevices,
377 XCAST(CreateLight) Thunk_IDirect3DImpl_2_CreateLight,
378 XCAST(CreateMaterial) Thunk_IDirect3DImpl_2_CreateMaterial,
379 XCAST(CreateViewport) Thunk_IDirect3DImpl_2_CreateViewport,
380 XCAST(FindDevice) Thunk_IDirect3DImpl_2_FindDevice,
381 XCAST(CreateDevice) GL_IDirect3DImpl_2_CreateDevice,
384 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
389 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
390 # define XCAST(fun) (typeof(VTABLE_IDirect3D.fun))
392 # define XCAST(fun) (void*)
395 static const IDirect3DVtbl VTABLE_IDirect3D =
397 XCAST(QueryInterface) Thunk_IDirect3DImpl_1_QueryInterface,
398 XCAST(AddRef) Thunk_IDirect3DImpl_1_AddRef,
399 XCAST(Release) Thunk_IDirect3DImpl_1_Release,
400 XCAST(Initialize) Main_IDirect3DImpl_1_Initialize,
401 XCAST(EnumDevices) GL_IDirect3DImpl_1_EnumDevices,
402 XCAST(CreateLight) Thunk_IDirect3DImpl_1_CreateLight,
403 XCAST(CreateMaterial) Thunk_IDirect3DImpl_1_CreateMaterial,
404 XCAST(CreateViewport) Thunk_IDirect3DImpl_1_CreateViewport,
405 XCAST(FindDevice) Thunk_IDirect3DImpl_1_FindDevice,
408 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
412 static HRESULT d3d_add_device(IDirectDrawImpl *This, IDirect3DDeviceImpl *device)
414 if (This->current_device == NULL) {
415 /* Create delayed textures now that we have an OpenGL context...
416 For that, go through all surface attached to our DDraw object and create
417 OpenGL textures for all textures.. */
418 IDirectDrawSurfaceImpl *surf = This->surfaces;
420 while (surf != NULL) {
421 if (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
422 /* Found a texture.. Now create the OpenGL part */
423 d3dtexture_create(This, surf, FALSE, surf->mip_main);
425 surf = surf->next_ddraw;
428 /* For the moment, only one device 'supported'... */
429 This->current_device = device;
434 static HRESULT d3d_remove_device(IDirectDrawImpl *This, IDirect3DDeviceImpl *device)
436 This->current_device = NULL;
440 HRESULT direct3d_create(IDirectDrawImpl *This)
442 IDirect3DGLImpl *globject;
444 globject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DGLImpl));
445 if (globject == NULL) return DDERR_OUTOFMEMORY;
447 This->d3d_create_texture = d3dtexture_create;
448 This->d3d_added_device = d3d_add_device;
449 This->d3d_removed_device = d3d_remove_device;
451 ICOM_INIT_INTERFACE(This, IDirect3D, VTABLE_IDirect3D);
452 ICOM_INIT_INTERFACE(This, IDirect3D2, VTABLE_IDirect3D2);
453 ICOM_INIT_INTERFACE(This, IDirect3D3, VTABLE_IDirect3D3);
454 ICOM_INIT_INTERFACE(This, IDirect3D7, VTABLE_IDirect3D7);
456 globject->free_lights = (0x01 << MAX_LIGHTS) - 1; /* There are, in total, 8 lights in OpenGL */
457 globject->light_released = light_released;
459 This->d3d_private = globject;
461 TRACE(" creating OpenGL private storage at %p.\n", globject);