Keep track of per-column information inside the listview.
[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 <string.h>
24
25 #include "windef.h"
26 #include "winerror.h"
27 #include "wine/obj_base.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "wine/debug.h"
31
32 #include "mesa_private.h"
33
34 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)(x)->private)
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37
38 /* Structure to store the 'semi transformed' vertices */
39 typedef struct {
40   D3DVALUE x;
41   D3DVALUE y;
42   D3DVALUE z;
43   D3DVALUE w;
44
45   D3DVALUE nx;
46   D3DVALUE ny;
47   D3DVALUE nz;
48
49   D3DVALUE u;
50   D3DVALUE v;
51 } OGL_Vertex;
52
53 typedef struct {
54   D3DVALUE x;
55   D3DVALUE y;
56   D3DVALUE z;
57   D3DVALUE w;
58
59   D3DCOLOR c;
60   D3DCOLOR sc;
61
62   D3DVALUE u;
63   D3DVALUE v;
64 } OGL_LVertex;
65
66 static ICOM_VTABLE(IDirect3DExecuteBuffer) executebuffer_vtable;
67
68 /*******************************************************************************
69  *                              ExecuteBuffer static functions
70  */
71 void _dump_d3dstatus(LPD3DSTATUS lpStatus) {
72
73 }
74
75 void _dump_executedata(LPD3DEXECUTEDATA lpData) {
76   DPRINTF("dwSize : %ld\n", lpData->dwSize);
77   DPRINTF("Vertex      Offset : %ld  Count  : %ld\n", lpData->dwVertexOffset, lpData->dwVertexCount);
78   DPRINTF("Instruction Offset : %ld  Length : %ld\n", lpData->dwInstructionOffset, lpData->dwInstructionLength);
79   DPRINTF("HVertex     Offset : %ld\n", lpData->dwHVertexOffset);
80   _dump_d3dstatus(&(lpData->dsStatus));
81 }
82
83 #define DO_VERTEX(index)                        \
84 {                                                                               \
85   glTexCoord2f(vx[index].u,                                                     \
86                vx[index].v);                                                    \
87   glNormal3f(vx[index].nx,                                                      \
88              vx[index].ny,                                                      \
89              vx[index].nz);                                                     \
90   glVertex4f(vx[index].x,                                                       \
91              vx[index].y,                                                       \
92              vx[index].z,                                                       \
93              vx[index].w);                                                      \
94                                                                                 \
95   TRACE("   V: %f %f %f %f (%f %f %f) (%f %f)\n",                       \
96         vx[index].x, vx[index].y, vx[index].z, vx[index].w,                     \
97         vx[index].nx, vx[index].ny, vx[index].nz,                               \
98         vx[index].u, vx[index].v);                                              \
99 }
100
101 #define DO_LVERTEX(index)                                                       \
102 {                                                                               \
103   DWORD col = l_vx[index].c;                                                    \
104                                                                                 \
105   glColor3f(((col >> 16) & 0xFF) / 255.0,                                       \
106             ((col >>  8) & 0xFF) / 255.0,                                       \
107             ((col >>  0) & 0xFF) / 255.0);                                      \
108   glTexCoord2f(l_vx[index].u,                                                   \
109                l_vx[index].v);                                                  \
110   glVertex4f(l_vx[index].x,                                                     \
111              l_vx[index].y,                                                     \
112              l_vx[index].z,                                                     \
113              l_vx[index].w);                                                    \
114                                                                                 \
115   TRACE("  LV: %f %f %f %f (%02lx %02lx %02lx) (%f %f)\n",              \
116         l_vx[index].x, l_vx[index].y, l_vx[index].z, l_vx[index].w,             \
117         ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF),       \
118         l_vx[index].u, l_vx[index].v);                                          \
119 }
120
121 #define DO_TLVERTEX(index)                                                      \
122 {                                                                               \
123   D3DTLVERTEX *vx = &(tl_vx[index]);                                            \
124   DWORD col = vx->u5.color;                                                     \
125                                                                                 \
126   glColor3f(((col >> 16) & 0xFF) / 255.0,                                       \
127             ((col >>  8) & 0xFF) / 255.0,                                       \
128             ((col >>  0) & 0xFF) / 255.0);                                      \
129   glTexCoord2f(vx->u7.tu, vx->u8.tv);                                           \
130   if (vx->u4.rhw < 0.01)                                                        \
131     glVertex3f(vx->u1.sx,                                                       \
132                vx->u2.sy,                                                       \
133                vx->u3.sz);                                                      \
134   else                                                                          \
135     glVertex4f(vx->u1.sx / vx->u4.rhw,                                          \
136                vx->u2.sy / vx->u4.rhw,                                          \
137                vx->u3.sz / vx->u4.rhw,                                          \
138                1.0 / vx->u4.rhw);                                               \
139   TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",            \
140         vx->u1.sx, vx->u2.sy, vx->u3.sz,                                                \
141         ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF),       \
142         vx->u7.tu, vx->u8.tv, vx->u4.rhw);                                              \
143 }
144
145 #define TRIANGLE_LOOP(macro)                            \
146 {                                                       \
147   glBegin(GL_TRIANGLES); {                              \
148     for (i = 0; i < count; i++) {                       \
149       LPD3DTRIANGLE ci = (LPD3DTRIANGLE) instr;         \
150                                                         \
151       TRACE("  v1: %d  v2: %d  v3: %d\n",       \
152             ci->u1.v1, ci->u2.v2, ci->u3.v3);           \
153       TRACE("  Flags : ");                      \
154       if (TRACE_ON(ddraw)) {                            \
155         /* Wireframe */                                 \
156         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)        \
157           DPRINTF("EDGEENABLE1 ");                              \
158         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2)        \
159           DPRINTF("EDGEENABLE2 ");                              \
160         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)        \
161           DPRINTF("EDGEENABLE3 ");                              \
162                                                         \
163         /* Strips / Fans */                             \
164         if (ci->wFlags == D3DTRIFLAG_EVEN)              \
165           DPRINTF("EVEN ");                             \
166         if (ci->wFlags == D3DTRIFLAG_ODD)               \
167           DPRINTF("ODD ");                                      \
168         if (ci->wFlags == D3DTRIFLAG_START)             \
169           DPRINTF("START ");                            \
170         if ((ci->wFlags > 0) && (ci->wFlags < 30))      \
171           DPRINTF("STARTFLAT(%d) ", ci->wFlags);                \
172         DPRINTF("\n");                                  \
173       }                                                 \
174                                                         \
175       /* Draw the triangle */                           \
176       macro(ci->u1.v1);                                 \
177       macro(ci->u2.v2);                                 \
178       macro(ci->u3.v3);                                 \
179                                                         \
180       instr += size;                                    \
181     }                                                   \
182   } glEnd();                                            \
183 }
184
185
186 static void execute(LPDIRECT3DEXECUTEBUFFER lpBuff,
187                     LPDIRECT3DDEVICE dev,
188                     LPDIRECT3DVIEWPORT vp) {
189   IDirect3DExecuteBufferImpl* ilpBuff=(IDirect3DExecuteBufferImpl*)lpBuff;
190   IDirect3DViewport2Impl* ivp=(IDirect3DViewport2Impl*)vp;
191   /* DWORD bs = ilpBuff->desc.dwBufferSize; */
192   DWORD vs = ilpBuff->data.dwVertexOffset;
193   /* DWORD vc = ilpBuff->data.dwVertexCount; */
194   DWORD is = ilpBuff->data.dwInstructionOffset;
195   /* DWORD il = ilpBuff->data.dwInstructionLength; */
196
197   void *instr = ilpBuff->desc.lpData + is;
198   D3DDPRIVATE((IDirect3DDeviceImpl*)dev);
199
200   /* Should check if the viewport was added or not to the device */
201
202   /* Activate the viewport */
203   ivp->device.active_device1 = (IDirect3DDeviceImpl*)dev;
204   ivp->activate(ivp);
205
206   TRACE("ExecuteData : \n");
207   if (TRACE_ON(ddraw))
208   _dump_executedata(&(ilpBuff->data));
209
210   ENTER_GL();
211
212   while (1) {
213     LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
214     BYTE size;
215     WORD count;
216
217     count = current->wCount;
218     size = current->bSize;
219     instr += sizeof(D3DINSTRUCTION);
220
221     switch (current->bOpcode) {
222     case D3DOP_POINT: {
223       TRACE("POINT-s          (%d)\n", count);
224
225       instr += count * size;
226     } break;
227
228     case D3DOP_LINE: {
229       TRACE("LINE-s           (%d)\n", count);
230
231       instr += count * size;
232     } break;
233
234     case D3DOP_TRIANGLE: {
235       int i;
236
237       OGL_Vertex  *vx    = (OGL_Vertex  *) ilpBuff->vertex_data;
238       OGL_LVertex *l_vx  = (OGL_LVertex *) ilpBuff->vertex_data;
239       D3DTLVERTEX *tl_vx = (D3DTLVERTEX *) ilpBuff->vertex_data;
240
241       TRACE("TRIANGLE         (%d)\n", count);
242
243       switch (ilpBuff->vertex_type) {
244       case D3DVT_VERTEX:
245         /* This time, there is lighting */
246         glEnable(GL_LIGHTING);
247
248       /* Use given matrixes */
249       glMatrixMode(GL_MODELVIEW);
250       glLoadIdentity(); /* The model transformation was done during the
251                            transformation phase */
252       glMatrixMode(GL_PROJECTION);
253         TRACE("  Projection Matrix : (%p)\n", odev->proj_mat);
254         dump_mat(odev->proj_mat);
255         TRACE("  View       Matrix : (%p)\n", odev->view_mat);
256         dump_mat(odev->view_mat);
257
258         /* Although z axis is inverted between OpenGL and Direct3D, the z projected coordinates
259            are always 0.0 at the front viewing volume and 1.0 at the back with Direct 3D and with
260            the default behaviour of OpenGL. So, no additional transformation is required. */
261         glLoadMatrixf((float *) odev->proj_mat);
262         glMultMatrixf((float *) odev->view_mat);
263         break;
264
265       case D3DVT_LVERTEX:
266         /* No lighting */
267         glDisable(GL_LIGHTING);
268
269         /* Use given matrixes */
270         glMatrixMode(GL_MODELVIEW);
271         glLoadIdentity(); /* The model transformation was done during the
272                              transformation phase */
273         glMatrixMode(GL_PROJECTION);
274
275         TRACE("  Projection Matrix : (%p)\n", odev->proj_mat);
276         dump_mat(odev->proj_mat);
277         TRACE("  View       Matrix : (%p)\n", odev->view_mat);
278         dump_mat(odev->view_mat);
279
280         /* Although z axis is inverted between OpenGL and Direct3D, the z projected coordinates
281            are always 0 at the front viewing volume and 1 at the back with Direct 3D and with
282            the default behaviour of OpenGL. So, no additional transformation is required. */
283         glLoadMatrixf((float *) odev->proj_mat);
284         glMultMatrixf((float *) odev->view_mat);
285         break;
286
287       case D3DVT_TLVERTEX: {
288         GLdouble height, width, minZ, maxZ;
289
290         /* First, disable lighting */
291         glDisable(GL_LIGHTING);
292
293         /* Then do not put any transformation matrixes */
294         glMatrixMode(GL_MODELVIEW);
295         glLoadIdentity();
296         glMatrixMode(GL_PROJECTION);
297         glLoadIdentity();
298
299         if (ivp == NULL) {
300           ERR("No current viewport !\n");
301           /* Using standard values */
302           height = 640.0;
303           width = 480.0;
304           minZ = -10.0;
305           maxZ = 10.0;
306         } else {
307           height = (GLdouble) ivp->viewport.vp1.dwHeight;
308           width  = (GLdouble) ivp->viewport.vp1.dwWidth;
309           minZ   = (GLdouble) ivp->viewport.vp1.dvMinZ;
310           maxZ   = (GLdouble) ivp->viewport.vp1.dvMaxZ;
311
312           if (minZ == maxZ) {
313             /* I do not know why, but many Dx 3.0 games have minZ = maxZ = 0.0 */
314             minZ = 0.0;
315             maxZ = 1.0;
316         }
317         }
318
319         glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
320       } break;
321
322       default:
323         ERR("Unhandled vertex type !\n");
324         break;
325       }
326
327       switch (ilpBuff->vertex_type) {
328       case D3DVT_VERTEX:
329         TRIANGLE_LOOP(DO_VERTEX);
330         break;
331
332       case D3DVT_LVERTEX:
333         TRIANGLE_LOOP(DO_LVERTEX);
334         break;
335
336       case D3DVT_TLVERTEX:
337         TRIANGLE_LOOP(DO_TLVERTEX);
338         break;
339
340       default:
341         ERR("Unhandled vertex type !\n");
342       }
343
344     } break;
345
346     case D3DOP_MATRIXLOAD: {
347       TRACE("MATRIXLOAD-s     (%d)\n", count);
348
349       instr += count * size;
350     } break;
351
352     case D3DOP_MATRIXMULTIPLY: {
353       int i;
354       TRACE("MATRIXMULTIPLY   (%d)\n", count);
355
356       for (i = 0; i < count; i++) {
357         LPD3DMATRIXMULTIPLY ci = (LPD3DMATRIXMULTIPLY) instr;
358         LPD3DMATRIX a = (LPD3DMATRIX) ci->hDestMatrix;
359         LPD3DMATRIX b = (LPD3DMATRIX) ci->hSrcMatrix1;
360         LPD3DMATRIX c = (LPD3DMATRIX) ci->hSrcMatrix2;
361
362         TRACE("  Dest : %08lx  Src1 : %08lx  Src2 : %08lx\n",
363               ci->hDestMatrix, ci->hSrcMatrix1, ci->hSrcMatrix2);
364
365         /* Do the multiplication..
366            As I am VERY lazy, I let OpenGL do the multiplication for me */
367         glMatrixMode(GL_PROJECTION);
368         /* Save the current matrix */
369         glPushMatrix();
370         /* Load Matrix one and do the multiplication */
371         glLoadMatrixf((float *) c);
372         glMultMatrixf((float *) b);
373         glGetFloatv(GL_PROJECTION_MATRIX, (float *) a);
374         /* Restore the current matrix */
375         glPopMatrix();
376
377         instr += size;
378       }
379     } break;
380
381     case D3DOP_STATETRANSFORM: {
382       int i;
383       TRACE("STATETRANSFORM   (%d)\n", count);
384
385       for (i = 0; i < count; i++) {
386         LPD3DSTATE ci = (LPD3DSTATE) instr;
387
388         /* Handle the state transform */
389         switch (ci->u1.dtstTransformStateType) {
390         case D3DTRANSFORMSTATE_WORLD: {
391           TRACE("  WORLD (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
392           odev->world_mat = (D3DMATRIX*) ci->u2.dwArg[0];
393         } break;
394
395         case D3DTRANSFORMSTATE_VIEW: {
396           TRACE("  VIEW (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
397           odev->view_mat = (D3DMATRIX*) ci->u2.dwArg[0];
398         } break;
399
400         case D3DTRANSFORMSTATE_PROJECTION: {
401           TRACE("  PROJECTION (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
402           odev->proj_mat = (D3DMATRIX*) ci->u2.dwArg[0];
403         } break;
404
405         default:
406           ERR("  Unhandled state transformation !! (%d)\n", (int) ci->u1.dtstTransformStateType);
407           break;
408
409         }
410
411         instr += size;
412       }
413     } break;
414
415     case D3DOP_STATELIGHT: {
416       int i;
417       TRACE("STATELIGHT       (%d)\n", count);
418
419       for (i = 0; i < count; i++) {
420         LPD3DSTATE ci = (LPD3DSTATE) instr;
421
422         /* Handle the state transform */
423         switch (ci->u1.dlstLightStateType) {
424         case D3DLIGHTSTATE_MATERIAL: {
425           IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) ci->u2.dwArg[0];
426           TRACE("  MATERIAL\n");
427
428           if (mat != NULL) {
429             mat->activate(mat);
430           } else {
431             TRACE("    bad Material Handle\n");
432           }
433         } break ;
434
435         case D3DLIGHTSTATE_AMBIENT: {
436           float light[4];
437           DWORD dwLightState = ci->u2.dwArg[0];
438           TRACE("  AMBIENT\n");
439
440           light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
441           light[1] = ((dwLightState >>  8) & 0xFF) / 255.0;
442           light[2] = ((dwLightState >>  0) & 0xFF) / 255.0;
443           light[3] = 1.0;
444           glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
445
446           TRACE("    R:%02lx G:%02lx B:%02lx A:%02lx\n",
447                 ((dwLightState >> 16) & 0xFF),
448                 ((dwLightState >>  8) & 0xFF),
449                 ((dwLightState >>  0) & 0xFF),
450                 ((dwLightState >> 24) & 0xFF));
451         } break ;
452
453         case D3DLIGHTSTATE_COLORMODEL: {
454           TRACE("  COLORMODEL\n");
455         } break ;
456
457         case D3DLIGHTSTATE_FOGMODE: {
458           TRACE("  FOGMODE\n");
459         } break ;
460
461         case D3DLIGHTSTATE_FOGSTART: {
462           TRACE("  FOGSTART\n");
463         } break ;
464
465         case D3DLIGHTSTATE_FOGEND: {
466           TRACE("  FOGEND\n");
467         } break ;
468
469         case D3DLIGHTSTATE_FOGDENSITY: {
470           TRACE("  FOGDENSITY\n");
471         } break ;
472
473         default:
474           ERR("  Unhandled light state !! (%d)\n", (int) ci->u1.dlstLightStateType);
475           break;
476         }
477         instr += size;
478       }
479     } break;
480
481     case D3DOP_STATERENDER: {
482       int i;
483       TRACE("STATERENDER      (%d)\n", count);
484
485       for (i = 0; i < count; i++) {
486         LPD3DSTATE ci = (LPD3DSTATE) instr;
487
488         /* Handle the state transform */
489         set_render_state(ci->u1.drstRenderStateType, ci->u2.dwArg[0], &(odev->rs));
490
491         instr += size;
492       }
493     } break;
494
495     case D3DOP_PROCESSVERTICES: {
496       int i;
497       TRACE("PROCESSVERTICES  (%d)\n", count);
498
499       for (i = 0; i < count; i++) {
500         LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
501
502         TRACE("  Start : %d Dest : %d Count : %ld\n",
503               ci->wStart, ci->wDest, ci->dwCount);
504         TRACE("  Flags : ");
505         if (TRACE_ON(ddraw)) {
506           if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
507             DPRINTF("COPY ");
508           if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
509             DPRINTF("NOCOLOR ");
510           if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
511             DPRINTF("OPMASK ");
512           if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
513             DPRINTF("TRANSFORM ");
514           if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
515             DPRINTF("TRANSFORMLIGHT ");
516           if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
517             DPRINTF("UPDATEEXTENTS ");
518           DPRINTF("\n");
519         }
520
521         /* This is where doing Direct3D on top on OpenGL is quite difficult.
522            This method transforms a set of vertices using the CURRENT state
523            (lighting, projection, ...) but does not rasterize them.
524            They will only be put on screen later (with the POINT / LINE and
525            TRIANGLE op-codes). The problem is that you can have a triangle
526            with each point having been transformed using another state...
527
528            In this implementation, I will emulate only ONE thing : each
529            vertex can have its own "WORLD" transformation (this is used in the
530            TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
531            execute buffer use the same state.
532
533            If I find applications that change other states, I will try to do a
534            more 'fine-tuned' state emulation (but I may become quite tricky if
535            it changes a light position in the middle of a triangle).
536
537            In this case, a 'direct' approach (i.e. without using OpenGL, but
538            writing our own 3D rasterizer) would be easier. */
539
540         /* The current method (with the hypothesis that only the WORLD matrix
541            will change between two points) is like this :
542             - I transform 'manually' all the vertices with the current WORLD
543               matrix and store them in the vertex buffer
544             - during the rasterization phase, the WORLD matrix will be set to
545               the Identity matrix */
546
547         /* Enough for the moment */
548         if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
549           int nb;
550           D3DVERTEX  *src = ((LPD3DVERTEX)  (ilpBuff->desc.lpData + vs)) + ci->wStart;
551           OGL_Vertex *dst = ((OGL_Vertex *) (ilpBuff->vertex_data)) + ci->wDest;
552           D3DMATRIX *mat = odev->world_mat;
553
554           TRACE("  World Matrix : (%p)\n", mat);
555           dump_mat(mat);
556
557           ilpBuff->vertex_type = D3DVT_VERTEX;
558
559           for (nb = 0; nb < ci->dwCount; nb++) {
560             /* For the moment, no normal transformation... */
561             dst->nx = (src->u4.nx * mat->_11) + (src->u5.ny * mat->_21) + (src->u6.nz * mat->_31);
562             dst->ny = (src->u4.nx * mat->_12) + (src->u5.ny * mat->_22) + (src->u6.nz * mat->_32);
563             dst->nz = (src->u4.nx * mat->_13) + (src->u5.ny * mat->_23) + (src->u6.nz * mat->_33);
564
565             dst->u  = src->u7.tu;
566             dst->v  = src->u8.tv;
567
568             /* Now, the matrix multiplication */
569             dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
570             dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
571             dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
572             dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
573
574             src++;
575             dst++;
576           }
577         } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
578           int nb;
579           D3DLVERTEX *src  = ((LPD3DLVERTEX) (ilpBuff->desc.lpData + vs)) + ci->wStart;
580           OGL_LVertex *dst = ((OGL_LVertex *) (ilpBuff->vertex_data)) + ci->wDest;
581           D3DMATRIX *mat = odev->world_mat;
582
583           TRACE("  World Matrix : (%p)\n", mat);
584           dump_mat(mat);
585
586           ilpBuff->vertex_type = D3DVT_LVERTEX;
587
588           for (nb = 0; nb < ci->dwCount; nb++) {
589             dst->c  = src->u4.color;
590             dst->sc = src->u5.specular;
591             dst->u  = src->u6.tu;
592             dst->v  = src->u7.tv;
593
594             /* Now, the matrix multiplication */
595             dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
596             dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
597             dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
598             dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
599
600             src++;
601             dst++;
602           }
603         } else if (ci->dwFlags == D3DPROCESSVERTICES_COPY) {
604           D3DTLVERTEX *src = ((LPD3DTLVERTEX) (ilpBuff->desc.lpData + vs)) + ci->wStart;
605           D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (ilpBuff->vertex_data)) + ci->wDest;
606
607           ilpBuff->vertex_type = D3DVT_TLVERTEX;
608
609           memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
610         } else {
611           ERR("Unhandled vertex processing !\n");
612         }
613
614         instr += size;
615       }
616     } break;
617
618     case D3DOP_TEXTURELOAD: {
619       TRACE("TEXTURELOAD-s    (%d)\n", count);
620
621       instr += count * size;
622     } break;
623
624     case D3DOP_EXIT: {
625       TRACE("EXIT             (%d)\n", count);
626       /* We did this instruction */
627       instr += size;
628       /* Exit this loop */
629       goto end_of_buffer;
630     } break;
631
632     case D3DOP_BRANCHFORWARD: {
633       int i;
634       TRACE("BRANCHFORWARD    (%d)\n", count);
635
636       for (i = 0; i < count; i++) {
637         LPD3DBRANCH ci = (LPD3DBRANCH) instr;
638
639         if ((ilpBuff->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
640           if (!ci->bNegate) {
641             TRACE(" Should branch to %ld\n", ci->dwOffset);
642           }
643         } else {
644           if (ci->bNegate) {
645             TRACE(" Should branch to %ld\n", ci->dwOffset);
646           }
647         }
648
649         instr += size;
650       }
651     } break;
652
653     case D3DOP_SPAN: {
654       TRACE("SPAN-s           (%d)\n", count);
655
656       instr += count * size;
657     } break;
658
659     case D3DOP_SETSTATUS: {
660       int i;
661       TRACE("SETSTATUS        (%d)\n", count);
662
663       for (i = 0; i < count; i++) {
664         LPD3DSTATUS ci = (LPD3DSTATUS) instr;
665
666         ilpBuff->data.dsStatus = *ci;
667
668         instr += size;
669       }
670     } break;
671
672     default:
673       ERR("Unhandled OpCode !!!\n");
674       /* Try to save ... */
675       instr += count * size;
676       break;
677     }
678   }
679
680  end_of_buffer:
681   LEAVE_GL();
682 }
683
684 /*******************************************************************************
685  *                              ExecuteBuffer Creation functions
686  */
687 LPDIRECT3DEXECUTEBUFFER d3dexecutebuffer_create(IDirect3DDeviceImpl* d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc)
688 {
689   IDirect3DExecuteBufferImpl* eb;
690
691   eb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DExecuteBufferImpl));
692   eb->ref = 1;
693   ICOM_VTBL(eb) = &executebuffer_vtable;
694   eb->d3ddev = d3ddev;
695
696   /* Initializes memory */
697   eb->desc = *lpDesc;
698
699   /* No buffer given */
700   if (!(eb->desc.dwFlags & D3DDEB_LPDATA))
701     eb->desc.lpData = NULL;
702
703   /* No buffer size given */
704   if (!(lpDesc->dwFlags & D3DDEB_BUFSIZE))
705     eb->desc.dwBufferSize = 0;
706
707   /* Create buffer if asked */
708   if ((eb->desc.lpData == NULL) && (eb->desc.dwBufferSize > 0)) {
709     eb->need_free = TRUE;
710     eb->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,eb->desc.dwBufferSize);
711   } else {
712     eb->need_free = FALSE;
713   }
714
715   /* No vertices for the moment */
716   eb->vertex_data = NULL;
717
718   eb->desc.dwFlags |= D3DDEB_LPDATA;
719
720   eb->execute = execute;
721
722   return (LPDIRECT3DEXECUTEBUFFER)eb;
723 }
724
725 /*******************************************************************************
726  *                              IDirect3ExecuteBuffer methods
727  */
728
729 static HRESULT WINAPI IDirect3DExecuteBufferImpl_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface,
730                                                             REFIID riid,
731                                                             LPVOID* ppvObj)
732 {
733   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
734
735   FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
736
737   return S_OK;
738 }
739
740
741
742 static ULONG WINAPI IDirect3DExecuteBufferImpl_AddRef(LPDIRECT3DEXECUTEBUFFER iface)
743 {
744   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
745   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
746
747   return ++(This->ref);
748 }
749
750
751
752 static ULONG WINAPI IDirect3DExecuteBufferImpl_Release(LPDIRECT3DEXECUTEBUFFER iface)
753 {
754   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
755   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
756
757   if (!--(This->ref)) {
758     if ((This->desc.lpData != NULL) && This->need_free)
759       HeapFree(GetProcessHeap(),0,This->desc.lpData);
760
761     if (This->vertex_data != NULL)
762       HeapFree(GetProcessHeap(),0,This->vertex_data);
763
764     HeapFree(GetProcessHeap(),0,This);
765     return 0;
766   }
767
768   return This->ref;
769 }
770
771 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Initialize(LPDIRECT3DEXECUTEBUFFER iface,
772                                                         LPDIRECT3DDEVICE lpDirect3DDevice,
773                                                         LPD3DEXECUTEBUFFERDESC lpDesc)
774 {
775   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
776   FIXME("(%p)->(%p,%p): stub\n", This, lpDirect3DDevice, lpDesc);
777
778   return DD_OK;
779 }
780
781 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Lock(LPDIRECT3DEXECUTEBUFFER iface,
782                                                   LPD3DEXECUTEBUFFERDESC lpDesc)
783 {
784   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
785   TRACE("(%p)->(%p)\n", This, lpDesc);
786
787   /* Copies the buffer description */
788   *lpDesc = This->desc;
789
790   return DD_OK;
791 }
792
793 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Unlock(LPDIRECT3DEXECUTEBUFFER iface)
794 {
795   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
796   TRACE("(%p)->()\n", This);
797
798   return DD_OK;
799 }
800
801 static HRESULT WINAPI IDirect3DExecuteBufferImpl_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
802                                                             LPD3DEXECUTEDATA lpData)
803 {
804   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
805   DWORD nbvert;
806
807   TRACE("(%p)->(%p)\n", This, lpData);
808
809   This->data = *lpData;
810
811   /* Get the number of vertices in the execute buffer */
812   nbvert = This->data.dwVertexCount;
813
814   /* Prepares the transformed vertex buffer */
815   if (This->vertex_data != NULL)
816     HeapFree(GetProcessHeap(), 0, This->vertex_data);
817   This->vertex_data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,nbvert * sizeof(OGL_Vertex));
818
819
820   if (TRACE_ON(ddraw)) {
821     _dump_executedata(lpData);
822   }
823
824   return DD_OK;
825 }
826
827 static HRESULT WINAPI IDirect3DExecuteBufferImpl_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
828                                                             LPD3DEXECUTEDATA lpData)
829 {
830   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
831   TRACE("(%p)->(%p): stub\n", This, lpData);
832
833   *lpData = This->data;
834
835   return DD_OK;
836 }
837
838 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Validate(LPDIRECT3DEXECUTEBUFFER iface,
839                                                       LPDWORD lpdwOffset,
840                                                       LPD3DVALIDATECALLBACK lpFunc,
841                                                       LPVOID lpUserArg,
842                                                       DWORD dwReserved)
843 {
844   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
845   TRACE("(%p)->(%p,%p,%p,%lu)\n", This, lpdwOffset, lpFunc, lpUserArg, dwReserved);
846
847   return DD_OK;
848 }
849
850 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Optimize(LPDIRECT3DEXECUTEBUFFER iface,
851                                                       DWORD dwReserved)
852 {
853   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
854   TRACE("(%p)->(%lu)\n", This, dwReserved);
855
856   return DD_OK;
857 }
858
859
860 /*******************************************************************************
861  *                              IDirect3DLight VTable
862  */
863 static ICOM_VTABLE(IDirect3DExecuteBuffer) executebuffer_vtable =
864 {
865   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
866   /*** IUnknown methods ***/
867   IDirect3DExecuteBufferImpl_QueryInterface,
868   IDirect3DExecuteBufferImpl_AddRef,
869   IDirect3DExecuteBufferImpl_Release,
870   /*** IDirect3DExecuteBuffer methods ***/
871   IDirect3DExecuteBufferImpl_Initialize,
872   IDirect3DExecuteBufferImpl_Lock,
873   IDirect3DExecuteBufferImpl_Unlock,
874   IDirect3DExecuteBufferImpl_SetExecuteData,
875   IDirect3DExecuteBufferImpl_GetExecuteData,
876   IDirect3DExecuteBufferImpl_Validate,
877   IDirect3DExecuteBufferImpl_Optimize
878 };