Define NONAMELESS{STRUCT,UNION} explicitly in the files that need them.
[wine.git] / dlls / ddraw / d3dexecutebuffer.c
blobfb1b8cc02a470ab41da55ebbe135bc504c61c26c
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 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winerror.h"
29 #include "objbase.h"
30 #include "ddraw.h"
31 #include "d3d.h"
32 #include "wine/debug.h"
34 #include "d3d_private.h"
35 #include "mesa_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39 /* Structure to store the 'semi transformed' vertices */
40 typedef struct {
41 D3DVALUE x;
42 D3DVALUE y;
43 D3DVALUE z;
44 D3DVALUE w;
46 D3DVALUE nx;
47 D3DVALUE ny;
48 D3DVALUE nz;
50 D3DVALUE u;
51 D3DVALUE v;
52 } OGL_Vertex;
54 typedef struct {
55 D3DVALUE x;
56 D3DVALUE y;
57 D3DVALUE z;
58 D3DVALUE w;
60 D3DCOLOR c;
61 D3DCOLOR sc;
63 D3DVALUE u;
64 D3DVALUE v;
65 } OGL_LVertex;
67 static void _dump_d3dstatus(LPD3DSTATUS lpStatus) {
71 static void _dump_executedata(LPD3DEXECUTEDATA lpData) {
72 DPRINTF("dwSize : %ld\n", lpData->dwSize);
73 DPRINTF("Vertex Offset : %ld Count : %ld\n", lpData->dwVertexOffset, lpData->dwVertexCount);
74 DPRINTF("Instruction Offset : %ld Length : %ld\n", lpData->dwInstructionOffset, lpData->dwInstructionLength);
75 DPRINTF("HVertex Offset : %ld\n", lpData->dwHVertexOffset);
76 _dump_d3dstatus(&(lpData->dsStatus));
79 static void _dump_D3DEXECUTEBUFFERDESC(LPD3DEXECUTEBUFFERDESC lpDesc) {
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 < 1e-8) \
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(IDirect3DExecuteBufferImpl *This,
187 IDirect3DDeviceImpl *lpDevice,
188 IDirect3DViewportImpl *lpViewport)
190 IDirect3DDeviceGLImpl* lpDeviceGL = (IDirect3DDeviceGLImpl*) lpDevice;
191 /* DWORD bs = This->desc.dwBufferSize; */
192 DWORD vs = This->data.dwVertexOffset;
193 /* DWORD vc = This->data.dwVertexCount; */
194 DWORD is = This->data.dwInstructionOffset;
195 /* DWORD il = This->data.dwInstructionLength; */
197 void *instr = This->desc.lpData + is;
199 /* Should check if the viewport was added or not to the device */
201 /* Activate the viewport */
202 lpViewport->active_device = lpDevice;
203 lpViewport->activate(lpViewport);
205 TRACE("ExecuteData : \n");
206 if (TRACE_ON(ddraw))
207 _dump_executedata(&(This->data));
209 ENTER_GL();
211 while (1) {
212 LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
213 BYTE size;
214 WORD count;
216 count = current->wCount;
217 size = current->bSize;
218 instr += sizeof(D3DINSTRUCTION);
220 switch (current->bOpcode) {
221 case D3DOP_POINT: {
222 WARN("POINT-s (%d)\n", count);
223 instr += count * size;
224 } break;
226 case D3DOP_LINE: {
227 WARN("LINE-s (%d)\n", count);
228 instr += count * size;
229 } break;
231 case D3DOP_TRIANGLE: {
232 int i;
233 OGL_Vertex *vx = (OGL_Vertex *) This->vertex_data;
234 OGL_LVertex *l_vx = (OGL_LVertex *) This->vertex_data;
235 D3DTLVERTEX *tl_vx = (D3DTLVERTEX *) This->vertex_data;
236 TRACE("TRIANGLE (%d)\n", count);
238 switch (This->vertex_type) {
239 case D3DVT_VERTEX:
240 /* This time, there is lighting */
241 glEnable(GL_LIGHTING);
243 if (TRACE_ON(ddraw)) {
244 TRACE(" Projection Matrix : (%p)\n", lpDevice->proj_mat);
245 dump_D3DMATRIX(lpDevice->proj_mat);
246 TRACE(" View Matrix : (%p)\n", lpDevice->view_mat);
247 dump_D3DMATRIX(lpDevice->view_mat);
250 /* Using the identity matrix as the world matrix as the world transformation was
251 already done. */
252 lpDevice->set_matrices(lpDevice, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
253 (D3DMATRIX *) id_mat, lpDevice->view_mat, lpDevice->proj_mat);
254 break;
256 case D3DVT_LVERTEX:
257 /* No lighting */
258 glDisable(GL_LIGHTING);
260 if (TRACE_ON(ddraw)) {
261 TRACE(" Projection Matrix : (%p)\n", lpDevice->proj_mat);
262 dump_D3DMATRIX(lpDevice->proj_mat);
263 TRACE(" View Matrix : (%p)\n", lpDevice->view_mat);
264 dump_D3DMATRIX(lpDevice->view_mat);
267 /* Using the identity matrix as the world matrix as the world transformation was
268 already done. */
269 lpDevice->set_matrices(lpDevice, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
270 (D3DMATRIX *) id_mat, lpDevice->view_mat, lpDevice->proj_mat);
271 break;
273 case D3DVT_TLVERTEX: {
274 /* First, disable lighting and fogging */
275 glDisable(GL_LIGHTING);
276 glDisable(GL_FOG);
278 d3ddevice_set_ortho(lpDevice);
279 } break;
281 default:
282 ERR("Unhandled vertex type !\n");
283 break;
286 switch (This->vertex_type) {
287 case D3DVT_VERTEX:
288 TRIANGLE_LOOP(DO_VERTEX);
289 break;
291 case D3DVT_LVERTEX:
292 TRIANGLE_LOOP(DO_LVERTEX);
293 break;
295 case D3DVT_TLVERTEX:
296 TRIANGLE_LOOP(DO_TLVERTEX);
297 break;
299 default:
300 ERR("Unhandled vertex type !\n");
302 } break;
304 case D3DOP_MATRIXLOAD:
305 WARN("MATRIXLOAD-s (%d)\n", count);
306 instr += count * size;
307 break;
309 case D3DOP_MATRIXMULTIPLY: {
310 int i;
311 TRACE("MATRIXMULTIPLY (%d)\n", count);
313 for (i = 0; i < count; i++) {
314 LPD3DMATRIXMULTIPLY ci = (LPD3DMATRIXMULTIPLY) instr;
315 LPD3DMATRIX a = (LPD3DMATRIX) ci->hDestMatrix;
316 LPD3DMATRIX b = (LPD3DMATRIX) ci->hSrcMatrix1;
317 LPD3DMATRIX c = (LPD3DMATRIX) ci->hSrcMatrix2;
319 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
320 ci->hDestMatrix, ci->hSrcMatrix1, ci->hSrcMatrix2);
322 /* Do the multiplication..
323 As I am VERY lazy, I let OpenGL do the multiplication for me */
324 glMatrixMode(GL_PROJECTION);
325 /* Save the current matrix */
326 glPushMatrix();
327 /* Load Matrix one and do the multiplication */
328 glLoadMatrixf((float *) c);
329 glMultMatrixf((float *) b);
330 glGetFloatv(GL_PROJECTION_MATRIX, (float *) a);
331 /* Restore the current matrix */
332 glPopMatrix();
334 instr += size;
336 } break;
338 case D3DOP_STATETRANSFORM: {
339 int i;
340 TRACE("STATETRANSFORM (%d)\n", count);
342 for (i = 0; i < count; i++) {
343 LPD3DSTATE ci = (LPD3DSTATE) instr;
345 /* Handle the state transform */
346 switch (ci->u1.dtstTransformStateType) {
347 case D3DTRANSFORMSTATE_WORLD: {
348 TRACE(" WORLD (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
349 lpDevice->world_mat = (D3DMATRIX*) ci->u2.dwArg[0];
350 } break;
352 case D3DTRANSFORMSTATE_VIEW: {
353 TRACE(" VIEW (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
354 lpDevice->view_mat = (D3DMATRIX*) ci->u2.dwArg[0];
355 } break;
357 case D3DTRANSFORMSTATE_PROJECTION: {
358 TRACE(" PROJECTION (%p)\n", (D3DMATRIX*) ci->u2.dwArg[0]);
359 lpDevice->proj_mat = (D3DMATRIX*) ci->u2.dwArg[0];
360 } break;
362 default:
363 ERR(" Unhandled state transformation !! (%d)\n", (int) ci->u1.dtstTransformStateType);
364 break;
367 instr += size;
369 } break;
371 case D3DOP_STATELIGHT: {
372 int i;
373 TRACE("STATELIGHT (%d)\n", count);
375 for (i = 0; i < count; i++) {
376 LPD3DSTATE ci = (LPD3DSTATE) instr;
378 /* Handle the state transform */
379 switch (ci->u1.dlstLightStateType) {
380 case D3DLIGHTSTATE_MATERIAL: {
381 IDirect3DMaterialImpl* mat = (IDirect3DMaterialImpl*) ci->u2.dwArg[0];
382 TRACE(" MATERIAL\n");
384 if (mat != NULL) {
385 mat->activate(mat);
386 } else {
387 TRACE(" bad Material Handle\n");
389 } break ;
391 case D3DLIGHTSTATE_AMBIENT: {
392 float light[4];
393 DWORD dwLightState = ci->u2.dwArg[0];
394 TRACE(" AMBIENT\n");
396 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
397 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
398 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
399 light[3] = 1.0;
400 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
402 TRACE(" R:%02lx G:%02lx B:%02lx A:%02lx\n",
403 ((dwLightState >> 16) & 0xFF),
404 ((dwLightState >> 8) & 0xFF),
405 ((dwLightState >> 0) & 0xFF),
406 ((dwLightState >> 24) & 0xFF));
407 } break ;
409 case D3DLIGHTSTATE_COLORMODEL: {
410 WARN(" COLORMODEL\n");
411 } break ;
413 case D3DLIGHTSTATE_FOGMODE: {
414 WARN(" FOGMODE\n");
415 } break ;
417 case D3DLIGHTSTATE_FOGSTART: {
418 WARN(" FOGSTART\n");
419 } break ;
421 case D3DLIGHTSTATE_FOGEND: {
422 WARN(" FOGEND\n");
423 } break ;
425 case D3DLIGHTSTATE_FOGDENSITY: {
426 WARN(" FOGDENSITY\n");
427 } break ;
429 default:
430 ERR(" Unhandled light state !! (%d)\n", (int) ci->u1.dlstLightStateType);
431 break;
433 instr += size;
435 } break;
437 case D3DOP_STATERENDER: {
438 int i;
439 TRACE("STATERENDER (%d)\n", count);
441 for (i = 0; i < count; i++) {
442 LPD3DSTATE ci = (LPD3DSTATE) instr;
444 /* Handle the state transform */
445 set_render_state(lpDeviceGL, ci->u1.drstRenderStateType, ci->u2.dwArg[0]);
447 instr += size;
449 } break;
451 case D3DOP_PROCESSVERTICES: {
452 int i;
453 TRACE("PROCESSVERTICES (%d)\n", count);
455 for (i = 0; i < count; i++) {
456 LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
458 TRACE(" Start : %d Dest : %d Count : %ld\n",
459 ci->wStart, ci->wDest, ci->dwCount);
460 TRACE(" Flags : ");
461 if (TRACE_ON(ddraw)) {
462 if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
463 DPRINTF("COPY ");
464 if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
465 DPRINTF("NOCOLOR ");
466 if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
467 DPRINTF("OPMASK ");
468 if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
469 DPRINTF("TRANSFORM ");
470 if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
471 DPRINTF("TRANSFORMLIGHT ");
472 if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
473 DPRINTF("UPDATEEXTENTS ");
474 DPRINTF("\n");
477 /* This is where doing Direct3D on top on OpenGL is quite difficult.
478 This method transforms a set of vertices using the CURRENT state
479 (lighting, projection, ...) but does not rasterize them.
480 They will only be put on screen later (with the POINT / LINE and
481 TRIANGLE op-codes). The problem is that you can have a triangle
482 with each point having been transformed using another state...
484 In this implementation, I will emulate only ONE thing : each
485 vertex can have its own "WORLD" transformation (this is used in the
486 TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
487 execute buffer use the same state.
489 If I find applications that change other states, I will try to do a
490 more 'fine-tuned' state emulation (but I may become quite tricky if
491 it changes a light position in the middle of a triangle).
493 In this case, a 'direct' approach (i.e. without using OpenGL, but
494 writing our own 3D rasterizer) would be easier. */
496 /* The current method (with the hypothesis that only the WORLD matrix
497 will change between two points) is like this :
498 - I transform 'manually' all the vertices with the current WORLD
499 matrix and store them in the vertex buffer
500 - during the rasterization phase, the WORLD matrix will be set to
501 the Identity matrix */
503 /* Enough for the moment */
504 if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
505 int nb;
506 D3DVERTEX *src = ((LPD3DVERTEX) (This->desc.lpData + vs)) + ci->wStart;
507 OGL_Vertex *dst = ((OGL_Vertex *) (This->vertex_data)) + ci->wDest;
508 D3DMATRIX *mat = lpDevice->world_mat;
510 TRACE(" World Matrix : (%p)\n", mat);
511 dump_D3DMATRIX(mat);
513 This->vertex_type = D3DVT_VERTEX;
515 for (nb = 0; nb < ci->dwCount; nb++) {
516 /* For the moment, no normal transformation... */
517 dst->nx = (src->u4.nx * mat->_11) + (src->u5.ny * mat->_21) + (src->u6.nz * mat->_31);
518 dst->ny = (src->u4.nx * mat->_12) + (src->u5.ny * mat->_22) + (src->u6.nz * mat->_32);
519 dst->nz = (src->u4.nx * mat->_13) + (src->u5.ny * mat->_23) + (src->u6.nz * mat->_33);
521 dst->u = src->u7.tu;
522 dst->v = src->u8.tv;
524 /* Now, the matrix multiplication */
525 dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
526 dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
527 dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
528 dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
530 src++;
531 dst++;
533 } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
534 int nb;
535 D3DLVERTEX *src = ((LPD3DLVERTEX) (This->desc.lpData + vs)) + ci->wStart;
536 OGL_LVertex *dst = ((OGL_LVertex *) (This->vertex_data)) + ci->wDest;
537 D3DMATRIX *mat = lpDevice->world_mat;
539 TRACE(" World Matrix : (%p)\n", mat);
540 dump_D3DMATRIX(mat);
542 This->vertex_type = D3DVT_LVERTEX;
544 for (nb = 0; nb < ci->dwCount; nb++) {
545 dst->c = src->u4.color;
546 dst->sc = src->u5.specular;
547 dst->u = src->u6.tu;
548 dst->v = src->u7.tv;
550 /* Now, the matrix multiplication */
551 dst->x = (src->u1.x * mat->_11) + (src->u2.y * mat->_21) + (src->u3.z * mat->_31) + (1.0 * mat->_41);
552 dst->y = (src->u1.x * mat->_12) + (src->u2.y * mat->_22) + (src->u3.z * mat->_32) + (1.0 * mat->_42);
553 dst->z = (src->u1.x * mat->_13) + (src->u2.y * mat->_23) + (src->u3.z * mat->_33) + (1.0 * mat->_43);
554 dst->w = (src->u1.x * mat->_14) + (src->u2.y * mat->_24) + (src->u3.z * mat->_34) + (1.0 * mat->_44);
556 src++;
557 dst++;
559 } else if (ci->dwFlags == D3DPROCESSVERTICES_COPY) {
560 D3DTLVERTEX *src = ((LPD3DTLVERTEX) (This->desc.lpData + vs)) + ci->wStart;
561 D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
563 This->vertex_type = D3DVT_TLVERTEX;
565 memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
566 } else {
567 ERR("Unhandled vertex processing !\n");
570 instr += size;
572 } break;
574 case D3DOP_TEXTURELOAD: {
575 WARN("TEXTURELOAD-s (%d)\n", count);
577 instr += count * size;
578 } break;
580 case D3DOP_EXIT: {
581 TRACE("EXIT (%d)\n", count);
582 /* We did this instruction */
583 instr += size;
584 /* Exit this loop */
585 goto end_of_buffer;
586 } break;
588 case D3DOP_BRANCHFORWARD: {
589 int i;
590 TRACE("BRANCHFORWARD (%d)\n", count);
592 for (i = 0; i < count; i++) {
593 LPD3DBRANCH ci = (LPD3DBRANCH) instr;
595 if ((This->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
596 if (!ci->bNegate) {
597 TRACE(" Should branch to %ld\n", ci->dwOffset);
599 } else {
600 if (ci->bNegate) {
601 TRACE(" Should branch to %ld\n", ci->dwOffset);
605 instr += size;
607 } break;
609 case D3DOP_SPAN: {
610 WARN("SPAN-s (%d)\n", count);
612 instr += count * size;
613 } break;
615 case D3DOP_SETSTATUS: {
616 int i;
617 TRACE("SETSTATUS (%d)\n", count);
619 for (i = 0; i < count; i++) {
620 LPD3DSTATUS ci = (LPD3DSTATUS) instr;
622 This->data.dsStatus = *ci;
624 instr += size;
626 } break;
628 default:
629 ERR("Unhandled OpCode !!!\n");
630 /* Try to save ... */
631 instr += count * size;
632 break;
636 end_of_buffer:
637 LEAVE_GL();
640 HRESULT WINAPI
641 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface,
642 REFIID riid,
643 LPVOID* obp)
645 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
646 TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
648 *obp = NULL;
650 if ( IsEqualGUID( &IID_IUnknown, riid ) ) {
651 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This, IDirect3DExecuteBuffer));
652 *obp = iface;
653 TRACE(" Creating IUnknown interface at %p.\n", *obp);
654 return S_OK;
656 if ( IsEqualGUID( &IID_IDirect3DMaterial, riid ) ) {
657 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This, IDirect3DExecuteBuffer));
658 *obp = ICOM_INTERFACE(This, IDirect3DExecuteBuffer);
659 TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obp);
660 return S_OK;
662 FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
663 return OLE_E_ENUM_NOMORE;
666 ULONG WINAPI
667 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface)
669 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
670 FIXME("(%p/%p)->()incrementing from %lu.\n", This, iface, This->ref );
671 return ++(This->ref);
674 ULONG WINAPI
675 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface)
677 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
678 TRACE("(%p/%p)->()decrementing from %lu.\n", This, iface, This->ref);
679 if (!--(This->ref)) {
680 if ((This->desc.lpData != NULL) && This->need_free)
681 HeapFree(GetProcessHeap(),0,This->desc.lpData);
682 if (This->vertex_data != NULL)
683 HeapFree(GetProcessHeap(),0,This->vertex_data);
684 HeapFree(GetProcessHeap(),0,This);
685 return 0;
688 return This->ref;
691 HRESULT WINAPI
692 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface,
693 LPDIRECT3DDEVICE lpDirect3DDevice,
694 LPD3DEXECUTEBUFFERDESC lpDesc)
696 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
697 TRACE("(%p/%p)->(%p,%p) no-op....\n", This, iface, lpDirect3DDevice, lpDesc);
698 return DD_OK;
701 HRESULT WINAPI
702 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface,
703 LPD3DEXECUTEBUFFERDESC lpDesc)
705 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
706 DWORD dwSize;
707 TRACE("(%p/%p)->(%p)\n", This, iface, lpDesc);
709 dwSize = lpDesc->dwSize;
710 memset(lpDesc, 0, dwSize);
711 memcpy(lpDesc, &This->desc, dwSize);
713 if (TRACE_ON(ddraw)) {
714 TRACE(" Returning description : \n");
715 _dump_D3DEXECUTEBUFFERDESC(lpDesc);
717 return DD_OK;
720 HRESULT WINAPI
721 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface)
723 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
724 TRACE("(%p/%p)->() no-op...\n", This, iface);
725 return DD_OK;
728 HRESULT WINAPI
729 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
730 LPD3DEXECUTEDATA lpData)
732 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
733 DWORD nbvert;
734 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
736 memcpy(&This->data, lpData, lpData->dwSize);
738 /* Get the number of vertices in the execute buffer */
739 nbvert = This->data.dwVertexCount;
741 /* Prepares the transformed vertex buffer */
742 if (This->vertex_data != NULL)
743 HeapFree(GetProcessHeap(), 0, This->vertex_data);
744 This->vertex_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbvert * sizeof(OGL_Vertex));
746 if (TRACE_ON(ddraw)) {
747 _dump_executedata(lpData);
750 return DD_OK;
753 HRESULT WINAPI
754 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface,
755 LPD3DEXECUTEDATA lpData)
757 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
758 DWORD dwSize;
759 TRACE("(%p/%p)->(%p): stub!\n", This, iface, lpData);
761 dwSize = lpData->dwSize;
762 memset(lpData, 0, dwSize);
763 memcpy(lpData, &This->data, dwSize);
765 if (TRACE_ON(ddraw)) {
766 TRACE("Returning data : \n");
767 _dump_executedata(lpData);
770 return DD_OK;
773 HRESULT WINAPI
774 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface,
775 LPDWORD lpdwOffset,
776 LPD3DVALIDATECALLBACK lpFunc,
777 LPVOID lpUserArg,
778 DWORD dwReserved)
780 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
781 FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This, iface, lpdwOffset, lpFunc, lpUserArg, dwReserved);
782 return DD_OK;
785 HRESULT WINAPI
786 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface,
787 DWORD dwDummy)
789 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer, iface);
790 TRACE("(%p/%p)->(%08lx) no-op...\n", This, iface, dwDummy);
791 return DD_OK;
794 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
795 # define XCAST(fun) (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
796 #else
797 # define XCAST(fun) (void*)
798 #endif
800 ICOM_VTABLE(IDirect3DExecuteBuffer) VTABLE_IDirect3DExecuteBuffer =
802 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
803 XCAST(QueryInterface) Main_IDirect3DExecuteBufferImpl_1_QueryInterface,
804 XCAST(AddRef) Main_IDirect3DExecuteBufferImpl_1_AddRef,
805 XCAST(Release) Main_IDirect3DExecuteBufferImpl_1_Release,
806 XCAST(Initialize) Main_IDirect3DExecuteBufferImpl_1_Initialize,
807 XCAST(Lock) Main_IDirect3DExecuteBufferImpl_1_Lock,
808 XCAST(Unlock) Main_IDirect3DExecuteBufferImpl_1_Unlock,
809 XCAST(SetExecuteData) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData,
810 XCAST(GetExecuteData) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData,
811 XCAST(Validate) Main_IDirect3DExecuteBufferImpl_1_Validate,
812 XCAST(Optimize) Main_IDirect3DExecuteBufferImpl_1_Optimize,
815 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
816 #undef XCAST
817 #endif
820 HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirect3DImpl *d3d, IDirect3DDeviceImpl *d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc)
822 IDirect3DExecuteBufferImpl* object;
824 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
826 ICOM_INIT_INTERFACE(object, IDirect3DExecuteBuffer, VTABLE_IDirect3DExecuteBuffer);
828 object->ref = 1;
829 object->d3d = d3d;
830 object->d3ddev = d3ddev;
832 /* Initializes memory */
833 memcpy(&object->desc, lpDesc, lpDesc->dwSize);
835 /* No buffer given */
836 if ((object->desc.dwFlags & D3DDEB_LPDATA) == 0)
837 object->desc.lpData = NULL;
839 /* No buffer size given */
840 if ((lpDesc->dwFlags & D3DDEB_BUFSIZE) == 0)
841 object->desc.dwBufferSize = 0;
843 /* Create buffer if asked */
844 if ((object->desc.lpData == NULL) && (object->desc.dwBufferSize > 0)) {
845 object->need_free = TRUE;
846 object->desc.lpData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,object->desc.dwBufferSize);
847 } else {
848 object->need_free = FALSE;
851 /* No vertices for the moment */
852 object->vertex_data = NULL;
854 object->desc.dwFlags |= D3DDEB_LPDATA;
856 object->execute = execute;
858 *obj = object;
860 TRACE(" creating implementation at %p.\n", *obj);
862 return DD_OK;