d3drm: Implement D3DRMCreateColorRGB.
[wine] / dlls / ddraw / direct3d.c
1 /*
2  * Copyright (c) 2006 Stefan Dösinger
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21 #include "wine/debug.h"
22
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #define COBJMACROS
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "wingdi.h"
34 #include "wine/exception.h"
35
36 #include "ddraw.h"
37 #include "d3d.h"
38
39 #include "ddraw_private.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
42
43 /*****************************************************************************
44  * IDirect3D7::QueryInterface
45  *
46  * QueryInterface implementation with thunks to IDirectDraw7
47  *
48  *****************************************************************************/
49 static HRESULT WINAPI
50 Thunk_IDirect3DImpl_7_QueryInterface(IDirect3D7 *iface,
51                                     REFIID refiid,
52                                     void **obj)
53 {
54     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
55     TRACE("(%p)->(%s,%p): Thunking to IDirectDraw7\n", This, debugstr_guid(refiid), obj);
56
57     return IDirectDraw7_QueryInterface(ICOM_INTERFACE(This, IDirectDraw7),
58                                        refiid,
59                                        obj);
60 }
61
62 static HRESULT WINAPI
63 Thunk_IDirect3DImpl_3_QueryInterface(IDirect3D3 *iface,
64                                     REFIID refiid,
65                                     void **obj)
66 {
67     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
68     TRACE("(%p)->(%s,%p): Thunking to IDirectDraw7\n", This, debugstr_guid(refiid), obj);
69
70     return IDirectDraw7_QueryInterface(ICOM_INTERFACE(This, IDirectDraw7),
71                                        refiid,
72                                        obj);
73 }
74
75 static HRESULT WINAPI
76 Thunk_IDirect3DImpl_2_QueryInterface(IDirect3D2 *iface,
77                                     REFIID refiid,
78                                     void **obj)
79 {
80     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
81     TRACE("(%p)->(%s,%p): Thunking to IDirectDraw7\n", This, debugstr_guid(refiid), obj);
82
83     return IDirectDraw7_QueryInterface(ICOM_INTERFACE(This, IDirectDraw7),
84                                        refiid,
85                                        obj);
86 }
87
88 static HRESULT WINAPI
89 Thunk_IDirect3DImpl_1_QueryInterface(IDirect3D *iface,
90                                     REFIID refiid,
91                                     void **obj)
92 {
93     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
94     TRACE("(%p)->(%s,%p): Thunking to IDirectDraw7\n", This, debugstr_guid(refiid), obj);
95
96     return IDirectDraw7_QueryInterface(ICOM_INTERFACE(This, IDirectDraw7),
97                                        refiid,
98                                        obj);
99 }
100
101 /*****************************************************************************
102  * IDirect3D7::AddRef
103  *
104  * DirectDraw refcounting is a bit odd. Every version of the ddraw interface
105  * has its own refcount, but IDirect3D 1/2/3 refcounts are linked to
106  * IDirectDraw, and IDirect3D7 is linked to IDirectDraw7
107  *
108  * IDirect3D7 -> IDirectDraw7
109  * IDirect3D3 -> IDirectDraw
110  * IDirect3D2 -> IDirectDraw
111  * IDirect3D  -> IDirectDraw
112  *
113  * So every AddRef implementation thunks to a different interface, and the
114  * IDirectDrawX::AddRef implementations have different counters...
115  *
116  * Returns
117  *  The new refcount
118  *
119  *****************************************************************************/
120 static ULONG WINAPI
121 Thunk_IDirect3DImpl_7_AddRef(IDirect3D7 *iface)
122 {
123     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
124     TRACE("(%p) : Thunking to IDirectDraw7.\n", This);
125
126     return IDirectDraw7_AddRef(ICOM_INTERFACE(This, IDirectDraw7));
127 }
128
129 static ULONG WINAPI
130 Thunk_IDirect3DImpl_3_AddRef(IDirect3D3 *iface)
131 {
132     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
133     TRACE("(%p) : Thunking to IDirectDraw.\n", This);
134
135     return IDirectDraw_AddRef(ICOM_INTERFACE(This, IDirectDraw));
136 }
137
138 static ULONG WINAPI
139 Thunk_IDirect3DImpl_2_AddRef(IDirect3D2 *iface)
140 {
141     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
142     TRACE("(%p) : Thunking to IDirectDraw.\n", This);
143
144     return IDirectDraw_AddRef(ICOM_INTERFACE(This, IDirectDraw));
145 }
146
147 static ULONG WINAPI
148 Thunk_IDirect3DImpl_1_AddRef(IDirect3D *iface)
149 {
150     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
151     TRACE("(%p) : Thunking to IDirectDraw.\n", This);
152
153     return IDirectDraw_AddRef(ICOM_INTERFACE(This, IDirectDraw));
154 }
155
156 /*****************************************************************************
157  * IDirect3D7::Release
158  *
159  * Same story as IDirect3D7::AddRef
160  *
161  * Returns: The new refcount
162  *
163  *****************************************************************************/
164 static ULONG WINAPI
165 Thunk_IDirect3DImpl_7_Release(IDirect3D7 *iface)
166 {
167     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
168     TRACE("(%p) : Thunking to IDirectDraw7.\n", This);
169
170     return IDirectDraw7_Release(ICOM_INTERFACE(This, IDirectDraw7));
171 }
172
173 static ULONG WINAPI
174 Thunk_IDirect3DImpl_3_Release(IDirect3D3 *iface)
175 {
176     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
177     TRACE("(%p) : Thunking to IDirectDraw.\n", This);
178
179     return IDirectDraw_Release(ICOM_INTERFACE(This, IDirectDraw));
180 }
181
182 static ULONG WINAPI
183 Thunk_IDirect3DImpl_2_Release(IDirect3D2 *iface)
184 {
185     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
186     TRACE("(%p) : Thunking to IDirectDraw.\n", This);
187
188     return IDirectDraw_Release(ICOM_INTERFACE(This, IDirectDraw));
189 }
190
191 static ULONG WINAPI
192 Thunk_IDirect3DImpl_1_Release(IDirect3D *iface)
193 {
194     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
195     TRACE("(%p) : Thunking to IDirectDraw.\n", This);
196
197     return IDirectDraw_Release(ICOM_INTERFACE(This, IDirectDraw));
198 }
199
200 /*****************************************************************************
201  * IDirect3D Methods
202  *****************************************************************************/
203
204 /*****************************************************************************
205  * IDirect3D::Initialize
206  *
207  * Initializes the IDirect3D interface. This is a no-op implementation,
208  * as all initialization is done at create time.
209  *
210  * Version 1
211  *
212  * Params:
213  *  refiid: ?
214  *
215  * Returns:
216  *  D3D_OK, because it's a no-op
217  *
218  *****************************************************************************/
219 static HRESULT WINAPI
220 IDirect3DImpl_1_Initialize(IDirect3D *iface,
221                            REFIID refiid)
222 {
223     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
224
225     TRACE("(%p)->(%s) no-op...\n", This, debugstr_guid(refiid));
226     return D3D_OK;
227 }
228
229 /*****************************************************************************
230  * IDirect3D7::EnumDevices
231  *
232  * The EnumDevices method for IDirect3D7. It enumerates all supported
233  * D3D7 devices. Currently there's only one.
234  *
235  * Params:
236  *  Callback: Function to call for each enumerated device
237  *  Context: Pointer to pass back to the app
238  *
239  * Returns:
240  *  D3D_OK, or the return value of the GetCaps call
241  *
242  *****************************************************************************/
243 static HRESULT WINAPI
244 IDirect3DImpl_7_EnumDevices(IDirect3D7 *iface,
245                           LPD3DENUMDEVICESCALLBACK7 Callback,
246                           void *Context)
247 {
248     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
249     char interface_name[] = "WINE Direct3D7 using WineD3D";
250     char device_name[] = "Wine D3D7 device";
251     D3DDEVICEDESC7 ddesc;
252     D3DDEVICEDESC oldDesc;
253     HRESULT hr;
254
255     TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
256
257     TRACE("(%p) Enumerating WineD3D D3Device7 interface\n", This);
258     hr = IDirect3DImpl_GetCaps(This->wineD3D, &oldDesc, &ddesc);
259     if(hr != D3D_OK) return hr;
260     Callback(interface_name, device_name, &ddesc, Context);
261
262     TRACE("(%p) End of enumeration\n", This);
263     return D3D_OK;
264 }
265
266 /*****************************************************************************
267  * IDirect3D3::EnumDevices
268  *
269  * Enumerates all supported Direct3DDevice interfaces. This is the
270  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
271  *
272  * Version 1, 2 and 3
273  *
274  * Params:
275  *  Callback: Application-provided routine to call for each enumerated device
276  *  Context: Pointer to pass to the callback
277  *
278  * Returns:
279  *  D3D_OK on success,
280  *  The result of IDirect3DImpl_GetCaps if it failed
281  *
282  *****************************************************************************/
283 static HRESULT WINAPI
284 IDirect3DImpl_3_EnumDevices(IDirect3D3 *iface,
285                             LPD3DENUMDEVICESCALLBACK Callback,
286                             void *Context)
287 {
288     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
289     D3DDEVICEDESC dref, d1, d2;
290     D3DDEVICEDESC7 newDesc;
291     static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
292     HRESULT hr;
293
294     /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
295        Let's put the string in a sufficiently sized array in writable memory. */
296     char device_name[50];
297     strcpy(device_name,"direct3d");
298
299     TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
300
301     hr = IDirect3DImpl_GetCaps(This->wineD3D, &dref, &newDesc);
302     if(hr != D3D_OK) return hr;
303
304     /* Do I have to enumerate the reference id? Note from old d3d7:
305      * "It seems that enumerating the reference IID on Direct3D 1 games
306      * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
307      *
308      * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers, EnumReference
309      * which enables / disables enumerating the reference rasterizer. It's a DWORD,
310      * 0 means disabled, 2 means enabled. The enablerefrast.reg and disablerefrast.reg
311      * files in the DirectX 7.0 sdk demo directory suggest this.
312      *
313      * Some games(GTA 2) seem to use the second enumerated device, so I have to enumerate
314      * at least 2 devices. So enumerate the reference device to have 2 devices.
315      *
316      * Other games(Rollcage) tell emulation and hal device appart by certain flags.
317      * Rollcage expects D3DPTEXTURECAPS_POW2 to be set(yeah, it is a limitation flag),
318      * and it refuses all devices that have the perspective flag set. This way it refuses
319      * the emulation device, and HAL devices never have POW2 unset in d3d7 on windows.
320      */
321
322     if(This->d3dversion != 1)
323     {
324         static CHAR reference_description[] = "RGB Direct3D emulation";
325
326         TRACE("(%p) Enumerating WineD3D D3DDevice interface\n", This);
327         d1 = dref;
328         d2 = dref;
329         /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps */
330         d1.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
331         d1.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
332         hr = Callback( (LPIID) &IID_IDirect3DRGBDevice, reference_description, device_name, &d1, &d2, Context);
333         if(hr != D3DENUMRET_OK)
334         {
335             TRACE("Application cancelled the enumeration\n");
336             return D3D_OK;
337         }
338     }
339
340     TRACE("(%p) Enumerating HAL Direct3D device\n", This);
341     d1 = dref;
342     d2 = dref;
343     /* The hal device does not have the pow2 flag set in hel, but in hal */
344     d2.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
345     d2.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
346     hr = Callback( (LPIID) &IID_IDirect3DHALDevice, wined3d_description, device_name, &d1, &d2, Context);
347     if(hr != D3DENUMRET_OK)
348     {
349         TRACE("Application cancelled the enumeration\n");
350         return D3D_OK;
351     }
352     TRACE("(%p) End of enumeration\n", This);
353
354     return D3D_OK;
355 }
356
357 static HRESULT WINAPI
358 Thunk_IDirect3DImpl_2_EnumDevices(IDirect3D2 *iface,
359                                   LPD3DENUMDEVICESCALLBACK Callback,
360                                   void *Context)
361 {
362     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
363     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Callback, Context);
364     return IDirect3D3_EnumDevices(ICOM_INTERFACE(This, IDirect3D3),
365                                   Callback,
366                                   Context);
367 }
368
369 static HRESULT WINAPI
370 Thunk_IDirect3DImpl_1_EnumDevices(IDirect3D *iface,
371                                   LPD3DENUMDEVICESCALLBACK Callback,
372                                   void *Context)
373 {
374     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
375     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Callback, Context);
376     return IDirect3D3_EnumDevices(ICOM_INTERFACE(This, IDirect3D3),
377                                   Callback,
378                                   Context);
379 }
380
381 /*****************************************************************************
382  * IDirect3D3::CreateLight
383  *
384  * Creates an IDirect3DLight interface. This interface is used in
385  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
386  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
387  * uses the IDirect3DDevice7 interface with D3D7 lights.
388  *
389  * Version 1, 2 and 3
390  *
391  * Params:
392  *  Light: Address to store the new interface pointer
393  *  UnkOuter: Basically for aggregation, but ddraw doesn't support it.
394  *            Must be NULL
395  *
396  * Returns:
397  *  D3D_OK on success
398  *  DDERR_OUTOFMEMORY if memory allocation failed
399  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
400  *
401  *****************************************************************************/
402 static HRESULT WINAPI
403 IDirect3DImpl_3_CreateLight(IDirect3D3 *iface,
404                             IDirect3DLight **Light,
405                             IUnknown *UnkOuter )
406 {
407     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
408     IDirect3DLightImpl *object;
409
410     TRACE("(%p)->(%p,%p)\n", This, Light, UnkOuter);
411
412     if(UnkOuter)
413         return CLASS_E_NOAGGREGATION;
414
415     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DLightImpl));
416     if (object == NULL)
417         return DDERR_OUTOFMEMORY;
418
419     ICOM_INIT_INTERFACE(object, IDirect3DLight, IDirect3DLight_Vtbl);
420     object->ref = 1;
421     object->ddraw = This;
422     object->next = NULL;
423     object->active_viewport = NULL;
424
425     /* Update functions */
426     object->activate = light_update;
427     object->desactivate = light_activate;
428     object->update = light_desactivate;
429     object->active_viewport = NULL;
430
431     *Light = ICOM_INTERFACE(object, IDirect3DLight);
432
433     TRACE("(%p) creating implementation at %p.\n", This, object);
434
435     return D3D_OK;
436 }
437
438 static HRESULT WINAPI
439 Thunk_IDirect3DImpl_2_CreateLight(IDirect3D2 *iface,
440                                   IDirect3DLight **Direct3DLight,
441                                   IUnknown *UnkOuter)
442 {
443     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
444     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DLight, UnkOuter);
445     return IDirect3D3_CreateLight(ICOM_INTERFACE(This, IDirect3D3),
446                                   Direct3DLight,
447                                   UnkOuter);
448 }
449
450 static HRESULT WINAPI
451 Thunk_IDirect3DImpl_1_CreateLight(IDirect3D *iface,
452                                   IDirect3DLight **Direct3DLight,
453                                   IUnknown *UnkOuter)
454 {
455     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
456     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DLight, UnkOuter);
457     return IDirect3D3_CreateLight(ICOM_INTERFACE(This, IDirect3D3),
458                                   Direct3DLight,
459                                   UnkOuter);
460 }
461
462 /*****************************************************************************
463  * IDirect3D3::CreateMaterial
464  *
465  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
466  * and older versions. The IDirect3DMaterial implementation wraps its
467  * functionality to IDirect3DDevice7::SetMaterial and friends.
468  *
469  * Version 1, 2 and 3
470  *
471  * Params:
472  *  Material: Address to store the new interface's pointer to
473  *  UnkOuter: Basically for aggregation, but ddraw doesn't support it.
474  *            Must be NULL
475  *
476  * Returns:
477  *  D3D_OK on success
478  *  DDERR_OUTOFMEMORY if memory allocation failed
479  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
480  *
481  *****************************************************************************/
482 static HRESULT WINAPI
483 IDirect3DImpl_3_CreateMaterial(IDirect3D3 *iface,
484                                IDirect3DMaterial3 **Material,
485                                IUnknown *UnkOuter )
486 {
487     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
488     IDirect3DMaterialImpl *object;
489
490     TRACE("(%p)->(%p,%p)\n", This, Material, UnkOuter);
491
492     if(UnkOuter)
493         return CLASS_E_NOAGGREGATION;
494
495     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DMaterialImpl));
496     if (object == NULL)
497         return DDERR_OUTOFMEMORY;
498
499     ICOM_INIT_INTERFACE(object, IDirect3DMaterial3, IDirect3DMaterial3_Vtbl);
500     ICOM_INIT_INTERFACE(object, IDirect3DMaterial2, IDirect3DMaterial2_Vtbl);
501     ICOM_INIT_INTERFACE(object, IDirect3DMaterial, IDirect3DMaterial_Vtbl);
502     object->ref = 1;
503     object->ddraw = This;
504     object->activate = material_activate;
505
506     *Material = ICOM_INTERFACE(object, IDirect3DMaterial3);
507
508     TRACE("(%p) creating implementation at %p.\n", This, object);
509
510     return D3D_OK;
511 }
512
513 static HRESULT WINAPI
514 Thunk_IDirect3DImpl_2_CreateMaterial(IDirect3D2 *iface,
515                                      IDirect3DMaterial2 **Direct3DMaterial,
516                                      IUnknown* UnkOuter)
517 {
518     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
519     HRESULT ret;
520     IDirect3DMaterial3 *ret_val;
521
522     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DMaterial, UnkOuter);
523     ret = IDirect3D3_CreateMaterial(ICOM_INTERFACE(This, IDirect3D3),
524                                     &ret_val,
525                                     UnkOuter);
526
527     *Direct3DMaterial = COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial3, IDirect3DMaterial2, ret_val);
528
529     TRACE(" returning interface %p.\n", *Direct3DMaterial);
530
531     return ret;
532 }
533
534 static HRESULT WINAPI
535 Thunk_IDirect3DImpl_1_CreateMaterial(IDirect3D *iface,
536                                      IDirect3DMaterial **Direct3DMaterial,
537                                      IUnknown* UnkOuter)
538 {
539     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
540     HRESULT ret;
541     LPDIRECT3DMATERIAL3 ret_val;
542
543     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DMaterial, UnkOuter);
544     ret = IDirect3D3_CreateMaterial(ICOM_INTERFACE(This, IDirect3D3),
545                                     &ret_val,
546                                     UnkOuter);
547
548     *Direct3DMaterial = COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial3, IDirect3DMaterial, ret_val);
549
550     TRACE(" returning interface %p.\n", *Direct3DMaterial);
551
552     return ret;
553 }
554
555 /*****************************************************************************
556  * IDirect3D3::CreateViewport
557  *
558  * Creates an IDirect3DViewport interface. This interface is used
559  * by Direct3D and earlier versions for Viewport management. In Direct3D7
560  * it has been replaced by a viewport structure and
561  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
562  * uses the IDirect3DDevice7 methods for its functionality
563  *
564  * Params:
565  *  Viewport: Address to store the new interface pointer
566  *  UnkOuter: Basically for aggregation, but ddraw doesn't support it.
567  *            Must be NULL
568  *
569  * Returns:
570  *  D3D_OK on success
571  *  DDERR_OUTOFMEMORY if memory allocation failed
572  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
573  *
574  *****************************************************************************/
575 static HRESULT WINAPI
576 IDirect3DImpl_3_CreateViewport(IDirect3D3 *iface,
577                               IDirect3DViewport3 **Viewport,
578                               IUnknown *UnkOuter )
579 {
580     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
581     IDirect3DViewportImpl *object;
582
583     if(UnkOuter)
584         return CLASS_E_NOAGGREGATION;
585
586     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DViewportImpl));
587     if (object == NULL)
588         return DDERR_OUTOFMEMORY;
589
590     ICOM_INIT_INTERFACE(object, IDirect3DViewport3, IDirect3DViewport3_Vtbl);
591     object->ref = 1;
592     object->ddraw = This;
593     object->activate = viewport_activate;
594     object->use_vp2 = 0xFF;
595     object->next = NULL;
596     object->lights = NULL;
597     object->num_lights = 0;
598     object->map_lights = 0;
599
600     *Viewport = ICOM_INTERFACE(object, IDirect3DViewport3);
601
602     TRACE("(%p) creating implementation at %p.\n",This, object);
603
604     return D3D_OK;
605 }
606
607 static HRESULT WINAPI
608 Thunk_IDirect3DImpl_2_CreateViewport(IDirect3D2 *iface,
609                                      IDirect3DViewport2 **D3DViewport2,
610                                      IUnknown *UnkOuter)
611 {
612     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
613     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, D3DViewport2, UnkOuter);
614
615     return IDirect3D3_CreateViewport(ICOM_INTERFACE(This, IDirect3D3),
616                                      (IDirect3DViewport3 **) D3DViewport2 /* No need to cast here */,
617                                      UnkOuter);
618 }
619
620 static HRESULT WINAPI
621 Thunk_IDirect3DImpl_1_CreateViewport(IDirect3D *iface,
622                                      IDirect3DViewport **D3DViewport,
623                                      IUnknown* UnkOuter)
624 {
625     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
626     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, D3DViewport, UnkOuter);
627
628     return IDirect3D3_CreateViewport(ICOM_INTERFACE(This, IDirect3D3),
629                                      (IDirect3DViewport3 **) D3DViewport /* No need to cast here */,
630                                      UnkOuter);
631 }
632
633 /*****************************************************************************
634  * IDirect3D3::FindDevice
635  *
636  * This method finds a device with the requested properties and returns a
637  * device description
638  *
639  * Verion 1, 2 and 3
640  * Params:
641  *  D3DDFS: Describes the requested device characteristics
642  *  D3DFDR: Returns the device description
643  *
644  * Returns:
645  *  D3D_OK on success
646  *  DDERR_INVALIDPARAMS if no device was found
647  *
648  *****************************************************************************/
649 static HRESULT WINAPI
650 IDirect3DImpl_3_FindDevice(IDirect3D3 *iface,
651                            D3DFINDDEVICESEARCH *D3DDFS,
652                            D3DFINDDEVICERESULT *D3DFDR)
653 {
654     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
655     D3DDEVICEDESC desc;
656     D3DDEVICEDESC7 newDesc;
657     HRESULT hr;
658
659     TRACE("(%p)->(%p,%p)\n", This, D3DDFS, D3DFDR);
660
661     if ((D3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
662         (D3DDFS->dcmColorModel != D3DCOLOR_RGB))
663     {
664         TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
665         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
666     }
667     if (D3DDFS->dwFlags & D3DFDS_GUID)
668     {
669         TRACE(" trying to match guid %s.\n", debugstr_guid(&(D3DDFS->guid)));
670         if ((IsEqualGUID(&IID_D3DDEVICE_WineD3D, &(D3DDFS->guid)) == 0) &&
671             (IsEqualGUID(&IID_IDirect3DHALDevice, &(D3DDFS->guid)) == 0) &&
672             (IsEqualGUID(&IID_IDirect3DRefDevice, &(D3DDFS->guid)) == 0))
673         {
674             TRACE(" no match for this GUID.\n");
675             return DDERR_INVALIDPARAMS;
676         }
677     }
678
679     /* Get the caps */
680     hr = IDirect3DImpl_GetCaps(This->wineD3D, &desc, &newDesc);
681     if(hr != D3D_OK) return hr;
682
683     /* Now return our own GUID */
684     D3DFDR->guid = IID_D3DDEVICE_WineD3D;
685     D3DFDR->ddHwDesc = desc;
686     D3DFDR->ddSwDesc = desc;
687
688     TRACE(" returning Wine's WineD3D device with (undumped) capabilities\n");
689
690     return D3D_OK;
691 }
692
693 static HRESULT WINAPI
694 Thunk_IDirect3DImpl_2_FindDevice(IDirect3D2 *iface,
695                                  D3DFINDDEVICESEARCH *D3DDFS,
696                                  D3DFINDDEVICERESULT *D3DFDR)
697 {
698     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
699     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, D3DDFS, D3DFDR);
700     return IDirect3D3_FindDevice(ICOM_INTERFACE(This, IDirect3D3),
701                                  D3DDFS,
702                                  D3DFDR);
703 }
704
705 static HRESULT WINAPI
706 Thunk_IDirect3DImpl_1_FindDevice(IDirect3D *iface,
707                                 D3DFINDDEVICESEARCH *D3DDFS,
708                                 D3DFINDDEVICERESULT *D3DDevice)
709 {
710     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
711     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, D3DDFS, D3DDevice);
712     return IDirect3D3_FindDevice(ICOM_INTERFACE(This, IDirect3D3),
713                                  D3DDFS,
714                                  D3DDevice);
715 }
716
717 /*****************************************************************************
718  * IDirect3D7::CreateDevice
719  *
720  * Creates an IDirect3DDevice7 interface.
721  *
722  * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
723  * DirectDraw surfaces and are created with
724  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
725  * create the device object and QueryInterfaces for IDirect3DDevice
726  *
727  * Params:
728  *  refiid: IID of the device to create
729  *  Surface: Inititial rendertarget
730  *  Device: Address to return the interface pointer
731  *
732  * Returns:
733  *  D3D_OK on success
734  *  DDERR_OUTOFMEMORY if memory allocation failed
735  *  DDERR_INVALIDPARAMS if a device exists already
736  *
737  *****************************************************************************/
738 static HRESULT WINAPI
739 IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
740                              REFCLSID refiid,
741                              IDirectDrawSurface7 *Surface,
742                              IDirect3DDevice7 **Device)
743 {
744     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
745     IDirect3DDeviceImpl *object;
746     IParentImpl *IndexBufferParent;
747     HRESULT hr;
748     IDirectDrawSurfaceImpl *target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Surface);
749     TRACE("(%p)->(%s,%p,%p)\n", iface, debugstr_guid(refiid), Surface, Device);
750
751     *Device = NULL;
752
753     /* Fail device creation if non-opengl surfaces are used */
754     if(This->ImplType != SURFACE_OPENGL)
755     {
756         ERR("The application wants to create a Direct3D device, but non-opengl surfaces are set in the registry. Please set the surface implementation to opengl or autodetection to allow 3D rendering\n");
757
758         /* We only hit this path if a default surface is set in the registry. Incorrect autodetection
759          * is caught in CreateSurface or QueryInterface
760          */
761         return DDERR_NO3D;
762     }
763
764     /* So far we can only create one device per ddraw object */
765     if(This->d3ddevice)
766     {
767         FIXME("(%p): Only one Direct3D device per DirectDraw object supported\n", This);
768         return DDERR_INVALIDPARAMS;
769     }
770
771     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirect3DDeviceImpl));
772     if(!object)
773     {
774         ERR("Out of memory when allocating a IDirect3DDevice implementation\n");
775         return DDERR_OUTOFMEMORY;
776     }
777
778     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, IDirect3DDevice7_Vtbl);
779     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, IDirect3DDevice3_Vtbl);
780     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, IDirect3DDevice2_Vtbl);
781     ICOM_INIT_INTERFACE(object, IDirect3DDevice, IDirect3DDevice1_Vtbl);
782
783     object->ref = 1;
784     object->ddraw = This;
785     object->viewport_list = NULL;
786     object->current_viewport = NULL;
787     object->material = 0;
788     object->target = target;
789
790     object->Handles = NULL;
791     object->numHandles = 0;
792
793     /* This is for convenience */
794     object->wineD3DDevice = This->wineD3DDevice;
795
796     /* Create an index buffer, it's needed for indexed drawing */
797     IndexBufferParent = HeapAlloc(GetProcessHeap(), 0, sizeof(IParentImpl *));
798     if(!IndexBufferParent)
799     {
800         ERR("Allocating memory for an index buffer parent failed\n");
801         HeapFree(GetProcessHeap(), 0, object);
802         return DDERR_OUTOFMEMORY;
803     }
804     ICOM_INIT_INTERFACE(IndexBufferParent, IParent, IParent_Vtbl);
805     IndexBufferParent->ref = 1;
806
807     /* Create an Index Buffer. WineD3D needs one for Drawing indexed primitives
808      * Create a (hopefully) long enough buffer, and copy the indices into it
809      * Ideally, a IWineD3DIndexBuffer::SetData method could be created, which
810      * takes the pointer and avoids the memcpy
811      */
812     hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice,
813                                           0x40000, /* Length. Don't know how long it should be */
814                                           WINED3DUSAGE_DYNAMIC, /* Usage */
815                                           WINED3DFMT_INDEX16, /* Format. D3D7 uses WORDS */
816                                           WINED3DPOOL_DEFAULT,
817                                           &object->indexbuffer,
818                                           0 /* Handle */,
819                                           (IUnknown *) ICOM_INTERFACE(IndexBufferParent, IParent));
820
821     if(FAILED(hr))
822     {
823         ERR("Failed to create an index buffer\n");
824         HeapFree(GetProcessHeap(), 0, object);
825         return hr;
826     }
827     IndexBufferParent->child = (IUnknown *) object->indexbuffer;
828
829     /* No need to set the indices, it's done when necessary */
830
831     /* AddRef the WineD3D Device */
832     IWineD3DDevice_AddRef(This->wineD3DDevice);
833
834     /* Don't forget to return the interface ;) */
835     *Device = ICOM_INTERFACE(object, IDirect3DDevice7);
836
837     TRACE(" (%p) Created an IDirect3DDeviceImpl object at %p\n", This, object);
838
839     /* This is for apps which create a non-flip, non-d3d primary surface
840      * and an offscreen D3DDEVICE surface, then render to the offscreen surface
841      * and do a Blt from the offscreen to the primary surface.
842      *
843      * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
844      * and the primary surface(=This->d3d_target) as the front buffer.
845      *
846      * This way the app will render to the D3DDEVICE surface and WineD3D
847      * will catch the Blt was Back Buffer -> Front buffer blt and perform
848      * a flip instead. This way we don't have to deal with a mixed GL / GDI
849      * environment.
850      *
851      * This should be checked against windowed apps. The only app tested with
852      * this is moto racer 2 during the loading screen.
853      */
854     TRACE("Isrendertarget: %s, d3d_target=%p\n", target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", This->d3d_target);
855     if(!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
856        (This->d3d_target != target))
857     {
858         WINED3DVIEWPORT vp;
859         TRACE("(%p) Using %p as front buffer, %p as back buffer\n", This, This->d3d_target, target);
860         hr = IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
861                                                 This->d3d_target->WineD3DSurface,
862                                                 target->WineD3DSurface);
863         if(hr != D3D_OK)
864             ERR("(%p) Error %08x setting the front and back buffer\n", This, hr);
865
866         /* Render to the back buffer */
867         IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
868                                        target->WineD3DSurface);
869
870         vp.X = 0;
871         vp.Y = 0;
872         vp.Width = target->surface_desc.dwWidth;
873         vp.Height = target->surface_desc.dwHeight;
874         vp.MinZ = 0.0;
875         vp.MaxZ = 1.0;
876         IWineD3DDevice_SetViewport(This->wineD3DDevice,
877                                    &vp);
878
879         object->OffScreenTarget = TRUE;
880     }
881     else
882     {
883         object->OffScreenTarget = FALSE;
884     }
885
886     /* AddRef the render target. Also AddRef the render target from ddraw,
887      * because if it is released before the app releases the D3D device, the D3D capabilities
888      * of WineD3D will be uninitialized, which has bad effects.
889      *
890      * In most cases, those surfaces are the surfaces are the same anyway, but this will simply
891      * add another ref which is released when the device is destroyed.
892      */
893     IDirectDrawSurface7_AddRef(Surface);
894     IDirectDrawSurface7_AddRef(ICOM_INTERFACE(This->d3d_target, IDirectDrawSurface7));
895
896     This->d3ddevice = object;
897
898     IWineD3DDevice_SetRenderState(This->wineD3DDevice,
899                                   WINED3DRS_ZENABLE,
900                                   IDirect3DDeviceImpl_UpdateDepthStencil(object));
901     return D3D_OK;
902 }
903
904 static HRESULT WINAPI
905 Thunk_IDirect3DImpl_3_CreateDevice(IDirect3D3 *iface,
906                                    REFCLSID refiid,
907                                    IDirectDrawSurface4 *Surface,
908                                    IDirect3DDevice3 **Device,
909                                    IUnknown *UnkOuter)
910 {
911     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
912     HRESULT hr;
913     TRACE("(%p)->(%s,%p,%p,%p): Thunking to IDirect3D7\n", This, debugstr_guid(refiid), Surface, Device, UnkOuter);
914
915     if(UnkOuter != NULL)
916         return CLASS_E_NOAGGREGATION;
917
918     hr =  IDirect3D7_CreateDevice(ICOM_INTERFACE(This, IDirect3D7),
919                                   refiid,
920                                   (IDirectDrawSurface7 *) Surface /* Same VTables */,
921                                   (IDirect3DDevice7 **) Device);
922
923     *Device = COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice7, IDirect3DDevice3, *Device);
924     return hr;
925 }
926
927 static HRESULT WINAPI
928 Thunk_IDirect3DImpl_2_CreateDevice(IDirect3D2 *iface,
929                                    REFCLSID refiid,
930                                    IDirectDrawSurface *Surface,
931                                    IDirect3DDevice2 **Device)
932 {
933     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
934     HRESULT hr;
935     TRACE("(%p)->(%s,%p,%p): Thunking to IDirect3D7\n", This, debugstr_guid(refiid), Surface, Device);
936
937     hr =  IDirect3D7_CreateDevice(ICOM_INTERFACE(This, IDirect3D7),
938                                   refiid,
939                                   COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirectDrawSurface3, IDirectDrawSurface7, Surface),
940                                   (IDirect3DDevice7 **) Device);
941
942     *Device = COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice7, IDirect3DDevice2, *Device);
943     return hr;
944 }
945
946 /*****************************************************************************
947  * IDirect3D7::CreateVertexBuffer
948  *
949  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
950  * interface.
951  *
952  * Version 3 and 7
953  *
954  * Params:
955  *  Desc: Requested Vertex buffer properties
956  *  VertexBuffer: Address to return the interface pointer at
957  *  Flags: Some flags, must be 0
958  *
959  * Returns
960  *  D3D_OK on success
961  *  DDERR_OUTOFMEMORY if memory allocation failed
962  *  The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
963  *  DDERR_INVALIDPARAMS if Desc or VertexBuffer are NULL, or Flags != 0
964  *
965  *****************************************************************************/
966 static HRESULT WINAPI
967 IDirect3DImpl_7_CreateVertexBuffer(IDirect3D7 *iface,
968                                    D3DVERTEXBUFFERDESC *Desc,
969                                    IDirect3DVertexBuffer7 **VertexBuffer,
970                                    DWORD Flags)
971 {
972     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
973     IDirect3DVertexBufferImpl *object;
974     HRESULT hr;
975     TRACE("(%p)->(%p,%p,%08x)\n", This, Desc, VertexBuffer, Flags);
976
977     TRACE("(%p) Vertex buffer description:\n", This);
978     TRACE("(%p)  dwSize=%d\n", This, Desc->dwSize);
979     TRACE("(%p)  dwCaps=%08x\n", This, Desc->dwCaps);
980     TRACE("(%p)  FVF=%08x\n", This, Desc->dwFVF);
981     TRACE("(%p)  dwNumVertices=%d\n", This, Desc->dwNumVertices);
982
983     /* D3D7 SDK: "No Flags are currently defined for this method. This
984      * parameter must be 0"
985      *
986      * Never trust the documentation - this is wrong
987     if(Flags != 0)
988     {
989         ERR("(%p) Flags is %08lx, returning DDERR_INVALIDPARAMS\n", This, Flags);
990         return DDERR_INVALIDPARAMS;
991     }
992      */
993
994     /* Well, this sounds sane */
995     if( (!VertexBuffer) || (!Desc) )
996         return DDERR_INVALIDPARAMS;
997
998     /* Now create the vertex buffer */
999     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirect3DVertexBufferImpl));
1000     if(!object)
1001     {
1002         ERR("(%p) Out of memory when allocating a IDirect3DVertexBufferImpl structure\n", This);
1003         return DDERR_OUTOFMEMORY;
1004     }
1005
1006     object->ref = 1;
1007     ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer7, IDirect3DVertexBuffer7_Vtbl);
1008     ICOM_INIT_INTERFACE(object, IDirect3DVertexBuffer, IDirect3DVertexBuffer1_Vtbl);
1009
1010     object->Caps = Desc->dwCaps;
1011     object->ddraw = This;
1012
1013     hr = IWineD3DDevice_CreateVertexBuffer(This->wineD3DDevice,
1014                                            get_flexible_vertex_size(Desc->dwFVF) * Desc->dwNumVertices,
1015                                            Desc->dwCaps & D3DVBCAPS_WRITEONLY ? WINED3DUSAGE_WRITEONLY : 0,
1016                                            Desc->dwFVF,
1017                                            Desc->dwCaps & D3DVBCAPS_SYSTEMMEMORY ? WINED3DPOOL_SYSTEMMEM : WINED3DPOOL_DEFAULT,
1018                                            &object->wineD3DVertexBuffer,
1019                                            0 /* SharedHandle */,
1020                                            (IUnknown *) ICOM_INTERFACE(object, IDirect3DVertexBuffer7));
1021     if(hr != D3D_OK)
1022     {
1023         ERR("(%p) IWineD3DDevice::CreateVertexBuffer failed with hr=%08x\n", This, hr);
1024         HeapFree(GetProcessHeap(), 0, object);
1025         if (hr == WINED3DERR_INVALIDCALL)
1026             return DDERR_INVALIDPARAMS;
1027         else
1028             return hr;
1029     }
1030
1031     object->wineD3DVertexDeclaration = IDirectDrawImpl_FindDecl(This,
1032                                                                 Desc->dwFVF);
1033     if(!object->wineD3DVertexDeclaration)
1034     {
1035         ERR("Cannot find the vertex declaration for fvf %08x\n", Desc->dwFVF);
1036         IWineD3DVertexBuffer_Release(object->wineD3DVertexBuffer);
1037         HeapFree(GetProcessHeap(), 0, object);
1038         return DDERR_INVALIDPARAMS;
1039     }
1040     IWineD3DVertexDeclaration_AddRef(object->wineD3DVertexDeclaration);
1041
1042     /* Return the interface */
1043     *VertexBuffer = ICOM_INTERFACE(object, IDirect3DVertexBuffer7);
1044
1045     TRACE("(%p) Created new vertex buffer implementation at %p, returning interface at %p\n", This, object, *VertexBuffer);
1046     return D3D_OK;
1047 }
1048
1049 static HRESULT WINAPI
1050 Thunk_IDirect3DImpl_3_CreateVertexBuffer(IDirect3D3 *iface,
1051                                          D3DVERTEXBUFFERDESC *Desc,
1052                                          IDirect3DVertexBuffer **VertexBuffer,
1053                                          DWORD Flags,
1054                                          IUnknown *UnkOuter)
1055 {
1056     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
1057     HRESULT hr;
1058     TRACE("(%p)->(%p,%p,%08x,%p): Relaying to IDirect3D7\n", This, Desc, VertexBuffer, Flags, UnkOuter);
1059
1060     if(UnkOuter != NULL) return CLASS_E_NOAGGREGATION;
1061
1062     hr = IDirect3D7_CreateVertexBuffer(ICOM_INTERFACE(This, IDirect3D7),
1063                                        Desc,
1064                                        (IDirect3DVertexBuffer7 **) VertexBuffer,
1065                                        Flags);
1066
1067     *VertexBuffer = COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, IDirect3DVertexBuffer, *VertexBuffer);
1068     return hr;
1069 }
1070
1071
1072 /*****************************************************************************
1073  * IDirect3D7::EnumZBufferFormats
1074  *
1075  * Enumerates all supported Z buffer pixel formats
1076  *
1077  * Version 3 and 7
1078  *
1079  * Params:
1080  *  refiidDevice:
1081  *  Callback: Callback to call for each pixel format
1082  *  Context: Pointer to pass back to the callback
1083  *
1084  * Returns:
1085  *  D3D_OK on success
1086  *  DDERR_INVALIDPARAMS if Callback is NULL
1087  *  For details, see IWineD3DDevice::EnumZBufferFormats
1088  *
1089  *****************************************************************************/
1090 static HRESULT WINAPI
1091 IDirect3DImpl_7_EnumZBufferFormats(IDirect3D7 *iface,
1092                                    REFCLSID refiidDevice,
1093                                    LPD3DENUMPIXELFORMATSCALLBACK Callback,
1094                                    void *Context)
1095 {
1096     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
1097     HRESULT hr;
1098     int i;
1099
1100     /* Order matters. Specifically, BattleZone II (full version) expects the
1101      * 16-bit depth formats to be listed before the 24 and 32 ones. */
1102     WINED3DFORMAT FormatList[] = {
1103         WINED3DFMT_D15S1,
1104         WINED3DFMT_D16,
1105         WINED3DFMT_D24X8,
1106         WINED3DFMT_D24X4S4,
1107         WINED3DFMT_D24S8,
1108         WINED3DFMT_D32
1109     };
1110
1111     TRACE("(%p)->(%s,%p,%p): Relay\n", iface, debugstr_guid(refiidDevice), Callback, Context);
1112
1113     if(!Callback)
1114         return DDERR_INVALIDPARAMS;
1115
1116     for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1117     {
1118         hr = IWineD3D_CheckDeviceFormat(This->wineD3D,
1119                                         0 /* Adapter */,
1120                                         0 /* DeviceType */,
1121                                         0 /* AdapterFormat */,
1122                                         WINED3DUSAGE_DEPTHSTENCIL /* Usage */,
1123                                         0 /* ResourceType */,
1124                                         FormatList[i]);
1125         if(hr == D3D_OK)
1126         {
1127             DDPIXELFORMAT pformat;
1128
1129             memset(&pformat, 0, sizeof(pformat));
1130             pformat.dwSize = sizeof(pformat);
1131             PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1132
1133             TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1134             hr = Callback(&pformat, Context);
1135             if(hr != DDENUMRET_OK)
1136             {
1137                 TRACE("Format enumeration cancelled by application\n");
1138                 return D3D_OK;
1139             }
1140         }
1141     }
1142     TRACE("End of enumeration\n");
1143     return D3D_OK;
1144 }
1145
1146 static HRESULT WINAPI
1147 Thunk_IDirect3DImpl_3_EnumZBufferFormats(IDirect3D3 *iface,
1148                                          REFCLSID riidDevice,
1149                                          LPD3DENUMPIXELFORMATSCALLBACK Callback,
1150                                          void *Context)
1151 {
1152     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
1153     TRACE("(%p)->(%s,%p,%p) thunking to IDirect3D7 interface.\n", This, debugstr_guid(riidDevice), Callback, Context);
1154     return IDirect3D7_EnumZBufferFormats(ICOM_INTERFACE(This, IDirect3D7),
1155                                          riidDevice,
1156                                          Callback,
1157                                          Context);
1158 }
1159
1160 /*****************************************************************************
1161  * IDirect3D7::EvictManagedTextures
1162  *
1163  * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
1164  * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
1165  *
1166  * Version 3 and 7
1167  *
1168  * Returns:
1169  *  D3D_OK, because it's a stub
1170  *
1171  *****************************************************************************/
1172 static HRESULT WINAPI
1173 IDirect3DImpl_7_EvictManagedTextures(IDirect3D7 *iface)
1174 {
1175     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
1176     FIXME("(%p): Stub!\n", This);
1177
1178     /* Implementation idea:
1179      * Add an IWineD3DSurface method which sets the opengl texture
1180      * priority low or even removes the opengl texture.
1181      */
1182
1183     return D3D_OK;
1184 }
1185
1186 static HRESULT WINAPI
1187 Thunk_IDirect3DImpl_3_EvictManagedTextures(IDirect3D3 *iface)
1188 {
1189     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
1190     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", This);
1191     return IDirect3D7_EvictManagedTextures(ICOM_INTERFACE(This, IDirect3D7));
1192 }
1193
1194 /*****************************************************************************
1195  * IDirect3DImpl_GetCaps
1196  *
1197  * This function retrieves the device caps from wined3d
1198  * and converts it into a D3D7 and D3D - D3D3 structure
1199  * This is a helper function called from various places in ddraw
1200  *
1201  * Params:
1202  *  WineD3D: The interface to get the caps from
1203  *  Desc123: Old D3D <3 structure to fill (needed)
1204  *  Desc7: D3D7 device desc structure to fill (needed)
1205  *
1206  * Returns
1207  *  D3D_OK on success, or the return value of IWineD3D::GetCaps
1208  *
1209  *****************************************************************************/
1210 HRESULT
1211 IDirect3DImpl_GetCaps(IWineD3D *WineD3D,
1212                       D3DDEVICEDESC *Desc123,
1213                       D3DDEVICEDESC7 *Desc7)
1214 {
1215     WINED3DCAPS WCaps;
1216     HRESULT hr;
1217
1218     /* Some Variables to asign to the pointers in WCaps */
1219     WINED3DDEVTYPE DevType;
1220     UINT dummy_uint;
1221     float dummy_float;
1222     DWORD dummy_dword, MaxTextureBlendStages, MaxSimultaneousTextures;
1223     DWORD MaxUserClipPlanes, MaxVertexBlendMatrices;
1224
1225     TRACE("()->(%p,%p,%p\n", WineD3D, Desc123, Desc7);
1226
1227     /* Asign the pointers in WCaps */
1228     WCaps.DeviceType = &DevType;
1229     WCaps.AdapterOrdinal = &dummy_uint;
1230
1231     WCaps.Caps = &dummy_dword;
1232     WCaps.Caps2 = &dummy_dword;
1233     WCaps.Caps3 = &dummy_dword;
1234     WCaps.PresentationIntervals = &dummy_dword;
1235
1236     WCaps.CursorCaps = &dummy_dword;
1237
1238     WCaps.DevCaps = &Desc7->dwDevCaps;
1239     WCaps.PrimitiveMiscCaps = &dummy_dword;
1240     WCaps.RasterCaps = &Desc7->dpcLineCaps.dwRasterCaps;
1241     WCaps.ZCmpCaps = &Desc7->dpcLineCaps.dwZCmpCaps;
1242     WCaps.SrcBlendCaps = &Desc7->dpcLineCaps.dwSrcBlendCaps;
1243     WCaps.DestBlendCaps = &Desc7->dpcLineCaps.dwDestBlendCaps;
1244     WCaps.AlphaCmpCaps = &Desc7->dpcLineCaps.dwAlphaCmpCaps;
1245     WCaps.ShadeCaps = &Desc7->dpcLineCaps.dwShadeCaps;
1246     WCaps.TextureCaps = &Desc7->dpcLineCaps.dwTextureCaps;
1247     WCaps.TextureFilterCaps = &Desc7->dpcLineCaps.dwTextureFilterCaps;
1248     WCaps.CubeTextureFilterCaps = &dummy_dword;
1249     WCaps.VolumeTextureFilterCaps = &dummy_dword;
1250     WCaps.TextureAddressCaps = &Desc7->dpcLineCaps.dwTextureAddressCaps;
1251     WCaps.VolumeTextureAddressCaps = &dummy_dword;
1252
1253     WCaps.LineCaps = &dummy_dword;
1254     WCaps.MaxTextureWidth = &Desc7->dwMaxTextureWidth;
1255     WCaps.MaxTextureHeight = &Desc7->dwMaxTextureHeight;
1256     WCaps.MaxVolumeExtent = &dummy_dword;
1257
1258     WCaps.MaxTextureRepeat = &Desc7->dwMaxTextureRepeat;
1259     WCaps.MaxTextureAspectRatio = &Desc7->dwMaxTextureAspectRatio;
1260     WCaps.MaxAnisotropy = &Desc7->dwMaxAnisotropy;
1261     WCaps.MaxVertexW = &Desc7->dvMaxVertexW;
1262
1263     WCaps.GuardBandLeft = &Desc7->dvGuardBandLeft;
1264     WCaps.GuardBandTop = &Desc7->dvGuardBandTop;
1265     WCaps.GuardBandRight = &Desc7->dvGuardBandRight;
1266     WCaps.GuardBandBottom = &Desc7->dvGuardBandBottom;
1267
1268     WCaps.ExtentsAdjust = &Desc7->dvExtentsAdjust;
1269     WCaps.StencilCaps = &Desc7->dwStencilCaps;
1270
1271     WCaps.FVFCaps = &Desc7->dwFVFCaps;
1272     WCaps.TextureOpCaps = &Desc7->dwTextureOpCaps;
1273     WCaps.MaxTextureBlendStages = &MaxTextureBlendStages;
1274     WCaps.MaxSimultaneousTextures = &MaxSimultaneousTextures;
1275
1276     WCaps.VertexProcessingCaps = &Desc7->dwVertexProcessingCaps;
1277     WCaps.MaxActiveLights = &Desc7->dwMaxActiveLights;
1278     WCaps.MaxUserClipPlanes = &MaxUserClipPlanes;
1279     WCaps.MaxVertexBlendMatrices = &MaxVertexBlendMatrices;
1280     WCaps.MaxVertexBlendMatrixIndex = &dummy_dword;
1281
1282     WCaps.MaxPointSize = &dummy_float;
1283     WCaps.MaxPrimitiveCount = &dummy_dword;
1284     WCaps.MaxVertexIndex = &dummy_dword;
1285     WCaps.MaxStreams = &dummy_dword;
1286     WCaps.MaxStreamStride = &dummy_dword;
1287
1288     WCaps.VertexShaderVersion = &dummy_dword;
1289     WCaps.MaxVertexShaderConst = &dummy_dword;
1290
1291     WCaps.PixelShaderVersion = &dummy_dword;
1292     WCaps.PixelShader1xMaxValue = &dummy_float;
1293
1294     /* These are dx9 only, set them to NULL */
1295     WCaps.DevCaps2 = NULL;
1296     WCaps.MaxNpatchTessellationLevel = NULL;
1297     WCaps.Reserved5 = NULL;
1298     WCaps.MasterAdapterOrdinal = NULL;
1299     WCaps.AdapterOrdinalInGroup = NULL;
1300     WCaps.NumberOfAdaptersInGroup = NULL;
1301     WCaps.DeclTypes = NULL;
1302     WCaps.NumSimultaneousRTs = NULL;
1303     WCaps.StretchRectFilterCaps = NULL;
1304     /* WCaps.VS20Caps = NULL; */
1305     /* WCaps.PS20Caps = NULL; */
1306     WCaps.VertexTextureFilterCaps = NULL;
1307     WCaps.MaxVShaderInstructionsExecuted = NULL;
1308     WCaps.MaxPShaderInstructionsExecuted = NULL;
1309     WCaps.MaxVertexShader30InstructionSlots = NULL;
1310     WCaps.MaxPixelShader30InstructionSlots = NULL;
1311     WCaps.Reserved2 = NULL;
1312     WCaps.Reserved3 = NULL;
1313
1314     /* Now get the caps */
1315     hr = IWineD3D_GetDeviceCaps(WineD3D, 0, WINED3DDEVTYPE_HAL, &WCaps);
1316     if(hr != D3D_OK) return hr;
1317
1318     /* Remove all non-d3d7 caps */
1319     Desc7->dwDevCaps &= (
1320         D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
1321         D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
1322         D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
1323         D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
1324         D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
1325         D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
1326         D3DDEVCAPS_HWRASTERIZATION);
1327
1328     Desc7->dwStencilCaps &= (
1329         D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
1330         D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
1331         D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR                 | D3DSTENCILCAPS_TWOSIDED);
1332
1333     /* FVF caps ?*/
1334
1335     Desc7->dwTextureOpCaps &= (
1336         D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
1337         D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
1338         D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
1339         D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
1340         D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
1341         D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
1342         D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
1343         D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
1344
1345     Desc7->dwVertexProcessingCaps &= (
1346         D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
1347         D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
1348
1349     Desc7->dpcLineCaps.dwMiscCaps &= (
1350         D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
1351         D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
1352         D3DPMISCCAPS_CULLCCW);
1353
1354     Desc7->dpcLineCaps.dwRasterCaps &= (
1355         D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
1356         D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
1357         D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
1358         D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
1359         D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
1360         D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
1361         D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
1362         D3DPRASTERCAPS_ZFOG);
1363
1364     Desc7->dpcLineCaps.dwZCmpCaps &= (
1365         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
1366         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
1367         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
1368
1369     Desc7->dpcLineCaps.dwSrcBlendCaps &= (
1370         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
1371         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
1372         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
1373         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
1374         D3DPBLENDCAPS_BOTHINVSRCALPHA);
1375
1376     Desc7->dpcLineCaps.dwDestBlendCaps &= (
1377         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
1378         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
1379         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
1380         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
1381         D3DPBLENDCAPS_BOTHINVSRCALPHA);
1382
1383     Desc7->dpcLineCaps.dwAlphaCmpCaps &= (
1384         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
1385         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
1386         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
1387
1388     Desc7->dpcLineCaps.dwShadeCaps &= (
1389         D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
1390         D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
1391         D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
1392         D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
1393         D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
1394         D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
1395         D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
1396
1397     Desc7->dpcLineCaps.dwTextureCaps &= (
1398         D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
1399         D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
1400         D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
1401         D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
1402
1403     Desc7->dpcLineCaps.dwTextureFilterCaps &= (
1404         D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
1405         D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
1406         D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
1407         D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
1408         D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
1409         D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
1410
1411     Desc7->dpcLineCaps.dwTextureBlendCaps &= (
1412         D3DPTBLENDCAPS_DECAL             | D3DPTBLENDCAPS_MODULATE             | D3DPTBLENDCAPS_DECALALPHA           |
1413         D3DPTBLENDCAPS_MODULATEALPHA     | D3DPTBLENDCAPS_DECALMASK            | D3DPTBLENDCAPS_MODULATEMASK         |
1414         D3DPTBLENDCAPS_COPY              | D3DPTBLENDCAPS_ADD);
1415
1416     Desc7->dpcLineCaps.dwTextureAddressCaps &= (
1417         D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
1418         D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
1419
1420     if(!(Desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)) {
1421         /* DirectX7 always has the np2 flag set, no matter what the card supports. Some old games(rollcage)
1422          * check the caps incorrectly. If wined3d supports nonpow2 textures it also has np2 conditional support
1423          */
1424         Desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1425     }
1426     /* Fill the missing members, and do some fixup */
1427     Desc7->dpcLineCaps.dwSize = sizeof(Desc7->dpcLineCaps);
1428     Desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
1429                                             D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
1430                                             D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
1431                                             D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
1432     Desc7->dpcLineCaps.dwStippleWidth = 32;
1433     Desc7->dpcLineCaps.dwStippleHeight = 32;
1434     /* Use the same for the TriCaps */
1435     Desc7->dpcTriCaps = Desc7->dpcLineCaps;
1436
1437     Desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
1438     Desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
1439     Desc7->dwMinTextureWidth = 1;
1440     Desc7->dwMinTextureHeight = 1;
1441
1442     /* Convert DWORDs safely to WORDs */
1443     if(MaxTextureBlendStages > 65535) Desc7->wMaxTextureBlendStages = 65535;
1444     else Desc7->wMaxTextureBlendStages = (WORD) MaxTextureBlendStages;
1445     if(MaxSimultaneousTextures > 65535) Desc7->wMaxSimultaneousTextures = 65535;
1446     else Desc7->wMaxSimultaneousTextures = (WORD) MaxSimultaneousTextures;
1447
1448     if(MaxUserClipPlanes > 65535) Desc7->wMaxUserClipPlanes = 65535;
1449     else Desc7->wMaxUserClipPlanes = (WORD) MaxUserClipPlanes;
1450     if(MaxVertexBlendMatrices > 65535) Desc7->wMaxVertexBlendMatrices = 65535;
1451     else Desc7->wMaxVertexBlendMatrices = (WORD) MaxVertexBlendMatrices;
1452
1453     Desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
1454
1455     Desc7->dwReserved1 = 0;
1456     Desc7->dwReserved2 = 0;
1457     Desc7->dwReserved3 = 0;
1458     Desc7->dwReserved4 = 0;
1459
1460     /* Fill the old structure */
1461     memset(Desc123, 0x0, sizeof(D3DDEVICEDESC));
1462     Desc123->dwSize = sizeof(D3DDEVICEDESC);
1463     Desc123->dwFlags = D3DDD_COLORMODEL            |
1464                        D3DDD_DEVCAPS               |
1465                        D3DDD_TRANSFORMCAPS         |
1466                        D3DDD_BCLIPPING             |
1467                        D3DDD_LIGHTINGCAPS          |
1468                        D3DDD_LINECAPS              |
1469                        D3DDD_TRICAPS               |
1470                        D3DDD_DEVICERENDERBITDEPTH  |
1471                        D3DDD_DEVICEZBUFFERBITDEPTH |
1472                        D3DDD_MAXBUFFERSIZE         |
1473                        D3DDD_MAXVERTEXCOUNT;
1474     Desc123->dcmColorModel = D3DCOLOR_RGB;
1475     Desc123->dwDevCaps = Desc7->dwDevCaps;
1476     Desc123->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
1477     Desc123->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
1478     Desc123->bClipping = TRUE;
1479     Desc123->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
1480     Desc123->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
1481     Desc123->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
1482     Desc123->dlcLightingCaps.dwNumLights = Desc7->dwMaxActiveLights;
1483
1484     Desc123->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
1485     Desc123->dpcLineCaps.dwMiscCaps = Desc7->dpcLineCaps.dwMiscCaps;
1486     Desc123->dpcLineCaps.dwRasterCaps = Desc7->dpcLineCaps.dwRasterCaps;
1487     Desc123->dpcLineCaps.dwZCmpCaps = Desc7->dpcLineCaps.dwZCmpCaps;
1488     Desc123->dpcLineCaps.dwSrcBlendCaps = Desc7->dpcLineCaps.dwSrcBlendCaps;
1489     Desc123->dpcLineCaps.dwDestBlendCaps = Desc7->dpcLineCaps.dwDestBlendCaps;
1490     Desc123->dpcLineCaps.dwShadeCaps = Desc7->dpcLineCaps.dwShadeCaps;
1491     Desc123->dpcLineCaps.dwTextureCaps = Desc7->dpcLineCaps.dwTextureCaps;
1492     Desc123->dpcLineCaps.dwTextureFilterCaps = Desc7->dpcLineCaps.dwTextureFilterCaps;
1493     Desc123->dpcLineCaps.dwTextureBlendCaps = Desc7->dpcLineCaps.dwTextureBlendCaps;
1494     Desc123->dpcLineCaps.dwTextureAddressCaps = Desc7->dpcLineCaps.dwTextureAddressCaps;
1495     Desc123->dpcLineCaps.dwStippleWidth = Desc7->dpcLineCaps.dwStippleWidth;
1496     Desc123->dpcLineCaps.dwAlphaCmpCaps = Desc7->dpcLineCaps.dwAlphaCmpCaps;
1497
1498     Desc123->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
1499     Desc123->dpcTriCaps.dwMiscCaps = Desc7->dpcTriCaps.dwMiscCaps;
1500     Desc123->dpcTriCaps.dwRasterCaps = Desc7->dpcTriCaps.dwRasterCaps;
1501     Desc123->dpcTriCaps.dwZCmpCaps = Desc7->dpcTriCaps.dwZCmpCaps;
1502     Desc123->dpcTriCaps.dwSrcBlendCaps = Desc7->dpcTriCaps.dwSrcBlendCaps;
1503     Desc123->dpcTriCaps.dwDestBlendCaps = Desc7->dpcTriCaps.dwDestBlendCaps;
1504     Desc123->dpcTriCaps.dwShadeCaps = Desc7->dpcTriCaps.dwShadeCaps;
1505     Desc123->dpcTriCaps.dwTextureCaps = Desc7->dpcTriCaps.dwTextureCaps;
1506     Desc123->dpcTriCaps.dwTextureFilterCaps = Desc7->dpcTriCaps.dwTextureFilterCaps;
1507     Desc123->dpcTriCaps.dwTextureBlendCaps = Desc7->dpcTriCaps.dwTextureBlendCaps;
1508     Desc123->dpcTriCaps.dwTextureAddressCaps = Desc7->dpcTriCaps.dwTextureAddressCaps;
1509     Desc123->dpcTriCaps.dwStippleWidth = Desc7->dpcTriCaps.dwStippleWidth;
1510     Desc123->dpcTriCaps.dwAlphaCmpCaps = Desc7->dpcTriCaps.dwAlphaCmpCaps;
1511
1512     Desc123->dwDeviceRenderBitDepth = Desc7->dwDeviceRenderBitDepth;
1513     Desc123->dwDeviceZBufferBitDepth = Desc7->dwDeviceZBufferBitDepth;
1514     Desc123->dwMaxBufferSize = 0;
1515     Desc123->dwMaxVertexCount = 65536;
1516     Desc123->dwMinTextureWidth  = Desc7->dwMinTextureWidth;
1517     Desc123->dwMinTextureHeight = Desc7->dwMinTextureHeight;
1518     Desc123->dwMaxTextureWidth  = Desc7->dwMaxTextureWidth;
1519     Desc123->dwMaxTextureHeight = Desc7->dwMaxTextureHeight;
1520     Desc123->dwMinStippleWidth  = 1;
1521     Desc123->dwMinStippleHeight = 1;
1522     Desc123->dwMaxStippleWidth  = 32;
1523     Desc123->dwMaxStippleHeight = 32;
1524     Desc123->dwMaxTextureRepeat = Desc7->dwMaxTextureRepeat;
1525     Desc123->dwMaxTextureAspectRatio = Desc7->dwMaxTextureAspectRatio;
1526     Desc123->dwMaxAnisotropy = Desc7->dwMaxAnisotropy;
1527     Desc123->dvGuardBandLeft = Desc7->dvGuardBandLeft;
1528     Desc123->dvGuardBandRight = Desc7->dvGuardBandRight;
1529     Desc123->dvGuardBandTop = Desc7->dvGuardBandTop;
1530     Desc123->dvGuardBandBottom = Desc7->dvGuardBandBottom;
1531     Desc123->dvExtentsAdjust = Desc7->dvExtentsAdjust;
1532     Desc123->dwStencilCaps = Desc7->dwStencilCaps;
1533     Desc123->dwFVFCaps = Desc7->dwFVFCaps;
1534     Desc123->dwTextureOpCaps = Desc7->dwTextureOpCaps;
1535     Desc123->wMaxTextureBlendStages = Desc7->wMaxTextureBlendStages;
1536     Desc123->wMaxSimultaneousTextures = Desc7->wMaxSimultaneousTextures;
1537
1538     return DD_OK;
1539 }
1540 /*****************************************************************************
1541  * IDirect3D vtables in various versions
1542  *****************************************************************************/
1543
1544 const IDirect3DVtbl IDirect3D1_Vtbl =
1545 {
1546     /*** IUnknown methods ***/
1547     Thunk_IDirect3DImpl_1_QueryInterface,
1548     Thunk_IDirect3DImpl_1_AddRef,
1549     Thunk_IDirect3DImpl_1_Release,
1550     /*** IDirect3D methods ***/
1551     IDirect3DImpl_1_Initialize,
1552     Thunk_IDirect3DImpl_1_EnumDevices,
1553     Thunk_IDirect3DImpl_1_CreateLight,
1554     Thunk_IDirect3DImpl_1_CreateMaterial,
1555     Thunk_IDirect3DImpl_1_CreateViewport,
1556     Thunk_IDirect3DImpl_1_FindDevice
1557 };
1558
1559 const IDirect3D2Vtbl IDirect3D2_Vtbl =
1560 {
1561     /*** IUnknown methods ***/
1562     Thunk_IDirect3DImpl_2_QueryInterface,
1563     Thunk_IDirect3DImpl_2_AddRef,
1564     Thunk_IDirect3DImpl_2_Release,
1565     /*** IDirect3D2 methods ***/
1566     Thunk_IDirect3DImpl_2_EnumDevices,
1567     Thunk_IDirect3DImpl_2_CreateLight,
1568     Thunk_IDirect3DImpl_2_CreateMaterial,
1569     Thunk_IDirect3DImpl_2_CreateViewport,
1570     Thunk_IDirect3DImpl_2_FindDevice,
1571     Thunk_IDirect3DImpl_2_CreateDevice
1572 };
1573
1574 const IDirect3D3Vtbl IDirect3D3_Vtbl =
1575 {
1576     /*** IUnknown methods ***/
1577     Thunk_IDirect3DImpl_3_QueryInterface,
1578     Thunk_IDirect3DImpl_3_AddRef,
1579     Thunk_IDirect3DImpl_3_Release,
1580     /*** IDirect3D3 methods ***/
1581     IDirect3DImpl_3_EnumDevices,
1582     IDirect3DImpl_3_CreateLight,
1583     IDirect3DImpl_3_CreateMaterial,
1584     IDirect3DImpl_3_CreateViewport,
1585     IDirect3DImpl_3_FindDevice,
1586     Thunk_IDirect3DImpl_3_CreateDevice,
1587     Thunk_IDirect3DImpl_3_CreateVertexBuffer,
1588     Thunk_IDirect3DImpl_3_EnumZBufferFormats,
1589     Thunk_IDirect3DImpl_3_EvictManagedTextures
1590 };
1591
1592 const IDirect3D7Vtbl IDirect3D7_Vtbl =
1593 {
1594     /*** IUnknown methods ***/
1595     Thunk_IDirect3DImpl_7_QueryInterface,
1596     Thunk_IDirect3DImpl_7_AddRef,
1597     Thunk_IDirect3DImpl_7_Release,
1598     /*** IDirect3D7 methods ***/
1599     IDirect3DImpl_7_EnumDevices,
1600     IDirect3DImpl_7_CreateDevice,
1601     IDirect3DImpl_7_CreateVertexBuffer,
1602     IDirect3DImpl_7_EnumZBufferFormats,
1603     IDirect3DImpl_7_EvictManagedTextures
1604 };