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
27 #include "wine/obj_base.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 */
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) \
85 glTexCoord2f(vx[index].u, \
87 glNormal3f(vx[index].nx, \
90 glVertex4f(vx[index].x, \
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, \
110 glVertex4f(l_vx[index].x, \
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, \
135 glVertex4f(vx->u1.sx / vx->u4.rhw, \
136 vx->u2.sy / vx->u4.rhw, \
137 vx->u3.sz / 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)) { \
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) \
166 if (ci->wFlags == D3DTRIFLAG_ODD) \
168 if (ci->wFlags == D3DTRIFLAG_START) \
170 if ((ci->wFlags > 0) && (ci->wFlags < 30)) \
171 DPRINTF("STARTFLAT(%d) ", ci->wFlags); \
175 /* Draw the triangle */ \
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
;
206 TRACE("ExecuteData : \n");
208 _dump_executedata(&(ilpBuff
->data
));
213 LPD3DINSTRUCTION current
= (LPD3DINSTRUCTION
) instr
;
217 count
= current
->wCount
;
218 size
= current
->bSize
;
219 instr
+= sizeof(D3DINSTRUCTION
);
221 switch (current
->bOpcode
) {
223 TRACE("POINT-s (%d)\n", count
);
225 instr
+= count
* size
;
229 TRACE("LINE-s (%d)\n", count
);
231 instr
+= count
* size
;
234 case D3DOP_TRIANGLE
: {
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
) {
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
);
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
);
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
);
296 glMatrixMode(GL_PROJECTION
);
300 ERR("No current viewport !\n");
301 /* Using standard values */
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
;
313 /* I do not know why, but many Dx 3.0 games have minZ = maxZ = 0.0 */
319 glOrtho(0.0, width
, height
, 0.0, -minZ
, -maxZ
);
323 ERR("Unhandled vertex type !\n");
327 switch (ilpBuff
->vertex_type
) {
329 TRIANGLE_LOOP(DO_VERTEX
);
333 TRIANGLE_LOOP(DO_LVERTEX
);
337 TRIANGLE_LOOP(DO_TLVERTEX
);
341 ERR("Unhandled vertex type !\n");
346 case D3DOP_MATRIXLOAD
: {
347 TRACE("MATRIXLOAD-s (%d)\n", count
);
349 instr
+= count
* size
;
352 case D3DOP_MATRIXMULTIPLY
: {
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 */
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 */
381 case D3DOP_STATETRANSFORM
: {
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];
395 case D3DTRANSFORMSTATE_VIEW
: {
396 TRACE(" VIEW (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
397 odev
->view_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
400 case D3DTRANSFORMSTATE_PROJECTION
: {
401 TRACE(" PROJECTION (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
402 odev
->proj_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
406 ERR(" Unhandled state transformation !! (%d)\n", (int) ci
->u1
.dtstTransformStateType
);
415 case D3DOP_STATELIGHT
: {
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");
431 TRACE(" bad Material Handle\n");
435 case D3DLIGHTSTATE_AMBIENT
: {
437 DWORD dwLightState
= ci
->u2
.dwArg
[0];
440 light
[0] = ((dwLightState
>> 16) & 0xFF) / 255.0;
441 light
[1] = ((dwLightState
>> 8) & 0xFF) / 255.0;
442 light
[2] = ((dwLightState
>> 0) & 0xFF) / 255.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));
453 case D3DLIGHTSTATE_COLORMODEL
: {
454 TRACE(" COLORMODEL\n");
457 case D3DLIGHTSTATE_FOGMODE
: {
461 case D3DLIGHTSTATE_FOGSTART
: {
462 TRACE(" FOGSTART\n");
465 case D3DLIGHTSTATE_FOGEND
: {
469 case D3DLIGHTSTATE_FOGDENSITY
: {
470 TRACE(" FOGDENSITY\n");
474 ERR(" Unhandled light state !! (%d)\n", (int) ci
->u1
.dlstLightStateType
);
481 case D3DOP_STATERENDER
: {
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
));
495 case D3DOP_PROCESSVERTICES
: {
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
);
505 if (TRACE_ON(ddraw
)) {
506 if (ci
->dwFlags
& D3DPROCESSVERTICES_COPY
)
508 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
510 if (ci
->dwFlags
== D3DPROCESSVERTICES_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 ");
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
) {
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
);
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
);
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
);
577 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORM
) {
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
);
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
;
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
);
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
));
611 ERR("Unhandled vertex processing !\n");
618 case D3DOP_TEXTURELOAD
: {
619 TRACE("TEXTURELOAD-s (%d)\n", count
);
621 instr
+= count
* size
;
625 TRACE("EXIT (%d)\n", count
);
626 /* We did this instruction */
632 case D3DOP_BRANCHFORWARD
: {
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
) {
641 TRACE(" Should branch to %ld\n", ci
->dwOffset
);
645 TRACE(" Should branch to %ld\n", ci
->dwOffset
);
654 TRACE("SPAN-s (%d)\n", count
);
656 instr
+= count
* size
;
659 case D3DOP_SETSTATUS
: {
661 TRACE("SETSTATUS (%d)\n", count
);
663 for (i
= 0; i
< count
; i
++) {
664 LPD3DSTATUS ci
= (LPD3DSTATUS
) instr
;
666 ilpBuff
->data
.dsStatus
= *ci
;
673 ERR("Unhandled OpCode !!!\n");
674 /* Try to save ... */
675 instr
+= count
* size
;
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
));
693 ICOM_VTBL(eb
) = &executebuffer_vtable
;
696 /* Initializes memory */
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
);
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
,
733 ICOM_THIS(IDirect3DExecuteBufferImpl
,iface
);
735 FIXME("(%p)->(%s,%p): stub\n", This
, debugstr_guid(riid
),ppvObj
);
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
);
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
);
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
;
793 static HRESULT WINAPI
IDirect3DExecuteBufferImpl_Unlock(LPDIRECT3DEXECUTEBUFFER iface
)
795 ICOM_THIS(IDirect3DExecuteBufferImpl
,iface
);
796 TRACE("(%p)->()\n", This
);
801 static HRESULT WINAPI
IDirect3DExecuteBufferImpl_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
802 LPD3DEXECUTEDATA lpData
)
804 ICOM_THIS(IDirect3DExecuteBufferImpl
,iface
);
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
);
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
;
838 static HRESULT WINAPI
IDirect3DExecuteBufferImpl_Validate(LPDIRECT3DEXECUTEBUFFER iface
,
840 LPD3DVALIDATECALLBACK lpFunc
,
844 ICOM_THIS(IDirect3DExecuteBufferImpl
,iface
);
845 TRACE("(%p)->(%p,%p,%p,%lu)\n", This
, lpdwOffset
, lpFunc
, lpUserArg
, dwReserved
);
850 static HRESULT WINAPI
IDirect3DExecuteBufferImpl_Optimize(LPDIRECT3DEXECUTEBUFFER iface
,
853 ICOM_THIS(IDirect3DExecuteBufferImpl
,iface
);
854 TRACE("(%p)->(%lu)\n", This
, dwReserved
);
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