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