Added version information.
[wine] / dlls / ddraw / direct3d / mesa.c
1 /*
2  * Copyright 2000 Marcus Meissner
3  * Copyright 2000 Peter Hunnisett
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include "config.h"
21
22 #include <assert.h>
23 #ifdef HAVE_UNISTD_H
24 # include <unistd.h>
25 #endif
26 #include <fcntl.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32 #include "d3d.h"
33 #include "ddraw.h"
34 #include "winerror.h"
35
36 #include "ddraw_private.h"
37 #include "d3d_private.h"
38 #include "mesa_private.h"
39 #include "main.h"
40
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
44
45 HRESULT WINAPI
46 GL_IDirect3DImpl_1_EnumDevices(LPDIRECT3D iface,
47                                LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
48                                LPVOID lpUserArg)
49 {
50     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D, iface);
51     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
52
53     /* Call functions defined in d3ddevices.c */
54     if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 1) != D3DENUMRET_OK)
55         return D3D_OK;
56
57     return D3D_OK;
58 }
59
60 HRESULT WINAPI
61 GL_IDirect3DImpl_3_2T_EnumDevices(LPDIRECT3D3 iface,
62                                   LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
63                                   LPVOID lpUserArg)
64 {
65     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
66     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
67
68     /* Call functions defined in d3ddevices.c */
69     if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 3) != D3DENUMRET_OK)
70         return D3D_OK;
71
72     return D3D_OK;
73 }
74
75 HRESULT WINAPI
76 GL_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
77                                      LPDIRECT3DLIGHT* lplpDirect3DLight,
78                                      IUnknown* pUnkOuter)
79 {
80     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
81     IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
82     int fl;
83     IDirect3DLightImpl *d3dlimpl;
84     HRESULT ret_value;
85     
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);
90             break;
91         }
92     }
93     if (fl == MAX_LIGHTS) {
94         return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */
95     }
96     ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl);
97     *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);
98
99     return ret_value;
100 }
101
102 HRESULT WINAPI
103 GL_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
104                                         LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
105                                         IUnknown* pUnkOuter)
106 {
107     IDirect3DMaterialImpl *D3Dmat_impl;
108     HRESULT ret_value;
109     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
110     
111     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
112     ret_value = d3dmaterial_create(&D3Dmat_impl, This);
113
114     *lplpDirect3DMaterial3 = ICOM_INTERFACE(D3Dmat_impl, IDirect3DMaterial3);
115
116     return ret_value;
117 }
118
119 HRESULT WINAPI
120 GL_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
121                                         LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
122                                         IUnknown* pUnkOuter)
123 {
124     IDirect3DViewportImpl *D3Dvp_impl;
125     HRESULT ret_value;
126     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
127     
128     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpD3DViewport3, pUnkOuter);
129     ret_value = d3dviewport_create(&D3Dvp_impl, This);
130
131     *lplpD3DViewport3 = ICOM_INTERFACE(D3Dvp_impl, IDirect3DViewport3);
132
133     return ret_value;
134 }
135
136 static HRESULT
137 create_device_helper(IDirect3DImpl *This,
138                      REFCLSID iid,
139                      IDirectDrawSurfaceImpl *lpDDS,
140                      void **obj,
141                      int version) {
142     IDirect3DDeviceImpl *lpd3ddev;
143     HRESULT ret_value;
144
145     ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS);
146     if (FAILED(ret_value)) return ret_value;
147     
148     if ((iid == NULL) ||
149         (IsEqualGUID(&IID_D3DDEVICE_OpenGL, iid)) ||
150         (IsEqualGUID(&IID_IDirect3DHALDevice, iid)) ||
151         (IsEqualGUID(&IID_IDirect3DTnLHalDevice, iid)) ||
152         (IsEqualGUID(&IID_IDirect3DRefDevice, iid))) {
153         switch (version) {
154             case 1:
155                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice);
156                 TRACE(" returning OpenGL D3DDevice %p.\n", *obj);
157                 return D3D_OK;
158
159             case 2:
160                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice2);
161                 TRACE(" returning OpenGL D3DDevice2 %p.\n", *obj);
162                 return D3D_OK;
163
164             case 3:
165                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice3);
166                 TRACE(" returning OpenGL D3DDevice3 %p.\n", *obj);
167                 return D3D_OK;
168
169             case 7:
170                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7);
171                 TRACE(" returning OpenGL D3DDevice7 %p.\n", *obj);
172                 return D3D_OK;
173         }
174     }
175
176     *obj = NULL;
177     ERR(" Interface unknown when creating D3DDevice (%s)\n", debugstr_guid(iid));
178     IDirect3DDevice7_Release(ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7));
179     return DDERR_INVALIDPARAMS;
180 }
181      
182
183 HRESULT WINAPI
184 GL_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
185                                 REFCLSID rclsid,
186                                 LPDIRECTDRAWSURFACE lpDDS,
187                                 LPDIRECT3DDEVICE2* lplpD3DDevice2)
188 {
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);
193 }
194
195 HRESULT WINAPI
196 GL_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
197                                 REFCLSID rclsid,
198                                 LPDIRECTDRAWSURFACE4 lpDDS,
199                                 LPDIRECT3DDEVICE3* lplpD3DDevice3,
200                                 LPUNKNOWN lpUnk)
201 {
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);
206 }
207
208 HRESULT WINAPI
209 GL_IDirect3DImpl_3_2T_1T_FindDevice(LPDIRECT3D3 iface,
210                                     LPD3DFINDDEVICESEARCH lpD3DDFS,
211                                     LPD3DFINDDEVICERESULT lpD3DFDR)
212 {
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);
216 }
217
218 HRESULT WINAPI
219 GL_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
220                                          REFCLSID riidDevice,
221                                          LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
222                                          LPVOID lpContext)
223 {
224     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
225     DDPIXELFORMAT pformat;
226     
227     TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
228
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;
237
238     /* Whatever the return value, stop here.. */
239     lpEnumCallback(&pformat, lpContext);
240     
241     return D3D_OK;
242 }
243
244 HRESULT WINAPI
245 GL_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
246                                LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
247                                LPVOID lpUserArg)
248 {
249     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
250     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
251
252     if (d3ddevice_enumerate7(lpEnumDevicesCallback, lpUserArg) != D3DENUMRET_OK)
253         return D3D_OK;
254     
255     return D3D_OK;
256 }
257
258 HRESULT WINAPI
259 GL_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
260                                 REFCLSID rclsid,
261                                 LPDIRECTDRAWSURFACE7 lpDDS,
262                                 LPDIRECT3DDEVICE7* lplpD3DDevice)
263 {
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);
268 }
269
270 HRESULT WINAPI
271 GL_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
272                                          LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
273                                          LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
274                                          DWORD dwFlags)
275 {
276     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
277     IDirect3DVertexBufferImpl *vbimpl;
278     HRESULT res;
279     
280     TRACE("(%p/%p)->(%p,%p,%08lx)\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);
281
282     res = d3dvertexbuffer_create(&vbimpl, This, lpD3DVertBufDesc, dwFlags);
283
284     *lplpD3DVertBuf = ICOM_INTERFACE(vbimpl, IDirect3DVertexBuffer7);
285     
286     return res;
287 }
288
289 static void light_released(IDirect3DImpl *This, GLenum light_num)
290 {
291     IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
292     glThis->free_lights |= (light_num - GL_LIGHT0);
293 }
294
295 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
296 # define XCAST(fun)     (typeof(VTABLE_IDirect3D7.fun))
297 #else
298 # define XCAST(fun)     (void*)
299 #endif
300
301 ICOM_VTABLE(IDirect3D7) VTABLE_IDirect3D7 =
302 {
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,
312 };
313
314 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
315 #undef XCAST
316 #endif
317
318
319 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
320 # define XCAST(fun)     (typeof(VTABLE_IDirect3D3.fun))
321 #else
322 # define XCAST(fun)     (void*)
323 #endif
324
325 ICOM_VTABLE(IDirect3D3) VTABLE_IDirect3D3 =
326 {
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,
340 };
341
342 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
343 #undef XCAST
344 #endif
345
346
347 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
348 # define XCAST(fun)     (typeof(VTABLE_IDirect3D2.fun))
349 #else
350 # define XCAST(fun)     (void*)
351 #endif
352
353 ICOM_VTABLE(IDirect3D2) VTABLE_IDirect3D2 =
354 {
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,
365 };
366
367 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
368 #undef XCAST
369 #endif
370
371
372 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
373 # define XCAST(fun)     (typeof(VTABLE_IDirect3D.fun))
374 #else
375 # define XCAST(fun)     (void*)
376 #endif
377
378 ICOM_VTABLE(IDirect3D) VTABLE_IDirect3D =
379 {
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,
390 };
391
392 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
393 #undef XCAST
394 #endif
395
396 static HRESULT d3d_add_device(IDirect3DImpl *This, IDirect3DDeviceImpl *device)
397 {
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;
403
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);
408             }
409             surf = surf->next_ddraw;
410         }
411     }
412     /* For the moment, only one device 'supported'... */
413     This->current_device = device;
414
415     return DD_OK;
416 }
417
418 static HRESULT d3d_remove_device(IDirect3DImpl *This, IDirect3DDeviceImpl *device)
419 {
420     This->current_device = NULL;
421     return DD_OK;
422 }
423
424 HRESULT direct3d_create(IDirect3DImpl **obj, IDirectDrawImpl *ddraw)
425 {
426     IDirect3DImpl *object;
427     IDirect3DGLImpl *globject;
428     
429     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DGLImpl));
430     if (object == NULL) return DDERR_OUTOFMEMORY;
431
432     object->ref = 1;
433     object->ddraw = ddraw;
434     object->create_texture = d3dtexture_create;
435     object->added_device = d3d_add_device;
436     object->removed_device = d3d_remove_device;
437
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);
442
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;
446
447     *obj = object;
448
449     TRACE(" creating implementation at %p.\n", *obj);
450     
451     return D3D_OK;
452 }