Make sure that no files except unknwn.h include wine/obj_base.h
[wine/hacks.git] / dlls / ddraw / d3dexecutebuffer.c
blob67415949929b994d3aeb946af33867d5658b7462
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 "objbase.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "wine/debug.h"
32 #include "d3d_private.h"
33 #include "mesa_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* Structure to store the 'semi transformed' vertices */
38 typedef struct {
39 D3DVALUE x;
40 D3DVALUE y;
41 D3DVALUE z;
42 D3DVALUE w;
44 D3DVALUE nx;
45 D3DVALUE ny;
46 D3DVALUE nz;
48 D3DVALUE u;
49 D3DVALUE v;
50 } OGL_Vertex;
52 typedef struct {
53 D3DVALUE x;
54 D3DVALUE y;
55 D3DVALUE z;
56 D3DVALUE w;
58 D3DCOLOR c;
59 D3DCOLOR sc;
61 D3DVALUE u;
62 D3DVALUE v;
63 } OGL_LVertex;
65 static void _dump_d3dstatus(LPD3DSTATUS lpStatus) {
69 static void _dump_executedata(LPD3DEXECUTEDATA lpData) {
70 DPRINTF("dwSize : %ld\n", lpData->dwSize);
71 DPRINTF("Vertex Offset : %ld Count : %ld\n", lpData->dwVertexOffset, lpData->dwVertexCount);
72 DPRINTF("Instruction Offset : %ld Length : %ld\n", lpData->dwInstructionOffset, lpData->dwInstructionLength);
73 DPRINTF("HVertex Offset : %ld\n", lpData->dwHVertexOffset);
74 _dump_d3dstatus(&(lpData->dsStatus));
77 static void _dump_D3DEXECUTEBUFFERDESC(LPD3DEXECUTEBUFFERDESC lpDesc) {
81 #define DO_VERTEX(index) \
82 { \
83 glTexCoord2f(vx[index].u, \
84 vx[index].v); \
85 glNormal3f(vx[index].nx, \
86 vx[index].ny, \
87 vx[index].nz); \
88 glVertex4f(vx[index].x, \
89 vx[index].y, \
90 vx[index].z, \
91 vx[index].w); \
93 TRACE(" V: %f %f %f %f (%f %f %f) (%f %f)\n", \
94 vx[index].x, vx[index].y, vx[index].z, vx[index].w, \
95 vx[index].nx, vx[index].ny, vx[index].nz, \
96 vx[index].u, vx[index].v); \
99 #define DO_LVERTEX(index) \
101 DWORD col = l_vx[index].c; \
103 glColor3f(((col >> 16) & 0xFF) / 255.0, \
104 ((col >> 8) & 0xFF) / 255.0, \
105 ((col >> 0) & 0xFF) / 255.0); \
106 glTexCoord2f(l_vx[index].u, \
107 l_vx[index].v); \
108 glVertex4f(l_vx[index].x, \
109 l_vx[index].y, \
110 l_vx[index].z, \
111 l_vx[index].w); \
113 TRACE(" LV: %f %f %f %f (%02lx %02lx %02lx) (%f %f)\n", \
114 l_vx[index].x, l_vx[index].y, l_vx[index].z, l_vx[index].w, \
115 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
116 l_vx[index].u, l_vx[index].v); \
119 #define DO_TLVERTEX(index) \
121 D3DTLVERTEX *vx = &(tl_vx[index]); \
122 DWORD col = vx->u5.color; \
124 glColor3f(((col >> 16) & 0xFF) / 255.0, \
125 ((col >> 8) & 0xFF) / 255.0, \
126 ((col >> 0) & 0xFF) / 255.0); \
127 glTexCoord2f(vx->u7.tu, vx->u8.tv); \
128 if (vx->u4.rhw < 0.01) \
129 glVertex3f(vx->u1.sx, \
130 vx->u2.sy, \
131 vx->u3.sz); \
132 else \
133 glVertex4f(vx->u1.sx / vx->u4.rhw, \
134 vx->u2.sy / vx->u4.rhw, \
135 vx->u3.sz / vx->u4.rhw, \
136 1.0 / vx->u4.rhw); \
137 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
138 vx->u1.sx, vx->u2.sy, vx->u3.sz, \
139 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
140 vx->u7.tu, vx->u8.tv, vx->u4.rhw); \
143 #define TRIANGLE_LOOP(macro) \
145 glBegin(GL_TRIANGLES); \
146 for (i = 0; i < count; i++) { \
147 LPD3DTRIANGLE ci = (LPD3DTRIANGLE) instr; \
149 TRACE(" v1: %d v2: %d v3: %d\n", \
150 ci->u1.v1, ci->u2.v2, ci->u3.v3); \
151 TRACE(" Flags : "); \
152 if (TRACE_ON(ddraw)) { \
153 /* Wireframe */ \
154 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) \
155 DPRINTF("EDGEENABLE1 "); \
156 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2) \
157 DPRINTF("EDGEENABLE2 "); \
158 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) \
159 DPRINTF("EDGEENABLE3 "); \
161 /* Strips / Fans */ \
162 if (ci->wFlags == D3DTRIFLAG_EVEN) \
163 DPRINTF("EVEN "); \
164 if (ci->wFlags == D3DTRIFLAG_ODD) \
165 DPRINTF("ODD "); \
166 if (ci->wFlags == D3DTRIFLAG_START) \
167 DPRINTF("START "); \
168 if ((ci->wFlags > 0) && (ci->wFlags < 30)) \
169 DPRINTF("STARTFLAT(%d) ", ci->wFlags); \
170 DPRINTF("\n"); \
173 /* Draw the triangle */ \
174 macro(ci->u1.v1); \
175 macro(ci->u2.v2); \
176 macro(ci->u3.v3); \
178 instr += size; \
180 glEnd(); \
184 static void execute(IDirect3DExecuteBufferImpl *This,
185 IDirect3DDeviceImpl *lpDevice,
186 IDirect3DViewportImpl *lpViewport)
188 IDirect3DDeviceGLImpl* lpDeviceGL = (IDirect3DDeviceGLImpl*) lpDevice;
189 /* DWORD bs = This->desc.dwBufferSize; */
190 DWORD vs = This->data.dwVertexOffset;
191 /* DWORD vc = This->data.dwVertexCount; */
192 DWORD is = This->data.dwInstructionOffset;
193 /* DWORD il = This->data.dwInstructionLength; */
195 void *instr = This->desc.lpData + is;
197 /* Should check if the viewport was added or not to the device */
199 /* Activate the viewport */
200 lpViewport->active_device = lpDevice;
201 lpViewport->activate(lpViewport);
203 TRACE("ExecuteData : \n");
204 if (TRACE_ON(ddraw))
205 _dump_executedata(&(This->data));
207 ENTER_GL();
209 while (1) {
210 LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
211 BYTE size;
212 WORD count;
214 count = current->wCount;
215 size = current->bSize;
216 instr += sizeof(D3DINSTRUCTION);
218 switch (current->bOpcode) {
219 case D3DOP_POINT: {
220 TRACE("POINT-s (%d)\n", count);
221 instr += count * size;
222 } break;
224 case D3DOP_LINE: {
225 TRACE("LINE-s (%d)\n", count);
226 instr += count * size;
227 } break;
229 case D3DOP_TRIANGLE: {
230 int i;
231 OGL_Vertex *vx = (OGL_Vertex *) This->vertex_data;
232 OGL_LVertex *l_vx = (OGL_LVertex *) This->vertex_data;
233 D3DTLVERTEX *tl_vx = (D3DTLVERTEX *) This->vertex_data;
234 TRACE("TRIANGLE (%d)\n", count);
236 switch (This->vertex_type) {
237 case D3DVT_VERTEX:
238 /* This time, there is lighting */
239 glEnable(GL_LIGHTING);
241 /* Use given matrixes */
242 glMatrixMode(GL_MODELVIEW);
243 glLoadIdentity(); /* The model transformation was done during the
244 transformation phase */
245 glMatrixMode(GL_PROJECTION);
246 TRACE(" Projection Matrix : (%p)\n", lpDeviceGL->proj_mat);
247 dump_mat(lpDeviceGL->proj_mat);
248 TRACE(" View Matrix : (%p)\n", lpDeviceGL->view_mat);
249 dump_mat(lpDeviceGL->view_mat);
251 /* Although z axis is inverted between OpenGL and Direct3D, the z projected coordinates
252 are always 0.0 at the front viewing volume and 1.0 at the back with Direct 3D and with
253 the default behaviour of OpenGL. So, no additional transformation is required. */
254 glLoadMatrixf((float *) lpDeviceGL->proj_mat);
255 glMultMatrixf((float *) lpDeviceGL->view_mat);
256 break;
258 case D3DVT_LVERTEX:
259 /* No lighting */
260 glDisable(GL_LIGHTING);
262 /* Use given matrixes */
263 glMatrixMode(GL_MODELVIEW);
264 glLoadIdentity(); /* The model transformation was done during the
265 transformation phase */
266 glMatrixMode(GL_PROJECTION);
268 TRACE(" Projection Matrix : (%p)\n", lpDeviceGL->proj_mat);
269 dump_mat(lpDeviceGL->proj_mat);
270 TRACE(" View Matrix : (%p)\n", lpDeviceGL->view_mat);
271 dump_mat(lpDeviceGL->view_mat);
273 /* Although z axis is inverted between OpenGL and Direct3D, the z projected coordinates
274 are always 0 at the front viewing volume and 1 at the back with Direct 3D and with
275 the default behaviour of OpenGL. So, no additional transformation is required. */
276 glLoadMatrixf((float *) lpDeviceGL->proj_mat);
277 glMultMatrixf((float *) lpDeviceGL->view_mat);
278 break;
280 case D3DVT_TLVERTEX: {
281 GLdouble height, width, minZ, maxZ;
283 /* First, disable lighting */
284 glDisable(GL_LIGHTING);
286 /* Then do not put any transformation matrixes */
287 glMatrixMode(GL_MODELVIEW);
288 glLoadIdentity();
289 glMatrixMode(GL_PROJECTION);
290 glLoadIdentity();
292 if (lpViewport == NULL) {
293 ERR("No current viewport !\n");
294 /* Using standard values */
295 height = 640.0;
296 width = 480.0;
297 minZ = -10.0;
298 maxZ = 10.0;
299 } else {
300 height = (GLdouble) lpViewport->viewports.vp1.dwHeight;
301 width = (GLdouble) lpViewport->viewports.vp1.dwWidth;
302 minZ = (GLdouble) lpViewport->viewports.vp1.dvMinZ;
303 maxZ = (GLdouble) lpViewport->viewports.vp1.dvMaxZ;
305 if (minZ == maxZ) {
306 /* I do not know why, but many Dx 3.0 games have minZ = maxZ = 0.0 */
307 minZ = 0.0;
308 maxZ = 1.0;
311 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
312 } break;
314 default:
315 ERR("Unhandled vertex type !\n");
316 break;
319 switch (This->vertex_type) {
320 case D3DVT_VERTEX:
321 TRIANGLE_LOOP(DO_VERTEX);
322 break;
324 case D3DVT_LVERTEX:
325 TRIANGLE_LOOP(DO_LVERTEX);
326 break;
328 case D3DVT_TLVERTEX:
329 TRIANGLE_LOOP(DO_TLVERTEX);
330 break;
332 default:
333 ERR("Unhandled vertex type !\n");
335 } break;
337 case D3DOP_MATRIXLOAD:
338 TRACE("MATRIXLOAD-s (%d)\n", count);
339 instr += count * size;
340 break;
342 case D3DOP_MATRIXMULTIPLY: {
343 int i;
344 TRACE("MATRIXMULTIPLY (%d)\n", count);
346 for (i = 0; i < count; i++) {
347 LPD3DMATRIXMULTIPLY ci = (LPD3DMATRIXMULTIPLY) instr;
348 LPD3DMATRIX a = (LPD3DMATRIX) ci->hDestMatrix;
349 LPD3DMATRIX b = (LPD3DMATRIX) ci->hSrcMatrix1;
350 LPD3DMATRIX c = (LPD3DMATRIX) ci->hSrcMatrix2;
352 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
353 ci->hDestMatrix, ci->hSrcMatrix1, ci->hSrcMatrix2);
355 /* Do the multiplication..
356 As I am VERY lazy, I let OpenGL do the multiplication for me */
357 glMatrixMode(GL_PROJECTION);
358 /* Save the current matrix */
359 glPushMatrix();
360 /* Load Matrix one and do the multiplication */
361 glLoadMatrixf((float *) c);
362 glMultMatrixf((float *) b);
363 glGetFloatv(GL_PROJECTION_MATRIX, (float *) a);
364 /* Restore the current matrix */
365 glPopMatrix();
367 instr += size;
369 } break;
371 case D3DOP_STATETRANSFORM: {
372 int i;
373 TRACE("STATETRANSFORM (%d)\n", count);
375 for (i = 0; i < count; i++) {
376 LPD3DSTATE ci = (LPD3DSTATE) instr;
378 /* Handle the state transform */
379 switch (ci->u1.dtstTransformStateType) {
380 case D3DTRANSFORMSTATE_WORLD: {
381 TRACE(" WORLD (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
382 lpDeviceGL->world_mat = (D3DMATRIX*) ci->u2.dwArg[0];
383 } break;
385 case D3DTRANSFORMSTATE_VIEW: {
386 TRACE(" VIEW (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
387 lpDeviceGL->view_mat = (D3DMATRIX*) ci->u2.dwArg[0];
388 } break;
390 case D3DTRANSFORMSTATE_PROJECTION: {
391 TRACE(" PROJECTION (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
392 lpDeviceGL->proj_mat = (D3DMATRIX*) ci->u2.dwArg[0];
393 } break;
395 default:
396 ERR(" Unhandled state transformation !! (%d)\n", (int) ci->u1.dtstTransformStateType);
397 break;
400 instr += size;
402 } break;
404 case D3DOP_STATELIGHT: {
405 int i;
406 TRACE("STATELIGHT (%d)\n", count);
408 for (i = 0; i < count; i++) {
409 LPD3DSTATE ci = (LPD3DSTATE) instr;
411 /* Handle the state transform */
412 switch (ci->u1.dlstLightStateType) {
413 case D3DLIGHTSTATE_MATERIAL: {
414 IDirect3DMaterialImpl* mat = (IDirect3DMaterialImpl*) ci->u2.dwArg[0];
415 TRACE(" MATERIAL\n");
417 if (mat != NULL) {
418 mat->activate(mat);
419 } else {
420 TRACE(" bad Material Handle\n");
422 } break ;
424 case D3DLIGHTSTATE_AMBIENT: {
425 float light[4];
426 DWORD dwLightState = ci->u2.dwArg[0];
427 TRACE(" AMBIENT\n");
429 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
430 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
431 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
432 light[3] = 1.0;
433 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
435 TRACE(" R:%02lx G:%02lx B:%02lx A:%02lx\n",
436 ((dwLightState >> 16) & 0xFF),
437 ((dwLightState >> 8) & 0xFF),
438 ((dwLightState >> 0) & 0xFF),
439 ((dwLightState >> 24) & 0xFF));
440 } break ;
442 case D3DLIGHTSTATE_COLORMODEL: {
443 TRACE(" COLORMODEL\n");
444 } break ;
446 case D3DLIGHTSTATE_FOGMODE: {
447 TRACE(" FOGMODE\n");
448 } break ;
450 case D3DLIGHTSTATE_FOGSTART: {
451 TRACE(" FOGSTART\n");
452 } break ;
454 case D3DLIGHTSTATE_FOGEND: {
455 TRACE(" FOGEND\n");
456 } break ;
458 case D3DLIGHTSTATE_FOGDENSITY: {
459 TRACE(" FOGDENSITY\n");
460 } break ;
462 default:
463 ERR(" Unhandled light state !! (%d)\n", (int) ci->u1.dlstLightStateType);
464 break;
466 instr += size;
468 } break;
470 case D3DOP_STATERENDER: {
471 int i;
472 TRACE("STATERENDER (%d)\n", count);
474 for (i = 0; i < count; i++) {
475 LPD3DSTATE ci = (LPD3DSTATE) instr;
477 /* Handle the state transform */
478 set_render_state(ci->u1.drstRenderStateType, ci->u2.dwArg[0], &(lpDeviceGL->render_state));
480 instr += size;
482 } break;
484 case D3DOP_PROCESSVERTICES: {
485 int i;
486 TRACE("PROCESSVERTICES (%d)\n", count);
488 for (i = 0; i < count; i++) {
489 LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
491 TRACE(" Start : %d Dest : %d Count : %ld\n",
492 ci->wStart, ci->wDest, ci->dwCount);
493 TRACE(" Flags : ");
494 if (TRACE_ON(ddraw)) {
495 if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
496 DPRINTF("COPY ");
497 if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
498 DPRINTF("NOCOLOR ");
499 if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
500 DPRINTF("OPMASK ");
501 if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
502 DPRINTF("TRANSFORM ");
503 if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
504 DPRINTF("TRANSFORMLIGHT ");
505 if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
506 DPRINTF("UPDATEEXTENTS ");
507 DPRINTF("\n");
510 /* This is where doing Direct3D on top on OpenGL is quite difficult.
511 This method transforms a set of vertices using the CURRENT state
512 (lighting, projection, ...) but does not rasterize them.
513 They will only be put on screen later (with the POINT / LINE and
514 TRIANGLE op-codes). The problem is that you can have a triangle
515 with each point having been transformed using another state...
517 In this implementation, I will emulate only ONE thing : each
518 vertex can have its own "WORLD" transformation (this is used in the
519 TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
520 execute buffer use the same state.
522 If I find applications that change other states, I will try to do a
523 more 'fine-tuned' state emulation (but I may become quite tricky if
524 it changes a light position in the middle of a triangle).
526 In this case, a 'direct' approach (i.e. without using OpenGL, but
527 writing our own 3D rasterizer) would be easier. */
529 /* The current method (with the hypothesis that only the WORLD matrix
530 will change between two points) is like this :
531 - I transform 'manually' all the vertices with the current WORLD
532 matrix and store them in the vertex buffer
533 - during the rasterization phase, the WORLD matrix will be set to
534 the Identity matrix */
536 /* Enough for the moment */
537 if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
538 int nb;
539 D3DVERTEX *src = ((LPD3DVERTEX) (This->desc.lpData + vs)) + ci->wStart;
540 OGL_Vertex *dst = ((OGL_Vertex *) (This->vertex_data)) + ci->wDest;
541 D3DMATRIX *mat = lpDeviceGL->world_mat;
543 TRACE(" World Matrix : (%p)\n", mat);
544 dump_mat(mat);
546 This->vertex_type = D3DVT_VERTEX;
548 for (nb = 0; nb < ci->dwCount; nb++) {
549 /* For the moment, no normal transformation... */
550 dst->nx = (src->u4.nx * mat->_11) + (src->u5.ny * mat->_21) + (src->u6.nz * mat->_31);
551 dst->ny = (src->u4.nx * mat->_12) + (src->u5.ny * mat->_22) + (src->u6.nz * mat->_32);
552 dst->nz = (src->u4.nx * mat->_13) + (src->u5.ny * mat->_23) + (src->u6.nz * mat->_33);
554 dst->u = src->u7.tu;
555 dst->v = src->u8.tv;
557 /* Now, the matrix multiplication */
558 dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
559 dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
560 dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
561 dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
563 src++;
564 dst++;
566 } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
567 int nb;
568 D3DLVERTEX *src = ((LPD3DLVERTEX) (This->desc.lpData + vs)) + ci->wStart;
569 OGL_LVertex *dst = ((OGL_LVertex *) (This->vertex_data)) + ci->wDest;
570 D3DMATRIX *mat = lpDeviceGL->world_mat;
572 TRACE(" World Matrix : (%p)\n", mat);
573 dump_mat(mat);
575 This->vertex_type = D3DVT_LVERTEX;
577 for (nb = 0; nb < ci->dwCount; nb++) {
578 dst->c = src->u4.color;
579 dst->sc = src->u5.specular;
580 dst->u = src->u6.tu;
581 dst->v = src->u7.tv;
583 /* Now, the matrix multiplication */
584 dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
585 dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
586 dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
587 dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
589 src++;
590 dst++;
592 } else if (ci->dwFlags == D3DPROCESSVERTICES_COPY) {
593 D3DTLVERTEX *src = ((LPD3DTLVERTEX) (This->desc.lpData + vs)) + ci->wStart;
594 D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
596 This->vertex_type = D3DVT_TLVERTEX;
598 memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
599 } else {
600 ERR("Unhandled vertex processing !\n");
603 instr += size;
605 } break;
607 case D3DOP_TEXTURELOAD: {
608 TRACE("TEXTURELOAD-s (%d)\n", count);
610 instr += count * size;
611 } break;
613 case D3DOP_EXIT: {
614 TRACE("EXIT (%d)\n", count);
615 /* We did this instruction */
616 instr += size;
617 /* Exit this loop */
618 goto end_of_buffer;
619 } break;
621 case D3DOP_BRANCHFORWARD: {
622 int i;
623 TRACE("BRANCHFORWARD (%d)\n", count);
625 for (i = 0; i < count; i++) {
626 LPD3DBRANCH ci = (LPD3DBRANCH) instr;
628 if ((This->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
629 if (!ci->bNegate) {
630 TRACE(" Should branch to %ld\n", ci->dwOffset);
632 } else {
633 if (ci->bNegate) {
634 TRACE(" Should branch to %ld\n", ci->dwOffset);
638 instr += size;
640 } break;
642 case D3DOP_SPAN: {
643 TRACE("SPAN-s (%d)\n", count);
645 instr += count * size;
646 } break;
648 case D3DOP_SETSTATUS: {
649 int i;
650 TRACE("SETSTATUS (%d)\n", count);
652 for (i = 0; i < count; i++) {
653 LPD3DSTATUS ci = (LPD3DSTATUS) instr;
655 This->data.dsStatus = *ci;
657 instr += size;
659 } break;
661 default:
662 ERR("Unhandled OpCode !!!\n");
663 /* Try to save ... */
664 instr += count * size;
665 break;
669 end_of_buffer:
670 LEAVE_GL();
673 HRESULT WINAPI
674 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface,
675 REFIID riid,
676 LPVOID* obp)
678 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
679 TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
681 *obp = NULL;
683 if ( IsEqualGUID( &IID_IUnknown, riid ) ) {
684 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This, IDirect3DExecuteBuffer));
685 *obp = iface;
686 TRACE(" Creating IUnknown interface at %p.\n", *obp);
687 return S_OK;
689 if ( IsEqualGUID( &IID_IDirect3DMaterial, riid ) ) {
690 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This, IDirect3DExecuteBuffer));
691 *obp = ICOM_INTERFACE(This, IDirect3DExecuteBuffer);
692 TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obp);
693 return S_OK;
695 FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
696 return OLE_E_ENUM_NOMORE;
699 ULONG WINAPI
700 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface)
702 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
703 FIXME("(%p/%p)->()incrementing from %lu.\n", This, iface, This->ref );
704 return ++(This->ref);
707 ULONG WINAPI
708 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface)
710 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
711 TRACE("(%p/%p)->()decrementing from %lu.\n", This, iface, This->ref);
712 if (!--(This->ref)) {
713 if ((This->desc.lpData != NULL) && This->need_free)
714 HeapFree(GetProcessHeap(),0,This->desc.lpData);
715 if (This->vertex_data != NULL)
716 HeapFree(GetProcessHeap(),0,This->vertex_data);
717 HeapFree(GetProcessHeap(),0,This);
718 return 0;
721 return This->ref;
724 HRESULT WINAPI
725 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface,
726 LPDIRECT3DDEVICE lpDirect3DDevice,
727 LPD3DEXECUTEBUFFERDESC lpDesc)
729 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
730 TRACE("(%p/%p)->(%p,%p) no-op....\n", This, iface, lpDirect3DDevice, lpDesc);
731 return DD_OK;
734 HRESULT WINAPI
735 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface,
736 LPD3DEXECUTEBUFFERDESC lpDesc)
738 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
739 DWORD dwSize;
740 TRACE("(%p/%p)->(%p): stub!\n", This, iface, lpDesc);
742 dwSize = lpDesc->dwSize;
743 memset(lpDesc, 0, dwSize);
744 memcpy(lpDesc, &This->desc, dwSize);
746 if (TRACE_ON(ddraw)) {
747 TRACE(" Returning description : \n");
748 _dump_D3DEXECUTEBUFFERDESC(lpDesc);
750 return DD_OK;
753 HRESULT WINAPI
754 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface)
756 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
757 TRACE("(%p/%p)->() no-op...\n", This, iface);
758 return DD_OK;
761 HRESULT WINAPI
762 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
763 LPD3DEXECUTEDATA lpData)
765 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
766 DWORD nbvert;
767 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
769 memcpy(&This->data, lpData, lpData->dwSize);
771 /* Get the number of vertices in the execute buffer */
772 nbvert = This->data.dwVertexCount;
774 /* Prepares the transformed vertex buffer */
775 if (This->vertex_data != NULL)
776 HeapFree(GetProcessHeap(), 0, This->vertex_data);
777 This->vertex_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbvert * sizeof(OGL_Vertex));
779 if (TRACE_ON(ddraw)) {
780 _dump_executedata(lpData);
783 return DD_OK;
786 HRESULT WINAPI
787 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
788 LPD3DEXECUTEDATA lpData)
790 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
791 DWORD dwSize;
792 TRACE("(%p/%p)->(%p): stub!\n", This, iface, lpData);
794 dwSize = lpData->dwSize;
795 memset(lpData, 0, dwSize);
796 memcpy(lpData, &This->data, dwSize);
798 if (TRACE_ON(ddraw)) {
799 TRACE("Returning data : \n");
800 _dump_executedata(lpData);
803 return DD_OK;
806 HRESULT WINAPI
807 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface,
808 LPDWORD lpdwOffset,
809 LPD3DVALIDATECALLBACK lpFunc,
810 LPVOID lpUserArg,
811 DWORD dwReserved)
813 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
814 FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This, iface, lpdwOffset, lpFunc, lpUserArg, dwReserved);
815 return DD_OK;
818 HRESULT WINAPI
819 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface,
820 DWORD dwDummy)
822 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
823 TRACE("(%p/%p)->(%08lx) no-op...\n", This, iface, dwDummy);
824 return DD_OK;
827 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
828 # define XCAST(fun) (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
829 #else
830 # define XCAST(fun) (void*)
831 #endif
833 ICOM_VTABLE(IDirect3DExecuteBuffer) VTABLE_IDirect3DExecuteBuffer =
835 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
836 XCAST(QueryInterface) Main_IDirect3DExecuteBufferImpl_1_QueryInterface,
837 XCAST(AddRef) Main_IDirect3DExecuteBufferImpl_1_AddRef,
838 XCAST(Release) Main_IDirect3DExecuteBufferImpl_1_Release,
839 XCAST(Initialize) Main_IDirect3DExecuteBufferImpl_1_Initialize,
840 XCAST(Lock) Main_IDirect3DExecuteBufferImpl_1_Lock,
841 XCAST(Unlock) Main_IDirect3DExecuteBufferImpl_1_Unlock,
842 XCAST(SetExecuteData) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData,
843 XCAST(GetExecuteData) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData,
844 XCAST(Validate) Main_IDirect3DExecuteBufferImpl_1_Validate,
845 XCAST(Optimize) Main_IDirect3DExecuteBufferImpl_1_Optimize,
848 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
849 #undef XCAST
850 #endif
853 HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirect3DImpl *d3d, IDirect3DDeviceImpl *d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc)
855 IDirect3DExecuteBufferImpl* object;
857 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
859 ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, VTABLE_IDirect3DExecuteBuffer);
861 object->ref = 1;
862 object->d3d = d3d;
863 object->d3ddev = d3ddev;
865 /* Initializes memory */
866 memcpy(&object->desc, lpDesc, lpDesc->dwSize);
868 /* No buffer given */
869 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
870 object->desc.lpData = NULL;
872 /* No buffer size given */
873 if ((lpDesc->dwFlags & D3DDEB_BUFSIZE) == 0)
874 object->desc.dwBufferSize = 0;
876 /* Create buffer if asked */
877 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0)) {
878 object->need_free = TRUE;
879 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
880 } else {
881 object->need_free = FALSE;
884 /* No vertices for the moment */
885 object->vertex_data = NULL;
887 object->desc.dwFlags |= D3DDEB_LPDATA;
889 object->execute = execute;
891 *obj = object;
893 TRACE(" creating implementation at %p.\n", *obj);
895 return DD_OK;