~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ddraw/direct3d.c

Version: ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 the T&L, HAL and RGB devices are enumerated.
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_tnl[] = "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D";
250     char device_name_tnl[] = "Wine D3D7 T&L HAL";
251     char interface_name_hal[] = "WINE Direct3D7 Hardware acceleration using WineD3D";
252     char device_name_hal[] = "Wine D3D7 HAL";
253     char interface_name_rgb[] = "WINE Direct3D7 RGB Software Emulation using WineD3D";
254     char device_name_rgb[] = "Wine D3D7 RGB";
255     D3DDEVICEDESC7 ddesc;
256     D3DDEVICEDESC oldDesc;
257     HRESULT hr;
258 
259     TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
260     EnterCriticalSection(&ddraw_cs);
261 
262     TRACE("(%p) Enumerating WineD3D D3Device7 interface\n", This);
263     hr = IDirect3DImpl_GetCaps(This->wineD3D, &oldDesc, &ddesc);
264     if(hr != D3D_OK)
265     {
266         LeaveCriticalSection(&ddraw_cs);
267         return hr;
268     }
269     Callback(interface_name_tnl, device_name_tnl, &ddesc, Context);
270 
271     ddesc.deviceGUID = IID_IDirect3DHALDevice;
272     Callback(interface_name_hal, device_name_hal, &ddesc, Context);
273 
274     ddesc.deviceGUID = IID_IDirect3DRGBDevice;
275     Callback(interface_name_rgb, device_name_rgb, &ddesc, Context);
276 
277     TRACE("(%p) End of enumeration\n", This);
278     LeaveCriticalSection(&ddraw_cs);
279     return D3D_OK;
280 }
281 
282 /*****************************************************************************
283  * IDirect3D3::EnumDevices
284  *
285  * Enumerates all supported Direct3DDevice interfaces. This is the
286  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
287  *
288  * Version 1, 2 and 3
289  *
290  * Params:
291  *  Callback: Application-provided routine to call for each enumerated device
292  *  Context: Pointer to pass to the callback
293  *
294  * Returns:
295  *  D3D_OK on success,
296  *  The result of IDirect3DImpl_GetCaps if it failed
297  *
298  *****************************************************************************/
299 static HRESULT WINAPI
300 IDirect3DImpl_3_EnumDevices(IDirect3D3 *iface,
301                             LPD3DENUMDEVICESCALLBACK Callback,
302                             void *Context)
303 {
304     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
305     D3DDEVICEDESC dref, d1, d2;
306     D3DDEVICEDESC7 newDesc;
307     static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
308     HRESULT hr;
309 
310     /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
311        Let's put the string in a sufficiently sized array in writable memory. */
312     char device_name[50];
313     strcpy(device_name,"Direct3D HEL");
314 
315     TRACE("(%p)->(%p,%p)\n", This, Callback, Context);
316     EnterCriticalSection(&ddraw_cs);
317 
318     hr = IDirect3DImpl_GetCaps(This->wineD3D, &dref, &newDesc);
319     if(hr != D3D_OK)
320     {
321         LeaveCriticalSection(&ddraw_cs);
322         return hr;
323     }
324 
325     /* Do I have to enumerate the reference id? Note from old d3d7:
326      * "It seems that enumerating the reference IID on Direct3D 1 games
327      * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
328      *
329      * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers, EnumReference
330      * which enables / disables enumerating the reference rasterizer. It's a DWORD,
331      * 0 means disabled, 2 means enabled. The enablerefrast.reg and disablerefrast.reg
332      * files in the DirectX 7.0 sdk demo directory suggest this.
333      *
334      * Some games(GTA 2) seem to use the second enumerated device, so I have to enumerate
335      * at least 2 devices. So enumerate the reference device to have 2 devices.
336      *
337      * Other games(Rollcage) tell emulation and hal device apart by certain flags.
338      * Rollcage expects D3DPTEXTURECAPS_POW2 to be set(yeah, it is a limitation flag),
339      * and it refuses all devices that have the perspective flag set. This way it refuses
340      * the emulation device, and HAL devices never have POW2 unset in d3d7 on windows.
341      */
342 
343     if(This->d3dversion != 1)
344     {
345         static CHAR reference_description[] = "RGB Direct3D emulation";
346 
347         TRACE("(%p) Enumerating WineD3D D3DDevice interface\n", This);
348         d1 = dref;
349         d2 = dref;
350         /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps */
351         d1.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
352         d1.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
353         hr = Callback( (LPIID) &IID_IDirect3DRGBDevice, reference_description, device_name, &d1, &d2, Context);
354         if(hr != D3DENUMRET_OK)
355         {
356             TRACE("Application cancelled the enumeration\n");
357             LeaveCriticalSection(&ddraw_cs);
358             return D3D_OK;
359         }
360     }
361 
362     strcpy(device_name,"Direct3D HAL");
363 
364     TRACE("(%p) Enumerating HAL Direct3D device\n", This);
365     d1 = dref;
366     d2 = dref;
367     /* The hal device does not have the pow2 flag set in hel, but in hal */
368     d2.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
369     d2.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
370     hr = Callback( (LPIID) &IID_IDirect3DHALDevice, wined3d_description, device_name, &d1, &d2, Context);
371     if(hr != D3DENUMRET_OK)
372     {
373         TRACE("Application cancelled the enumeration\n");
374         LeaveCriticalSection(&ddraw_cs);
375         return D3D_OK;
376     }
377     TRACE("(%p) End of enumeration\n", This);
378 
379     LeaveCriticalSection(&ddraw_cs);
380     return D3D_OK;
381 }
382 
383 static HRESULT WINAPI
384 Thunk_IDirect3DImpl_2_EnumDevices(IDirect3D2 *iface,
385                                   LPD3DENUMDEVICESCALLBACK Callback,
386                                   void *Context)
387 {
388     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
389     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Callback, Context);
390     return IDirect3D3_EnumDevices(ICOM_INTERFACE(This, IDirect3D3),
391                                   Callback,
392                                   Context);
393 }
394 
395 static HRESULT WINAPI
396 Thunk_IDirect3DImpl_1_EnumDevices(IDirect3D *iface,
397                                   LPD3DENUMDEVICESCALLBACK Callback,
398                                   void *Context)
399 {
400     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
401     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Callback, Context);
402     return IDirect3D3_EnumDevices(ICOM_INTERFACE(This, IDirect3D3),
403                                   Callback,
404                                   Context);
405 }
406 
407 /*****************************************************************************
408  * IDirect3D3::CreateLight
409  *
410  * Creates an IDirect3DLight interface. This interface is used in
411  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
412  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
413  * uses the IDirect3DDevice7 interface with D3D7 lights.
414  *
415  * Version 1, 2 and 3
416  *
417  * Params:
418  *  Light: Address to store the new interface pointer
419  *  UnkOuter: Basically for aggregation, but ddraw doesn't support it.
420  *            Must be NULL
421  *
422  * Returns:
423  *  D3D_OK on success
424  *  DDERR_OUTOFMEMORY if memory allocation failed
425  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
426  *
427  *****************************************************************************/
428 static HRESULT WINAPI
429 IDirect3DImpl_3_CreateLight(IDirect3D3 *iface,
430                             IDirect3DLight **Light,
431                             IUnknown *UnkOuter )
432 {
433     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
434     IDirect3DLightImpl *object;
435 
436     TRACE("(%p)->(%p,%p)\n", This, Light, UnkOuter);
437 
438     if(UnkOuter)
439         return CLASS_E_NOAGGREGATION;
440 
441     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DLightImpl));
442     if (object == NULL)
443         return DDERR_OUTOFMEMORY;
444 
445     ICOM_INIT_INTERFACE(object, IDirect3DLight, IDirect3DLight_Vtbl);
446     object->ref = 1;
447     object->ddraw = This;
448     object->next = NULL;
449     object->active_viewport = NULL;
450 
451     /* Update functions */
452     object->activate = light_update;
453     object->desactivate = light_activate;
454     object->update = light_desactivate;
455     object->active_viewport = NULL;
456 
457     *Light = ICOM_INTERFACE(object, IDirect3DLight);
458 
459     TRACE("(%p) creating implementation at %p.\n", This, object);
460 
461     return D3D_OK;
462 }
463 
464 static HRESULT WINAPI
465 Thunk_IDirect3DImpl_2_CreateLight(IDirect3D2 *iface,
466                                   IDirect3DLight **Direct3DLight,
467                                   IUnknown *UnkOuter)
468 {
469     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
470     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DLight, UnkOuter);
471     return IDirect3D3_CreateLight(ICOM_INTERFACE(This, IDirect3D3),
472                                   Direct3DLight,
473                                   UnkOuter);
474 }
475 
476 static HRESULT WINAPI
477 Thunk_IDirect3DImpl_1_CreateLight(IDirect3D *iface,
478                                   IDirect3DLight **Direct3DLight,
479                                   IUnknown *UnkOuter)
480 {
481     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
482     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DLight, UnkOuter);
483     return IDirect3D3_CreateLight(ICOM_INTERFACE(This, IDirect3D3),
484                                   Direct3DLight,
485                                   UnkOuter);
486 }
487 
488 /*****************************************************************************
489  * IDirect3D3::CreateMaterial
490  *
491  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
492  * and older versions. The IDirect3DMaterial implementation wraps its
493  * functionality to IDirect3DDevice7::SetMaterial and friends.
494  *
495  * Version 1, 2 and 3
496  *
497  * Params:
498  *  Material: Address to store the new interface's pointer to
499  *  UnkOuter: Basically for aggregation, but ddraw doesn't support it.
500  *            Must be NULL
501  *
502  * Returns:
503  *  D3D_OK on success
504  *  DDERR_OUTOFMEMORY if memory allocation failed
505  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
506  *
507  *****************************************************************************/
508 static HRESULT WINAPI
509 IDirect3DImpl_3_CreateMaterial(IDirect3D3 *iface,
510                                IDirect3DMaterial3 **Material,
511                                IUnknown *UnkOuter )
512 {
513     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
514     IDirect3DMaterialImpl *object;
515 
516     TRACE("(%p)->(%p,%p)\n", This, Material, UnkOuter);
517 
518     if(UnkOuter)
519         return CLASS_E_NOAGGREGATION;
520 
521     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DMaterialImpl));
522     if (object == NULL)
523         return DDERR_OUTOFMEMORY;
524 
525     ICOM_INIT_INTERFACE(object, IDirect3DMaterial3, IDirect3DMaterial3_Vtbl);
526     ICOM_INIT_INTERFACE(object, IDirect3DMaterial2, IDirect3DMaterial2_Vtbl);
527     ICOM_INIT_INTERFACE(object, IDirect3DMaterial, IDirect3DMaterial_Vtbl);
528     object->ref = 1;
529     object->ddraw = This;
530     object->activate = material_activate;
531 
532     *Material = ICOM_INTERFACE(object, IDirect3DMaterial3);
533 
534     TRACE("(%p) creating implementation at %p.\n", This, object);
535 
536     return D3D_OK;
537 }
538 
539 static HRESULT WINAPI
540 Thunk_IDirect3DImpl_2_CreateMaterial(IDirect3D2 *iface,
541                                      IDirect3DMaterial2 **Direct3DMaterial,
542                                      IUnknown* UnkOuter)
543 {
544     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
545     HRESULT ret;
546     IDirect3DMaterial3 *ret_val;
547 
548     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DMaterial, UnkOuter);
549     ret = IDirect3D3_CreateMaterial(ICOM_INTERFACE(This, IDirect3D3),
550                                     &ret_val,
551                                     UnkOuter);
552 
553     *Direct3DMaterial = COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial3, IDirect3DMaterial2, ret_val);
554 
555     TRACE(" returning interface %p.\n", *Direct3DMaterial);
556 
557     return ret;
558 }
559 
560 static HRESULT WINAPI
561 Thunk_IDirect3DImpl_1_CreateMaterial(IDirect3D *iface,
562                                      IDirect3DMaterial **Direct3DMaterial,
563                                      IUnknown* UnkOuter)
564 {
565     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
566     HRESULT ret;
567     LPDIRECT3DMATERIAL3 ret_val;
568 
569     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, Direct3DMaterial, UnkOuter);
570     ret = IDirect3D3_CreateMaterial(ICOM_INTERFACE(This, IDirect3D3),
571                                     &ret_val,
572                                     UnkOuter);
573 
574     *Direct3DMaterial = COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial3, IDirect3DMaterial, ret_val);
575 
576     TRACE(" returning interface %p.\n", *Direct3DMaterial);
577 
578     return ret;
579 }
580 
581 /*****************************************************************************
582  * IDirect3D3::CreateViewport
583  *
584  * Creates an IDirect3DViewport interface. This interface is used
585  * by Direct3D and earlier versions for Viewport management. In Direct3D7
586  * it has been replaced by a viewport structure and
587  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
588  * uses the IDirect3DDevice7 methods for its functionality
589  *
590  * Params:
591  *  Viewport: Address to store the new interface pointer
592  *  UnkOuter: Basically for aggregation, but ddraw doesn't support it.
593  *            Must be NULL
594  *
595  * Returns:
596  *  D3D_OK on success
597  *  DDERR_OUTOFMEMORY if memory allocation failed
598  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
599  *
600  *****************************************************************************/
601 static HRESULT WINAPI
602 IDirect3DImpl_3_CreateViewport(IDirect3D3 *iface,
603                               IDirect3DViewport3 **Viewport,
604                               IUnknown *UnkOuter )
605 {
606     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
607     IDirect3DViewportImpl *object;
608 
609     if(UnkOuter)
610         return CLASS_E_NOAGGREGATION;
611 
612     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DViewportImpl));
613     if (object == NULL)
614         return DDERR_OUTOFMEMORY;
615 
616     ICOM_INIT_INTERFACE(object, IDirect3DViewport3, IDirect3DViewport3_Vtbl);
617     object->ref = 1;
618     object->ddraw = This;
619     object->activate = viewport_activate;
620     object->use_vp2 = 0xFF;
621     object->next = NULL;
622     object->lights = NULL;
623     object->num_lights = 0;
624     object->map_lights = 0;
625 
626     *Viewport = ICOM_INTERFACE(object, IDirect3DViewport3);
627 
628     TRACE("(%p) creating implementation at %p.\n",This, object);
629 
630     return D3D_OK;
631 }
632 
633 static HRESULT WINAPI
634 Thunk_IDirect3DImpl_2_CreateViewport(IDirect3D2 *iface,
635                                      IDirect3DViewport2 **D3DViewport2,
636                                      IUnknown *UnkOuter)
637 {
638     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
639     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, D3DViewport2, UnkOuter);
640 
641     return IDirect3D3_CreateViewport(ICOM_INTERFACE(This, IDirect3D3),
642                                      (IDirect3DViewport3 **) D3DViewport2 /* No need to cast here */,
643                                      UnkOuter);
644 }
645 
646 static HRESULT WINAPI
647 Thunk_IDirect3DImpl_1_CreateViewport(IDirect3D *iface,
648                                      IDirect3DViewport **D3DViewport,
649                                      IUnknown* UnkOuter)
650 {
651     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
652     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, D3DViewport, UnkOuter);
653 
654     return IDirect3D3_CreateViewport(ICOM_INTERFACE(This, IDirect3D3),
655                                      (IDirect3DViewport3 **) D3DViewport /* No need to cast here */,
656                                      UnkOuter);
657 }
658 
659 /*****************************************************************************
660  * IDirect3D3::FindDevice
661  *
662  * This method finds a device with the requested properties and returns a
663  * device description
664  *
665  * Verion 1, 2 and 3
666  * Params:
667  *  D3DDFS: Describes the requested device characteristics
668  *  D3DFDR: Returns the device description
669  *
670  * Returns:
671  *  D3D_OK on success
672  *  DDERR_INVALIDPARAMS if no device was found
673  *
674  *****************************************************************************/
675 static HRESULT WINAPI
676 IDirect3DImpl_3_FindDevice(IDirect3D3 *iface,
677                            D3DFINDDEVICESEARCH *D3DDFS,
678                            D3DFINDDEVICERESULT *D3DFDR)
679 {
680     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
681     D3DDEVICEDESC desc;
682     D3DDEVICEDESC7 newDesc;
683     HRESULT hr;
684 
685     TRACE("(%p)->(%p,%p)\n", This, D3DDFS, D3DFDR);
686 
687     if ((D3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
688         (D3DDFS->dcmColorModel != D3DCOLOR_RGB))
689     {
690         TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
691         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
692     }
693     if (D3DDFS->dwFlags & D3DFDS_GUID)
694     {
695         TRACE(" trying to match guid %s.\n", debugstr_guid(&(D3DDFS->guid)));
696         if ((IsEqualGUID(&IID_D3DDEVICE_WineD3D, &(D3DDFS->guid)) == 0) &&
697             (IsEqualGUID(&IID_IDirect3DHALDevice, &(D3DDFS->guid)) == 0) &&
698             (IsEqualGUID(&IID_IDirect3DRefDevice, &(D3DDFS->guid)) == 0))
699         {
700             TRACE(" no match for this GUID.\n");
701             return DDERR_INVALIDPARAMS;
702         }
703     }
704 
705     /* Get the caps */
706     hr = IDirect3DImpl_GetCaps(This->wineD3D, &desc, &newDesc);
707     if(hr != D3D_OK) return hr;
708 
709     /* Now return our own GUID */
710     D3DFDR->guid = IID_D3DDEVICE_WineD3D;
711     D3DFDR->ddHwDesc = desc;
712     D3DFDR->ddSwDesc = desc;
713 
714     TRACE(" returning Wine's WineD3D device with (undumped) capabilities\n");
715 
716     return D3D_OK;
717 }
718 
719 static HRESULT WINAPI
720 Thunk_IDirect3DImpl_2_FindDevice(IDirect3D2 *iface,
721                                  D3DFINDDEVICESEARCH *D3DDFS,
722                                  D3DFINDDEVICERESULT *D3DFDR)
723 {
724     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
725     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, D3DDFS, D3DFDR);
726     return IDirect3D3_FindDevice(ICOM_INTERFACE(This, IDirect3D3),
727                                  D3DDFS,
728                                  D3DFDR);
729 }
730 
731 static HRESULT WINAPI
732 Thunk_IDirect3DImpl_1_FindDevice(IDirect3D *iface,
733                                 D3DFINDDEVICESEARCH *D3DDFS,
734                                 D3DFINDDEVICERESULT *D3DDevice)
735 {
736     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
737     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", This, D3DDFS, D3DDevice);
738     return IDirect3D3_FindDevice(ICOM_INTERFACE(This, IDirect3D3),
739                                  D3DDFS,
740                                  D3DDevice);
741 }
742 
743 /*****************************************************************************
744  * IDirect3D7::CreateDevice
745  *
746  * Creates an IDirect3DDevice7 interface.
747  *
748  * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
749  * DirectDraw surfaces and are created with
750  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
751  * create the device object and QueryInterfaces for IDirect3DDevice
752  *
753  * Params:
754  *  refiid: IID of the device to create
755  *  Surface: Initial rendertarget
756  *  Device: Address to return the interface pointer
757  *
758  * Returns:
759  *  D3D_OK on success
760  *  DDERR_OUTOFMEMORY if memory allocation failed
761  *  DDERR_INVALIDPARAMS if a device exists already
762  *
763  *****************************************************************************/
764 static HRESULT WINAPI
765 IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface,
766                              REFCLSID refiid,
767                              IDirectDrawSurface7 *Surface,
768                              IDirect3DDevice7 **Device)
769 {
770     ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
771     IDirect3DDeviceImpl *object;
772     IParentImpl *IndexBufferParent;
773     HRESULT hr;
774     IDirectDrawSurfaceImpl *target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Surface);
775     TRACE("(%p)->(%s,%p,%p)\n", iface, debugstr_guid(refiid), Surface, Device);
776 
777     EnterCriticalSection(&ddraw_cs);
778     *Device = NULL;
779 
780     /* Fail device creation if non-opengl surfaces are used */
781     if(This->ImplType != SURFACE_OPENGL)
782     {
783         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");
784 
785         /* We only hit this path if a default surface is set in the registry. Incorrect autodetection
786          * is caught in CreateSurface or QueryInterface
787          */
788         LeaveCriticalSection(&ddraw_cs);
789         return DDERR_NO3D;
790     }
791 
792     /* So far we can only create one device per ddraw object */
793     if(This->d3ddevice)
794     {
795         FIXME("(%p): Only one Direct3D device per DirectDraw object supported\n", This);
796         LeaveCriticalSection(&ddraw_cs);
797         return DDERR_INVALIDPARAMS;
798     }
799 
800     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirect3DDeviceImpl));
801     if(!object)
802     {
803         ERR("Out of memory when allocating a IDirect3DDevice implementation\n");
804         LeaveCriticalSection(&ddraw_cs);
805         return DDERR_OUTOFMEMORY;
806     }
807 
808     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, IDirect3DDevice7_Vtbl);
809     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, IDirect3DDevice3_Vtbl);
810     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, IDirect3DDevice2_Vtbl);
811     ICOM_INIT_INTERFACE(object, IDirect3DDevice, IDirect3DDevice1_Vtbl);
812 
813     object->ref = 1;
814     object->ddraw = This;
815     object->viewport_list = NULL;
816     object->current_viewport = NULL;
817     object->material = 0;
818     object->target = target;
819 
820     object->Handles = NULL;
821     object->numHandles = 0;
822 
823     /* This is for convenience */
824     object->wineD3DDevice = This->wineD3DDevice;
825 
826     /* Create an index buffer, it's needed for indexed drawing */
827     IndexBufferParent = HeapAlloc(GetProcessHeap(), 0, sizeof(IParentImpl *));
828     if(!IndexBufferParent)
829     {
830         ERR("Allocating memory for an index buffer parent failed\n");
831         HeapFree(GetProcessHeap(), 0, object);
832         LeaveCriticalSection(&ddraw_cs);
833         return DDERR_OUTOFMEMORY;
834     }
835     ICOM_INIT_INTERFACE(IndexBufferParent, IParent, IParent_Vtbl);
836     IndexBufferParent->ref = 1;
837 
838     /* Create an Index Buffer. WineD3D needs one for Drawing indexed primitives
839      * Create a (hopefully) long enough buffer, and copy the indices into it
840      * Ideally, a IWineD3DIndexBuffer::SetData method could be created, which
841      * takes the pointer and avoids the memcpy
842      */
843     hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice,
844                                           0x40000, /* Length. Don't know how long it should be */
845                                           WINED3DUSAGE_DYNAMIC, /* Usage */
846                                           WINED3DFMT_INDEX16, /* Format. D3D7 uses WORDS */
847                                           WINED3DPOOL_DEFAULT,
848                                           &object->indexbuffer,
849                                           0 /* Handle */,
850                                           (IUnknown *) ICOM_INTERFACE(IndexBufferParent, IParent));
851 
852     if(FAILED(hr))
853     {
854         ERR("Failed to create an index buffer\n");
855         HeapFree(GetProcessHeap(), 0, object);
856         LeaveCriticalSection(&ddraw_cs);
857         return hr;
858     }
859     IndexBufferParent->child = (IUnknown *) object->indexbuffer;
860 
861     /* No need to set the indices, it's done when necessary */
862 
863     /* AddRef the WineD3D Device */
864     IWineD3DDevice_AddRef(This->wineD3DDevice);
865 
866     /* Don't forget to return the interface ;) */
867     *Device = ICOM_INTERFACE(object, IDirect3DDevice7);
868 
869     TRACE(" (%p) Created an IDirect3DDeviceImpl object at %p\n", This, object);
870 
871     /* This is for apps which create a non-flip, non-d3d primary surface
872      * and an offscreen D3DDEVICE surface, then render to the offscreen surface
873      * and do a Blt from the offscreen to the primary surface.
874      *
875      * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
876      * and the primary surface(=This->d3d_target) as the front buffer.
877      *
878      * This way the app will render to the D3DDEVICE surface and WineD3D
879      * will catch the Blt was Back Buffer -> Front buffer blt and perform
880      * a flip instead. This way we don't have to deal with a mixed GL / GDI
881      * environment.
882      *
883      * This should be checked against windowed apps. The only app tested with
884      * this is moto racer 2 during the loading screen.
885      */
886     TRACE("Isrendertarget: %s, d3d_target=%p\n", target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", This->d3d_target);
887     if(!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
888        (This->d3d_target != target))
889     {
890         WINED3DVIEWPORT vp;
891         TRACE("(%p) Using %p as front buffer, %p as back buffer\n", This, This->d3d_target, target);
892         hr = IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
893                                                 This->d3d_target->WineD3DSurface,
894                                                 target->WineD3DSurface);
895         if(hr != D3D_OK)
896             ERR("(%p) Error %08x setting the front and back buffer\n", This, hr);
897 
898         /* Render to the back buffer */