Fix the case of product and company names.
[wine] / dlls / ddraw / d3dexecutebuffer.c
1 /* Direct3D ExecuteBuffer
2  * Copyright (c) 1998 Lionel ULMER
3  *
4  * This file contains the implementation of Direct3DExecuteBuffer.
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
23 #include <stdarg.h>
24 #include <string.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "wingdi.h"
33 #include "ddraw.h"
34 #include "d3d.h"
35 #include "wine/debug.h"
36
37 #include "d3d_private.h"
38 #include "mesa_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
41
42 static void _dump_d3dstatus(LPD3DSTATUS lpStatus) {
43
44 }
45
46 static void _dump_executedata(LPD3DEXECUTEDATA lpData) {
47     DPRINTF("dwSize : %ld\n", lpData->dwSize);
48     DPRINTF("Vertex      Offset : %ld  Count  : %ld\n", lpData->dwVertexOffset, lpData->dwVertexCount);
49     DPRINTF("Instruction Offset : %ld  Length : %ld\n", lpData->dwInstructionOffset, lpData->dwInstructionLength);
50     DPRINTF("HVertex     Offset : %ld\n", lpData->dwHVertexOffset);
51     _dump_d3dstatus(&(lpData->dsStatus));
52 }
53
54 static void _dump_D3DEXECUTEBUFFERDESC(LPD3DEXECUTEBUFFERDESC lpDesc) {
55
56 }
57
58 static void execute(IDirect3DExecuteBufferImpl *This,
59                     IDirect3DDeviceImpl *lpDevice,
60                     IDirect3DViewportImpl *lpViewport)
61 {
62     /* DWORD bs = This->desc.dwBufferSize; */
63     DWORD vs = This->data.dwVertexOffset;
64     /* DWORD vc = This->data.dwVertexCount; */
65     DWORD is = This->data.dwInstructionOffset;
66     /* DWORD il = This->data.dwInstructionLength; */
67
68     char *instr = (char *)This->desc.lpData + is;
69
70     /* Should check if the viewport was added or not to the device */
71
72     /* Activate the viewport */
73     lpViewport->active_device = lpDevice;
74     lpViewport->activate(lpViewport);
75
76     TRACE("ExecuteData : \n");
77     if (TRACE_ON(ddraw))
78       _dump_executedata(&(This->data));
79
80     while (1) {
81         LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
82         BYTE size;
83         WORD count;
84         
85         count = current->wCount;
86         size = current->bSize;
87         instr += sizeof(D3DINSTRUCTION);
88         
89         switch (current->bOpcode) {
90             case D3DOP_POINT: {
91                 WARN("POINT-s          (%d)\n", count);
92                 instr += count * size;
93             } break;
94
95             case D3DOP_LINE: {
96                 WARN("LINE-s           (%d)\n", count);
97                 instr += count * size;
98             } break;
99
100             case D3DOP_TRIANGLE: {
101                 int i;
102                 D3DTLVERTEX *tl_vx = (D3DTLVERTEX *) This->vertex_data;
103                 TRACE("TRIANGLE         (%d)\n", count);
104                 
105                 if (count*3>This->nb_indices) {
106                     This->nb_indices = count * 3;
107                     if (This->indices)
108                         HeapFree(GetProcessHeap(),0,This->indices);
109                     This->indices = HeapAlloc(GetProcessHeap(),0,sizeof(WORD)*This->nb_indices);
110                 }
111                         
112                 for (i = 0; i < count; i++) {
113                     LPD3DTRIANGLE ci = (LPD3DTRIANGLE) instr;
114                     TRACE("  v1: %d  v2: %d  v3: %d\n",ci->u1.v1, ci->u2.v2, ci->u3.v3);
115                     TRACE("  Flags : ");
116                     if (TRACE_ON(ddraw)) {
117                         /* Wireframe */
118                         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)
119                             TRACE("EDGEENABLE1 ");
120                         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2)
121                             TRACE("EDGEENABLE2 ");
122                         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)
123                             TRACE("EDGEENABLE3 ");
124                         /* Strips / Fans */
125                         if (ci->wFlags == D3DTRIFLAG_EVEN)
126                             TRACE("EVEN ");
127                         if (ci->wFlags == D3DTRIFLAG_ODD)
128                             TRACE("ODD ");
129                         if (ci->wFlags == D3DTRIFLAG_START)
130                             TRACE("START ");
131                         if ((ci->wFlags > 0) && (ci->wFlags < 30))
132                             TRACE("STARTFLAT(%d) ", ci->wFlags);
133                         TRACE("\n");
134                     }
135                     This->indices[i*3]=ci->u1.v1;This->indices[i*3+1]=ci->u2.v2;This->indices[i*3+2]=ci->u3.v3;
136                     instr += size;
137                 }
138                 IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(lpDevice,IDirect3DDevice7),
139                                                       D3DPT_TRIANGLELIST,D3DFVF_TLVERTEX,tl_vx,0,This->indices,count*3,0);
140             } break;
141
142             case D3DOP_MATRIXLOAD:
143                 WARN("MATRIXLOAD-s     (%d)\n", count);
144                 instr += count * size;
145                 break;
146
147             case D3DOP_MATRIXMULTIPLY: {
148                 int i;
149                 TRACE("MATRIXMULTIPLY   (%d)\n", count);
150                 
151                 for (i = 0; i < count; i++) {
152                     LPD3DMATRIXMULTIPLY ci = (LPD3DMATRIXMULTIPLY) instr;
153                     LPD3DMATRIX a = (LPD3DMATRIX) ci->hDestMatrix;
154                     LPD3DMATRIX b = (LPD3DMATRIX) ci->hSrcMatrix1;
155                     LPD3DMATRIX c = (LPD3DMATRIX) ci->hSrcMatrix2;
156                     
157                     TRACE("  Dest : %08lx  Src1 : %08lx  Src2 : %08lx\n",
158                           ci->hDestMatrix, ci->hSrcMatrix1, ci->hSrcMatrix2);
159                     
160                     multiply_matrix(a,c,b);
161
162                     instr += size;
163                 }
164             } break;
165
166             case D3DOP_STATETRANSFORM: {
167                 int i;
168                 TRACE("STATETRANSFORM   (%d)\n", count);
169                 
170                 for (i = 0; i < count; i++) {
171                     LPD3DSTATE ci = (LPD3DSTATE) instr;
172
173                     IDirect3DDevice7_SetTransform(ICOM_INTERFACE(lpDevice, IDirect3DDevice7),
174                                                   ci->u1.drstRenderStateType, (LPD3DMATRIX)ci->u2.dwArg[0]);
175                     
176                     instr += size;
177                 }
178             } break;
179
180             case D3DOP_STATELIGHT: {
181                 int i;
182                 TRACE("STATELIGHT       (%d)\n", count);
183                 
184                 for (i = 0; i < count; i++) {
185                     LPD3DSTATE ci = (LPD3DSTATE) instr;
186
187                     TRACE("(%08x,%08lx)\n",ci->u1.dlstLightStateType, ci->u2.dwArg[0]);
188
189                     if (!ci->u1.dlstLightStateType && (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX))
190                         ERR("Unexpected Light State Type\n");
191                     else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
192                         IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) ci->u2.dwArg[0];
193
194                         if (mat != NULL) {
195                             mat->activate(mat);
196                         } else {
197                             ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
198                         }
199                     }
200                    else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
201                         switch (ci->u2.dwArg[0]) {
202                             case D3DCOLOR_MONO:
203                                ERR("DDCOLOR_MONO should not happen!\n");
204                                break;
205                             case D3DCOLOR_RGB:
206                                /* We are already in this mode */
207                                break;
208                             default:
209                                ERR("Unknown color model!\n");
210                         }
211                     } else {
212                         D3DRENDERSTATETYPE rs = 0;
213                         switch (ci->u1.dlstLightStateType) {
214
215                             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
216                                 rs = D3DRENDERSTATE_AMBIENT;
217                                 break;          
218                             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
219                                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
220                                 break;
221                             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
222                                 rs = D3DRENDERSTATE_FOGSTART;
223                                 break;
224                             case D3DLIGHTSTATE_FOGEND:        /* 6 */
225                                 rs = D3DRENDERSTATE_FOGEND;
226                                 break;
227                             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
228                                 rs = D3DRENDERSTATE_FOGDENSITY;
229                                 break;
230                             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
231                                 rs = D3DRENDERSTATE_COLORVERTEX;
232                                 break;
233                             default:
234                                 break;
235                         }
236                         
237                         IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice, IDirect3DDevice7),
238                                                         rs,ci->u2.dwArg[0]);
239                    }
240
241                 }
242                 instr += size;
243             } break;
244
245             case D3DOP_STATERENDER: {
246                 int i;
247                 TRACE("STATERENDER      (%d)\n", count);
248
249                 for (i = 0; i < count; i++) {
250                     LPD3DSTATE ci = (LPD3DSTATE) instr;
251                     
252                     IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice, IDirect3DDevice7),
253                                                     ci->u1.drstRenderStateType, ci->u2.dwArg[0]);
254
255                     instr += size;
256                 }
257             } break;
258
259             case D3DOP_PROCESSVERTICES: {
260                 int i;
261                 TRACE("PROCESSVERTICES  (%d)\n", count);
262
263                 for (i = 0; i < count; i++) {
264                     LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
265
266                     TRACE("  Start : %d Dest : %d Count : %ld\n",
267                           ci->wStart, ci->wDest, ci->dwCount);
268                     TRACE("  Flags : ");
269                     if (TRACE_ON(ddraw)) {
270                         if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
271                             TRACE("COPY ");
272                         if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
273                             TRACE("NOCOLOR ");
274                         if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
275                             TRACE("OPMASK ");
276                         if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
277                             TRACE("TRANSFORM ");
278                         if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
279                             TRACE("TRANSFORMLIGHT ");
280                         if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
281                             TRACE("UPDATEEXTENTS ");
282                         TRACE("\n");
283                     }
284                     
285                     /* This is where doing Direct3D on top on OpenGL is quite difficult.
286                        This method transforms a set of vertices using the CURRENT state
287                        (lighting, projection, ...) but does not rasterize them.
288                        They will only be put on screen later (with the POINT / LINE and
289                        TRIANGLE op-codes). The problem is that you can have a triangle
290                        with each point having been transformed using another state...
291                        
292                        In this implementation, I will emulate only ONE thing : each
293                        vertex can have its own "WORLD" transformation (this is used in the
294                        TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
295                        execute buffer use the same state.
296                        
297                        If I find applications that change other states, I will try to do a
298                        more 'fine-tuned' state emulation (but I may become quite tricky if
299                        it changes a light position in the middle of a triangle).
300                        
301                        In this case, a 'direct' approach (i.e. without using OpenGL, but
302                        writing our own 3D rasterizer) would be easier. */
303                     
304                     /* The current method (with the hypothesis that only the WORLD matrix
305                        will change between two points) is like this :
306                        - I transform 'manually' all the vertices with the current WORLD
307                          matrix and store them in the vertex buffer
308                        - during the rasterization phase, the WORLD matrix will be set to
309                          the Identity matrix */
310                     
311                     /* Enough for the moment */
312                     if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
313                         int nb;
314                         D3DVERTEX  *src = ((LPD3DVERTEX)  ((char *)This->desc.lpData + vs)) + ci->wStart;
315                         D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
316                         D3DMATRIX *mat2 = lpDevice->world_mat;
317                         D3DMATRIX mat;
318                         D3DVALUE nx,ny,nz;
319                         D3DVIEWPORT* Viewport = &lpViewport->viewports.vp1;
320                         
321                         if (TRACE_ON(ddraw)) {
322                             TRACE("  Projection Matrix : (%p)\n", lpDevice->proj_mat);
323                             dump_D3DMATRIX(lpDevice->proj_mat);
324                             TRACE("  View       Matrix : (%p)\n", lpDevice->view_mat);
325                             dump_D3DMATRIX(lpDevice->view_mat);
326                             TRACE("  World Matrix : (%p)\n", &mat);
327                             dump_D3DMATRIX(&mat);
328                         }
329
330                         multiply_matrix(&mat,lpDevice->view_mat,lpDevice->world_mat);
331                         multiply_matrix(&mat,lpDevice->proj_mat,&mat);
332
333                         for (nb = 0; nb < ci->dwCount; nb++) {
334                             /* Normals transformation */
335                             nx = (src->u4.nx * mat2->_11) + (src->u5.ny * mat2->_21) + (src->u6.nz * mat2->_31);
336                             ny = (src->u4.nx * mat2->_12) + (src->u5.ny * mat2->_22) + (src->u6.nz * mat2->_32);
337                             nz = (src->u4.nx * mat2->_13) + (src->u5.ny * mat2->_23) + (src->u6.nz * mat2->_33);
338                             
339                             /* No lighting yet */
340                             dst->u5.color = 0xFFFFFFFF; /* Opaque white */
341                             dst->u6.specular = 0xFF000000; /* No specular and no fog factor */
342                             
343                             dst->u7.tu  = src->u7.tu;
344                             dst->u8.tv  = src->u8.tv;
345                             
346                             /* Now, the matrix multiplication */
347                             dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41);
348                             dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42);
349                             dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + (1.0 * mat._43);
350                             dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + (1.0 * mat._44);
351
352                             dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dwWidth / 2
353                                        + Viewport->dwX + Viewport->dwWidth / 2;
354                             dst->u2.sy = dst->u2.sy / dst->u4.rhw * Viewport->dwHeight / 2
355                                        + Viewport->dwY + Viewport->dwHeight / 2;
356                             dst->u3.sz /= dst->u4.rhw;
357                             dst->u4.rhw = 1 / dst->u4.rhw;
358
359                             src++;
360                             dst++;
361                             
362                         }
363                     } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
364                         int nb;
365                         D3DLVERTEX *src  = ((LPD3DLVERTEX) ((char *)This->desc.lpData + vs)) + ci->wStart;
366                         D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
367                         D3DMATRIX mat;
368                         D3DVIEWPORT* Viewport = &lpViewport->viewports.vp1;
369                         
370                         if (TRACE_ON(ddraw)) {
371                             TRACE("  Projection Matrix : (%p)\n", lpDevice->proj_mat);
372                             dump_D3DMATRIX(lpDevice->proj_mat);
373                             TRACE("  View       Matrix : (%p)\n", lpDevice->view_mat);
374                             dump_D3DMATRIX(lpDevice->view_mat);
375                             TRACE("  World Matrix : (%p)\n", &mat);
376                             dump_D3DMATRIX(&mat);
377                         }
378
379                         multiply_matrix(&mat,lpDevice->view_mat,lpDevice->world_mat);
380                         multiply_matrix(&mat,lpDevice->proj_mat,&mat);
381
382                         for (nb = 0; nb < ci->dwCount; nb++) {
383                             dst->u5.color = src->u4.color;
384                             dst->u6.specular = src->u5.specular;
385                             dst->u7.tu = src->u6.tu;
386                             dst->u8.tv = src->u7.tv;
387                             
388                             /* Now, the matrix multiplication */
389                             dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41);
390                             dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42);
391                             dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + (1.0 * mat._43);
392                             dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + (1.0 * mat._44);
393
394                             dst->u1.sx /= dst->u4.rhw * Viewport->dvScaleX * Viewport->dwWidth / 2 + Viewport->dwX;
395                             dst->u2.sy /= dst->u4.rhw * Viewport->dvScaleY * Viewport->dwHeight / 2 + Viewport->dwY;
396                             dst->u3.sz /= dst->u4.rhw;
397                             dst->u4.rhw = 1 / dst->u4.rhw;
398
399                             src++;
400                             dst++;
401                         }
402                     } else if (ci->dwFlags == D3DPROCESSVERTICES_COPY) {
403                         D3DTLVERTEX *src = ((LPD3DTLVERTEX) ((char *)This->desc.lpData + vs)) + ci->wStart;
404                         D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
405                         
406                         memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
407                     } else {
408                         ERR("Unhandled vertex processing !\n");
409                     }
410
411                     instr += size;
412                 }
413             } break;
414
415             case D3DOP_TEXTURELOAD: {
416                 WARN("TEXTURELOAD-s    (%d)\n", count);
417
418                 instr += count * size;
419             } break;
420
421             case D3DOP_EXIT: {
422                 TRACE("EXIT             (%d)\n", count);
423                 /* We did this instruction */
424                 instr += size;
425                 /* Exit this loop */
426                 goto end_of_buffer;
427             } break;
428
429             case D3DOP_BRANCHFORWARD: {
430                 int i;
431                 TRACE("BRANCHFORWARD    (%d)\n", count);
432
433                 for (i = 0; i < count; i++) {
434                     LPD3DBRANCH ci = (LPD3DBRANCH) instr;
435
436                     if ((This->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
437                         if (!ci->bNegate) {
438                             TRACE(" Branch to %ld\n", ci->dwOffset);
439                             instr = (char*)current + ci->dwOffset;
440                             break;
441                         }
442                     } else {
443                         if (ci->bNegate) {
444                             TRACE(" Branch to %ld\n", ci->dwOffset);
445                             instr = (char*)current + ci->dwOffset;
446                             break;
447                         }
448                     }
449
450                     instr += size;
451                 }
452             } break;
453
454             case D3DOP_SPAN: {
455                 WARN("SPAN-s           (%d)\n", count);
456
457                 instr += count * size;
458             } break;
459
460             case D3DOP_SETSTATUS: {
461                 int i;
462                 TRACE("SETSTATUS        (%d)\n", count);
463
464                 for (i = 0; i < count; i++) {
465                     LPD3DSTATUS ci = (LPD3DSTATUS) instr;
466                     
467                     This->data.dsStatus = *ci;
468
469                     instr += size;
470                 }
471             } break;
472
473             default:
474                 ERR("Unhandled OpCode %d !!!\n",current->bOpcode);
475                 /* Try to save ... */
476                 instr += count * size;
477                 break;
478         }
479     }
480
481 end_of_buffer:
482     ;
483 }
484
485 HRESULT WINAPI
486 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface,
487                                                  REFIID riid,
488                                                  LPVOID* obp)
489 {
490     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
491     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
492
493     *obp = NULL;
494
495     if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
496         IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This, IDirect3DExecuteBuffer));
497         *obp = iface;
498         TRACE("  Creating IUnknown interface at %p.\n", *obp);
499         return S_OK;
500     }
501     if ( IsEqualGUID( &IID_IDirect3DMaterial, riid ) ) {
502         IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This, IDirect3DExecuteBuffer));
503         *obp = ICOM_INTERFACE(This, IDirect3DExecuteBuffer);
504         TRACE("  Creating IDirect3DExecuteBuffer interface %p\n", *obp);
505         return S_OK;
506     }
507     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
508     return OLE_E_ENUM_NOMORE;
509 }
510
511 ULONG WINAPI
512 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface)
513 {
514     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
515     FIXME("(%p/%p)->()incrementing from %lu.\n", This, iface, This->ref );
516     return ++(This->ref);
517 }
518
519 ULONG WINAPI
520 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface)
521 {
522     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
523     TRACE("(%p/%p)->()decrementing from %lu.\n", This, iface, This->ref);
524     if (!--(This->ref)) {
525         if ((This->desc.lpData != NULL) && This->need_free)
526             HeapFree(GetProcessHeap(),0,This->desc.lpData);
527         if (This->vertex_data != NULL)
528             HeapFree(GetProcessHeap(),0,This->vertex_data);
529         if (This->indices != NULL)
530             HeapFree(GetProcessHeap(),0,This->indices);
531         HeapFree(GetProcessHeap(),0,This);
532         return 0;
533     }
534
535     return This->ref;
536 }
537
538 HRESULT WINAPI
539 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface,
540                                              LPDIRECT3DDEVICE lpDirect3DDevice,
541                                              LPD3DEXECUTEBUFFERDESC lpDesc)
542 {
543     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
544     TRACE("(%p/%p)->(%p,%p) no-op....\n", This, iface, lpDirect3DDevice, lpDesc);
545     return DD_OK;
546 }
547
548 HRESULT WINAPI
549 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface,
550                                        LPD3DEXECUTEBUFFERDESC lpDesc)
551 {
552     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
553     DWORD dwSize;
554     TRACE("(%p/%p)->(%p)\n", This, iface, lpDesc);
555
556     dwSize = lpDesc->dwSize;
557     memset(lpDesc, 0, dwSize);
558     memcpy(lpDesc, &This->desc, dwSize);
559     
560     if (TRACE_ON(ddraw)) {
561         TRACE("  Returning description : \n");
562         _dump_D3DEXECUTEBUFFERDESC(lpDesc);
563     }
564     return DD_OK;
565 }
566
567 HRESULT WINAPI
568 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface)
569 {
570     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
571     TRACE("(%p/%p)->() no-op...\n", This, iface);
572     return DD_OK;
573 }
574
575 HRESULT WINAPI
576 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
577                                                  LPD3DEXECUTEDATA lpData)
578 {
579     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
580     DWORD nbvert;
581     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
582
583     memcpy(&This->data, lpData, lpData->dwSize);
584
585     /* Get the number of vertices in the execute buffer */
586     nbvert = This->data.dwVertexCount;
587     
588     /* Prepares the transformed vertex buffer */
589     if (This->vertex_data != NULL)
590         HeapFree(GetProcessHeap(), 0, This->vertex_data);
591     This->vertex_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbvert * sizeof(D3DTLVERTEX));
592
593     if (TRACE_ON(ddraw)) {
594         _dump_executedata(lpData);
595     }
596
597     return DD_OK;
598 }
599
600 HRESULT WINAPI
601 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
602                                                  LPD3DEXECUTEDATA lpData)
603 {
604     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
605     DWORD dwSize;
606     TRACE("(%p/%p)->(%p): stub!\n", This, iface, lpData);
607
608     dwSize = lpData->dwSize;
609     memset(lpData, 0, dwSize);
610     memcpy(lpData, &This->data, dwSize);
611
612     if (TRACE_ON(ddraw)) {
613         TRACE("Returning data : \n");
614         _dump_executedata(lpData);
615     }
616
617     return DD_OK;
618 }
619
620 HRESULT WINAPI
621 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface,
622                                            LPDWORD lpdwOffset,
623                                            LPD3DVALIDATECALLBACK lpFunc,
624                                            LPVOID lpUserArg,
625                                            DWORD dwReserved)
626 {
627     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
628     FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This, iface, lpdwOffset, lpFunc, lpUserArg, dwReserved);
629     return DD_OK;
630 }
631
632 HRESULT WINAPI
633 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface,
634                                            DWORD dwDummy)
635 {
636     ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
637     TRACE("(%p/%p)->(%08lx) no-op...\n", This, iface, dwDummy);
638     return DD_OK;
639 }
640
641 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
642 # define XCAST(fun)     (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
643 #else
644 # define XCAST(fun)     (void*)
645 #endif
646
647 ICOM_VTABLE(IDirect3DExecuteBuffer) VTABLE_IDirect3DExecuteBuffer =
648 {
649     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
650     XCAST(QueryInterface) Main_IDirect3DExecuteBufferImpl_1_QueryInterface,
651     XCAST(AddRef) Main_IDirect3DExecuteBufferImpl_1_AddRef,
652     XCAST(Release) Main_IDirect3DExecuteBufferImpl_1_Release,
653     XCAST(Initialize) Main_IDirect3DExecuteBufferImpl_1_Initialize,
654     XCAST(Lock) Main_IDirect3DExecuteBufferImpl_1_Lock,
655     XCAST(Unlock) Main_IDirect3DExecuteBufferImpl_1_Unlock,
656     XCAST(SetExecuteData) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData,
657     XCAST(GetExecuteData) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData,
658     XCAST(Validate) Main_IDirect3DExecuteBufferImpl_1_Validate,
659     XCAST(Optimize) Main_IDirect3DExecuteBufferImpl_1_Optimize,
660 };
661
662 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
663 #undef XCAST
664 #endif
665
666
667 HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirectDrawImpl *d3d, IDirect3DDeviceImpl *d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc)
668 {
669     IDirect3DExecuteBufferImpl* object;
670
671     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
672
673     ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, VTABLE_IDirect3DExecuteBuffer);
674     
675     object->ref = 1;
676     object->d3d = d3d;
677     object->d3ddev = d3ddev;
678
679     /* Initializes memory */
680     memcpy(&object->desc, lpDesc, lpDesc->dwSize);
681
682     /* No buffer given */
683     if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
684         object->desc.lpData = NULL;
685
686     /* No buffer size given */
687     if ((lpDesc->dwFlags & D3DDEB_BUFSIZE) == 0)
688         object->desc.dwBufferSize = 0;
689
690     /* Create buffer if asked */
691     if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0)) {
692         object->need_free = TRUE;
693         object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
694     } else {
695         object->need_free = FALSE;
696     }
697
698     /* No vertices for the moment */
699     object->vertex_data = NULL;
700
701     object->desc.dwFlags |= D3DDEB_LPDATA;
702
703     object->execute = execute;
704
705     object->indices = NULL;
706     object->nb_indices = 0;
707
708     *obj = object;
709     
710     TRACE(" creating implementation at %p.\n", *obj);
711     
712     return DD_OK;
713 }