1 /* Direct3D ExecuteBuffer
2 * Copyright (c) 1998-2004 Lionel ULMER
3 * Copyright (c) 2002-2004 Christian Costa
5 * This file contains the implementation of Direct3DExecuteBuffer.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
36 #include "wine/debug.h"
38 #include "d3d_private.h"
39 #include "mesa_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
42 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom
);
44 static void _dump_d3dstatus(LPD3DSTATUS lpStatus
) {
48 static void _dump_executedata(LPD3DEXECUTEDATA lpData
) {
49 DPRINTF("dwSize : %ld\n", lpData
->dwSize
);
50 DPRINTF("Vertex Offset : %ld Count : %ld\n", lpData
->dwVertexOffset
, lpData
->dwVertexCount
);
51 DPRINTF("Instruction Offset : %ld Length : %ld\n", lpData
->dwInstructionOffset
, lpData
->dwInstructionLength
);
52 DPRINTF("HVertex Offset : %ld\n", lpData
->dwHVertexOffset
);
53 _dump_d3dstatus(&(lpData
->dsStatus
));
56 static void _dump_D3DEXECUTEBUFFERDESC(LPD3DEXECUTEBUFFERDESC lpDesc
) {
57 DPRINTF("dwSize : %ld\n", lpDesc
->dwSize
);
58 DPRINTF("dwFlags : %lx\n", lpDesc
->dwFlags
);
59 DPRINTF("dwCaps : %lx\n", lpDesc
->dwCaps
);
60 DPRINTF("dwBufferSize : %ld\n", lpDesc
->dwBufferSize
);
61 DPRINTF("lpData : %p\n", lpDesc
->lpData
);
64 static void execute(IDirect3DExecuteBufferImpl
*This
,
65 IDirect3DDeviceImpl
*lpDevice
,
66 IDirect3DViewportImpl
*lpViewport
)
68 /* DWORD bs = This->desc.dwBufferSize; */
69 DWORD vs
= This
->data
.dwVertexOffset
;
70 /* DWORD vc = This->data.dwVertexCount; */
71 DWORD is
= This
->data
.dwInstructionOffset
;
72 /* DWORD il = This->data.dwInstructionLength; */
74 char *instr
= (char *)This
->desc
.lpData
+ is
;
76 /* Should check if the viewport was added or not to the device */
78 /* Activate the viewport */
79 lpViewport
->active_device
= lpDevice
;
80 lpViewport
->activate(lpViewport
);
82 TRACE("ExecuteData : \n");
84 _dump_executedata(&(This
->data
));
87 LPD3DINSTRUCTION current
= (LPD3DINSTRUCTION
) instr
;
91 count
= current
->wCount
;
92 size
= current
->bSize
;
93 instr
+= sizeof(D3DINSTRUCTION
);
95 switch (current
->bOpcode
) {
97 WARN("POINT-s (%d)\n", count
);
98 instr
+= count
* size
;
102 WARN("LINE-s (%d)\n", count
);
103 instr
+= count
* size
;
106 case D3DOP_TRIANGLE
: {
108 D3DTLVERTEX
*tl_vx
= (D3DTLVERTEX
*) This
->vertex_data
;
109 TRACE("TRIANGLE (%d)\n", count
);
111 if (count
*3>This
->nb_indices
) {
112 This
->nb_indices
= count
* 3;
113 HeapFree(GetProcessHeap(),0,This
->indices
);
114 This
->indices
= HeapAlloc(GetProcessHeap(),0,sizeof(WORD
)*This
->nb_indices
);
117 for (i
= 0; i
< count
; i
++) {
118 LPD3DTRIANGLE ci
= (LPD3DTRIANGLE
) instr
;
119 TRACE_(ddraw_geom
)(" v1: %d v2: %d v3: %d\n",ci
->u1
.v1
, ci
->u2
.v2
, ci
->u3
.v3
);
120 TRACE_(ddraw_geom
)(" Flags : ");
121 if (TRACE_ON(ddraw
)) {
123 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
124 TRACE_(ddraw_geom
)("EDGEENABLE1 ");
125 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE2
)
126 TRACE_(ddraw_geom
)("EDGEENABLE2 ");
127 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
128 TRACE_(ddraw_geom
)("EDGEENABLE3 ");
130 if (ci
->wFlags
== D3DTRIFLAG_EVEN
)
131 TRACE_(ddraw_geom
)("EVEN ");
132 if (ci
->wFlags
== D3DTRIFLAG_ODD
)
133 TRACE_(ddraw_geom
)("ODD ");
134 if (ci
->wFlags
== D3DTRIFLAG_START
)
135 TRACE_(ddraw_geom
)("START ");
136 if ((ci
->wFlags
> 0) && (ci
->wFlags
< 30))
137 TRACE_(ddraw_geom
)("STARTFLAT(%d) ", ci
->wFlags
);
138 TRACE_(ddraw_geom
)("\n");
140 This
->indices
[(i
* 3) ] = ci
->u1
.v1
;
141 This
->indices
[(i
* 3) + 1] = ci
->u2
.v2
;
142 This
->indices
[(i
* 3) + 2] = ci
->u3
.v3
;
145 IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(lpDevice
,IDirect3DDevice7
),
146 D3DPT_TRIANGLELIST
,D3DFVF_TLVERTEX
,tl_vx
,0,This
->indices
,count
*3,0);
149 case D3DOP_MATRIXLOAD
:
150 WARN("MATRIXLOAD-s (%d)\n", count
);
151 instr
+= count
* size
;
154 case D3DOP_MATRIXMULTIPLY
: {
156 TRACE("MATRIXMULTIPLY (%d)\n", count
);
158 for (i
= 0; i
< count
; i
++) {
159 LPD3DMATRIXMULTIPLY ci
= (LPD3DMATRIXMULTIPLY
) instr
;
160 LPD3DMATRIX a
= (LPD3DMATRIX
) ci
->hDestMatrix
;
161 LPD3DMATRIX b
= (LPD3DMATRIX
) ci
->hSrcMatrix1
;
162 LPD3DMATRIX c
= (LPD3DMATRIX
) ci
->hSrcMatrix2
;
164 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
165 ci
->hDestMatrix
, ci
->hSrcMatrix1
, ci
->hSrcMatrix2
);
167 multiply_matrix(a
,c
,b
);
173 case D3DOP_STATETRANSFORM
: {
175 TRACE("STATETRANSFORM (%d)\n", count
);
177 for (i
= 0; i
< count
; i
++) {
178 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
180 IDirect3DDevice7_SetTransform(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
181 ci
->u1
.drstRenderStateType
, (LPD3DMATRIX
)ci
->u2
.dwArg
[0]);
187 case D3DOP_STATELIGHT
: {
189 TRACE("STATELIGHT (%d)\n", count
);
191 for (i
= 0; i
< count
; i
++) {
192 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
194 TRACE("(%08x,%08lx)\n",ci
->u1
.dlstLightStateType
, ci
->u2
.dwArg
[0]);
196 if (!ci
->u1
.dlstLightStateType
&& (ci
->u1
.dlstLightStateType
> D3DLIGHTSTATE_COLORVERTEX
))
197 ERR("Unexpected Light State Type\n");
198 else if (ci
->u1
.dlstLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
199 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) ci
->u2
.dwArg
[0];
204 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
207 else if (ci
->u1
.dlstLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
208 switch (ci
->u2
.dwArg
[0]) {
210 ERR("DDCOLOR_MONO should not happen!\n");
213 /* We are already in this mode */
216 ERR("Unknown color model!\n");
219 D3DRENDERSTATETYPE rs
= 0;
220 switch (ci
->u1
.dlstLightStateType
) {
222 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
223 rs
= D3DRENDERSTATE_AMBIENT
;
225 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
226 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
228 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
229 rs
= D3DRENDERSTATE_FOGSTART
;
231 case D3DLIGHTSTATE_FOGEND
: /* 6 */
232 rs
= D3DRENDERSTATE_FOGEND
;
234 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
235 rs
= D3DRENDERSTATE_FOGDENSITY
;
237 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
238 rs
= D3DRENDERSTATE_COLORVERTEX
;
244 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
252 case D3DOP_STATERENDER
: {
254 TRACE("STATERENDER (%d)\n", count
);
256 for (i
= 0; i
< count
; i
++) {
257 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
259 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
260 ci
->u1
.drstRenderStateType
, ci
->u2
.dwArg
[0]);
266 case D3DOP_PROCESSVERTICES
: {
268 TRACE("PROCESSVERTICES (%d)\n", count
);
270 for (i
= 0; i
< count
; i
++) {
271 LPD3DPROCESSVERTICES ci
= (LPD3DPROCESSVERTICES
) instr
;
273 TRACE(" Start : %d Dest : %d Count : %ld\n",
274 ci
->wStart
, ci
->wDest
, ci
->dwCount
);
276 if (TRACE_ON(ddraw
)) {
277 if (ci
->dwFlags
& D3DPROCESSVERTICES_COPY
)
279 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
281 if (ci
->dwFlags
== D3DPROCESSVERTICES_OPMASK
)
283 if (ci
->dwFlags
& D3DPROCESSVERTICES_TRANSFORM
)
285 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
)
286 TRACE("TRANSFORMLIGHT ");
287 if (ci
->dwFlags
& D3DPROCESSVERTICES_UPDATEEXTENTS
)
288 TRACE("UPDATEEXTENTS ");
292 /* This is where doing Direct3D on top on OpenGL is quite difficult.
293 This method transforms a set of vertices using the CURRENT state
294 (lighting, projection, ...) but does not rasterize them.
295 They will only be put on screen later (with the POINT / LINE and
296 TRIANGLE op-codes). The problem is that you can have a triangle
297 with each point having been transformed using another state...
299 In this implementation, I will emulate only ONE thing : each
300 vertex can have its own "WORLD" transformation (this is used in the
301 TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
302 execute buffer use the same state.
304 If I find applications that change other states, I will try to do a
305 more 'fine-tuned' state emulation (but I may become quite tricky if
306 it changes a light position in the middle of a triangle).
308 In this case, a 'direct' approach (i.e. without using OpenGL, but
309 writing our own 3D rasterizer) would be easier. */
311 /* The current method (with the hypothesis that only the WORLD matrix
312 will change between two points) is like this :
313 - I transform 'manually' all the vertices with the current WORLD
314 matrix and store them in the vertex buffer
315 - during the rasterization phase, the WORLD matrix will be set to
316 the Identity matrix */
318 /* Enough for the moment */
319 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
) {
321 D3DVERTEX
*src
= ((LPD3DVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
322 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
323 D3DMATRIX
*mat2
= lpDevice
->world_mat
;
326 D3DVIEWPORT
* Viewport
= &lpViewport
->viewports
.vp1
;
328 if (TRACE_ON(ddraw
)) {
329 TRACE(" Projection Matrix : (%p)\n", lpDevice
->proj_mat
);
330 dump_D3DMATRIX(lpDevice
->proj_mat
);
331 TRACE(" View Matrix : (%p)\n", lpDevice
->view_mat
);
332 dump_D3DMATRIX(lpDevice
->view_mat
);
333 TRACE(" World Matrix : (%p)\n", lpDevice
->world_mat
);
334 dump_D3DMATRIX(lpDevice
->world_mat
);
337 multiply_matrix(&mat
,lpDevice
->view_mat
,lpDevice
->world_mat
);
338 multiply_matrix(&mat
,lpDevice
->proj_mat
,&mat
);
340 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
341 /* Normals transformation */
342 nx
= (src
->u4
.nx
* mat2
->_11
) + (src
->u5
.ny
* mat2
->_21
) + (src
->u6
.nz
* mat2
->_31
);
343 ny
= (src
->u4
.nx
* mat2
->_12
) + (src
->u5
.ny
* mat2
->_22
) + (src
->u6
.nz
* mat2
->_32
);
344 nz
= (src
->u4
.nx
* mat2
->_13
) + (src
->u5
.ny
* mat2
->_23
) + (src
->u6
.nz
* mat2
->_33
);
346 /* No lighting yet */
347 dst
->u5
.color
= 0xFFFFFFFF; /* Opaque white */
348 dst
->u6
.specular
= 0xFF000000; /* No specular and no fog factor */
350 dst
->u7
.tu
= src
->u7
.tu
;
351 dst
->u8
.tv
= src
->u8
.tv
;
353 /* Now, the matrix multiplication */
354 dst
->u1
.sx
= (src
->u1
.x
* mat
._11
) + (src
->u2
.y
* mat
._21
) + (src
->u3
.z
* mat
._31
) + (1.0 * mat
._41
);
355 dst
->u2
.sy
= (src
->u1
.x
* mat
._12
) + (src
->u2
.y
* mat
._22
) + (src
->u3
.z
* mat
._32
) + (1.0 * mat
._42
);
356 dst
->u3
.sz
= (src
->u1
.x
* mat
._13
) + (src
->u2
.y
* mat
._23
) + (src
->u3
.z
* mat
._33
) + (1.0 * mat
._43
);
357 dst
->u4
.rhw
= (src
->u1
.x
* mat
._14
) + (src
->u2
.y
* mat
._24
) + (src
->u3
.z
* mat
._34
) + (1.0 * mat
._44
);
359 dst
->u1
.sx
= dst
->u1
.sx
/ dst
->u4
.rhw
* Viewport
->dwWidth
/ 2
360 + Viewport
->dwX
+ Viewport
->dwWidth
/ 2;
361 dst
->u2
.sy
= dst
->u2
.sy
/ dst
->u4
.rhw
* Viewport
->dwHeight
/ 2
362 + Viewport
->dwY
+ Viewport
->dwHeight
/ 2;
363 dst
->u3
.sz
/= dst
->u4
.rhw
;
364 dst
->u4
.rhw
= 1 / dst
->u4
.rhw
;
370 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORM
) {
372 D3DLVERTEX
*src
= ((LPD3DLVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
373 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
375 D3DVIEWPORT
* Viewport
= &lpViewport
->viewports
.vp1
;
377 if (TRACE_ON(ddraw
)) {
378 TRACE(" Projection Matrix : (%p)\n", lpDevice
->proj_mat
);
379 dump_D3DMATRIX(lpDevice
->proj_mat
);
380 TRACE(" View Matrix : (%p)\n", lpDevice
->view_mat
);
381 dump_D3DMATRIX(lpDevice
->view_mat
);
382 TRACE(" World Matrix : (%p)\n", &mat
);
383 dump_D3DMATRIX(&mat
);
386 multiply_matrix(&mat
,lpDevice
->view_mat
,lpDevice
->world_mat
);
387 multiply_matrix(&mat
,lpDevice
->proj_mat
,&mat
);
389 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
390 dst
->u5
.color
= src
->u4
.color
;
391 dst
->u6
.specular
= src
->u5
.specular
;
392 dst
->u7
.tu
= src
->u6
.tu
;
393 dst
->u8
.tv
= src
->u7
.tv
;
395 /* Now, the matrix multiplication */
396 dst
->u1
.sx
= (src
->u1
.x
* mat
._11
) + (src
->u2
.y
* mat
._21
) + (src
->u3
.z
* mat
._31
) + (1.0 * mat
._41
);
397 dst
->u2
.sy
= (src
->u1
.x
* mat
._12
) + (src
->u2
.y
* mat
._22
) + (src
->u3
.z
* mat
._32
) + (1.0 * mat
._42
);
398 dst
->u3
.sz
= (src
->u1
.x
* mat
._13
) + (src
->u2
.y
* mat
._23
) + (src
->u3
.z
* mat
._33
) + (1.0 * mat
._43
);
399 dst
->u4
.rhw
= (src
->u1
.x
* mat
._14
) + (src
->u2
.y
* mat
._24
) + (src
->u3
.z
* mat
._34
) + (1.0 * mat
._44
);
401 dst
->u1
.sx
/= dst
->u4
.rhw
* Viewport
->dvScaleX
* Viewport
->dwWidth
/ 2 + Viewport
->dwX
;
402 dst
->u2
.sy
/= dst
->u4
.rhw
* Viewport
->dvScaleY
* Viewport
->dwHeight
/ 2 + Viewport
->dwY
;
403 dst
->u3
.sz
/= dst
->u4
.rhw
;
404 dst
->u4
.rhw
= 1 / dst
->u4
.rhw
;
409 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_COPY
) {
410 D3DTLVERTEX
*src
= ((LPD3DTLVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
411 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
413 memcpy(dst
, src
, ci
->dwCount
* sizeof(D3DTLVERTEX
));
415 ERR("Unhandled vertex processing !\n");
422 case D3DOP_TEXTURELOAD
: {
423 WARN("TEXTURELOAD-s (%d)\n", count
);
425 instr
+= count
* size
;
429 TRACE("EXIT (%d)\n", count
);
430 /* We did this instruction */
436 case D3DOP_BRANCHFORWARD
: {
438 TRACE("BRANCHFORWARD (%d)\n", count
);
440 for (i
= 0; i
< count
; i
++) {
441 LPD3DBRANCH ci
= (LPD3DBRANCH
) instr
;
443 if ((This
->data
.dsStatus
.dwStatus
& ci
->dwMask
) == ci
->dwValue
) {
445 TRACE(" Branch to %ld\n", ci
->dwOffset
);
446 instr
= (char*)current
+ ci
->dwOffset
;
451 TRACE(" Branch to %ld\n", ci
->dwOffset
);
452 instr
= (char*)current
+ ci
->dwOffset
;
462 WARN("SPAN-s (%d)\n", count
);
464 instr
+= count
* size
;
467 case D3DOP_SETSTATUS
: {
469 TRACE("SETSTATUS (%d)\n", count
);
471 for (i
= 0; i
< count
; i
++) {
472 LPD3DSTATUS ci
= (LPD3DSTATUS
) instr
;
474 This
->data
.dsStatus
= *ci
;
481 ERR("Unhandled OpCode %d !!!\n",current
->bOpcode
);
482 /* Try to save ... */
483 instr
+= count
* size
;
493 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface
,
497 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
498 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_guid(riid
), obp
);
502 if ( IsEqualGUID( &IID_IUnknown
, riid
) ) {
503 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
505 TRACE(" Creating IUnknown interface at %p.\n", *obp
);
508 if ( IsEqualGUID( &IID_IDirect3DMaterial
, riid
) ) {
509 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
510 *obp
= ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
);
511 TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obp
);
514 FIXME("(%p): interface for IID %s NOT found!\n", This
, debugstr_guid(riid
));
515 return OLE_E_ENUM_NOMORE
;
519 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface
)
521 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
522 ULONG ref
= InterlockedIncrement(&This
->ref
);
524 FIXME("(%p/%p)->()incrementing from %lu.\n", This
, iface
, ref
- 1);
530 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface
)
532 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
533 ULONG ref
= InterlockedDecrement(&This
->ref
);
535 TRACE("(%p/%p)->()decrementing from %lu.\n", This
, iface
, ref
+ 1);
538 if ((This
->desc
.lpData
!= NULL
) && This
->need_free
)
539 HeapFree(GetProcessHeap(),0,This
->desc
.lpData
);
540 HeapFree(GetProcessHeap(),0,This
->vertex_data
);
541 HeapFree(GetProcessHeap(),0,This
->indices
);
542 HeapFree(GetProcessHeap(),0,This
);
550 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface
,
551 LPDIRECT3DDEVICE lpDirect3DDevice
,
552 LPD3DEXECUTEBUFFERDESC lpDesc
)
554 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
555 TRACE("(%p/%p)->(%p,%p) no-op....\n", This
, iface
, lpDirect3DDevice
, lpDesc
);
560 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface
,
561 LPD3DEXECUTEBUFFERDESC lpDesc
)
563 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
565 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpDesc
);
567 dwSize
= lpDesc
->dwSize
;
568 memset(lpDesc
, 0, dwSize
);
569 memcpy(lpDesc
, &This
->desc
, dwSize
);
571 if (TRACE_ON(ddraw
)) {
572 TRACE(" Returning description : \n");
573 _dump_D3DEXECUTEBUFFERDESC(lpDesc
);
579 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface
)
581 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
582 TRACE("(%p/%p)->() no-op...\n", This
, iface
);
587 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
588 LPD3DEXECUTEDATA lpData
)
590 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
592 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
594 memcpy(&This
->data
, lpData
, lpData
->dwSize
);
596 /* Get the number of vertices in the execute buffer */
597 nbvert
= This
->data
.dwVertexCount
;
599 /* Prepares the transformed vertex buffer */
600 HeapFree(GetProcessHeap(), 0, This
->vertex_data
);
601 This
->vertex_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbvert
* sizeof(D3DTLVERTEX
));
603 if (TRACE_ON(ddraw
)) {
604 _dump_executedata(lpData
);
611 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
612 LPD3DEXECUTEDATA lpData
)
614 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
616 TRACE("(%p/%p)->(%p): stub!\n", This
, iface
, lpData
);
618 dwSize
= lpData
->dwSize
;
619 memset(lpData
, 0, dwSize
);
620 memcpy(lpData
, &This
->data
, dwSize
);
622 if (TRACE_ON(ddraw
)) {
623 TRACE("Returning data : \n");
624 _dump_executedata(lpData
);
631 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface
,
633 LPD3DVALIDATECALLBACK lpFunc
,
637 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
638 FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This
, iface
, lpdwOffset
, lpFunc
, lpUserArg
, dwReserved
);
643 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface
,
646 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
647 TRACE("(%p/%p)->(%08lx) no-op...\n", This
, iface
, dwDummy
);
651 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
652 # define XCAST(fun) (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
654 # define XCAST(fun) (void*)
657 IDirect3DExecuteBufferVtbl VTABLE_IDirect3DExecuteBuffer
=
659 XCAST(QueryInterface
) Main_IDirect3DExecuteBufferImpl_1_QueryInterface
,
660 XCAST(AddRef
) Main_IDirect3DExecuteBufferImpl_1_AddRef
,
661 XCAST(Release
) Main_IDirect3DExecuteBufferImpl_1_Release
,
662 XCAST(Initialize
) Main_IDirect3DExecuteBufferImpl_1_Initialize
,
663 XCAST(Lock
) Main_IDirect3DExecuteBufferImpl_1_Lock
,
664 XCAST(Unlock
) Main_IDirect3DExecuteBufferImpl_1_Unlock
,
665 XCAST(SetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData
,
666 XCAST(GetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData
,
667 XCAST(Validate
) Main_IDirect3DExecuteBufferImpl_1_Validate
,
668 XCAST(Optimize
) Main_IDirect3DExecuteBufferImpl_1_Optimize
,
671 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
676 HRESULT
d3dexecutebuffer_create(IDirect3DExecuteBufferImpl
**obj
, IDirectDrawImpl
*d3d
, IDirect3DDeviceImpl
*d3ddev
, LPD3DEXECUTEBUFFERDESC lpDesc
)
678 IDirect3DExecuteBufferImpl
* object
;
680 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DExecuteBufferImpl
));
682 ICOM_INIT_INTERFACE(object
, IDirect3DExecuteBuffer
, VTABLE_IDirect3DExecuteBuffer
);
686 object
->d3ddev
= d3ddev
;
688 /* Initializes memory */
689 memcpy(&object
->desc
, lpDesc
, lpDesc
->dwSize
);
691 /* No buffer given */
692 if ((object
->desc
.dwFlags
& D3DDEB_LPDATA
) == 0)
693 object
->desc
.lpData
= NULL
;
695 /* No buffer size given */
696 if ((lpDesc
->dwFlags
& D3DDEB_BUFSIZE
) == 0)
697 object
->desc
.dwBufferSize
= 0;
699 /* Create buffer if asked */
700 if ((object
->desc
.lpData
== NULL
) && (object
->desc
.dwBufferSize
> 0)) {
701 object
->need_free
= TRUE
;
702 object
->desc
.lpData
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,object
->desc
.dwBufferSize
);
704 object
->need_free
= FALSE
;
707 /* No vertices for the moment */
708 object
->vertex_data
= NULL
;
710 object
->desc
.dwFlags
|= D3DDEB_LPDATA
;
712 object
->execute
= execute
;
714 object
->indices
= NULL
;
715 object
->nb_indices
= 0;
719 TRACE(" creating implementation at %p.\n", *obj
);