execute: Activate the viewport passed as parameter when executing
[wine/multimedia.git] / dlls / ddraw / d3dexecutebuffer.c
blobdb84a353f2b5c0cf75a9f7d596d805bbdee98006
1 /* Direct3D ExecuteBuffer
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the implementation of Direct3DExecuteBuffer.
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.
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.
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
21 #include "config.h"
23 #include <string.h>
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"
32 #include "mesa_private.h"
34 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)(x)->private)
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38 /* Structure to store the 'semi transformed' vertices */
39 typedef struct {
40 D3DVALUE x;
41 D3DVALUE y;
42 D3DVALUE z;
43 D3DVALUE w;
45 D3DVALUE nx;
46 D3DVALUE ny;
47 D3DVALUE nz;
49 D3DVALUE u;
50 D3DVALUE v;
51 } OGL_Vertex;
53 typedef struct {
54 D3DVALUE x;
55 D3DVALUE y;
56 D3DVALUE z;
57 D3DVALUE w;
59 D3DCOLOR c;
60 D3DCOLOR sc;
62 D3DVALUE u;
63 D3DVALUE v;
64 } OGL_LVertex;
66 static ICOM_VTABLE(IDirect3DExecuteBuffer) executebuffer_vtable;
68 /*******************************************************************************
69 * ExecuteBuffer static functions
71 void _dump_d3dstatus(LPD3DSTATUS lpStatus) {
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));
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); \
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); \
101 #define DO_LVERTEX(index) \
103 DWORD col = l_vx[index].c; \
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); \
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); \
121 #define DO_TLVERTEX(index) \
123 D3DTLVERTEX *vx = &(tl_vx[index]); \
124 DWORD col = vx->u5.color; \
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); \
145 #define TRIANGLE_LOOP(macro) \
147 glBegin(GL_TRIANGLES); { \
148 for (i = 0; i < count; i++) { \
149 LPD3DTRIANGLE ci = (LPD3DTRIANGLE) instr; \
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 "); \
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"); \
175 /* Draw the triangle */ \
176 macro(ci->u1.v1); \
177 macro(ci->u2.v2); \
178 macro(ci->u3.v3); \
180 instr += size; \
182 } glEnd(); \
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; */
197 void *instr = ilpBuff->desc.lpData + is;
198 D3DDPRIVATE((IDirect3DDeviceImpl*)dev);
200 /* Should check if the viewport was added or not to the device */
202 /* Activate the viewport */
203 ivp->device.active_device1 = (IDirect3DDeviceImpl*)dev;
204 ivp->activate(ivp);
206 TRACE("ExecuteData : \n");
207 if (TRACE_ON(ddraw))
208 _dump_executedata(&(ilpBuff->data));
210 ENTER_GL();
212 while (1) {
213 LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
214 BYTE size;
215 WORD count;
217 count = current->wCount;
218 size = current->bSize;
219 instr += sizeof(D3DINSTRUCTION);
221 switch (current->bOpcode) {
222 case D3DOP_POINT: {
223 TRACE("POINT-s (%d)\n", count);
225 instr += count * size;
226 } break;
228 case D3DOP_LINE: {
229 TRACE("LINE-s (%d)\n", count);
231 instr += count * size;
232 } break;
234 case D3DOP_TRIANGLE: {
235 int i;
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;
241 TRACE("TRIANGLE (%d)\n", count);
243 switch (ilpBuff->vertex_type) {
244 case D3DVT_VERTEX:
245 /* This time, there is lighting */
246 glEnable(GL_LIGHTING);
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);
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;
265 case D3DVT_LVERTEX:
266 /* No lighting */
267 glDisable(GL_LIGHTING);
269 /* Use given matrixes */
270 glMatrixMode(GL_MODELVIEW);
271 glLoadIdentity(); /* The model transformation was done during the
272 transformation phase */
273 glMatrixMode(GL_PROJECTION);
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);
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;
287 case D3DVT_TLVERTEX: {
288 GLdouble height, width, minZ, maxZ;
290 /* First, disable lighting */
291 glDisable(GL_LIGHTING);
293 /* Then do not put any transformation matrixes */
294 glMatrixMode(GL_MODELVIEW);
295 glLoadIdentity();
296 glMatrixMode(GL_PROJECTION);
297 glLoadIdentity();
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;
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;
319 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
320 } break;
322 default:
323 ERR("Unhandled vertex type !\n");
324 break;
327 switch (ilpBuff->vertex_type) {
328 case D3DVT_VERTEX:
329 TRIANGLE_LOOP(DO_VERTEX);
330 break;
332 case D3DVT_LVERTEX:
333 TRIANGLE_LOOP(DO_LVERTEX);
334 break;
336 case D3DVT_TLVERTEX:
337 TRIANGLE_LOOP(DO_TLVERTEX);
338 break;
340 default:
341 ERR("Unhandled vertex type !\n");
344 } break;
346 case D3DOP_MATRIXLOAD: {
347 TRACE("MATRIXLOAD-s (%d)\n", count);
349 instr += count * size;
350 } break;
352 case D3DOP_MATRIXMULTIPLY: {
353 int i;
354 TRACE("MATRIXMULTIPLY (%d)\n", count);
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;
362 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
363 ci->hDestMatrix, ci->hSrcMatrix1, ci->hSrcMatrix2);
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();
377 instr += size;
379 } break;
381 case D3DOP_STATETRANSFORM: {
382 int i;
383 TRACE("STATETRANSFORM (%d)\n", count);
385 for (i = 0; i < count; i++) {
386 LPD3DSTATE ci = (LPD3DSTATE) instr;
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;
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;
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;
405 default:
406 ERR(" Unhandled state transformation !! (%d)\n", (int) ci->u1.dtstTransformStateType);
407 break;
411 instr += size;
413 } break;
415 case D3DOP_STATELIGHT: {
416 int i;
417 TRACE("STATELIGHT (%d)\n", count);
419 for (i = 0; i < count; i++) {
420 LPD3DSTATE ci = (LPD3DSTATE) instr;
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");
428 if (mat != NULL) {
429 mat->activate(mat);
430 } else {
431 TRACE(" bad Material Handle\n");
433 } break ;
435 case D3DLIGHTSTATE_AMBIENT: {
436 float light[4];
437 DWORD dwLightState = ci->u2.dwArg[0];
438 TRACE(" AMBIENT\n");
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);
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 ;
453 case D3DLIGHTSTATE_COLORMODEL: {
454 TRACE(" COLORMODEL\n");
455 } break ;
457 case D3DLIGHTSTATE_FOGMODE: {
458 TRACE(" FOGMODE\n");
459 } break ;
461 case D3DLIGHTSTATE_FOGSTART: {
462 TRACE(" FOGSTART\n");
463 } break ;
465 case D3DLIGHTSTATE_FOGEND: {
466 TRACE(" FOGEND\n");
467 } break ;
469 case D3DLIGHTSTATE_FOGDENSITY: {
470 TRACE(" FOGDENSITY\n");
471 } break ;
473 default:
474 ERR(" Unhandled light state !! (%d)\n", (int) ci->u1.dlstLightStateType);
475 break;
477 instr += size;
479 } break;
481 case D3DOP_STATERENDER: {
482 int i;
483 TRACE("STATERENDER (%d)\n", count);
485 for (i = 0; i < count; i++) {
486 LPD3DSTATE ci = (LPD3DSTATE) instr;
488 /* Handle the state transform */
489 set_render_state(ci->u1.drstRenderStateType, ci->u2.dwArg[0], &(odev->rs));
491 instr += size;
493 } break;
495 case D3DOP_PROCESSVERTICES: {
496 int i;
497 TRACE("PROCESSVERTICES (%d)\n", count);
499 for (i = 0; i < count; i++) {
500 LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
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");
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...
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.
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).
537 In this case, a 'direct' approach (i.e. without using OpenGL, but
538 writing our own 3D rasterizer) would be easier. */
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 */
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;
554 TRACE(" World Matrix : (%p)\n", mat);
555 dump_mat(mat);
557 ilpBuff->vertex_type = D3DVT_VERTEX;
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);
565 dst->u = src->u7.tu;
566 dst->v = src->u8.tv;
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);
574 src++;
575 dst++;
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;
583 TRACE(" World Matrix : (%p)\n", mat);
584 dump_mat(mat);
586 ilpBuff->vertex_type = D3DVT_LVERTEX;
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;
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);
600 src++;
601 dst++;
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;
607 ilpBuff->vertex_type = D3DVT_TLVERTEX;
609 memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
610 } else {
611 ERR("Unhandled vertex processing !\n");
614 instr += size;
616 } break;
618 case D3DOP_TEXTURELOAD: {
619 TRACE("TEXTURELOAD-s (%d)\n", count);
621 instr += count * size;
622 } break;
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;
632 case D3DOP_BRANCHFORWARD: {
633 int i;
634 TRACE("BRANCHFORWARD (%d)\n", count);
636 for (i = 0; i < count; i++) {
637 LPD3DBRANCH ci = (LPD3DBRANCH) instr;
639 if ((ilpBuff->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
640 if (!ci->bNegate) {
641 TRACE(" Should branch to %ld\n", ci->dwOffset);
643 } else {
644 if (ci->bNegate) {
645 TRACE(" Should branch to %ld\n", ci->dwOffset);
649 instr += size;
651 } break;
653 case D3DOP_SPAN: {
654 TRACE("SPAN-s (%d)\n", count);
656 instr += count * size;
657 } break;
659 case D3DOP_SETSTATUS: {
660 int i;
661 TRACE("SETSTATUS (%d)\n", count);
663 for (i = 0; i < count; i++) {
664 LPD3DSTATUS ci = (LPD3DSTATUS) instr;
666 ilpBuff->data.dsStatus = *ci;
668 instr += size;
670 } break;
672 default:
673 ERR("Unhandled OpCode !!!\n");
674 /* Try to save ... */
675 instr += count * size;
676 break;
680 end_of_buffer:
681 LEAVE_GL();
684 /*******************************************************************************
685 * ExecuteBuffer Creation functions
687 LPDIRECT3DEXECUTEBUFFER d3dexecutebuffer_create(IDirect3DDeviceImpl* d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc)
689 IDirect3DExecuteBufferImpl* eb;
691 eb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DExecuteBufferImpl));
692 eb->ref = 1;
693 ICOM_VTBL(eb) = &executebuffer_vtable;
694 eb->d3ddev = d3ddev;
696 /* Initializes memory */
697 eb->desc = *lpDesc;
699 /* No buffer given */
700 if (!(eb->desc.dwFlags & D3DDEB_LPDATA))
701 eb->desc.lpData = NULL;
703 /* No buffer size given */
704 if (!(lpDesc->dwFlags & D3DDEB_BUFSIZE))
705 eb->desc.dwBufferSize = 0;
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;
715 /* No vertices for the moment */
716 eb->vertex_data = NULL;
718 eb->desc.dwFlags |= D3DDEB_LPDATA;
720 eb->execute = execute;
722 return (LPDIRECT3DEXECUTEBUFFER)eb;
725 /*******************************************************************************
726 * IDirect3ExecuteBuffer methods
729 static HRESULT WINAPI IDirect3DExecuteBufferImpl_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface,
730 REFIID riid,
731 LPVOID* ppvObj)
733 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
735 FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
737 return S_OK;
742 static ULONG WINAPI IDirect3DExecuteBufferImpl_AddRef(LPDIRECT3DEXECUTEBUFFER iface)
744 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
745 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
747 return ++(This->ref);
752 static ULONG WINAPI IDirect3DExecuteBufferImpl_Release(LPDIRECT3DEXECUTEBUFFER iface)
754 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
755 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
757 if (!--(This->ref)) {
758 if ((This->desc.lpData != NULL) && This->need_free)
759 HeapFree(GetProcessHeap(),0,This->desc.lpData);
761 if (This->vertex_data != NULL)
762 HeapFree(GetProcessHeap(),0,This->vertex_data);
764 HeapFree(GetProcessHeap(),0,This);
765 return 0;
768 return This->ref;
771 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Initialize(LPDIRECT3DEXECUTEBUFFER iface,
772 LPDIRECT3DDEVICE lpDirect3DDevice,
773 LPD3DEXECUTEBUFFERDESC lpDesc)
775 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
776 FIXME("(%p)->(%p,%p): stub\n", This, lpDirect3DDevice, lpDesc);
778 return DD_OK;
781 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Lock(LPDIRECT3DEXECUTEBUFFER iface,
782 LPD3DEXECUTEBUFFERDESC lpDesc)
784 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
785 TRACE("(%p)->(%p)\n", This, lpDesc);
787 /* Copies the buffer description */
788 *lpDesc = This->desc;
790 return DD_OK;
793 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Unlock(LPDIRECT3DEXECUTEBUFFER iface)
795 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
796 TRACE("(%p)->()\n", This);
798 return DD_OK;
801 static HRESULT WINAPI IDirect3DExecuteBufferImpl_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
802 LPD3DEXECUTEDATA lpData)
804 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
805 DWORD nbvert;
807 TRACE("(%p)->(%p)\n", This, lpData);
809 This->data = *lpData;
811 /* Get the number of vertices in the execute buffer */
812 nbvert = This->data.dwVertexCount;
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));
820 if (TRACE_ON(ddraw)) {
821 _dump_executedata(lpData);
824 return DD_OK;
827 static HRESULT WINAPI IDirect3DExecuteBufferImpl_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
828 LPD3DEXECUTEDATA lpData)
830 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
831 TRACE("(%p)->(%p): stub\n", This, lpData);
833 *lpData = This->data;
835 return DD_OK;
838 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Validate(LPDIRECT3DEXECUTEBUFFER iface,
839 LPDWORD lpdwOffset,
840 LPD3DVALIDATECALLBACK lpFunc,
841 LPVOID lpUserArg,
842 DWORD dwReserved)
844 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
845 TRACE("(%p)->(%p,%p,%p,%lu)\n", This, lpdwOffset, lpFunc, lpUserArg, dwReserved);
847 return DD_OK;
850 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Optimize(LPDIRECT3DEXECUTEBUFFER iface,
851 DWORD dwReserved)
853 ICOM_THIS(IDirect3DExecuteBufferImpl,iface);
854 TRACE("(%p)->(%lu)\n", This, dwReserved);
856 return DD_OK;
860 /*******************************************************************************
861 * IDirect3DLight VTable
863 static ICOM_VTABLE(IDirect3DExecuteBuffer) executebuffer_vtable =
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