xcopy: Remove spaces before '\n's in the Korean translation.
[wine/hramrach.git] / dlls / ddraw / viewport.c
blob918b002e3f7809ebd9960bd27052a0c56ff68b1a
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 "ddraw_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
29 /*****************************************************************************
30 * Helper functions
31 *****************************************************************************/
33 /*****************************************************************************
34 * viewport_activate
36 * activates the viewport using IDirect3DDevice7::SetViewport
38 *****************************************************************************/
39 void viewport_activate(IDirect3DViewportImpl* This, BOOL ignore_lights) {
40 IDirect3DLightImpl* light;
41 D3DVIEWPORT7 vp;
43 if (!ignore_lights) {
44 /* Activate all the lights associated with this context */
45 light = This->lights;
47 while (light)
49 light_activate(light);
50 light = light->next;
54 /* And copy the values in the structure used by the device */
55 if (This->use_vp2) {
56 vp.dwX = This->viewports.vp2.dwX;
57 vp.dwY = This->viewports.vp2.dwY;
58 vp.dwHeight = This->viewports.vp2.dwHeight;
59 vp.dwWidth = This->viewports.vp2.dwWidth;
60 vp.dvMinZ = This->viewports.vp2.dvMinZ;
61 vp.dvMaxZ = This->viewports.vp2.dvMaxZ;
62 } else {
63 vp.dwX = This->viewports.vp1.dwX;
64 vp.dwY = This->viewports.vp1.dwY;
65 vp.dwHeight = This->viewports.vp1.dwHeight;
66 vp.dwWidth = This->viewports.vp1.dwWidth;
67 vp.dvMinZ = This->viewports.vp1.dvMinZ;
68 vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
71 /* And also set the viewport */
72 IDirect3DDevice7_SetViewport((IDirect3DDevice7 *)This->active_device, &vp);
75 /*****************************************************************************
76 * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2
78 * Writes viewport information to TRACE
80 *****************************************************************************/
81 static void _dump_D3DVIEWPORT(const D3DVIEWPORT *lpvp)
83 TRACE(" - dwSize = %d dwX = %d dwY = %d\n",
84 lpvp->dwSize, lpvp->dwX, lpvp->dwY);
85 TRACE(" - dwWidth = %d dwHeight = %d\n",
86 lpvp->dwWidth, lpvp->dwHeight);
87 TRACE(" - dvScaleX = %f dvScaleY = %f\n",
88 lpvp->dvScaleX, lpvp->dvScaleY);
89 TRACE(" - dvMaxX = %f dvMaxY = %f\n",
90 lpvp->dvMaxX, lpvp->dvMaxY);
91 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
92 lpvp->dvMinZ, lpvp->dvMaxZ);
95 static void _dump_D3DVIEWPORT2(const D3DVIEWPORT2 *lpvp)
97 TRACE(" - dwSize = %d dwX = %d dwY = %d\n",
98 lpvp->dwSize, lpvp->dwX, lpvp->dwY);
99 TRACE(" - dwWidth = %d dwHeight = %d\n",
100 lpvp->dwWidth, lpvp->dwHeight);
101 TRACE(" - dvClipX = %f dvClipY = %f\n",
102 lpvp->dvClipX, lpvp->dvClipY);
103 TRACE(" - dvClipWidth = %f dvClipHeight = %f\n",
104 lpvp->dvClipWidth, lpvp->dvClipHeight);
105 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
106 lpvp->dvMinZ, lpvp->dvMaxZ);
109 /*****************************************************************************
110 * IUnknown Methods.
111 *****************************************************************************/
113 /*****************************************************************************
114 * IDirect3DViewport3::QueryInterface
116 * A normal QueryInterface. Can query all interface versions and the
117 * IUnknown interface. The VTables of the different versions
118 * are equal
120 * Params:
121 * refiid: Interface id queried for
122 * obj: Address to write the interface pointer to
124 * Returns:
125 * S_OK on success.
126 * E_NOINTERFACE if the requested interface wasn't found
128 *****************************************************************************/
129 static HRESULT WINAPI
130 IDirect3DViewportImpl_QueryInterface(IDirect3DViewport3 *iface,
131 REFIID riid,
132 void **obp)
134 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
136 *obp = NULL;
138 if ( IsEqualGUID(&IID_IUnknown, riid) ||
139 IsEqualGUID(&IID_IDirect3DViewport, riid) ||
140 IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
141 IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
142 IDirect3DViewport3_AddRef(iface);
143 *obp = iface;
144 TRACE(" Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
145 return S_OK;
147 FIXME("(%p): interface for IID %s NOT found!\n", iface, debugstr_guid(riid));
148 return E_NOINTERFACE;
151 /*****************************************************************************
152 * IDirect3DViewport3::AddRef
154 * Increases the refcount.
156 * Returns:
157 * The new refcount
159 *****************************************************************************/
160 static ULONG WINAPI
161 IDirect3DViewportImpl_AddRef(IDirect3DViewport3 *iface)
163 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
164 ULONG ref = InterlockedIncrement(&This->ref);
166 TRACE("%p increasing refcount to %u.\n", This, ref);
168 return ref;
171 /*****************************************************************************
172 * IDirect3DViewport3::Release
174 * Reduces the refcount. If it falls to 0, the interface is released
176 * Returns:
177 * The new refcount
179 *****************************************************************************/
180 static ULONG WINAPI
181 IDirect3DViewportImpl_Release(IDirect3DViewport3 *iface)
183 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
184 ULONG ref = InterlockedDecrement(&This->ref);
186 TRACE("%p decreasing refcount to %u.\n", This, ref);
188 if (!ref) {
189 HeapFree(GetProcessHeap(), 0, This);
190 return 0;
192 return ref;
195 /*****************************************************************************
196 * IDirect3DViewport Methods.
197 *****************************************************************************/
199 /*****************************************************************************
200 * IDirect3DViewport3::Initialize
202 * No-op initialization.
204 * Params:
205 * Direct3D: The direct3D device this viewport is assigned to
207 * Returns:
208 * DDERR_ALREADYINITIALIZED
210 *****************************************************************************/
211 static HRESULT WINAPI
212 IDirect3DViewportImpl_Initialize(IDirect3DViewport3 *iface,
213 IDirect3D *Direct3D)
215 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
217 return DDERR_ALREADYINITIALIZED;
220 /*****************************************************************************
221 * IDirect3DViewport3::GetViewport
223 * Returns the viewport data assigned to this viewport interface
225 * Params:
226 * Data: Address to store the data
228 * Returns:
229 * D3D_OK on success
230 * DDERR_INVALIDPARAMS if Data is NULL
232 *****************************************************************************/
233 static HRESULT WINAPI
234 IDirect3DViewportImpl_GetViewport(IDirect3DViewport3 *iface,
235 D3DVIEWPORT *lpData)
237 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
238 DWORD dwSize;
240 TRACE("iface %p, data %p.\n", iface, lpData);
242 EnterCriticalSection(&ddraw_cs);
243 dwSize = lpData->dwSize;
244 memset(lpData, 0, dwSize);
245 if (!This->use_vp2)
246 memcpy(lpData, &(This->viewports.vp1), dwSize);
247 else {
248 D3DVIEWPORT vp1;
249 vp1.dwSize = sizeof(vp1);
250 vp1.dwX = This->viewports.vp2.dwX;
251 vp1.dwY = This->viewports.vp2.dwY;
252 vp1.dwWidth = This->viewports.vp2.dwWidth;
253 vp1.dwHeight = This->viewports.vp2.dwHeight;
254 vp1.dvMaxX = 0.0;
255 vp1.dvMaxY = 0.0;
256 vp1.dvScaleX = 0.0;
257 vp1.dvScaleY = 0.0;
258 vp1.dvMinZ = This->viewports.vp2.dvMinZ;
259 vp1.dvMaxZ = This->viewports.vp2.dvMaxZ;
260 memcpy(lpData, &vp1, dwSize);
263 if (TRACE_ON(ddraw))
265 TRACE(" returning D3DVIEWPORT :\n");
266 _dump_D3DVIEWPORT(lpData);
268 LeaveCriticalSection(&ddraw_cs);
270 return DD_OK;
273 /*****************************************************************************
274 * IDirect3DViewport3::SetViewport
276 * Sets the viewport information for this interface
278 * Params:
279 * lpData: Viewport to set
281 * Returns:
282 * D3D_OK on success
283 * DDERR_INVALIDPARAMS if Data is NULL
285 *****************************************************************************/
286 static HRESULT WINAPI
287 IDirect3DViewportImpl_SetViewport(IDirect3DViewport3 *iface,
288 D3DVIEWPORT *lpData)
290 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
291 LPDIRECT3DVIEWPORT3 current_viewport;
293 TRACE("iface %p, data %p.\n", iface, lpData);
295 if (TRACE_ON(ddraw))
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 *d3d_device3 = (IDirect3DDevice3 *)&This->active_device->IDirect3DDevice3_vtbl;
314 IDirect3DDevice3_GetCurrentViewport(d3d_device3, &current_viewport);
315 if (current_viewport)
317 if ((IDirect3DViewportImpl *)current_viewport == This) viewport_activate(This, FALSE);
318 IDirect3DViewport3_Release(current_viewport);
321 LeaveCriticalSection(&ddraw_cs);
323 return DD_OK;
326 /*****************************************************************************
327 * IDirect3DViewport3::TransformVertices
329 * Transforms vertices by the transformation matrix.
331 * This function is pretty similar to IDirect3DVertexBuffer7::ProcessVertices,
332 * so it's tempting to forward it to there. However, there are some
333 * tiny differences. First, the lpOffscreen flag that is reported back,
334 * then there is the homogeneous vertex that is generated. Also there's a lack
335 * of FVFs, but still a custom stride. Last, the d3d1 - d3d3 viewport has some
336 * settings (scale) that d3d7 and wined3d do not have. All in all wrapping to
337 * ProcessVertices doesn't pay of in terms of wrapper code needed and code
338 * reused.
340 * Params:
341 * dwVertexCount: The number of vertices to be transformed
342 * lpData: Pointer to the vertex data
343 * dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED
344 * lpOffScreen: Set to the clipping plane clipping the vertex, if only one
345 * vertex is transformed and clipping is on. 0 otherwise
347 * Returns:
348 * D3D_OK on success
349 * D3DERR_VIEWPORTHASNODEVICE if the viewport is not assigned to a device
350 * DDERR_INVALIDPARAMS if no clipping flag is specified
352 *****************************************************************************/
353 static HRESULT WINAPI
354 IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface,
355 DWORD dwVertexCount,
356 D3DTRANSFORMDATA *lpData,
357 DWORD dwFlags,
358 DWORD *lpOffScreen)
360 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
361 D3DMATRIX view_mat, world_mat, proj_mat, mat;
362 float *in;
363 float *out;
364 float x, y, z, w;
365 unsigned int i;
366 D3DVIEWPORT vp = This->viewports.vp1;
367 D3DHVERTEX *outH;
369 TRACE("iface %p, vertex_count %u, vertex_data %p, flags %#x, clip_plane %p.\n",
370 iface, dwVertexCount, lpData, dwFlags, lpOffScreen);
372 /* Tests on windows show that Windows crashes when this occurs,
373 * so don't return the (intuitive) return value
374 if(!This->active_device)
376 WARN("No device active, returning D3DERR_VIEWPORTHASNODEVICE\n");
377 return D3DERR_VIEWPORTHASNODEVICE;
381 if(!(dwFlags & (D3DTRANSFORM_UNCLIPPED | D3DTRANSFORM_CLIPPED)))
383 WARN("No clipping flag passed, returning DDERR_INVALIDPARAMS\n");
384 return DDERR_INVALIDPARAMS;
388 EnterCriticalSection(&ddraw_cs);
389 IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
390 D3DTRANSFORMSTATE_VIEW,
391 (WINED3DMATRIX*) &view_mat);
393 IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
394 D3DTRANSFORMSTATE_PROJECTION,
395 (WINED3DMATRIX*) &proj_mat);
397 IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
398 WINED3DTS_WORLDMATRIX(0),
399 (WINED3DMATRIX*) &world_mat);
400 multiply_matrix(&mat,&view_mat,&world_mat);
401 multiply_matrix(&mat,&proj_mat,&mat);
403 in = lpData->lpIn;
404 out = lpData->lpOut;
405 outH = lpData->lpHOut;
406 for(i = 0; i < dwVertexCount; i++)
408 x = (in[0] * mat._11) + (in[1] * mat._21) + (in[2] * mat._31) + (1.0 * mat._41);
409 y = (in[0] * mat._12) + (in[1] * mat._22) + (in[2] * mat._32) + (1.0 * mat._42);
410 z = (in[0] * mat._13) + (in[1] * mat._23) + (in[2] * mat._33) + (1.0 * mat._43);
411 w = (in[0] * mat._14) + (in[1] * mat._24) + (in[2] * mat._34) + (1.0 * mat._44);
413 if(dwFlags & D3DTRANSFORM_CLIPPED)
415 /* If clipping is enabled, Windows assumes that outH is
416 * a valid pointer
418 outH[i].u1.hx = x; outH[i].u2.hy = y; outH[i].u3.hz = z;
420 outH[i].dwFlags = 0;
421 if(x * vp.dvScaleX > ((float) vp.dwWidth * 0.5))
422 outH[i].dwFlags |= D3DCLIP_RIGHT;
423 if(x * vp.dvScaleX <= -((float) vp.dwWidth) * 0.5)
424 outH[i].dwFlags |= D3DCLIP_LEFT;
425 if(y * vp.dvScaleY > ((float) vp.dwHeight * 0.5))
426 outH[i].dwFlags |= D3DCLIP_TOP;
427 if(y * vp.dvScaleY <= -((float) vp.dwHeight) * 0.5)
428 outH[i].dwFlags |= D3DCLIP_BOTTOM;
429 if(z < 0.0)
430 outH[i].dwFlags |= D3DCLIP_FRONT;
431 if(z > 1.0)
432 outH[i].dwFlags |= D3DCLIP_BACK;
434 if(outH[i].dwFlags)
436 /* Looks like native just drops the vertex, leaves whatever data
437 * it has in the output buffer and goes on with the next vertex.
438 * The exact scheme hasn't been figured out yet, but windows
439 * definitely writes something there.
441 out[0] = x;
442 out[1] = y;
443 out[2] = z;
444 out[3] = w;
445 in = (float *) ((char *) in + lpData->dwInSize);
446 out = (float *) ((char *) out + lpData->dwOutSize);
447 continue;
451 w = 1 / w;
452 x *= w; y *= w; z *= w;
454 out[0] = vp.dwWidth / 2 + vp.dwX + x * vp.dvScaleX;
455 out[1] = vp.dwHeight / 2 + vp.dwY - y * vp.dvScaleY;
456 out[2] = z;
457 out[3] = w;
458 in = (float *) ((char *) in + lpData->dwInSize);
459 out = (float *) ((char *) out + lpData->dwOutSize);
462 /* According to the d3d test, the offscreen flag is set only
463 * if exactly one vertex is transformed. Its not documented,
464 * but the test shows that the lpOffscreen flag is set to the
465 * flag combination of clipping planes that clips the vertex.
467 * If clipping is requested, Windows assumes that the offscreen
468 * param is a valid pointer.
470 if(dwVertexCount == 1 && dwFlags & D3DTRANSFORM_CLIPPED)
472 *lpOffScreen = outH[0].dwFlags;
474 else if(*lpOffScreen)
476 *lpOffScreen = 0;
478 LeaveCriticalSection(&ddraw_cs);
480 TRACE("All done\n");
481 return DD_OK;
484 /*****************************************************************************
485 * IDirect3DViewport3::LightElements
487 * The DirectX 5.0 sdk says that it's not implemented
489 * Params:
492 * Returns:
493 * DDERR_UNSUPPORTED
495 *****************************************************************************/
496 static HRESULT WINAPI
497 IDirect3DViewportImpl_LightElements(IDirect3DViewport3 *iface,
498 DWORD dwElementCount,
499 LPD3DLIGHTDATA lpData)
501 TRACE("iface %p, element_count %u, data %p.\n", iface, dwElementCount, lpData);
503 return DDERR_UNSUPPORTED;
506 /*****************************************************************************
507 * IDirect3DViewport3::SetBackground
509 * Sets tje background material
511 * Params:
512 * hMat: Handle from a IDirect3DMaterial interface
514 * Returns:
515 * D3D_OK on success
517 *****************************************************************************/
518 static HRESULT WINAPI
519 IDirect3DViewportImpl_SetBackground(IDirect3DViewport3 *iface,
520 D3DMATERIALHANDLE hMat)
522 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
523 IDirect3DMaterialImpl *m;
525 TRACE("iface %p, material %#x.\n", iface, hMat);
527 EnterCriticalSection(&ddraw_cs);
529 if (!hMat)
531 This->background = NULL;
532 TRACE("Setting background to NULL\n");
533 LeaveCriticalSection(&ddraw_cs);
534 return D3D_OK;
537 m = ddraw_get_object(&This->ddraw->d3ddevice->handle_table, hMat - 1, DDRAW_HANDLE_MATERIAL);
538 if (!m)
540 WARN("Invalid material handle.\n");
541 LeaveCriticalSection(&ddraw_cs);
542 return DDERR_INVALIDPARAMS;
545 TRACE("Setting background color : %.8e %.8e %.8e %.8e.\n",
546 m->mat.u.diffuse.u1.r, m->mat.u.diffuse.u2.g,
547 m->mat.u.diffuse.u3.b, m->mat.u.diffuse.u4.a);
548 This->background = m;
550 LeaveCriticalSection(&ddraw_cs);
551 return D3D_OK;
554 /*****************************************************************************
555 * IDirect3DViewport3::GetBackground
557 * Returns the material handle assigned to the background of the viewport
559 * Params:
560 * lphMat: Address to store the handle
561 * lpValid: is set to FALSE if no background is set, TRUE if one is set
563 * Returns:
564 * D3D_OK
566 *****************************************************************************/
567 static HRESULT WINAPI
568 IDirect3DViewportImpl_GetBackground(IDirect3DViewport3 *iface,
569 D3DMATERIALHANDLE *lphMat,
570 BOOL *lpValid)
572 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
574 TRACE("iface %p, material %p, valid %p.\n", iface, lphMat, lpValid);
576 EnterCriticalSection(&ddraw_cs);
577 if(lpValid)
579 *lpValid = This->background != NULL;
581 if(lphMat)
583 if(This->background)
585 *lphMat = This->background->Handle;
587 else
589 *lphMat = 0;
592 LeaveCriticalSection(&ddraw_cs);
594 return D3D_OK;
597 /*****************************************************************************
598 * IDirect3DViewport3::SetBackgroundDepth
600 * Sets a surface that represents the background depth. It's contents are
601 * used to set the depth buffer in IDirect3DViewport3::Clear
603 * Params:
604 * lpDDSurface: Surface to set
606 * Returns: D3D_OK, because it's a stub
608 *****************************************************************************/
609 static HRESULT WINAPI
610 IDirect3DViewportImpl_SetBackgroundDepth(IDirect3DViewport3 *iface,
611 IDirectDrawSurface *lpDDSurface)
613 FIXME("iface %p, surface %p stub!\n", iface, lpDDSurface);
615 return D3D_OK;
618 /*****************************************************************************
619 * IDirect3DViewport3::GetBackgroundDepth
621 * Returns the surface that represents the depth field
623 * Params:
624 * lplpDDSurface: Address to store the interface pointer
625 * lpValid: Set to TRUE if a depth is assigned, FALSE otherwise
627 * Returns:
628 * D3D_OK, because it's a stub
629 * (DDERR_INVALIDPARAMS if DDSurface of Valid is NULL)
631 *****************************************************************************/
632 static HRESULT WINAPI
633 IDirect3DViewportImpl_GetBackgroundDepth(IDirect3DViewport3 *iface,
634 IDirectDrawSurface **lplpDDSurface,
635 LPBOOL lpValid)
637 FIXME("iface %p, surface %p, valid %p stub!\n", iface, lplpDDSurface, lpValid);
639 return DD_OK;
642 /*****************************************************************************
643 * IDirect3DViewport3::Clear
645 * Clears the render target and / or the z buffer
647 * Params:
648 * dwCount: The amount of rectangles to clear. If 0, the whole buffer is
649 * cleared
650 * lpRects: Pointer to the array of rectangles. If NULL, Count must be 0
651 * dwFlags: D3DCLEAR_ZBUFFER and / or D3DCLEAR_TARGET
653 * Returns:
654 * D3D_OK on success
655 * D3DERR_VIEWPORTHASNODEVICE if there's no active device
656 * The return value of IDirect3DDevice7::Clear
658 *****************************************************************************/
659 static HRESULT WINAPI IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface,
660 DWORD dwCount, D3DRECT *lpRects, DWORD dwFlags)
662 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
663 DWORD color = 0x00000000;
664 HRESULT hr;
665 LPDIRECT3DVIEWPORT3 current_viewport;
666 IDirect3DDevice3 *d3d_device3;
668 TRACE("iface %p, rect_count %u, rects %p, flags %#x.\n", iface, dwCount, lpRects, dwFlags);
670 if (This->active_device == NULL) {
671 ERR(" Trying to clear a viewport not attached to a device !\n");
672 return D3DERR_VIEWPORTHASNODEVICE;
674 d3d_device3 = (IDirect3DDevice3 *)&This->active_device->IDirect3DDevice3_vtbl;
676 EnterCriticalSection(&ddraw_cs);
677 if (dwFlags & D3DCLEAR_TARGET) {
678 if (This->background == NULL) {
679 ERR(" Trying to clear the color buffer without background material !\n");
681 else
683 color = ((int)((This->background->mat.u.diffuse.u1.r) * 255) << 16)
684 | ((int) ((This->background->mat.u.diffuse.u2.g) * 255) << 8)
685 | ((int) ((This->background->mat.u.diffuse.u3.b) * 255) << 0)
686 | ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
690 /* Need to temporarily activate viewport to clear it. Previously active one will be restored
691 afterwards. */
692 viewport_activate(This, TRUE);
694 hr = IDirect3DDevice7_Clear((IDirect3DDevice7 *)This->active_device, dwCount, lpRects,
695 dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET), color, 1.0, 0x00000000);
697 IDirect3DDevice3_GetCurrentViewport(d3d_device3, &current_viewport);
698 if(current_viewport) {
699 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)current_viewport;
700 viewport_activate(vp, TRUE);
701 IDirect3DViewport3_Release(current_viewport);
704 LeaveCriticalSection(&ddraw_cs);
705 return hr;
708 /*****************************************************************************
709 * IDirect3DViewport3::AddLight
711 * Adds an light to the viewport
713 * Params:
714 * lpDirect3DLight: Interface of the light to add
716 * Returns:
717 * D3D_OK on success
718 * DDERR_INVALIDPARAMS if Direct3DLight is NULL
719 * DDERR_INVALIDPARAMS if there are 8 lights or more
721 *****************************************************************************/
722 static HRESULT WINAPI
723 IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface,
724 IDirect3DLight *lpDirect3DLight)
726 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
727 IDirect3DLightImpl *lpDirect3DLightImpl = (IDirect3DLightImpl *)lpDirect3DLight;
728 DWORD i = 0;
729 DWORD map = This->map_lights;
731 TRACE("iface %p, light %p.\n", iface, lpDirect3DLight);
733 EnterCriticalSection(&ddraw_cs);
734 if (This->num_lights >= 8)
736 LeaveCriticalSection(&ddraw_cs);
737 return DDERR_INVALIDPARAMS;
740 /* Find a light number and update both light and viewports objects accordingly */
741 while(map&1) {
742 map>>=1;
743 i++;
745 lpDirect3DLightImpl->dwLightIndex = i;
746 This->num_lights++;
747 This->map_lights |= 1<<i;
749 /* Add the light in the 'linked' chain */
750 lpDirect3DLightImpl->next = This->lights;
751 This->lights = lpDirect3DLightImpl;
752 IDirect3DLight_AddRef(lpDirect3DLight);
754 /* Attach the light to the viewport */
755 lpDirect3DLightImpl->active_viewport = This;
757 /* If active, activate the light */
758 if (This->active_device)
759 light_activate(lpDirect3DLightImpl);
761 LeaveCriticalSection(&ddraw_cs);
762 return D3D_OK;
765 /*****************************************************************************
766 * IDirect3DViewport3::DeleteLight
768 * Deletes a light from the viewports' light list
770 * Params:
771 * lpDirect3DLight: Light to delete
773 * Returns:
774 * D3D_OK on success
775 * DDERR_INVALIDPARAMS if the light wasn't found
777 *****************************************************************************/
778 static HRESULT WINAPI
779 IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3 *iface,
780 IDirect3DLight *lpDirect3DLight)
782 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
783 IDirect3DLightImpl *lpDirect3DLightImpl = (IDirect3DLightImpl *)lpDirect3DLight;
784 IDirect3DLightImpl *cur_light, *prev_light = NULL;
786 TRACE("iface %p, light %p.\n", iface, lpDirect3DLight);
788 EnterCriticalSection(&ddraw_cs);
789 cur_light = This->lights;
790 while (cur_light != NULL) {
791 if (cur_light == lpDirect3DLightImpl)
793 light_deactivate(lpDirect3DLightImpl);
794 if (prev_light == NULL) This->lights = cur_light->next;
795 else prev_light->next = cur_light->next;
796 /* Detach the light to the viewport */
797 cur_light->active_viewport = NULL;
798 IDirect3DLight_Release( (IDirect3DLight *)cur_light );
799 This->num_lights--;
800 This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
801 LeaveCriticalSection(&ddraw_cs);
802 return D3D_OK;
804 prev_light = cur_light;
805 cur_light = cur_light->next;
807 LeaveCriticalSection(&ddraw_cs);
809 return DDERR_INVALIDPARAMS;
812 /*****************************************************************************
813 * IDirect3DViewport::NextLight
815 * Enumerates the lights associated with the viewport
817 * Params:
818 * lpDirect3DLight: Light to start with
819 * lplpDirect3DLight: Address to store the successor to
821 * Returns:
822 * D3D_OK, because it's a stub
824 *****************************************************************************/
825 static HRESULT WINAPI
826 IDirect3DViewportImpl_NextLight(IDirect3DViewport3 *iface,
827 IDirect3DLight *lpDirect3DLight,
828 IDirect3DLight **lplpDirect3DLight,
829 DWORD dwFlags)
831 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
832 IDirect3DLightImpl *cur_light, *prev_light = NULL;
834 TRACE("iface %p, light %p, next_light %p, flags %#x.\n",
835 iface, lpDirect3DLight, lplpDirect3DLight, dwFlags);
837 if (!lplpDirect3DLight)
838 return DDERR_INVALIDPARAMS;
840 *lplpDirect3DLight = NULL;
842 EnterCriticalSection(&ddraw_cs);
844 cur_light = This->lights;
846 switch (dwFlags) {
847 case D3DNEXT_NEXT:
848 if (!lpDirect3DLight) {
849 LeaveCriticalSection(&ddraw_cs);
850 return DDERR_INVALIDPARAMS;
852 while (cur_light != NULL) {
853 if (cur_light == (IDirect3DLightImpl *)lpDirect3DLight) {
854 *lplpDirect3DLight = (IDirect3DLight*)cur_light->next;
855 break;
857 cur_light = cur_light->next;
859 break;
860 case D3DNEXT_HEAD:
861 *lplpDirect3DLight = (IDirect3DLight*)This->lights;
862 break;
863 case D3DNEXT_TAIL:
864 while (cur_light != NULL) {
865 prev_light = cur_light;
866 cur_light = cur_light->next;
868 *lplpDirect3DLight = (IDirect3DLight*)prev_light;
869 break;
870 default:
871 ERR("Unknown flag %d\n", dwFlags);
872 break;
875 if (*lplpDirect3DLight)
876 IDirect3DLight_AddRef(*lplpDirect3DLight);
878 LeaveCriticalSection(&ddraw_cs);
880 return *lplpDirect3DLight ? D3D_OK : DDERR_INVALIDPARAMS;
883 /*****************************************************************************
884 * IDirect3DViewport2 Methods.
885 *****************************************************************************/
887 /*****************************************************************************
888 * IDirect3DViewport3::GetViewport2
890 * Returns the currently set viewport in a D3DVIEWPORT2 structure.
891 * Similar to IDirect3DViewport3::GetViewport
893 * Params:
894 * lpData: Pointer to the structure to fill
896 * Returns:
897 * D3D_OK on success
898 * DDERR_INVALIDPARAMS if the viewport was set with
899 * IDirect3DViewport3::SetViewport
900 * DDERR_INVALIDPARAMS if Data is NULL
902 *****************************************************************************/
903 static HRESULT WINAPI
904 IDirect3DViewportImpl_GetViewport2(IDirect3DViewport3 *iface,
905 D3DVIEWPORT2 *lpData)
907 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
908 DWORD dwSize;
910 TRACE("iface %p, data %p.\n", iface, lpData);
912 EnterCriticalSection(&ddraw_cs);
913 dwSize = lpData->dwSize;
914 memset(lpData, 0, dwSize);
915 if (This->use_vp2)
916 memcpy(lpData, &(This->viewports.vp2), dwSize);
917 else {
918 D3DVIEWPORT2 vp2;
919 vp2.dwSize = sizeof(vp2);
920 vp2.dwX = This->viewports.vp1.dwX;
921 vp2.dwY = This->viewports.vp1.dwY;
922 vp2.dwWidth = This->viewports.vp1.dwWidth;
923 vp2.dwHeight = This->viewports.vp1.dwHeight;
924 vp2.dvClipX = 0.0;
925 vp2.dvClipY = 0.0;
926 vp2.dvClipWidth = 0.0;
927 vp2.dvClipHeight = 0.0;
928 vp2.dvMinZ = This->viewports.vp1.dvMinZ;
929 vp2.dvMaxZ = This->viewports.vp1.dvMaxZ;
930 memcpy(lpData, &vp2, dwSize);
933 if (TRACE_ON(ddraw))
935 TRACE(" returning D3DVIEWPORT2 :\n");
936 _dump_D3DVIEWPORT2(lpData);
939 LeaveCriticalSection(&ddraw_cs);
940 return D3D_OK;
943 /*****************************************************************************
944 * IDirect3DViewport3::SetViewport2
946 * Sets the viewport from a D3DVIEWPORT2 structure
948 * Params:
949 * lpData: Viewport to set
951 * Returns:
952 * D3D_OK on success
954 *****************************************************************************/
955 static HRESULT WINAPI
956 IDirect3DViewportImpl_SetViewport2(IDirect3DViewport3 *iface,
957 D3DVIEWPORT2 *lpData)
959 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
960 LPDIRECT3DVIEWPORT3 current_viewport;
962 TRACE("iface %p, data %p.\n", iface, lpData);
964 if (TRACE_ON(ddraw))
966 TRACE(" getting D3DVIEWPORT2 :\n");
967 _dump_D3DVIEWPORT2(lpData);
970 EnterCriticalSection(&ddraw_cs);
971 This->use_vp2 = 1;
972 memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
973 memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
975 if (This->active_device) {
976 IDirect3DDevice3 *d3d_device3 = (IDirect3DDevice3 *)&This->active_device->IDirect3DDevice3_vtbl;
977 IDirect3DDevice3_GetCurrentViewport(d3d_device3, &current_viewport);
978 if (current_viewport)
980 if ((IDirect3DViewportImpl *)current_viewport == This) viewport_activate(This, FALSE);
981 IDirect3DViewport3_Release(current_viewport);
984 LeaveCriticalSection(&ddraw_cs);
986 return D3D_OK;
989 /*****************************************************************************
990 * IDirect3DViewport3 Methods.
991 *****************************************************************************/
993 /*****************************************************************************
994 * IDirect3DViewport3::SetBackgroundDepth2
996 * Sets a IDirectDrawSurface4 surface as the background depth surface
998 * Params:
999 * lpDDS: Surface to set
1001 * Returns:
1002 * D3D_OK, because it's stub
1004 *****************************************************************************/
1005 static HRESULT WINAPI
1006 IDirect3DViewportImpl_SetBackgroundDepth2(IDirect3DViewport3 *iface,
1007 IDirectDrawSurface4 *lpDDS)
1009 FIXME("iface %p, surface %p stub!\n", iface, lpDDS);
1011 return D3D_OK;
1014 /*****************************************************************************
1015 * IDirect3DViewport3::GetBackgroundDepth2
1017 * Returns the IDirect3DSurface4 interface to the background depth surface
1019 * Params:
1020 * lplpDDS: Address to store the interface pointer at
1021 * lpValid: Set to true if a surface is assigned
1023 * Returns:
1024 * D3D_OK because it's a stub
1026 *****************************************************************************/
1027 static HRESULT WINAPI
1028 IDirect3DViewportImpl_GetBackgroundDepth2(IDirect3DViewport3 *iface,
1029 IDirectDrawSurface4 **lplpDDS,
1030 BOOL *lpValid)
1032 FIXME("iface %p, surface %p, valid %p stub!\n", iface, lplpDDS, lpValid);
1034 return D3D_OK;
1037 /*****************************************************************************
1038 * IDirect3DViewport3::Clear2
1040 * Another clearing method
1042 * Params:
1043 * Count: Number of rectangles to clear
1044 * Rects: Rectangle array to clear
1045 * Flags: Some flags :)
1046 * Color: Color to fill the render target with
1047 * Z: Value to fill the depth buffer with
1048 * Stencil: Value to fill the stencil bits with
1050 * Returns:
1052 *****************************************************************************/
1053 static HRESULT WINAPI
1054 IDirect3DViewportImpl_Clear2(IDirect3DViewport3 *iface,
1055 DWORD dwCount,
1056 LPD3DRECT lpRects,
1057 DWORD dwFlags,
1058 DWORD dwColor,
1059 D3DVALUE dvZ,
1060 DWORD dwStencil)
1062 IDirect3DViewportImpl *This = (IDirect3DViewportImpl *)iface;
1063 HRESULT hr;
1064 LPDIRECT3DVIEWPORT3 current_viewport;
1065 IDirect3DDevice3 *d3d_device3;
1067 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n",
1068 iface, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1070 EnterCriticalSection(&ddraw_cs);
1071 if (This->active_device == NULL) {
1072 ERR(" Trying to clear a viewport not attached to a device !\n");
1073 LeaveCriticalSection(&ddraw_cs);
1074 return D3DERR_VIEWPORTHASNODEVICE;
1076 d3d_device3 = (IDirect3DDevice3 *)&This->active_device->IDirect3DDevice3_vtbl;
1077 /* Need to temporarily activate viewport to clear it. Previously active
1078 * one will be restored afterwards. */
1079 viewport_activate(This, TRUE);
1081 hr = IDirect3DDevice7_Clear((IDirect3DDevice7 *)This->active_device,
1082 dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1083 IDirect3DDevice3_GetCurrentViewport(d3d_device3, &current_viewport);
1084 if(current_viewport) {
1085 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)current_viewport;
1086 viewport_activate(vp, TRUE);
1087 IDirect3DViewport3_Release(current_viewport);
1089 LeaveCriticalSection(&ddraw_cs);
1090 return hr;
1093 /*****************************************************************************
1094 * The VTable
1095 *****************************************************************************/
1097 static const struct IDirect3DViewport3Vtbl d3d_viewport_vtbl =
1099 /*** IUnknown Methods ***/
1100 IDirect3DViewportImpl_QueryInterface,
1101 IDirect3DViewportImpl_AddRef,
1102 IDirect3DViewportImpl_Release,
1103 /*** IDirect3DViewport Methods */
1104 IDirect3DViewportImpl_Initialize,
1105 IDirect3DViewportImpl_GetViewport,
1106 IDirect3DViewportImpl_SetViewport,
1107 IDirect3DViewportImpl_TransformVertices,
1108 IDirect3DViewportImpl_LightElements,
1109 IDirect3DViewportImpl_SetBackground,
1110 IDirect3DViewportImpl_GetBackground,
1111 IDirect3DViewportImpl_SetBackgroundDepth,
1112 IDirect3DViewportImpl_GetBackgroundDepth,
1113 IDirect3DViewportImpl_Clear,
1114 IDirect3DViewportImpl_AddLight,
1115 IDirect3DViewportImpl_DeleteLight,
1116 IDirect3DViewportImpl_NextLight,
1117 /*** IDirect3DViewport2 Methods ***/
1118 IDirect3DViewportImpl_GetViewport2,
1119 IDirect3DViewportImpl_SetViewport2,
1120 /*** IDirect3DViewport3 Methods ***/
1121 IDirect3DViewportImpl_SetBackgroundDepth2,
1122 IDirect3DViewportImpl_GetBackgroundDepth2,
1123 IDirect3DViewportImpl_Clear2,
1126 void d3d_viewport_init(IDirect3DViewportImpl *viewport, IDirectDrawImpl *ddraw)
1128 viewport->lpVtbl = &d3d_viewport_vtbl;
1129 viewport->ref = 1;
1130 viewport->ddraw = ddraw;
1131 viewport->use_vp2 = 0xff;