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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
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 */
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) \
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 < 1e-8) \
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 TRACE("EDGEENABLE1 "); \
158 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2) \
159 TRACE("EDGEENABLE2 "); \
160 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) \
161 TRACE("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 TRACE("STARTFLAT(%d) ", ci->wFlags); \
175 /* Draw the triangle */ \
186 static void execute(IDirect3DExecuteBufferImpl
*This
,
187 IDirect3DDeviceImpl
*lpDevice
,
188 IDirect3DViewportImpl
*lpViewport
)
190 /* DWORD bs = This->desc.dwBufferSize; */
191 DWORD vs
= This
->data
.dwVertexOffset
;
192 /* DWORD vc = This->data.dwVertexCount; */
193 DWORD is
= This
->data
.dwInstructionOffset
;
194 /* DWORD il = This->data.dwInstructionLength; */
196 char *instr
= (char *)This
->desc
.lpData
+ is
;
198 /* Should check if the viewport was added or not to the device */
200 /* Activate the viewport */
201 lpViewport
->active_device
= lpDevice
;
202 lpViewport
->activate(lpViewport
);
204 TRACE("ExecuteData : \n");
206 _dump_executedata(&(This
->data
));
211 LPD3DINSTRUCTION current
= (LPD3DINSTRUCTION
) instr
;
215 count
= current
->wCount
;
216 size
= current
->bSize
;
217 instr
+= sizeof(D3DINSTRUCTION
);
219 switch (current
->bOpcode
) {
221 WARN("POINT-s (%d)\n", count
);
222 instr
+= count
* size
;
226 WARN("LINE-s (%d)\n", count
);
227 instr
+= count
* size
;
230 case D3DOP_TRIANGLE
: {
232 OGL_Vertex
*vx
= (OGL_Vertex
*) This
->vertex_data
;
233 OGL_LVertex
*l_vx
= (OGL_LVertex
*) This
->vertex_data
;
234 D3DTLVERTEX
*tl_vx
= (D3DTLVERTEX
*) This
->vertex_data
;
235 TRACE("TRIANGLE (%d)\n", count
);
237 switch (This
->vertex_type
) {
239 /* This time, there is lighting */
240 glEnable(GL_LIGHTING
);
242 if (TRACE_ON(ddraw
)) {
243 TRACE(" Projection Matrix : (%p)\n", lpDevice
->proj_mat
);
244 dump_D3DMATRIX(lpDevice
->proj_mat
);
245 TRACE(" View Matrix : (%p)\n", lpDevice
->view_mat
);
246 dump_D3DMATRIX(lpDevice
->view_mat
);
249 /* Using the identity matrix as the world matrix as the world transformation was
251 lpDevice
->set_matrices(lpDevice
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
252 (D3DMATRIX
*) id_mat
, lpDevice
->view_mat
, lpDevice
->proj_mat
);
257 glDisable(GL_LIGHTING
);
259 if (TRACE_ON(ddraw
)) {
260 TRACE(" Projection Matrix : (%p)\n", lpDevice
->proj_mat
);
261 dump_D3DMATRIX(lpDevice
->proj_mat
);
262 TRACE(" View Matrix : (%p)\n", lpDevice
->view_mat
);
263 dump_D3DMATRIX(lpDevice
->view_mat
);
266 /* Using the identity matrix as the world matrix as the world transformation was
268 lpDevice
->set_matrices(lpDevice
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
269 (D3DMATRIX
*) id_mat
, lpDevice
->view_mat
, lpDevice
->proj_mat
);
272 case D3DVT_TLVERTEX
: {
273 /* First, disable lighting and fogging */
274 glDisable(GL_LIGHTING
);
277 d3ddevice_set_ortho(lpDevice
);
281 ERR("Unhandled vertex type !\n");
285 switch (This
->vertex_type
) {
287 TRIANGLE_LOOP(DO_VERTEX
);
291 TRIANGLE_LOOP(DO_LVERTEX
);
295 TRIANGLE_LOOP(DO_TLVERTEX
);
299 ERR("Unhandled vertex type !\n");
303 case D3DOP_MATRIXLOAD
:
304 WARN("MATRIXLOAD-s (%d)\n", count
);
305 instr
+= count
* size
;
308 case D3DOP_MATRIXMULTIPLY
: {
310 TRACE("MATRIXMULTIPLY (%d)\n", count
);
312 for (i
= 0; i
< count
; i
++) {
313 LPD3DMATRIXMULTIPLY ci
= (LPD3DMATRIXMULTIPLY
) instr
;
314 LPD3DMATRIX a
= (LPD3DMATRIX
) ci
->hDestMatrix
;
315 LPD3DMATRIX b
= (LPD3DMATRIX
) ci
->hSrcMatrix1
;
316 LPD3DMATRIX c
= (LPD3DMATRIX
) ci
->hSrcMatrix2
;
318 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
319 ci
->hDestMatrix
, ci
->hSrcMatrix1
, ci
->hSrcMatrix2
);
321 /* Do the multiplication..
322 As I am VERY lazy, I let OpenGL do the multiplication for me */
323 glMatrixMode(GL_PROJECTION
);
324 /* Save the current matrix */
326 /* Load Matrix one and do the multiplication */
327 glLoadMatrixf((float *) c
);
328 glMultMatrixf((float *) b
);
329 glGetFloatv(GL_PROJECTION_MATRIX
, (float *) a
);
330 /* Restore the current matrix */
337 case D3DOP_STATETRANSFORM
: {
339 TRACE("STATETRANSFORM (%d)\n", count
);
341 for (i
= 0; i
< count
; i
++) {
342 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
344 /* Handle the state transform */
345 switch (ci
->u1
.dtstTransformStateType
) {
346 case D3DTRANSFORMSTATE_WORLD
: {
347 TRACE(" WORLD (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
348 lpDevice
->world_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
351 case D3DTRANSFORMSTATE_VIEW
: {
352 TRACE(" VIEW (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
353 lpDevice
->view_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
356 case D3DTRANSFORMSTATE_PROJECTION
: {
357 TRACE(" PROJECTION (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
358 lpDevice
->proj_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
362 ERR(" Unhandled state transformation !! (%d)\n", (int) ci
->u1
.dtstTransformStateType
);
370 case D3DOP_STATELIGHT
: {
372 TRACE("STATELIGHT (%d)\n", count
);
374 for (i
= 0; i
< count
; i
++) {
375 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
377 /* Handle the state transform */
378 switch (ci
->u1
.dlstLightStateType
) {
379 case D3DLIGHTSTATE_MATERIAL
: {
380 IDirect3DMaterialImpl
* mat
= (IDirect3DMaterialImpl
*) ci
->u2
.dwArg
[0];
381 TRACE(" MATERIAL\n");
386 TRACE(" bad Material Handle\n");
390 case D3DLIGHTSTATE_AMBIENT
: {
392 DWORD dwLightState
= ci
->u2
.dwArg
[0];
395 light
[0] = ((dwLightState
>> 16) & 0xFF) / 255.0;
396 light
[1] = ((dwLightState
>> 8) & 0xFF) / 255.0;
397 light
[2] = ((dwLightState
>> 0) & 0xFF) / 255.0;
399 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, (float *) light
);
401 TRACE(" R:%02lx G:%02lx B:%02lx A:%02lx\n",
402 ((dwLightState
>> 16) & 0xFF),
403 ((dwLightState
>> 8) & 0xFF),
404 ((dwLightState
>> 0) & 0xFF),
405 ((dwLightState
>> 24) & 0xFF));
408 case D3DLIGHTSTATE_COLORMODEL
: {
409 WARN(" COLORMODEL\n");
412 case D3DLIGHTSTATE_FOGMODE
: {
416 case D3DLIGHTSTATE_FOGSTART
: {
420 case D3DLIGHTSTATE_FOGEND
: {
424 case D3DLIGHTSTATE_FOGDENSITY
: {
425 WARN(" FOGDENSITY\n");
429 ERR(" Unhandled light state !! (%d)\n", (int) ci
->u1
.dlstLightStateType
);
436 case D3DOP_STATERENDER
: {
438 TRACE("STATERENDER (%d)\n", count
);
440 for (i
= 0; i
< count
; i
++) {
441 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
444 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
445 ci
->u1
.drstRenderStateType
, ci
->u2
.dwArg
[0]);
452 case D3DOP_PROCESSVERTICES
: {
454 TRACE("PROCESSVERTICES (%d)\n", count
);
456 for (i
= 0; i
< count
; i
++) {
457 LPD3DPROCESSVERTICES ci
= (LPD3DPROCESSVERTICES
) instr
;
459 TRACE(" Start : %d Dest : %d Count : %ld\n",
460 ci
->wStart
, ci
->wDest
, ci
->dwCount
);
462 if (TRACE_ON(ddraw
)) {
463 if (ci
->dwFlags
& D3DPROCESSVERTICES_COPY
)
465 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
467 if (ci
->dwFlags
== D3DPROCESSVERTICES_OPMASK
)
469 if (ci
->dwFlags
& D3DPROCESSVERTICES_TRANSFORM
)
471 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
)
472 TRACE("TRANSFORMLIGHT ");
473 if (ci
->dwFlags
& D3DPROCESSVERTICES_UPDATEEXTENTS
)
474 TRACE("UPDATEEXTENTS ");
478 /* This is where doing Direct3D on top on OpenGL is quite difficult.
479 This method transforms a set of vertices using the CURRENT state
480 (lighting, projection, ...) but does not rasterize them.
481 They will only be put on screen later (with the POINT / LINE and
482 TRIANGLE op-codes). The problem is that you can have a triangle
483 with each point having been transformed using another state...
485 In this implementation, I will emulate only ONE thing : each
486 vertex can have its own "WORLD" transformation (this is used in the
487 TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
488 execute buffer use the same state.
490 If I find applications that change other states, I will try to do a
491 more 'fine-tuned' state emulation (but I may become quite tricky if
492 it changes a light position in the middle of a triangle).
494 In this case, a 'direct' approach (i.e. without using OpenGL, but
495 writing our own 3D rasterizer) would be easier. */
497 /* The current method (with the hypothesis that only the WORLD matrix
498 will change between two points) is like this :
499 - I transform 'manually' all the vertices with the current WORLD
500 matrix and store them in the vertex buffer
501 - during the rasterization phase, the WORLD matrix will be set to
502 the Identity matrix */
504 /* Enough for the moment */
505 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
) {
507 D3DVERTEX
*src
= ((LPD3DVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
508 OGL_Vertex
*dst
= ((OGL_Vertex
*) (This
->vertex_data
)) + ci
->wDest
;
509 D3DMATRIX
*mat
= lpDevice
->world_mat
;
511 TRACE(" World Matrix : (%p)\n", mat
);
514 This
->vertex_type
= D3DVT_VERTEX
;
516 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
517 /* For the moment, no normal transformation... */
518 dst
->nx
= (src
->u4
.nx
* mat
->_11
) + (src
->u5
.ny
* mat
->_21
) + (src
->u6
.nz
* mat
->_31
);
519 dst
->ny
= (src
->u4
.nx
* mat
->_12
) + (src
->u5
.ny
* mat
->_22
) + (src
->u6
.nz
* mat
->_32
);
520 dst
->nz
= (src
->u4
.nx
* mat
->_13
) + (src
->u5
.ny
* mat
->_23
) + (src
->u6
.nz
* mat
->_33
);
525 /* Now, the matrix multiplication */
526 dst
->x
= (src
->u1
.x
* mat
->_11
) + (src
->u2
.y
* mat
->_21
) + (src
->u3
.z
* mat
->_31
) + (1.0 * mat
->_41
);
527 dst
->y
= (src
->u1
.x
* mat
->_12
) + (src
->u2
.y
* mat
->_22
) + (src
->u3
.z
* mat
->_32
) + (1.0 * mat
->_42
);
528 dst
->z
= (src
->u1
.x
* mat
->_13
) + (src
->u2
.y
* mat
->_23
) + (src
->u3
.z
* mat
->_33
) + (1.0 * mat
->_43
);
529 dst
->w
= (src
->u1
.x
* mat
->_14
) + (src
->u2
.y
* mat
->_24
) + (src
->u3
.z
* mat
->_34
) + (1.0 * mat
->_44
);
534 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORM
) {
536 D3DLVERTEX
*src
= ((LPD3DLVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
537 OGL_LVertex
*dst
= ((OGL_LVertex
*) (This
->vertex_data
)) + ci
->wDest
;
538 D3DMATRIX
*mat
= lpDevice
->world_mat
;
540 TRACE(" World Matrix : (%p)\n", mat
);
543 This
->vertex_type
= D3DVT_LVERTEX
;
545 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
546 dst
->c
= src
->u4
.color
;
547 dst
->sc
= src
->u5
.specular
;
551 /* Now, the matrix multiplication */
552 dst
->x
= (src
->u1
.x
* mat
->_11
) + (src
->u2
.y
* mat
->_21
) + (src
->u3
.z
* mat
->_31
) + (1.0 * mat
->_41
);
553 dst
->y
= (src
->u1
.x
* mat
->_12
) + (src
->u2
.y
* mat
->_22
) + (src
->u3
.z
* mat
->_32
) + (1.0 * mat
->_42
);
554 dst
->z
= (src
->u1
.x
* mat
->_13
) + (src
->u2
.y
* mat
->_23
) + (src
->u3
.z
* mat
->_33
) + (1.0 * mat
->_43
);
555 dst
->w
= (src
->u1
.x
* mat
->_14
) + (src
->u2
.y
* mat
->_24
) + (src
->u3
.z
* mat
->_34
) + (1.0 * mat
->_44
);
560 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_COPY
) {
561 D3DTLVERTEX
*src
= ((LPD3DTLVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
562 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
564 This
->vertex_type
= D3DVT_TLVERTEX
;
566 memcpy(dst
, src
, ci
->dwCount
* sizeof(D3DTLVERTEX
));
568 ERR("Unhandled vertex processing !\n");
575 case D3DOP_TEXTURELOAD
: {
576 WARN("TEXTURELOAD-s (%d)\n", count
);
578 instr
+= count
* size
;
582 TRACE("EXIT (%d)\n", count
);
583 /* We did this instruction */
589 case D3DOP_BRANCHFORWARD
: {
591 TRACE("BRANCHFORWARD (%d)\n", count
);
593 for (i
= 0; i
< count
; i
++) {
594 LPD3DBRANCH ci
= (LPD3DBRANCH
) instr
;
596 if ((This
->data
.dsStatus
.dwStatus
& ci
->dwMask
) == ci
->dwValue
) {
598 TRACE(" Should branch to %ld\n", ci
->dwOffset
);
602 TRACE(" Should branch to %ld\n", ci
->dwOffset
);
611 WARN("SPAN-s (%d)\n", count
);
613 instr
+= count
* size
;
616 case D3DOP_SETSTATUS
: {
618 TRACE("SETSTATUS (%d)\n", count
);
620 for (i
= 0; i
< count
; i
++) {
621 LPD3DSTATUS ci
= (LPD3DSTATUS
) instr
;
623 This
->data
.dsStatus
= *ci
;
630 ERR("Unhandled OpCode !!!\n");
631 /* Try to save ... */
632 instr
+= count
* size
;
642 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface
,
646 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
647 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_guid(riid
), obp
);
651 if ( IsEqualGUID( &IID_IUnknown
, riid
) ) {
652 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
654 TRACE(" Creating IUnknown interface at %p.\n", *obp
);
657 if ( IsEqualGUID( &IID_IDirect3DMaterial
, riid
) ) {
658 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
659 *obp
= ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
);
660 TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obp
);
663 FIXME("(%p): interface for IID %s NOT found!\n", This
, debugstr_guid(riid
));
664 return OLE_E_ENUM_NOMORE
;
668 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface
)
670 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
671 FIXME("(%p/%p)->()incrementing from %lu.\n", This
, iface
, This
->ref
);
672 return ++(This
->ref
);
676 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface
)
678 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
679 TRACE("(%p/%p)->()decrementing from %lu.\n", This
, iface
, This
->ref
);
680 if (!--(This
->ref
)) {
681 if ((This
->desc
.lpData
!= NULL
) && This
->need_free
)
682 HeapFree(GetProcessHeap(),0,This
->desc
.lpData
);
683 if (This
->vertex_data
!= NULL
)
684 HeapFree(GetProcessHeap(),0,This
->vertex_data
);
685 HeapFree(GetProcessHeap(),0,This
);
693 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface
,
694 LPDIRECT3DDEVICE lpDirect3DDevice
,
695 LPD3DEXECUTEBUFFERDESC lpDesc
)
697 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
698 TRACE("(%p/%p)->(%p,%p) no-op....\n", This
, iface
, lpDirect3DDevice
, lpDesc
);
703 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface
,
704 LPD3DEXECUTEBUFFERDESC lpDesc
)
706 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
708 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpDesc
);
710 dwSize
= lpDesc
->dwSize
;
711 memset(lpDesc
, 0, dwSize
);
712 memcpy(lpDesc
, &This
->desc
, dwSize
);
714 if (TRACE_ON(ddraw
)) {
715 TRACE(" Returning description : \n");
716 _dump_D3DEXECUTEBUFFERDESC(lpDesc
);
722 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface
)
724 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
725 TRACE("(%p/%p)->() no-op...\n", This
, iface
);
730 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
731 LPD3DEXECUTEDATA lpData
)
733 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
735 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
737 memcpy(&This
->data
, lpData
, lpData
->dwSize
);
739 /* Get the number of vertices in the execute buffer */
740 nbvert
= This
->data
.dwVertexCount
;
742 /* Prepares the transformed vertex buffer */
743 if (This
->vertex_data
!= NULL
)
744 HeapFree(GetProcessHeap(), 0, This
->vertex_data
);
745 This
->vertex_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbvert
* sizeof(OGL_Vertex
));
747 if (TRACE_ON(ddraw
)) {
748 _dump_executedata(lpData
);
755 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
756 LPD3DEXECUTEDATA lpData
)
758 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
760 TRACE("(%p/%p)->(%p): stub!\n", This
, iface
, lpData
);
762 dwSize
= lpData
->dwSize
;
763 memset(lpData
, 0, dwSize
);
764 memcpy(lpData
, &This
->data
, dwSize
);
766 if (TRACE_ON(ddraw
)) {
767 TRACE("Returning data : \n");
768 _dump_executedata(lpData
);
775 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface
,
777 LPD3DVALIDATECALLBACK lpFunc
,
781 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
782 FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This
, iface
, lpdwOffset
, lpFunc
, lpUserArg
, dwReserved
);
787 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface
,
790 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
791 TRACE("(%p/%p)->(%08lx) no-op...\n", This
, iface
, dwDummy
);
795 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
796 # define XCAST(fun) (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
798 # define XCAST(fun) (void*)
801 ICOM_VTABLE(IDirect3DExecuteBuffer
) VTABLE_IDirect3DExecuteBuffer
=
803 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
804 XCAST(QueryInterface
) Main_IDirect3DExecuteBufferImpl_1_QueryInterface
,
805 XCAST(AddRef
) Main_IDirect3DExecuteBufferImpl_1_AddRef
,
806 XCAST(Release
) Main_IDirect3DExecuteBufferImpl_1_Release
,
807 XCAST(Initialize
) Main_IDirect3DExecuteBufferImpl_1_Initialize
,
808 XCAST(Lock
) Main_IDirect3DExecuteBufferImpl_1_Lock
,
809 XCAST(Unlock
) Main_IDirect3DExecuteBufferImpl_1_Unlock
,
810 XCAST(SetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData
,
811 XCAST(GetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData
,
812 XCAST(Validate
) Main_IDirect3DExecuteBufferImpl_1_Validate
,
813 XCAST(Optimize
) Main_IDirect3DExecuteBufferImpl_1_Optimize
,
816 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
821 HRESULT
d3dexecutebuffer_create(IDirect3DExecuteBufferImpl
**obj
, IDirect3DImpl
*d3d
, IDirect3DDeviceImpl
*d3ddev
, LPD3DEXECUTEBUFFERDESC lpDesc
)
823 IDirect3DExecuteBufferImpl
* object
;
825 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DExecuteBufferImpl
));
827 ICOM_INIT_INTERFACE(object
, IDirect3DExecuteBuffer
, VTABLE_IDirect3DExecuteBuffer
);
831 object
->d3ddev
= d3ddev
;
833 /* Initializes memory */
834 memcpy(&object
->desc
, lpDesc
, lpDesc
->dwSize
);
836 /* No buffer given */
837 if ((object
->desc
.dwFlags
& D3DDEB_LPDATA
) == 0)
838 object
->desc
.lpData
= NULL
;
840 /* No buffer size given */
841 if ((lpDesc
->dwFlags
& D3DDEB_BUFSIZE
) == 0)
842 object
->desc
.dwBufferSize
= 0;
844 /* Create buffer if asked */
845 if ((object
->desc
.lpData
== NULL
) && (object
->desc
.dwBufferSize
> 0)) {
846 object
->need_free
= TRUE
;
847 object
->desc
.lpData
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,object
->desc
.dwBufferSize
);
849 object
->need_free
= FALSE
;
852 /* No vertices for the moment */
853 object
->vertex_data
= NULL
;
855 object
->desc
.dwFlags
|= D3DDEB_LPDATA
;
857 object
->execute
= execute
;
861 TRACE(" creating implementation at %p.\n", *obj
);