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
30 #include "wine/debug.h"
32 #include "d3d_private.h"
33 #include "mesa_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
37 /* Structure to store the 'semi transformed' vertices */
65 static void _dump_d3dstatus(LPD3DSTATUS lpStatus
) {
69 static void _dump_executedata(LPD3DEXECUTEDATA lpData
) {
70 DPRINTF("dwSize : %ld\n", lpData
->dwSize
);
71 DPRINTF("Vertex Offset : %ld Count : %ld\n", lpData
->dwVertexOffset
, lpData
->dwVertexCount
);
72 DPRINTF("Instruction Offset : %ld Length : %ld\n", lpData
->dwInstructionOffset
, lpData
->dwInstructionLength
);
73 DPRINTF("HVertex Offset : %ld\n", lpData
->dwHVertexOffset
);
74 _dump_d3dstatus(&(lpData
->dsStatus
));
77 static void _dump_D3DEXECUTEBUFFERDESC(LPD3DEXECUTEBUFFERDESC lpDesc
) {
81 #define DO_VERTEX(index) \
83 glTexCoord2f(vx[index].u, \
85 glNormal3f(vx[index].nx, \
88 glVertex4f(vx[index].x, \
93 TRACE(" V: %f %f %f %f (%f %f %f) (%f %f)\n", \
94 vx[index].x, vx[index].y, vx[index].z, vx[index].w, \
95 vx[index].nx, vx[index].ny, vx[index].nz, \
96 vx[index].u, vx[index].v); \
99 #define DO_LVERTEX(index) \
101 DWORD col = l_vx[index].c; \
103 glColor3f(((col >> 16) & 0xFF) / 255.0, \
104 ((col >> 8) & 0xFF) / 255.0, \
105 ((col >> 0) & 0xFF) / 255.0); \
106 glTexCoord2f(l_vx[index].u, \
108 glVertex4f(l_vx[index].x, \
113 TRACE(" LV: %f %f %f %f (%02lx %02lx %02lx) (%f %f)\n", \
114 l_vx[index].x, l_vx[index].y, l_vx[index].z, l_vx[index].w, \
115 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
116 l_vx[index].u, l_vx[index].v); \
119 #define DO_TLVERTEX(index) \
121 D3DTLVERTEX *vx = &(tl_vx[index]); \
122 DWORD col = vx->u5.color; \
124 glColor3f(((col >> 16) & 0xFF) / 255.0, \
125 ((col >> 8) & 0xFF) / 255.0, \
126 ((col >> 0) & 0xFF) / 255.0); \
127 glTexCoord2f(vx->u7.tu, vx->u8.tv); \
128 if (vx->u4.rhw < 0.01) \
129 glVertex3f(vx->u1.sx, \
133 glVertex4f(vx->u1.sx / vx->u4.rhw, \
134 vx->u2.sy / vx->u4.rhw, \
135 vx->u3.sz / vx->u4.rhw, \
137 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
138 vx->u1.sx, vx->u2.sy, vx->u3.sz, \
139 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
140 vx->u7.tu, vx->u8.tv, vx->u4.rhw); \
143 #define TRIANGLE_LOOP(macro) \
145 glBegin(GL_TRIANGLES); \
146 for (i = 0; i < count; i++) { \
147 LPD3DTRIANGLE ci = (LPD3DTRIANGLE) instr; \
149 TRACE(" v1: %d v2: %d v3: %d\n", \
150 ci->u1.v1, ci->u2.v2, ci->u3.v3); \
151 TRACE(" Flags : "); \
152 if (TRACE_ON(ddraw)) { \
154 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) \
155 DPRINTF("EDGEENABLE1 "); \
156 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2) \
157 DPRINTF("EDGEENABLE2 "); \
158 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) \
159 DPRINTF("EDGEENABLE3 "); \
161 /* Strips / Fans */ \
162 if (ci->wFlags == D3DTRIFLAG_EVEN) \
164 if (ci->wFlags == D3DTRIFLAG_ODD) \
166 if (ci->wFlags == D3DTRIFLAG_START) \
168 if ((ci->wFlags > 0) && (ci->wFlags < 30)) \
169 DPRINTF("STARTFLAT(%d) ", ci->wFlags); \
173 /* Draw the triangle */ \
184 static void execute(IDirect3DExecuteBufferImpl
*This
,
185 IDirect3DDeviceImpl
*lpDevice
,
186 IDirect3DViewportImpl
*lpViewport
)
188 IDirect3DDeviceGLImpl
* lpDeviceGL
= (IDirect3DDeviceGLImpl
*) lpDevice
;
189 /* DWORD bs = This->desc.dwBufferSize; */
190 DWORD vs
= This
->data
.dwVertexOffset
;
191 /* DWORD vc = This->data.dwVertexCount; */
192 DWORD is
= This
->data
.dwInstructionOffset
;
193 /* DWORD il = This->data.dwInstructionLength; */
195 void *instr
= This
->desc
.lpData
+ is
;
197 /* Should check if the viewport was added or not to the device */
199 /* Activate the viewport */
200 lpViewport
->active_device
= lpDevice
;
201 lpViewport
->activate(lpViewport
);
203 TRACE("ExecuteData : \n");
205 _dump_executedata(&(This
->data
));
210 LPD3DINSTRUCTION current
= (LPD3DINSTRUCTION
) instr
;
214 count
= current
->wCount
;
215 size
= current
->bSize
;
216 instr
+= sizeof(D3DINSTRUCTION
);
218 switch (current
->bOpcode
) {
220 TRACE("POINT-s (%d)\n", count
);
221 instr
+= count
* size
;
225 TRACE("LINE-s (%d)\n", count
);
226 instr
+= count
* size
;
229 case D3DOP_TRIANGLE
: {
231 OGL_Vertex
*vx
= (OGL_Vertex
*) This
->vertex_data
;
232 OGL_LVertex
*l_vx
= (OGL_LVertex
*) This
->vertex_data
;
233 D3DTLVERTEX
*tl_vx
= (D3DTLVERTEX
*) This
->vertex_data
;
234 TRACE("TRIANGLE (%d)\n", count
);
236 switch (This
->vertex_type
) {
238 /* This time, there is lighting */
239 glEnable(GL_LIGHTING
);
241 /* Use given matrixes */
242 glMatrixMode(GL_MODELVIEW
);
243 glLoadIdentity(); /* The model transformation was done during the
244 transformation phase */
245 glMatrixMode(GL_PROJECTION
);
246 TRACE(" Projection Matrix : (%p)\n", lpDeviceGL
->proj_mat
);
247 dump_mat(lpDeviceGL
->proj_mat
);
248 TRACE(" View Matrix : (%p)\n", lpDeviceGL
->view_mat
);
249 dump_mat(lpDeviceGL
->view_mat
);
251 /* Although z axis is inverted between OpenGL and Direct3D, the z projected coordinates
252 are always 0.0 at the front viewing volume and 1.0 at the back with Direct 3D and with
253 the default behaviour of OpenGL. So, no additional transformation is required. */
254 glLoadMatrixf((float *) lpDeviceGL
->proj_mat
);
255 glMultMatrixf((float *) lpDeviceGL
->view_mat
);
260 glDisable(GL_LIGHTING
);
262 /* Use given matrixes */
263 glMatrixMode(GL_MODELVIEW
);
264 glLoadIdentity(); /* The model transformation was done during the
265 transformation phase */
266 glMatrixMode(GL_PROJECTION
);
268 TRACE(" Projection Matrix : (%p)\n", lpDeviceGL
->proj_mat
);
269 dump_mat(lpDeviceGL
->proj_mat
);
270 TRACE(" View Matrix : (%p)\n", lpDeviceGL
->view_mat
);
271 dump_mat(lpDeviceGL
->view_mat
);
273 /* Although z axis is inverted between OpenGL and Direct3D, the z projected coordinates
274 are always 0 at the front viewing volume and 1 at the back with Direct 3D and with
275 the default behaviour of OpenGL. So, no additional transformation is required. */
276 glLoadMatrixf((float *) lpDeviceGL
->proj_mat
);
277 glMultMatrixf((float *) lpDeviceGL
->view_mat
);
280 case D3DVT_TLVERTEX
: {
281 GLdouble height
, width
, minZ
, maxZ
;
283 /* First, disable lighting */
284 glDisable(GL_LIGHTING
);
286 /* Then do not put any transformation matrixes */
287 glMatrixMode(GL_MODELVIEW
);
289 glMatrixMode(GL_PROJECTION
);
292 if (lpViewport
== NULL
) {
293 ERR("No current viewport !\n");
294 /* Using standard values */
300 height
= (GLdouble
) lpViewport
->viewports
.vp1
.dwHeight
;
301 width
= (GLdouble
) lpViewport
->viewports
.vp1
.dwWidth
;
302 minZ
= (GLdouble
) lpViewport
->viewports
.vp1
.dvMinZ
;
303 maxZ
= (GLdouble
) lpViewport
->viewports
.vp1
.dvMaxZ
;
306 /* I do not know why, but many Dx 3.0 games have minZ = maxZ = 0.0 */
311 glOrtho(0.0, width
, height
, 0.0, -minZ
, -maxZ
);
315 ERR("Unhandled vertex type !\n");
319 switch (This
->vertex_type
) {
321 TRIANGLE_LOOP(DO_VERTEX
);
325 TRIANGLE_LOOP(DO_LVERTEX
);
329 TRIANGLE_LOOP(DO_TLVERTEX
);
333 ERR("Unhandled vertex type !\n");
337 case D3DOP_MATRIXLOAD
:
338 TRACE("MATRIXLOAD-s (%d)\n", count
);
339 instr
+= count
* size
;
342 case D3DOP_MATRIXMULTIPLY
: {
344 TRACE("MATRIXMULTIPLY (%d)\n", count
);
346 for (i
= 0; i
< count
; i
++) {
347 LPD3DMATRIXMULTIPLY ci
= (LPD3DMATRIXMULTIPLY
) instr
;
348 LPD3DMATRIX a
= (LPD3DMATRIX
) ci
->hDestMatrix
;
349 LPD3DMATRIX b
= (LPD3DMATRIX
) ci
->hSrcMatrix1
;
350 LPD3DMATRIX c
= (LPD3DMATRIX
) ci
->hSrcMatrix2
;
352 TRACE(" Dest : %08lx Src1 : %08lx Src2 : %08lx\n",
353 ci
->hDestMatrix
, ci
->hSrcMatrix1
, ci
->hSrcMatrix2
);
355 /* Do the multiplication..
356 As I am VERY lazy, I let OpenGL do the multiplication for me */
357 glMatrixMode(GL_PROJECTION
);
358 /* Save the current matrix */
360 /* Load Matrix one and do the multiplication */
361 glLoadMatrixf((float *) c
);
362 glMultMatrixf((float *) b
);
363 glGetFloatv(GL_PROJECTION_MATRIX
, (float *) a
);
364 /* Restore the current matrix */
371 case D3DOP_STATETRANSFORM
: {
373 TRACE("STATETRANSFORM (%d)\n", count
);
375 for (i
= 0; i
< count
; i
++) {
376 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
378 /* Handle the state transform */
379 switch (ci
->u1
.dtstTransformStateType
) {
380 case D3DTRANSFORMSTATE_WORLD
: {
381 TRACE(" WORLD (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
382 lpDeviceGL
->world_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
385 case D3DTRANSFORMSTATE_VIEW
: {
386 TRACE(" VIEW (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
387 lpDeviceGL
->view_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
390 case D3DTRANSFORMSTATE_PROJECTION
: {
391 TRACE(" PROJECTION (%p)\n", (D3DMATRIX
*) ci
->u2
.dwArg
[0]);
392 lpDeviceGL
->proj_mat
= (D3DMATRIX
*) ci
->u2
.dwArg
[0];
396 ERR(" Unhandled state transformation !! (%d)\n", (int) ci
->u1
.dtstTransformStateType
);
404 case D3DOP_STATELIGHT
: {
406 TRACE("STATELIGHT (%d)\n", count
);
408 for (i
= 0; i
< count
; i
++) {
409 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
411 /* Handle the state transform */
412 switch (ci
->u1
.dlstLightStateType
) {
413 case D3DLIGHTSTATE_MATERIAL
: {
414 IDirect3DMaterialImpl
* mat
= (IDirect3DMaterialImpl
*) ci
->u2
.dwArg
[0];
415 TRACE(" MATERIAL\n");
420 TRACE(" bad Material Handle\n");
424 case D3DLIGHTSTATE_AMBIENT
: {
426 DWORD dwLightState
= ci
->u2
.dwArg
[0];
429 light
[0] = ((dwLightState
>> 16) & 0xFF) / 255.0;
430 light
[1] = ((dwLightState
>> 8) & 0xFF) / 255.0;
431 light
[2] = ((dwLightState
>> 0) & 0xFF) / 255.0;
433 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, (float *) light
);
435 TRACE(" R:%02lx G:%02lx B:%02lx A:%02lx\n",
436 ((dwLightState
>> 16) & 0xFF),
437 ((dwLightState
>> 8) & 0xFF),
438 ((dwLightState
>> 0) & 0xFF),
439 ((dwLightState
>> 24) & 0xFF));
442 case D3DLIGHTSTATE_COLORMODEL
: {
443 TRACE(" COLORMODEL\n");
446 case D3DLIGHTSTATE_FOGMODE
: {
450 case D3DLIGHTSTATE_FOGSTART
: {
451 TRACE(" FOGSTART\n");
454 case D3DLIGHTSTATE_FOGEND
: {
458 case D3DLIGHTSTATE_FOGDENSITY
: {
459 TRACE(" FOGDENSITY\n");
463 ERR(" Unhandled light state !! (%d)\n", (int) ci
->u1
.dlstLightStateType
);
470 case D3DOP_STATERENDER
: {
472 TRACE("STATERENDER (%d)\n", count
);
474 for (i
= 0; i
< count
; i
++) {
475 LPD3DSTATE ci
= (LPD3DSTATE
) instr
;
477 /* Handle the state transform */
478 set_render_state(ci
->u1
.drstRenderStateType
, ci
->u2
.dwArg
[0], &(lpDeviceGL
->render_state
));
484 case D3DOP_PROCESSVERTICES
: {
486 TRACE("PROCESSVERTICES (%d)\n", count
);
488 for (i
= 0; i
< count
; i
++) {
489 LPD3DPROCESSVERTICES ci
= (LPD3DPROCESSVERTICES
) instr
;
491 TRACE(" Start : %d Dest : %d Count : %ld\n",
492 ci
->wStart
, ci
->wDest
, ci
->dwCount
);
494 if (TRACE_ON(ddraw
)) {
495 if (ci
->dwFlags
& D3DPROCESSVERTICES_COPY
)
497 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
499 if (ci
->dwFlags
== D3DPROCESSVERTICES_OPMASK
)
501 if (ci
->dwFlags
& D3DPROCESSVERTICES_TRANSFORM
)
502 DPRINTF("TRANSFORM ");
503 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
)
504 DPRINTF("TRANSFORMLIGHT ");
505 if (ci
->dwFlags
& D3DPROCESSVERTICES_UPDATEEXTENTS
)
506 DPRINTF("UPDATEEXTENTS ");
510 /* This is where doing Direct3D on top on OpenGL is quite difficult.
511 This method transforms a set of vertices using the CURRENT state
512 (lighting, projection, ...) but does not rasterize them.
513 They will only be put on screen later (with the POINT / LINE and
514 TRIANGLE op-codes). The problem is that you can have a triangle
515 with each point having been transformed using another state...
517 In this implementation, I will emulate only ONE thing : each
518 vertex can have its own "WORLD" transformation (this is used in the
519 TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
520 execute buffer use the same state.
522 If I find applications that change other states, I will try to do a
523 more 'fine-tuned' state emulation (but I may become quite tricky if
524 it changes a light position in the middle of a triangle).
526 In this case, a 'direct' approach (i.e. without using OpenGL, but
527 writing our own 3D rasterizer) would be easier. */
529 /* The current method (with the hypothesis that only the WORLD matrix
530 will change between two points) is like this :
531 - I transform 'manually' all the vertices with the current WORLD
532 matrix and store them in the vertex buffer
533 - during the rasterization phase, the WORLD matrix will be set to
534 the Identity matrix */
536 /* Enough for the moment */
537 if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORMLIGHT
) {
539 D3DVERTEX
*src
= ((LPD3DVERTEX
) (This
->desc
.lpData
+ vs
)) + ci
->wStart
;
540 OGL_Vertex
*dst
= ((OGL_Vertex
*) (This
->vertex_data
)) + ci
->wDest
;
541 D3DMATRIX
*mat
= lpDeviceGL
->world_mat
;
543 TRACE(" World Matrix : (%p)\n", mat
);
546 This
->vertex_type
= D3DVT_VERTEX
;
548 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
549 /* For the moment, no normal transformation... */
550 dst
->nx
= (src
->u4
.nx
* mat
->_11
) + (src
->u5
.ny
* mat
->_21
) + (src
->u6
.nz
* mat
->_31
);
551 dst
->ny
= (src
->u4
.nx
* mat
->_12
) + (src
->u5
.ny
* mat
->_22
) + (src
->u6
.nz
* mat
->_32
);
552 dst
->nz
= (src
->u4
.nx
* mat
->_13
) + (src
->u5
.ny
* mat
->_23
) + (src
->u6
.nz
* mat
->_33
);
557 /* Now, the matrix multiplication */
558 dst
->x
= (src
->u1
.x
* mat
->_11
) + (src
->u2
.y
* mat
->_21
) + (src
->u3
.z
* mat
->_31
) + (1.0 * mat
->_41
);
559 dst
->y
= (src
->u1
.x
* mat
->_12
) + (src
->u2
.y
* mat
->_22
) + (src
->u3
.z
* mat
->_32
) + (1.0 * mat
->_42
);
560 dst
->z
= (src
->u1
.x
* mat
->_13
) + (src
->u2
.y
* mat
->_23
) + (src
->u3
.z
* mat
->_33
) + (1.0 * mat
->_43
);
561 dst
->w
= (src
->u1
.x
* mat
->_14
) + (src
->u2
.y
* mat
->_24
) + (src
->u3
.z
* mat
->_34
) + (1.0 * mat
->_44
);
566 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_TRANSFORM
) {
568 D3DLVERTEX
*src
= ((LPD3DLVERTEX
) (This
->desc
.lpData
+ vs
)) + ci
->wStart
;
569 OGL_LVertex
*dst
= ((OGL_LVertex
*) (This
->vertex_data
)) + ci
->wDest
;
570 D3DMATRIX
*mat
= lpDeviceGL
->world_mat
;
572 TRACE(" World Matrix : (%p)\n", mat
);
575 This
->vertex_type
= D3DVT_LVERTEX
;
577 for (nb
= 0; nb
< ci
->dwCount
; nb
++) {
578 dst
->c
= src
->u4
.color
;
579 dst
->sc
= src
->u5
.specular
;
583 /* Now, the matrix multiplication */
584 dst
->x
= (src
->u1
.x
* mat
->_11
) + (src
->u2
.y
* mat
->_21
) + (src
->u3
.z
* mat
->_31
) + (1.0 * mat
->_41
);
585 dst
->y
= (src
->u1
.x
* mat
->_12
) + (src
->u2
.y
* mat
->_22
) + (src
->u3
.z
* mat
->_32
) + (1.0 * mat
->_42
);
586 dst
->z
= (src
->u1
.x
* mat
->_13
) + (src
->u2
.y
* mat
->_23
) + (src
->u3
.z
* mat
->_33
) + (1.0 * mat
->_43
);
587 dst
->w
= (src
->u1
.x
* mat
->_14
) + (src
->u2
.y
* mat
->_24
) + (src
->u3
.z
* mat
->_34
) + (1.0 * mat
->_44
);
592 } else if (ci
->dwFlags
== D3DPROCESSVERTICES_COPY
) {
593 D3DTLVERTEX
*src
= ((LPD3DTLVERTEX
) (This
->desc
.lpData
+ vs
)) + ci
->wStart
;
594 D3DTLVERTEX
*dst
= ((LPD3DTLVERTEX
) (This
->vertex_data
)) + ci
->wDest
;
596 This
->vertex_type
= D3DVT_TLVERTEX
;
598 memcpy(dst
, src
, ci
->dwCount
* sizeof(D3DTLVERTEX
));
600 ERR("Unhandled vertex processing !\n");
607 case D3DOP_TEXTURELOAD
: {
608 TRACE("TEXTURELOAD-s (%d)\n", count
);
610 instr
+= count
* size
;
614 TRACE("EXIT (%d)\n", count
);
615 /* We did this instruction */
621 case D3DOP_BRANCHFORWARD
: {
623 TRACE("BRANCHFORWARD (%d)\n", count
);
625 for (i
= 0; i
< count
; i
++) {
626 LPD3DBRANCH ci
= (LPD3DBRANCH
) instr
;
628 if ((This
->data
.dsStatus
.dwStatus
& ci
->dwMask
) == ci
->dwValue
) {
630 TRACE(" Should branch to %ld\n", ci
->dwOffset
);
634 TRACE(" Should branch to %ld\n", ci
->dwOffset
);
643 TRACE("SPAN-s (%d)\n", count
);
645 instr
+= count
* size
;
648 case D3DOP_SETSTATUS
: {
650 TRACE("SETSTATUS (%d)\n", count
);
652 for (i
= 0; i
< count
; i
++) {
653 LPD3DSTATUS ci
= (LPD3DSTATUS
) instr
;
655 This
->data
.dsStatus
= *ci
;
662 ERR("Unhandled OpCode !!!\n");
663 /* Try to save ... */
664 instr
+= count
* size
;
674 Main_IDirect3DExecuteBufferImpl_1_QueryInterface(LPDIRECT3DEXECUTEBUFFER iface
,
678 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
679 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_guid(riid
), obp
);
683 if ( IsEqualGUID( &IID_IUnknown
, riid
) ) {
684 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
686 TRACE(" Creating IUnknown interface at %p.\n", *obp
);
689 if ( IsEqualGUID( &IID_IDirect3DMaterial
, riid
) ) {
690 IDirect3DExecuteBuffer_AddRef(ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
));
691 *obp
= ICOM_INTERFACE(This
, IDirect3DExecuteBuffer
);
692 TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obp
);
695 FIXME("(%p): interface for IID %s NOT found!\n", This
, debugstr_guid(riid
));
696 return OLE_E_ENUM_NOMORE
;
700 Main_IDirect3DExecuteBufferImpl_1_AddRef(LPDIRECT3DEXECUTEBUFFER iface
)
702 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
703 FIXME("(%p/%p)->()incrementing from %lu.\n", This
, iface
, This
->ref
);
704 return ++(This
->ref
);
708 Main_IDirect3DExecuteBufferImpl_1_Release(LPDIRECT3DEXECUTEBUFFER iface
)
710 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
711 TRACE("(%p/%p)->()decrementing from %lu.\n", This
, iface
, This
->ref
);
712 if (!--(This
->ref
)) {
713 if ((This
->desc
.lpData
!= NULL
) && This
->need_free
)
714 HeapFree(GetProcessHeap(),0,This
->desc
.lpData
);
715 if (This
->vertex_data
!= NULL
)
716 HeapFree(GetProcessHeap(),0,This
->vertex_data
);
717 HeapFree(GetProcessHeap(),0,This
);
725 Main_IDirect3DExecuteBufferImpl_1_Initialize(LPDIRECT3DEXECUTEBUFFER iface
,
726 LPDIRECT3DDEVICE lpDirect3DDevice
,
727 LPD3DEXECUTEBUFFERDESC lpDesc
)
729 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
730 TRACE("(%p/%p)->(%p,%p) no-op....\n", This
, iface
, lpDirect3DDevice
, lpDesc
);
735 Main_IDirect3DExecuteBufferImpl_1_Lock(LPDIRECT3DEXECUTEBUFFER iface
,
736 LPD3DEXECUTEBUFFERDESC lpDesc
)
738 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
740 TRACE("(%p/%p)->(%p): stub!\n", This
, iface
, lpDesc
);
742 dwSize
= lpDesc
->dwSize
;
743 memset(lpDesc
, 0, dwSize
);
744 memcpy(lpDesc
, &This
->desc
, dwSize
);
746 if (TRACE_ON(ddraw
)) {
747 TRACE(" Returning description : \n");
748 _dump_D3DEXECUTEBUFFERDESC(lpDesc
);
754 Main_IDirect3DExecuteBufferImpl_1_Unlock(LPDIRECT3DEXECUTEBUFFER iface
)
756 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
757 TRACE("(%p/%p)->() no-op...\n", This
, iface
);
762 Main_IDirect3DExecuteBufferImpl_1_SetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
763 LPD3DEXECUTEDATA lpData
)
765 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
767 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
769 memcpy(&This
->data
, lpData
, lpData
->dwSize
);
771 /* Get the number of vertices in the execute buffer */
772 nbvert
= This
->data
.dwVertexCount
;
774 /* Prepares the transformed vertex buffer */
775 if (This
->vertex_data
!= NULL
)
776 HeapFree(GetProcessHeap(), 0, This
->vertex_data
);
777 This
->vertex_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbvert
* sizeof(OGL_Vertex
));
779 if (TRACE_ON(ddraw
)) {
780 _dump_executedata(lpData
);
787 Main_IDirect3DExecuteBufferImpl_1_GetExecuteData(LPDIRECT3DEXECUTEBUFFER iface
,
788 LPD3DEXECUTEDATA lpData
)
790 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
792 TRACE("(%p/%p)->(%p): stub!\n", This
, iface
, lpData
);
794 dwSize
= lpData
->dwSize
;
795 memset(lpData
, 0, dwSize
);
796 memcpy(lpData
, &This
->data
, dwSize
);
798 if (TRACE_ON(ddraw
)) {
799 TRACE("Returning data : \n");
800 _dump_executedata(lpData
);
807 Main_IDirect3DExecuteBufferImpl_1_Validate(LPDIRECT3DEXECUTEBUFFER iface
,
809 LPD3DVALIDATECALLBACK lpFunc
,
813 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
814 FIXME("(%p/%p)->(%p,%p,%p,%08lx): stub!\n", This
, iface
, lpdwOffset
, lpFunc
, lpUserArg
, dwReserved
);
819 Main_IDirect3DExecuteBufferImpl_1_Optimize(LPDIRECT3DEXECUTEBUFFER iface
,
822 ICOM_THIS_FROM(IDirect3DExecuteBufferImpl
, IDirect3DExecuteBuffer
, iface
);
823 TRACE("(%p/%p)->(%08lx) no-op...\n", This
, iface
, dwDummy
);
827 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
828 # define XCAST(fun) (typeof(VTABLE_IDirect3DExecuteBuffer.fun))
830 # define XCAST(fun) (void*)
833 ICOM_VTABLE(IDirect3DExecuteBuffer
) VTABLE_IDirect3DExecuteBuffer
=
835 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
836 XCAST(QueryInterface
) Main_IDirect3DExecuteBufferImpl_1_QueryInterface
,
837 XCAST(AddRef
) Main_IDirect3DExecuteBufferImpl_1_AddRef
,
838 XCAST(Release
) Main_IDirect3DExecuteBufferImpl_1_Release
,
839 XCAST(Initialize
) Main_IDirect3DExecuteBufferImpl_1_Initialize
,
840 XCAST(Lock
) Main_IDirect3DExecuteBufferImpl_1_Lock
,
841 XCAST(Unlock
) Main_IDirect3DExecuteBufferImpl_1_Unlock
,
842 XCAST(SetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_SetExecuteData
,
843 XCAST(GetExecuteData
) Main_IDirect3DExecuteBufferImpl_1_GetExecuteData
,
844 XCAST(Validate
) Main_IDirect3DExecuteBufferImpl_1_Validate
,
845 XCAST(Optimize
) Main_IDirect3DExecuteBufferImpl_1_Optimize
,
848 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
853 HRESULT
d3dexecutebuffer_create(IDirect3DExecuteBufferImpl
**obj
, IDirect3DImpl
*d3d
, IDirect3DDeviceImpl
*d3ddev
, LPD3DEXECUTEBUFFERDESC lpDesc
)
855 IDirect3DExecuteBufferImpl
* object
;
857 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DExecuteBufferImpl
));
859 ICOM_INIT_INTERFACE(object
, IDirect3DExecuteBuffer
, VTABLE_IDirect3DExecuteBuffer
);
863 object
->d3ddev
= d3ddev
;
865 /* Initializes memory */
866 memcpy(&object
->desc
, lpDesc
, lpDesc
->dwSize
);
868 /* No buffer given */
869 if ((object
->desc
.dwFlags
& D3DDEB_LPDATA
) == 0)
870 object
->desc
.lpData
= NULL
;
872 /* No buffer size given */
873 if ((lpDesc
->dwFlags
& D3DDEB_BUFSIZE
) == 0)
874 object
->desc
.dwBufferSize
= 0;
876 /* Create buffer if asked */
877 if ((object
->desc
.lpData
== NULL
) && (object
->desc
.dwBufferSize
> 0)) {
878 object
->need_free
= TRUE
;
879 object
->desc
.lpData
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,object
->desc
.dwBufferSize
);
881 object
->need_free
= FALSE
;
884 /* No vertices for the moment */
885 object
->vertex_data
= NULL
;
887 object
->desc
.dwFlags
|= D3DDEB_LPDATA
;
889 object
->execute
= execute
;
893 TRACE(" creating implementation at %p.\n", *obj
);