Authors: Mike McCormack <mike@codeweavers.com>, Aric Stewart <aric@codeweavers.com...
[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 <stdarg.h>
29 #include <stdio.h>
30
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wingdi.h"
36 #include "d3d.h"
37 #include "ddraw.h"
38 #include "winerror.h"
39
40 #include "ddraw_private.h"
41 #include "d3d_private.h"
42 #include "mesa_private.h"
43 #include "main.h"
44
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
48
49 HRESULT WINAPI
50 GL_IDirect3DImpl_1_EnumDevices(LPDIRECT3D iface,
51                                LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
52                                LPVOID lpUserArg)
53 {
54     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
55     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
56
57     /* Call functions defined in d3ddevices.c */
58     if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 1) != D3DENUMRET_OK)
59         return D3D_OK;
60
61     return D3D_OK;
62 }
63
64 HRESULT WINAPI
65 GL_IDirect3DImpl_3_2T_EnumDevices(LPDIRECT3D3 iface,
66                                   LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
67                                   LPVOID lpUserArg)
68 {
69     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
70     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
71
72     /* Call functions defined in d3ddevices.c */
73     if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 3) != D3DENUMRET_OK)
74         return D3D_OK;
75
76     return D3D_OK;
77 }
78
79 HRESULT WINAPI
80 GL_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
81                                      LPDIRECT3DLIGHT* lplpDirect3DLight,
82                                      IUnknown* pUnkOuter)
83 {
84     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
85     IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This->d3d_private;
86     int fl;
87     IDirect3DLightImpl *d3dlimpl;
88     HRESULT ret_value;
89     
90     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DLight, pUnkOuter);
91     for (fl = 0; fl < MAX_LIGHTS; fl++) {
92         if ((glThis->free_lights & (0x01 << fl)) != 0) {
93             glThis->free_lights &= ~(0x01 << fl);
94             break;
95         }
96     }
97     if (fl == MAX_LIGHTS) {
98         return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */
99     }
100     ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl);
101     *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);
102
103     return ret_value;
104 }
105
106 HRESULT WINAPI
107 GL_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
108                                         LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
109                                         IUnknown* pUnkOuter)
110 {
111     IDirect3DMaterialImpl *D3Dmat_impl;
112     HRESULT ret_value;
113     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
114     
115     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
116     ret_value = d3dmaterial_create(&D3Dmat_impl, This);
117
118     *lplpDirect3DMaterial3 = ICOM_INTERFACE(D3Dmat_impl, IDirect3DMaterial3);
119
120     return ret_value;
121 }
122
123 HRESULT WINAPI
124 GL_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
125                                         LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
126                                         IUnknown* pUnkOuter)
127 {
128     IDirect3DViewportImpl *D3Dvp_impl;
129     HRESULT ret_value;
130     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
131     
132     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpD3DViewport3, pUnkOuter);
133     ret_value = d3dviewport_create(&D3Dvp_impl, This);
134
135     *lplpD3DViewport3 = ICOM_INTERFACE(D3Dvp_impl, IDirect3DViewport3);
136
137     return ret_value;
138 }
139
140 static HRESULT
141 create_device_helper(IDirectDrawImpl *This,
142                      REFCLSID iid,
143                      IDirectDrawSurfaceImpl *lpDDS,
144                      void **obj,
145                      int version) {
146     IDirect3DDeviceImpl *lpd3ddev;
147     HRESULT ret_value;
148
149     ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS, FALSE);
150     if (FAILED(ret_value)) return ret_value;
151     
152     if ((iid == NULL) ||
153         (IsEqualGUID(&IID_D3DDEVICE_OpenGL, iid)) ||
154         (IsEqualGUID(&IID_IDirect3DHALDevice, iid)) ||
155         (IsEqualGUID(&IID_IDirect3DTnLHalDevice, iid)) ||
156         (IsEqualGUID(&IID_IDirect3DRGBDevice, iid)) ||
157         (IsEqualGUID(&IID_IDirect3DRefDevice, iid))) {
158         switch (version) {
159             case 1:
160                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice);
161                 TRACE(" returning OpenGL D3DDevice %p.\n", *obj);
162                 return D3D_OK;
163
164             case 2:
165                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice2);
166                 TRACE(" returning OpenGL D3DDevice2 %p.\n", *obj);
167                 return D3D_OK;
168
169             case 3:
170                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice3);
171                 TRACE(" returning OpenGL D3DDevice3 %p.\n", *obj);
172                 return D3D_OK;
173
174             case 7:
175                 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7);
176                 TRACE(" returning OpenGL D3DDevice7 %p.\n", *obj);
177                 return D3D_OK;
178         }
179     }
180
181     *obj = NULL;
182     ERR(" Interface unknown when creating D3DDevice (%s)\n", debugstr_guid(iid));
183     IDirect3DDevice7_Release(ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7));
184     return DDERR_INVALIDPARAMS;
185 }
186      
187
188 HRESULT WINAPI
189 GL_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
190                                 REFCLSID rclsid,
191                                 LPDIRECTDRAWSURFACE lpDDS,
192                                 LPDIRECT3DDEVICE2* lplpD3DDevice2)
193 {
194     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
195     IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, lpDDS);
196     TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice2);
197     return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice2, 2);
198 }
199
200 HRESULT WINAPI
201 GL_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
202                                 REFCLSID rclsid,
203                                 LPDIRECTDRAWSURFACE4 lpDDS,
204                                 LPDIRECT3DDEVICE3* lplpD3DDevice3,
205                                 LPUNKNOWN lpUnk)
206 {
207     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
208     IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
209     TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice3);
210     return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice3, 3);
211 }
212
213 HRESULT WINAPI
214 GL_IDirect3DImpl_3_2T_1T_FindDevice(LPDIRECT3D3 iface,
215                                     LPD3DFINDDEVICESEARCH lpD3DDFS,
216                                     LPD3DFINDDEVICERESULT lpD3DFDR)
217 {
218     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
219     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DDFS, lpD3DFDR);
220     return d3ddevice_find(This, lpD3DDFS, lpD3DFDR);
221 }
222
223 HRESULT WINAPI
224 GL_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
225                                          REFCLSID riidDevice,
226                                          LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
227                                          LPVOID lpContext)
228 {
229     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
230     DDPIXELFORMAT pformat;
231     
232     TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
233
234     memset(&pformat, 0, sizeof(pformat));
235     pformat.dwSize = sizeof(DDPIXELFORMAT);
236     pformat.dwFourCC = 0;   
237     TRACE("Enumerating dummy ZBuffer format (16 bits)\n");
238     pformat.dwFlags = DDPF_ZBUFFER;
239     pformat.u1.dwZBufferBitDepth = 16;
240     pformat.u3.dwZBitMask =    0x0000FFFF;
241     pformat.u5.dwRGBZBitMask = 0x0000FFFF;
242
243     /* Whatever the return value, stop here.. */
244     lpEnumCallback(&pformat, lpContext);
245     
246     return D3D_OK;
247 }
248
249 HRESULT WINAPI
250 GL_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
251                                LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
252                                LPVOID lpUserArg)
253 {
254     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
255     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
256
257     if (d3ddevice_enumerate7(lpEnumDevicesCallback, lpUserArg) != D3DENUMRET_OK)
258         return D3D_OK;
259     
260     return D3D_OK;
261 }
262
263 HRESULT WINAPI
264 GL_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
265                                 REFCLSID rclsid,
266                                 LPDIRECTDRAWSURFACE7 lpDDS,
267                                 LPDIRECT3DDEVICE7* lplpD3DDevice)
268 {
269     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
270     IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
271     TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice);
272     return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice, 7);
273 }
274
275 HRESULT WINAPI
276 GL_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
277                                          LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
278                                          LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
279                                          DWORD dwFlags)
280 {
281     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
282     IDirect3DVertexBufferImpl *vbimpl;
283     HRESULT res;
284     
285     TRACE("(%p/%p)->(%p,%p,%08lx)\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);
286
287     res = d3dvertexbuffer_create(&vbimpl, This, lpD3DVertBufDesc, dwFlags);
288
289     *lplpD3DVertBuf = ICOM_INTERFACE(vbimpl, IDirect3DVertexBuffer7);
290     
291     return res;
292 }
293
294 static void light_released(IDirectDrawImpl *This, GLenum light_num)
295 {
296     IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This->d3d_private;
297     glThis->free_lights |= (light_num - GL_LIGHT0);
298 }
299
300 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
301 # define XCAST(fun)     (typeof(VTABLE_IDirect3D7.fun))
302 #else
303 # define XCAST(fun)     (void*)
304 #endif
305
306 IDirect3D7Vtbl VTABLE_IDirect3D7 =
307 {
308     XCAST(QueryInterface) Thunk_IDirect3DImpl_7_QueryInterface,
309     XCAST(AddRef) Thunk_IDirect3DImpl_7_AddRef,
310     XCAST(Release) Thunk_IDirect3DImpl_7_Release,
311     XCAST(EnumDevices) GL_IDirect3DImpl_7_EnumDevices,
312     XCAST(CreateDevice) GL_IDirect3DImpl_7_CreateDevice,
313     XCAST(CreateVertexBuffer) GL_IDirect3DImpl_7_3T_CreateVertexBuffer,
314     XCAST(EnumZBufferFormats) GL_IDirect3DImpl_7_3T_EnumZBufferFormats,
315     XCAST(EvictManagedTextures) Main_IDirect3DImpl_7_3T_EvictManagedTextures,
316 };
317
318 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
319 #undef XCAST
320 #endif
321
322
323 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
324 # define XCAST(fun)     (typeof(VTABLE_IDirect3D3.fun))
325 #else
326 # define XCAST(fun)     (void*)
327 #endif
328
329 IDirect3D3Vtbl VTABLE_IDirect3D3 =
330 {
331     XCAST(QueryInterface) Thunk_IDirect3DImpl_3_QueryInterface,
332     XCAST(AddRef) Thunk_IDirect3DImpl_3_AddRef,
333     XCAST(Release) Thunk_IDirect3DImpl_3_Release,
334     XCAST(EnumDevices) GL_IDirect3DImpl_3_2T_EnumDevices,
335     XCAST(CreateLight) GL_IDirect3DImpl_3_2T_1T_CreateLight,
336     XCAST(CreateMaterial) GL_IDirect3DImpl_3_2T_1T_CreateMaterial,
337     XCAST(CreateViewport) GL_IDirect3DImpl_3_2T_1T_CreateViewport,
338     XCAST(FindDevice) GL_IDirect3DImpl_3_2T_1T_FindDevice,
339     XCAST(CreateDevice) GL_IDirect3DImpl_3_CreateDevice,
340     XCAST(CreateVertexBuffer) Thunk_IDirect3DImpl_3_CreateVertexBuffer,
341     XCAST(EnumZBufferFormats) Thunk_IDirect3DImpl_3_EnumZBufferFormats,
342     XCAST(EvictManagedTextures) Thunk_IDirect3DImpl_3_EvictManagedTextures,
343 };
344
345 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
346 #undef XCAST
347 #endif
348
349
350 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
351 # define XCAST(fun)     (typeof(VTABLE_IDirect3D2.fun))
352 #else
353 # define XCAST(fun)     (void*)
354 #endif
355
356 IDirect3D2Vtbl VTABLE_IDirect3D2 =
357 {
358     XCAST(QueryInterface) Thunk_IDirect3DImpl_2_QueryInterface,
359     XCAST(AddRef) Thunk_IDirect3DImpl_2_AddRef,
360     XCAST(Release) Thunk_IDirect3DImpl_2_Release,
361     XCAST(EnumDevices) Thunk_IDirect3DImpl_2_EnumDevices,
362     XCAST(CreateLight) Thunk_IDirect3DImpl_2_CreateLight,
363     XCAST(CreateMaterial) Thunk_IDirect3DImpl_2_CreateMaterial,
364     XCAST(CreateViewport) Thunk_IDirect3DImpl_2_CreateViewport,
365     XCAST(FindDevice) Thunk_IDirect3DImpl_2_FindDevice,
366     XCAST(CreateDevice) GL_IDirect3DImpl_2_CreateDevice,
367 };
368
369 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
370 #undef XCAST
371 #endif
372
373
374 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
375 # define XCAST(fun)     (typeof(VTABLE_IDirect3D.fun))
376 #else
377 # define XCAST(fun)     (void*)
378 #endif
379
380 IDirect3DVtbl VTABLE_IDirect3D =
381 {
382     XCAST(QueryInterface) Thunk_IDirect3DImpl_1_QueryInterface,
383     XCAST(AddRef) Thunk_IDirect3DImpl_1_AddRef,
384     XCAST(Release) Thunk_IDirect3DImpl_1_Release,
385     XCAST(Initialize) Main_IDirect3DImpl_1_Initialize,
386     XCAST(EnumDevices) GL_IDirect3DImpl_1_EnumDevices,
387     XCAST(CreateLight) Thunk_IDirect3DImpl_1_CreateLight,
388     XCAST(CreateMaterial) Thunk_IDirect3DImpl_1_CreateMaterial,
389     XCAST(CreateViewport) Thunk_IDirect3DImpl_1_CreateViewport,
390     XCAST(FindDevice) Thunk_IDirect3DImpl_1_FindDevice,
391 };
392
393 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
394 #undef XCAST
395 #endif
396
397 static HRESULT d3d_add_device(IDirectDrawImpl *This, IDirect3DDeviceImpl *device)
398 {
399     if  (This->current_device == NULL) {
400         /* Create delayed textures now that we have an OpenGL context...
401            For that, go through all surface attached to our DDraw object and create
402            OpenGL textures for all textures.. */
403         IDirectDrawSurfaceImpl *surf = This->surfaces;
404
405         while (surf != NULL) {
406             if (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
407                 /* Found a texture.. Now create the OpenGL part */
408                 d3dtexture_create(This, surf, FALSE, surf->mip_main);
409             }
410             surf = surf->next_ddraw;
411         }
412     }
413     /* For the moment, only one device 'supported'... */
414     This->current_device = device;
415
416     return DD_OK;
417 }
418
419 static HRESULT d3d_remove_device(IDirectDrawImpl *This, IDirect3DDeviceImpl *device)
420 {
421     This->current_device = NULL;
422     return DD_OK;
423 }
424
425 HRESULT direct3d_create(IDirectDrawImpl *This)
426 {
427     IDirect3DGLImpl *globject;
428     
429     globject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DGLImpl));
430     if (globject == NULL) return DDERR_OUTOFMEMORY;
431
432     This->d3d_create_texture = d3dtexture_create;
433     This->d3d_added_device = d3d_add_device;
434     This->d3d_removed_device = d3d_remove_device;
435
436     ICOM_INIT_INTERFACE(This, IDirect3D,  VTABLE_IDirect3D);
437     ICOM_INIT_INTERFACE(This, IDirect3D2, VTABLE_IDirect3D2);
438     ICOM_INIT_INTERFACE(This, IDirect3D3, VTABLE_IDirect3D3);
439     ICOM_INIT_INTERFACE(This, IDirect3D7, VTABLE_IDirect3D7);
440
441     globject->free_lights = (0x01 << MAX_LIGHTS) - 1; /* There are, in total, 8 lights in OpenGL */
442     globject->light_released = light_released;
443
444     This->d3d_private = globject;
445
446     TRACE(" creating OpenGL private storage at %p.\n", globject);
447     
448     return D3D_OK;
449 }