Fix matrix multiplication.
[wine] / dlls / ddraw / d3dmaterial.c
1 /* Direct3D Material
2  * Copyright (c) 2002 Lionel ULMER
3  *
4  * This file contains the implementation of Direct3DMaterial.
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 #include "mesa_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
35
36 static void dump_material(LPD3DMATERIAL mat)
37 {
38     DPRINTF("  dwSize : %ld\n", mat->dwSize);
39 }
40
41 HRESULT WINAPI
42 Main_IDirect3DMaterialImpl_3_2T_1T_QueryInterface(LPDIRECT3DMATERIAL3 iface,
43                                                   REFIID riid,
44                                                   LPVOID* obp)
45 {
46     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial3, iface);
47     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
48
49     *obp = NULL;
50
51     if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
52         IDirect3DMaterial_AddRef(ICOM_INTERFACE(This, IDirect3DMaterial));
53         *obp = iface;
54         TRACE("  Creating IUnknown interface at %p.\n", *obp);
55         return S_OK;
56     }
57     if ( IsEqualGUID( &IID_IDirect3DMaterial, riid ) ) {
58         IDirect3DMaterial_AddRef(ICOM_INTERFACE(This, IDirect3DMaterial));
59         *obp = ICOM_INTERFACE(This, IDirect3DMaterial);
60         TRACE("  Creating IDirect3DMaterial interface %p\n", *obp);
61         return S_OK;
62     }
63     if ( IsEqualGUID( &IID_IDirect3DMaterial2, riid ) ) {
64         IDirect3DMaterial_AddRef(ICOM_INTERFACE(This, IDirect3DMaterial));
65         *obp = ICOM_INTERFACE(This, IDirect3DMaterial2);
66         TRACE("  Creating IDirect3DMaterial2 interface %p\n", *obp);
67         return S_OK;
68     }
69     if ( IsEqualGUID( &IID_IDirect3DMaterial3, riid ) ) {
70         IDirect3DMaterial_AddRef(ICOM_INTERFACE(This, IDirect3DMaterial));
71         *obp = ICOM_INTERFACE(This, IDirect3DMaterial3);
72         TRACE("  Creating IDirect3DMaterial3 interface %p\n", *obp);
73         return S_OK;
74     }
75     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
76     return OLE_E_ENUM_NOMORE;
77 }
78
79 ULONG WINAPI
80 Main_IDirect3DMaterialImpl_3_2T_1T_AddRef(LPDIRECT3DMATERIAL3 iface)
81 {
82     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial3, iface);
83     TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, This->ref);
84     return ++(This->ref);
85 }
86
87 ULONG WINAPI
88 Main_IDirect3DMaterialImpl_3_2T_1T_Release(LPDIRECT3DMATERIAL3 iface)
89 {
90     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial3, iface);
91     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
92     if (!--(This->ref)) {
93         HeapFree(GetProcessHeap(), 0, This);
94         return 0;
95     }
96     return This->ref;
97 }
98
99 HRESULT WINAPI
100 Main_IDirect3DMaterialImpl_1_Initialize(LPDIRECT3DMATERIAL iface,
101                                         LPDIRECT3D lpDirect3D)
102 {
103     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial, iface);
104     TRACE("(%p/%p)->(%p) no-op...!\n", This, iface, lpDirect3D);
105     return DD_OK;
106 }
107
108 HRESULT WINAPI
109 Main_IDirect3DMaterialImpl_1_Reserve(LPDIRECT3DMATERIAL iface)
110 {
111     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial, iface);
112     TRACE("(%p/%p)->() not implemented.\n", This, iface);
113     return DD_OK;
114 }
115
116 HRESULT WINAPI
117 Main_IDirect3DMaterialImpl_1_Unreserve(LPDIRECT3DMATERIAL iface)
118 {
119     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial, iface);
120     FIXME("(%p/%p)->() not implemented.\n", This, iface);
121     return DD_OK;
122 }
123
124 HRESULT WINAPI
125 Main_IDirect3DMaterialImpl_3_2T_1T_SetMaterial(LPDIRECT3DMATERIAL3 iface,
126                                                LPD3DMATERIAL lpMat)
127 {
128     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial3, iface);
129     TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
130     if (TRACE_ON(ddraw))
131         dump_material(lpMat);
132
133     /* Stores the material */
134     memset(&This->mat, 0, sizeof(This->mat));
135     memcpy(&This->mat, lpMat, lpMat->dwSize);
136     
137     return DD_OK;
138 }
139
140 HRESULT WINAPI
141 Main_IDirect3DMaterialImpl_3_2T_1T_GetMaterial(LPDIRECT3DMATERIAL3 iface,
142                                                LPD3DMATERIAL lpMat)
143 {
144     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial3, iface);
145     DWORD dwSize;
146     TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
147     if (TRACE_ON(ddraw)) {
148         TRACE("  Returning material : ");
149         dump_material(&This->mat);
150     }
151
152     /* Copies the material structure */
153     dwSize = lpMat->dwSize;
154     memset(lpMat, 0, dwSize);
155     memcpy(lpMat, &This->mat, dwSize);
156
157     return DD_OK;
158 }
159
160 HRESULT WINAPI
161 Main_IDirect3DMaterialImpl_3_2T_1T_GetHandle(LPDIRECT3DMATERIAL3 iface,
162                                              LPDIRECT3DDEVICE3 lpDirect3DDevice3,
163                                              LPD3DMATERIALHANDLE lpHandle)
164 {
165     ICOM_THIS_FROM(IDirect3DMaterialImpl, IDirect3DMaterial3, iface);
166     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice3, lpHandle);
167
168     This->active_device = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice3, lpDirect3DDevice3);
169     *lpHandle = (DWORD) This; /* Warning: this is not 64 bit clean.
170                                  Maybe also we need to store this material somewhere in the device ? */
171
172     TRACE(" returning handle %08lx.\n", *lpHandle);
173     
174     return DD_OK;
175 }
176
177 HRESULT WINAPI
178 Thunk_IDirect3DMaterialImpl_2_GetHandle(LPDIRECT3DMATERIAL2 iface,
179                                         LPDIRECT3DDEVICE2 lpDirect3DDevice2,
180                                         LPD3DMATERIALHANDLE lpHandle)
181 {
182     TRACE("(%p)->(%p,%p) thunking to IDirect3DMaterial3 interface.\n", iface, lpDirect3DDevice2, lpHandle);
183     return IDirect3DMaterial3_GetHandle(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial2, IDirect3DMaterial3, iface),
184                                         COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice2, IDirect3DDevice3, lpDirect3DDevice2),
185                                         lpHandle);
186 }
187
188 HRESULT WINAPI
189 Thunk_IDirect3DMaterialImpl_1_GetHandle(LPDIRECT3DMATERIAL iface,
190                                         LPDIRECT3DDEVICE lpDirect3DDevice,
191                                         LPD3DMATERIALHANDLE lpHandle)
192 {
193     TRACE("(%p)->(%p,%p) thunking to IDirect3DMaterial3 interface.\n", iface, lpDirect3DDevice, lpHandle);
194     return IDirect3DMaterial3_GetHandle(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial, IDirect3DMaterial3, iface),
195                                         COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice3, lpDirect3DDevice),
196                                         lpHandle);
197 }
198
199 HRESULT WINAPI
200 Thunk_IDirect3DMaterialImpl_2_QueryInterface(LPDIRECT3DMATERIAL2 iface,
201                                              REFIID riid,
202                                              LPVOID* obp)
203 {
204     TRACE("(%p)->(%s,%p) thunking to IDirect3DMaterial3 interface.\n", iface, debugstr_guid(riid), obp);
205     return IDirect3DMaterial3_QueryInterface(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial2, IDirect3DMaterial3, iface),
206                                              riid,
207                                              obp);
208 }
209
210 HRESULT WINAPI
211 Thunk_IDirect3DMaterialImpl_1_QueryInterface(LPDIRECT3DMATERIAL iface,
212                                              REFIID riid,
213                                              LPVOID* obp)
214 {
215     TRACE("(%p)->(%s,%p) thunking to IDirect3DMaterial3 interface.\n", iface, debugstr_guid(riid), obp);
216     return IDirect3DMaterial3_QueryInterface(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial, IDirect3DMaterial3, iface),
217                                              riid,
218                                              obp);
219 }
220
221 ULONG WINAPI
222 Thunk_IDirect3DMaterialImpl_2_AddRef(LPDIRECT3DMATERIAL2 iface)
223 {
224     TRACE("(%p)->() thunking to IDirect3DMaterial3 interface.\n", iface);
225     return IDirect3DMaterial3_AddRef(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial2, IDirect3DMaterial3, iface));
226 }
227
228 ULONG WINAPI
229 Thunk_IDirect3DMaterialImpl_1_AddRef(LPDIRECT3DMATERIAL iface)
230 {
231     TRACE("(%p)->() thunking to IDirect3DMaterial3 interface.\n", iface);
232     return IDirect3DMaterial3_AddRef(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial, IDirect3DMaterial3, iface));
233 }
234
235 ULONG WINAPI
236 Thunk_IDirect3DMaterialImpl_2_Release(LPDIRECT3DMATERIAL2 iface)
237 {
238     TRACE("(%p)->() thunking to IDirect3DMaterial3 interface.\n", iface);
239     return IDirect3DMaterial3_Release(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial2, IDirect3DMaterial3, iface));
240 }
241
242 ULONG WINAPI
243 Thunk_IDirect3DMaterialImpl_1_Release(LPDIRECT3DMATERIAL iface)
244 {
245     TRACE("(%p)->() thunking to IDirect3DMaterial3 interface.\n", iface);
246     return IDirect3DMaterial3_Release(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial, IDirect3DMaterial3, iface));
247 }
248
249 HRESULT WINAPI
250 Thunk_IDirect3DMaterialImpl_2_SetMaterial(LPDIRECT3DMATERIAL2 iface,
251                                           LPD3DMATERIAL lpMat)
252 {
253     TRACE("(%p)->(%p) thunking to IDirect3DMaterial3 interface.\n", iface, lpMat);
254     return IDirect3DMaterial3_SetMaterial(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial2, IDirect3DMaterial3, iface),
255                                           lpMat);
256 }
257
258 HRESULT WINAPI
259 Thunk_IDirect3DMaterialImpl_1_SetMaterial(LPDIRECT3DMATERIAL iface,
260                                           LPD3DMATERIAL lpMat)
261 {
262     TRACE("(%p)->(%p) thunking to IDirect3DMaterial3 interface.\n", iface, lpMat);
263     return IDirect3DMaterial3_SetMaterial(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial, IDirect3DMaterial3, iface),
264                                           lpMat);
265 }
266
267 HRESULT WINAPI
268 Thunk_IDirect3DMaterialImpl_2_GetMaterial(LPDIRECT3DMATERIAL2 iface,
269                                           LPD3DMATERIAL lpMat)
270 {
271     TRACE("(%p)->(%p) thunking to IDirect3DMaterial3 interface.\n", iface, lpMat);
272     return IDirect3DMaterial3_GetMaterial(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial2, IDirect3DMaterial3, iface),
273                                           lpMat);
274 }
275
276 HRESULT WINAPI
277 Thunk_IDirect3DMaterialImpl_1_GetMaterial(LPDIRECT3DMATERIAL iface,
278                                           LPD3DMATERIAL lpMat)
279 {
280     TRACE("(%p)->(%p) thunking to IDirect3DMaterial3 interface.\n", iface, lpMat);
281     return IDirect3DMaterial3_GetMaterial(COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial, IDirect3DMaterial3, iface),
282                                           lpMat);
283 }
284
285 /*******************************************************************************
286  *                              Matrial2 static functions
287  */
288 static void activate(IDirect3DMaterialImpl* This) {
289     TRACE("Activating material %p\n", This);
290
291     /* Set the current Material */
292     ENTER_GL();
293     glMaterialfv(GL_FRONT_AND_BACK,
294                  GL_DIFFUSE,
295                  (float *) &(This->mat.u.diffuse));
296     glMaterialfv(GL_FRONT_AND_BACK,
297                  GL_AMBIENT,
298                  (float *) &(This->mat.u1.ambient));
299     glMaterialfv(GL_FRONT_AND_BACK,
300                  GL_SPECULAR,
301                  (float *) &(This->mat.u2.specular));
302     glMaterialfv(GL_FRONT_AND_BACK,
303                  GL_EMISSION,
304                  (float *) &(This->mat.u3.emissive));
305     LEAVE_GL();
306
307   if (TRACE_ON(ddraw)) {
308       DPRINTF(" - size  : %ld\n", This->mat.dwSize);
309       DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(This->mat.u.diffuse)); DPRINTF("\n");
310       DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(This->mat.u1.ambient)); DPRINTF("\n");
311       DPRINTF(" - specular: "); dump_D3DCOLORVALUE(&(This->mat.u2.specular)); DPRINTF("\n");
312       DPRINTF(" - emissive: "); dump_D3DCOLORVALUE(&(This->mat.u3.emissive)); DPRINTF("\n");
313       DPRINTF(" - power : %f\n", This->mat.u4.power);
314       DPRINTF(" - texture handle : %08lx\n", (DWORD)This->mat.hTexture);
315   }
316
317   return ;
318 }
319
320 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
321 # define XCAST(fun)     (typeof(VTABLE_IDirect3DMaterial3.fun))
322 #else
323 # define XCAST(fun)     (void*)
324 #endif
325
326 ICOM_VTABLE(IDirect3DMaterial3) VTABLE_IDirect3DMaterial3 =
327 {
328     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
329     XCAST(QueryInterface) Main_IDirect3DMaterialImpl_3_2T_1T_QueryInterface,
330     XCAST(AddRef) Main_IDirect3DMaterialImpl_3_2T_1T_AddRef,
331     XCAST(Release) Main_IDirect3DMaterialImpl_3_2T_1T_Release,
332     XCAST(SetMaterial) Main_IDirect3DMaterialImpl_3_2T_1T_SetMaterial,
333     XCAST(GetMaterial) Main_IDirect3DMaterialImpl_3_2T_1T_GetMaterial,
334     XCAST(GetHandle) Main_IDirect3DMaterialImpl_3_2T_1T_GetHandle,
335 };
336
337 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
338 #undef XCAST
339 #endif
340
341
342 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
343 # define XCAST(fun)     (typeof(VTABLE_IDirect3DMaterial2.fun))
344 #else
345 # define XCAST(fun)     (void*)
346 #endif
347
348 ICOM_VTABLE(IDirect3DMaterial2) VTABLE_IDirect3DMaterial2 =
349 {
350     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
351     XCAST(QueryInterface) Thunk_IDirect3DMaterialImpl_2_QueryInterface,
352     XCAST(AddRef) Thunk_IDirect3DMaterialImpl_2_AddRef,
353     XCAST(Release) Thunk_IDirect3DMaterialImpl_2_Release,
354     XCAST(SetMaterial) Thunk_IDirect3DMaterialImpl_2_SetMaterial,
355     XCAST(GetMaterial) Thunk_IDirect3DMaterialImpl_2_GetMaterial,
356     XCAST(GetHandle) Thunk_IDirect3DMaterialImpl_2_GetHandle,
357 };
358
359 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
360 #undef XCAST
361 #endif
362
363
364 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
365 # define XCAST(fun)     (typeof(VTABLE_IDirect3DMaterial.fun))
366 #else
367 # define XCAST(fun)     (void*)
368 #endif
369
370 ICOM_VTABLE(IDirect3DMaterial) VTABLE_IDirect3DMaterial =
371 {
372     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
373     XCAST(QueryInterface) Thunk_IDirect3DMaterialImpl_1_QueryInterface,
374     XCAST(AddRef) Thunk_IDirect3DMaterialImpl_1_AddRef,
375     XCAST(Release) Thunk_IDirect3DMaterialImpl_1_Release,
376     XCAST(Initialize) Main_IDirect3DMaterialImpl_1_Initialize,
377     XCAST(SetMaterial) Thunk_IDirect3DMaterialImpl_1_SetMaterial,
378     XCAST(GetMaterial) Thunk_IDirect3DMaterialImpl_1_GetMaterial,
379     XCAST(GetHandle) Thunk_IDirect3DMaterialImpl_1_GetHandle,
380     XCAST(Reserve) Main_IDirect3DMaterialImpl_1_Reserve,
381     XCAST(Unreserve) Main_IDirect3DMaterialImpl_1_Unreserve,
382 };
383
384 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
385 #undef XCAST
386 #endif
387
388
389
390
391 HRESULT d3dmaterial_create(IDirect3DMaterialImpl **obj, IDirectDrawImpl *d3d)
392 {
393     IDirect3DMaterialImpl *object;
394
395     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DMaterialImpl));
396     if (object == NULL) return DDERR_OUTOFMEMORY;
397
398     object->ref = 1;
399     object->d3d = d3d;
400     object->activate = activate;
401     
402     ICOM_INIT_INTERFACE(object, IDirect3DMaterial,  VTABLE_IDirect3DMaterial);
403     ICOM_INIT_INTERFACE(object, IDirect3DMaterial2, VTABLE_IDirect3DMaterial2);
404     ICOM_INIT_INTERFACE(object, IDirect3DMaterial3, VTABLE_IDirect3DMaterial3);
405
406     *obj = object;
407     
408     TRACE(" creating implementation at %p.\n", *obj);
409     
410     return D3D_OK;
411 }