2 * Copyright (c) 1998 Lionel ULMER
3 * Copyright (c) 2006-2007 Stefan DÖSINGER
5 * This file contains the implementation of Direct3DViewport2.
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.
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.
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
23 #include "wine/port.h"
31 #define NONAMELESSUNION
37 #include "wine/exception.h"
42 #include "ddraw_private.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(d3d7
);
47 /*****************************************************************************
49 *****************************************************************************/
51 /*****************************************************************************
54 * activates the viewport using IDirect3DDevice7::SetViewport
56 *****************************************************************************/
57 void viewport_activate(IDirect3DViewportImpl
* This
, BOOL ignore_lights
) {
58 IDirect3DLightImpl
* light
;
62 /* Activate all the lights associated with this context */
65 while (light
!= NULL
) {
66 light
->activate(light
);
71 /* And copy the values in the structure used by the device */
73 vp
.dwX
= This
->viewports
.vp2
.dwX
;
74 vp
.dwY
= This
->viewports
.vp2
.dwY
;
75 vp
.dwHeight
= This
->viewports
.vp2
.dwHeight
;
76 vp
.dwWidth
= This
->viewports
.vp2
.dwWidth
;
77 vp
.dvMinZ
= This
->viewports
.vp2
.dvMinZ
;
78 vp
.dvMaxZ
= This
->viewports
.vp2
.dvMaxZ
;
80 vp
.dwX
= This
->viewports
.vp1
.dwX
;
81 vp
.dwY
= This
->viewports
.vp1
.dwY
;
82 vp
.dwHeight
= This
->viewports
.vp1
.dwHeight
;
83 vp
.dwWidth
= This
->viewports
.vp1
.dwWidth
;
84 vp
.dvMinZ
= This
->viewports
.vp1
.dvMinZ
;
85 vp
.dvMaxZ
= This
->viewports
.vp1
.dvMaxZ
;
88 /* And also set the viewport */
89 IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice7
), &vp
);
92 /*****************************************************************************
93 * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2
95 * Writes viewport information to TRACE
97 *****************************************************************************/
98 static void _dump_D3DVIEWPORT(const D3DVIEWPORT
*lpvp
)
100 TRACE(" - dwSize = %d dwX = %d dwY = %d\n",
101 lpvp
->dwSize
, lpvp
->dwX
, lpvp
->dwY
);
102 TRACE(" - dwWidth = %d dwHeight = %d\n",
103 lpvp
->dwWidth
, lpvp
->dwHeight
);
104 TRACE(" - dvScaleX = %f dvScaleY = %f\n",
105 lpvp
->dvScaleX
, lpvp
->dvScaleY
);
106 TRACE(" - dvMaxX = %f dvMaxY = %f\n",
107 lpvp
->dvMaxX
, lpvp
->dvMaxY
);
108 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
109 lpvp
->dvMinZ
, lpvp
->dvMaxZ
);
112 static void _dump_D3DVIEWPORT2(const D3DVIEWPORT2
*lpvp
)
114 TRACE(" - dwSize = %d dwX = %d dwY = %d\n",
115 lpvp
->dwSize
, lpvp
->dwX
, lpvp
->dwY
);
116 TRACE(" - dwWidth = %d dwHeight = %d\n",
117 lpvp
->dwWidth
, lpvp
->dwHeight
);
118 TRACE(" - dvClipX = %f dvClipY = %f\n",
119 lpvp
->dvClipX
, lpvp
->dvClipY
);
120 TRACE(" - dvClipWidth = %f dvClipHeight = %f\n",
121 lpvp
->dvClipWidth
, lpvp
->dvClipHeight
);
122 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
123 lpvp
->dvMinZ
, lpvp
->dvMaxZ
);
126 /*****************************************************************************
128 *****************************************************************************/
130 /*****************************************************************************
131 * IDirect3DViewport3::QueryInterface
133 * A normal QueryInterface. Can query all interface versions and the
134 * IUnknown interface. The VTables of the different versions
138 * refiid: Interface id queried for
139 * obj: Address to write the interface pointer to
143 * E_NOINTERFACE if the requested interface wasn't found
145 *****************************************************************************/
146 static HRESULT WINAPI
147 IDirect3DViewportImpl_QueryInterface(IDirect3DViewport3
*iface
,
151 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
152 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), obp
);
156 if ( IsEqualGUID(&IID_IUnknown
, riid
) ||
157 IsEqualGUID(&IID_IDirect3DViewport
, riid
) ||
158 IsEqualGUID(&IID_IDirect3DViewport2
, riid
) ||
159 IsEqualGUID(&IID_IDirect3DViewport3
, riid
) ) {
160 IDirect3DViewport3_AddRef(ICOM_INTERFACE(This
, IDirect3DViewport3
));
161 *obp
= ICOM_INTERFACE(This
, IDirect3DViewport3
);
162 TRACE(" Creating IDirect3DViewport1/2/3 interface %p\n", *obp
);
165 FIXME("(%p): interface for IID %s NOT found!\n", This
, debugstr_guid(riid
));
166 return E_NOINTERFACE
;
169 /*****************************************************************************
170 * IDirect3DViewport3::AddRef
172 * Increases the refcount.
177 *****************************************************************************/
179 IDirect3DViewportImpl_AddRef(IDirect3DViewport3
*iface
)
181 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
182 ULONG ref
= InterlockedIncrement(&This
->ref
);
184 TRACE("(%p)->() incrementing from %u.\n", This
, ref
- 1);
189 /*****************************************************************************
190 * IDirect3DViewport3::Release
192 * Reduces the refcount. If it falls to 0, the interface is released
197 *****************************************************************************/
199 IDirect3DViewportImpl_Release(IDirect3DViewport3
*iface
)
201 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
202 ULONG ref
= InterlockedDecrement(&This
->ref
);
204 TRACE("(%p)->() decrementing from %u.\n", This
, ref
+ 1);
207 HeapFree(GetProcessHeap(), 0, This
);
213 /*****************************************************************************
214 * IDirect3DViewport Methods.
215 *****************************************************************************/
217 /*****************************************************************************
218 * IDirect3DViewport3::Initialize
220 * No-op initialization.
223 * Direct3D: The direct3D device this viewport is assigned to
226 * DDERR_ALREADYINITIALIZED
228 *****************************************************************************/
229 static HRESULT WINAPI
230 IDirect3DViewportImpl_Initialize(IDirect3DViewport3
*iface
,
233 TRACE("(%p)->(%p) no-op...\n", iface
, Direct3D
);
234 return DDERR_ALREADYINITIALIZED
;
237 /*****************************************************************************
238 * IDirect3DViewport3::GetViewport
240 * Returns the viewport data assigned to this viewport interface
243 * Data: Address to store the data
247 * DDERR_INVALIDPARAMS if Data is NULL
249 *****************************************************************************/
250 static HRESULT WINAPI
251 IDirect3DViewportImpl_GetViewport(IDirect3DViewport3
*iface
,
254 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
256 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
258 EnterCriticalSection(&ddraw_cs
);
259 if (This
->use_vp2
!= 0) {
260 ERR(" Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
261 LeaveCriticalSection(&ddraw_cs
);
262 return DDERR_INVALIDPARAMS
;
264 dwSize
= lpData
->dwSize
;
265 memset(lpData
, 0, dwSize
);
266 memcpy(lpData
, &(This
->viewports
.vp1
), dwSize
);
268 if (TRACE_ON(d3d7
)) {
269 TRACE(" returning D3DVIEWPORT :\n");
270 _dump_D3DVIEWPORT(lpData
);
272 LeaveCriticalSection(&ddraw_cs
);
277 /*****************************************************************************
278 * IDirect3DViewport3::SetViewport
280 * Sets the viewport information for this interface
283 * lpData: Viewport to set
287 * DDERR_INVALIDPARAMS if Data is NULL
289 *****************************************************************************/
290 static HRESULT WINAPI
291 IDirect3DViewportImpl_SetViewport(IDirect3DViewport3
*iface
,
294 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
295 LPDIRECT3DVIEWPORT3 current_viewport
;
296 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
298 if (TRACE_ON(d3d7
)) {
299 TRACE(" getting D3DVIEWPORT :\n");
300 _dump_D3DVIEWPORT(lpData
);
303 EnterCriticalSection(&ddraw_cs
);
305 memset(&(This
->viewports
.vp1
), 0, sizeof(This
->viewports
.vp1
));
306 memcpy(&(This
->viewports
.vp1
), lpData
, lpData
->dwSize
);
308 /* Tests on two games show that these values are never used properly so override
309 them with proper ones :-)
311 This
->viewports
.vp1
.dvMinZ
= 0.0;
312 This
->viewports
.vp1
.dvMaxZ
= 1.0;
314 if (This
->active_device
) {
315 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice3
), ¤t_viewport
);
316 if (current_viewport
) {
317 if (ICOM_OBJECT(IDirect3DViewportImpl
, IDirect3DViewport3
, current_viewport
) == This
)
318 This
->activate(This
, FALSE
);
319 IDirect3DViewport3_Release(current_viewport
);
322 LeaveCriticalSection(&ddraw_cs
);
327 /*****************************************************************************
328 * IDirect3DViewport3::TransformVertices
330 * Transforms vertices by the transformation matrix.
332 * This function is pretty similar to IDirect3DVertexBuffer7::ProcessVertices,
333 * so it's tempting to forward it to there. However, there are some
334 * tiny differences. First, the lpOffscreen flag that is reported back,
335 * then there is the homogeneous vertex that is generated. Also there's a lack
336 * of FVFs, but still a custom stride. Last, the d3d1 - d3d3 viewport has some
337 * settings (scale) that d3d7 and wined3d do not have. All in all wrapping to
338 * ProcessVertices doesn't pay of in terms of wrapper code needed and code
342 * dwVertexCount: The number of vertices to be transformed
343 * lpData: Pointer to the vertex data
344 * dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED
345 * lpOffScreen: Set to the clipping plane clipping the vertex, if only one
346 * vertex is transformed and clipping is on. 0 otherwise
350 * D3DERR_VIEWPORTHASNODEVICE if the viewport is not assigned to a device
351 * DDERR_INVALIDPARAMS if no clipping flag is specified
353 *****************************************************************************/
354 static HRESULT WINAPI
355 IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3
*iface
,
357 D3DTRANSFORMDATA
*lpData
,
361 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
362 D3DMATRIX view_mat
, world_mat
, proj_mat
, mat
;
367 D3DVIEWPORT vp
= This
->viewports
.vp1
;
369 TRACE("(%p)->(%08x,%p,%08x,%p)\n", This
, dwVertexCount
, lpData
, dwFlags
, lpOffScreen
);
371 /* Tests on windows show that Windows crashes when this occurs,
372 * so don't return the (intuitive) return value
373 if(!This->active_device)
375 WARN("No device active, returning D3DERR_VIEWPORTHASNODEVICE\n");
376 return D3DERR_VIEWPORTHASNODEVICE;
380 if(!(dwFlags
& (D3DTRANSFORM_UNCLIPPED
| D3DTRANSFORM_CLIPPED
)))
382 WARN("No clipping flag passed, returning DDERR_INVALIDPARAMS\n");
383 return DDERR_INVALIDPARAMS
;
387 EnterCriticalSection(&ddraw_cs
);
388 IWineD3DDevice_GetTransform(This
->active_device
->wineD3DDevice
,
389 D3DTRANSFORMSTATE_VIEW
,
390 (WINED3DMATRIX
*) &view_mat
);
392 IWineD3DDevice_GetTransform(This
->active_device
->wineD3DDevice
,
393 D3DTRANSFORMSTATE_PROJECTION
,
394 (WINED3DMATRIX
*) &proj_mat
);
396 IWineD3DDevice_GetTransform(This
->active_device
->wineD3DDevice
,
397 WINED3DTS_WORLDMATRIX(0),
398 (WINED3DMATRIX
*) &world_mat
);
399 multiply_matrix(&mat
,&view_mat
,&world_mat
);
400 multiply_matrix(&mat
,&proj_mat
,&mat
);
402 in
= (float *) lpData
->lpIn
;
403 out
= (float *) lpData
->lpOut
;
404 outH
= lpData
->lpHOut
;
405 for(i
= 0; i
< dwVertexCount
; i
++)
407 x
= (in
[0] * mat
._11
) + (in
[1] * mat
._21
) + (in
[2] * mat
._31
) + (1.0 * mat
._41
);
408 y
= (in
[0] * mat
._12
) + (in
[1] * mat
._22
) + (in
[2] * mat
._32
) + (1.0 * mat
._42
);
409 z
= (in
[0] * mat
._13
) + (in
[1] * mat
._23
) + (in
[2] * mat
._33
) + (1.0 * mat
._43
);
410 w
= (in
[0] * mat
._14
) + (in
[1] * mat
._24
) + (in
[2] * mat
._34
) + (1.0 * mat
._44
);
412 if(dwFlags
& D3DTRANSFORM_CLIPPED
)
414 /* If clipping is enabled, Windows assumes that outH is
417 outH
[i
].u1
.hx
= x
; outH
[i
].u2
.hy
= y
; outH
[i
].u3
.hz
= z
;
420 if(x
* vp
.dvScaleX
> ((float) vp
.dwWidth
* 0.5))
421 outH
[i
].dwFlags
|= D3DCLIP_RIGHT
;
422 if(x
* vp
.dvScaleX
<= -((float) vp
.dwWidth
) * 0.5)
423 outH
[i
].dwFlags
|= D3DCLIP_LEFT
;
424 if(y
* vp
.dvScaleY
> ((float) vp
.dwHeight
* 0.5))
425 outH
[i
].dwFlags
|= D3DCLIP_TOP
;
426 if(y
* vp
.dvScaleY
<= -((float) vp
.dwHeight
) * 0.5)
427 outH
[i
].dwFlags
|= D3DCLIP_BOTTOM
;
429 outH
[i
].dwFlags
|= D3DCLIP_FRONT
;
431 outH
[i
].dwFlags
|= D3DCLIP_BACK
;
435 /* Looks like native just drops the vertex, leaves whatever data
436 * it has in the output buffer and goes on with the next vertex.
437 * The exact scheme hasn't been figured out yet, but windows
438 * definitely writes something there.
444 in
= (float *) ((char *) in
+ lpData
->dwInSize
);
445 out
= (float *) ((char *) out
+ lpData
->dwOutSize
);
451 x
*= w
; y
*= w
; z
*= w
;
453 out
[0] = vp
.dwWidth
/ 2 + vp
.dwX
+ x
* vp
.dvScaleX
;
454 out
[1] = vp
.dwHeight
/ 2 + vp
.dwY
- y
* vp
.dvScaleY
;
457 in
= (float *) ((char *) in
+ lpData
->dwInSize
);
458 out
= (float *) ((char *) out
+ lpData
->dwOutSize
);
461 /* According to the d3d test, the offscreen flag is set only
462 * if exactly one vertex is transformed. Its not documented,
463 * but the test shows that the lpOffscreen flag is set to the
464 * flag combination of clipping planes that clips the vertex.
466 * If clipping is requested, Windows assumes that the offscreen
467 * param is a valid pointer.
469 if(dwVertexCount
== 1 && dwFlags
& D3DTRANSFORM_CLIPPED
)
471 *lpOffScreen
= outH
[0].dwFlags
;
473 else if(*lpOffScreen
)
477 LeaveCriticalSection(&ddraw_cs
);
483 /*****************************************************************************
484 * IDirect3DViewport3::LightElements
486 * The DirectX 5.0 sdk says that it's not implemented
494 *****************************************************************************/
495 static HRESULT WINAPI
496 IDirect3DViewportImpl_LightElements(IDirect3DViewport3
*iface
,
497 DWORD dwElementCount
,
498 LPD3DLIGHTDATA lpData
)
500 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
501 TRACE("(%p)->(%08x,%p): Unimplemented!\n", This
, dwElementCount
, lpData
);
502 return DDERR_UNSUPPORTED
;
505 /*****************************************************************************
506 * IDirect3DViewport3::SetBackground
508 * Sets tje background material
511 * hMat: Handle from a IDirect3DMaterial interface
516 *****************************************************************************/
517 static HRESULT WINAPI
518 IDirect3DViewportImpl_SetBackground(IDirect3DViewport3
*iface
,
519 D3DMATERIALHANDLE hMat
)
521 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
522 TRACE("(%p)->(%d)\n", This
, hMat
);
524 EnterCriticalSection(&ddraw_cs
);
525 if(hMat
&& hMat
> This
->ddraw
->d3ddevice
->numHandles
)
527 WARN("Specified Handle %d out of range\n", hMat
);
528 LeaveCriticalSection(&ddraw_cs
);
529 return DDERR_INVALIDPARAMS
;
531 else if(hMat
&& This
->ddraw
->d3ddevice
->Handles
[hMat
- 1].type
!= DDrawHandle_Material
)
533 WARN("Handle %d is not a material handle\n", hMat
);
534 LeaveCriticalSection(&ddraw_cs
);
535 return DDERR_INVALIDPARAMS
;
540 This
->background
= (IDirect3DMaterialImpl
*) This
->ddraw
->d3ddevice
->Handles
[hMat
- 1].ptr
;
541 TRACE(" setting background color : %f %f %f %f\n",
542 This
->background
->mat
.u
.diffuse
.u1
.r
,
543 This
->background
->mat
.u
.diffuse
.u2
.g
,
544 This
->background
->mat
.u
.diffuse
.u3
.b
,
545 This
->background
->mat
.u
.diffuse
.u4
.a
);
549 This
->background
= NULL
;
550 TRACE("Setting background to NULL\n");
553 LeaveCriticalSection(&ddraw_cs
);
557 /*****************************************************************************
558 * IDirect3DViewport3::GetBackground
560 * Returns the material handle assigned to the background of the viewport
563 * lphMat: Address to store the handle
564 * lpValid: is set to FALSE if no background is set, TRUE if one is set
569 *****************************************************************************/
570 static HRESULT WINAPI
571 IDirect3DViewportImpl_GetBackground(IDirect3DViewport3
*iface
,
572 D3DMATERIALHANDLE
*lphMat
,
575 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
576 TRACE("(%p)->(%p,%p)\n", This
, lphMat
, lpValid
);
578 EnterCriticalSection(&ddraw_cs
);
581 *lpValid
= This
->background
!= NULL
;
587 *lphMat
= This
->background
->Handle
;
594 LeaveCriticalSection(&ddraw_cs
);
599 /*****************************************************************************
600 * IDirect3DViewport3::SetBackgroundDepth
602 * Sets a surface that represents the background depth. It's contents are
603 * used to set the depth buffer in IDirect3DViewport3::Clear
606 * lpDDSurface: Surface to set
608 * Returns: D3D_OK, because it's a stub
610 *****************************************************************************/
611 static HRESULT WINAPI
612 IDirect3DViewportImpl_SetBackgroundDepth(IDirect3DViewport3
*iface
,
613 IDirectDrawSurface
*lpDDSurface
)
615 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
616 FIXME("(%p)->(%p): stub!\n", This
, lpDDSurface
);
620 /*****************************************************************************
621 * IDirect3DViewport3::GetBackgroundDepth
623 * Returns the surface that represents the depth field
626 * lplpDDSurface: Address to store the interface pointer
627 * lpValid: Set to TRUE if a depth is assigned, FALSE otherwise
630 * D3D_OK, because it's a stub
631 * (DDERR_INVALIDPARAMS if DDSurface of Valid is NULL)
633 *****************************************************************************/
634 static HRESULT WINAPI
635 IDirect3DViewportImpl_GetBackgroundDepth(IDirect3DViewport3
*iface
,
636 IDirectDrawSurface
**lplpDDSurface
,
639 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
640 FIXME("(%p)->(%p,%p): stub!\n", This
, lplpDDSurface
, lpValid
);
644 /*****************************************************************************
645 * IDirect3DViewport3::Clear
647 * Clears the render target and / or the z buffer
650 * dwCount: The amount of rectangles to clear. If 0, the whole buffer is
652 * lpRects: Pointer to the array of rectangles. If NULL, Count must be 0
653 * dwFlags: D3DCLEAR_ZBUFFER and / or D3DCLEAR_TARGET
657 * D3DERR_VIEWPORTHASNODEVICE if there's no active device
658 * The return value of IDirect3DDevice7::Clear
660 *****************************************************************************/
661 static HRESULT WINAPI
662 IDirect3DViewportImpl_Clear(IDirect3DViewport3
*iface
,
667 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
668 DWORD color
= 0x00000000;
670 LPDIRECT3DVIEWPORT3 current_viewport
;
672 TRACE("(%p/%p)->(%08x,%p,%08x)\n", This
, iface
, dwCount
, lpRects
, dwFlags
);
673 if (This
->active_device
== NULL
) {
674 ERR(" Trying to clear a viewport not attached to a device !\n");
675 return D3DERR_VIEWPORTHASNODEVICE
;
678 EnterCriticalSection(&ddraw_cs
);
679 if (dwFlags
& D3DCLEAR_TARGET
) {
680 if (This
->background
== NULL
) {
681 ERR(" Trying to clear the color buffer without background material !\n");
684 ((int) ((This
->background
->mat
.u
.diffuse
.u1
.r
) * 255) << 16) |
685 ((int) ((This
->background
->mat
.u
.diffuse
.u2
.g
) * 255) << 8) |
686 ((int) ((This
->background
->mat
.u
.diffuse
.u3
.b
) * 255) << 0) |
687 ((int) ((This
->background
->mat
.u
.diffuse
.u4
.a
) * 255) << 24);
691 /* Need to temporarily activate viewport to clear it. Previously active one will be restored
693 This
->activate(This
, TRUE
);
695 hr
= IDirect3DDevice7_Clear(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice7
),
698 dwFlags
& (D3DCLEAR_ZBUFFER
| D3DCLEAR_TARGET
),
703 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice3
), ¤t_viewport
);
704 if(current_viewport
) {
705 IDirect3DViewportImpl
*vp
= ICOM_OBJECT(IDirect3DViewportImpl
, IDirect3DViewport3
, current_viewport
);
706 vp
->activate(vp
, TRUE
);
707 IDirect3DViewport3_Release(current_viewport
);
710 LeaveCriticalSection(&ddraw_cs
);
714 /*****************************************************************************
715 * IDirect3DViewport3::AddLight
717 * Adds an light to the viewport
720 * lpDirect3DLight: Interface of the light to add
724 * DDERR_INVALIDPARAMS if Direct3DLight is NULL
725 * DDERR_INVALIDPARAMS if there are 8 lights or more
727 *****************************************************************************/
728 static HRESULT WINAPI
729 IDirect3DViewportImpl_AddLight(IDirect3DViewport3
*iface
,
730 IDirect3DLight
*lpDirect3DLight
)
732 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
733 IDirect3DLightImpl
*lpDirect3DLightImpl
= ICOM_OBJECT(IDirect3DLightImpl
, IDirect3DLight
, lpDirect3DLight
);
735 DWORD map
= This
->map_lights
;
737 TRACE("(%p)->(%p)\n", This
, lpDirect3DLight
);
739 EnterCriticalSection(&ddraw_cs
);
740 if (This
->num_lights
>= 8)
742 LeaveCriticalSection(&ddraw_cs
);
743 return DDERR_INVALIDPARAMS
;
746 /* Find a light number and update both light and viewports objects accordingly */
751 lpDirect3DLightImpl
->dwLightIndex
= i
;
753 This
->map_lights
|= 1<<i
;
755 /* Add the light in the 'linked' chain */
756 lpDirect3DLightImpl
->next
= This
->lights
;
757 This
->lights
= lpDirect3DLightImpl
;
759 /* Attach the light to the viewport */
760 lpDirect3DLightImpl
->active_viewport
= This
;
762 /* If active, activate the light */
763 if (This
->active_device
!= NULL
) {
764 lpDirect3DLightImpl
->activate(lpDirect3DLightImpl
);
767 LeaveCriticalSection(&ddraw_cs
);
771 /*****************************************************************************
772 * IDirect3DViewport3::DeleteLight
774 * Deletes a light from the viewports' light list
777 * lpDirect3DLight: Light to delete
781 * DDERR_INVALIDPARAMS if the light wasn't found
783 *****************************************************************************/
784 static HRESULT WINAPI
785 IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3
*iface
,
786 IDirect3DLight
*lpDirect3DLight
)
788 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
789 IDirect3DLightImpl
*lpDirect3DLightImpl
= ICOM_OBJECT(IDirect3DLightImpl
, IDirect3DLight
, lpDirect3DLight
);
790 IDirect3DLightImpl
*cur_light
, *prev_light
= NULL
;
792 TRACE("(%p)->(%p)\n", This
, lpDirect3DLight
);
794 EnterCriticalSection(&ddraw_cs
);
795 cur_light
= This
->lights
;
796 while (cur_light
!= NULL
) {
797 if (cur_light
== lpDirect3DLightImpl
) {
798 lpDirect3DLightImpl
->desactivate(lpDirect3DLightImpl
);
799 if (prev_light
== NULL
) This
->lights
= cur_light
->next
;
800 else prev_light
->next
= cur_light
->next
;
801 /* Detach the light to the viewport */
802 cur_light
->active_viewport
= NULL
;
804 This
->map_lights
&= ~(1<<lpDirect3DLightImpl
->dwLightIndex
);
805 LeaveCriticalSection(&ddraw_cs
);
808 prev_light
= cur_light
;
809 cur_light
= cur_light
->next
;
811 LeaveCriticalSection(&ddraw_cs
);
813 return DDERR_INVALIDPARAMS
;
816 /*****************************************************************************
817 * IDirect3DViewport::NextLight
819 * Enumerates the lights associated with the viewport
822 * lpDirect3DLight: Light to start with
823 * lplpDirect3DLight: Address to store the successor to
826 * D3D_OK, because it's a stub
828 *****************************************************************************/
829 static HRESULT WINAPI
830 IDirect3DViewportImpl_NextLight(IDirect3DViewport3
*iface
,
831 IDirect3DLight
*lpDirect3DLight
,
832 IDirect3DLight
**lplpDirect3DLight
,
835 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
836 FIXME("(%p)->(%p,%p,%08x): stub!\n", This
, lpDirect3DLight
, lplpDirect3DLight
, dwFlags
);
840 /*****************************************************************************
841 * IDirect3DViewport2 Methods.
842 *****************************************************************************/
844 /*****************************************************************************
845 * IDirect3DViewport3::GetViewport2
847 * Returns the currently set viewport in a D3DVIEWPORT2 structure.
848 * Similar to IDirect3DViewport3::GetViewport
851 * lpData: Pointer to the structure to fill
855 * DDERR_INVALIDPARAMS if the viewport was set with
856 * IDirect3DViewport3::SetViewport
857 * DDERR_INVALIDPARAMS if Data is NULL
859 *****************************************************************************/
860 static HRESULT WINAPI
861 IDirect3DViewportImpl_GetViewport2(IDirect3DViewport3
*iface
,
862 D3DVIEWPORT2
*lpData
)
864 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
866 TRACE("(%p)->(%p)\n", This
, lpData
);
868 EnterCriticalSection(&ddraw_cs
);
869 if (This
->use_vp2
!= 1) {
870 ERR(" Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
871 LeaveCriticalSection(&ddraw_cs
);
872 return DDERR_INVALIDPARAMS
;
874 dwSize
= lpData
->dwSize
;
875 memset(lpData
, 0, dwSize
);
876 memcpy(lpData
, &(This
->viewports
.vp2
), dwSize
);
878 if (TRACE_ON(d3d7
)) {
879 TRACE(" returning D3DVIEWPORT2 :\n");
880 _dump_D3DVIEWPORT2(lpData
);
883 LeaveCriticalSection(&ddraw_cs
);
887 /*****************************************************************************
888 * IDirect3DViewport3::SetViewport2
890 * Sets the viewport from a D3DVIEWPORT2 structure
893 * lpData: Viewport to set
898 *****************************************************************************/
899 static HRESULT WINAPI
900 IDirect3DViewportImpl_SetViewport2(IDirect3DViewport3
*iface
,
901 D3DVIEWPORT2
*lpData
)
903 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
904 LPDIRECT3DVIEWPORT3 current_viewport
;
905 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
907 if (TRACE_ON(d3d7
)) {
908 TRACE(" getting D3DVIEWPORT2 :\n");
909 _dump_D3DVIEWPORT2(lpData
);
912 EnterCriticalSection(&ddraw_cs
);
914 memset(&(This
->viewports
.vp2
), 0, sizeof(This
->viewports
.vp2
));
915 memcpy(&(This
->viewports
.vp2
), lpData
, lpData
->dwSize
);
917 if (This
->active_device
) {
918 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice3
), ¤t_viewport
);
919 if (current_viewport
) {
920 if (ICOM_OBJECT(IDirect3DViewportImpl
, IDirect3DViewport3
, current_viewport
) == This
)
921 This
->activate(This
, FALSE
);
922 IDirect3DViewport3_Release(current_viewport
);
925 LeaveCriticalSection(&ddraw_cs
);
930 /*****************************************************************************
931 * IDirect3DViewport3 Methods.
932 *****************************************************************************/
934 /*****************************************************************************
935 * IDirect3DViewport3::SetBackgroundDepth2
937 * Sets a IDirectDrawSurface4 surface as the background depth surface
940 * lpDDS: Surface to set
943 * D3D_OK, because it's stub
945 *****************************************************************************/
946 static HRESULT WINAPI
947 IDirect3DViewportImpl_SetBackgroundDepth2(IDirect3DViewport3
*iface
,
948 IDirectDrawSurface4
*lpDDS
)
950 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
951 FIXME("(%p)->(%p): stub!\n", This
, lpDDS
);
955 /*****************************************************************************
956 * IDirect3DViewport3::GetBackgroundDepth2
958 * Returns the IDirect3DSurface4 interface to the background depth surface
961 * lplpDDS: Address to store the interface pointer at
962 * lpValid: Set to true if a surface is assigned
965 * D3D_OK because it's a stub
967 *****************************************************************************/
968 static HRESULT WINAPI
969 IDirect3DViewportImpl_GetBackgroundDepth2(IDirect3DViewport3
*iface
,
970 IDirectDrawSurface4
**lplpDDS
,
973 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
974 FIXME("(%p/%p)->(%p,%p): stub!\n", This
, iface
, lplpDDS
, lpValid
);
978 /*****************************************************************************
979 * IDirect3DViewport3::Clear2
981 * Another clearing method
984 * Count: Number of rectangles to clear
985 * Rects: Rectangle array to clear
986 * Flags: Some flags :)
987 * Color: Color to fill the render target with
988 * Z: Value to fill the depth buffer with
989 * Stencil: Value to fill the stencil bits with
993 *****************************************************************************/
994 static HRESULT WINAPI
995 IDirect3DViewportImpl_Clear2(IDirect3DViewport3
*iface
,
1003 ICOM_THIS_FROM(IDirect3DViewportImpl
, IDirect3DViewport3
, iface
);
1005 LPDIRECT3DVIEWPORT3 current_viewport
;
1006 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x)\n", This
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
1008 EnterCriticalSection(&ddraw_cs
);
1009 if (This
->active_device
== NULL
) {
1010 ERR(" Trying to clear a viewport not attached to a device !\n");
1011 LeaveCriticalSection(&ddraw_cs
);
1012 return D3DERR_VIEWPORTHASNODEVICE
;
1014 /* Need to temporarily activate viewport to clear it. Previously active one will be restored
1016 This
->activate(This
, TRUE
);
1018 hr
= IDirect3DDevice7_Clear(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice7
),
1025 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This
->active_device
, IDirect3DDevice3
), ¤t_viewport
);
1026 if(current_viewport
) {
1027 IDirect3DViewportImpl
*vp
= ICOM_OBJECT(IDirect3DViewportImpl
, IDirect3DViewport3
, current_viewport
);
1028 vp
->activate(vp
, TRUE
);
1029 IDirect3DViewport3_Release(current_viewport
);
1031 LeaveCriticalSection(&ddraw_cs
);
1035 /*****************************************************************************
1037 *****************************************************************************/
1039 const IDirect3DViewport3Vtbl IDirect3DViewport3_Vtbl
=
1041 /*** IUnknown Methods ***/
1042 IDirect3DViewportImpl_QueryInterface
,
1043 IDirect3DViewportImpl_AddRef
,
1044 IDirect3DViewportImpl_Release
,
1045 /*** IDirect3DViewport Methods */
1046 IDirect3DViewportImpl_Initialize
,
1047 IDirect3DViewportImpl_GetViewport
,
1048 IDirect3DViewportImpl_SetViewport
,
1049 IDirect3DViewportImpl_TransformVertices
,
1050 IDirect3DViewportImpl_LightElements
,
1051 IDirect3DViewportImpl_SetBackground
,
1052 IDirect3DViewportImpl_GetBackground
,
1053 IDirect3DViewportImpl_SetBackgroundDepth
,
1054 IDirect3DViewportImpl_GetBackgroundDepth
,
1055 IDirect3DViewportImpl_Clear
,
1056 IDirect3DViewportImpl_AddLight
,
1057 IDirect3DViewportImpl_DeleteLight
,
1058 IDirect3DViewportImpl_NextLight
,
1059 /*** IDirect3DViewport2 Methods ***/
1060 IDirect3DViewportImpl_GetViewport2
,
1061 IDirect3DViewportImpl_SetViewport2
,
1062 /*** IDirect3DViewport3 Methods ***/
1063 IDirect3DViewportImpl_SetBackgroundDepth2
,
1064 IDirect3DViewportImpl_GetBackgroundDepth2
,
1065 IDirect3DViewportImpl_Clear2
,