- actually use the background color when Clear-ing
[wine] / dlls / ddraw / d3dviewport.c
1 /* Direct3D Viewport
2  * Copyright (c) 1998 Lionel ULMER
3  *
4  * This file contains the implementation of Direct3DViewport2.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "windef.h"
23 #include "winerror.h"
24 #include "objbase.h"
25 #include "ddraw.h"
26 #include "d3d.h"
27 #include "wine/debug.h"
28
29 #include "d3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
32
33 static void activate(IDirect3DViewportImpl* This) {
34     IDirect3DLightImpl* light;
35
36     /* Activate all the lights associated with this context */
37     light = This->lights;
38
39     while (light != NULL) {
40         light->activate(light);
41         light = light->next;
42     }
43 }
44
45
46 static void _dump_D3DVIEWPORT(D3DVIEWPORT *lpvp)
47 {
48     TRACE("    - dwSize = %ld   dwX = %ld   dwY = %ld\n",
49           lpvp->dwSize, lpvp->dwX, lpvp->dwY);
50     TRACE("    - dwWidth = %ld   dwHeight = %ld\n",
51           lpvp->dwWidth, lpvp->dwHeight);
52     TRACE("    - dvScaleX = %f   dvScaleY = %f\n",
53           lpvp->dvScaleX, lpvp->dvScaleY);
54     TRACE("    - dvMaxX = %f   dvMaxY = %f\n",
55           lpvp->dvMaxX, lpvp->dvMaxY);
56     TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
57           lpvp->dvMinZ, lpvp->dvMaxZ);
58 }
59
60 static void _dump_D3DVIEWPORT2(D3DVIEWPORT2 *lpvp)
61 {
62     TRACE("    - dwSize = %ld   dwX = %ld   dwY = %ld\n",
63           lpvp->dwSize, lpvp->dwX, lpvp->dwY);
64     TRACE("    - dwWidth = %ld   dwHeight = %ld\n",
65           lpvp->dwWidth, lpvp->dwHeight);
66     TRACE("    - dvClipX = %f   dvClipY = %f\n",
67           lpvp->dvClipX, lpvp->dvClipY);
68     TRACE("    - dvClipWidth = %f   dvClipHeight = %f\n",
69           lpvp->dvClipWidth, lpvp->dvClipHeight);
70     TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
71           lpvp->dvMinZ, lpvp->dvMaxZ);
72 }
73
74 HRESULT WINAPI
75 Main_IDirect3DViewportImpl_3_2_1_QueryInterface(LPDIRECT3DVIEWPORT3 iface,
76                                                 REFIID riid,
77                                                 LPVOID* obp)
78 {
79     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
80     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
81
82     *obp = NULL;
83
84     if ( IsEqualGUID(&IID_IUnknown,  riid) ||
85          IsEqualGUID(&IID_IDirect3DViewport, riid) ||
86          IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
87          IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
88         IDirect3DViewport3_AddRef(ICOM_INTERFACE(This, IDirect3DViewport3));
89         *obp = ICOM_INTERFACE(This, IDirect3DViewport3);
90         TRACE("  Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
91         return S_OK;
92     }
93     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
94     return OLE_E_ENUM_NOMORE;
95 }
96
97 ULONG WINAPI
98 Main_IDirect3DViewportImpl_3_2_1_AddRef(LPDIRECT3DVIEWPORT3 iface)
99 {
100     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
101     FIXME("(%p/%p)->() incrementing from %lu.\n", This, iface, This->ref);
102     return ++(This->ref);
103 }
104
105 ULONG WINAPI
106 Main_IDirect3DViewportImpl_3_2_1_Release(LPDIRECT3DVIEWPORT3 iface)
107 {
108     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
109     FIXME("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
110     if (!--(This->ref)) {
111         HeapFree(GetProcessHeap(), 0, This);
112         return 0;
113     }
114     return This->ref;
115 }
116
117
118 HRESULT WINAPI
119 Main_IDirect3DViewportImpl_3_2_1_Initialize(LPDIRECT3DVIEWPORT3 iface,
120                                             LPDIRECT3D lpDirect3D)
121 {
122     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
123     TRACE("(%p/%p)->(%p) no-op...\n", This, iface, lpDirect3D);
124     return DD_OK;
125 }
126
127 HRESULT WINAPI
128 Main_IDirect3DViewportImpl_3_2_1_GetViewport(LPDIRECT3DVIEWPORT3 iface,
129                                              LPD3DVIEWPORT lpData)
130 {
131     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
132     DWORD dwSize;
133     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
134     if (This->use_vp2 != 0) {
135         ERR("  Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
136         return DDERR_INVALIDPARAMS;
137     }
138     dwSize = lpData->dwSize;
139     memset(lpData, 0, dwSize);
140     memcpy(lpData, &(This->viewports.vp1), dwSize);
141
142     if (TRACE_ON(ddraw)) {
143         TRACE("  returning D3DVIEWPORT :\n");
144         _dump_D3DVIEWPORT(lpData);
145     }
146     
147     return DD_OK;
148 }
149
150 HRESULT WINAPI
151 Main_IDirect3DViewportImpl_3_2_1_SetViewport(LPDIRECT3DVIEWPORT3 iface,
152                                              LPD3DVIEWPORT lpData)
153 {
154     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
155     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
156
157     if (TRACE_ON(ddraw)) {
158         TRACE("  getting D3DVIEWPORT :\n");
159         _dump_D3DVIEWPORT(lpData);
160     }
161
162     This->use_vp2 = 0;
163     memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
164     memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);
165     return DD_OK;
166 }
167
168 HRESULT WINAPI
169 Main_IDirect3DViewportImpl_3_2_1_TransformVertices(LPDIRECT3DVIEWPORT3 iface,
170                                                    DWORD dwVertexCount,
171                                                    LPD3DTRANSFORMDATA lpData,
172                                                    DWORD dwFlags,
173                                                    LPDWORD lpOffScreen)
174 {
175     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
176     FIXME("(%p/%p)->(%08lx,%p,%08lx,%p): stub!\n", This, iface, dwVertexCount, lpData, dwFlags, lpOffScreen);
177     return DD_OK;
178 }
179
180 HRESULT WINAPI
181 Main_IDirect3DViewportImpl_3_2_1_LightElements(LPDIRECT3DVIEWPORT3 iface,
182                                                DWORD dwElementCount,
183                                                LPD3DLIGHTDATA lpData)
184 {
185     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
186     FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwElementCount, lpData);
187     return DD_OK;
188 }
189
190 HRESULT WINAPI
191 Main_IDirect3DViewportImpl_3_2_1_SetBackground(LPDIRECT3DVIEWPORT3 iface,
192                                                D3DMATERIALHANDLE hMat)
193 {
194     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
195     TRACE("(%p/%p)->(%08lx)\n", This, iface, (DWORD) hMat);
196     
197     This->background = (IDirect3DMaterialImpl *) hMat;
198     TRACE(" setting background color : %f %f %f %f\n",
199           This->background->mat.u.diffuse.u1.r,
200           This->background->mat.u.diffuse.u2.g,
201           This->background->mat.u.diffuse.u3.b,
202           This->background->mat.u.diffuse.u4.a);
203
204     return DD_OK;
205 }
206
207 HRESULT WINAPI
208 Main_IDirect3DViewportImpl_3_2_1_GetBackground(LPDIRECT3DVIEWPORT3 iface,
209                                                LPD3DMATERIALHANDLE lphMat,
210                                                LPBOOL lpValid)
211 {
212     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
213     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lphMat, lpValid);
214     return DD_OK;
215 }
216
217 HRESULT WINAPI
218 Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
219                                                     LPDIRECTDRAWSURFACE lpDDSurface)
220 {
221     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
222     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDSurface);
223     return DD_OK;
224 }
225
226 HRESULT WINAPI
227 Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth(LPDIRECT3DVIEWPORT3 iface,
228                                                     LPDIRECTDRAWSURFACE* lplpDDSurface,
229                                                     LPBOOL lpValid)
230 {
231     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
232     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDSurface, lpValid);
233     return DD_OK;
234 }
235
236 HRESULT WINAPI
237 Main_IDirect3DViewportImpl_3_2_1_Clear(LPDIRECT3DVIEWPORT3 iface,
238                                        DWORD dwCount,
239                                        LPD3DRECT lpRects,
240                                        DWORD dwFlags)
241 {
242     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
243     DWORD color = 0x00000000;
244     
245     TRACE("(%p/%p)->(%08lx,%p,%08lx)\n", This, iface, dwCount, lpRects, dwFlags);
246     if (This->active_device == NULL) {
247         ERR(" Trying to clear a viewport not attached to a device !\n");
248         return D3DERR_VIEWPORTHASNODEVICE;
249     }
250     if (dwFlags & D3DCLEAR_TARGET) {
251         if (This->background == NULL) {
252             ERR(" Trying to clear the color buffer without background material !\n");
253         } else {
254             color = 
255               ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) |
256               ((int) ((This->background->mat.u.diffuse.u2.g) * 255) <<  8) |
257               ((int) ((This->background->mat.u.diffuse.u3.b) * 255) <<  0) |
258               ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
259         }
260     }
261     return This->active_device->clear(This->active_device, dwCount, lpRects, 
262                                       dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET),
263                                       color, 1.0, 0x00000000);
264 }
265
266 HRESULT WINAPI
267 Main_IDirect3DViewportImpl_3_2_1_AddLight(LPDIRECT3DVIEWPORT3 iface,
268                                           LPDIRECT3DLIGHT lpDirect3DLight)
269 {
270     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
271     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
272     
273     TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
274     
275     /* Add the light in the 'linked' chain */
276     lpDirect3DLightImpl->next = This->lights;
277     This->lights = lpDirect3DLightImpl;
278
279     /* If active, activate the light */
280     if (This->active_device != NULL) {
281         lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
282     }
283     
284     return DD_OK;
285 }
286
287 HRESULT WINAPI
288 Main_IDirect3DViewportImpl_3_2_1_DeleteLight(LPDIRECT3DVIEWPORT3 iface,
289                                              LPDIRECT3DLIGHT lpDirect3DLight)
290 {
291     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
292     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
293     IDirect3DLightImpl *cur_light, *prev_light = NULL;
294     
295     TRACE("(%p/%p)->(%p)\n", This, iface, lpDirect3DLight);
296     cur_light = This->lights;
297     while (cur_light != NULL) {
298         if (cur_light == lpDirect3DLightImpl) {
299             lpDirect3DLightImpl->desactivate(lpDirect3DLightImpl);
300             if (prev_light == NULL) This->lights = cur_light->next;
301             else prev_light->next = cur_light->next;
302             return DD_OK;
303         }
304         prev_light = cur_light;
305         cur_light = cur_light->next;
306     }
307     return DDERR_INVALIDPARAMS;
308 }
309
310 HRESULT WINAPI
311 Main_IDirect3DViewportImpl_3_2_1_NextLight(LPDIRECT3DVIEWPORT3 iface,
312                                            LPDIRECT3DLIGHT lpDirect3DLight,
313                                            LPDIRECT3DLIGHT* lplpDirect3DLight,
314                                            DWORD dwFlags)
315 {
316     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
317     FIXME("(%p/%p)->(%p,%p,%08lx): stub!\n", This, iface, lpDirect3DLight, lplpDirect3DLight, dwFlags);
318     return DD_OK;
319 }
320
321 HRESULT WINAPI
322 Main_IDirect3DViewportImpl_3_2_GetViewport2(LPDIRECT3DVIEWPORT3 iface,
323                                             LPD3DVIEWPORT2 lpData)
324 {
325     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
326     DWORD dwSize;
327     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
328     if (This->use_vp2 != 1) {
329         ERR("  Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
330         return DDERR_INVALIDPARAMS;
331     }
332     dwSize = lpData->dwSize;
333     memset(lpData, 0, dwSize);
334     memcpy(lpData, &(This->viewports.vp2), dwSize);
335
336     if (TRACE_ON(ddraw)) {
337         TRACE("  returning D3DVIEWPORT2 :\n");
338         _dump_D3DVIEWPORT2(lpData);
339     }
340     
341     return DD_OK;
342 }
343
344 HRESULT WINAPI
345 Main_IDirect3DViewportImpl_3_2_SetViewport2(LPDIRECT3DVIEWPORT3 iface,
346                                             LPD3DVIEWPORT2 lpData)
347 {
348     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
349     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
350
351     if (TRACE_ON(ddraw)) {
352         TRACE("  getting D3DVIEWPORT2 :\n");
353         _dump_D3DVIEWPORT2(lpData);
354     }
355
356     This->use_vp2 = 1;
357     memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
358     memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
359     return DD_OK;
360 }
361
362 HRESULT WINAPI
363 Main_IDirect3DViewportImpl_3_SetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
364                                                  LPDIRECTDRAWSURFACE4 lpDDS)
365 {
366     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
367     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpDDS);
368     return DD_OK;
369 }
370
371 HRESULT WINAPI
372 Main_IDirect3DViewportImpl_3_GetBackgroundDepth2(LPDIRECT3DVIEWPORT3 iface,
373                                                  LPDIRECTDRAWSURFACE4* lplpDDS,
374                                                  LPBOOL lpValid)
375 {
376     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
377     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDDS, lpValid);
378     return DD_OK;
379 }
380
381 HRESULT WINAPI
382 Main_IDirect3DViewportImpl_3_Clear2(LPDIRECT3DVIEWPORT3 iface,
383                                     DWORD dwCount,
384                                     LPD3DRECT lpRects,
385                                     DWORD dwFlags,
386                                     DWORD dwColor,
387                                     D3DVALUE dvZ,
388                                     DWORD dwStencil)
389 {
390     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
391     TRACE("(%p/%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, iface, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
392     if (This->active_device == NULL) {
393         ERR(" Trying to clear a viewport not attached to a device !\n");
394         return D3DERR_VIEWPORTHASNODEVICE;
395     }
396     return This->active_device->clear(This->active_device, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
397 }
398
399 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
400 # define XCAST(fun)     (typeof(VTABLE_IDirect3DViewport3.fun))
401 #else
402 # define XCAST(fun)     (void*)
403 #endif
404
405 ICOM_VTABLE(IDirect3DViewport3) VTABLE_IDirect3DViewport3 =
406 {
407     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
408     XCAST(QueryInterface) Main_IDirect3DViewportImpl_3_2_1_QueryInterface,
409     XCAST(AddRef) Main_IDirect3DViewportImpl_3_2_1_AddRef,
410     XCAST(Release) Main_IDirect3DViewportImpl_3_2_1_Release,
411     XCAST(Initialize) Main_IDirect3DViewportImpl_3_2_1_Initialize,
412     XCAST(GetViewport) Main_IDirect3DViewportImpl_3_2_1_GetViewport,
413     XCAST(SetViewport) Main_IDirect3DViewportImpl_3_2_1_SetViewport,
414     XCAST(TransformVertices) Main_IDirect3DViewportImpl_3_2_1_TransformVertices,
415     XCAST(LightElements) Main_IDirect3DViewportImpl_3_2_1_LightElements,
416     XCAST(SetBackground) Main_IDirect3DViewportImpl_3_2_1_SetBackground,
417     XCAST(GetBackground) Main_IDirect3DViewportImpl_3_2_1_GetBackground,
418     XCAST(SetBackgroundDepth) Main_IDirect3DViewportImpl_3_2_1_SetBackgroundDepth,
419     XCAST(GetBackgroundDepth) Main_IDirect3DViewportImpl_3_2_1_GetBackgroundDepth,
420     XCAST(Clear) Main_IDirect3DViewportImpl_3_2_1_Clear,
421     XCAST(AddLight) Main_IDirect3DViewportImpl_3_2_1_AddLight,
422     XCAST(DeleteLight) Main_IDirect3DViewportImpl_3_2_1_DeleteLight,
423     XCAST(NextLight) Main_IDirect3DViewportImpl_3_2_1_NextLight,
424     XCAST(GetViewport2) Main_IDirect3DViewportImpl_3_2_GetViewport2,
425     XCAST(SetViewport2) Main_IDirect3DViewportImpl_3_2_SetViewport2,
426     XCAST(SetBackgroundDepth2) Main_IDirect3DViewportImpl_3_SetBackgroundDepth2,
427     XCAST(GetBackgroundDepth2) Main_IDirect3DViewportImpl_3_GetBackgroundDepth2,
428     XCAST(Clear2) Main_IDirect3DViewportImpl_3_Clear2,
429 };
430
431 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
432 #undef XCAST
433 #endif
434
435
436
437
438 HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirect3DImpl *d3d)
439 {
440     IDirect3DViewportImpl *object;
441
442     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DViewportImpl));
443     if (object == NULL) return DDERR_OUTOFMEMORY;
444
445     object->ref = 1;
446     object->d3d = d3d;
447     object->activate = activate;
448     object->use_vp2 = 0xFF;
449     object->next = NULL;
450     object->lights = NULL;
451     
452     ICOM_INIT_INTERFACE(object, IDirect3DViewport3, VTABLE_IDirect3DViewport3);
453
454     *obj = object;
455
456     TRACE(" creating implementation at %p.\n", *obj);
457     
458     return D3D_OK;
459 }