Fixes for Sparc build.
[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   TRACE("ExecuteData : \n");
201   if (TRACE_ON(ddraw))
202   _dump_executedata(&(ilpBuff->data));
203
204   ENTER_GL();
205
206   while (1) {
207     LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
208     BYTE size;
209     WORD count;
210
211     count = current->wCount;
212     size = current->bSize;
213     instr += sizeof(D3DINSTRUCTION);
214
215     switch (current->bOpcode) {
216     case D3DOP_POINT: {
217       TRACE("POINT-s          (%d)\n", count);
218
219       instr += count * size;
220     } break;
221
222     case D3DOP_LINE: {
223       TRACE("LINE-s           (%d)\n", count);
224
225       instr += count * size;
226     } break;
227
228     case D3DOP_TRIANGLE: {
229       int i;
230       float z_inv_matrix[16] = {
231         1.0, 0.0,  0.0, 0.0,
232         0.0, 1.0,  0.0, 0.0,
233         0.0, 0.0, -1.0, 0.0,
234         0.0, 0.0,  1.0, 1.0
235       };
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         glLoadMatrixf((float *) z_inv_matrix);
259         glMultMatrixf((float *) odev->proj_mat);
260       glMultMatrixf((float *) odev->view_mat);
261         break;
262
263       case D3DVT_LVERTEX:
264         /* No lighting */
265         glDisable(GL_LIGHTING);
266
267         /* Use given matrixes */
268         glMatrixMode(GL_MODELVIEW);
269         glLoadIdentity(); /* The model transformation was done during the
270                              transformation phase */
271         glMatrixMode(GL_PROJECTION);
272
273         TRACE("  Projection Matrix : (%p)\n", odev->proj_mat);
274         dump_mat(odev->proj_mat);
275         TRACE("  View       Matrix : (%p)\n", odev->view_mat);
276         dump_mat(odev->view_mat);
277
278         glLoadMatrixf((float *) z_inv_matrix);
279         glMultMatrixf((float *) odev->proj_mat);
280         glMultMatrixf((float *) odev->view_mat);
281         break;
282
283       case D3DVT_TLVERTEX: {
284         GLdouble height, width, minZ, maxZ;
285
286         /* First, disable lighting */
287         glDisable(GL_LIGHTING);
288
289         /* Then do not put any transformation matrixes */
290         glMatrixMode(GL_MODELVIEW);
291         glLoadIdentity();
292         glMatrixMode(GL_PROJECTION);
293         glLoadIdentity();
294
295         if (ivp == NULL) {
296           ERR("No current viewport !\n");
297           /* Using standard values */
298           height = 640.0;
299           width = 480.0;
300           minZ = -10.0;
301           maxZ = 10.0;
302         } else {
303           height = (GLdouble) ivp->viewport.vp1.dwHeight;
304           width  = (GLdouble) ivp->viewport.vp1.dwWidth;
305           minZ   = (GLdouble) ivp->viewport.vp1.dvMinZ;
306           maxZ   = (GLdouble) ivp->viewport.vp1.dvMaxZ;
307
308           if (minZ == maxZ) {
309             /* I do not know why, but many Dx 3.0 games have minZ = maxZ = 0.0 */
310             minZ = 0.0;
311             maxZ = 1.0;
312         }
313         }
314
315         glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
316       } break;
317
318       default:
319         ERR("Unhandled vertex type !\n");
320         break;
321       }
322
323       switch (ilpBuff->vertex_type) {
324       case D3DVT_VERTEX:
325         TRIANGLE_LOOP(DO_VERTEX);
326         break;
327
328       case D3DVT_LVERTEX:
329         TRIANGLE_LOOP(DO_LVERTEX);
330         break;
331
332       case D3DVT_TLVERTEX:
333         TRIANGLE_LOOP(DO_TLVERTEX);
334         break;
335
336       default:
337         ERR("Unhandled vertex type !\n");
338       }
339
340     } break;
341
342     case D3DOP_MATRIXLOAD: {
343       TRACE("MATRIXLOAD-s     (%d)\n", count);
344
345       instr += count * size;
346     } break;
347
348     case D3DOP_MATRIXMULTIPLY: {
349       int i;
350       TRACE("MATRIXMULTIPLY   (%d)\n", count);
351
352       for (i = 0; i < count; i++) {
353         LPD3DMATRIXMULTIPLY ci = (LPD3DMATRIXMULTIPLY) instr;
354         LPD3DMATRIX a = (LPD3DMATRIX) ci->hDestMatrix;
355         LPD3DMATRIX b = (LPD3DMATRIX) ci->hSrcMatrix1;
356         LPD3DMATRIX c = (LPD3DMATRIX) ci->hSrcMatrix2;
357
358         TRACE("  Dest : %08lx  Src1 : %08lx  Src2 : %08lx\n",
359               ci->hDestMatrix, ci->hSrcMatrix1, ci->hSrcMatrix2);
360
361         /* Do the multiplication..
362            As I am VERY lazy, I let OpenGL do the multiplication for me */
363         glMatrixMode(GL_PROJECTION);
364         /* Save the current matrix */
365         glPushMatrix();
366         /* Load Matrix one and do the multiplication */
367         glLoadMatrixf((float *) c);
368         glMultMatrixf((float *) b);
369         glGetFloatv(GL_PROJECTION_MATRIX, (float *) a);
370         /* Restore the current matrix */
371         glPopMatrix();
372
373         instr += size;
374       }
375     } break;
376
377     case D3DOP_STATETRANSFORM: {
378       int i;
379       TRACE("STATETRANSFORM   (%d)\n", count);
380
381       for (i = 0; i < count; i++) {
382         LPD3DSTATE ci = (LPD3DSTATE) instr;
383
384         /* Handle the state transform */
385         switch (ci->u1.dtstTransformStateType) {
386         case D3DTRANSFORMSTATE_WORLD: {
387           TRACE("  WORLD (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
388           odev->world_mat = (D3DMATRIX*) ci->u2.dwArg[0];
389         } break;
390
391         case D3DTRANSFORMSTATE_VIEW: {
392           TRACE("  VIEW (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
393           odev->view_mat = (D3DMATRIX*) ci->u2.dwArg[0];
394         } break;
395
396         case D3DTRANSFORMSTATE_PROJECTION: {
397           TRACE("  PROJECTION (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
398           odev->proj_mat = (D3DMATRIX*) ci->u2.dwArg[0];
399         } break;
400
401         default:
402           ERR("  Unhandled state transformation !! (%d)\n", (int) ci->u1.dtstTransformStateType);
403           break;
404
405         }
406
407         instr += size;
408       }
409     } break;
410
411     case D3DOP_STATELIGHT: {
412       int i;
413       TRACE("STATELIGHT       (%d)\n", count);
414
415       for (i = 0; i < count; i++) {
416         LPD3DSTATE ci = (LPD3DSTATE) instr;
417
418         /* Handle the state transform */
419         switch (ci->u1.dlstLightStateType) {
420         case D3DLIGHTSTATE_MATERIAL: {
421           IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) ci->u2.dwArg[0];
422           TRACE("  MATERIAL\n");
423
424           if (mat != NULL) {
425             mat->activate(mat);
426           } else {
427             TRACE("    bad Material Handle\n");
428           }
429         } break ;
430
431         case D3DLIGHTSTATE_AMBIENT: {
432           float light[4];
433           DWORD dwLightState = ci->u2.dwArg[0];
434           TRACE("  AMBIENT\n");
435
436           light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
437           light[1] = ((dwLightState >>  8) & 0xFF) / 255.0;
438           light[2] = ((dwLightState >>  0) & 0xFF) / 255.0;
439           light[3] = 1.0;
440           glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
441
442           TRACE("    R:%02lx G:%02lx B:%02lx A:%02lx\n",
443                 ((dwLightState >> 16) & 0xFF),
444                 ((dwLightState >>  8) & 0xFF),
445                 ((dwLightState >>  0) & 0xFF),
446                 ((dwLightState >> 24) & 0xFF));
447         } break ;
448
449         case D3DLIGHTSTATE_COLORMODEL: {
450           TRACE("  COLORMODEL\n");
451         } break ;
452
453         case D3DLIGHTSTATE_FOGMODE: {
454           TRACE("  FOGMODE\n");
455         } break ;
456
457         case D3DLIGHTSTATE_FOGSTART: {
458           TRACE("  FOGSTART\n");
459         } break ;
460
461         case D3DLIGHTSTATE_FOGEND: {
462           TRACE("  FOGEND\n");
463         } break ;
464
465         case D3DLIGHTSTATE_FOGDENSITY: {
466           TRACE("  FOGDENSITY\n");
467         } break ;
468
469         default:
470           ERR("  Unhandled light state !! (%d)\n", (int) ci->u1.dlstLightStateType);
471           break;
472         }
473         instr += size;
474       }
475     } break;
476
477     case D3DOP_STATERENDER: {
478       int i;
479       TRACE("STATERENDER      (%d)\n", count);
480
481       for (i = 0; i < count; i++) {
482         LPD3DSTATE ci = (LPD3DSTATE) instr;
483
484         /* Handle the state transform */
485         set_render_state(ci->u1.drstRenderStateType, ci->u2.dwArg[0], &(odev->rs));
486
487         instr += size;
488       }
489     } break;
490
491     case D3DOP_PROCESSVERTICES: {
492       int i;
493       TRACE("PROCESSVERTICES  (%d)\n", count);
494
495       for (i = 0; i < count; i++) {
496         LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
497
498         TRACE("  Start : %d Dest : %d Count : %ld\n",
499               ci->wStart, ci->wDest, ci->dwCount);
500         TRACE("  Flags : ");
501         if (TRACE_ON(ddraw)) {
502           if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
503             DPRINTF("COPY ");
504           if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
505             DPRINTF("NOCOLOR ");
506           if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
507             DPRINTF("OPMASK ");
508           if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
509             DPRINTF("TRANSFORM ");
510           if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
511             DPRINTF("TRANSFORMLIGHT ");
512           if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
513             DPRINTF("UPDATEEXTENTS ");
514           DPRINTF("\n");
515         }
516
517         /* This is where doing Direct3D on top on OpenGL is quite difficult.
518            This method transforms a set of vertices using the CURRENT state
519            (lighting, projection, ...) but does not rasterize them.
520            They will only be put on screen later (with the POINT / LINE and
521            TRIANGLE op-codes). The problem is that you can have a triangle
522            with each point having been transformed using another state...
523
524            In this implementation, I will emulate only ONE thing : each
525            vertex can have its own "WORLD" transformation (this is used in the
526            TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
527            execute buffer use the same state.
528
529            If I find applications that change other states, I will try to do a
530            more 'fine-tuned' state emulation (but I may become quite tricky if
531            it changes a light position in the middle of a triangle).
532
533            In this case, a 'direct' approach (i.e. without using OpenGL, but
534            writing our own 3D rasterizer) would be easier. */
535
536         /* The current method (with the hypothesis that only the WORLD matrix
537            will change between two points) is like this :
538             - I transform 'manually' all the vertices with the current WORLD
539               matrix and store them in the vertex buffer
540             - during the rasterization phase, the WORLD matrix will be set to
541               the Identity matrix */
542
543         /* Enough for the moment */
544         if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
545           int nb;
546           D3DVERTEX  *src = ((LPD3DVERTEX)  (ilpBuff->desc.lpData + vs)) + ci->wStart;
547           OGL_Vertex *dst = ((OGL_Vertex *) (ilpBuff->vertex_data)) + ci->wDest;
548           D3DMATRIX *mat = odev->world_mat;
549
550           TRACE("  World Matrix : (%p)\n", mat);
551           dump_mat(mat);
552
553           ilpBuff->vertex_type = D3DVT_VERTEX;
554
555           for (nb = 0; nb < ci->dwCount; nb++) {
556             /* For the moment, no normal transformation... */
557             dst->nx = src->u4.nx;
558             dst->ny = src->u5.ny;
559             dst->nz = src->u6.nz;
560
561             dst->u  = src->u7.tu;
562             dst->v  = src->u8.tv;
563
564             /* Now, the matrix multiplication */
565             dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
566             dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
567             dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
568             dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
569
570             src++;
571             dst++;
572           }
573         } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
574           int nb;
575           D3DLVERTEX *src  = ((LPD3DLVERTEX) (ilpBuff->desc.lpData + vs)) + ci->wStart;
576           OGL_LVertex *dst = ((OGL_LVertex *) (ilpBuff->vertex_data)) + ci->wDest;
577           D3DMATRIX *mat = odev->world_mat;
578
579           TRACE("  World Matrix : (%p)\n", mat);
580           dump_mat(mat);
581
582           ilpBuff->vertex_type = D3DVT_LVERTEX;
583
584           for (nb = 0; nb < ci->dwCount; nb++) {
585             dst->c  = src->u4.color;
586             dst->sc = src->u5.specular;
587             dst->u  = src->u6.tu;
588             dst->v  = src->u7.tv;
589
590             /* Now, the matrix multiplication */
591             dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
592             dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
593             dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
594             dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
595
596             src++;
597             dst++;
598           }
599         } else if (ci->dwFlags == D3DPROCESSVERTICES_COPY) {
600           D3DTLVERTEX *src = ((LPD3DTLVERTEX) (ilpBuff->desc.lpData + vs)) + ci->wStart;
601           D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (ilpBuff->vertex_data)) + ci->wDest;
602
603           ilpBuff->vertex_type = D3DVT_TLVERTEX;
604
605           memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
606         } else {
607           ERR("Unhandled vertex processing !\n");
608         }
609
610         instr += size;
611       }
612     } break;
613
614     case D3DOP_TEXTURELOAD: {
615       TRACE("TEXTURELOAD-s    (%d)\n", count);
616
617       instr += count * size;
618     } break;
619
620     case D3DOP_EXIT: {
621       TRACE("EXIT             (%d)\n", count);
622       /* We did this instruction */
623       instr += size;
624       /* Exit this loop */
625       goto end_of_buffer;
626     } break;
627
628     case D3DOP_BRANCHFORWARD: {
629       int i;
630       TRACE("BRANCHFORWARD    (%d)\n", count);
631
632       for (i = 0; i < count; i++) {
633         LPD3DBRANCH ci = (LPD3DBRANCH) instr;
634
635         if ((ilpBuff->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
636           if (!ci->bNegate) {
637             TRACE(" Should branch to %ld\n", ci->dwOffset);
638           }
639         } else {
640           if (ci->bNegate) {
641             TRACE(" Should branch to %ld\n", ci->dwOffset);
642           }
643         }
644
645         instr += size;
646       }
647     } break;
648
649     case D3DOP_SPAN: {
650       TRACE("SPAN-s           (%d)\n", count);
651
652       instr += count * size;
653     } break;
654
655     case D3DOP_SETSTATUS: {
656       int i;
657       TRACE("SETSTATUS        (%d)\n", count);
658
659       for (i = 0; i < count; i++) {
660         LPD3DSTATUS ci = (LPD3DSTATUS) instr;
661
662         ilpBuff->data.dsStatus = *ci;
663
664         instr += size;
665       }
666     } break;
667
668     default:
669       ERR("Unhandled OpCode !!!\n");
670       /* Try to save ... */
671       instr += count * size;
672       break;
673     }
674   }
675
676  end_of_buffer:
677   LEAVE_GL();
678 }
679
680 /*******************************************************************************
681  *                              ExecuteBuffer Creation functions
682  */
683 LPDIRECT3DEXECUTEBUFFER d3dexecutebuffer_create(IDirect3DDeviceImpl* d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc)
684 {
685   IDirect3DExecuteBufferImpl* eb;
686
687   eb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DExecuteBufferImpl));
688   eb->ref = 1;
689   ICOM_VTBL(eb) = &executebuffer_vtable;
690   eb->d3ddev = d3ddev;
691
692   /* Initializes memory */
693   eb->desc = *lpDesc;
694
695   /* No buffer given */
696   if (!(eb->desc.dwFlags & D3DDEB_LPDATA))
697     eb->desc.lpData = NULL;
698
699   /* No buffer size given */
700   if (!(lpDesc->dwFlags & D3DDEB_BUFSIZE))
701     eb->desc.dwBufferSize = 0;
702
703   /* Create buffer if asked */
704   if ((eb->desc.lpData == NULL) && (eb->desc.dwBufferSize > 0)) {
705     eb->need_free = TRUE;
706     eb->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,eb->desc.dwBufferSize);
707   } else {
708     eb->need_free = FALSE;
709   }
710
711   /* No vertices for the moment */
712   eb->vertex_data = NULL;
713
714   eb->desc.dwFlags |= D3DDEB_LPDATA;
715
716   eb->execute = execute;
717
718   return (LPDIRECT3DEXECUTEBUFFER)eb;
719 }
720
721 /*******************************************************************************
722  *                              IDirect3ExecuteBuffer methods
723  */
724
725 static HRESULT WINAPI IDirect3DExecuteBufferImpl_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface,
726                                                             REFIID riid,
727                                                             LPVOID* ppvObj)
728 {
729   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
730
731   FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
732
733   return S_OK;
734 }
735
736
737
738 static ULONG WINAPI IDirect3DExecuteBufferImpl_AddRef(LPDIRECT3DEXECUTEBUFFER iface)
739 {
740   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
741   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
742
743   return ++(This->ref);
744 }
745
746
747
748 static ULONG WINAPI IDirect3DExecuteBufferImpl_Release(LPDIRECT3DEXECUTEBUFFER iface)
749 {
750   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
751   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
752
753   if (!--(This->ref)) {
754     if ((This->desc.lpData != NULL) && This->need_free)
755       HeapFree(GetProcessHeap(),0,This->desc.lpData);
756
757     if (This->vertex_data != NULL)
758       HeapFree(GetProcessHeap(),0,This->vertex_data);
759
760     HeapFree(GetProcessHeap(),0,This);
761     return 0;
762   }
763
764   return This->ref;
765 }
766
767 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Initialize(LPDIRECT3DEXECUTEBUFFER iface,
768                                                         LPDIRECT3DDEVICE lpDirect3DDevice,
769                                                         LPD3DEXECUTEBUFFERDESC lpDesc)
770 {
771   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
772   FIXME("(%p)->(%p,%p): stub\n", This, lpDirect3DDevice, lpDesc);
773
774   return DD_OK;
775 }
776
777 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Lock(LPDIRECT3DEXECUTEBUFFER iface,
778                                                   LPD3DEXECUTEBUFFERDESC lpDesc)
779 {
780   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
781   TRACE("(%p)->(%p)\n", This, lpDesc);
782
783   /* Copies the buffer description */
784   *lpDesc = This->desc;
785
786   return DD_OK;
787 }
788
789 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Unlock(LPDIRECT3DEXECUTEBUFFER iface)
790 {
791   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
792   TRACE("(%p)->()\n", This);
793
794   return DD_OK;
795 }
796
797 static HRESULT WINAPI IDirect3DExecuteBufferImpl_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
798                                                             LPD3DEXECUTEDATA lpData)
799 {
800   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
801   DWORD nbvert;
802
803   TRACE("(%p)->(%p)\n", This, lpData);
804
805   This->data = *lpData;
806
807   /* Get the number of vertices in the execute buffer */
808   nbvert = This->data.dwVertexCount;
809
810   /* Prepares the transformed vertex buffer */
811   if (This->vertex_data != NULL)
812     HeapFree(GetProcessHeap(), 0, This->vertex_data);
813   This->vertex_data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,nbvert * sizeof(OGL_Vertex));
814
815
816   if (TRACE_ON(ddraw)) {
817     _dump_executedata(lpData);
818   }
819
820   return DD_OK;
821 }
822
823 static HRESULT WINAPI IDirect3DExecuteBufferImpl_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
824                                                             LPD3DEXECUTEDATA lpData)
825 {
826   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
827   TRACE("(%p)->(%p): stub\n", This, lpData);
828
829   *lpData = This->data;
830
831   return DD_OK;
832 }
833
834 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Validate(LPDIRECT3DEXECUTEBUFFER iface,
835                                                       LPDWORD lpdwOffset,
836                                                       LPD3DVALIDATECALLBACK lpFunc,
837                                                       LPVOID lpUserArg,
838                                                       DWORD dwReserved)
839 {
840   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
841   TRACE("(%p)->(%p,%p,%p,%lu)\n", This, lpdwOffset, lpFunc, lpUserArg, dwReserved);
842
843   return DD_OK;
844 }
845
846 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Optimize(LPDIRECT3DEXECUTEBUFFER iface,
847                                                       DWORD dwReserved)
848 {
849   ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
850   TRACE("(%p)->(%lu)\n", This, dwReserved);
851
852   return DD_OK;
853 }
854
855
856 /*******************************************************************************
857  *                              IDirect3DLight VTable
858  */
859 static ICOM_VTABLE(IDirect3DExecuteBuffer) executebuffer_vtable =
860 {
861   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
862   /*** IUnknown methods ***/
863   IDirect3DExecuteBufferImpl_QueryInterface,
864   IDirect3DExecuteBufferImpl_AddRef,
865   IDirect3DExecuteBufferImpl_Release,
866   /*** IDirect3DExecuteBuffer methods ***/
867   IDirect3DExecuteBufferImpl_Initialize,
868   IDirect3DExecuteBufferImpl_Lock,
869   IDirect3DExecuteBufferImpl_Unlock,
870   IDirect3DExecuteBufferImpl_SetExecuteData,
871   IDirect3DExecuteBufferImpl_GetExecuteData,
872   IDirect3DExecuteBufferImpl_Validate,
873   IDirect3DExecuteBufferImpl_Optimize
874 };