itss: Avoid checking an unsigned value for < 0.
[wine/gsoc_dplay.git] / dlls / ddraw / viewport.c
blobe5fb45bd7a5061980dc9b73b0ce4af5cc09a2a61
1 /* Direct3D Viewport
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
22 #include "config.h"
23 #include "wine/port.h"
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <stdlib.h>
30 #define COBJMACROS
31 #define NONAMELESSUNION
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "wingdi.h"
37 #include "wine/exception.h"
39 #include "ddraw.h"
40 #include "d3d.h"
42 #include "ddraw_private.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
47 /*****************************************************************************
48 * Helper functions
49 *****************************************************************************/
51 /*****************************************************************************
52 * viewport_activate
54 * activates the viewport using IDirect3DDevice7::SetViewport
56 *****************************************************************************/
57 void viewport_activate(IDirect3DViewportImpl* This) {
58 IDirect3DLightImpl* light;
59 D3DVIEWPORT7 vp;
61 /* Activate all the lights associated with this context */
62 light = This->lights;
64 while (light != NULL) {
65 light->activate(light);
66 light = light->next;
69 /* And copy the values in the structure used by the device */
70 if (This->use_vp2) {
71 vp.dwX = This->viewports.vp2.dwX;
72 vp.dwY = This->viewports.vp2.dwY;
73 vp.dwHeight = This->viewports.vp2.dwHeight;
74 vp.dwWidth = This->viewports.vp2.dwWidth;
75 vp.dvMinZ = This->viewports.vp2.dvMinZ;
76 vp.dvMaxZ = This->viewports.vp2.dvMaxZ;
77 } else {
78 vp.dwX = This->viewports.vp1.dwX;
79 vp.dwY = This->viewports.vp1.dwY;
80 vp.dwHeight = This->viewports.vp1.dwHeight;
81 vp.dwWidth = This->viewports.vp1.dwWidth;
82 vp.dvMinZ = This->viewports.vp1.dvMinZ;
83 vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
86 /* And also set the viewport */
87 IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp);
90 /*****************************************************************************
91 * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2
93 * Writes viewport information to TRACE
95 *****************************************************************************/
96 static void _dump_D3DVIEWPORT(const D3DVIEWPORT *lpvp)
98 TRACE(" - dwSize = %d dwX = %d dwY = %d\n",
99 lpvp->dwSize, lpvp->dwX, lpvp->dwY);
100 TRACE(" - dwWidth = %d dwHeight = %d\n",
101 lpvp->dwWidth, lpvp->dwHeight);
102 TRACE(" - dvScaleX = %f dvScaleY = %f\n",
103 lpvp->dvScaleX, lpvp->dvScaleY);
104 TRACE(" - dvMaxX = %f dvMaxY = %f\n",
105 lpvp->dvMaxX, lpvp->dvMaxY);
106 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
107 lpvp->dvMinZ, lpvp->dvMaxZ);
110 static void _dump_D3DVIEWPORT2(const D3DVIEWPORT2 *lpvp)
112 TRACE(" - dwSize = %d dwX = %d dwY = %d\n",
113 lpvp->dwSize, lpvp->dwX, lpvp->dwY);
114 TRACE(" - dwWidth = %d dwHeight = %d\n",
115 lpvp->dwWidth, lpvp->dwHeight);
116 TRACE(" - dvClipX = %f dvClipY = %f\n",
117 lpvp->dvClipX, lpvp->dvClipY);
118 TRACE(" - dvClipWidth = %f dvClipHeight = %f\n",
119 lpvp->dvClipWidth, lpvp->dvClipHeight);
120 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
121 lpvp->dvMinZ, lpvp->dvMaxZ);
124 /*****************************************************************************
125 * IUnknown Methods.
126 *****************************************************************************/
128 /*****************************************************************************
129 * IDirect3DViewport3::QueryInterface
131 * A normal QueryInterface. Can query all interface versions and the
132 * IUnknown interface. The VTables of the different versions
133 * are equal
135 * Params:
136 * refiid: Interface id queried for
137 * obj: Address to write the interface pointer to
139 * Returns:
140 * S_OK on success.
141 * E_NOINTERFACE if the requested interface wasn't found
143 *****************************************************************************/
144 static HRESULT WINAPI
145 IDirect3DViewportImpl_QueryInterface(IDirect3DViewport3 *iface,
146 REFIID riid,
147 void **obp)
149 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
150 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), obp);
152 *obp = NULL;
154 if ( IsEqualGUID(&IID_IUnknown, riid) ||
155 IsEqualGUID(&IID_IDirect3DViewport, riid) ||
156 IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
157 IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
158 IDirect3DViewport3_AddRef(ICOM_INTERFACE(This, IDirect3DViewport3));
159 *obp = ICOM_INTERFACE(This, IDirect3DViewport3);
160 TRACE(" Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
161 return S_OK;
163 FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
164 return E_NOINTERFACE;
167 /*****************************************************************************
168 * IDirect3DViewport3::AddRef
170 * Increases the refcount.
172 * Returns:
173 * The new refcount
175 *****************************************************************************/
176 static ULONG WINAPI
177 IDirect3DViewportImpl_AddRef(IDirect3DViewport3 *iface)
179 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
180 ULONG ref = InterlockedIncrement(&This->ref);
182 TRACE("(%p)->() incrementing from %u.\n", This, ref - 1);
184 return ref;
187 /*****************************************************************************
188 * IDirect3DViewport3::Release
190 * Reduces the refcount. If it falls to 0, the interface is released
192 * Returns:
193 * The new refcount
195 *****************************************************************************/
196 static ULONG WINAPI
197 IDirect3DViewportImpl_Release(IDirect3DViewport3 *iface)
199 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
200 ULONG ref = InterlockedDecrement(&This->ref);
202 TRACE("(%p)->() decrementing from %u.\n", This, ref + 1);
204 if (!ref) {
205 HeapFree(GetProcessHeap(), 0, This);
206 return 0;
208 return ref;
211 /*****************************************************************************
212 * IDirect3DViewport Methods.
213 *****************************************************************************/
215 /*****************************************************************************
216 * IDirect3DViewport3::Initialize
218 * No-op initialization.
220 * Params:
221 * Direct3D: The direct3D device this viewport is assigned to
223 * Returns:
224 * DDERR_ALREADYINITIALIZED
226 *****************************************************************************/
227 static HRESULT WINAPI
228 IDirect3DViewportImpl_Initialize(IDirect3DViewport3 *iface,
229 IDirect3D *Direct3D)
231 TRACE("(%p)->(%p) no-op...\n", iface, Direct3D);
232 return DDERR_ALREADYINITIALIZED;
235 /*****************************************************************************
236 * IDirect3DViewport3::GetViewport
238 * Returns the viewport data assigned to this viewport interface
240 * Params:
241 * Data: Address to store the data
243 * Returns:
244 * D3D_OK on success
245 * DDERR_INVALIDPARAMS if Data is NULL
247 *****************************************************************************/
248 static HRESULT WINAPI
249 IDirect3DViewportImpl_GetViewport(IDirect3DViewport3 *iface,
250 D3DVIEWPORT *lpData)
252 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
253 DWORD dwSize;
254 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
256 EnterCriticalSection(&ddraw_cs);
257 if (This->use_vp2 != 0) {
258 ERR(" Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
259 LeaveCriticalSection(&ddraw_cs);
260 return DDERR_INVALIDPARAMS;
262 dwSize = lpData->dwSize;
263 memset(lpData, 0, dwSize);
264 memcpy(lpData, &(This->viewports.vp1), dwSize);
266 if (TRACE_ON(d3d7)) {
267 TRACE(" returning D3DVIEWPORT :\n");
268 _dump_D3DVIEWPORT(lpData);
270 LeaveCriticalSection(&ddraw_cs);
272 return DD_OK;
275 /*****************************************************************************
276 * IDirect3DViewport3::SetViewport
278 * Sets the viewport information for this interface
280 * Params:
281 * lpData: Viewport to set
283 * Returns:
284 * D3D_OK on success
285 * DDERR_INVALIDPARAMS if Data is NULL
287 *****************************************************************************/
288 static HRESULT WINAPI
289 IDirect3DViewportImpl_SetViewport(IDirect3DViewport3 *iface,
290 D3DVIEWPORT *lpData)
292 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
293 LPDIRECT3DVIEWPORT3 current_viewport;
294 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
296 if (TRACE_ON(d3d7)) {
297 TRACE(" getting D3DVIEWPORT :\n");
298 _dump_D3DVIEWPORT(lpData);
301 EnterCriticalSection(&ddraw_cs);
302 This->use_vp2 = 0;
303 memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
304 memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
306 /* Tests on two games show that these values are never used properly so override
307 them with proper ones :-)
309 This->viewports.vp1.dvMinZ = 0.0;
310 This->viewports.vp1.dvMaxZ = 1.0;
312 if (This->active_device) {
313 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
314 if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
315 This->activate(This);
316 if(current_viewport) IDirect3DViewport3_Release(current_viewport);
318 LeaveCriticalSection(&ddraw_cs);
320 return DD_OK;
323 /*****************************************************************************
324 * IDirect3DViewport3::TransformVertices
326 * Transforms vertices by the transformation matrix.
328 * This function is pretty similar to IDirect3DVertexBuffer7::ProcessVertices,
329 * so it's tempting to forward it to there. However, there are some
330 * tiny differences. First, the lpOffscreen flag that is reported back,
331 * then there is the homogenous vertex that is generated. Also there's a lack
332 * of FVFs, but still a custom stride. Last, the d3d1 - d3d3 viewport has some
333 * settings (scale) that d3d7 and wined3d do not have. All in all wrapping to
334 * ProcessVertices doesn't pay of in terms of wrapper code needed and code
335 * reused.
337 * Params:
338 * dwVertexCount: The number of vertices to be transformed
339 * lpData: Pointer to the vertex data
340 * dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED
341 * lpOffScreen: Set to the clipping plane clipping the vertex, if only one
342 * vertex is transformed and clipping is on. 0 otherwise
344 * Returns:
345 * D3D_OK on success
346 * D3DERR_VIEWPORTHASNODEVICE if the viewport is not assigned to a device
347 * DDERR_INVALIDPARAMS if no clipping flag is specified
349 *****************************************************************************/
350 static HRESULT WINAPI
351 IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface,
352 DWORD dwVertexCount,
353 D3DTRANSFORMDATA *lpData,
354 DWORD dwFlags,
355 DWORD *lpOffScreen)
357 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
358 D3DMATRIX view_mat, world_mat, proj_mat, mat;
359 float *in;
360 float *out;
361 float x, y, z, w;
362 unsigned int i;
363 D3DVIEWPORT vp = This->viewports.vp1;
364 D3DHVERTEX *outH;
365 TRACE("(%p)->(%08x,%p,%08x,%p)\n", This, dwVertexCount, lpData, dwFlags, lpOffScreen);
367 /* Tests on windows show that Windows crashes when this occurs,
368 * so don't return the (intuitive) return value
369 if(!This->active_device)
371 WARN("No device active, returning D3DERR_VIEWPORTHASNODEVICE\n");
372 return D3DERR_VIEWPORTHASNODEVICE;
376 if(!(dwFlags & (D3DTRANSFORM_UNCLIPPED | D3DTRANSFORM_CLIPPED)))
378 WARN("No clipping flag passed, returning DDERR_INVALIDPARAMS\n");
379 return DDERR_INVALIDPARAMS;
383 EnterCriticalSection(&ddraw_cs);
384 IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
385 D3DTRANSFORMSTATE_VIEW,
386 (WINED3DMATRIX*) &view_mat);
388 IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
389 D3DTRANSFORMSTATE_PROJECTION,
390 (WINED3DMATRIX*) &proj_mat);
392 IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
393 WINED3DTS_WORLDMATRIX(0),
394 (WINED3DMATRIX*) &world_mat);
395 multiply_matrix(&mat,&view_mat,&world_mat);
396 multiply_matrix(&mat,&proj_mat,&mat);
398 in = (float *) lpData->lpIn;
399 out = (float *) lpData->lpOut;
400 outH = lpData->lpHOut;
401 for(i = 0; i < dwVertexCount; i++)
403 x = (in[0] * mat._11) + (in[1] * mat._21) + (in[2] * mat._31) + (1.0 * mat._41);
404 y = (in[0] * mat._12) + (in[1] * mat._22) + (in[2] * mat._32) + (1.0 * mat._42);
405 z = (in[0] * mat._13) + (in[1] * mat._23) + (in[2] * mat._33) + (1.0 * mat._43);
406 w = (in[0] * mat._14) + (in[1] * mat._24) + (in[2] * mat._34) + (1.0 * mat._44);
408 if(dwFlags & D3DTRANSFORM_CLIPPED)
410 /* If clipping is enabled, Windows assumes that outH is
411 * a valid pointer
413 outH[i].u1.hx = x; outH[i].u2.hy = y; outH[i].u3.hz = z;
415 outH[i].dwFlags = 0;
416 if(x * vp.dvScaleX > ((float) vp.dwWidth * 0.5))
417 outH[i].dwFlags |= D3DCLIP_RIGHT;
418 if(x * vp.dvScaleX <= -((float) vp.dwWidth) * 0.5)
419 outH[i].dwFlags |= D3DCLIP_LEFT;
420 if(y * vp.dvScaleY > ((float) vp.dwHeight * 0.5))
421 outH[i].dwFlags |= D3DCLIP_TOP;
422 if(y * vp.dvScaleY <= -((float) vp.dwHeight) * 0.5)
423 outH[i].dwFlags |= D3DCLIP_BOTTOM;
424 if(z < 0.0)
425 outH[i].dwFlags |= D3DCLIP_FRONT;
426 if(z > 1.0)
427 outH[i].dwFlags |= D3DCLIP_BACK;
429 if(outH[i].dwFlags)
431 /* Looks like native just drops the vertex, leaves whatever data
432 * it has in the output buffer and goes on with the next vertex.
433 * The exact scheme hasn't been figured out yet, but windows
434 * definitely writes something there.
436 out[0] = x;
437 out[1] = y;
438 out[2] = z;
439 out[3] = w;
440 in = (float *) ((char *) in + lpData->dwInSize);
441 out = (float *) ((char *) out + lpData->dwOutSize);
442 continue;
446 w = 1 / w;
447 x *= w; y *= w; z *= w;
449 out[0] = vp.dwWidth / 2 + vp.dwX + x * vp.dvScaleX;
450 out[1] = vp.dwHeight / 2 + vp.dwY - y * vp.dvScaleY;
451 out[2] = z;
452 out[3] = w;
453 in = (float *) ((char *) in + lpData->dwInSize);
454 out = (float *) ((char *) out + lpData->dwOutSize);
457 /* According to the d3d test, the offscreen flag is set only
458 * if exactly one vertex is transformed. Its not documented,
459 * but the test shows that the lpOffscreen flag is set to the
460 * flag combination of clipping planes that clips the vertex.
462 * If clipping is requested, Windows assumes that the offscreen
463 * param is a valid pointer.
465 if(dwVertexCount == 1 && dwFlags & D3DTRANSFORM_CLIPPED)
467 *lpOffScreen = outH[0].dwFlags;
469 else if(*lpOffScreen)
471 *lpOffScreen = 0;
473 LeaveCriticalSection(&ddraw_cs);
475 TRACE("All done\n");
476 return DD_OK;
479 /*****************************************************************************
480 * IDirect3DViewport3::LightElements
482 * The DirectX 5.0 sdk says that it's not implemented
484 * Params:
487 * Returns:
488 * DDERR_UNSUPPORTED
490 *****************************************************************************/
491 static HRESULT WINAPI
492 IDirect3DViewportImpl_LightElements(IDirect3DViewport3 *iface,
493 DWORD dwElementCount,
494 LPD3DLIGHTDATA lpData)
496 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
497 TRACE("(%p)->(%08x,%p): Unimplemented!\n", This, dwElementCount, lpData);
498 return DDERR_UNSUPPORTED;
501 /*****************************************************************************
502 * IDirect3DViewport3::SetBackground
504 * Sets tje background material
506 * Params:
507 * hMat: Handle from a IDirect3DMaterial interface
509 * Returns:
510 * D3D_OK on success
512 *****************************************************************************/
513 static HRESULT WINAPI
514 IDirect3DViewportImpl_SetBackground(IDirect3DViewport3 *iface,
515 D3DMATERIALHANDLE hMat)
517 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
518 TRACE("(%p)->(%d)\n", This, (DWORD) hMat);
520 EnterCriticalSection(&ddraw_cs);
521 if(hMat && hMat > This->ddraw->d3ddevice->numHandles)
523 WARN("Specified Handle %d out of range\n", hMat);
524 LeaveCriticalSection(&ddraw_cs);
525 return DDERR_INVALIDPARAMS;
527 else if(hMat && This->ddraw->d3ddevice->Handles[hMat - 1].type != DDrawHandle_Material)
529 WARN("Handle %d is not a material handle\n", hMat);
530 LeaveCriticalSection(&ddraw_cs);
531 return DDERR_INVALIDPARAMS;
534 if(hMat)
536 This->background = (IDirect3DMaterialImpl *) This->ddraw->d3ddevice->Handles[hMat - 1].ptr;
537 TRACE(" setting background color : %f %f %f %f\n",
538 This->background->mat.u.diffuse.u1.r,
539 This->background->mat.u.diffuse.u2.g,
540 This->background->mat.u.diffuse.u3.b,
541 This->background->mat.u.diffuse.u4.a);
543 else
545 This->background = NULL;
546 TRACE("Setting background to NULL\n");
549 LeaveCriticalSection(&ddraw_cs);
550 return D3D_OK;
553 /*****************************************************************************
554 * IDirect3DViewport3::GetBackground
556 * Returns the material handle assigned to the background of the viewport
558 * Params:
559 * lphMat: Address to store the handle
560 * lpValid: is set to FALSE if no background is set, TRUE if one is set
562 * Returns:
563 * D3D_OK
565 *****************************************************************************/
566 static HRESULT WINAPI
567 IDirect3DViewportImpl_GetBackground(IDirect3DViewport3 *iface,
568 D3DMATERIALHANDLE *lphMat,
569 BOOL *lpValid)
571 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
572 TRACE("(%p)->(%p,%p)\n", This, lphMat, lpValid);
574 EnterCriticalSection(&ddraw_cs);
575 if(lpValid)
577 *lpValid = This->background != NULL;
579 if(lphMat)
581 if(This->background)
583 *lphMat = This->background->Handle;
585 else
587 *lphMat = 0;
590 LeaveCriticalSection(&ddraw_cs);
592 return D3D_OK;
595 /*****************************************************************************
596 * IDirect3DViewport3::SetBackgroundDepth
598 * Sets a surface that represents the background depth. It's contents are
599 * used to set the depth buffer in IDirect3DViewport3::Clear
601 * Params:
602 * lpDDSurface: Surface to set
604 * Returns: D3D_OK, because it's a stub
606 *****************************************************************************/
607 static HRESULT WINAPI
608 IDirect3DViewportImpl_SetBackgroundDepth(IDirect3DViewport3 *iface,
609 IDirectDrawSurface *lpDDSurface)
611 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
612 FIXME("(%p)->(%p): stub!\n", This, lpDDSurface);
613 return D3D_OK;
616 /*****************************************************************************
617 * IDirect3DViewport3::GetBackgroundDepth
619 * Returns the surface that represents the depth field
621 * Params:
622 * lplpDDSurface: Address to store the interface pointer
623 * lpValid: Set to TRUE if a depth is asigned, FALSE otherwise
625 * Returns:
626 * D3D_OK, because it's a stub
627 * (DDERR_INVALIDPARAMS if DDSurface of Valid is NULL)
629 *****************************************************************************/
630 static HRESULT WINAPI
631 IDirect3DViewportImpl_GetBackgroundDepth(IDirect3DViewport3 *iface,
632 IDirectDrawSurface **lplpDDSurface,
633 LPBOOL lpValid)
635 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
636 FIXME("(%p)->(%p,%p): stub!\n", This, lplpDDSurface, lpValid);
637 return DD_OK;
640 /*****************************************************************************
641 * IDirect3DViewport3::Clear
643 * Clears the render target and / or the z buffer
645 * Params:
646 * dwCount: The amount of rectangles to clear. If 0, the whole buffer is
647 * cleared
648 * lpRects: Pointer to the array of rectangles. If NULL, Count must be 0
649 * dwFlags: D3DCLEAR_ZBUFFER and / or D3DCLEAR_TARGET
651 * Returns:
652 * D3D_OK on success
653 * D3DERR_VIEWPORTHASNODEVICE if there's no active device
654 * The return value of IDirect3DDevice7::Clear
656 *****************************************************************************/
657 static HRESULT WINAPI
658 IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface,
659 DWORD dwCount,
660 D3DRECT *lpRects,
661 DWORD dwFlags)
663 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
664 DWORD color = 0x00000000;
665 HRESULT hr;
667 TRACE("(%p/%p)->(%08x,%p,%08x)\n", This, iface, dwCount, lpRects, dwFlags);
668 if (This->active_device == NULL) {
669 ERR(" Trying to clear a viewport not attached to a device !\n");
670 return D3DERR_VIEWPORTHASNODEVICE;
673 EnterCriticalSection(&ddraw_cs);
674 if (dwFlags & D3DCLEAR_TARGET) {
675 if (This->background == NULL) {
676 ERR(" Trying to clear the color buffer without background material !\n");
677 } else {
678 color =
679 ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) |
680 ((int) ((This->background->mat.u.diffuse.u2.g) * 255) << 8) |
681 ((int) ((This->background->mat.u.diffuse.u3.b) * 255) << 0) |
682 ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
686 hr = IDirect3DDevice7_Clear(ICOM_INTERFACE(This->active_device, IDirect3DDevice7),
687 dwCount,
688 lpRects,
689 dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET),
690 color,
691 1.0,
692 0x00000000);
693 LeaveCriticalSection(&ddraw_cs);
694 return hr;
697 /*****************************************************************************
698 * IDirect3DViewport3::AddLight
700 * Adds an light to the viewport
702 * Params:
703 * lpDirect3DLight: Interface of the light to add
705 * Returns:
706 * D3D_OK on success
707 * DDERR_INVALIDPARAMS if Direct3DLight is NULL
708 * DDERR_INVALIDPARAMS if there are 8 lights or more
710 *****************************************************************************/
711 static HRESULT WINAPI
712 IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface,
713 IDirect3DLight *lpDirect3DLight)
715 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
716 IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
717 DWORD i = 0;
718 DWORD map = This->map_lights;
720 TRACE("(%p)->(%p)\n", This, lpDirect3DLight);
722 EnterCriticalSection(&ddraw_cs);
723 if (This->num_lights >= 8)
725 LeaveCriticalSection(&ddraw_cs);
726 return DDERR_INVALIDPARAMS;
729 /* Find a light number and update both light and viewports objects accordingly */
730 while(map&1) {
731 map>>=1;
732 i++;
734 lpDirect3DLightImpl->dwLightIndex = i;
735 This->num_lights++;
736 This->map_lights |= 1<<i;
738 /* Add the light in the 'linked' chain */
739 lpDirect3DLightImpl->next = This->lights;
740 This->lights = lpDirect3DLightImpl;
742 /* Attach the light to the viewport */
743 lpDirect3DLightImpl->active_viewport = This;
745 /* If active, activate the light */
746 if (This->active_device != NULL) {
747 lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
750 LeaveCriticalSection(&ddraw_cs);
751 return D3D_OK;
754 /*****************************************************************************
755 * IDirect3DViewport3::DeleteLight
757 * Deletes a light from the viewports' light list
759 * Params:
760 * lpDirect3DLight: Light to delete
762 * Returns:
763 * D3D_OK on success
764 * DDERR_INVALIDPARAMS if the light wasn't found
766 *****************************************************************************/
767 static HRESULT WINAPI
768 IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3 *iface,
769 IDirect3DLight *lpDirect3DLight)
771 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
772 IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
773 IDirect3DLightImpl *cur_light, *prev_light = NULL;
775 TRACE("(%p)->(%p)\n", This, lpDirect3DLight);
777 EnterCriticalSection(&ddraw_cs);
778 cur_light = This->lights;
779 while (cur_light != NULL) {
780 if (cur_light == lpDirect3DLightImpl) {
781 lpDirect3DLightImpl->desactivate(lpDirect3DLightImpl);
782 if (prev_light == NULL) This->lights = cur_light->next;
783 else prev_light->next = cur_light->next;
784 /* Detach the light to the viewport */
785 cur_light->active_viewport = NULL;
786 This->num_lights--;
787 This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
788 LeaveCriticalSection(&ddraw_cs);
789 return D3D_OK;
791 prev_light = cur_light;
792 cur_light = cur_light->next;
794 LeaveCriticalSection(&ddraw_cs);
796 return DDERR_INVALIDPARAMS;
799 /*****************************************************************************
800 * IDirect3DViewport::NextLight
802 * Enumerates the lights associated with the viewport
804 * Params:
805 * lpDirect3DLight: Light to start with
806 * lplpDirect3DLight: Address to store the successor to
808 * Returns:
809 * D3D_OK, because it's a stub
811 *****************************************************************************/
812 static HRESULT WINAPI
813 IDirect3DViewportImpl_NextLight(IDirect3DViewport3 *iface,
814 IDirect3DLight *lpDirect3DLight,
815 IDirect3DLight **lplpDirect3DLight,
816 DWORD dwFlags)
818 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
819 FIXME("(%p)->(%p,%p,%08x): stub!\n", This, lpDirect3DLight, lplpDirect3DLight, dwFlags);
820 return D3D_OK;
823 /*****************************************************************************
824 * IDirect3DViewport2 Methods.
825 *****************************************************************************/
827 /*****************************************************************************
828 * IDirect3DViewport3::GetViewport2
830 * Returns the currently set viewport in a D3DVIEWPORT2 structure.
831 * Similar to IDirect3DViewport3::GetViewport
833 * Params:
834 * lpData: Pointer to the structure to fill
836 * Returns:
837 * D3D_OK on success
838 * DDERR_INVALIDPARAMS if the viewport was set with
839 * IDirect3DViewport3::SetViewport
840 * DDERR_INVALIDPARAMS if Data is NULL
842 *****************************************************************************/
843 static HRESULT WINAPI
844 IDirect3DViewportImpl_GetViewport2(IDirect3DViewport3 *iface,
845 D3DVIEWPORT2 *lpData)
847 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
848 DWORD dwSize;
849 TRACE("(%p)->(%p)\n", This, lpData);
851 EnterCriticalSection(&ddraw_cs);
852 if (This->use_vp2 != 1) {
853 ERR(" Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
854 LeaveCriticalSection(&ddraw_cs);
855 return DDERR_INVALIDPARAMS;
857 dwSize = lpData->dwSize;
858 memset(lpData, 0, dwSize);
859 memcpy(lpData, &(This->viewports.vp2), dwSize);
861 if (TRACE_ON(d3d7)) {
862 TRACE(" returning D3DVIEWPORT2 :\n");
863 _dump_D3DVIEWPORT2(lpData);
866 LeaveCriticalSection(&ddraw_cs);
867 return D3D_OK;
870 /*****************************************************************************
871 * IDirect3DViewport3::SetViewport2
873 * Sets the viewport from a D3DVIEWPORT2 structure
875 * Params:
876 * lpData: Viewport to set
878 * Returns:
879 * D3D_OK on success
881 *****************************************************************************/
882 static HRESULT WINAPI
883 IDirect3DViewportImpl_SetViewport2(IDirect3DViewport3 *iface,
884 D3DVIEWPORT2 *lpData)
886 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
887 LPDIRECT3DVIEWPORT3 current_viewport;
888 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
890 if (TRACE_ON(d3d7)) {
891 TRACE(" getting D3DVIEWPORT2 :\n");
892 _dump_D3DVIEWPORT2(lpData);
895 EnterCriticalSection(&ddraw_cs);
896 This->use_vp2 = 1;
897 memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
898 memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
900 if (This->active_device) {
901 IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
902 if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
903 This->activate(This);
904 IDirect3DViewport3_Release(current_viewport);
906 LeaveCriticalSection(&ddraw_cs);
908 return D3D_OK;
911 /*****************************************************************************
912 * IDirect3DViewport3 Methods.
913 *****************************************************************************/
915 /*****************************************************************************
916 * IDirect3DViewport3::SetBackgroundDepth2
918 * Sets a IDirectDrawSurface4 surface as the background depth surface
920 * Params:
921 * lpDDS: Surface to set
923 * Returns:
924 * D3D_OK, because it's stub
926 *****************************************************************************/
927 static HRESULT WINAPI
928 IDirect3DViewportImpl_SetBackgroundDepth2(IDirect3DViewport3 *iface,
929 IDirectDrawSurface4 *lpDDS)
931 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
932 FIXME("(%p)->(%p): stub!\n", This, lpDDS);
933 return D3D_OK;
936 /*****************************************************************************
937 * IDirect3DViewport3::GetBackgroundDepth2
939 * Returns the IDirect3DSurface4 interface to the background depth surface
941 * Params:
942 * lplpDDS: Address to store the interface pointer at
943 * lpValid: Set to true if a surface is assigned
945 * Returns:
946 * D3D_OK because it's a stub
948 *****************************************************************************/
949 static HRESULT WINAPI
950 IDirect3DViewportImpl_GetBackgroundDepth2(IDirect3DViewport3 *iface,
951 IDirectDrawSurface4 **lplpDDS,
952 BOOL *lpValid)
954 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
955 FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDS, lpValid);
956 return D3D_OK;
959 /*****************************************************************************
960 * IDirect3DViewport3::Clear2
962 * Another clearing method
964 * Params:
965 * Count: Number of rectangles to clear
966 * Rects: Rectangle array to clear
967 * Flags: Some flags :)
968 * Color: Color to fill the render target with
969 * Z: Value to fill the depth buffer with
970 * Stencil: Value to fill the stencil bits with
972 * Returns:
974 *****************************************************************************/
975 static HRESULT WINAPI
976 IDirect3DViewportImpl_Clear2(IDirect3DViewport3 *iface,
977 DWORD dwCount,
978 LPD3DRECT lpRects,
979 DWORD dwFlags,
980 DWORD dwColor,
981 D3DVALUE dvZ,
982 DWORD dwStencil)
984 ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
985 HRESULT hr;
986 TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
988 EnterCriticalSection(&ddraw_cs);
989 if (This->active_device == NULL) {
990 ERR(" Trying to clear a viewport not attached to a device !\n");
991 LeaveCriticalSection(&ddraw_cs);
992 return D3DERR_VIEWPORTHASNODEVICE;
994 hr = IDirect3DDevice7_Clear(ICOM_INTERFACE(This->active_device, IDirect3DDevice7),
995 dwCount,
996 lpRects,
997 dwFlags,
998 dwColor,
999 dvZ,
1000 dwStencil);
1001 LeaveCriticalSection(&ddraw_cs);
1002 return hr;
1005 /*****************************************************************************
1006 * The VTable
1007 *****************************************************************************/
1009 const IDirect3DViewport3Vtbl IDirect3DViewport3_Vtbl =
1011 /*** IUnknown Methods ***/
1012 IDirect3DViewportImpl_QueryInterface,
1013 IDirect3DViewportImpl_AddRef,
1014 IDirect3DViewportImpl_Release,
1015 /*** IDirect3DViewport Methods */
1016 IDirect3DViewportImpl_Initialize,
1017 IDirect3DViewportImpl_GetViewport,
1018 IDirect3DViewportImpl_SetViewport,
1019 IDirect3DViewportImpl_TransformVertices,
1020 IDirect3DViewportImpl_LightElements,
1021 IDirect3DViewportImpl_SetBackground,
1022 IDirect3DViewportImpl_GetBackground,
1023 IDirect3DViewportImpl_SetBackgroundDepth,
1024 IDirect3DViewportImpl_GetBackgroundDepth,
1025 IDirect3DViewportImpl_Clear,
1026 IDirect3DViewportImpl_AddLight,
1027 IDirect3DViewportImpl_DeleteLight,
1028 IDirect3DViewportImpl_NextLight,
1029 /*** IDirect3DViewport2 Methods ***/
1030 IDirect3DViewportImpl_GetViewport2,
1031 IDirect3DViewportImpl_SetViewport2,
1032 /*** IDirect3DViewport3 Methods ***/
1033 IDirect3DViewportImpl_SetBackgroundDepth2,
1034 IDirect3DViewportImpl_GetBackgroundDepth2,
1035 IDirect3DViewportImpl_Clear2,