Sync ddraw, d3d8 and d3d9 + wined3d to wine 1.1.28
[reactos.git] / reactos / dll / directx / wine / ddraw / device.c
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
27 *
28 */
29
30 #include "config.h"
31 #include "wine/port.h"
32
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <stdlib.h>
37
38 #define COBJMACROS
39 #define NONAMELESSUNION
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winerror.h"
44 #include "wingdi.h"
45 #include "wine/exception.h"
46
47 #include "ddraw.h"
48 #include "d3d.h"
49
50 #include "ddraw_private.h"
51 #include "wine/debug.h"
52
53 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
54 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
55
56 /* The device ID */
57 const GUID IID_D3DDEVICE_WineD3D = {
58 0xaef72d43,
59 0xb09a,
60 0x4b7b,
61 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
62 };
63
64 static inline void set_fpu_control_word(WORD fpucw)
65 {
66 #if defined(__i386__) && defined(__GNUC__)
67 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
68 #elif defined(__i386__) && defined(_MSC_VER)
69 __asm fldcw fpucw;
70 #endif
71 }
72
73 static inline WORD d3d_fpu_setup(void)
74 {
75 WORD oldcw;
76
77 #if defined(__i386__) && defined(__GNUC__)
78 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
79 #elif defined(__i386__) && defined(_MSC_VER)
80 __asm fnstcw oldcw;
81 #else
82 static BOOL warned = FALSE;
83 if(!warned)
84 {
85 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
86 warned = TRUE;
87 }
88 return 0;
89 #endif
90
91 set_fpu_control_word(0x37f);
92
93 return oldcw;
94 }
95
96 /*****************************************************************************
97 * IUnknown Methods. Common for Version 1, 2, 3 and 7
98 *****************************************************************************/
99
100 /*****************************************************************************
101 * IDirect3DDevice7::QueryInterface
102 *
103 * Used to query other interfaces from a Direct3DDevice interface.
104 * It can return interface pointers to all Direct3DDevice versions as well
105 * as IDirectDraw and IDirect3D. For a link to QueryInterface
106 * rules see ddraw.c, IDirectDraw7::QueryInterface
107 *
108 * Exists in Version 1, 2, 3 and 7
109 *
110 * Params:
111 * refiid: Interface ID queried for
112 * obj: Used to return the interface pointer
113 *
114 * Returns:
115 * D3D_OK or E_NOINTERFACE
116 *
117 *****************************************************************************/
118 static HRESULT WINAPI
119 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
120 REFIID refiid,
121 void **obj)
122 {
123 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
124 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
125
126 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
127 *obj = NULL;
128
129 if(!refiid)
130 return DDERR_INVALIDPARAMS;
131
132 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
133 {
134 *obj = iface;
135 }
136
137 /* Check DirectDraw Interfac\ 1s */
138 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
139 {
140 *obj = This->ddraw;
141 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
142 }
143 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
144 {
145 *obj = &This->ddraw->IDirectDraw4_vtbl;
146 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
147 }
148 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
149 {
150 *obj = &This->ddraw->IDirectDraw2_vtbl;
151 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
152 }
153 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
154 {
155 *obj = &This->ddraw->IDirectDraw_vtbl;
156 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
157 }
158
159 /* Direct3D */
160 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
161 {
162 *obj = &This->ddraw->IDirect3D_vtbl;
163 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
164 }
165 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
166 {
167 *obj = &This->ddraw->IDirect3D2_vtbl;
168 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
169 }
170 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
171 {
172 *obj = &This->ddraw->IDirect3D3_vtbl;
173 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
174 }
175 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
176 {
177 *obj = &This->ddraw->IDirect3D7_vtbl;
178 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
179 }
180
181 /* Direct3DDevice */
182 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
183 {
184 *obj = &This->IDirect3DDevice_vtbl;
185 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
186 }
187 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
188 *obj = &This->IDirect3DDevice2_vtbl;
189 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
190 }
191 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
192 *obj = &This->IDirect3DDevice3_vtbl;
193 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
194 }
195 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
196 *obj = This;
197 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
198 }
199
200 /* Unknown interface */
201 else
202 {
203 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
204 return E_NOINTERFACE;
205 }
206
207 /* AddRef the returned interface */
208 IUnknown_AddRef( (IUnknown *) *obj);
209 return D3D_OK;
210 }
211
212 static HRESULT WINAPI
213 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
214 REFIID riid,
215 void **obj)
216 {
217 IDirect3DDeviceImpl *This = device_from_device3(iface);
218 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
219 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
220 }
221
222 static HRESULT WINAPI
223 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
224 REFIID riid,
225 void **obj)
226 {
227 IDirect3DDeviceImpl *This = device_from_device2(iface);
228 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obj);
229 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
230 }
231
232 static HRESULT WINAPI
233 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
234 REFIID riid,
235 void **obp)
236 {
237 IDirect3DDeviceImpl *This = device_from_device1(iface);
238 TRACE_(ddraw_thunk)("(%p)->(%s,%p) thunking to IDirect3DDevice7 interface.\n", This, debugstr_guid(riid), obp);
239 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obp);
240 }
241
242 /*****************************************************************************
243 * IDirect3DDevice7::AddRef
244 *
245 * Increases the refcount....
246 * The most exciting Method, definitely
247 *
248 * Exists in Version 1, 2, 3 and 7
249 *
250 * Returns:
251 * The new refcount
252 *
253 *****************************************************************************/
254 static ULONG WINAPI
255 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
256 {
257 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
258 ULONG ref = InterlockedIncrement(&This->ref);
259
260 TRACE("(%p) : incrementing from %u.\n", This, ref -1);
261
262 return ref;
263 }
264
265 static ULONG WINAPI
266 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
267 {
268 IDirect3DDeviceImpl *This = device_from_device3(iface);
269 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
270 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
271 }
272
273 static ULONG WINAPI
274 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
275 {
276 IDirect3DDeviceImpl *This = device_from_device2(iface);
277 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
278 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
279 }
280
281 static ULONG WINAPI
282 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
283 {
284 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", iface);
285 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
286 }
287
288 /*****************************************************************************
289 * IDirect3DDevice7::Release
290 *
291 * Decreases the refcount of the interface
292 * When the refcount is reduced to 0, the object is destroyed.
293 *
294 * Exists in Version 1, 2, 3 and 7
295 *
296 * Returns:d
297 * The new refcount
298 *
299 *****************************************************************************/
300 static ULONG WINAPI
301 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
302 {
303 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
304 ULONG ref = InterlockedDecrement(&This->ref);
305
306 TRACE("(%p)->() decrementing from %u.\n", This, ref +1);
307
308 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
309 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
310 * when the render target is released
311 */
312 if (ref == 0)
313 {
314 IParent *IndexBufferParent;
315 DWORD i;
316
317 EnterCriticalSection(&ddraw_cs);
318 /* Free the index buffer. */
319 IWineD3DDevice_SetIndices(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
320 IWineD3DBuffer_GetParent(This->indexbuffer,
321 (IUnknown **) &IndexBufferParent);
322 IParent_Release(IndexBufferParent); /* Once for the getParent */
323 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
324 {
325 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
326 }
327
328 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
329 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
330 * IDirect3DVertexBuffer::Release will unset it.
331 */
332
333 /* Restore the render targets */
334 if(This->OffScreenTarget)
335 {
336 WINED3DVIEWPORT vp;
337
338 vp.X = 0;
339 vp.Y = 0;
340 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
341 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
342 vp.MinZ = 0.0;
343 vp.MaxZ = 1.0;
344 IWineD3DDevice_SetViewport(This->wineD3DDevice,
345 &vp);
346
347 /* Set the device up to render to the front buffer since the back buffer will
348 * vanish soon.
349 */
350 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
351 This->ddraw->d3d_target->WineD3DSurface);
352 /* This->target is the offscreen target.
353 * This->ddraw->d3d_target is the target used by DDraw
354 */
355 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
356 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
357 This->ddraw->d3d_target->WineD3DSurface,
358 NULL);
359 }
360
361 /* Release the WineD3DDevice. This won't destroy it */
362 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
363 {
364 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
365 }
366
367 /* The texture handles should be unset by now, but there might be some bits
368 * missing in our reference counting(needs test). Do a sanity check
369 */
370 for(i = 0; i < This->numHandles; i++)
371 {
372 if(This->Handles[i].ptr)
373 {
374 switch(This->Handles[i].type)
375 {
376 case DDrawHandle_Texture:
377 {
378 IDirectDrawSurfaceImpl *surf = This->Handles[i].ptr;
379 FIXME("Texture Handle %d not unset properly\n", i + 1);
380 surf->Handle = 0;
381 }
382 break;
383
384 case DDrawHandle_Material:
385 {
386 IDirect3DMaterialImpl *mat = This->Handles[i].ptr;
387 FIXME("Material handle %d not unset properly\n", i + 1);
388 mat->Handle = 0;
389 }
390 break;
391
392 case DDrawHandle_Matrix:
393 {
394 /* No fixme here because this might happen because of sloppy apps */
395 WARN("Leftover matrix handle %d, deleting\n", i + 1);
396 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
397 }
398 break;
399
400 case DDrawHandle_StateBlock:
401 {
402 /* No fixme here because this might happen because of sloppy apps */
403 WARN("Leftover stateblock handle %d, deleting\n", i + 1);
404 IDirect3DDevice7_DeleteStateBlock((IDirect3DDevice7 *)This, i + 1);
405 }
406 break;
407
408 default:
409 FIXME("Unknown handle %d not unset properly\n", i + 1);
410 }
411 }
412 }
413
414 HeapFree(GetProcessHeap(), 0, This->Handles);
415
416 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
417 /* Release the render target and the WineD3D render target
418 * (See IDirect3D7::CreateDevice for more comments on this)
419 */
420 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
421 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
422 TRACE("Target release done\n");
423
424 This->ddraw->d3ddevice = NULL;
425
426 /* Now free the structure */
427 HeapFree(GetProcessHeap(), 0, This);
428 LeaveCriticalSection(&ddraw_cs);
429 }
430
431 TRACE("Done\n");
432 return ref;
433 }
434
435 static ULONG WINAPI
436 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
437 {
438 IDirect3DDeviceImpl *This = device_from_device3(iface);
439 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
440 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
441 }
442
443 static ULONG WINAPI
444 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
445 {
446 IDirect3DDeviceImpl *This = device_from_device2(iface);
447 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
448 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
449 }
450
451 static ULONG WINAPI
452 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
453 {
454 IDirect3DDeviceImpl *This = device_from_device1(iface);
455 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
456 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
457 }
458
459 /*****************************************************************************
460 * IDirect3DDevice Methods
461 *****************************************************************************/
462
463 /*****************************************************************************
464 * IDirect3DDevice::Initialize
465 *
466 * Initializes a Direct3DDevice. This implementation is a no-op, as all
467 * initialization is done at create time.
468 *
469 * Exists in Version 1
470 *
471 * Parameters:
472 * No idea what they mean, as the MSDN page is gone
473 *
474 * Returns: DD_OK
475 *
476 *****************************************************************************/
477 static HRESULT WINAPI
478 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
479 IDirect3D *Direct3D, GUID *guid,
480 D3DDEVICEDESC *Desc)
481 {
482 IDirect3DDeviceImpl *This = device_from_device1(iface);
483
484 /* It shouldn't be crucial, but print a FIXME, I'm interested if
485 * any game calls it and when
486 */
487 FIXME("(%p)->(%p,%p,%p): No-op!\n", This, Direct3D, guid, Desc);
488
489 return D3D_OK;
490 }
491
492 /*****************************************************************************
493 * IDirect3DDevice7::GetCaps
494 *
495 * Retrieves the device's capabilities
496 *
497 * This implementation is used for Version 7 only, the older versions have
498 * their own implementation.
499 *
500 * Parameters:
501 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
502 *
503 * Returns:
504 * D3D_OK on success
505 * D3DERR_* if a problem occurs. See WineD3D
506 *
507 *****************************************************************************/
508 static HRESULT
509 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
510 D3DDEVICEDESC7 *Desc)
511 {
512 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
513 D3DDEVICEDESC OldDesc;
514 TRACE("(%p)->(%p)\n", This, Desc);
515
516 /* Call the same function used by IDirect3D, this saves code */
517 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
518 }
519
520 static HRESULT WINAPI
521 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
522 D3DDEVICEDESC7 *Desc)
523 {
524 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
525 }
526
527 static HRESULT WINAPI
528 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
529 D3DDEVICEDESC7 *Desc)
530 {
531 HRESULT hr;
532 WORD old_fpucw;
533
534 old_fpucw = d3d_fpu_setup();
535 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
536 set_fpu_control_word(old_fpucw);
537
538 return hr;
539 }
540 /*****************************************************************************
541 * IDirect3DDevice3::GetCaps
542 *
543 * Retrieves the capabilities of the hardware device and the emulation
544 * device. For Wine, hardware and emulation are the same (it's all HW).
545 *
546 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
547 *
548 * Parameters:
549 * HWDesc: Structure to fill with the HW caps
550 * HelDesc: Structure to fill with the hardware emulation caps
551 *
552 * Returns:
553 * D3D_OK on success
554 * D3DERR_* if a problem occurs. See WineD3D
555 *
556 *****************************************************************************/
557 static HRESULT WINAPI
558 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
559 D3DDEVICEDESC *HWDesc,
560 D3DDEVICEDESC *HelDesc)
561 {
562 IDirect3DDeviceImpl *This = device_from_device3(iface);
563 D3DDEVICEDESC7 newDesc;
564 HRESULT hr;
565 TRACE("(%p)->(%p,%p)\n", iface, HWDesc, HelDesc);
566
567 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
568 if(hr != D3D_OK) return hr;
569
570 *HelDesc = *HWDesc;
571 return D3D_OK;
572 }
573
574 static HRESULT WINAPI
575 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
576 D3DDEVICEDESC *D3DHWDevDesc,
577 D3DDEVICEDESC *D3DHELDevDesc)
578 {
579 IDirect3DDeviceImpl *This = device_from_device2(iface);
580 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
581 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
582 }
583
584 static HRESULT WINAPI
585 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
586 D3DDEVICEDESC *D3DHWDevDesc,
587 D3DDEVICEDESC *D3DHELDevDesc)
588 {
589 IDirect3DDeviceImpl *This = device_from_device1(iface);
590 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice3 interface.\n", This, D3DHWDevDesc, D3DHELDevDesc);
591 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
592 }
593
594 /*****************************************************************************
595 * IDirect3DDevice2::SwapTextureHandles
596 *
597 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
598 *
599 * Parameters:
600 * Tex1, Tex2: The 2 Textures to swap
601 *
602 * Returns:
603 * D3D_OK
604 *
605 *****************************************************************************/
606 static HRESULT WINAPI
607 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
608 IDirect3DTexture2 *Tex1,
609 IDirect3DTexture2 *Tex2)
610 {
611 IDirect3DDeviceImpl *This = device_from_device2(iface);
612 DWORD swap;
613 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
614 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
615 TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
616
617 EnterCriticalSection(&ddraw_cs);
618 This->Handles[surf1->Handle - 1].ptr = surf2;
619 This->Handles[surf2->Handle - 1].ptr = surf1;
620
621 swap = surf2->Handle;
622 surf2->Handle = surf1->Handle;
623 surf1->Handle = swap;
624 LeaveCriticalSection(&ddraw_cs);
625
626 return D3D_OK;
627 }
628
629 static HRESULT WINAPI
630 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
631 IDirect3DTexture *D3DTex1,
632 IDirect3DTexture *D3DTex2)
633 {
634 IDirect3DDeviceImpl *This = device_from_device1(iface);
635 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
636 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
637 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
638 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
639 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, surf1, surf2);
640 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
641 }
642
643 /*****************************************************************************
644 * IDirect3DDevice3::GetStats
645 *
646 * This method seems to retrieve some stats from the device.
647 * The MSDN documentation doesn't exist any more, but the D3DSTATS
648 * structure suggests that the amount of drawn primitives and processed
649 * vertices is returned.
650 *
651 * Exists in Version 1, 2 and 3
652 *
653 * Parameters:
654 * Stats: Pointer to a D3DSTATS structure to be filled
655 *
656 * Returns:
657 * D3D_OK on success
658 * DDERR_INVALIDPARAMS if Stats == NULL
659 *
660 *****************************************************************************/
661 static HRESULT WINAPI
662 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
663 D3DSTATS *Stats)
664 {
665 IDirect3DDeviceImpl *This = device_from_device3(iface);
666 FIXME("(%p)->(%p): Stub!\n", This, Stats);
667
668 if(!Stats)
669 return DDERR_INVALIDPARAMS;
670
671 /* Fill the Stats with 0 */
672 Stats->dwTrianglesDrawn = 0;
673 Stats->dwLinesDrawn = 0;
674 Stats->dwPointsDrawn = 0;
675 Stats->dwSpansDrawn = 0;
676 Stats->dwVerticesProcessed = 0;
677
678 return D3D_OK;
679 }
680
681 static HRESULT WINAPI
682 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
683 D3DSTATS *Stats)
684 {
685 IDirect3DDeviceImpl *This = device_from_device2(iface);
686 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
687 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
688 }
689
690 static HRESULT WINAPI
691 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
692 D3DSTATS *Stats)
693 {
694 IDirect3DDeviceImpl *This = device_from_device1(iface);
695 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Stats);
696 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
697 }
698
699 /*****************************************************************************
700 * IDirect3DDevice::CreateExecuteBuffer
701 *
702 * Creates an IDirect3DExecuteBuffer, used for rendering with a
703 * Direct3DDevice.
704 *
705 * Version 1 only.
706 *
707 * Params:
708 * Desc: Buffer description
709 * ExecuteBuffer: Address to return the Interface pointer at
710 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
711 * support
712 *
713 * Returns:
714 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
715 * DDERR_OUTOFMEMORY if we ran out of memory
716 * D3D_OK on success
717 *
718 *****************************************************************************/
719 static HRESULT WINAPI
720 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
721 D3DEXECUTEBUFFERDESC *Desc,
722 IDirect3DExecuteBuffer **ExecuteBuffer,
723 IUnknown *UnkOuter)
724 {
725 IDirect3DDeviceImpl *This = device_from_device1(iface);
726 IDirect3DExecuteBufferImpl* object;
727 TRACE("(%p)->(%p,%p,%p)!\n", This, Desc, ExecuteBuffer, UnkOuter);
728
729 if(UnkOuter)
730 return CLASS_E_NOAGGREGATION;
731
732 /* Allocate the new Execute Buffer */
733 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
734 if(!object)
735 {
736 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
737 return DDERR_OUTOFMEMORY;
738 }
739
740 object->lpVtbl = &IDirect3DExecuteBuffer_Vtbl;
741 object->ref = 1;
742 object->d3ddev = This;
743
744 /* Initializes memory */
745 memcpy(&object->desc, Desc, Desc->dwSize);
746
747 /* No buffer given */
748 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
749 object->desc.lpData = NULL;
750
751 /* No buffer size given */
752 if ((object->desc.dwFlags & D3DDEB_BUFSIZE) == 0)
753 object->desc.dwBufferSize = 0;
754
755 /* Create buffer if asked */
756 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0))
757 {
758 object->need_free = TRUE;
759 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
760 if(!object->desc.lpData)
761 {
762 ERR("Out of memory when allocating the execute buffer data\n");
763 HeapFree(GetProcessHeap(), 0, object);
764 return DDERR_OUTOFMEMORY;
765 }
766 }
767 else
768 {
769 object->need_free = FALSE;
770 }
771
772 /* No vertices for the moment */
773 object->vertex_data = NULL;
774
775 object->desc.dwFlags |= D3DDEB_LPDATA;
776
777 object->indices = NULL;
778 object->nb_indices = 0;
779
780 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
781
782 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
783
784 return D3D_OK;
785 }
786
787 /*****************************************************************************
788 * IDirect3DDevice::Execute
789 *
790 * Executes all the stuff in an execute buffer.
791 *
792 * Params:
793 * ExecuteBuffer: The buffer to execute
794 * Viewport: The viewport used for rendering
795 * Flags: Some flags
796 *
797 * Returns:
798 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
799 * D3D_OK on success
800 *
801 *****************************************************************************/
802 static HRESULT WINAPI
803 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
804 IDirect3DExecuteBuffer *ExecuteBuffer,
805 IDirect3DViewport *Viewport,
806 DWORD Flags)
807 {
808 IDirect3DDeviceImpl *This = device_from_device1(iface);
809 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
810 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
811
812 TRACE("(%p)->(%p,%p,%08x)\n", This, Direct3DExecuteBufferImpl, Direct3DViewportImpl, Flags);
813
814 if(!Direct3DExecuteBufferImpl)
815 return DDERR_INVALIDPARAMS;
816
817 /* Execute... */
818 EnterCriticalSection(&ddraw_cs);
819 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
820 LeaveCriticalSection(&ddraw_cs);
821
822 return D3D_OK;
823 }
824
825 /*****************************************************************************
826 * IDirect3DDevice3::AddViewport
827 *
828 * Add a Direct3DViewport to the device's viewport list. These viewports
829 * are wrapped to IDirect3DDevice7 viewports in viewport.c
830 *
831 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
832 * are the same interfaces.
833 *
834 * Params:
835 * Viewport: The viewport to add
836 *
837 * Returns:
838 * DDERR_INVALIDPARAMS if Viewport == NULL
839 * D3D_OK on success
840 *
841 *****************************************************************************/
842 static HRESULT WINAPI
843 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
844 IDirect3DViewport3 *Viewport)
845 {
846 IDirect3DDeviceImpl *This = device_from_device3(iface);
847 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
848
849 TRACE("(%p)->(%p)\n", This, vp);
850
851 /* Sanity check */
852 if(!vp)
853 return DDERR_INVALIDPARAMS;
854
855 EnterCriticalSection(&ddraw_cs);
856 vp->next = This->viewport_list;
857 This->viewport_list = vp;
858 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
859 so set active_device here. */
860 LeaveCriticalSection(&ddraw_cs);
861
862 return D3D_OK;
863 }
864
865 static HRESULT WINAPI
866 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
867 IDirect3DViewport2 *Direct3DViewport2)
868 {
869 IDirect3DDeviceImpl *This = device_from_device2(iface);
870 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
871 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
872 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
873 }
874
875 static HRESULT WINAPI
876 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
877 IDirect3DViewport *Direct3DViewport)
878 {
879 IDirect3DDeviceImpl *This = device_from_device1(iface);
880 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
881 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
882 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
883 }
884
885 /*****************************************************************************
886 * IDirect3DDevice3::DeleteViewport
887 *
888 * Deletes a Direct3DViewport from the device's viewport list.
889 *
890 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
891 * are equal.
892 *
893 * Params:
894 * Viewport: The viewport to delete
895 *
896 * Returns:
897 * D3D_OK on success
898 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
899 *
900 *****************************************************************************/
901 static HRESULT WINAPI
902 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
903 IDirect3DViewport3 *Viewport)
904 {
905 IDirect3DDeviceImpl *This = device_from_device3(iface);
906 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
907 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
908
909 TRACE("(%p)->(%p)\n", This, vp);
910
911 EnterCriticalSection(&ddraw_cs);
912 cur_viewport = This->viewport_list;
913 while (cur_viewport != NULL)
914 {
915 if (cur_viewport == vp)
916 {
917 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
918 else prev_viewport->next = cur_viewport->next;
919 /* TODO : add desactivate of the viewport and all associated lights... */
920 LeaveCriticalSection(&ddraw_cs);
921 return D3D_OK;
922 }
923 prev_viewport = cur_viewport;
924 cur_viewport = cur_viewport->next;
925 }
926
927 LeaveCriticalSection(&ddraw_cs);
928 return DDERR_INVALIDPARAMS;
929 }
930
931 static HRESULT WINAPI
932 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
933 IDirect3DViewport2 *Direct3DViewport2)
934 {
935 IDirect3DDeviceImpl *This = device_from_device2(iface);
936 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
937 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
938 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
939 }
940
941 static HRESULT WINAPI
942 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
943 IDirect3DViewport *Direct3DViewport)
944 {
945 IDirect3DDeviceImpl *This = device_from_device1(iface);
946 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
947 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
948 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
949 }
950
951 /*****************************************************************************
952 * IDirect3DDevice3::NextViewport
953 *
954 * Returns a viewport from the viewport list, depending on the
955 * passed viewport and the flags.
956 *
957 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
958 * are equal.
959 *
960 * Params:
961 * Viewport: Viewport to use for beginning the search
962 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
963 *
964 * Returns:
965 * D3D_OK on success
966 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
967 *
968 *****************************************************************************/
969 static HRESULT WINAPI
970 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
971 IDirect3DViewport3 *Viewport3,
972 IDirect3DViewport3 **lplpDirect3DViewport3,
973 DWORD Flags)
974 {
975 IDirect3DDeviceImpl *This = device_from_device3(iface);
976 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
977 IDirect3DViewportImpl *res = NULL;
978
979 TRACE("(%p)->(%p,%p,%08x)\n", This, vp, lplpDirect3DViewport3, Flags);
980
981 if(!vp)
982 {
983 *lplpDirect3DViewport3 = NULL;
984 return DDERR_INVALIDPARAMS;
985 }
986
987
988 EnterCriticalSection(&ddraw_cs);
989 switch (Flags)
990 {
991 case D3DNEXT_NEXT:
992 {
993 res = vp->next;
994 }
995 break;
996 case D3DNEXT_HEAD:
997 {
998 res = This->viewport_list;
999 }
1000 break;
1001 case D3DNEXT_TAIL:
1002 {
1003 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
1004 if (cur_viewport != NULL)
1005 {
1006 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
1007 }
1008 res = cur_viewport;
1009 }
1010 break;
1011 default:
1012 *lplpDirect3DViewport3 = NULL;
1013 LeaveCriticalSection(&ddraw_cs);
1014 return DDERR_INVALIDPARAMS;
1015 }
1016
1017 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
1018 LeaveCriticalSection(&ddraw_cs);
1019 return D3D_OK;
1020 }
1021
1022 static HRESULT WINAPI
1023 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
1024 IDirect3DViewport2 *Viewport2,
1025 IDirect3DViewport2 **lplpDirect3DViewport2,
1026 DWORD Flags)
1027 {
1028 IDirect3DDeviceImpl *This = device_from_device2(iface);
1029 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
1030 IDirect3DViewport3 *res;
1031 HRESULT hr;
1032 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport2, Flags);
1033 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1034 (IDirect3DViewport3 *)vp, &res, Flags);
1035 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1036 return hr;
1037 }
1038
1039 static HRESULT WINAPI
1040 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1041 IDirect3DViewport *Viewport,
1042 IDirect3DViewport **lplpDirect3DViewport,
1043 DWORD Flags)
1044 {
1045 IDirect3DDeviceImpl *This = device_from_device1(iface);
1046 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1047 IDirect3DViewport3 *res;
1048 HRESULT hr;
1049 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x) thunking to IDirect3DDevice3 interface.\n", This, vp, lplpDirect3DViewport, Flags);
1050 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1051 (IDirect3DViewport3 *)vp, &res, Flags);
1052 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1053 return hr;
1054 }
1055
1056 /*****************************************************************************
1057 * IDirect3DDevice::Pick
1058 *
1059 * Executes an execute buffer without performing rendering. Instead, a
1060 * list of primitives that intersect with (x1,y1) of the passed rectangle
1061 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1062 * this list.
1063 *
1064 * Version 1 only
1065 *
1066 * Params:
1067 * ExecuteBuffer: Buffer to execute
1068 * Viewport: Viewport to use for execution
1069 * Flags: None are defined, according to the SDK
1070 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1071 * x2 and y2 are ignored.
1072 *
1073 * Returns:
1074 * D3D_OK because it's a stub
1075 *
1076 *****************************************************************************/
1077 static HRESULT WINAPI
1078 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1079 IDirect3DExecuteBuffer *ExecuteBuffer,
1080 IDirect3DViewport *Viewport,
1081 DWORD Flags,
1082 D3DRECT *Rect)
1083 {
1084 IDirect3DDeviceImpl *This = device_from_device1(iface);
1085 IDirect3DExecuteBufferImpl *execbuf = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
1086 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1087 FIXME("(%p)->(%p,%p,%08x,%p): stub!\n", This, execbuf, vp, Flags, Rect);
1088
1089 return D3D_OK;
1090 }
1091
1092 /*****************************************************************************
1093 * IDirect3DDevice::GetPickRecords
1094 *
1095 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1096 *
1097 * Version 1 only
1098 *
1099 * Params:
1100 * Count: Pointer to a DWORD containing the numbers of pick records to
1101 * retrieve
1102 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1103 *
1104 * Returns:
1105 * D3D_OK, because it's a stub
1106 *
1107 *****************************************************************************/
1108 static HRESULT WINAPI
1109 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1110 DWORD *Count,
1111 D3DPICKRECORD *D3DPickRec)
1112 {
1113 IDirect3DDeviceImpl *This = device_from_device1(iface);
1114 FIXME("(%p)->(%p,%p): stub!\n", This, Count, D3DPickRec);
1115
1116 return D3D_OK;
1117 }
1118
1119 /*****************************************************************************
1120 * IDirect3DDevice7::EnumTextureformats
1121 *
1122 * Enumerates the supported texture formats. It has a list of all possible
1123 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1124 * WineD3D supports it. If so, then it is passed to the app.
1125 *
1126 * This is for Version 7 and 3, older versions have a different
1127 * callback function and their own implementation
1128 *
1129 * Params:
1130 * Callback: Callback to call for each enumerated format
1131 * Arg: Argument to pass to the callback
1132 *
1133 * Returns:
1134 * D3D_OK on success
1135 * DDERR_INVALIDPARAMS if Callback == NULL
1136 *
1137 *****************************************************************************/
1138 static HRESULT
1139 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1140 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1141 void *Arg)
1142 {
1143 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1144 HRESULT hr;
1145 WINED3DDISPLAYMODE mode;
1146 unsigned int i;
1147
1148 WINED3DFORMAT FormatList[] = {
1149 /* 32 bit */
1150 WINED3DFMT_A8R8G8B8,
1151 WINED3DFMT_X8R8G8B8,
1152 /* 24 bit */
1153 WINED3DFMT_R8G8B8,
1154 /* 16 Bit */
1155 WINED3DFMT_A1R5G5B5,
1156 WINED3DFMT_A4R4G4B4,
1157 WINED3DFMT_R5G6B5,
1158 WINED3DFMT_X1R5G5B5,
1159 /* 8 Bit */
1160 WINED3DFMT_R3G3B2,
1161 WINED3DFMT_P8,
1162 /* FOURCC codes */
1163 WINED3DFMT_DXT1,
1164 WINED3DFMT_DXT3,
1165 WINED3DFMT_DXT5,
1166 };
1167
1168 WINED3DFORMAT BumpFormatList[] = {
1169 WINED3DFMT_R8G8_SNORM,
1170 WINED3DFMT_L6V5U5,
1171 WINED3DFMT_X8L8V8U8,
1172 WINED3DFMT_R8G8B8A8_SNORM,
1173 WINED3DFMT_R16G16_SNORM,
1174 WINED3DFMT_W11V11U10,
1175 WINED3DFMT_A2W10V10U10
1176 };
1177
1178 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1179
1180 if(!Callback)
1181 return DDERR_INVALIDPARAMS;
1182
1183 EnterCriticalSection(&ddraw_cs);
1184
1185 memset(&mode, 0, sizeof(mode));
1186 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1187 0,
1188 &mode);
1189 if(FAILED(hr)) {
1190 LeaveCriticalSection(&ddraw_cs);
1191 WARN("Cannot get the current adapter format\n");
1192 return hr;
1193 }
1194
1195 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1196 {
1197 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1198 WINED3DADAPTER_DEFAULT,
1199 WINED3DDEVTYPE_HAL,
1200 mode.Format,
1201 0 /* Usage */,
1202 WINED3DRTYPE_TEXTURE,
1203 FormatList[i],
1204 SURFACE_OPENGL);
1205 if(hr == D3D_OK)
1206 {
1207 DDPIXELFORMAT pformat;
1208
1209 memset(&pformat, 0, sizeof(pformat));
1210 pformat.dwSize = sizeof(pformat);
1211 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1212
1213 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1214 hr = Callback(&pformat, Arg);
1215 if(hr != DDENUMRET_OK)
1216 {
1217 TRACE("Format enumeration cancelled by application\n");
1218 LeaveCriticalSection(&ddraw_cs);
1219 return D3D_OK;
1220 }
1221 }
1222 }
1223
1224 for(i = 0; i < sizeof(BumpFormatList) / sizeof(WINED3DFORMAT); i++)
1225 {
1226 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1227 WINED3DADAPTER_DEFAULT,
1228 WINED3DDEVTYPE_HAL,
1229 mode.Format,
1230 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1231 WINED3DRTYPE_TEXTURE,
1232 BumpFormatList[i],
1233 SURFACE_OPENGL);
1234 if(hr == D3D_OK)
1235 {
1236 DDPIXELFORMAT pformat;
1237
1238 memset(&pformat, 0, sizeof(pformat));
1239 pformat.dwSize = sizeof(pformat);
1240 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1241
1242 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1243 hr = Callback(&pformat, Arg);
1244 if(hr != DDENUMRET_OK)
1245 {
1246 TRACE("Format enumeration cancelled by application\n");
1247 LeaveCriticalSection(&ddraw_cs);
1248 return D3D_OK;
1249 }
1250 }
1251 }
1252 TRACE("End of enumeration\n");
1253 LeaveCriticalSection(&ddraw_cs);
1254 return D3D_OK;
1255 }
1256
1257 static HRESULT WINAPI
1258 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1259 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1260 void *Arg)
1261 {
1262 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1263 }
1264
1265 static HRESULT WINAPI
1266 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1267 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1268 void *Arg)
1269 {
1270 HRESULT hr;
1271 WORD old_fpucw;
1272
1273 old_fpucw = d3d_fpu_setup();
1274 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1275 set_fpu_control_word(old_fpucw);
1276
1277 return hr;
1278 }
1279
1280 static HRESULT WINAPI
1281 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1282 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1283 void *Arg)
1284 {
1285 IDirect3DDeviceImpl *This = device_from_device3(iface);
1286 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice7 interface.\n", This, Callback, Arg);
1287 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1288 }
1289
1290 /*****************************************************************************
1291 * IDirect3DDevice2::EnumTextureformats
1292 *
1293 * EnumTextureFormats for Version 1 and 2, see
1294 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1295 *
1296 * This version has a different callback and does not enumerate FourCC
1297 * formats
1298 *
1299 *****************************************************************************/
1300 static HRESULT WINAPI
1301 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1302 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1303 void *Arg)
1304 {
1305 IDirect3DDeviceImpl *This = device_from_device2(iface);
1306 HRESULT hr;
1307 unsigned int i;
1308 WINED3DDISPLAYMODE mode;
1309
1310 WINED3DFORMAT FormatList[] = {
1311 /* 32 bit */
1312 WINED3DFMT_A8R8G8B8,
1313 WINED3DFMT_X8R8G8B8,
1314 /* 24 bit */
1315 WINED3DFMT_R8G8B8,
1316 /* 16 Bit */
1317 WINED3DFMT_A1R5G5B5,
1318 WINED3DFMT_A4R4G4B4,
1319 WINED3DFMT_R5G6B5,
1320 WINED3DFMT_X1R5G5B5,
1321 /* 8 Bit */
1322 WINED3DFMT_R3G3B2,
1323 WINED3DFMT_P8,
1324 /* FOURCC codes - Not in this version*/
1325 };
1326
1327 TRACE("(%p)->(%p,%p): Relay\n", This, Callback, Arg);
1328
1329 if(!Callback)
1330 return DDERR_INVALIDPARAMS;
1331
1332 EnterCriticalSection(&ddraw_cs);
1333
1334 memset(&mode, 0, sizeof(mode));
1335 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1336 0,
1337 &mode);
1338 if(FAILED(hr)) {
1339 LeaveCriticalSection(&ddraw_cs);
1340 WARN("Cannot get the current adapter format\n");
1341 return hr;
1342 }
1343
1344 for(i = 0; i < sizeof(FormatList) / sizeof(WINED3DFORMAT); i++)
1345 {
1346 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1347 0 /* Adapter */,
1348 WINED3DDEVTYPE_HAL,
1349 mode.Format,
1350 0 /* Usage */,
1351 WINED3DRTYPE_TEXTURE,
1352 FormatList[i],
1353 SURFACE_OPENGL);
1354 if(hr == D3D_OK)
1355 {
1356 DDSURFACEDESC sdesc;
1357
1358 memset(&sdesc, 0, sizeof(sdesc));
1359 sdesc.dwSize = sizeof(sdesc);
1360 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1361 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1362 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1363 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1364
1365 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1366 hr = Callback(&sdesc, Arg);
1367 if(hr != DDENUMRET_OK)
1368 {
1369 TRACE("Format enumeration cancelled by application\n");
1370 LeaveCriticalSection(&ddraw_cs);
1371 return D3D_OK;
1372 }
1373 }
1374 }
1375 TRACE("End of enumeration\n");
1376 LeaveCriticalSection(&ddraw_cs);
1377 return D3D_OK;
1378 }
1379
1380 static HRESULT WINAPI
1381 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1382 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1383 void *Arg)
1384 {
1385 IDirect3DDeviceImpl *This = device_from_device1(iface);
1386 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DDevice2 interface.\n", This, Callback, Arg);
1387 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1388 }
1389
1390 /*****************************************************************************
1391 * IDirect3DDevice::CreateMatrix
1392 *
1393 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1394 * allocated for the handle.
1395 *
1396 * Version 1 only
1397 *
1398 * Params
1399 * D3DMatHandle: Address to return the handle at
1400 *
1401 * Returns:
1402 * D3D_OK on success
1403 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1404 *
1405 *****************************************************************************/
1406 static HRESULT WINAPI
1407 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1408 {
1409 IDirect3DDeviceImpl *This = device_from_device1(iface);
1410 D3DMATRIX *Matrix;
1411 TRACE("(%p)->(%p)\n", This, D3DMatHandle);
1412
1413 if(!D3DMatHandle)
1414 return DDERR_INVALIDPARAMS;
1415
1416 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1417 if(!Matrix)
1418 {
1419 ERR("Out of memory when allocating a D3DMATRIX\n");
1420 return DDERR_OUTOFMEMORY;
1421 }
1422
1423 EnterCriticalSection(&ddraw_cs);
1424 *D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
1425 if(!(*D3DMatHandle))
1426 {
1427 ERR("Failed to create a matrix handle\n");
1428 HeapFree(GetProcessHeap(), 0, Matrix);
1429 LeaveCriticalSection(&ddraw_cs);
1430 return DDERR_OUTOFMEMORY;
1431 }
1432 This->Handles[*D3DMatHandle - 1].ptr = Matrix;
1433 This->Handles[*D3DMatHandle - 1].type = DDrawHandle_Matrix;
1434 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1435
1436 LeaveCriticalSection(&ddraw_cs);
1437 return D3D_OK;
1438 }
1439
1440 /*****************************************************************************
1441 * IDirect3DDevice::SetMatrix
1442 *
1443 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1444 * allocated for the handle
1445 *
1446 * Version 1 only
1447 *
1448 * Params:
1449 * D3DMatHandle: Handle to set the matrix to
1450 * D3DMatrix: Matrix to set
1451 *
1452 * Returns:
1453 * D3D_OK on success
1454 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1455 * to set is NULL
1456 *
1457 *****************************************************************************/
1458 static HRESULT WINAPI
1459 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1460 D3DMATRIXHANDLE D3DMatHandle,
1461 D3DMATRIX *D3DMatrix)
1462 {
1463 IDirect3DDeviceImpl *This = device_from_device1(iface);
1464 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1465
1466 if( (!D3DMatHandle) || (!D3DMatrix) )
1467 return DDERR_INVALIDPARAMS;
1468
1469 EnterCriticalSection(&ddraw_cs);
1470 if(D3DMatHandle > This->numHandles)
1471 {
1472 ERR("Handle %d out of range\n", D3DMatHandle);
1473 LeaveCriticalSection(&ddraw_cs);
1474 return DDERR_INVALIDPARAMS;
1475 }
1476 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1477 {
1478 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1479 LeaveCriticalSection(&ddraw_cs);
1480 return DDERR_INVALIDPARAMS;
1481 }
1482
1483 if (TRACE_ON(d3d7))
1484 dump_D3DMATRIX(D3DMatrix);
1485
1486 *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
1487
1488 if(This->world == D3DMatHandle)
1489 {
1490 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1491 WINED3DTS_WORLDMATRIX(0),
1492 (WINED3DMATRIX *) D3DMatrix);
1493 }
1494 if(This->view == D3DMatHandle)
1495 {
1496 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1497 WINED3DTS_VIEW,
1498 (WINED3DMATRIX *) D3DMatrix);
1499 }
1500 if(This->proj == D3DMatHandle)
1501 {
1502 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1503 WINED3DTS_PROJECTION,
1504 (WINED3DMATRIX *) D3DMatrix);
1505 }
1506
1507 LeaveCriticalSection(&ddraw_cs);
1508 return D3D_OK;
1509 }
1510
1511 /*****************************************************************************
1512 * IDirect3DDevice::SetMatrix
1513 *
1514 * Returns the content of a D3DMATRIX handle
1515 *
1516 * Version 1 only
1517 *
1518 * Params:
1519 * D3DMatHandle: Matrix handle to read the content from
1520 * D3DMatrix: Address to store the content at
1521 *
1522 * Returns:
1523 * D3D_OK on success
1524 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1525 *
1526 *****************************************************************************/
1527 static HRESULT WINAPI
1528 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1529 D3DMATRIXHANDLE D3DMatHandle,
1530 D3DMATRIX *D3DMatrix)
1531 {
1532 IDirect3DDeviceImpl *This = device_from_device1(iface);
1533 TRACE("(%p)->(%08x,%p)\n", This, D3DMatHandle, D3DMatrix);
1534
1535 if(!D3DMatrix)
1536 return DDERR_INVALIDPARAMS;
1537 if(!D3DMatHandle)
1538 return DDERR_INVALIDPARAMS;
1539
1540 EnterCriticalSection(&ddraw_cs);
1541 if(D3DMatHandle > This->numHandles)
1542 {
1543 ERR("Handle %d out of range\n", D3DMatHandle);
1544 LeaveCriticalSection(&ddraw_cs);
1545 return DDERR_INVALIDPARAMS;
1546 }
1547 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1548 {
1549 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1550 LeaveCriticalSection(&ddraw_cs);
1551 return DDERR_INVALIDPARAMS;
1552 }
1553
1554 /* The handle is simply a pointer to a D3DMATRIX structure */
1555 *D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
1556
1557 LeaveCriticalSection(&ddraw_cs);
1558 return D3D_OK;
1559 }
1560
1561 /*****************************************************************************
1562 * IDirect3DDevice::DeleteMatrix
1563 *
1564 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1565 *
1566 * Version 1 only
1567 *
1568 * Params:
1569 * D3DMatHandle: Handle to destroy
1570 *
1571 * Returns:
1572 * D3D_OK on success
1573 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1574 *
1575 *****************************************************************************/
1576 static HRESULT WINAPI
1577 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1578 D3DMATRIXHANDLE D3DMatHandle)
1579 {
1580 IDirect3DDeviceImpl *This = device_from_device1(iface);
1581 TRACE("(%p)->(%08x)\n", This, D3DMatHandle);
1582
1583 if(!D3DMatHandle)
1584 return DDERR_INVALIDPARAMS;
1585
1586 EnterCriticalSection(&ddraw_cs);
1587 if(D3DMatHandle > This->numHandles)
1588 {
1589 ERR("Handle %d out of range\n", D3DMatHandle);
1590 LeaveCriticalSection(&ddraw_cs);
1591 return DDERR_INVALIDPARAMS;
1592 }
1593 else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
1594 {
1595 ERR("Handle %d is not a matrix handle\n", D3DMatHandle);
1596 LeaveCriticalSection(&ddraw_cs);
1597 return DDERR_INVALIDPARAMS;
1598 }
1599
1600 HeapFree(GetProcessHeap(), 0, This->Handles[D3DMatHandle - 1].ptr);
1601 This->Handles[D3DMatHandle - 1].ptr = NULL;
1602 This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
1603
1604 LeaveCriticalSection(&ddraw_cs);
1605 return D3D_OK;
1606 }
1607
1608 /*****************************************************************************
1609 * IDirect3DDevice7::BeginScene
1610 *
1611 * This method must be called before any rendering is performed.
1612 * IDirect3DDevice::EndScene has to be called after the scene is complete
1613 *
1614 * Version 1, 2, 3 and 7
1615 *
1616 * Returns:
1617 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1618 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1619 * started scene).
1620 *
1621 *****************************************************************************/
1622 static HRESULT
1623 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1624 {
1625 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1626 HRESULT hr;
1627 TRACE("(%p): Relay\n", This);
1628
1629 EnterCriticalSection(&ddraw_cs);
1630 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1631 LeaveCriticalSection(&ddraw_cs);
1632 if(hr == WINED3D_OK) return D3D_OK;
1633 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1634 }
1635
1636 static HRESULT WINAPI
1637 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1638 {
1639 return IDirect3DDeviceImpl_7_BeginScene(iface);
1640 }
1641
1642 static HRESULT WINAPI
1643 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1644 {
1645 HRESULT hr;
1646 WORD old_fpucw;
1647
1648 old_fpucw = d3d_fpu_setup();
1649 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1650 set_fpu_control_word(old_fpucw);
1651
1652 return hr;
1653 }
1654
1655 static HRESULT WINAPI
1656 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1657 {
1658 IDirect3DDeviceImpl *This = device_from_device3(iface);
1659 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1660 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1661 }
1662
1663 static HRESULT WINAPI
1664 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1665 {
1666 IDirect3DDeviceImpl *This = device_from_device2(iface);
1667 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1668 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1669 }
1670
1671 static HRESULT WINAPI
1672 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1673 {
1674 IDirect3DDeviceImpl *This = device_from_device1(iface);
1675 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1676 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1677 }
1678
1679 /*****************************************************************************
1680 * IDirect3DDevice7::EndScene
1681 *
1682 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1683 * This method must be called after rendering is finished.
1684 *
1685 * Version 1, 2, 3 and 7
1686 *
1687 * Returns:
1688 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1689 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1690 * that only if the scene was already ended.
1691 *
1692 *****************************************************************************/
1693 static HRESULT
1694 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1695 {
1696 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1697 HRESULT hr;
1698 TRACE("(%p): Relay\n", This);
1699
1700 EnterCriticalSection(&ddraw_cs);
1701 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1702 LeaveCriticalSection(&ddraw_cs);
1703 if(hr == WINED3D_OK) return D3D_OK;
1704 else return D3DERR_SCENE_NOT_IN_SCENE;
1705 }
1706
1707 static HRESULT WINAPI
1708 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1709 {
1710 return IDirect3DDeviceImpl_7_EndScene(iface);
1711 }
1712
1713 static HRESULT WINAPI
1714 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1715 {
1716 HRESULT hr;
1717 WORD old_fpucw;
1718
1719 old_fpucw = d3d_fpu_setup();
1720 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1721 set_fpu_control_word(old_fpucw);
1722
1723 return hr;
1724 }
1725
1726 static HRESULT WINAPI
1727 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1728 {
1729 IDirect3DDeviceImpl *This = device_from_device3(iface);
1730 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1731 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1732 }
1733
1734 static HRESULT WINAPI
1735 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1736 {
1737 IDirect3DDeviceImpl *This = device_from_device2(iface);
1738 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1739 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1740 }
1741
1742 static HRESULT WINAPI
1743 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1744 {
1745 IDirect3DDeviceImpl *This = device_from_device1(iface);
1746 TRACE_(ddraw_thunk)("(%p)->() thunking to IDirect3DDevice7 interface.\n", This);
1747 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1748 }
1749
1750 /*****************************************************************************
1751 * IDirect3DDevice7::GetDirect3D
1752 *
1753 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1754 * this device.
1755 *
1756 * Params:
1757 * Direct3D7: Address to store the interface pointer at
1758 *
1759 * Returns:
1760 * D3D_OK on success
1761 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1762 *
1763 *****************************************************************************/
1764 static HRESULT WINAPI
1765 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1766 IDirect3D7 **Direct3D7)
1767 {
1768 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1769 TRACE("(%p)->(%p)\n", This, Direct3D7);
1770
1771 if(!Direct3D7)
1772 return DDERR_INVALIDPARAMS;
1773
1774 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1775 IDirect3D7_AddRef(*Direct3D7);
1776
1777 TRACE(" returning interface %p\n", *Direct3D7);
1778 return D3D_OK;
1779 }
1780
1781 static HRESULT WINAPI
1782 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1783 IDirect3D3 **Direct3D3)
1784 {
1785 IDirect3DDeviceImpl *This = device_from_device3(iface);
1786 HRESULT ret;
1787 IDirect3D7 *ret_ptr;
1788
1789 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D3);
1790 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1791 if(ret != D3D_OK)
1792 return ret;
1793 *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1794 TRACE(" returning interface %p\n", *Direct3D3);
1795 return D3D_OK;
1796 }
1797
1798 static HRESULT WINAPI
1799 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1800 IDirect3D2 **Direct3D2)
1801 {
1802 IDirect3DDeviceImpl *This = device_from_device2(iface);
1803 HRESULT ret;
1804 IDirect3D7 *ret_ptr;
1805
1806 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D2);
1807 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1808 if(ret != D3D_OK)
1809 return ret;
1810 *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1811 TRACE(" returning interface %p\n", *Direct3D2);
1812 return D3D_OK;
1813 }
1814
1815 static HRESULT WINAPI
1816 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1817 IDirect3D **Direct3D)
1818 {
1819 IDirect3DDeviceImpl *This = device_from_device1(iface);
1820 HRESULT ret;
1821 IDirect3D7 *ret_ptr;
1822
1823 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Direct3D);
1824 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1825 if(ret != D3D_OK)
1826 return ret;
1827 *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1828 TRACE(" returning interface %p\n", *Direct3D);
1829 return D3D_OK;
1830 }
1831
1832 /*****************************************************************************
1833 * IDirect3DDevice3::SetCurrentViewport
1834 *
1835 * Sets a Direct3DViewport as the current viewport.
1836 * For the thunks note that all viewport interface versions are equal
1837 *
1838 * Params:
1839 * Direct3DViewport3: The viewport to set
1840 *
1841 * Version 2 and 3
1842 *
1843 * Returns:
1844 * D3D_OK on success
1845 * (Is a NULL viewport valid?)
1846 *
1847 *****************************************************************************/
1848 static HRESULT WINAPI
1849 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1850 IDirect3DViewport3 *Direct3DViewport3)
1851 {
1852 IDirect3DDeviceImpl *This = device_from_device3(iface);
1853 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1854 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1855
1856 EnterCriticalSection(&ddraw_cs);
1857 /* Do nothing if the specified viewport is the same as the current one */
1858 if (This->current_viewport == vp )
1859 {
1860 LeaveCriticalSection(&ddraw_cs);
1861 return D3D_OK;
1862 }
1863
1864 /* Should check if the viewport was added or not */
1865
1866 /* Release previous viewport and AddRef the new one */
1867 if (This->current_viewport)
1868 {
1869 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1870 (IDirect3DViewport3 *)This->current_viewport);
1871 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1872 }
1873 IDirect3DViewport3_AddRef(Direct3DViewport3);
1874
1875 /* Set this viewport as the current viewport */
1876 This->current_viewport = vp;
1877
1878 /* Activate this viewport */
1879 This->current_viewport->active_device = This;
1880 This->current_viewport->activate(This->current_viewport, FALSE);
1881
1882 LeaveCriticalSection(&ddraw_cs);
1883 return D3D_OK;
1884 }
1885
1886 static HRESULT WINAPI
1887 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1888 IDirect3DViewport2 *Direct3DViewport2)
1889 {
1890 IDirect3DDeviceImpl *This = device_from_device2(iface);
1891 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1892 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, vp);
1893 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1894 (IDirect3DViewport3 *)vp);
1895 }
1896
1897 /*****************************************************************************
1898 * IDirect3DDevice3::GetCurrentViewport
1899 *
1900 * Returns the currently active viewport.
1901 *
1902 * Version 2 and 3
1903 *
1904 * Params:
1905 * Direct3DViewport3: Address to return the interface pointer at
1906 *
1907 * Returns:
1908 * D3D_OK on success
1909 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1910 *
1911 *****************************************************************************/
1912 static HRESULT WINAPI
1913 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1914 IDirect3DViewport3 **Direct3DViewport3)
1915 {
1916 IDirect3DDeviceImpl *This = device_from_device3(iface);
1917 TRACE("(%p)->(%p)\n", This, Direct3DViewport3);
1918
1919 if(!Direct3DViewport3)
1920 return DDERR_INVALIDPARAMS;
1921
1922 EnterCriticalSection(&ddraw_cs);
1923 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1924
1925 /* AddRef the returned viewport */
1926 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1927
1928 TRACE(" returning interface %p\n", *Direct3DViewport3);
1929
1930 LeaveCriticalSection(&ddraw_cs);
1931 return D3D_OK;
1932 }
1933
1934 static HRESULT WINAPI
1935 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1936 IDirect3DViewport2 **Direct3DViewport2)
1937 {
1938 IDirect3DDeviceImpl *This = device_from_device2(iface);
1939 HRESULT hr;
1940 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, Direct3DViewport2);
1941 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1942 (IDirect3DViewport3 **)Direct3DViewport2);
1943 if(hr != D3D_OK) return hr;
1944 return D3D_OK;
1945 }
1946
1947 /*****************************************************************************
1948 * IDirect3DDevice7::SetRenderTarget
1949 *
1950 * Sets the render target for the Direct3DDevice.
1951 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1952 * IDirectDrawSurface3 == IDirectDrawSurface
1953 *
1954 * Version 2, 3 and 7
1955 *
1956 * Params:
1957 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1958 * render target
1959 * Flags: Some flags
1960 *
1961 * Returns:
1962 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1963 *
1964 *****************************************************************************/
1965 static HRESULT
1966 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1967 IDirectDrawSurface7 *NewTarget,
1968 DWORD Flags)
1969 {
1970 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1971 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1972 HRESULT hr;
1973 TRACE("(%p)->(%p,%08x): Relay\n", This, NewTarget, Flags);
1974
1975 EnterCriticalSection(&ddraw_cs);
1976 /* Flags: Not used */
1977
1978 if(This->target == Target)
1979 {
1980 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1981 LeaveCriticalSection(&ddraw_cs);
1982 return D3D_OK;
1983 }
1984
1985 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1986 0,
1987 Target ? Target->WineD3DSurface : NULL);
1988 if(hr != D3D_OK)
1989 {
1990 LeaveCriticalSection(&ddraw_cs);
1991 return hr;
1992 }
1993 IDirectDrawSurface7_AddRef(NewTarget);
1994 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1995 This->target = Target;
1996 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1997 LeaveCriticalSection(&ddraw_cs);
1998 return D3D_OK;
1999 }
2000
2001 static HRESULT WINAPI
2002 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
2003 IDirectDrawSurface7 *NewTarget,
2004 DWORD Flags)
2005 {
2006 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2007 }
2008
2009 static HRESULT WINAPI
2010 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
2011 IDirectDrawSurface7 *NewTarget,
2012 DWORD Flags)
2013 {
2014 HRESULT hr;
2015 WORD old_fpucw;
2016
2017 old_fpucw = d3d_fpu_setup();
2018 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2019 set_fpu_control_word(old_fpucw);
2020
2021 return hr;
2022 }
2023
2024 static HRESULT WINAPI
2025 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2026 IDirectDrawSurface4 *NewRenderTarget,
2027 DWORD Flags)
2028 {
2029 IDirect3DDeviceImpl *This = device_from_device3(iface);
2030 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2031 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2032 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2033 }
2034
2035 static HRESULT WINAPI
2036 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2037 IDirectDrawSurface *NewRenderTarget,
2038 DWORD Flags)
2039 {
2040 IDirect3DDeviceImpl *This = device_from_device2(iface);
2041 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2042 TRACE_(ddraw_thunk)("(%p)->(%p,%08x) thunking to IDirect3DDevice7 interface.\n", This, Target, Flags);
2043 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2044 }
2045
2046 /*****************************************************************************
2047 * IDirect3DDevice7::GetRenderTarget
2048 *
2049 * Returns the current render target.
2050 * This is handled locally, because the WineD3D render target's parent
2051 * is an IParent
2052 *
2053 * Version 2, 3 and 7
2054 *
2055 * Params:
2056 * RenderTarget: Address to store the surface interface pointer
2057 *
2058 * Returns:
2059 * D3D_OK on success
2060 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2061 *
2062 *****************************************************************************/
2063 static HRESULT WINAPI
2064 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2065 IDirectDrawSurface7 **RenderTarget)
2066 {
2067 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2068 TRACE("(%p)->(%p): Relay\n", This, RenderTarget);
2069
2070 if(!RenderTarget)
2071 return DDERR_INVALIDPARAMS;
2072
2073 EnterCriticalSection(&ddraw_cs);
2074 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2075 IDirectDrawSurface7_AddRef(*RenderTarget);
2076
2077 LeaveCriticalSection(&ddraw_cs);
2078 return D3D_OK;
2079 }
2080
2081 static HRESULT WINAPI
2082 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2083 IDirectDrawSurface4 **RenderTarget)
2084 {
2085 IDirect3DDeviceImpl *This = device_from_device3(iface);
2086 HRESULT hr;
2087 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2088 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2089 if(hr != D3D_OK) return hr;
2090 return D3D_OK;
2091 }
2092
2093 static HRESULT WINAPI
2094 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2095 IDirectDrawSurface **RenderTarget)
2096 {
2097 IDirect3DDeviceImpl *This = device_from_device2(iface);
2098 HRESULT hr;
2099 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, RenderTarget);
2100 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2101 if(hr != D3D_OK) return hr;
2102 *RenderTarget = *RenderTarget ?
2103 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2104 return D3D_OK;
2105 }
2106
2107 /*****************************************************************************
2108 * IDirect3DDevice3::Begin
2109 *
2110 * Begins a description block of vertices. This is similar to glBegin()
2111 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2112 * described with IDirect3DDevice::Vertex are drawn.
2113 *
2114 * Version 2 and 3
2115 *
2116 * Params:
2117 * PrimitiveType: The type of primitives to draw
2118 * VertexTypeDesc: A flexible vertex format description of the vertices
2119 * Flags: Some flags..
2120 *
2121 * Returns:
2122 * D3D_OK on success
2123 *
2124 *****************************************************************************/
2125 static HRESULT WINAPI
2126 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2127 D3DPRIMITIVETYPE PrimitiveType,
2128 DWORD VertexTypeDesc,
2129 DWORD Flags)
2130 {
2131 IDirect3DDeviceImpl *This = device_from_device3(iface);
2132 TRACE("(%p)->(%d,%d,%08x)\n", This, PrimitiveType, VertexTypeDesc, Flags);
2133
2134 EnterCriticalSection(&ddraw_cs);
2135 This->primitive_type = PrimitiveType;
2136 This->vertex_type = VertexTypeDesc;
2137 This->render_flags = Flags;
2138 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2139 This->nb_vertices = 0;
2140 LeaveCriticalSection(&ddraw_cs);
2141
2142 return D3D_OK;
2143 }
2144
2145 static HRESULT WINAPI
2146 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2147 D3DPRIMITIVETYPE d3dpt,
2148 D3DVERTEXTYPE dwVertexTypeDesc,
2149 DWORD dwFlags)
2150 {
2151 DWORD FVF;
2152 IDirect3DDeviceImpl *This = device_from_device2(iface);
2153 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dpt, dwVertexTypeDesc, dwFlags);
2154
2155 switch(dwVertexTypeDesc)
2156 {
2157 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2158 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2159 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2160 default:
2161 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2162 return DDERR_INVALIDPARAMS; /* Should never happen */
2163 };
2164
2165 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2166 }
2167
2168 /*****************************************************************************
2169 * IDirect3DDevice3::BeginIndexed
2170 *
2171 * Draws primitives based on vertices in a vertex array which are specified
2172 * by indices.
2173 *
2174 * Version 2 and 3
2175 *
2176 * Params:
2177 * PrimitiveType: Primitive type to draw
2178 * VertexType: A FVF description of the vertex format
2179 * Vertices: pointer to an array containing the vertices
2180 * NumVertices: The number of vertices in the vertex array
2181 * Flags: Some flags ...
2182 *
2183 * Returns:
2184 * D3D_OK, because it's a stub
2185 *
2186 *****************************************************************************/
2187 static HRESULT WINAPI
2188 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2189 D3DPRIMITIVETYPE PrimitiveType,
2190 DWORD VertexType,
2191 void *Vertices,
2192 DWORD NumVertices,
2193 DWORD Flags)
2194 {
2195 IDirect3DDeviceImpl *This = device_from_device3(iface);
2196 FIXME("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2197 return D3D_OK;
2198 }
2199
2200
2201 static HRESULT WINAPI
2202 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2203 D3DPRIMITIVETYPE d3dptPrimitiveType,
2204 D3DVERTEXTYPE d3dvtVertexType,
2205 void *lpvVertices,
2206 DWORD dwNumVertices,
2207 DWORD dwFlags)
2208 {
2209 DWORD FVF;
2210 IDirect3DDeviceImpl *This = device_from_device2(iface);
2211 TRACE_(ddraw_thunk)("(%p/%p)->(%08x,%08x,%p,%08x,%08x): Thunking to IDirect3DDevice3\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2212
2213 switch(d3dvtVertexType)
2214 {
2215 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2216 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2217 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2218 default:
2219 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2220 return DDERR_INVALIDPARAMS; /* Should never happen */
2221 };
2222
2223 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2224 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2225 }
2226
2227 /*****************************************************************************
2228 * IDirect3DDevice3::Vertex
2229 *
2230 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2231 * drawn vertices in a vertex buffer. If the buffer is too small, its
2232 * size is increased.
2233 *
2234 * Version 2 and 3
2235 *
2236 * Params:
2237 * Vertex: Pointer to the vertex
2238 *
2239 * Returns:
2240 * D3D_OK, on success
2241 * DDERR_INVALIDPARAMS if Vertex is NULL
2242 *
2243 *****************************************************************************/
2244 static HRESULT WINAPI
2245 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2246 void *Vertex)
2247 {
2248 IDirect3DDeviceImpl *This = device_from_device3(iface);
2249 TRACE("(%p)->(%p)\n", This, Vertex);
2250
2251 if(!Vertex)
2252 return DDERR_INVALIDPARAMS;
2253
2254 EnterCriticalSection(&ddraw_cs);
2255 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2256 {
2257 BYTE *old_buffer;
2258 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2259 old_buffer = This->vertex_buffer;
2260 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2261 if (old_buffer)
2262 {
2263 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2264 HeapFree(GetProcessHeap(), 0, old_buffer);
2265 }
2266 }
2267
2268 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2269
2270 LeaveCriticalSection(&ddraw_cs);
2271 return D3D_OK;
2272 }
2273
2274 static HRESULT WINAPI
2275 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2276 void *lpVertexType)
2277 {
2278 IDirect3DDeviceImpl *This = device_from_device2(iface);
2279 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice3 interface.\n", This, lpVertexType);
2280 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2281 }
2282
2283 /*****************************************************************************
2284 * IDirect3DDevice3::Index
2285 *
2286 * Specifies an index to a vertex to be drawn. The vertex array has to
2287 * be specified with BeginIndexed first.
2288 *
2289 * Parameters:
2290 * VertexIndex: The index of the vertex to draw
2291 *
2292 * Returns:
2293 * D3D_OK because it's a stub
2294 *
2295 *****************************************************************************/
2296 static HRESULT WINAPI
2297 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2298 WORD VertexIndex)
2299 {
2300 IDirect3DDeviceImpl *This = device_from_device3(iface);
2301 FIXME("(%p)->(%04x): stub!\n", This, VertexIndex);
2302 return D3D_OK;
2303 }
2304
2305 static HRESULT WINAPI
2306 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2307 WORD wVertexIndex)
2308 {
2309 IDirect3DDeviceImpl *This = device_from_device2(iface);
2310 TRACE_(ddraw_thunk)("(%p)->(%04x) thunking to IDirect3DDevice3 interface.\n", This, wVertexIndex);
2311 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2312 }
2313
2314 /*****************************************************************************
2315 * IDirect3DDevice3::End
2316 *
2317 * Ends a draw begun with IDirect3DDevice3::Begin or
2318 * IDirect3DDevice::BeginIndexed. The vertices specified with
2319 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2320 * the IDirect3DDevice7::DrawPrimitive method. So far only
2321 * non-indexed mode is supported
2322 *
2323 * Version 2 and 3
2324 *
2325 * Params:
2326 * Flags: Some flags, as usual. Don't know which are defined
2327 *
2328 * Returns:
2329 * The return value of IDirect3DDevice7::DrawPrimitive
2330 *
2331 *****************************************************************************/
2332 static HRESULT WINAPI
2333 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2334 DWORD Flags)
2335 {
2336 IDirect3DDeviceImpl *This = device_from_device3(iface);
2337 TRACE("(%p)->(%08x)\n", This, Flags);
2338
2339 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2340 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2341 }
2342
2343 static HRESULT WINAPI
2344 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2345 DWORD dwFlags)
2346 {
2347 IDirect3DDeviceImpl *This = device_from_device2(iface);
2348 TRACE_(ddraw_thunk)("(%p)->(%08x) thunking to IDirect3DDevice3 interface.\n", This, dwFlags);
2349 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2350 }
2351
2352 /*****************************************************************************
2353 * IDirect3DDevice7::GetRenderState
2354 *
2355 * Returns the value of a render state. The possible render states are
2356 * defined in include/d3dtypes.h
2357 *
2358 * Version 2, 3 and 7
2359 *
2360 * Params:
2361 * RenderStateType: Render state to return the current setting of
2362 * Value: Address to store the value at
2363 *
2364 * Returns:
2365 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2366 * DDERR_INVALIDPARAMS if Value == NULL
2367 *
2368 *****************************************************************************/
2369 static HRESULT
2370 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2371 D3DRENDERSTATETYPE RenderStateType,
2372 DWORD *Value)
2373 {
2374 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2375 HRESULT hr;
2376 TRACE("(%p)->(%08x,%p): Relay\n", This, RenderStateType, Value);
2377
2378 if(!Value)
2379 return DDERR_INVALIDPARAMS;
2380
2381 EnterCriticalSection(&ddraw_cs);
2382 switch(RenderStateType)
2383 {
2384 case D3DRENDERSTATE_TEXTUREMAG:
2385 {
2386 WINED3DTEXTUREFILTERTYPE tex_mag;
2387
2388 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2389 0, WINED3DSAMP_MAGFILTER,
2390 &tex_mag);
2391
2392 switch (tex_mag)
2393 {
2394 case WINED3DTEXF_POINT:
2395 *Value = D3DFILTER_NEAREST;
2396 break;
2397 case WINED3DTEXF_LINEAR:
2398 *Value = D3DFILTER_LINEAR;
2399 break;
2400 default:
2401 ERR("Unhandled texture mag %d !\n",tex_mag);
2402 *Value = 0;
2403 }
2404 break;
2405 }
2406
2407 case D3DRENDERSTATE_TEXTUREMIN:
2408 {
2409 WINED3DTEXTUREFILTERTYPE tex_min;
2410
2411 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2412 0, WINED3DSAMP_MINFILTER,
2413 &tex_min);
2414
2415 switch (tex_min)
2416 {
2417 case WINED3DTEXF_POINT:
2418 *Value = D3DFILTER_NEAREST;
2419 break;
2420 case WINED3DTEXF_LINEAR:
2421 *Value = D3DFILTER_LINEAR;
2422 break;
2423 default:
2424 ERR("Unhandled texture mag %d !\n",tex_min);
2425 *Value = 0;
2426 }
2427 break;
2428 }
2429
2430 case D3DRENDERSTATE_TEXTUREADDRESS:
2431 case D3DRENDERSTATE_TEXTUREADDRESSU:
2432 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2433 0, WINED3DSAMP_ADDRESSU,
2434 Value);
2435 break;
2436 case D3DRENDERSTATE_TEXTUREADDRESSV:
2437 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2438 0, WINED3DSAMP_ADDRESSV,
2439 Value);
2440 break;
2441
2442 default:
2443 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2444 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2445 RenderStateType,
2446 Value);
2447 }
2448 LeaveCriticalSection(&ddraw_cs);
2449 return hr;
2450 }
2451
2452 static HRESULT WINAPI
2453 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2454 D3DRENDERSTATETYPE RenderStateType,
2455 DWORD *Value)
2456 {
2457 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2458 }
2459
2460 static HRESULT WINAPI
2461 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2462 D3DRENDERSTATETYPE RenderStateType,
2463 DWORD *Value)
2464 {
2465 HRESULT hr;
2466 WORD old_fpucw;
2467
2468 old_fpucw = d3d_fpu_setup();
2469 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2470 set_fpu_control_word(old_fpucw);
2471
2472 return hr;
2473 }
2474
2475 static HRESULT WINAPI
2476 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2477 D3DRENDERSTATETYPE dwRenderStateType,
2478 DWORD *lpdwRenderState)
2479 {
2480 IDirect3DDeviceImpl *This = device_from_device3(iface);
2481 HRESULT hr;
2482 TRACE("(%p)->(%08x,%p)\n", This, dwRenderStateType, lpdwRenderState);
2483
2484 switch(dwRenderStateType)
2485 {
2486 case D3DRENDERSTATE_TEXTUREHANDLE:
2487 {
2488 /* This state is wrapped to SetTexture in SetRenderState, so
2489 * it has to be wrapped to GetTexture here
2490 */
2491 IWineD3DBaseTexture *tex = NULL;
2492 *lpdwRenderState = 0;
2493
2494 EnterCriticalSection(&ddraw_cs);
2495
2496 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2497 0,
2498 &tex);
2499
2500 if(hr == WINED3D_OK && tex)
2501 {
2502 IDirectDrawSurface7 *parent = NULL;
2503 hr = IWineD3DBaseTexture_GetParent(tex,
2504 (IUnknown **) &parent);
2505 if(parent)
2506 {
2507 /* The parent of the texture is the IDirectDrawSurface7 interface
2508 * of the ddraw surface
2509 */
2510 IDirectDrawSurfaceImpl *texImpl = (IDirectDrawSurfaceImpl *)parent;
2511 *lpdwRenderState = texImpl->Handle;
2512 IDirectDrawSurface7_Release(parent);
2513 }
2514 IWineD3DBaseTexture_Release(tex);
2515 }
2516
2517 LeaveCriticalSection(&ddraw_cs);
2518
2519 return hr;
2520 }
2521
2522 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2523 {
2524 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2525 the mapping to get the value. */
2526 DWORD colorop, colorarg1, colorarg2;
2527 DWORD alphaop, alphaarg1, alphaarg2;
2528
2529 EnterCriticalSection(&ddraw_cs);
2530
2531 This->legacyTextureBlending = TRUE;
2532
2533 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2534 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2535 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2536 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2537 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2538 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2539
2540 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2541 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2542 {
2543 *lpdwRenderState = D3DTBLEND_DECAL;
2544 }
2545 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2546 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2547 {
2548 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2549 }
2550 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2551 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2552 {
2553 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2554 }
2555 else
2556 {
2557 HRESULT hr;
2558 BOOL tex_alpha = FALSE;
2559 IWineD3DBaseTexture *tex = NULL;
2560 WINED3DSURFACE_DESC desc;
2561 DDPIXELFORMAT ddfmt;
2562
2563 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2564 0,
2565 &tex);
2566
2567 if(hr == WINED3D_OK && tex)
2568 {
2569 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2570 if (SUCCEEDED(hr))
2571 {
2572 ddfmt.dwSize = sizeof(ddfmt);
2573 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2574 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2575 }
2576
2577 IWineD3DBaseTexture_Release(tex);
2578 }
2579
2580 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2581 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
2582 {
2583 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2584 }
2585
2586 *lpdwRenderState = D3DTBLEND_MODULATE;
2587 }
2588
2589 LeaveCriticalSection(&ddraw_cs);
2590
2591 return D3D_OK;
2592 }
2593
2594 default:
2595 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2596 }
2597 }
2598
2599 static HRESULT WINAPI
2600 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2601 D3DRENDERSTATETYPE dwRenderStateType,
2602 DWORD *lpdwRenderState)
2603 {
2604 IDirect3DDeviceImpl *This = device_from_device2(iface);
2605 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, dwRenderStateType, lpdwRenderState);
2606 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2607 dwRenderStateType, lpdwRenderState);
2608 }
2609
2610 /*****************************************************************************
2611 * IDirect3DDevice7::SetRenderState
2612 *
2613 * Sets a render state. The possible render states are defined in
2614 * include/d3dtypes.h
2615 *
2616 * Version 2, 3 and 7
2617 *
2618 * Params:
2619 * RenderStateType: State to set
2620 * Value: Value to assign to that state
2621 *
2622 * Returns:
2623 * D3D_OK on success,
2624 * for details see IWineD3DDevice::SetRenderState
2625 *
2626 *****************************************************************************/
2627 static HRESULT
2628 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2629 D3DRENDERSTATETYPE RenderStateType,
2630 DWORD Value)
2631 {
2632 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2633 HRESULT hr;
2634 TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
2635
2636 EnterCriticalSection(&ddraw_cs);
2637 /* Some render states need special care */
2638 switch(RenderStateType)
2639 {
2640 case D3DRENDERSTATE_TEXTUREMAG:
2641 {
2642 WINED3DTEXTUREFILTERTYPE tex_mag = WINED3DTEXF_POINT;
2643
2644 switch ((D3DTEXTUREFILTER) Value)
2645 {
2646 case D3DFILTER_NEAREST:
2647 case D3DFILTER_LINEARMIPNEAREST:
2648 tex_mag = WINED3DTEXF_POINT;
2649 break;
2650 case D3DFILTER_LINEAR:
2651 case D3DFILTER_LINEARMIPLINEAR:
2652 tex_mag = WINED3DTEXF_LINEAR;
2653 break;
2654 default:
2655 ERR("Unhandled texture mag %d !\n",Value);
2656 }
2657
2658 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2659 0, WINED3DSAMP_MAGFILTER,
2660 tex_mag);
2661 break;
2662 }
2663
2664 case D3DRENDERSTATE_TEXTUREMIN:
2665 {
2666 WINED3DTEXTUREFILTERTYPE tex_min = WINED3DTEXF_POINT;
2667 WINED3DTEXTUREFILTERTYPE tex_mip = WINED3DTEXF_NONE;
2668
2669 switch ((D3DTEXTUREFILTER) Value)
2670 {
2671 case D3DFILTER_NEAREST:
2672 tex_min = WINED3DTEXF_POINT;
2673 break;
2674 case D3DFILTER_LINEAR:
2675 tex_min = WINED3DTEXF_LINEAR;
2676 break;
2677 case D3DFILTER_MIPNEAREST:
2678 tex_min = WINED3DTEXF_POINT;
2679 tex_mip = WINED3DTEXF_POINT;
2680 break;
2681 case D3DFILTER_MIPLINEAR:
2682 tex_min = WINED3DTEXF_POINT;
2683 tex_mip = WINED3DTEXF_LINEAR;
2684 break;
2685 case D3DFILTER_LINEARMIPNEAREST:
2686 tex_min = WINED3DTEXF_POINT;
2687 tex_mip = WINED3DTEXF_LINEAR;
2688 break;
2689 case D3DFILTER_LINEARMIPLINEAR:
2690 tex_min = WINED3DTEXF_LINEAR;
2691 tex_mip = WINED3DTEXF_LINEAR;
2692 break;
2693
2694 default:
2695 ERR("Unhandled texture min %d !\n",Value);
2696 }
2697
2698 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2699 0, WINED3DSAMP_MIPFILTER,
2700 tex_mip);
2701 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2702 0, WINED3DSAMP_MINFILTER,
2703 tex_min);
2704 break;
2705 }
2706
2707 case D3DRENDERSTATE_TEXTUREADDRESS:
2708 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2709 0, WINED3DSAMP_ADDRESSV,
2710 Value);
2711 /* Drop through */
2712 case D3DRENDERSTATE_TEXTUREADDRESSU:
2713 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2714 0, WINED3DSAMP_ADDRESSU,
2715 Value);
2716 break;
2717 case D3DRENDERSTATE_TEXTUREADDRESSV:
2718 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2719 0, WINED3DSAMP_ADDRESSV,
2720 Value);
2721 break;
2722
2723 default:
2724
2725 /* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
2726
2727 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2728 RenderStateType,
2729 Value);
2730 break;
2731 }
2732 LeaveCriticalSection(&ddraw_cs);
2733 return hr;
2734 }
2735
2736 static HRESULT WINAPI
2737 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2738 D3DRENDERSTATETYPE RenderStateType,
2739 DWORD Value)
2740 {
2741 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2742 }
2743
2744 static HRESULT WINAPI
2745 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2746 D3DRENDERSTATETYPE RenderStateType,
2747 DWORD Value)
2748 {
2749 HRESULT hr;
2750 WORD old_fpucw;
2751
2752 old_fpucw = d3d_fpu_setup();
2753 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2754 set_fpu_control_word(old_fpucw);
2755
2756 return hr;
2757 }
2758
2759 static HRESULT WINAPI
2760 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2761 D3DRENDERSTATETYPE RenderStateType,
2762 DWORD Value)
2763 {
2764 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2765 for this state can be directly mapped to texture stage colorop and alphaop, but
2766 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2767 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2768 alphaarg when needed.
2769
2770 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2771
2772 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2773 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2774 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2775 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2776 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2777 in device - TRUE if the app is using TEXTUREMAPBLEND.
2778
2779 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2780 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2781 unless some broken game will be found that cares. */
2782
2783 HRESULT hr;
2784 IDirect3DDeviceImpl *This = device_from_device3(iface);
2785 TRACE("(%p)->(%08x,%d)\n", This, RenderStateType, Value);
2786
2787 EnterCriticalSection(&ddraw_cs);
2788
2789 switch(RenderStateType)
2790 {
2791 case D3DRENDERSTATE_TEXTUREHANDLE:
2792 {
2793 if(Value == 0)
2794 {
2795 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2796 0,
2797 NULL);
2798 break;
2799 }
2800
2801 if(Value > This->numHandles)
2802 {
2803 FIXME("Specified handle %d out of range\n", Value);
2804 hr = DDERR_INVALIDPARAMS;
2805 break;
2806 }
2807 if(This->Handles[Value - 1].type != DDrawHandle_Texture)
2808 {
2809 FIXME("Handle %d isn't a texture handle\n", Value);
2810 hr = DDERR_INVALIDPARAMS;
2811 break;
2812 }
2813 else
2814 {
2815 IDirectDrawSurfaceImpl *surf = This->Handles[Value - 1].ptr;
2816 IDirect3DTexture2 *tex = surf ? (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl : NULL;
2817 hr = IDirect3DDevice3_SetTexture(iface, 0, tex);
2818 break;
2819 }
2820 }
2821
2822 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2823 {
2824 This->legacyTextureBlending = TRUE;
2825
2826 switch ( (D3DTEXTUREBLEND) Value)
2827 {
2828 case D3DTBLEND_MODULATE:
2829 {
2830 BOOL tex_alpha = FALSE;
2831 IWineD3DBaseTexture *tex = NULL;
2832 WINED3DSURFACE_DESC desc;
2833 DDPIXELFORMAT ddfmt;
2834
2835 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2836 0,
2837 &tex);
2838
2839 if(hr == WINED3D_OK && tex)
2840 {
2841 memset(&desc, 0, sizeof(desc));
2842 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2843 if (SUCCEEDED(hr))
2844 {
2845 ddfmt.dwSize = sizeof(ddfmt);
2846 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2847 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2848 }
2849
2850 IWineD3DBaseTexture_Release(tex);
2851 }
2852
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2854 if (tex_alpha)
2855 {
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2857 }
2858 else
2859 {
2860 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
2861 }
2862
2863 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2864 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2865 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2866
2867 break;
2868 }
2869
2870 case D3DTBLEND_ADD:
2871 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2872 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2874 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2875 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2876 break;
2877
2878 case D3DTBLEND_MODULATEALPHA:
2879 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2880 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2881 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2882 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2883 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2884 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2885 break;
2886
2887 case D3DTBLEND_COPY:
2888 case D3DTBLEND_DECAL:
2889 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2890 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2891 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2892 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2893 break;
2894
2895 case D3DTBLEND_DECALALPHA:
2896 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2897 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2898 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2899 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2900 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2901 break;
2902
2903 default:
2904 ERR("Unhandled texture environment %d !\n",Value);
2905 }
2906
2907 hr = D3D_OK;
2908 break;
2909 }
2910
2911 default:
2912 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2913 break;
2914 }
2915
2916 LeaveCriticalSection(&ddraw_cs);
2917
2918 return hr;
2919 }
2920
2921 static HRESULT WINAPI
2922 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2923 D3DRENDERSTATETYPE RenderStateType,
2924 DWORD Value)
2925 {
2926 IDirect3DDeviceImpl *This = device_from_device2(iface);
2927 TRACE_(ddraw_thunk)("(%p)->(%08x,%d) thunking to IDirect3DDevice3 interface.\n", This, RenderStateType, Value);
2928 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2929 }
2930
2931 /*****************************************************************************
2932 * Direct3DDevice3::SetLightState
2933 *
2934 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2935 * light states are forwarded to Direct3DDevice7 render states
2936 *
2937 * Version 2 and 3
2938 *
2939 * Params:
2940 * LightStateType: The light state to change
2941 * Value: The value to assign to that light state
2942 *
2943 * Returns:
2944 * D3D_OK on success
2945 * DDERR_INVALIDPARAMS if the parameters were incorrect
2946 * Also check IDirect3DDevice7::SetRenderState
2947 *
2948 *****************************************************************************/
2949 static HRESULT WINAPI
2950 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2951 D3DLIGHTSTATETYPE LightStateType,
2952 DWORD Value)
2953 {
2954 IDirect3DDeviceImpl *This = device_from_device3(iface);
2955 HRESULT hr;
2956
2957 TRACE("(%p)->(%08x,%08x)\n", This, LightStateType, Value);
2958
2959 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2960 {
2961 TRACE("Unexpected Light State Type\n");
2962 return DDERR_INVALIDPARAMS;
2963 }
2964
2965 EnterCriticalSection(&ddraw_cs);
2966 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2967 {
2968 IDirect3DMaterialImpl *mat;
2969
2970 if(Value == 0) mat = NULL;
2971 else if(Value > This->numHandles)
2972 {
2973 ERR("Material handle out of range(%d)\n", Value);
2974 LeaveCriticalSection(&ddraw_cs);
2975 return DDERR_INVALIDPARAMS;
2976 }
2977 else if(This->Handles[Value - 1].type != DDrawHandle_Material)
2978 {
2979 ERR("Invalid handle %d\n", Value);
2980 LeaveCriticalSection(&ddraw_cs);
2981 return DDERR_INVALIDPARAMS;
2982 }
2983 else
2984 {
2985 mat = This->Handles[Value - 1].ptr;
2986 }
2987
2988 if (mat != NULL)
2989 {
2990 TRACE(" activating material %p.\n", mat);
2991 mat->activate(mat);
2992 }
2993 else
2994 {
2995 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
2996 }
2997 This->material = Value;
2998 }
2999 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3000 {
3001 switch (Value)
3002 {
3003 case D3DCOLOR_MONO:
3004 ERR("DDCOLOR_MONO should not happen!\n");
3005 break;
3006 case D3DCOLOR_RGB:
3007 /* We are already in this mode */
3008 TRACE("Setting color model to RGB (no-op).\n");
3009 break;
3010 default:
3011 ERR("Unknown color model!\n");
3012 LeaveCriticalSection(&ddraw_cs);
3013 return DDERR_INVALIDPARAMS;
3014 }
3015 }
3016 else
3017 {
3018 D3DRENDERSTATETYPE rs;
3019 switch (LightStateType)
3020 {
3021 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3022 rs = D3DRENDERSTATE_AMBIENT;
3023 break;
3024 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3025 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3026 break;
3027 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3028 rs = D3DRENDERSTATE_FOGSTART;
3029 break;
3030 case D3DLIGHTSTATE_FOGEND: /* 6 */
3031 rs = D3DRENDERSTATE_FOGEND;
3032 break;
3033 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3034 rs = D3DRENDERSTATE_FOGDENSITY;
3035 break;
3036 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3037 rs = D3DRENDERSTATE_COLORVERTEX;
3038 break;
3039 default:
3040 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3041 LeaveCriticalSection(&ddraw_cs);
3042 return DDERR_INVALIDPARAMS;
3043 }
3044
3045 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3046 LeaveCriticalSection(&ddraw_cs);
3047 return hr;
3048 }
3049
3050 LeaveCriticalSection(&ddraw_cs);
3051 return D3D_OK;
3052 }
3053
3054 static HRESULT WINAPI
3055 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3056 D3DLIGHTSTATETYPE LightStateType,
3057 DWORD Value)
3058 {
3059 IDirect3DDeviceImpl *This = device_from_device2(iface);
3060 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3061 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3062 }
3063
3064 /*****************************************************************************
3065 * IDirect3DDevice3::GetLightState
3066 *
3067 * Returns the current setting of a light state. The state is read from
3068 * the Direct3DDevice7 render state.
3069 *
3070 * Version 2 and 3
3071 *
3072 * Params:
3073 * LightStateType: The light state to return
3074 * Value: The address to store the light state setting at
3075 *
3076 * Returns:
3077 * D3D_OK on success
3078 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3079 * Also see IDirect3DDevice7::GetRenderState
3080 *
3081 *****************************************************************************/
3082 static HRESULT WINAPI
3083 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3084 D3DLIGHTSTATETYPE LightStateType,
3085 DWORD *Value)
3086 {
3087 IDirect3DDeviceImpl *This = device_from_device3(iface);
3088 HRESULT hr;
3089
3090 TRACE("(%p)->(%08x,%p)\n", This, LightStateType, Value);
3091
3092 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3093 {
3094 TRACE("Unexpected Light State Type\n");
3095 return DDERR_INVALIDPARAMS;
3096 }
3097
3098 if(!Value)
3099 return DDERR_INVALIDPARAMS;
3100
3101 EnterCriticalSection(&ddraw_cs);
3102 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3103 {
3104 *Value = This->material;
3105 }
3106 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3107 {
3108 *Value = D3DCOLOR_RGB;
3109 }
3110 else
3111 {
3112 D3DRENDERSTATETYPE rs;
3113 switch (LightStateType)
3114 {
3115 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3116 rs = D3DRENDERSTATE_AMBIENT;
3117 break;
3118 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3119 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3120 break;
3121 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3122 rs = D3DRENDERSTATE_FOGSTART;
3123 break;
3124 case D3DLIGHTSTATE_FOGEND: /* 6 */
3125 rs = D3DRENDERSTATE_FOGEND;
3126 break;
3127 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3128 rs = D3DRENDERSTATE_FOGDENSITY;
3129 break;
3130 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3131 rs = D3DRENDERSTATE_COLORVERTEX;
3132 break;
3133 default:
3134 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3135 LeaveCriticalSection(&ddraw_cs);
3136 return DDERR_INVALIDPARAMS;
3137 }
3138
3139 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3140 LeaveCriticalSection(&ddraw_cs);
3141 return hr;
3142 }
3143
3144 LeaveCriticalSection(&ddraw_cs);
3145 return D3D_OK;
3146 }
3147
3148 static HRESULT WINAPI
3149 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3150 D3DLIGHTSTATETYPE LightStateType,
3151 DWORD *Value)
3152 {
3153 IDirect3DDeviceImpl *This = device_from_device2(iface);
3154 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice3 interface.\n", This, LightStateType, Value);
3155 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3156 }
3157
3158 /*****************************************************************************
3159 * IDirect3DDevice7::SetTransform
3160 *
3161 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3162 * in include/d3dtypes.h.
3163 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3164 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3165 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3166 *
3167 * Version 2, 3 and 7
3168 *
3169 * Params:
3170 * TransformStateType: transform state to set
3171 * Matrix: Matrix to assign to the state
3172 *
3173 * Returns:
3174 * D3D_OK on success
3175 * DDERR_INVALIDPARAMS if Matrix == NULL
3176 * For details see IWineD3DDevice::SetTransform
3177 *
3178 *****************************************************************************/
3179 static HRESULT
3180 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3181 D3DTRANSFORMSTATETYPE TransformStateType,
3182 D3DMATRIX *Matrix)
3183 {
3184 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3185 D3DTRANSFORMSTATETYPE type;
3186 HRESULT hr;
3187 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3188
3189 switch(TransformStateType)
3190 {
3191 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3192 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3193 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3194 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3195 default: type = TransformStateType;
3196 }
3197
3198 if(!Matrix)
3199 return DDERR_INVALIDPARAMS;
3200
3201 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3202 EnterCriticalSection(&ddraw_cs);
3203 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3204 type,
3205 (WINED3DMATRIX*) Matrix);
3206 LeaveCriticalSection(&ddraw_cs);
3207 return hr;
3208 }
3209
3210 static HRESULT WINAPI
3211 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3212 D3DTRANSFORMSTATETYPE TransformStateType,
3213 D3DMATRIX *Matrix)
3214 {
3215 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3216 }
3217
3218 static HRESULT WINAPI
3219 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3220 D3DTRANSFORMSTATETYPE TransformStateType,
3221 D3DMATRIX *Matrix)
3222 {
3223 HRESULT hr;
3224 WORD old_fpucw;
3225
3226 old_fpucw = d3d_fpu_setup();
3227 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3228 set_fpu_control_word(old_fpucw);
3229
3230 return hr;
3231 }
3232
3233 static HRESULT WINAPI
3234 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3235 D3DTRANSFORMSTATETYPE TransformStateType,
3236 D3DMATRIX *D3DMatrix)
3237 {
3238 IDirect3DDeviceImpl *This = device_from_device3(iface);
3239 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3240 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3241 }
3242
3243 static HRESULT WINAPI
3244 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3245 D3DTRANSFORMSTATETYPE TransformStateType,
3246 D3DMATRIX *D3DMatrix)
3247 {
3248 IDirect3DDeviceImpl *This = device_from_device2(iface);
3249 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3250 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3251 }
3252
3253 /*****************************************************************************
3254 * IDirect3DDevice7::GetTransform
3255 *
3256 * Returns the matrix assigned to a transform state
3257 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3258 * SetTransform
3259 *
3260 * Params:
3261 * TransformStateType: State to read the matrix from
3262 * Matrix: Address to store the matrix at
3263 *
3264 * Returns:
3265 * D3D_OK on success
3266 * DDERR_INVALIDPARAMS if Matrix == NULL
3267 * For details, see IWineD3DDevice::GetTransform
3268 *
3269 *****************************************************************************/
3270 static HRESULT
3271 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3272 D3DTRANSFORMSTATETYPE TransformStateType,
3273 D3DMATRIX *Matrix)
3274 {
3275 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3276 D3DTRANSFORMSTATETYPE type;
3277 HRESULT hr;
3278 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, Matrix);
3279
3280 switch(TransformStateType)
3281 {
3282 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3283 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3284 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3285 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3286 default: type = TransformStateType;
3287 }
3288
3289 if(!Matrix)
3290 return DDERR_INVALIDPARAMS;
3291
3292 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3293 EnterCriticalSection(&ddraw_cs);
3294 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3295 LeaveCriticalSection(&ddraw_cs);
3296 return hr;
3297 }
3298
3299 static HRESULT WINAPI
3300 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType,
3302 D3DMATRIX *Matrix)
3303 {
3304 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3305 }
3306
3307 static HRESULT WINAPI
3308 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3309 D3DTRANSFORMSTATETYPE TransformStateType,
3310 D3DMATRIX *Matrix)
3311 {
3312 HRESULT hr;
3313 WORD old_fpucw;
3314
3315 old_fpucw = d3d_fpu_setup();
3316 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3317 set_fpu_control_word(old_fpucw);
3318
3319 return hr;
3320 }
3321
3322 static HRESULT WINAPI
3323 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3324 D3DTRANSFORMSTATETYPE TransformStateType,
3325 D3DMATRIX *D3DMatrix)
3326 {
3327 IDirect3DDeviceImpl *This = device_from_device3(iface);
3328 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3329 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3330 }
3331
3332 static HRESULT WINAPI
3333 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3334 D3DTRANSFORMSTATETYPE TransformStateType,
3335 D3DMATRIX *D3DMatrix)
3336 {
3337 IDirect3DDeviceImpl *This = device_from_device2(iface);
3338 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3339 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3340 }
3341
3342 /*****************************************************************************
3343 * IDirect3DDevice7::MultiplyTransform
3344 *
3345 * Multiplies the already-set transform matrix of a transform state
3346 * with another matrix. For the world matrix, see SetTransform
3347 *
3348 * Version 2, 3 and 7
3349 *
3350 * Params:
3351 * TransformStateType: Transform state to multiply
3352 * D3DMatrix Matrix to multiply with.
3353 *
3354 * Returns
3355 * D3D_OK on success
3356 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3357 * For details, see IWineD3DDevice::MultiplyTransform
3358 *
3359 *****************************************************************************/
3360 static HRESULT
3361 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3362 D3DTRANSFORMSTATETYPE TransformStateType,
3363 D3DMATRIX *D3DMatrix)
3364 {
3365 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3366 HRESULT hr;
3367 D3DTRANSFORMSTATETYPE type;
3368 TRACE("(%p)->(%08x,%p): Relay\n", This, TransformStateType, D3DMatrix);
3369
3370 switch(TransformStateType)
3371 {
3372 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3373 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3374 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3375 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3376 default: type = TransformStateType;
3377 }
3378
3379 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3380 EnterCriticalSection(&ddraw_cs);
3381 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3382 type,
3383 (WINED3DMATRIX*) D3DMatrix);
3384 LeaveCriticalSection(&ddraw_cs);
3385 return hr;
3386 }
3387
3388 static HRESULT WINAPI
3389 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3390 D3DTRANSFORMSTATETYPE TransformStateType,
3391 D3DMATRIX *D3DMatrix)
3392 {
3393 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3394 }
3395
3396 static HRESULT WINAPI
3397 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3398 D3DTRANSFORMSTATETYPE TransformStateType,
3399 D3DMATRIX *D3DMatrix)
3400 {
3401 HRESULT hr;
3402 WORD old_fpucw;
3403
3404 old_fpucw = d3d_fpu_setup();
3405 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3406 set_fpu_control_word(old_fpucw);
3407
3408 return hr;
3409 }
3410
3411 static HRESULT WINAPI
3412 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3413 D3DTRANSFORMSTATETYPE TransformStateType,
3414 D3DMATRIX *D3DMatrix)
3415 {
3416 IDirect3DDeviceImpl *This = device_from_device3(iface);
3417 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3418 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3419 }
3420
3421 static HRESULT WINAPI
3422 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3423 D3DTRANSFORMSTATETYPE TransformStateType,
3424 D3DMATRIX *D3DMatrix)
3425 {
3426 IDirect3DDeviceImpl *This = device_from_device2(iface);
3427 TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, TransformStateType, D3DMatrix);
3428 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3429 }
3430
3431 /*****************************************************************************
3432 * IDirect3DDevice7::DrawPrimitive
3433 *
3434 * Draws primitives based on vertices in an application-provided pointer
3435 *
3436 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3437 * an FVF format for D3D7
3438 *
3439 * Params:
3440 * PrimitiveType: The type of the primitives to draw
3441 * Vertex type: Flexible vertex format vertex description
3442 * Vertices: Pointer to the vertex array
3443 * VertexCount: The number of vertices to draw
3444 * Flags: As usual a few flags
3445 *
3446 * Returns:
3447 * D3D_OK on success
3448 * DDERR_INVALIDPARAMS if Vertices is NULL
3449 * For details, see IWineD3DDevice::DrawPrimitiveUP
3450 *
3451 *****************************************************************************/
3452 static HRESULT
3453 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3454 D3DPRIMITIVETYPE PrimitiveType,
3455 DWORD VertexType,
3456 void *Vertices,
3457 DWORD VertexCount,
3458 DWORD Flags)
3459 {
3460 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3461 UINT stride;
3462 HRESULT hr;
3463 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3464
3465 if(!Vertices)
3466 return DDERR_INVALIDPARAMS;
3467
3468 /* Get the stride */
3469 stride = get_flexible_vertex_size(VertexType);
3470
3471 /* Set the FVF */
3472 EnterCriticalSection(&ddraw_cs);
3473 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3474 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3475 if(hr != D3D_OK)
3476 {
3477 LeaveCriticalSection(&ddraw_cs);
3478 return hr;
3479 }
3480
3481 /* This method translates to the user pointer draw of WineD3D */
3482 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3483 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3484 LeaveCriticalSection(&ddraw_cs);
3485 return hr;
3486 }
3487
3488 static HRESULT WINAPI
3489 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3490 D3DPRIMITIVETYPE PrimitiveType,
3491 DWORD VertexType,
3492 void *Vertices,
3493 DWORD VertexCount,
3494 DWORD Flags)
3495 {
3496 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3497 }
3498
3499 static HRESULT WINAPI
3500 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3501 D3DPRIMITIVETYPE PrimitiveType,
3502 DWORD VertexType,
3503 void *Vertices,
3504 DWORD VertexCount,
3505 DWORD Flags)
3506 {
3507 HRESULT hr;
3508 WORD old_fpucw;
3509
3510 old_fpucw = d3d_fpu_setup();
3511 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3512 set_fpu_control_word(old_fpucw);
3513
3514 return hr;
3515 }
3516
3517 static HRESULT WINAPI
3518 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3519 D3DPRIMITIVETYPE PrimitiveType,
3520 DWORD VertexType,
3521 void *Vertices,
3522 DWORD VertexCount,
3523 DWORD Flags)
3524 {
3525 IDirect3DDeviceImpl *This = device_from_device3(iface);
3526 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3527 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3528 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3529 }
3530
3531 static HRESULT WINAPI
3532 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3533 D3DPRIMITIVETYPE PrimitiveType,
3534 D3DVERTEXTYPE VertexType,
3535 void *Vertices,
3536 DWORD VertexCount,
3537 DWORD Flags)
3538 {
3539 IDirect3DDeviceImpl *This = device_from_device2(iface);
3540 DWORD FVF;
3541 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3542
3543 switch(VertexType)
3544 {
3545 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3546 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3547 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3548 default:
3549 ERR("Unexpected vertex type %d\n", VertexType);
3550 return DDERR_INVALIDPARAMS; /* Should never happen */
3551 }
3552
3553 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, PrimitiveType, FVF, Vertices, VertexCount, Flags);
3554 }
3555
3556 /*****************************************************************************
3557 * IDirect3DDevice7::DrawIndexedPrimitive
3558 *
3559 * Draws vertices from an application-provided pointer, based on the index
3560 * numbers in a WORD array.
3561 *
3562 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3563 * an FVF format for D3D7
3564 *
3565 * Params:
3566 * PrimitiveType: The primitive type to draw
3567 * VertexType: The FVF vertex description
3568 * Vertices: Pointer to the vertex array
3569 * VertexCount: ?
3570 * Indices: Pointer to the index array
3571 * IndexCount: Number of indices = Number of vertices to draw
3572 * Flags: As usual, some flags
3573 *
3574 * Returns:
3575 * D3D_OK on success
3576 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3577 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3578 *
3579 *****************************************************************************/
3580 static HRESULT
3581 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3582 D3DPRIMITIVETYPE PrimitiveType,
3583 DWORD VertexType,
3584 void *Vertices,
3585 DWORD VertexCount,
3586 WORD *Indices,
3587 DWORD IndexCount,
3588 DWORD Flags)
3589 {
3590 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3591 HRESULT hr;
3592 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x): Relay!\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3593
3594 /* Set the D3DDevice's FVF */
3595 EnterCriticalSection(&ddraw_cs);
3596 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
3597 IDirectDrawImpl_FindDecl(This->ddraw, VertexType));
3598 if(FAILED(hr))
3599 {
3600 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3601 LeaveCriticalSection(&ddraw_cs);
3602 return hr;
3603 }
3604
3605 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3606 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, 0 /* MinVertexIndex */,
3607 VertexCount /* UINT NumVertexIndex */, IndexCount, Indices, WINED3DFMT_R16_UINT,
3608 Vertices, get_flexible_vertex_size(VertexType));
3609 LeaveCriticalSection(&ddraw_cs);
3610 return hr;
3611 }
3612
3613 static HRESULT WINAPI
3614 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3615 D3DPRIMITIVETYPE PrimitiveType,
3616 DWORD VertexType,
3617 void *Vertices,
3618 DWORD VertexCount,
3619 WORD *Indices,
3620 DWORD IndexCount,
3621 DWORD Flags)
3622 {
3623 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3624 }
3625
3626 static HRESULT WINAPI
3627 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3628 D3DPRIMITIVETYPE PrimitiveType,
3629 DWORD VertexType,
3630 void *Vertices,
3631 DWORD VertexCount,
3632 WORD *Indices,
3633 DWORD IndexCount,
3634 DWORD Flags)
3635 {
3636 HRESULT hr;
3637 WORD old_fpucw;
3638
3639 old_fpucw = d3d_fpu_setup();
3640 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3641 set_fpu_control_word(old_fpucw);
3642
3643 return hr;
3644 }
3645
3646 static HRESULT WINAPI
3647 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3648 D3DPRIMITIVETYPE PrimitiveType,
3649 DWORD VertexType,
3650 void *Vertices,
3651 DWORD VertexCount,
3652 WORD *Indices,
3653 DWORD IndexCount,
3654 DWORD Flags)
3655 {
3656 IDirect3DDeviceImpl *This = device_from_device3(iface);
3657 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3658 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3659 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3660 }
3661
3662 static HRESULT WINAPI
3663 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3664 D3DPRIMITIVETYPE PrimitiveType,
3665 D3DVERTEXTYPE VertexType,
3666 void *Vertices,
3667 DWORD VertexCount,
3668 WORD *Indices,
3669 DWORD IndexCount,
3670 DWORD Flags)
3671 {
3672 DWORD FVF;
3673 IDirect3DDeviceImpl *This = device_from_device2(iface);
3674 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3675
3676 switch(VertexType)
3677 {
3678 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3679 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3680 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3681 default:
3682 ERR("Unexpected vertex type %d\n", VertexType);
3683 return DDERR_INVALIDPARAMS; /* Should never happen */
3684 }
3685
3686 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3687 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3688 }
3689
3690 /*****************************************************************************
3691 * IDirect3DDevice7::SetClipStatus
3692 *
3693 * Sets the clip status. This defines things as clipping conditions and
3694 * the extents of the clipping region.
3695 *
3696 * Version 2, 3 and 7
3697 *
3698 * Params:
3699 * ClipStatus:
3700 *
3701 * Returns:
3702 * D3D_OK because it's a stub
3703 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3704 *
3705 *****************************************************************************/
3706 static HRESULT WINAPI
3707 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3708 D3DCLIPSTATUS *ClipStatus)
3709 {
3710 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3711 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3712
3713 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3714 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3715 */
3716 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3717 return D3D_OK;
3718 }
3719
3720 static HRESULT WINAPI
3721 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3722 D3DCLIPSTATUS *ClipStatus)
3723 {
3724 IDirect3DDeviceImpl *This = device_from_device3(iface);
3725 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3726 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3727 }
3728
3729 static HRESULT WINAPI
3730 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3731 D3DCLIPSTATUS *ClipStatus)
3732 {
3733 IDirect3DDeviceImpl *This = device_from_device2(iface);
3734 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3735 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3736 }
3737
3738 /*****************************************************************************
3739 * IDirect3DDevice7::GetClipStatus
3740 *
3741 * Returns the clip status
3742 *
3743 * Params:
3744 * ClipStatus: Address to write the clip status to
3745 *
3746 * Returns:
3747 * D3D_OK because it's a stub
3748 *
3749 *****************************************************************************/
3750 static HRESULT WINAPI
3751 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3752 D3DCLIPSTATUS *ClipStatus)
3753 {
3754 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3755 FIXME("(%p)->(%p): Stub!\n", This, ClipStatus);
3756
3757 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3758 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3759 return D3D_OK;
3760 }
3761
3762 static HRESULT WINAPI
3763 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3764 D3DCLIPSTATUS *ClipStatus)
3765 {
3766 IDirect3DDeviceImpl *This = device_from_device3(iface);
3767 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3768 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3769 }
3770
3771 static HRESULT WINAPI
3772 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3773 D3DCLIPSTATUS *ClipStatus)
3774 {
3775 IDirect3DDeviceImpl *This = device_from_device2(iface);
3776 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, ClipStatus);
3777 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3778 }
3779
3780 /*****************************************************************************
3781 * IDirect3DDevice::DrawPrimitiveStrided
3782 *
3783 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3784 *
3785 * Version 3 and 7
3786 *
3787 * Params:
3788 * PrimitiveType: The primitive type to draw
3789 * VertexType: The FVF description of the vertices to draw (for the stride??)
3790 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3791 * the vertex data locations
3792 * VertexCount: The number of vertices to draw
3793 * Flags: Some flags
3794 *
3795 * Returns:
3796 * D3D_OK, because it's a stub
3797 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3798 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3799 *
3800 *****************************************************************************/
3801 static HRESULT
3802 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3803 D3DPRIMITIVETYPE PrimitiveType,
3804 DWORD VertexType,
3805 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3806 DWORD VertexCount,
3807 DWORD Flags)
3808 {
3809 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3810 WineDirect3DVertexStridedData WineD3DStrided;
3811 DWORD i;
3812 HRESULT hr;
3813
3814 TRACE("(%p)->(%08x,%08x,%p,%08x,%08x): stub!\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3815
3816 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3817 /* Get the strided data right. the wined3d structure is a bit bigger
3818 * Watch out: The contents of the strided data are determined by the fvf,
3819 * not by the members set in D3DDrawPrimStrideData. So it's valid
3820 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3821 * not set in the fvf.
3822 */
3823 if(VertexType & D3DFVF_POSITION_MASK)
3824 {
3825 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3826 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3827 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3828 if (VertexType & D3DFVF_XYZRHW)
3829 {
3830 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3831 WineD3DStrided.position_transformed = TRUE;
3832 } else
3833 WineD3DStrided.position_transformed = FALSE;
3834 }
3835
3836 if(VertexType & D3DFVF_NORMAL)
3837 {
3838 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3839 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3840 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3841 }
3842
3843 if(VertexType & D3DFVF_DIFFUSE)
3844 {
3845 WineD3DStrided.diffuse.format = WINED3DFMT_A8R8G8B8;
3846 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3847 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3848 }
3849
3850 if(VertexType & D3DFVF_SPECULAR)
3851 {
3852 WineD3DStrided.specular.format = WINED3DFMT_A8R8G8B8;
3853 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3854 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3855 }
3856
3857 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3858 {
3859 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3860 {
3861 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3862 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3863 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3864 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3865 default: ERR("Unexpected texture coordinate size %d\n",
3866 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3867 }
3868 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3869 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3870 }
3871
3872 /* WineD3D doesn't need the FVF here */
3873 EnterCriticalSection(&ddraw_cs);
3874 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3875 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3876 LeaveCriticalSection(&ddraw_cs);
3877 return hr;
3878 }
3879
3880 static HRESULT WINAPI
3881 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3882 D3DPRIMITIVETYPE PrimitiveType,
3883 DWORD VertexType,
3884 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3885 DWORD VertexCount,
3886 DWORD Flags)
3887 {
3888 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3889 }
3890
3891 static HRESULT WINAPI
3892 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3893 D3DPRIMITIVETYPE PrimitiveType,
3894 DWORD VertexType,
3895 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3896 DWORD VertexCount,
3897 DWORD Flags)
3898 {
3899 HRESULT hr;
3900 WORD old_fpucw;
3901
3902 old_fpucw = d3d_fpu_setup();
3903 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3904 set_fpu_control_word(old_fpucw);
3905
3906 return hr;
3907 }
3908
3909 static HRESULT WINAPI
3910 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3911 D3DPRIMITIVETYPE PrimitiveType,
3912 DWORD VertexType,
3913 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3914 DWORD VertexCount,
3915 DWORD Flags)
3916 {
3917 IDirect3DDeviceImpl *This = device_from_device3(iface);
3918 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3919 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)This,
3920 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3921 }
3922
3923 /*****************************************************************************
3924 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3925 *
3926 * Draws primitives specified by strided data locations based on indices
3927 *
3928 * Version 3 and 7
3929 *
3930 * Params:
3931 * PrimitiveType:
3932 *
3933 * Returns:
3934 * D3D_OK, because it's a stub
3935 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3936 * (DDERR_INVALIDPARAMS if Indices is NULL)
3937 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3938 *
3939 *****************************************************************************/
3940 static HRESULT
3941 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3942 D3DPRIMITIVETYPE PrimitiveType,
3943 DWORD VertexType,
3944 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3945 DWORD VertexCount,
3946 WORD *Indices,
3947 DWORD IndexCount,
3948 DWORD Flags)
3949 {
3950 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3951 WineDirect3DVertexStridedData WineD3DStrided;
3952 DWORD i;
3953 HRESULT hr;
3954
3955 TRACE("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x)\n", This, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3956
3957 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3958 /* Get the strided data right. the wined3d structure is a bit bigger
3959 * Watch out: The contents of the strided data are determined by the fvf,
3960 * not by the members set in D3DDrawPrimStrideData. So it's valid
3961 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3962 * not set in the fvf.
3963 */
3964 if(VertexType & D3DFVF_POSITION_MASK)
3965 {
3966 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3967 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3968 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3969 if (VertexType & D3DFVF_XYZRHW)
3970 {
3971 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3972 WineD3DStrided.position_transformed = TRUE;
3973 } else
3974 WineD3DStrided.position_transformed = FALSE;
3975 }
3976
3977 if(VertexType & D3DFVF_NORMAL)
3978 {
3979 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3980 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3981 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3982 }
3983
3984 if(VertexType & D3DFVF_DIFFUSE)
3985 {
3986 WineD3DStrided.diffuse.format = WINED3DFMT_A8R8G8B8;
3987 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3988 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3989 }
3990
3991 if(VertexType & D3DFVF_SPECULAR)
3992 {
3993 WineD3DStrided.specular.format = WINED3DFMT_A8R8G8B8;
3994 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3995 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3996 }
3997
3998 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3999 {
4000 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4001 {
4002 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4003 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4004 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4005 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4006 default: ERR("Unexpected texture coordinate size %d\n",
4007 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4008 }
4009 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4010 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4011 }
4012
4013 /* WineD3D doesn't need the FVF here */
4014 EnterCriticalSection(&ddraw_cs);
4015 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4016 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4017 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4018 LeaveCriticalSection(&ddraw_cs);
4019 return hr;
4020 }
4021
4022 static HRESULT WINAPI
4023 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4024 D3DPRIMITIVETYPE PrimitiveType,
4025 DWORD VertexType,
4026 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4027 DWORD VertexCount,
4028 WORD *Indices,
4029 DWORD IndexCount,
4030 DWORD Flags)
4031 {
4032 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4033 }
4034
4035 static HRESULT WINAPI
4036 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4037 D3DPRIMITIVETYPE PrimitiveType,
4038 DWORD VertexType,
4039 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4040 DWORD VertexCount,
4041 WORD *Indices,
4042 DWORD IndexCount,
4043 DWORD Flags)
4044 {
4045 HRESULT hr;
4046 WORD old_fpucw;
4047
4048 old_fpucw = d3d_fpu_setup();
4049 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4050 set_fpu_control_word(old_fpucw);
4051
4052 return hr;
4053 }
4054
4055 static HRESULT WINAPI
4056 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4057 D3DPRIMITIVETYPE PrimitiveType,
4058 DWORD VertexType,
4059 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4060 DWORD VertexCount,
4061 WORD *Indices,
4062 DWORD IndexCount,
4063 DWORD Flags)
4064 {
4065 IDirect3DDeviceImpl *This = device_from_device3(iface);
4066 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4067 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)This, PrimitiveType,
4068 VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4069 }
4070
4071 /*****************************************************************************
4072 * IDirect3DDevice7::DrawPrimitiveVB
4073 *
4074 * Draws primitives from a vertex buffer to the screen.
4075 *
4076 * Version 3 and 7
4077 *
4078 * Params:
4079 * PrimitiveType: Type of primitive to be rendered.
4080 * D3DVertexBuf: Source Vertex Buffer
4081 * StartVertex: Index of the first vertex from the buffer to be rendered
4082 * NumVertices: Number of vertices to be rendered
4083 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4084 *
4085 * Return values
4086 * D3D_OK on success
4087 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4088 *
4089 *****************************************************************************/
4090 static HRESULT
4091 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4092 D3DPRIMITIVETYPE PrimitiveType,
4093 IDirect3DVertexBuffer7 *D3DVertexBuf,
4094 DWORD StartVertex,
4095 DWORD NumVertices,
4096 DWORD Flags)
4097 {
4098 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4099 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4100 HRESULT hr;
4101 DWORD stride;
4102
4103 TRACE("(%p)->(%08x,%p,%08x,%08x,%08x)\n", This, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4104
4105 /* Sanity checks */
4106 if(!vb)
4107 {
4108 ERR("(%p) No Vertex buffer specified\n", This);
4109 return DDERR_INVALIDPARAMS;
4110 }
4111 stride = get_flexible_vertex_size(vb->fvf);
4112
4113 EnterCriticalSection(&ddraw_cs);
4114 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4115 vb->wineD3DVertexDeclaration);
4116 if(FAILED(hr))
4117 {
4118 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4119 LeaveCriticalSection(&ddraw_cs);
4120 return hr;
4121 }
4122
4123 /* Set the vertex stream source */
4124 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4125 0 /* StreamNumber */,
4126 vb->wineD3DVertexBuffer,
4127 0 /* StartVertex - we pass this to DrawPrimitive */,
4128 stride);
4129 if(hr != D3D_OK)
4130 {
4131 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4132 LeaveCriticalSection(&ddraw_cs);
4133 return hr;
4134 }
4135
4136 /* Now draw the primitives */
4137 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4138 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4139 LeaveCriticalSection(&ddraw_cs);
4140 return hr;
4141 }
4142
4143 static HRESULT WINAPI
4144 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4145 D3DPRIMITIVETYPE PrimitiveType,
4146 IDirect3DVertexBuffer7 *D3DVertexBuf,
4147 DWORD StartVertex,
4148 DWORD NumVertices,
4149 DWORD Flags)
4150 {
4151 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4152 }
4153
4154 static HRESULT WINAPI
4155 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4156 D3DPRIMITIVETYPE PrimitiveType,
4157 IDirect3DVertexBuffer7 *D3DVertexBuf,
4158 DWORD StartVertex,
4159 DWORD NumVertices,
4160 DWORD Flags)
4161 {
4162 HRESULT hr;
4163 WORD old_fpucw;
4164
4165 old_fpucw = d3d_fpu_setup();
4166 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4167 set_fpu_control_word(old_fpucw);
4168
4169 return hr;
4170 }
4171
4172 static HRESULT WINAPI
4173 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4174 D3DPRIMITIVETYPE PrimitiveType,
4175 IDirect3DVertexBuffer *D3DVertexBuf,
4176 DWORD StartVertex,
4177 DWORD NumVertices,
4178 DWORD Flags)
4179 {
4180 IDirect3DDeviceImpl *This = device_from_device3(iface);
4181 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4182 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, vb, StartVertex, NumVertices, Flags);
4183 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)This, PrimitiveType,
4184 (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4185 }
4186
4187
4188 /*****************************************************************************
4189 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4190 *
4191 * Draws primitives from a vertex buffer to the screen
4192 *
4193 * Params:
4194 * PrimitiveType: Type of primitive to be rendered.
4195 * D3DVertexBuf: Source Vertex Buffer
4196 * StartVertex: Index of the first vertex from the buffer to be rendered
4197 * NumVertices: Number of vertices to be rendered
4198 * Indices: Array of DWORDs used to index into the Vertices
4199 * IndexCount: Number of indices in Indices
4200 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4201 *
4202 * Return values
4203 *
4204 *****************************************************************************/
4205 static HRESULT
4206 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4207 D3DPRIMITIVETYPE PrimitiveType,
4208 IDirect3DVertexBuffer7 *D3DVertexBuf,
4209 DWORD StartVertex,
4210 DWORD NumVertices,
4211 WORD *Indices,
4212 DWORD IndexCount,
4213 DWORD Flags)
4214 {
4215 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4216 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4217 DWORD stride = get_flexible_vertex_size(vb->fvf);
4218 WORD *LockedIndices;
4219 HRESULT hr;
4220
4221 TRACE("(%p)->(%08x,%p,%d,%d,%p,%d,%08x)\n", This, PrimitiveType, vb, StartVertex, NumVertices, Indices, IndexCount, Flags);
4222
4223 /* Steps:
4224 * 1) Upload the Indices to the index buffer
4225 * 2) Set the index source
4226 * 3) Set the Vertex Buffer as the Stream source
4227 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4228 */
4229
4230 EnterCriticalSection(&ddraw_cs);
4231
4232 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4233 vb->wineD3DVertexDeclaration);
4234 if(FAILED(hr))
4235 {
4236 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4237 LeaveCriticalSection(&ddraw_cs);
4238 return hr;
4239 }
4240
4241 /* copy the index stream into the index buffer.
4242 * A new IWineD3DDevice method could be created
4243 * which takes an user pointer containing the indices
4244 * or a SetData-Method for the index buffer, which
4245 * overrides the index buffer data with our pointer.
4246 */
4247 hr = IWineD3DBuffer_Map(This->indexbuffer,
4248 0 /* OffSetToLock */,
4249 IndexCount * sizeof(WORD),
4250 (BYTE **) &LockedIndices,
4251 0 /* Flags */);
4252 assert(IndexCount < 0x100000);
4253 if(hr != D3D_OK)
4254 {
4255 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4256 LeaveCriticalSection(&ddraw_cs);
4257 return hr;
4258 }
4259 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4260 hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4261 if(hr != D3D_OK)
4262 {
4263 ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4264 LeaveCriticalSection(&ddraw_cs);
4265 return hr;
4266 }
4267
4268 /* Set the index stream */
4269 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4270 hr = IWineD3DDevice_SetIndices(This->wineD3DDevice, This->indexbuffer,
4271 WINED3DFMT_R16_UINT);
4272
4273 /* Set the vertex stream source */
4274 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4275 0 /* StreamNumber */,
4276 vb->wineD3DVertexBuffer,
4277 0 /* offset, we pass this to DrawIndexedPrimitive */,
4278 stride);
4279 if(hr != D3D_OK)
4280 {
4281 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4282 LeaveCriticalSection(&ddraw_cs);
4283 return hr;
4284 }
4285
4286
4287 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4288 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice,
4289 0 /* minIndex */, NumVertices, 0 /* StartIndex */, IndexCount);
4290
4291 LeaveCriticalSection(&ddraw_cs);
4292 return hr;
4293 }
4294
4295 static HRESULT WINAPI
4296 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4297 D3DPRIMITIVETYPE PrimitiveType,
4298 IDirect3DVertexBuffer7 *D3DVertexBuf,
4299 DWORD StartVertex,
4300 DWORD NumVertices,
4301 WORD *Indices,
4302 DWORD IndexCount,
4303 DWORD Flags)
4304 {
4305 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4306 }
4307
4308 static HRESULT WINAPI
4309 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4310 D3DPRIMITIVETYPE PrimitiveType,
4311 IDirect3DVertexBuffer7 *D3DVertexBuf,
4312 DWORD StartVertex,
4313 DWORD NumVertices,
4314 WORD *Indices,
4315 DWORD IndexCount,
4316 DWORD Flags)
4317 {
4318 HRESULT hr;
4319 WORD old_fpucw;
4320
4321 old_fpucw = d3d_fpu_setup();
4322 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4323 set_fpu_control_word(old_fpucw);
4324
4325 return hr;
4326 }
4327
4328 static HRESULT WINAPI
4329 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4330 D3DPRIMITIVETYPE PrimitiveType,
4331 IDirect3DVertexBuffer *D3DVertexBuf,
4332 WORD *Indices,
4333 DWORD IndexCount,
4334 DWORD Flags)
4335 {
4336 IDirect3DDeviceImpl *This = device_from_device3(iface);
4337 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4338 TRACE_(ddraw_thunk)("(%p)->(%08x,%p,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, PrimitiveType, VB, Indices, IndexCount, Flags);
4339
4340 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)This, PrimitiveType,
4341 (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4342 }
4343
4344 /*****************************************************************************
4345 * IDirect3DDevice7::ComputeSphereVisibility
4346 *
4347 * Calculates the visibility of spheres in the current viewport. The spheres
4348 * are passed in the Centers and Radii arrays, the results are passed back
4349 * in the ReturnValues array. Return values are either completely visible,
4350 * partially visible or completely invisible.
4351 * The return value consist of a combination of D3DCLIP_* flags, or it's
4352 * 0 if the sphere is completely visible(according to the SDK, not checked)
4353 *
4354 * Version 3 and 7
4355 *
4356 * Params:
4357 * Centers: Array containing the sphere centers
4358 * Radii: Array containing the sphere radii
4359 * NumSpheres: The number of centers and radii in the arrays
4360 * Flags: Some flags
4361 * ReturnValues: Array to write the results to
4362 *
4363 * Returns:
4364 * D3D_OK
4365 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4366 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4367 * is singular)
4368 *
4369 *****************************************************************************/
4370
4371 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4372 {
4373 float distance, norm;
4374
4375 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4376 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4377
4378 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4379 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4380 return 0;
4381 }
4382
4383 static HRESULT WINAPI
4384 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4385 D3DVECTOR *Centers,
4386 D3DVALUE *Radii,
4387 DWORD NumSpheres,
4388 DWORD Flags,
4389 DWORD *ReturnValues)
4390 {
4391 D3DMATRIX m, temp;
4392 D3DVALUE origin_plane[6];
4393 D3DVECTOR vec[6];
4394 HRESULT hr;
4395 UINT i, j;
4396
4397 TRACE("(%p)->(%p,%p,%08x,%08x,%p)\n", iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4398
4399 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4400 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4401 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4402 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4403 multiply_matrix_D3D_way(&m, &m, &temp);
4404
4405 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4406 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4407 multiply_matrix_D3D_way(&m, &m, &temp);
4408
4409 /* Left plane */
4410 vec[0].u1.x = m._14 + m._11;
4411 vec[0].u2.y = m._24 + m._21;
4412 vec[0].u3.z = m._34 + m._31;
4413 origin_plane[0] = m._44 + m._41;
4414
4415 /* Right plane */
4416 vec[1].u1.x = m._14 - m._11;
4417 vec[1].u2.y = m._24 - m._21;
4418 vec[1].u3.z = m._34 - m._31;
4419 origin_plane[1] = m._44 - m._41;
4420
4421 /* Top plane */
4422 vec[2].u1.x = m._14 - m._12;
4423 vec[2].u2.y = m._24 - m._22;
4424 vec[2].u3.z = m._34 - m._32;
4425 origin_plane[2] = m._44 - m._42;
4426
4427 /* Bottom plane */
4428 vec[3].u1.x = m._14 + m._12;
4429 vec[3].u2.y = m._24 + m._22;
4430 vec[3].u3.z = m._34 + m._32;
4431 origin_plane[3] = m._44 + m._42;
4432
4433 /* Front plane */
4434 vec[4].u1.x = m._13;
4435 vec[4].u2.y = m._23;
4436 vec[4].u3.z = m._33;
4437 origin_plane[4] = m._43;
4438
4439 /* Back plane*/
4440 vec[5].u1.x = m._14 - m._13;
4441 vec[5].u2.y = m._24 - m._23;
4442 vec[5].u3.z = m._34 - m._33;
4443 origin_plane[5] = m._44 - m._43;
4444
4445 for(i=0; i<NumSpheres; i++)
4446 {
4447 ReturnValues[i] = 0;
4448 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4449 }
4450
4451 return D3D_OK;
4452 }
4453
4454 static HRESULT WINAPI
4455 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4456 D3DVECTOR *Centers,
4457 D3DVALUE *Radii,
4458 DWORD NumSpheres,
4459 DWORD Flags,
4460 DWORD *ReturnValues)
4461 {
4462 IDirect3DDeviceImpl *This = device_from_device3(iface);
4463 TRACE_(ddraw_thunk)("(%p)->(%p,%p,%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues);
4464 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)This,
4465 Centers, Radii, NumSpheres, Flags, ReturnValues);
4466 }
4467
4468 /*****************************************************************************
4469 * IDirect3DDevice7::GetTexture
4470 *
4471 * Returns the texture interface handle assigned to a texture stage.
4472 * The returned texture is AddRefed. This is taken from old ddraw,
4473 * not checked in Windows.
4474 *
4475 * Version 3 and 7
4476 *
4477 * Params:
4478 * Stage: Texture stage to read the texture from
4479 * Texture: Address to store the interface pointer at
4480 *
4481 * Returns:
4482 * D3D_OK on success
4483 * DDERR_INVALIDPARAMS if Texture is NULL
4484 * For details, see IWineD3DDevice::GetTexture
4485 *
4486 *****************************************************************************/
4487 static HRESULT
4488 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4489 DWORD Stage,
4490 IDirectDrawSurface7 **Texture)
4491 {
4492 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4493 IWineD3DBaseTexture *Surf;
4494 HRESULT hr;
4495 TRACE("(%p)->(%d,%p): Relay\n", This, Stage, Texture);
4496
4497 if(!Texture)
4498 {
4499 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4500 return DDERR_INVALIDPARAMS;
4501 }
4502
4503 EnterCriticalSection(&ddraw_cs);
4504 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4505 if( (hr != D3D_OK) || (!Surf) )
4506 {
4507 *Texture = NULL;
4508 LeaveCriticalSection(&ddraw_cs);
4509 return hr;
4510 }
4511
4512 /* GetParent AddRef()s, which is perfectly OK.
4513 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4514 */
4515 hr = IWineD3DBaseTexture_GetParent(Surf,
4516 (IUnknown **) Texture);
4517 LeaveCriticalSection(&ddraw_cs);
4518 return hr;
4519 }
4520
4521 static HRESULT WINAPI
4522 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4523 DWORD Stage,
4524 IDirectDrawSurface7 **Texture)
4525 {
4526 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4527 }
4528
4529 static HRESULT WINAPI
4530 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4531 DWORD Stage,
4532 IDirectDrawSurface7 **Texture)
4533 {
4534 HRESULT hr;
4535 WORD old_fpucw;
4536
4537 old_fpucw = d3d_fpu_setup();
4538 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4539 set_fpu_control_word(old_fpucw);
4540
4541 return hr;
4542 }
4543
4544 static HRESULT WINAPI
4545 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4546 DWORD Stage,
4547 IDirect3DTexture2 **Texture2)
4548 {
4549 IDirect3DDeviceImpl *This = device_from_device3(iface);
4550 HRESULT ret;
4551 IDirectDrawSurface7 *ret_val;
4552
4553 TRACE_(ddraw_thunk)("(%p)->(%d,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, Texture2);
4554 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)This, Stage, &ret_val);
4555
4556 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4557
4558 TRACE_(ddraw_thunk)(" returning interface %p.\n", *Texture2);
4559
4560 return ret;
4561 }
4562
4563 /*****************************************************************************
4564 * IDirect3DDevice7::SetTexture
4565 *
4566 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4567 *
4568 * Version 3 and 7
4569 *
4570 * Params:
4571 * Stage: The stage to assign the texture to
4572 * Texture: Interface pointer to the texture surface
4573 *
4574 * Returns
4575 * D3D_OK on success
4576 * For details, see IWineD3DDevice::SetTexture
4577 *
4578 *****************************************************************************/
4579 static HRESULT
4580 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4581 DWORD Stage,
4582 IDirectDrawSurface7 *Texture)
4583 {
4584 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4585 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4586 HRESULT hr;
4587 TRACE("(%p)->(%08x,%p): Relay!\n", This, Stage, surf);
4588
4589 /* Texture may be NULL here */
4590 EnterCriticalSection(&ddraw_cs);
4591 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4592 Stage,
4593 surf ? surf->wineD3DTexture : NULL);
4594 LeaveCriticalSection(&ddraw_cs);
4595 return hr;
4596 }
4597
4598 static HRESULT WINAPI
4599 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4600 DWORD Stage,
4601 IDirectDrawSurface7 *Texture)
4602 {
4603 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4604 }
4605
4606 static HRESULT WINAPI
4607 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4608 DWORD Stage,
4609 IDirectDrawSurface7 *Texture)
4610 {
4611 HRESULT hr;
4612 WORD old_fpucw;
4613
4614 old_fpucw = d3d_fpu_setup();
4615 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4616 set_fpu_control_word(old_fpucw);
4617
4618 return hr;
4619 }
4620
4621 static HRESULT WINAPI
4622 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4623 DWORD Stage,
4624 IDirect3DTexture2 *Texture2)
4625 {
4626 IDirect3DDeviceImpl *This = device_from_device3(iface);
4627 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4628 DWORD texmapblend;
4629 HRESULT hr;
4630 TRACE("(%p)->(%d,%p)\n", This, Stage, tex);
4631
4632 EnterCriticalSection(&ddraw_cs);
4633
4634 if (This->legacyTextureBlending)
4635 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4636
4637 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4638
4639 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4640 {
4641 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4642 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4643 BOOL tex_alpha = FALSE;
4644 IWineD3DBaseTexture *tex = NULL;
4645 WINED3DSURFACE_DESC desc;
4646 DDPIXELFORMAT ddfmt;
4647 HRESULT result;
4648
4649 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4650 0,
4651 &tex);
4652
4653 if(result == WINED3D_OK && tex)
4654 {
4655 memset(&desc, 0, sizeof(desc));
4656 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4657 if (SUCCEEDED(result))
4658 {
4659 ddfmt.dwSize = sizeof(ddfmt);
4660 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4661 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4662 }
4663
4664 IWineD3DBaseTexture_Release(tex);
4665 }
4666
4667 /* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
4668 if (tex_alpha)
4669 {
4670 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
4671 }
4672 else
4673 {
4674 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
4675 }
4676 }
4677
4678 LeaveCriticalSection(&ddraw_cs);
4679
4680 return hr;
4681 }
4682
4683 static const struct tss_lookup
4684 {
4685 BOOL sampler_state;
4686 DWORD state;
4687 }
4688 tss_lookup[] =
4689 {
4690 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4691 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4692 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4693 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4694 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4695 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4696 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4697 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4698 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4699 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4700 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4701 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4702 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4703 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4704 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4705 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4706 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4707 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4708 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4709 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4710 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4711 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4712 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4713 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4714 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4715 };
4716
4717 /*****************************************************************************
4718 * IDirect3DDevice7::GetTextureStageState
4719 *
4720 * Retrieves a state from a texture stage.
4721 *
4722 * Version 3 and 7
4723 *
4724 * Params:
4725 * Stage: The stage to retrieve the state from
4726 * TexStageStateType: The state type to retrieve
4727 * State: Address to store the state's value at
4728 *
4729 * Returns:
4730 * D3D_OK on success
4731 * DDERR_INVALIDPARAMS if State is NULL
4732 * For details, see IWineD3DDevice::GetTextureStageState
4733 *
4734 *****************************************************************************/
4735 static HRESULT
4736 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4737 DWORD Stage,
4738 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4739 DWORD *State)
4740 {
4741 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4742 HRESULT hr;
4743 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4744 TRACE("(%p)->(%08x,%08x,%p): Relay!\n", This, Stage, TexStageStateType, State);
4745
4746 if(!State)
4747 return DDERR_INVALIDPARAMS;
4748
4749 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4750 {
4751 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4752 *State = 0;
4753 return DD_OK;
4754 }
4755
4756 EnterCriticalSection(&ddraw_cs);
4757
4758 if (l->sampler_state)
4759 {
4760 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4761
4762 switch(TexStageStateType)
4763 {
4764 /* Mipfilter is a sampler state with different values */
4765 case D3DTSS_MIPFILTER:
4766 {
4767 switch(*State)
4768 {
4769 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4770 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4771 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4772 default:
4773 ERR("Unexpected mipfilter value %#x\n", *State);
4774 *State = D3DTFP_NONE;
4775 break;
4776 }
4777 break;
4778 }
4779
4780 /* Magfilter has slightly different values */
4781 case D3DTSS_MAGFILTER:
4782 {
4783 switch(*State)
4784 {
4785 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4786 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4787 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4788 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4789 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4790 default:
4791 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4792 *State = D3DTFG_POINT;
4793 break;
4794 }
4795 break;
4796 }
4797
4798 default:
4799 break;
4800 }
4801 }
4802 else
4803 {
4804 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4805 }
4806
4807 LeaveCriticalSection(&ddraw_cs);
4808 return hr;
4809 }
4810
4811 static HRESULT WINAPI
4812 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4813 DWORD Stage,
4814 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4815 DWORD *State)
4816 {
4817 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4818 }
4819
4820 static HRESULT WINAPI
4821 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4822 DWORD Stage,
4823 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4824 DWORD *State)
4825 {
4826 HRESULT hr;
4827 WORD old_fpucw;
4828
4829 old_fpucw = d3d_fpu_setup();
4830 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4831 set_fpu_control_word(old_fpucw);
4832
4833 return hr;
4834 }
4835
4836 static HRESULT WINAPI
4837 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4838 DWORD Stage,
4839 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4840 DWORD *State)
4841 {
4842 IDirect3DDeviceImpl *This = device_from_device3(iface);
4843 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4844 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)This, Stage, TexStageStateType, State);
4845 }
4846
4847 /*****************************************************************************
4848 * IDirect3DDevice7::SetTextureStageState
4849 *
4850 * Sets a texture stage state. Some stage types need to be handled specially,
4851 * because they do not exist in WineD3D and were moved to another place
4852 *
4853 * Version 3 and 7
4854 *
4855 * Params:
4856 * Stage: The stage to modify
4857 * TexStageStateType: The state to change
4858 * State: The new value for the state
4859 *
4860 * Returns:
4861 * D3D_OK on success
4862 * For details, see IWineD3DDevice::SetTextureStageState
4863 *
4864 *****************************************************************************/
4865 static HRESULT
4866 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4867 DWORD Stage,
4868 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4869 DWORD State)
4870 {
4871 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4872 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4873 HRESULT hr;
4874 TRACE("(%p)->(%08x,%08x,%08x): Relay!\n", This, Stage, TexStageStateType, State);
4875
4876 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4877 {
4878 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4879 return DD_OK;
4880 }
4881
4882 EnterCriticalSection(&ddraw_cs);
4883
4884 if (l->sampler_state)
4885 {
4886 switch(TexStageStateType)
4887 {
4888 /* Mipfilter is a sampler state with different values */
4889 case D3DTSS_MIPFILTER:
4890 {
4891 switch(State)
4892 {
4893 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4894 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4895 case 0: /* Unchecked */
4896 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4897 default:
4898 ERR("Unexpected mipfilter value %d\n", State);
4899 State = WINED3DTEXF_NONE;
4900 break;
4901 }
4902 break;
4903 }
4904
4905 /* Magfilter has slightly different values */
4906 case D3DTSS_MAGFILTER:
4907 {
4908 switch(State)
4909 {
4910 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4911 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4912 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4913 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4914 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4915 default:
4916 ERR("Unexpected d3d7 mag filter type %d\n", State);
4917 State = WINED3DTEXF_POINT;
4918 break;
4919 }
4920 break;
4921 }
4922
4923 case D3DTSS_ADDRESS:
4924 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4925 break;
4926
4927 default:
4928 break;
4929 }
4930
4931 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4932 }
4933 else
4934 {
4935 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4936 }
4937
4938 LeaveCriticalSection(&ddraw_cs);
4939 return hr;
4940 }
4941
4942 static HRESULT WINAPI
4943 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4944 DWORD Stage,
4945 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4946 DWORD State)
4947 {
4948 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4949 }
4950
4951 static HRESULT WINAPI
4952 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4953 DWORD Stage,
4954 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4955 DWORD State)
4956 {
4957 HRESULT hr;
4958 WORD old_fpucw;
4959
4960 old_fpucw = d3d_fpu_setup();
4961 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4962 set_fpu_control_word(old_fpucw);
4963
4964 return hr;
4965 }
4966
4967 static HRESULT WINAPI
4968 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4969 DWORD Stage,
4970 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4971 DWORD State)
4972 {
4973 IDirect3DDeviceImpl *This = device_from_device3(iface);
4974 TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, Stage, TexStageStateType, State);
4975 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)This, Stage, TexStageStateType, State);
4976 }
4977
4978 /*****************************************************************************
4979 * IDirect3DDevice7::ValidateDevice
4980 *
4981 * SDK: "Reports the device's ability to render the currently set
4982 * texture-blending operations in a single pass". Whatever that means
4983 * exactly...
4984 *
4985 * Version 3 and 7
4986 *
4987 * Params:
4988 * NumPasses: Address to write the number of necessary passes for the
4989 * desired effect to.
4990 *
4991 * Returns:
4992 * D3D_OK on success
4993 * See IWineD3DDevice::ValidateDevice for more details
4994 *
4995 *****************************************************************************/
4996 static HRESULT
4997 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4998 DWORD *NumPasses)
4999 {
5000 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5001 HRESULT hr;
5002 TRACE("(%p)->(%p): Relay\n", This, NumPasses);
5003
5004 EnterCriticalSection(&ddraw_cs);
5005 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5006 LeaveCriticalSection(&ddraw_cs);
5007 return hr;
5008 }
5009
5010 static HRESULT WINAPI
5011 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5012 DWORD *NumPasses)
5013 {
5014 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5015 }
5016
5017 static HRESULT WINAPI
5018 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5019 DWORD *NumPasses)
5020 {
5021 HRESULT hr;
5022 WORD old_fpucw;
5023
5024 old_fpucw = d3d_fpu_setup();
5025 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5026 set_fpu_control_word(old_fpucw);
5027
5028 return hr;
5029 }
5030
5031 static HRESULT WINAPI
5032 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5033 DWORD *Passes)
5034 {
5035 IDirect3DDeviceImpl *This = device_from_device3(iface);
5036 TRACE_(ddraw_thunk)("(%p)->(%p) thunking to IDirect3DDevice7 interface.\n", This, Passes);
5037 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)This, Passes);
5038 }
5039
5040 /*****************************************************************************
5041 * IDirect3DDevice7::Clear
5042 *
5043 * Fills the render target, the z buffer and the stencil buffer with a
5044 * clear color / value
5045 *
5046 * Version 7 only
5047 *
5048 * Params:
5049 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5050 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5051 * Flags: Some flags, as usual
5052 * Color: Clear color for the render target
5053 * Z: Clear value for the Z buffer
5054 * Stencil: Clear value to store in each stencil buffer entry
5055 *
5056 * Returns:
5057 * D3D_OK on success
5058 * For details, see IWineD3DDevice::Clear
5059 *
5060 *****************************************************************************/
5061 static HRESULT
5062 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5063 DWORD Count,
5064 D3DRECT *Rects,
5065 DWORD Flags,
5066 D3DCOLOR Color,
5067 D3DVALUE Z,
5068 DWORD Stencil)
5069 {
5070 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5071 HRESULT hr;
5072 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x): Relay\n", This, Count, Rects, Flags, Color, Z, Stencil);
5073
5074 /* Note; D3DRECT is compatible with WINED3DRECT */
5075 EnterCriticalSection(&ddraw_cs);
5076 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5077 LeaveCriticalSection(&ddraw_cs);
5078 return hr;
5079 }
5080
5081 static HRESULT WINAPI
5082 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5083 DWORD Count,
5084 D3DRECT *Rects,
5085 DWORD Flags,
5086 D3DCOLOR Color,
5087 D3DVALUE Z,
5088 DWORD Stencil)
5089 {
5090 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5091 }
5092
5093 static HRESULT WINAPI
5094 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5095 DWORD Count,
5096 D3DRECT *Rects,
5097 DWORD Flags,
5098 D3DCOLOR Color,
5099 D3DVALUE Z,
5100 DWORD Stencil)
5101 {
5102 HRESULT hr;
5103 WORD old_fpucw;
5104
5105 old_fpucw = d3d_fpu_setup();
5106 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5107 set_fpu_control_word(old_fpucw);
5108
5109 return hr;
5110 }
5111
5112 /*****************************************************************************
5113 * IDirect3DDevice7::SetViewport
5114 *
5115 * Sets the current viewport.
5116 *
5117 * Version 7 only, but IDirect3DViewport uses this call for older
5118 * versions
5119 *
5120 * Params:
5121 * Data: The new viewport to set
5122 *
5123 * Returns:
5124 * D3D_OK on success
5125 * DDERR_INVALIDPARAMS if Data is NULL
5126 * For more details, see IWineDDDevice::SetViewport
5127 *
5128 *****************************************************************************/
5129 static HRESULT
5130 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5131 D3DVIEWPORT7 *Data)
5132 {
5133 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5134 HRESULT hr;
5135 TRACE("(%p)->(%p) Relay!\n", This, Data);
5136
5137 if(!Data)
5138 return DDERR_INVALIDPARAMS;
5139
5140 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5141 EnterCriticalSection(&ddraw_cs);
5142 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5143 (WINED3DVIEWPORT*) Data);
5144 LeaveCriticalSection(&ddraw_cs);
5145 return hr;
5146 }
5147
5148 static HRESULT WINAPI
5149 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5150 D3DVIEWPORT7 *Data)
5151 {
5152 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5153 }
5154
5155 static HRESULT WINAPI
5156 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5157 D3DVIEWPORT7 *Data)
5158 {
5159 HRESULT hr;
5160 WORD old_fpucw;
5161
5162 old_fpucw = d3d_fpu_setup();
5163 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5164 set_fpu_control_word(old_fpucw);
5165
5166 return hr;
5167 }
5168
5169 /*****************************************************************************
5170 * IDirect3DDevice::GetViewport
5171 *
5172 * Returns the current viewport
5173 *
5174 * Version 7
5175 *
5176 * Params:
5177 * Data: D3D7Viewport structure to write the viewport information to
5178 *
5179 * Returns:
5180 * D3D_OK on success
5181 * DDERR_INVALIDPARAMS if Data is NULL
5182 * For more details, see IWineD3DDevice::GetViewport
5183 *
5184 *****************************************************************************/
5185 static HRESULT
5186 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5187 D3DVIEWPORT7 *Data)
5188 {
5189 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5190 HRESULT hr;
5191 TRACE("(%p)->(%p) Relay!\n", This, Data);
5192
5193 if(!Data)
5194 return DDERR_INVALIDPARAMS;
5195
5196 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5197 EnterCriticalSection(&ddraw_cs);
5198 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5199 (WINED3DVIEWPORT*) Data);
5200
5201 LeaveCriticalSection(&ddraw_cs);
5202 return hr_ddraw_from_wined3d(hr);
5203 }
5204
5205 static HRESULT WINAPI
5206 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5207 D3DVIEWPORT7 *Data)
5208 {
5209 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5210 }
5211
5212 static HRESULT WINAPI
5213 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5214 D3DVIEWPORT7 *Data)
5215 {
5216 HRESULT hr;
5217 WORD old_fpucw;
5218
5219 old_fpucw = d3d_fpu_setup();
5220 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5221 set_fpu_control_word(old_fpucw);
5222
5223 return hr;
5224 }
5225
5226 /*****************************************************************************
5227 * IDirect3DDevice7::SetMaterial
5228 *
5229 * Sets the Material
5230 *
5231 * Version 7
5232 *
5233 * Params:
5234 * Mat: The material to set
5235 *
5236 * Returns:
5237 * D3D_OK on success
5238 * DDERR_INVALIDPARAMS if Mat is NULL.
5239 * For more details, see IWineD3DDevice::SetMaterial
5240 *
5241 *****************************************************************************/
5242 static HRESULT
5243 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5244 D3DMATERIAL7 *Mat)
5245 {
5246 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5247 HRESULT hr;
5248 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5249
5250 if (!Mat) return DDERR_INVALIDPARAMS;
5251 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5252 EnterCriticalSection(&ddraw_cs);
5253 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5254 (WINED3DMATERIAL*) Mat);
5255 LeaveCriticalSection(&ddraw_cs);
5256 return hr_ddraw_from_wined3d(hr);
5257 }
5258
5259 static HRESULT WINAPI
5260 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5261 D3DMATERIAL7 *Mat)
5262 {
5263 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5264 }
5265
5266 static HRESULT WINAPI
5267 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5268 D3DMATERIAL7 *Mat)
5269 {
5270 HRESULT hr;
5271 WORD old_fpucw;
5272
5273 old_fpucw = d3d_fpu_setup();
5274 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5275 set_fpu_control_word(old_fpucw);
5276
5277 return hr;
5278 }
5279
5280 /*****************************************************************************
5281 * IDirect3DDevice7::GetMaterial
5282 *
5283 * Returns the current material
5284 *
5285 * Version 7
5286 *
5287 * Params:
5288 * Mat: D3DMATERIAL7 structure to write the material parameters to
5289 *
5290 * Returns:
5291 * D3D_OK on success
5292 * DDERR_INVALIDPARAMS if Mat is NULL
5293 * For more details, see IWineD3DDevice::GetMaterial
5294 *
5295 *****************************************************************************/
5296 static HRESULT
5297 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5298 D3DMATERIAL7 *Mat)
5299 {
5300 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5301 HRESULT hr;
5302 TRACE("(%p)->(%p): Relay!\n", This, Mat);
5303
5304 EnterCriticalSection(&ddraw_cs);
5305 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5306 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5307 (WINED3DMATERIAL*) Mat);
5308 LeaveCriticalSection(&ddraw_cs);
5309 return hr_ddraw_from_wined3d(hr);
5310 }
5311
5312 static HRESULT WINAPI
5313 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5314 D3DMATERIAL7 *Mat)
5315 {
5316 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5317 }
5318
5319 static HRESULT WINAPI
5320 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5321 D3DMATERIAL7 *Mat)
5322 {
5323 HRESULT hr;
5324 WORD old_fpucw;
5325
5326 old_fpucw = d3d_fpu_setup();
5327 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5328 set_fpu_control_word(old_fpucw);
5329
5330 return hr;
5331 }
5332
5333 /*****************************************************************************
5334 * IDirect3DDevice7::SetLight
5335 *
5336 * Assigns a light to a light index, but doesn't activate it yet.
5337 *
5338 * Version 7, IDirect3DLight uses this method for older versions
5339 *
5340 * Params:
5341 * LightIndex: The index of the new light
5342 * Light: A D3DLIGHT7 structure describing the light
5343 *
5344 * Returns:
5345 * D3D_OK on success
5346 * For more details, see IWineD3DDevice::SetLight
5347 *
5348 *****************************************************************************/
5349 static HRESULT
5350 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5351 DWORD LightIndex,
5352 D3DLIGHT7 *Light)
5353 {
5354 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5355 HRESULT hr;
5356 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5357
5358 EnterCriticalSection(&ddraw_cs);
5359 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5360 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5361 LightIndex,
5362 (WINED3DLIGHT*) Light);
5363 LeaveCriticalSection(&ddraw_cs);
5364 return hr_ddraw_from_wined3d(hr);
5365 }
5366
5367 static HRESULT WINAPI
5368 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5369 DWORD LightIndex,
5370 D3DLIGHT7 *Light)
5371 {
5372 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5373 }
5374
5375 static HRESULT WINAPI
5376 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5377 DWORD LightIndex,
5378 D3DLIGHT7 *Light)
5379 {
5380 HRESULT hr;
5381 WORD old_fpucw;
5382
5383 old_fpucw = d3d_fpu_setup();
5384 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5385 set_fpu_control_word(old_fpucw);
5386
5387 return hr;
5388 }
5389
5390 /*****************************************************************************
5391 * IDirect3DDevice7::GetLight
5392 *
5393 * Returns the light assigned to a light index
5394 *
5395 * Params:
5396 * Light: Structure to write the light information to
5397 *
5398 * Returns:
5399 * D3D_OK on success
5400 * DDERR_INVALIDPARAMS if Light is NULL
5401 * For details, see IWineD3DDevice::GetLight
5402 *
5403 *****************************************************************************/
5404 static HRESULT
5405 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5406 DWORD LightIndex,
5407 D3DLIGHT7 *Light)
5408 {
5409 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5410 HRESULT rc;
5411 TRACE("(%p)->(%08x,%p): Relay!\n", This, LightIndex, Light);
5412
5413 EnterCriticalSection(&ddraw_cs);
5414 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5415 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5416 LightIndex,
5417 (WINED3DLIGHT*) Light);
5418
5419 /* Translate the result. WineD3D returns other values than D3D7 */
5420 LeaveCriticalSection(&ddraw_cs);
5421 return hr_ddraw_from_wined3d(rc);
5422 }
5423
5424 static HRESULT WINAPI
5425 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5426 DWORD LightIndex,
5427 D3DLIGHT7 *Light)
5428 {
5429 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5430 }
5431
5432 static HRESULT WINAPI
5433 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5434 DWORD LightIndex,
5435 D3DLIGHT7 *Light)
5436 {
5437 HRESULT hr;
5438 WORD old_fpucw;
5439
5440 old_fpucw = d3d_fpu_setup();
5441 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5442 set_fpu_control_word(old_fpucw);
5443
5444 return hr;
5445 }
5446
5447 /*****************************************************************************
5448 * IDirect3DDevice7::BeginStateBlock
5449 *
5450 * Begins recording to a stateblock
5451 *
5452 * Version 7
5453 *
5454 * Returns:
5455 * D3D_OK on success
5456 * For details see IWineD3DDevice::BeginStateBlock
5457 *
5458 *****************************************************************************/
5459 static HRESULT
5460 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5461 {
5462 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5463 HRESULT hr;
5464 TRACE("(%p)->(): Relay!\n", This);
5465
5466 EnterCriticalSection(&ddraw_cs);
5467 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5468 LeaveCriticalSection(&ddraw_cs);
5469 return hr_ddraw_from_wined3d(hr);
5470 }
5471
5472 static HRESULT WINAPI
5473 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5474 {
5475 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5476 }
5477
5478 static HRESULT WINAPI
5479 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5480 {
5481 HRESULT hr;
5482 WORD old_fpucw;
5483
5484 old_fpucw = d3d_fpu_setup();
5485 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5486 set_fpu_control_word(old_fpucw);
5487
5488 return hr;
5489 }
5490
5491 /*****************************************************************************
5492 * IDirect3DDevice7::EndStateBlock
5493 *
5494 * Stops recording to a state block and returns the created stateblock
5495 * handle.
5496 *
5497 * Version 7
5498 *
5499 * Params:
5500 * BlockHandle: Address to store the stateblock's handle to
5501 *
5502 * Returns:
5503 * D3D_OK on success
5504 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5505 * See IWineD3DDevice::EndStateBlock for more details
5506 *
5507 *****************************************************************************/
5508 static HRESULT
5509 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5510 DWORD *BlockHandle)
5511 {
5512 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5513 HRESULT hr;
5514 TRACE("(%p)->(%p): Relay!\n", This, BlockHandle);
5515
5516 if(!BlockHandle)
5517 {
5518 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5519 return DDERR_INVALIDPARAMS;
5520 }
5521
5522 EnterCriticalSection(&ddraw_cs);
5523 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5524 if(!*BlockHandle)
5525 {
5526 ERR("Cannot get a handle number for the stateblock\n");
5527 LeaveCriticalSection(&ddraw_cs);
5528 return DDERR_OUTOFMEMORY;
5529 }
5530 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5531 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice,
5532 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr);
5533 LeaveCriticalSection(&ddraw_cs);
5534 return hr_ddraw_from_wined3d(hr);
5535 }
5536
5537 static HRESULT WINAPI
5538 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5539 DWORD *BlockHandle)
5540 {
5541 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5542 }
5543
5544 static HRESULT WINAPI
5545 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5546 DWORD *BlockHandle)
5547 {
5548 HRESULT hr;
5549 WORD old_fpucw;
5550
5551 old_fpucw = d3d_fpu_setup();
5552 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5553 set_fpu_control_word(old_fpucw);
5554
5555 return hr;
5556 }
5557
5558 /*****************************************************************************
5559 * IDirect3DDevice7::PreLoad
5560 *
5561 * Allows the app to signal that a texture will be used soon, to allow
5562 * the Direct3DDevice to load it to the video card in the meantime.
5563 *
5564 * Version 7
5565 *
5566 * Params:
5567 * Texture: The texture to preload
5568 *
5569 * Returns:
5570 * D3D_OK on success
5571 * DDERR_INVALIDPARAMS if Texture is NULL
5572 * See IWineD3DSurface::PreLoad for details
5573 *
5574 *****************************************************************************/
5575 static HRESULT
5576 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5577 IDirectDrawSurface7 *Texture)
5578 {
5579 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5580 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5581
5582 TRACE("(%p)->(%p): Relay!\n", This, surf);
5583
5584 if(!Texture)
5585 return DDERR_INVALIDPARAMS;
5586
5587 EnterCriticalSection(&ddraw_cs);
5588 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5589 LeaveCriticalSection(&ddraw_cs);
5590 return D3D_OK;
5591 }
5592
5593 static HRESULT WINAPI
5594 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5595 IDirectDrawSurface7 *Texture)
5596 {
5597 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5598 }
5599
5600 static HRESULT WINAPI
5601 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5602 IDirectDrawSurface7 *Texture)
5603 {
5604 HRESULT hr;
5605 WORD old_fpucw;
5606
5607 old_fpucw = d3d_fpu_setup();
5608 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5609 set_fpu_control_word(old_fpucw);
5610
5611 return hr;
5612 }
5613
5614 /*****************************************************************************
5615 * IDirect3DDevice7::ApplyStateBlock
5616 *
5617 * Activates the state stored in a state block handle.
5618 *
5619 * Params:
5620 * BlockHandle: The stateblock handle to activate
5621 *
5622 * Returns:
5623 * D3D_OK on success
5624 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5625 *
5626 *****************************************************************************/
5627 static HRESULT
5628 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5629 DWORD BlockHandle)
5630 {
5631 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5632 HRESULT hr;
5633 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5634
5635 EnterCriticalSection(&ddraw_cs);
5636 if(!BlockHandle || BlockHandle > This->numHandles)
5637 {
5638 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5639 LeaveCriticalSection(&ddraw_cs);
5640 return D3DERR_INVALIDSTATEBLOCK;
5641 }
5642 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5643 {
5644 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5645 LeaveCriticalSection(&ddraw_cs);
5646 return D3DERR_INVALIDSTATEBLOCK;
5647 }
5648
5649 hr = IWineD3DStateBlock_Apply((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5650 LeaveCriticalSection(&ddraw_cs);
5651 return hr_ddraw_from_wined3d(hr);
5652 }
5653
5654 static HRESULT WINAPI
5655 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5656 DWORD BlockHandle)
5657 {
5658 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5659 }
5660
5661 static HRESULT WINAPI
5662 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5663 DWORD BlockHandle)
5664 {
5665 HRESULT hr;
5666 WORD old_fpucw;
5667
5668 old_fpucw = d3d_fpu_setup();
5669 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5670 set_fpu_control_word(old_fpucw);
5671
5672 return hr;
5673 }
5674
5675 /*****************************************************************************
5676 * IDirect3DDevice7::CaptureStateBlock
5677 *
5678 * Updates a stateblock's values to the values currently set for the device
5679 *
5680 * Version 7
5681 *
5682 * Params:
5683 * BlockHandle: Stateblock to update
5684 *
5685 * Returns:
5686 * D3D_OK on success
5687 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5688 * See IWineD3DDevice::CaptureStateBlock for more details
5689 *
5690 *****************************************************************************/
5691 static HRESULT
5692 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5693 DWORD BlockHandle)
5694 {
5695 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5696 HRESULT hr;
5697 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5698
5699 EnterCriticalSection(&ddraw_cs);
5700 if(BlockHandle == 0 || BlockHandle > This->numHandles)
5701 {
5702 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5703 LeaveCriticalSection(&ddraw_cs);
5704 return D3DERR_INVALIDSTATEBLOCK;
5705 }
5706 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5707 {
5708 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5709 LeaveCriticalSection(&ddraw_cs);
5710 return D3DERR_INVALIDSTATEBLOCK;
5711 }
5712
5713 hr = IWineD3DStateBlock_Capture((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5714 LeaveCriticalSection(&ddraw_cs);
5715 return hr_ddraw_from_wined3d(hr);
5716 }
5717
5718 static HRESULT WINAPI
5719 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5720 DWORD BlockHandle)
5721 {
5722 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5723 }
5724
5725 static HRESULT WINAPI
5726 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5727 DWORD BlockHandle)
5728 {
5729 HRESULT hr;
5730 WORD old_fpucw;
5731
5732 old_fpucw = d3d_fpu_setup();
5733 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5734 set_fpu_control_word(old_fpucw);
5735
5736 return hr;
5737 }
5738
5739 /*****************************************************************************
5740 * IDirect3DDevice7::DeleteStateBlock
5741 *
5742 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5743 *
5744 * Version 7
5745 *
5746 * Params:
5747 * BlockHandle: Stateblock handle to delete
5748 *
5749 * Returns:
5750 * D3D_OK on success
5751 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5752 *
5753 *****************************************************************************/
5754 static HRESULT
5755 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5756 DWORD BlockHandle)
5757 {
5758 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5759 ULONG ref;
5760 TRACE("(%p)->(%08x): Relay!\n", This, BlockHandle);
5761
5762 EnterCriticalSection(&ddraw_cs);
5763 if(BlockHandle == 0 || BlockHandle > This->numHandles)
5764 {
5765 WARN("Out of range handle %d, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5766 LeaveCriticalSection(&ddraw_cs);
5767 return D3DERR_INVALIDSTATEBLOCK;
5768 }
5769 if(This->Handles[BlockHandle - 1].type != DDrawHandle_StateBlock)
5770 {
5771 WARN("Handle %d is not a stateblock, returning D3DERR_INVALIDSTATEBLOCK\n", BlockHandle);
5772 LeaveCriticalSection(&ddraw_cs);
5773 return D3DERR_INVALIDSTATEBLOCK;
5774 }
5775
5776 ref = IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->Handles[BlockHandle - 1].ptr);
5777 if(ref)
5778 {
5779 ERR("Something is still holding the stateblock %p(Handle %d). Ref = %d\n", This->Handles[BlockHandle - 1].ptr, BlockHandle, ref);
5780 }
5781 This->Handles[BlockHandle - 1].ptr = NULL;
5782 This->Handles[BlockHandle - 1].type = DDrawHandle_Unknown;
5783
5784 LeaveCriticalSection(&ddraw_cs);
5785 return D3D_OK;
5786 }
5787
5788 static HRESULT WINAPI
5789 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5790 DWORD BlockHandle)
5791 {
5792 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5793 }
5794
5795 static HRESULT WINAPI
5796 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5797 DWORD BlockHandle)
5798 {
5799 HRESULT hr;
5800 WORD old_fpucw;
5801
5802 old_fpucw = d3d_fpu_setup();
5803 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5804 set_fpu_control_word(old_fpucw);
5805
5806 return hr;
5807 }
5808
5809 /*****************************************************************************
5810 * IDirect3DDevice7::CreateStateBlock
5811 *
5812 * Creates a new state block handle.
5813 *
5814 * Version 7
5815 *
5816 * Params:
5817 * Type: The state block type
5818 * BlockHandle: Address to write the created handle to
5819 *
5820 * Returns:
5821 * D3D_OK on success
5822 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5823 *
5824 *****************************************************************************/
5825 static HRESULT
5826 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5827 D3DSTATEBLOCKTYPE Type,
5828 DWORD *BlockHandle)
5829 {
5830 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5831 HRESULT hr;
5832 TRACE("(%p)->(%08x,%p)!\n", This, Type, BlockHandle);
5833
5834 if(!BlockHandle)
5835 {
5836 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5837 return DDERR_INVALIDPARAMS;
5838 }
5839 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5840 Type != D3DSBT_VERTEXSTATE ) {
5841 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5842 return DDERR_INVALIDPARAMS;
5843 }
5844
5845 EnterCriticalSection(&ddraw_cs);
5846 *BlockHandle = IDirect3DDeviceImpl_CreateHandle(This);
5847 if(!*BlockHandle)
5848 {
5849 ERR("Cannot get a handle number for the stateblock\n");
5850 LeaveCriticalSection(&ddraw_cs);
5851 return DDERR_OUTOFMEMORY;
5852 }
5853 This->Handles[*BlockHandle - 1].type = DDrawHandle_StateBlock;
5854
5855 /* The D3DSTATEBLOCKTYPE enum is fine here */
5856 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice,
5857 Type,
5858 (IWineD3DStateBlock **) &This->Handles[*BlockHandle - 1].ptr,
5859 NULL /* Parent, hope that works */);
5860 LeaveCriticalSection(&ddraw_cs);
5861 return hr_ddraw_from_wined3d(hr);
5862 }
5863
5864 static HRESULT WINAPI
5865 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5866 D3DSTATEBLOCKTYPE Type,
5867 DWORD *BlockHandle)
5868 {
5869 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5870 }
5871
5872 static HRESULT WINAPI
5873 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5874 D3DSTATEBLOCKTYPE Type,
5875 DWORD *BlockHandle)
5876 {
5877 HRESULT hr;
5878 WORD old_fpucw;
5879
5880 old_fpucw = d3d_fpu_setup();
5881 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5882 set_fpu_control_word(old_fpucw);
5883
5884 return hr;
5885 }
5886
5887 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5888 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5889 IDirectDrawSurfaceImpl *src)
5890 {
5891 IDirectDrawSurfaceImpl *src_level, *dest_level;
5892 IDirectDrawSurface7 *temp;
5893 DDSURFACEDESC2 ddsd;
5894 BOOL levelFound; /* at least one suitable sublevel in dest found */
5895
5896 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5897 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5898 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5899 */
5900 levelFound = FALSE;
5901
5902 src_level = src;
5903 dest_level = dest;
5904
5905 for (;src_level && dest_level;)
5906 {
5907 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5908 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5909 {
5910 levelFound = TRUE;
5911
5912 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5913 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5914 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5915
5916 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5917
5918 dest_level = (IDirectDrawSurfaceImpl *)temp;
5919 }
5920
5921 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5922 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5923 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5924
5925 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5926
5927 src_level = (IDirectDrawSurfaceImpl *)temp;
5928 }
5929
5930 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5931 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5932
5933 return !dest_level && levelFound;
5934 }
5935
5936 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5937 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5938 IDirectDrawSurfaceImpl *dest,
5939 IDirectDrawSurfaceImpl *src,
5940 const POINT *DestPoint,
5941 const RECT *SrcRect)
5942 {
5943 IDirectDrawSurfaceImpl *src_level, *dest_level;
5944 IDirectDrawSurface7 *temp;
5945 DDSURFACEDESC2 ddsd;
5946 POINT point;
5947 RECT rect;
5948 HRESULT hr;
5949 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5950 DWORD ckeyflag;
5951 DDCOLORKEY ddckey;
5952 BOOL palette_missing = FALSE;
5953
5954 /* Copy palette, if possible. */
5955 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5956 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5957
5958 if (pal_src != NULL && pal != NULL)
5959 {
5960 PALETTEENTRY palent[256];
5961
5962 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5963 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5964 }
5965
5966 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5967 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5968 {
5969 palette_missing = TRUE;
5970 }
5971
5972 if (pal) IDirectDrawPalette_Release(pal);
5973 if (pal_src) IDirectDrawPalette_Release(pal_src);
5974
5975 /* Copy colorkeys, if present. */
5976 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5977 {
5978 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5979
5980 if (SUCCEEDED(hr))
5981 {
5982 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5983 }
5984 }
5985
5986 src_level = src;
5987 dest_level = dest;
5988
5989 point = *DestPoint;
5990 rect = *SrcRect;
5991
5992 for (;src_level && dest_level;)
5993 {
5994 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5995 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5996 {
5997 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5998 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5999 * warnings in wined3d. */
6000 if (!palette_missing)
6001 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6002 &point);
6003
6004 if (palette_missing || FAILED(hr))
6005 {
6006 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6007 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6008 point.x, point.y,
6009 src_level->WineD3DSurface, &rect, 0);
6010 }
6011
6012 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6013 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6014 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6015
6016 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6017
6018 dest_level = (IDirectDrawSurfaceImpl *)temp;
6019 }
6020
6021 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6022 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6023 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6024
6025 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6026
6027 src_level = (IDirectDrawSurfaceImpl *)temp;
6028
6029 point.x /= 2;
6030 point.y /= 2;
6031
6032 rect.top /= 2;
6033 rect.left /= 2;
6034 rect.right = (rect.right + 1) / 2;
6035 rect.bottom = (rect.bottom + 1) / 2;
6036 }
6037
6038 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6039 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6040 }
6041
6042 /*****************************************************************************
6043 * IDirect3DDevice7::Load
6044 *
6045 * Loads a rectangular area from the source into the destination texture.
6046 * It can also copy the source to the faces of a cubic environment map
6047 *
6048 * Version 7
6049 *
6050 * Params:
6051 * DestTex: Destination texture
6052 * DestPoint: Point in the destination where the source image should be
6053 * written to
6054 * SrcTex: Source texture
6055 * SrcRect: Source rectangle
6056 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6057 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6058 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6059 *
6060 * Returns:
6061 * D3D_OK on success
6062 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6063 *
6064 *
6065 *****************************************************************************/
6066
6067 static HRESULT
6068 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6069 IDirectDrawSurface7 *DestTex,
6070 POINT *DestPoint,
6071 IDirectDrawSurface7 *SrcTex,
6072 RECT *SrcRect,
6073 DWORD Flags)
6074 {
6075 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6076 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6077 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6078 POINT destpoint;
6079 RECT srcrect;
6080 TRACE("(%p)->(%p,%p,%p,%p,%08x)\n", This, dest, DestPoint, src, SrcRect, Flags);
6081
6082 if( (!src) || (!dest) )
6083 return DDERR_INVALIDPARAMS;
6084
6085 EnterCriticalSection(&ddraw_cs);
6086
6087 if (SrcRect) srcrect = *SrcRect;
6088 else
6089 {
6090 srcrect.left = srcrect.top = 0;
6091 srcrect.right = src->surface_desc.dwWidth;
6092 srcrect.bottom = src->surface_desc.dwHeight;
6093 }
6094
6095 if (DestPoint) destpoint = *DestPoint;
6096 else
6097 {
6098 destpoint.x = destpoint.y = 0;
6099 }
6100 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6101 * destination can be a subset of mip levels, in which case actual coordinates used
6102 * for it may be divided. If any dimension of dest is larger than source, it can't be
6103 * mip level subset, so an error can be returned early.
6104 */
6105 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6106 srcrect.right > src->surface_desc.dwWidth ||
6107 srcrect.bottom > src->surface_desc.dwHeight ||
6108 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6109 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6110 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6111 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6112 {
6113 LeaveCriticalSection(&ddraw_cs);
6114 return DDERR_INVALIDPARAMS;
6115 }
6116
6117 /* Must be top level surfaces. */
6118 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6119 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6120 {
6121 LeaveCriticalSection(&ddraw_cs);
6122 return DDERR_INVALIDPARAMS;
6123 }
6124
6125 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6126 {
6127 DWORD src_face_flag, dest_face_flag;
6128 IDirectDrawSurfaceImpl *src_face, *dest_face;
6129 IDirectDrawSurface7 *temp;
6130 DDSURFACEDESC2 ddsd;
6131 int i;
6132
6133 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6134 {
6135 LeaveCriticalSection(&ddraw_cs);
6136 return DDERR_INVALIDPARAMS;
6137 }
6138
6139 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6140 * time it's actual surface loading. */
6141 for (i = 0; i < 2; i++)
6142 {
6143 dest_face = dest;
6144 src_face = src;
6145
6146 for (;dest_face && src_face;)
6147 {
6148 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6149 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6150
6151 if (src_face_flag == dest_face_flag)
6152 {
6153 if (i == 0)
6154 {
6155 /* Destination mip levels must be subset of source mip levels. */
6156 if (!is_mip_level_subset(dest_face, src_face))
6157 {
6158 LeaveCriticalSection(&ddraw_cs);
6159 return DDERR_INVALIDPARAMS;
6160 }
6161 }
6162 else if (Flags & dest_face_flag)
6163 {
6164 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6165 }
6166
6167 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6168 {
6169 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6170 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6171 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6172
6173 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6174
6175 src_face = (IDirectDrawSurfaceImpl *)temp;
6176 }
6177 else
6178 {
6179 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6180
6181 src_face = NULL;
6182 }
6183 }
6184
6185 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6186 {
6187 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6188 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6189 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6190
6191 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6192
6193 dest_face = (IDirectDrawSurfaceImpl *)temp;
6194 }
6195 else
6196 {
6197 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6198
6199 dest_face = NULL;
6200 }
6201 }
6202
6203 if (i == 0)
6204 {
6205 /* Native returns error if src faces are not subset of dest faces. */
6206 if (src_face)
6207 {
6208 LeaveCriticalSection(&ddraw_cs);
6209 return DDERR_INVALIDPARAMS;
6210 }
6211 }
6212 }
6213
6214 LeaveCriticalSection(&ddraw_cs);
6215 return D3D_OK;
6216 }
6217 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6218 {
6219 LeaveCriticalSection(&ddraw_cs);
6220 return DDERR_INVALIDPARAMS;
6221 }
6222
6223 /* Handle non cube map textures. */
6224
6225 /* Destination mip levels must be subset of source mip levels. */
6226 if (!is_mip_level_subset(dest, src))
6227 {
6228 LeaveCriticalSection(&ddraw_cs);
6229 return DDERR_INVALIDPARAMS;
6230 }
6231
6232 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6233
6234 LeaveCriticalSection(&ddraw_cs);
6235 return D3D_OK;
6236 }
6237
6238 static HRESULT WINAPI
6239 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6240 IDirectDrawSurface7 *DestTex,
6241 POINT *DestPoint,
6242 IDirectDrawSurface7 *SrcTex,
6243 RECT *SrcRect,
6244 DWORD Flags)
6245 {
6246 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6247 }
6248
6249 static HRESULT WINAPI
6250 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6251 IDirectDrawSurface7 *DestTex,
6252 POINT *DestPoint,
6253 IDirectDrawSurface7 *SrcTex,
6254 RECT *SrcRect,
6255 DWORD Flags)
6256 {
6257 HRESULT hr;
6258 WORD old_fpucw;
6259
6260 old_fpucw = d3d_fpu_setup();
6261 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6262 set_fpu_control_word(old_fpucw);
6263
6264 return hr;
6265 }
6266
6267 /*****************************************************************************
6268 * IDirect3DDevice7::LightEnable
6269 *
6270 * Enables or disables a light
6271 *
6272 * Version 7, IDirect3DLight uses this method too.
6273 *
6274 * Params:
6275 * LightIndex: The index of the light to enable / disable
6276 * Enable: Enable or disable the light
6277 *
6278 * Returns:
6279 * D3D_OK on success
6280 * For more details, see IWineD3DDevice::SetLightEnable
6281 *
6282 *****************************************************************************/
6283 static HRESULT
6284 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6285 DWORD LightIndex,
6286 BOOL Enable)
6287 {
6288 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6289 HRESULT hr;
6290 TRACE("(%p)->(%08x,%d): Relay!\n", This, LightIndex, Enable);
6291
6292 EnterCriticalSection(&ddraw_cs);
6293 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6294 LeaveCriticalSection(&ddraw_cs);
6295 return hr_ddraw_from_wined3d(hr);
6296 }
6297
6298 static HRESULT WINAPI
6299 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6300 DWORD LightIndex,
6301 BOOL Enable)
6302 {
6303 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6304 }
6305
6306 static HRESULT WINAPI
6307 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6308 DWORD LightIndex,
6309 BOOL Enable)
6310 {
6311 HRESULT hr;
6312 WORD old_fpucw;
6313
6314 old_fpucw = d3d_fpu_setup();
6315 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6316 set_fpu_control_word(old_fpucw);
6317
6318 return hr;
6319 }
6320
6321 /*****************************************************************************
6322 * IDirect3DDevice7::GetLightEnable
6323 *
6324 * Retrieves if the light with the given index is enabled or not
6325 *
6326 * Version 7
6327 *
6328 * Params:
6329 * LightIndex: Index of desired light
6330 * Enable: Pointer to a BOOL which contains the result
6331 *
6332 * Returns:
6333 * D3D_OK on success
6334 * DDERR_INVALIDPARAMS if Enable is NULL
6335 * See IWineD3DDevice::GetLightEnable for more details
6336 *
6337 *****************************************************************************/
6338 static HRESULT
6339 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6340 DWORD LightIndex,
6341 BOOL* Enable)
6342 {
6343 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6344 HRESULT hr;
6345 TRACE("(%p)->(%08x,%p): Relay\n", This, LightIndex, Enable);
6346
6347 if(!Enable)
6348 return DDERR_INVALIDPARAMS;
6349
6350 EnterCriticalSection(&ddraw_cs);
6351 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6352 LeaveCriticalSection(&ddraw_cs);
6353 return hr_ddraw_from_wined3d(hr);
6354 }
6355
6356 static HRESULT WINAPI
6357 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6358 DWORD LightIndex,
6359 BOOL* Enable)
6360 {
6361 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6362 }
6363
6364 static HRESULT WINAPI
6365 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6366 DWORD LightIndex,
6367 BOOL* Enable)
6368 {
6369 HRESULT hr;
6370 WORD old_fpucw;
6371
6372 old_fpucw = d3d_fpu_setup();
6373 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6374 set_fpu_control_word(old_fpucw);
6375
6376 return hr;
6377 }
6378
6379 /*****************************************************************************
6380 * IDirect3DDevice7::SetClipPlane
6381 *
6382 * Sets custom clipping plane
6383 *
6384 * Version 7
6385 *
6386 * Params:
6387 * Index: The index of the clipping plane
6388 * PlaneEquation: An equation defining the clipping plane
6389 *
6390 * Returns:
6391 * D3D_OK on success
6392 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6393 * See IWineD3DDevice::SetClipPlane for more details
6394 *
6395 *****************************************************************************/
6396 static HRESULT
6397 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6398 DWORD Index,
6399 D3DVALUE* PlaneEquation)
6400 {
6401 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6402 HRESULT hr;
6403 TRACE("(%p)->(%08x,%p): Relay!\n", This, Index, PlaneEquation);
6404
6405 if(!PlaneEquation)
6406 return DDERR_INVALIDPARAMS;
6407
6408 EnterCriticalSection(&ddraw_cs);
6409 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6410 LeaveCriticalSection(&ddraw_cs);
6411 return hr;
6412 }
6413
6414 static HRESULT WINAPI
6415 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6416 DWORD Index,
6417 D3DVALUE* PlaneEquation)
6418 {
6419 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6420 }
6421
6422 static HRESULT WINAPI
6423 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6424 DWORD Index,
6425 D3DVALUE* PlaneEquation)
6426 {
6427 HRESULT hr;
6428 WORD old_fpucw;
6429
6430 old_fpucw = d3d_fpu_setup();
6431 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6432 set_fpu_control_word(old_fpucw);
6433
6434 return hr;
6435 }
6436
6437 /*****************************************************************************
6438 * IDirect3DDevice7::GetClipPlane
6439 *
6440 * Returns the clipping plane with a specific index
6441 *
6442 * Params:
6443 * Index: The index of the desired plane
6444 * PlaneEquation: Address to store the plane equation to
6445 *
6446 * Returns:
6447 * D3D_OK on success
6448 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6449 * See IWineD3DDevice::GetClipPlane for more details
6450 *
6451 *****************************************************************************/
6452 static HRESULT
6453 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6454 DWORD Index,
6455 D3DVALUE* PlaneEquation)
6456 {
6457 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6458 HRESULT hr;
6459 TRACE("(%p)->(%d,%p): Relay!\n", This, Index, PlaneEquation);
6460
6461 if(!PlaneEquation)
6462 return DDERR_INVALIDPARAMS;
6463
6464 EnterCriticalSection(&ddraw_cs);
6465 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6466 LeaveCriticalSection(&ddraw_cs);
6467 return hr;
6468 }
6469
6470 static HRESULT WINAPI
6471 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6472 DWORD Index,
6473 D3DVALUE* PlaneEquation)
6474 {
6475 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6476 }
6477
6478 static HRESULT WINAPI
6479 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6480 DWORD Index,
6481 D3DVALUE* PlaneEquation)
6482 {
6483 HRESULT hr;
6484 WORD old_fpucw;
6485
6486 old_fpucw = d3d_fpu_setup();
6487 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6488 set_fpu_control_word(old_fpucw);
6489
6490 return hr;
6491 }
6492
6493 /*****************************************************************************
6494 * IDirect3DDevice7::GetInfo
6495 *
6496 * Retrieves some information about the device. The DirectX sdk says that
6497 * this version returns S_FALSE for all retail builds of DirectX, that's what
6498 * this implementation does.
6499 *
6500 * Params:
6501 * DevInfoID: Information type requested
6502 * DevInfoStruct: Pointer to a structure to store the info to
6503 * Size: Size of the structure
6504 *
6505 * Returns:
6506 * S_FALSE, because it's a non-debug driver
6507 *
6508 *****************************************************************************/
6509 static HRESULT WINAPI
6510 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6511 DWORD DevInfoID,
6512 void *DevInfoStruct,
6513 DWORD Size)
6514 {
6515 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6516 TRACE("(%p)->(%08x,%p,%08x)\n", This, DevInfoID, DevInfoStruct, Size);
6517
6518 if (TRACE_ON(d3d7))
6519 {
6520 TRACE(" info requested : ");
6521 switch (DevInfoID)
6522 {
6523 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6524 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6525 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6526 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6527 }
6528 }
6529
6530 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6531 }
6532
6533 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6534 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6535 * are not duplicated.
6536
6537 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6538 * has already been setup for optimal d3d operation.
6539
6540 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6541 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6542 * by Sacrifice (game). */
6543 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
6544 {
6545 /*** IUnknown Methods ***/
6546 IDirect3DDeviceImpl_7_QueryInterface,
6547 IDirect3DDeviceImpl_7_AddRef,
6548 IDirect3DDeviceImpl_7_Release,
6549 /*** IDirect3DDevice7 ***/
6550 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6551 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6552 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6553 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6554 IDirect3DDeviceImpl_7_GetDirect3D,
6555 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6556 IDirect3DDeviceImpl_7_GetRenderTarget,
6557 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6558 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6559 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6560 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6561 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6562 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6563 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6564 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6565 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6566 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6567 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6568 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6569 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6570 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6571 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6572 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6573 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6574 IDirect3DDeviceImpl_7_SetClipStatus,
6575 IDirect3DDeviceImpl_7_GetClipStatus,
6576 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6577 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6578 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6579 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6580 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6581 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6582 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6583 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6584 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6585 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6586 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6587 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6588 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6589 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6590 IDirect3DDeviceImpl_7_Load_FPUSetup,
6591 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6592 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6593 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6594 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6595 IDirect3DDeviceImpl_7_GetInfo
6596 };
6597
6598 const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
6599 {
6600 /*** IUnknown Methods ***/
6601 IDirect3DDeviceImpl_7_QueryInterface,
6602 IDirect3DDeviceImpl_7_AddRef,
6603 IDirect3DDeviceImpl_7_Release,
6604 /*** IDirect3DDevice7 ***/
6605 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6606 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6607 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6608 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6609 IDirect3DDeviceImpl_7_GetDirect3D,
6610 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6611 IDirect3DDeviceImpl_7_GetRenderTarget,
6612 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6613 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6614 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6615 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6616 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6617 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6618 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6619 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6620 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6621 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6622 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6623 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6624 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6625 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6626 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6627 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6628 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6629 IDirect3DDeviceImpl_7_SetClipStatus,
6630 IDirect3DDeviceImpl_7_GetClipStatus,
6631 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6632 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6633 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6634 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6635 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6636 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6637 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6638 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6639 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6640 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6641 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6642 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6643 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6644 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6645 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6646 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6647 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6648 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6649 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6650 IDirect3DDeviceImpl_7_GetInfo
6651 };
6652
6653 const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
6654 {
6655 /*** IUnknown Methods ***/
6656 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6657 Thunk_IDirect3DDeviceImpl_3_AddRef,
6658 Thunk_IDirect3DDeviceImpl_3_Release,
6659 /*** IDirect3DDevice3 ***/
6660 IDirect3DDeviceImpl_3_GetCaps,
6661 IDirect3DDeviceImpl_3_GetStats,
6662 IDirect3DDeviceImpl_3_AddViewport,
6663 IDirect3DDeviceImpl_3_DeleteViewport,
6664 IDirect3DDeviceImpl_3_NextViewport,
6665 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6666 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6667 Thunk_IDirect3DDeviceImpl_3_EndScene,
6668 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6669 IDirect3DDeviceImpl_3_SetCurrentViewport,
6670 IDirect3DDeviceImpl_3_GetCurrentViewport,
6671 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6672 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6673 IDirect3DDeviceImpl_3_Begin,
6674 IDirect3DDeviceImpl_3_BeginIndexed,
6675 IDirect3DDeviceImpl_3_Vertex,
6676 IDirect3DDeviceImpl_3_Index,
6677 IDirect3DDeviceImpl_3_End,
6678 IDirect3DDeviceImpl_3_GetRenderState,
6679 IDirect3DDeviceImpl_3_SetRenderState,
6680 IDirect3DDeviceImpl_3_GetLightState,
6681 IDirect3DDeviceImpl_3_SetLightState,
6682 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6683 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6684 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6685 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6686 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6687 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6688 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6689 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6690 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6691 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6692 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6693 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6694 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6695 IDirect3DDeviceImpl_3_SetTexture,
6696 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6697 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6698 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6699 };
6700
6701 const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
6702 {
6703 /*** IUnknown Methods ***/
6704 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6705 Thunk_IDirect3DDeviceImpl_2_AddRef,
6706 Thunk_IDirect3DDeviceImpl_2_Release,
6707 /*** IDirect3DDevice2 ***/
6708 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6709 IDirect3DDeviceImpl_2_SwapTextureHandles,
6710 Thunk_IDirect3DDeviceImpl_2_GetStats,
6711 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6712 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6713 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6714 IDirect3DDeviceImpl_2_EnumTextureFormats,
6715 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6716 Thunk_IDirect3DDeviceImpl_2_EndScene,
6717 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6718 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6719 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6720 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6721 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6722 Thunk_IDirect3DDeviceImpl_2_Begin,
6723 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6724 Thunk_IDirect3DDeviceImpl_2_Vertex,
6725 Thunk_IDirect3DDeviceImpl_2_Index,
6726 Thunk_IDirect3DDeviceImpl_2_End,
6727 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6728 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6729 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6730 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6731 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6732 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6733 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6734 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6735 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6736 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6737 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6738 };
6739
6740 const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
6741 {
6742 /*** IUnknown Methods ***/
6743 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6744 Thunk_IDirect3DDeviceImpl_1_AddRef,
6745 Thunk_IDirect3DDeviceImpl_1_Release,
6746 /*** IDirect3DDevice1 ***/
6747 IDirect3DDeviceImpl_1_Initialize,
6748 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6749 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6750 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6751 Thunk_IDirect3DDeviceImpl_1_GetStats,
6752 IDirect3DDeviceImpl_1_Execute,
6753 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6754 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6755 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6756 IDirect3DDeviceImpl_1_Pick,
6757 IDirect3DDeviceImpl_1_GetPickRecords,
6758 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6759 IDirect3DDeviceImpl_1_CreateMatrix,
6760 IDirect3DDeviceImpl_1_SetMatrix,
6761 IDirect3DDeviceImpl_1_GetMatrix,
6762 IDirect3DDeviceImpl_1_DeleteMatrix,
6763 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6764 Thunk_IDirect3DDeviceImpl_1_EndScene,
6765 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6766 };
6767
6768 /*****************************************************************************
6769 * IDirect3DDeviceImpl_CreateHandle
6770 *
6771 * Not called from the VTable
6772 *
6773 * Some older interface versions operate with handles, which are basically
6774 * DWORDs which identify an interface, for example
6775 * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE
6776 *
6777 * Those handle could be just casts to the interface pointers or vice versa,
6778 * but that is not 64 bit safe and would mean blindly derefering a DWORD
6779 * passed by the app. Instead there is a dynamic array in the device which
6780 * keeps a DWORD to pointer information and a type for the handle.
6781 *
6782 * Basically this array only grows, when a handle is freed its pointer is
6783 * just set to NULL. There will be much more reads from the array than
6784 * insertion operations, so a dynamic array is fine.
6785 *
6786 * Params:
6787 * This: D3DDevice implementation for which this handle should be created
6788 *
6789 * Returns:
6790 * A free handle on success
6791 * 0 on failure
6792 *
6793 *****************************************************************************/
6794 DWORD
6795 IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This)
6796 {
6797 DWORD i;
6798 struct HandleEntry *oldHandles = This->Handles;
6799
6800 TRACE("(%p)\n", This);
6801
6802 for(i = 0; i < This->numHandles; i++)
6803 {
6804 if(This->Handles[i].ptr == NULL &&
6805 This->Handles[i].type == DDrawHandle_Unknown)
6806 {
6807 TRACE("Reusing freed handle %d\n", i + 1);
6808 return i + 1;
6809 }
6810 }
6811
6812 TRACE("Growing the handle array\n");
6813
6814 This->numHandles++;
6815 This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles);
6816 if(!This->Handles)
6817 {
6818 ERR("Out of memory\n");
6819 This->Handles = oldHandles;
6820 This->numHandles--;
6821 return 0;
6822 }
6823 if(oldHandles)
6824 {
6825 memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry));
6826 HeapFree(GetProcessHeap(), 0, oldHandles);
6827 }
6828
6829 TRACE("Returning %d\n", This->numHandles);
6830 return This->numHandles;
6831 }
6832
6833 /*****************************************************************************
6834 * IDirect3DDeviceImpl_UpdateDepthStencil
6835 *
6836 * Checks the current render target for attached depth stencils and sets the
6837 * WineD3D depth stencil accordingly.
6838 *
6839 * Returns:
6840 * The depth stencil state to set if creating the device
6841 *
6842 *****************************************************************************/
6843 WINED3DZBUFFERTYPE
6844 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6845 {
6846 IDirectDrawSurface7 *depthStencil = NULL;
6847 IDirectDrawSurfaceImpl *dsi;
6848 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6849
6850 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6851 if(!depthStencil)
6852 {
6853 TRACE("Setting wined3d depth stencil to NULL\n");
6854 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6855 NULL);
6856 return WINED3DZB_FALSE;
6857 }
6858
6859 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6860 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6861 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6862 dsi->WineD3DSurface);
6863
6864 IDirectDrawSurface7_Release(depthStencil);
6865 return WINED3DZB_TRUE;
6866 }