Enable the application to create first textures and then the D3D
[wine/multimedia.git] / dlls / ddraw / direct3d / mesa.c
blob6583a31d72ecbb347599edc1ad074106665d4910
1 /*
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
20 #include "config.h"
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>
30 #include "d3d.h"
31 #include "ddraw.h"
32 #include "winerror.h"
34 #include "ddraw_private.h"
35 #include "d3d_private.h"
36 #include "mesa_private.h"
37 #include "main.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
43 #define MAX_LIGHTS 8
45 HRESULT WINAPI
46 GL_IDirect3DImpl_3_2T_1T_EnumDevices(LPDIRECT3D3 iface,
47 LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
48 LPVOID lpUserArg)
50 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, 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) != D3DENUMRET_OK)
55 return D3D_OK;
57 return D3D_OK;
60 HRESULT WINAPI
61 GL_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
62 LPDIRECT3DLIGHT* lplpDirect3DLight,
63 IUnknown* pUnkOuter)
65 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
66 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
67 int fl;
68 IDirect3DLightImpl *d3dlimpl;
69 HRESULT ret_value;
71 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DLight, pUnkOuter);
72 for (fl = 0; fl < MAX_LIGHTS; fl++) {
73 if ((glThis->free_lights & (0x01 << fl)) != 0) {
74 glThis->free_lights &= ~(0x01 << fl);
75 break;
78 if (fl == MAX_LIGHTS) {
79 return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */
81 ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl);
82 *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);
84 return ret_value;
87 HRESULT WINAPI
88 GL_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
89 LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
90 IUnknown* pUnkOuter)
92 IDirect3DMaterialImpl *D3Dmat_impl;
93 HRESULT ret_value;
94 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
96 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
97 ret_value = d3dmaterial_create(&D3Dmat_impl, This);
99 *lplpDirect3DMaterial3 = ICOM_INTERFACE(D3Dmat_impl, IDirect3DMaterial3);
101 return ret_value;
104 HRESULT WINAPI
105 GL_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
106 LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
107 IUnknown* pUnkOuter)
109 IDirect3DViewportImpl *D3Dvp_impl;
110 HRESULT ret_value;
111 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
113 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpD3DViewport3, pUnkOuter);
114 ret_value = d3dviewport_create(&D3Dvp_impl, This);
116 *lplpD3DViewport3 = ICOM_INTERFACE(D3Dvp_impl, IDirect3DViewport3);
118 return ret_value;
121 static HRESULT
122 create_device_helper(IDirect3DImpl *This,
123 REFCLSID iid,
124 IDirectDrawSurfaceImpl *lpDDS,
125 void **obj,
126 int interface) {
127 IDirect3DDeviceImpl *lpd3ddev;
128 HRESULT ret_value;
130 ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS);
131 if (FAILED(ret_value)) return ret_value;
133 if ((iid == NULL) ||
134 (IsEqualGUID(&IID_D3DDEVICE_OpenGL, iid)) ||
135 (IsEqualGUID(&IID_IDirect3DHALDevice, iid)) ||
136 (IsEqualGUID(&IID_IDirect3DTnLHalDevice, iid))) {
137 switch (interface) {
138 case 1:
139 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice);
140 TRACE(" returning OpenGL D3DDevice %p.\n", *obj);
141 return D3D_OK;
143 case 2:
144 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice2);
145 TRACE(" returning OpenGL D3DDevice2 %p.\n", *obj);
146 return D3D_OK;
148 case 3:
149 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice3);
150 TRACE(" returning OpenGL D3DDevice3 %p.\n", *obj);
151 return D3D_OK;
153 case 7:
154 *obj = ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7);
155 TRACE(" returning OpenGL D3DDevice7 %p.\n", *obj);
156 return D3D_OK;
160 *obj = NULL;
161 ERR(" Interface unknown when creating D3DDevice (%s)\n", debugstr_guid(iid));
162 IDirect3DDevice7_Release(ICOM_INTERFACE(lpd3ddev, IDirect3DDevice7));
163 return DDERR_INVALIDPARAMS;
167 HRESULT WINAPI
168 GL_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
169 REFCLSID rclsid,
170 LPDIRECTDRAWSURFACE lpDDS,
171 LPDIRECT3DDEVICE2* lplpD3DDevice2)
173 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D2, iface);
174 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, lpDDS);
175 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice2);
176 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice2, 2);
179 HRESULT WINAPI
180 GL_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
181 REFCLSID rclsid,
182 LPDIRECTDRAWSURFACE4 lpDDS,
183 LPDIRECT3DDEVICE3* lplpD3DDevice3,
184 LPUNKNOWN lpUnk)
186 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
187 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
188 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice3);
189 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice3, 3);
192 HRESULT WINAPI
193 GL_IDirect3DImpl_3_2T_1T_FindDevice(LPDIRECT3D3 iface,
194 LPD3DFINDDEVICESEARCH lpD3DDFS,
195 LPD3DFINDDEVICERESULT lpD3DFDR)
197 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
198 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DDFS, lpD3DFDR);
199 return d3ddevice_find(This, lpD3DDFS, lpD3DFDR);
202 HRESULT WINAPI
203 GL_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
204 REFCLSID riidDevice,
205 LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
206 LPVOID lpContext)
208 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
209 DDPIXELFORMAT pformat;
211 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
213 memset(&pformat, 0, sizeof(pformat));
214 pformat.dwSize = sizeof(DDPIXELFORMAT);
215 pformat.dwFourCC = 0;
216 TRACE("Enumerating dummy ZBuffer format (16 bits)\n");
217 pformat.dwFlags = DDPF_ZBUFFER;
218 pformat.u1.dwZBufferBitDepth = 16;
219 pformat.u3.dwZBitMask = 0x0000FFFF;
220 pformat.u5.dwRGBZBitMask = 0x0000FFFF;
222 /* Whatever the return value, stop here.. */
223 lpEnumCallback(&pformat, lpContext);
225 return D3D_OK;
228 HRESULT WINAPI
229 GL_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
230 LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
231 LPVOID lpUserArg)
233 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
234 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg);
236 if (d3ddevice_enumerate7(lpEnumDevicesCallback, lpUserArg) != D3DENUMRET_OK)
237 return D3D_OK;
239 return D3D_OK;
242 HRESULT WINAPI
243 GL_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
244 REFCLSID rclsid,
245 LPDIRECTDRAWSURFACE7 lpDDS,
246 LPDIRECT3DDEVICE7* lplpD3DDevice)
248 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
249 IDirectDrawSurfaceImpl *ddsurfaceimpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpDDS);
250 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice);
251 return create_device_helper(This, rclsid, ddsurfaceimpl, (void **) lplpD3DDevice, 7);
254 HRESULT WINAPI
255 GL_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
256 LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
257 LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
258 DWORD dwFlags)
260 ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
261 IDirect3DVertexBufferImpl *vbimpl;
262 HRESULT res;
264 TRACE("(%p/%p)->(%p,%p,%08lx)\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);
266 res = d3dvertexbuffer_create(&vbimpl, This, lpD3DVertBufDesc, dwFlags);
268 *lplpD3DVertBuf = ICOM_INTERFACE(vbimpl, IDirect3DVertexBuffer7);
270 return res;
273 static void light_released(IDirect3DImpl *This, GLenum light_num)
275 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
276 glThis->free_lights |= (light_num - GL_LIGHT0);
279 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
280 # define XCAST(fun) (typeof(VTABLE_IDirect3D7.fun))
281 #else
282 # define XCAST(fun) (void*)
283 #endif
285 ICOM_VTABLE(IDirect3D7) VTABLE_IDirect3D7 =
287 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
288 XCAST(QueryInterface) Main_IDirect3DImpl_7_3T_2T_1T_QueryInterface,
289 XCAST(AddRef) Main_IDirect3DImpl_7_3T_2T_1T_AddRef,
290 XCAST(Release) Main_IDirect3DImpl_7_3T_2T_1T_Release,
291 XCAST(EnumDevices) GL_IDirect3DImpl_7_EnumDevices,
292 XCAST(CreateDevice) GL_IDirect3DImpl_7_CreateDevice,
293 XCAST(CreateVertexBuffer) GL_IDirect3DImpl_7_3T_CreateVertexBuffer,
294 XCAST(EnumZBufferFormats) GL_IDirect3DImpl_7_3T_EnumZBufferFormats,
295 XCAST(EvictManagedTextures) Main_IDirect3DImpl_7_3T_EvictManagedTextures,
298 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
299 #undef XCAST
300 #endif
303 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
304 # define XCAST(fun) (typeof(VTABLE_IDirect3D3.fun))
305 #else
306 # define XCAST(fun) (void*)
307 #endif
309 ICOM_VTABLE(IDirect3D3) VTABLE_IDirect3D3 =
311 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
312 XCAST(QueryInterface) Thunk_IDirect3DImpl_3_QueryInterface,
313 XCAST(AddRef) Thunk_IDirect3DImpl_3_AddRef,
314 XCAST(Release) Thunk_IDirect3DImpl_3_Release,
315 XCAST(EnumDevices) GL_IDirect3DImpl_3_2T_1T_EnumDevices,
316 XCAST(CreateLight) GL_IDirect3DImpl_3_2T_1T_CreateLight,
317 XCAST(CreateMaterial) GL_IDirect3DImpl_3_2T_1T_CreateMaterial,
318 XCAST(CreateViewport) GL_IDirect3DImpl_3_2T_1T_CreateViewport,
319 XCAST(FindDevice) GL_IDirect3DImpl_3_2T_1T_FindDevice,
320 XCAST(CreateDevice) GL_IDirect3DImpl_3_CreateDevice,
321 XCAST(CreateVertexBuffer) Thunk_IDirect3DImpl_3_CreateVertexBuffer,
322 XCAST(EnumZBufferFormats) Thunk_IDirect3DImpl_3_EnumZBufferFormats,
323 XCAST(EvictManagedTextures) Thunk_IDirect3DImpl_3_EvictManagedTextures,
326 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
327 #undef XCAST
328 #endif
331 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
332 # define XCAST(fun) (typeof(VTABLE_IDirect3D2.fun))
333 #else
334 # define XCAST(fun) (void*)
335 #endif
337 ICOM_VTABLE(IDirect3D2) VTABLE_IDirect3D2 =
339 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
340 XCAST(QueryInterface) Thunk_IDirect3DImpl_2_QueryInterface,
341 XCAST(AddRef) Thunk_IDirect3DImpl_2_AddRef,
342 XCAST(Release) Thunk_IDirect3DImpl_2_Release,
343 XCAST(EnumDevices) Thunk_IDirect3DImpl_2_EnumDevices,
344 XCAST(CreateLight) Thunk_IDirect3DImpl_2_CreateLight,
345 XCAST(CreateMaterial) Thunk_IDirect3DImpl_2_CreateMaterial,
346 XCAST(CreateViewport) Thunk_IDirect3DImpl_2_CreateViewport,
347 XCAST(FindDevice) Thunk_IDirect3DImpl_2_FindDevice,
348 XCAST(CreateDevice) GL_IDirect3DImpl_2_CreateDevice,
351 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
352 #undef XCAST
353 #endif
356 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
357 # define XCAST(fun) (typeof(VTABLE_IDirect3D.fun))
358 #else
359 # define XCAST(fun) (void*)
360 #endif
362 ICOM_VTABLE(IDirect3D) VTABLE_IDirect3D =
364 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
365 XCAST(QueryInterface) Thunk_IDirect3DImpl_1_QueryInterface,
366 XCAST(AddRef) Thunk_IDirect3DImpl_1_AddRef,
367 XCAST(Release) Thunk_IDirect3DImpl_1_Release,
368 XCAST(Initialize) Main_IDirect3DImpl_1_Initialize,
369 XCAST(EnumDevices) Thunk_IDirect3DImpl_1_EnumDevices,
370 XCAST(CreateLight) Thunk_IDirect3DImpl_1_CreateLight,
371 XCAST(CreateMaterial) Thunk_IDirect3DImpl_1_CreateMaterial,
372 XCAST(CreateViewport) Thunk_IDirect3DImpl_1_CreateViewport,
373 XCAST(FindDevice) Thunk_IDirect3DImpl_1_FindDevice,
376 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
377 #undef XCAST
378 #endif
380 static HRESULT d3d_add_device(IDirect3DImpl *This, IDirect3DDeviceImpl *device)
382 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
384 if (glThis->current_device == NULL) {
385 /* Create delayed textures now that we have an OpenGL context...
386 For that, go through all surface attached to our DDraw object and create
387 OpenGL textures for all textures.. */
388 IDirectDrawSurfaceImpl *surf = This->ddraw->surfaces;
390 while (surf != NULL) {
391 if (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
392 /* Found a texture.. Now create the OpenGL part */
393 d3dtexture_create(This, surf, FALSE, surf->mip_main);
395 surf = surf->next_ddraw;
398 /* For the moment, only one device 'supported'... */
399 glThis->current_device = device;
401 return DD_OK;
404 static HRESULT d3d_remove_device(IDirect3DImpl *This, IDirect3DDeviceImpl *device)
406 IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This;
408 glThis->current_device = NULL;
409 return DD_OK;
412 HRESULT direct3d_create(IDirect3DImpl **obj, IDirectDrawImpl *ddraw)
414 IDirect3DImpl *object;
415 IDirect3DGLImpl *globject;
417 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DGLImpl));
418 if (object == NULL) return DDERR_OUTOFMEMORY;
420 object->ref = 1;
421 object->ddraw = ddraw;
422 object->create_texture = d3dtexture_create;
423 object->added_device = d3d_add_device;
424 object->removed_device = d3d_remove_device;
426 ICOM_INIT_INTERFACE(object, IDirect3D, VTABLE_IDirect3D);
427 ICOM_INIT_INTERFACE(object, IDirect3D2, VTABLE_IDirect3D2);
428 ICOM_INIT_INTERFACE(object, IDirect3D3, VTABLE_IDirect3D3);
429 ICOM_INIT_INTERFACE(object, IDirect3D7, VTABLE_IDirect3D7);
431 globject = (IDirect3DGLImpl *) object;
432 globject->free_lights = (0x01 << MAX_LIGHTS) - 1; /* There are, in total, 8 lights in OpenGL */
433 globject->light_released = light_released;
435 *obj = object;
437 TRACE(" creating implementation at %p.\n", *obj);
439 return D3D_OK;