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;
114 HeapFree(GetProcessHeap(),0,This
->indices
);
115 This
->indices
= HeapAlloc(GetProcessHeap(),0,sizeof(WORD
)*This
->nb_indices
);
118 for (i
= 0; i
< count
; i
++) {
119 LPD3DTRIANGLE ci
= (LPD3DTRIANGLE
) instr
;
120 TRACE_(ddraw_geom
)(" v1: %d v2: %d v3: %d\n",ci
->u1
.v1
, ci
->u2
.v2
, ci
->u3
.v3
);
121 TRACE_(ddraw_geom
)(" Flags : ");
122 if (TRACE_ON(ddraw
)) {
124 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
125 TRACE_(ddraw_geom
)("EDGEENABLE1 ");
126 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE2
)
127 TRACE_(ddraw_geom
)("EDGEENABLE2 ");
128 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
129 TRACE_(ddraw_geom
)("EDGEENABLE3 ");
131 if (ci
->wFlags
== D3DTRIFLAG_EVEN
)
132 TRACE_(ddraw_geom
)("EVEN ");
133 if (ci
->wFlags
== D3DTRIFLAG_ODD
)
134 TRACE_(ddraw_geom
)("ODD ");
135 if (ci
->wFlags
== D3DTRIFLAG_START
)
136 TRACE_(ddraw_geom
)("START ");
137 if ((ci
->wFlags
> 0) && (ci
->wFlags
< 30))
138 TRACE_(ddraw_geom
)("STARTFLAT(%d) ", ci
->wFlags
);
139 TRACE_(ddraw_geom
)("\n");
141 This
->indices
[(i
* 3) ] = ci
->u1
.v1
;
142 This
->indices
[(i
* 3) + 1] = ci
->u2
.v2
;
143 This
->indices
[(i
* 3) + 2] = ci
->u3
.v3
;
146 IDirect3DDevice7_DrawIndexedPrimitive(ICOM_INTERFACE(lpDevice
,IDirect3DDevice7
),
147 D3DPT_TRIANGLELIST
,D3DFVF_TLVERTEX
,tl_vx
,0,This
->indices
,count
*3,0);
150 case D3DOP_MATRIXLOAD
:
151 WARN("MATRIXLOAD-s (%d)\n", count
);
152 instr
+= count
* size
;
155 case D3DOP_MATRIXMULTIPLY
: {
157 TRACE("MATRIXMULTIPLY (%d)\n", count
);
159 for (i
= 0; i
< count
; i
++) {
160 LPD3DMATRIXMULTIPLY ci
= (LPD3DMATRIXMULTIPLY
) instr
;
161 LPD3DMATRIX a
= (LPD3DMATRIX
) ci
->hDestMatrix
;
162 LPD3DMATRIX b
= (LPD3DMATRIX
) ci
->hSrcMatrix1
;
163 LPD3DMATRIX c
= (LPD3DMATRIX
) ci
->hSrcMatrix2
;
165 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
166 ci
->hDestMatrix
, ci
->hSrcMatrix1
, ci
->hSrcMatrix2
);
168 multiply_matrix(a
,c
,b
);
174 case D3DOP_STATETRANSFORM
: {
176 TRACE("STATETRANSFORM (%d)\n", count
);
178 for (i
= 0; i
< count
; i
++) {
179 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
181 IDirect3DDevice7_SetTransform(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
182 ci
->u1
.drstRenderStateType
, (LPD3DMATRIX
)ci
->u2
.dwArg
[0]);
188 case D3DOP_STATELIGHT
: {
190 TRACE("STATELIGHT (%d)\n", count
);
192 for (i
= 0; i
< count
; i
++) {
193 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
195 TRACE("(%08x,%08lx)\n",ci
->u1
.dlstLightStateType
, ci
->u2
.dwArg
[0]);
197 if (!ci
->u1
.dlstLightStateType
&& (ci
->u1
.dlstLightStateType
> D3DLIGHTSTATE_COLORVERTEX
))
198 ERR("Unexpected Light State Type\n");
199 else if (ci
->u1
.dlstLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
200 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) ci
->u2
.dwArg
[0];
205 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
208 else if (ci
->u1
.dlstLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
209 switch (ci
->u2
.dwArg
[0]) {
211 ERR("DDCOLOR_MONO should not happen!\n");
214 /* We are already in this mode */
217 ERR("Unknown color model!\n");
220 D3DRENDERSTATETYPE rs
= 0;
221 switch (ci
->u1
.dlstLightStateType
) {
223 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
224 rs
= D3DRENDERSTATE_AMBIENT
;
226 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
227 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
229 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
230 rs
= D3DRENDERSTATE_FOGSTART
;
232 case D3DLIGHTSTATE_FOGEND
: /* 6 */
233 rs
= D3DRENDERSTATE_FOGEND
;
235 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
236 rs
= D3DRENDERSTATE_FOGDENSITY
;
238 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
239 rs
= D3DRENDERSTATE_COLORVERTEX
;
245 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
253 case D3DOP_STATERENDER
: {
255 TRACE("STATERENDER (%d)\n", count
);
257 for (i
= 0; i
< count
; i
++) {
258 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
260 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice
, IDirect3DDevice7
),
261 ci
->u1
.drstRenderStateType
, ci
->u2
.dwArg
[0]);
267 case D3DOP_PROCESSVERTICES
: {
269 TRACE("PROCESSVERTICES (%d)\n", count
);
271 for (i
= 0; i
< count
; i
++) {
272 LPD3DPROCESSVERTICES ci
= (LPD3DPROCESSVERTICES
) instr
;
274 TRACE(" Start : %d Dest : %d Count : %ld\n",
275 ci
->wStart
, ci
->wDest
, ci
->dwCount
);
277 if (TRACE_ON(ddraw
)) {
278 if (ci
->dwFlags
& D3DPROCESSVERTICES_COPY
)
280 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
282 if (ci
->dwFlags
== D3DPROCESSVERTICES_OPMASK
)
284 if (ci
->dwFlags
& D3DPROCESSVERTICES_TRANSFORM
)
286 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
)
287 TRACE("TRANSFORMLIGHT ");
288 if (ci
->dwFlags
& D3DPROCESSVERTICES_UPDATEEXTENTS
)
289 TRACE("UPDATEEXTENTS ");
293 /* This is where doing Direct3D on top on OpenGL is quite difficult.
294 This method transforms a set of vertices using the CURRENT state
295 (lighting, projection, ...) but does not rasterize them.
296 They will only be put on screen later (with the POINT / LINE and
297 TRIANGLE op-codes). The problem is that you can have a triangle
298 with each point having been transformed using another state...
300 In this implementation, I will emulate only ONE thing : each
301 vertex can have its own "WORLD" transformation (this is used in the
302 TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
303 execute buffer use the same state.
305 If I find applications that change other states, I will try to do a
306 more 'fine-tuned' state emulation (but I may become quite tricky if
307 it changes a light position in the middle of a triangle).
309 In this case, a 'direct' approach (i.e. without using OpenGL, but
310 writing our own 3D rasterizer) would be easier. */
312 /* The current method (with the hypothesis that only the WORLD matrix
313 will change between two points) is like this :
314 - I transform 'manually' all the vertices with the current WORLD
315 matrix and store them in the vertex buffer
316 - during the rasterization phase, the WORLD matrix will be set to
317 the Identity matrix */
319 /* Enough for the moment */
320 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
) {
322 D3DVERTEX
*src
= ((LPD3DVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
323 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
324 D3DMATRIX
*mat2
= lpDevice
->world_mat
;
327 D3DVIEWPORT
* Viewport
= &lpViewport
->viewports
.vp1
;
329 if (TRACE_ON(ddraw
)) {
330 TRACE(" Projection Matrix : (%p)\n", lpDevice
->proj_mat
);
331 dump_D3DMATRIX(lpDevice
->proj_mat
);
332 TRACE(" View Matrix : (%p)\n", lpDevice
->view_mat
);
333 dump_D3DMATRIX(lpDevice
->view_mat
);
334 TRACE(" World Matrix : (%p)\n", lpDevice
->world_mat
);
335 dump_D3DMATRIX(lpDevice
->world_mat
);
338 multiply_matrix(&mat
,lpDevice
->view_mat
,lpDevice
->world_mat
);
339 multiply_matrix(&mat
,lpDevice
->proj_mat
,&mat
);
341 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
342 /* Normals transformation */
343 nx
= (src
->u4
.nx
* mat2
->_11
) + (src
->u5
.ny
* mat2
->_21
) + (src
->u6
.nz
* mat2
->_31
);
344 ny
= (src
->u4
.nx
* mat2
->_12
) + (src
->u5
.ny
* mat2
->_22
) + (src
->u6
.nz
* mat2
->_32
);
345 nz
= (src
->u4
.nx
* mat2
->_13
) + (src
->u5
.ny
* mat2
->_23
) + (src
->u6
.nz
* mat2
->_33
);
347 /* No lighting yet */
348 dst
->u5
.color
= 0xFFFFFFFF; /* Opaque white */
349 dst
->u6
.specular
= 0xFF000000; /* No specular and no fog factor */
351 dst
->u7
.tu
= src
->u7
.tu
;
352 dst
->u8
.tv
= src
->u8
.tv
;
354 /* Now, the matrix multiplication */
355 dst
->u1
.sx
= (src
->u1
.x
* mat
._11
) + (src
->u2
.y
* mat
._21
) + (src
->u3
.z
* mat
._31
) + (1.0 * mat
._41
);
356 dst
->u2
.sy
= (src
->u1
.x
* mat
._12
) + (src
->u2
.y
* mat
._22
) + (src
->u3
.z
* mat
._32
) + (1.0 * mat
._42
);
357 dst
->u3
.sz
= (src
->u1
.x
* mat
._13
) + (src
->u2
.y
* mat
._23
) + (src
->u3
.z
* mat
._33
) + (1.0 * mat
._43
);
358 dst
->u4
.rhw
= (src
->u1
.x
* mat
._14
) + (src
->u2
.y
* mat
._24
) + (src
->u3
.z
* mat
._34
) + (1.0 * mat
._44
);
360 dst
->u1
.sx
= dst
->u1
.sx
/ dst
->u4
.rhw
* Viewport
->dwWidth
/ 2
361 + Viewport
->dwX
+ Viewport
->dwWidth
/ 2;
362 dst
->u2
.sy
= dst
->u2
.sy
/ dst
->u4
.rhw
* Viewport
->dwHeight
/ 2
363 + Viewport
->dwY
+ Viewport
->dwHeight
/ 2;
364 dst
->u3
.sz
/= dst
->u4
.rhw
;
365 dst
->u4
.rhw
= 1 / dst
->u4
.rhw
;
371 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORM
) {
373 D3DLVERTEX
*src
= ((LPD3DLVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
374 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
376 D3DVIEWPORT
* Viewport
= &lpViewport
->viewports
.vp1
;
378 if (TRACE_ON(ddraw
)) {
379 TRACE(" Projection Matrix : (%p)\n", lpDevice
->proj_mat
);
380 dump_D3DMATRIX(lpDevice
->proj_mat
);
381 TRACE(" View Matrix : (%p)\n", lpDevice
->view_mat
);
382 dump_D3DMATRIX(lpDevice
->view_mat
);
383 TRACE(" World Matrix : (%p)\n", &mat
);
384 dump_D3DMATRIX(&mat
);
387 multiply_matrix(&mat
,lpDevice
->view_mat
,lpDevice
->world_mat
);
388 multiply_matrix(&mat
,lpDevice
->proj_mat
,&mat
);
390 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
391 dst
->u5
.color
= src
->u4
.color
;
392 dst
->u6
.specular
= src
->u5
.specular
;
393 dst
->u7
.tu
= src
->u6
.tu
;
394 dst
->u8
.tv
= src
->u7
.tv
;
396 /* Now, the matrix multiplication */
397 dst
->u1
.sx
= (src
->u1
.x
* mat
._11
) + (src
->u2
.y
* mat
._21
) + (src
->u3
.z
* mat
._31
) + (1.0 * mat
._41
);
398 dst
->u2
.sy
= (src
->u1
.x
* mat
._12
) + (src
->u2
.y
* mat
._22
) + (src
->u3
.z
* mat
._32
) + (1.0 * mat
._42
);
399 dst
->u3
.sz
= (src
->u1
.x
* mat
._13
) + (src
->u2
.y
* mat
._23
) + (src
->u3
.z
* mat
._33
) + (1.0 * mat
._43
);
400 dst
->u4
.rhw
= (src
->u1
.x
* mat
._14
) + (src
->u2
.y
* mat
._24
) + (src
->u3
.z
* mat
._34
) + (1.0 * mat
._44
);
402 dst
->u1
.sx
/= dst
->u4
.rhw
* Viewport
->dvScaleX
* Viewport
->dwWidth
/ 2 + Viewport
->dwX
;
403 dst
->u2
.sy
/= dst
->u4
.rhw
* Viewport
->dvScaleY
* Viewport
->dwHeight
/ 2 + Viewport
->dwY
;
404 dst
->u3
.sz
/= dst
->u4
.rhw
;
405 dst
->u4
.rhw
= 1 / dst
->u4
.rhw
;
410 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_COPY
) {
411 D3DTLVERTEX
*src
= ((LPD3DTLVERTEX
) ((char *)This
->desc
.lpData
+ vs
)) + ci
->wStart
;
412 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
414 memcpy(dst
, src
, ci
->dwCount
* sizeof(D3DTLVERTEX
));
416 ERR("Unhandled vertex processing !\n");
423 case D3DOP_TEXTURELOAD
: {
424 WARN("TEXTURELOAD-s (%d)\n", count
);
426 instr
+= count
* size
;
430 TRACE("EXIT (%d)\n", count
);
431 /* We did this instruction */
437 case D3DOP_BRANCHFORWARD
: {
439 TRACE("BRANCHFORWARD (%d)\n", count
);
441 for (i
= 0; i
< count
; i
++) {
442 LPD3DBRANCH ci
= (LPD3DBRANCH
) instr
;
444 if ((This
->data
.dsStatus
.dwStatus
& ci
->dwMask
) == ci
->dwValue
) {
446 TRACE(" Branch to %ld\n", ci
->dwOffset
);
447 instr
= (char*)current
+ ci
->dwOffset
;
452 TRACE(" Branch to %ld\n", ci
->dwOffset
);
453 instr
= (char*)current
+ ci
->dwOffset
;
463 WARN("SPAN-s (%d)\n", count
);
465 instr
+= count
* size
;
468 case D3DOP_SETSTATUS
: {
470 TRACE("SETSTATUS (%d)\n", count
);
472 for (i
= 0; i
< count
; i
++) {
473 LPD3DSTATUS ci
= (LPD3DSTATUS
) instr
;
475 This
->data
.dsStatus
= *ci
;
482 ERR("Unhandled OpCode %d !!!\n",current
->bOpcode
);
483 /* Try to save ... */
484 instr
+= count
* size
;
494 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface
,
498 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
499 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_guid(riid
), obp
);
503 if ( IsEqualGUID( &IID_IUnknown
, riid
) ) {
504 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
506 TRACE(" Creating IUnknown interface at %p.\n", *obp
);
509 if ( IsEqualGUID( &IID_IDirect3DMaterial
, riid
) ) {
510 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
511 *obp
= ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
);
512 TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obp
);
515 FIXME("(%p): interface for IID %s NOT found!\n", This
, debugstr_guid(riid
));
516 return OLE_E_ENUM_NOMORE
;
520 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface
)
522 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
523 FIXME("(%p/%p)->()incrementing from %lu.\n", This
, iface
, This
->ref
);
524 return ++(This
->ref
);
528 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface
)
530 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
531 TRACE("(%p/%p)->()decrementing from %lu.\n", This
, iface
, This
->ref
);
532 if (!--(This
->ref
)) {
533 if ((This
->desc
.lpData
!= NULL
) && This
->need_free
)
534 HeapFree(GetProcessHeap(),0,This
->desc
.lpData
);
535 if (This
->vertex_data
!= NULL
)
536 HeapFree(GetProcessHeap(),0,This
->vertex_data
);
537 if (This
->indices
!= NULL
)
538 HeapFree(GetProcessHeap(),0,This
->indices
);
539 HeapFree(GetProcessHeap(),0,This
);
547 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface
,
548 LPDIRECT3DDEVICE lpDirect3DDevice
,
549 LPD3DEXECUTEBUFFERDESC lpDesc
)
551 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
552 TRACE("(%p/%p)->(%p,%p) no-op....\n", This
, iface
, lpDirect3DDevice
, lpDesc
);
557 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface
,
558 LPD3DEXECUTEBUFFERDESC lpDesc
)
560 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
562 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpDesc
);
564 dwSize
= lpDesc
->dwSize
;
565 memset(lpDesc
, 0, dwSize
);
566 memcpy(lpDesc
, &This
->desc
, dwSize
);
568 if (TRACE_ON(ddraw
)) {
569 TRACE(" Returning description : \n");
570 _dump_D3DEXECUTEBUFFERDESC(lpDesc
);
576 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface
)
578 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
579 TRACE("(%p/%p)->() no-op...\n", This
, iface
);
584 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
585 LPD3DEXECUTEDATA lpData
)
587 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
589 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
591 memcpy(&This
->data
, lpData
, lpData
->dwSize
);
593 /* Get the number of vertices in the execute buffer */
594 nbvert
= This
->data
.dwVertexCount
;
596 /* Prepares the transformed vertex buffer */
597 if (This
->vertex_data
!= NULL
)
598 HeapFree(GetProcessHeap(), 0, This
->vertex_data
);
599 This
->vertex_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbvert
* sizeof(D3DTLVERTEX
));
601 if (TRACE_ON(ddraw
)) {
602 _dump_executedata(lpData
);
609 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
610 LPD3DEXECUTEDATA lpData
)
612 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
614 TRACE("(%p/%p)->(%p): stub!\n", This
, iface
, lpData
);
616 dwSize
= lpData
->dwSize
;
617 memset(lpData
, 0, dwSize
);
618 memcpy(lpData
, &This
->data
, dwSize
);
620 if (TRACE_ON(ddraw
)) {
621 TRACE("Returning data : \n");
622 _dump_executedata(lpData
);
629 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface
,
631 LPD3DVALIDATECALLBACK lpFunc
,
635 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
636 FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This
, iface
, lpdwOffset
, lpFunc
, lpUserArg
, dwReserved
);
641 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface
,
644 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
645 TRACE("(%p/%p)->(%08lx) no-op...\n", This
, iface
, dwDummy
);
649 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
650 # define XCAST(fun) (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
652 # define XCAST(fun) (void*)
655 ICOM_VTABLE(IDirect3DExecuteBuffer
) VTABLE_IDirect3DExecuteBuffer
=
657 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
658 XCAST(QueryInterface
) Main_IDirect3DExecuteBufferImpl_1_QueryInterface
,
659 XCAST(AddRef
) Main_IDirect3DExecuteBufferImpl_1_AddRef
,
660 XCAST(Release
) Main_IDirect3DExecuteBufferImpl_1_Release
,
661 XCAST(Initialize
) Main_IDirect3DExecuteBufferImpl_1_Initialize
,
662 XCAST(Lock
) Main_IDirect3DExecuteBufferImpl_1_Lock
,
663 XCAST(Unlock
) Main_IDirect3DExecuteBufferImpl_1_Unlock
,
664 XCAST(SetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData
,
665 XCAST(GetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData
,
666 XCAST(Validate
) Main_IDirect3DExecuteBufferImpl_1_Validate
,
667 XCAST(Optimize
) Main_IDirect3DExecuteBufferImpl_1_Optimize
,
670 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
675 HRESULT
d3dexecutebuffer_create(IDirect3DExecuteBufferImpl
**obj
, IDirectDrawImpl
*d3d
, IDirect3DDeviceImpl
*d3ddev
, LPD3DEXECUTEBUFFERDESC lpDesc
)
677 IDirect3DExecuteBufferImpl
* object
;
679 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DExecuteBufferImpl
));
681 ICOM_INIT_INTERFACE(object
, IDirect3DExecuteBuffer
, VTABLE_IDirect3DExecuteBuffer
);
685 object
->d3ddev
= d3ddev
;
687 /* Initializes memory */
688 memcpy(&object
->desc
, lpDesc
, lpDesc
->dwSize
);
690 /* No buffer given */
691 if ((object
->desc
.dwFlags
& D3DDEB_LPDATA
) == 0)
692 object
->desc
.lpData
= NULL
;
694 /* No buffer size given */
695 if ((lpDesc
->dwFlags
& D3DDEB_BUFSIZE
) == 0)
696 object
->desc
.dwBufferSize
= 0;
698 /* Create buffer if asked */
699 if ((object
->desc
.lpData
== NULL
) && (object
->desc
.dwBufferSize
> 0)) {
700 object
->need_free
= TRUE
;
701 object
->desc
.lpData
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,object
->desc
.dwBufferSize
);
703 object
->need_free
= FALSE
;
706 /* No vertices for the moment */
707 object
->vertex_data
= NULL
;
709 object
->desc
.dwFlags
|= D3DDEB_LPDATA
;
711 object
->execute
= execute
;
713 object
->indices
= NULL
;
714 object
->nb_indices
= 0;
718 TRACE(" creating implementation at %p.\n", *obj
);