1 /* Direct3D ExecuteBuffer
2 * Copyright (c) 1998-2004 Lionel ULMER
3 * Copyright (c) 2002-2004 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
6 * This file contains the implementation of IDirect3DExecuteBuffer.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
26 #include "ddraw_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
30 /*****************************************************************************
32 * _dump_D3DEXECUTEBUFFERDESC
34 * Debug functions which write the executebuffer data to the console
36 *****************************************************************************/
38 static void _dump_executedata(const D3DEXECUTEDATA
*lpData
) {
39 TRACE("dwSize : %d\n", lpData
->dwSize
);
40 TRACE("Vertex Offset : %d Count : %d\n", lpData
->dwVertexOffset
, lpData
->dwVertexCount
);
41 TRACE("Instruction Offset : %d Length : %d\n", lpData
->dwInstructionOffset
, lpData
->dwInstructionLength
);
42 TRACE("HVertex Offset : %d\n", lpData
->dwHVertexOffset
);
45 static void _dump_D3DEXECUTEBUFFERDESC(const D3DEXECUTEBUFFERDESC
*lpDesc
) {
46 TRACE("dwSize : %d\n", lpDesc
->dwSize
);
47 TRACE("dwFlags : %x\n", lpDesc
->dwFlags
);
48 TRACE("dwCaps : %x\n", lpDesc
->dwCaps
);
49 TRACE("dwBufferSize : %d\n", lpDesc
->dwBufferSize
);
50 TRACE("lpData : %p\n", lpDesc
->lpData
);
53 static void transform_vertex(D3DTLVERTEX
*dst
, const D3DMATRIX
*mat
,
54 const D3DVIEWPORT
*vp
, float x
, float y
, float z
)
56 dst
->u1
.sx
= (x
* mat
->_11
) + (y
* mat
->_21
) + (z
* mat
->_31
) + mat
->_41
;
57 dst
->u2
.sy
= (x
* mat
->_12
) + (y
* mat
->_22
) + (z
* mat
->_32
) + mat
->_42
;
58 dst
->u3
.sz
= (x
* mat
->_13
) + (y
* mat
->_23
) + (z
* mat
->_33
) + mat
->_43
;
59 dst
->u4
.rhw
= (x
* mat
->_14
) + (y
* mat
->_24
) + (z
* mat
->_34
) + mat
->_44
;
61 dst
->u1
.sx
= dst
->u1
.sx
/ dst
->u4
.rhw
* vp
->dvScaleX
+ vp
->dwX
+ vp
->dwWidth
/ 2;
62 dst
->u2
.sy
= -dst
->u2
.sy
/ dst
->u4
.rhw
* vp
->dvScaleY
+ vp
->dwY
+ vp
->dwHeight
/ 2;
63 dst
->u3
.sz
/= dst
->u4
.rhw
;
64 dst
->u4
.rhw
= 1.0f
/ dst
->u4
.rhw
;
67 HRESULT
d3d_execute_buffer_execute(struct d3d_execute_buffer
*buffer
,
68 struct d3d_device
*device
, struct d3d_viewport
*viewport
)
70 DWORD vs
= buffer
->data
.dwVertexOffset
;
71 DWORD is
= buffer
->data
.dwInstructionOffset
;
72 char *instr
= (char *)buffer
->desc
.lpData
+ is
;
75 if (viewport
->active_device
!= device
)
77 WARN("Viewport %p active device is %p.\n",
78 viewport
, viewport
->active_device
);
79 return DDERR_INVALIDPARAMS
;
82 /* Activate the viewport */
83 viewport_activate(viewport
, FALSE
);
85 TRACE("ExecuteData :\n");
87 _dump_executedata(&(buffer
->data
));
91 D3DINSTRUCTION
*current
= (D3DINSTRUCTION
*)instr
;
95 count
= current
->wCount
;
96 size
= current
->bSize
;
97 instr
+= sizeof(D3DINSTRUCTION
);
99 switch (current
->bOpcode
) {
101 WARN("POINT-s (%d)\n", count
);
102 instr
+= count
* size
;
106 WARN("LINE-s (%d)\n", count
);
107 instr
+= count
* size
;
112 D3DTLVERTEX
*tl_vx
= buffer
->vertex_data
;
113 TRACE("TRIANGLE (%d)\n", count
);
115 if (buffer
->nb_indices
< count
* 3)
117 buffer
->nb_indices
= count
* 3;
118 HeapFree(GetProcessHeap(), 0, buffer
->indices
);
119 buffer
->indices
= HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer
->indices
) * buffer
->nb_indices
);
122 for (i
= 0; i
< count
; ++i
)
124 D3DTRIANGLE
*ci
= (D3DTRIANGLE
*)instr
;
125 TRACE(" v1: %d v2: %d v3: %d\n",ci
->u1
.v1
, ci
->u2
.v2
, ci
->u3
.v3
);
130 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
131 TRACE("EDGEENABLE1 ");
132 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE2
)
133 TRACE("EDGEENABLE2 ");
134 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
135 TRACE("EDGEENABLE3 ");
137 if (ci
->wFlags
== D3DTRIFLAG_EVEN
)
139 if (ci
->wFlags
== D3DTRIFLAG_ODD
)
141 if (ci
->wFlags
== D3DTRIFLAG_START
)
143 if ((ci
->wFlags
> 0) && (ci
->wFlags
< 30))
144 TRACE("STARTFLAT(%u) ", ci
->wFlags
);
147 buffer
->indices
[(i
* 3) ] = ci
->u1
.v1
;
148 buffer
->indices
[(i
* 3) + 1] = ci
->u2
.v2
;
149 buffer
->indices
[(i
* 3) + 2] = ci
->u3
.v3
;
152 IDirect3DDevice7_DrawIndexedPrimitive(&device
->IDirect3DDevice7_iface
,
153 D3DPT_TRIANGLELIST
, D3DFVF_TLVERTEX
, tl_vx
, buffer
->nb_vertices
,
154 buffer
->indices
, count
* 3, 0);
157 case D3DOP_MATRIXLOAD
:
158 WARN("MATRIXLOAD-s (%d)\n", count
);
159 instr
+= count
* size
;
162 case D3DOP_MATRIXMULTIPLY
:
163 TRACE("MATRIXMULTIPLY (%d)\n", count
);
164 for (i
= 0; i
< count
; ++i
)
166 D3DMATRIXMULTIPLY
*ci
= (D3DMATRIXMULTIPLY
*)instr
;
167 D3DMATRIX
*a
, *b
, *c
;
169 a
= ddraw_get_object(&device
->handle_table
, ci
->hDestMatrix
- 1, DDRAW_HANDLE_MATRIX
);
170 b
= ddraw_get_object(&device
->handle_table
, ci
->hSrcMatrix1
- 1, DDRAW_HANDLE_MATRIX
);
171 c
= ddraw_get_object(&device
->handle_table
, ci
->hSrcMatrix2
- 1, DDRAW_HANDLE_MATRIX
);
175 ERR("Invalid matrix handle (a %#x -> %p, b %#x -> %p, c %#x -> %p).\n",
176 ci
->hDestMatrix
, a
, ci
->hSrcMatrix1
, b
, ci
->hSrcMatrix2
, c
);
180 TRACE("dst %p, src1 %p, src2 %p.\n", a
, b
, c
);
181 multiply_matrix(a
, c
, b
);
188 case D3DOP_STATETRANSFORM
:
189 TRACE("STATETRANSFORM (%d)\n", count
);
190 for (i
= 0; i
< count
; ++i
)
192 D3DSTATE
*ci
= (D3DSTATE
*)instr
;
195 m
= ddraw_get_object(&device
->handle_table
, ci
->u2
.dwArg
[0] - 1, DDRAW_HANDLE_MATRIX
);
198 ERR("Invalid matrix handle %#x.\n", ci
->u2
.dwArg
[0]);
202 if (ci
->u1
.dtstTransformStateType
== D3DTRANSFORMSTATE_WORLD
)
203 device
->world
= ci
->u2
.dwArg
[0];
204 if (ci
->u1
.dtstTransformStateType
== D3DTRANSFORMSTATE_VIEW
)
205 device
->view
= ci
->u2
.dwArg
[0];
206 if (ci
->u1
.dtstTransformStateType
== D3DTRANSFORMSTATE_PROJECTION
)
207 device
->proj
= ci
->u2
.dwArg
[0];
208 IDirect3DDevice7_SetTransform(&device
->IDirect3DDevice7_iface
,
209 ci
->u1
.dtstTransformStateType
, m
);
216 case D3DOP_STATELIGHT
:
217 TRACE("STATELIGHT (%d)\n", count
);
218 for (i
= 0; i
< count
; ++i
)
220 D3DSTATE
*ci
= (D3DSTATE
*)instr
;
222 if (FAILED(IDirect3DDevice3_SetLightState(&device
->IDirect3DDevice3_iface
,
223 ci
->u1
.dlstLightStateType
, ci
->u2
.dwArg
[0])))
224 WARN("Failed to set light state.\n");
230 case D3DOP_STATERENDER
:
231 TRACE("STATERENDER (%d)\n", count
);
232 for (i
= 0; i
< count
; ++i
)
234 D3DSTATE
*ci
= (D3DSTATE
*)instr
;
236 if (FAILED(IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
,
237 ci
->u1
.drstRenderStateType
, ci
->u2
.dwArg
[0])))
238 WARN("Failed to set render state.\n");
244 case D3DOP_PROCESSVERTICES
:
246 /* TODO: Share code with d3d_vertex_buffer7_ProcessVertices()
247 * and / or wined3d_device_process_vertices(). */
248 D3DMATRIX view_mat
, world_mat
, proj_mat
, mat
;
250 TRACE("PROCESSVERTICES (%d)\n", count
);
252 /* Get the transform and world matrix */
253 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
254 wined3d_device_get_transform(device
->wined3d_device
,
255 D3DTRANSFORMSTATE_VIEW
, (struct wined3d_matrix
*)&view_mat
);
256 wined3d_device_get_transform(device
->wined3d_device
,
257 D3DTRANSFORMSTATE_PROJECTION
, (struct wined3d_matrix
*)&proj_mat
);
258 wined3d_device_get_transform(device
->wined3d_device
,
259 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix
*)&world_mat
);
263 TRACE(" Projection Matrix:\n");
264 dump_D3DMATRIX(&proj_mat
);
265 TRACE(" View Matrix:\n");
266 dump_D3DMATRIX(&view_mat
);
267 TRACE(" World Matrix:\n");
268 dump_D3DMATRIX(&world_mat
);
271 multiply_matrix(&mat
, &view_mat
, &world_mat
);
272 multiply_matrix(&mat
, &proj_mat
, &mat
);
274 for (i
= 0; i
< count
; ++i
)
276 D3DPROCESSVERTICES
*ci
= (D3DPROCESSVERTICES
*)instr
;
277 D3DTLVERTEX
*dst
= (D3DTLVERTEX
*)buffer
->vertex_data
+ ci
->wDest
;
278 DWORD op
= ci
->dwFlags
& D3DPROCESSVERTICES_OPMASK
;
280 TRACE(" start %u, dest %u, count %u, flags %#x.\n",
281 ci
->wStart
, ci
->wDest
, ci
->dwCount
, ci
->dwFlags
);
283 if (ci
->dwFlags
& D3DPROCESSVERTICES_UPDATEEXTENTS
)
284 FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
285 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
286 FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n");
290 case D3DPROCESSVERTICES_TRANSFORMLIGHT
:
292 const D3DVERTEX
*src
= (D3DVERTEX
*)((char *)buffer
->desc
.lpData
+ vs
) + ci
->wStart
;
293 unsigned int vtx_idx
;
294 static unsigned int once
;
297 FIXME("Lighting not implemented.\n");
299 for (vtx_idx
= 0; vtx_idx
< ci
->dwCount
; ++vtx_idx
)
301 transform_vertex(&dst
[vtx_idx
], &mat
, &viewport
->viewports
.vp1
,
302 src
[vtx_idx
].u1
.x
, src
[vtx_idx
].u2
.y
, src
[vtx_idx
].u3
.z
);
303 /* No lighting yet */
304 dst
[vtx_idx
].u5
.color
= 0xffffffff; /* Opaque white */
305 dst
[vtx_idx
].u6
.specular
= 0xff000000; /* No specular and no fog factor */
306 dst
[vtx_idx
].u7
.tu
= src
[vtx_idx
].u7
.tu
;
307 dst
[vtx_idx
].u8
.tv
= src
[vtx_idx
].u8
.tv
;
312 case D3DPROCESSVERTICES_TRANSFORM
:
314 const D3DLVERTEX
*src
= (D3DLVERTEX
*)((char *)buffer
->desc
.lpData
+ vs
) + ci
->wStart
;
315 unsigned int vtx_idx
;
317 for (vtx_idx
= 0; vtx_idx
< ci
->dwCount
; ++vtx_idx
)
319 transform_vertex(&dst
[vtx_idx
], &mat
, &viewport
->viewports
.vp1
,
320 src
[vtx_idx
].u1
.x
, src
[vtx_idx
].u2
.y
, src
[vtx_idx
].u3
.z
);
321 dst
[vtx_idx
].u5
.color
= src
[vtx_idx
].u4
.color
;
322 dst
[vtx_idx
].u6
.specular
= src
[vtx_idx
].u5
.specular
;
323 dst
[vtx_idx
].u7
.tu
= src
[vtx_idx
].u6
.tu
;
324 dst
[vtx_idx
].u8
.tv
= src
[vtx_idx
].u7
.tv
;
329 case D3DPROCESSVERTICES_COPY
:
331 const D3DTLVERTEX
*src
= (D3DTLVERTEX
*)((char *)buffer
->desc
.lpData
+ vs
) + ci
->wStart
;
333 memcpy(dst
, src
, ci
->dwCount
* sizeof(*dst
));
338 FIXME("Unhandled vertex processing op %#x.\n", op
);
347 case D3DOP_TEXTURELOAD
: {
348 WARN("TEXTURELOAD-s (%d)\n", count
);
350 instr
+= count
* size
;
354 TRACE("EXIT (%d)\n", count
);
355 /* We did this instruction */
361 case D3DOP_BRANCHFORWARD
:
362 TRACE("BRANCHFORWARD (%d)\n", count
);
363 for (i
= 0; i
< count
; ++i
)
365 D3DBRANCH
*ci
= (D3DBRANCH
*)instr
;
367 if ((buffer
->data
.dsStatus
.dwStatus
& ci
->dwMask
) == ci
->dwValue
)
371 TRACE(" Branch to %d\n", ci
->dwOffset
);
373 instr
= (char*)current
+ ci
->dwOffset
;
379 TRACE(" Branch to %d\n", ci
->dwOffset
);
381 instr
= (char*)current
+ ci
->dwOffset
;
392 WARN("SPAN-s (%d)\n", count
);
394 instr
+= count
* size
;
397 case D3DOP_SETSTATUS
:
398 TRACE("SETSTATUS (%d)\n", count
);
399 for (i
= 0; i
< count
; ++i
)
401 buffer
->data
.dsStatus
= *(D3DSTATUS
*)instr
;
407 ERR("Unhandled OpCode %d !!!\n",current
->bOpcode
);
408 /* Try to save ... */
409 instr
+= count
* size
;
418 static inline struct d3d_execute_buffer
*impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer
*iface
)
420 return CONTAINING_RECORD(iface
, struct d3d_execute_buffer
, IDirect3DExecuteBuffer_iface
);
423 static HRESULT WINAPI
d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer
*iface
, REFIID iid
, void **out
)
425 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
427 if (IsEqualGUID(&IID_IDirect3DExecuteBuffer
, iid
)
428 || IsEqualGUID(&IID_IUnknown
, iid
))
430 IDirect3DExecuteBuffer_AddRef(iface
);
435 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
438 return E_NOINTERFACE
;
441 /*****************************************************************************
442 * IDirect3DExecuteBuffer::AddRef
444 * A normal AddRef method, nothing special
449 *****************************************************************************/
450 static ULONG WINAPI
d3d_execute_buffer_AddRef(IDirect3DExecuteBuffer
*iface
)
452 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
453 ULONG ref
= InterlockedIncrement(&buffer
->ref
);
455 TRACE("%p increasing refcount to %u.\n", buffer
, ref
);
460 /*****************************************************************************
461 * IDirect3DExecuteBuffer::Release
463 * A normal Release method, nothing special
468 *****************************************************************************/
469 static ULONG WINAPI
d3d_execute_buffer_Release(IDirect3DExecuteBuffer
*iface
)
471 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
472 ULONG ref
= InterlockedDecrement(&buffer
->ref
);
474 TRACE("%p decreasing refcount to %u.\n", buffer
, ref
);
478 if (buffer
->need_free
)
479 HeapFree(GetProcessHeap(), 0, buffer
->desc
.lpData
);
480 HeapFree(GetProcessHeap(), 0, buffer
->vertex_data
);
481 HeapFree(GetProcessHeap(), 0, buffer
->indices
);
482 HeapFree(GetProcessHeap(), 0, buffer
);
488 /*****************************************************************************
489 * IDirect3DExecuteBuffer::Initialize
491 * Initializes the Execute Buffer. This method exists for COM compliance
492 * Nothing to do here.
497 *****************************************************************************/
498 static HRESULT WINAPI
d3d_execute_buffer_Initialize(IDirect3DExecuteBuffer
*iface
,
499 IDirect3DDevice
*device
, D3DEXECUTEBUFFERDESC
*desc
)
501 TRACE("iface %p, device %p, desc %p.\n", iface
, device
, desc
);
506 /*****************************************************************************
507 * IDirect3DExecuteBuffer::Lock
509 * Locks the buffer, so the app can write into it.
512 * Desc: Pointer to return the buffer description. This Description contains
513 * a pointer to the buffer data.
516 * This implementation always returns D3D_OK
518 *****************************************************************************/
519 static HRESULT WINAPI
d3d_execute_buffer_Lock(IDirect3DExecuteBuffer
*iface
, D3DEXECUTEBUFFERDESC
*desc
)
521 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
524 TRACE("iface %p, desc %p.\n", iface
, desc
);
526 dwSize
= desc
->dwSize
;
527 memcpy(desc
, &buffer
->desc
, dwSize
);
531 TRACE(" Returning description :\n");
532 _dump_D3DEXECUTEBUFFERDESC(desc
);
537 /*****************************************************************************
538 * IDirect3DExecuteBuffer::Unlock
540 * Unlocks the buffer. We don't have anything to do here
543 * This implementation always returns D3D_OK
545 *****************************************************************************/
546 static HRESULT WINAPI
d3d_execute_buffer_Unlock(IDirect3DExecuteBuffer
*iface
)
548 TRACE("iface %p.\n", iface
);
553 /*****************************************************************************
554 * IDirect3DExecuteBuffer::SetExecuteData
556 * Sets the execute data. This data is used to describe the buffer's content
559 * Data: Pointer to a D3DEXECUTEDATA structure containing the data to
564 * DDERR_OUTOFMEMORY if the vertex buffer allocation failed
566 *****************************************************************************/
567 static HRESULT WINAPI
d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer
*iface
, D3DEXECUTEDATA
*data
)
569 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
572 TRACE("iface %p, data %p.\n", iface
, data
);
574 memcpy(&buffer
->data
, data
, data
->dwSize
);
576 /* Get the number of vertices in the execute buffer */
577 nbvert
= buffer
->data
.dwVertexCount
;
579 /* Prepares the transformed vertex buffer */
580 HeapFree(GetProcessHeap(), 0, buffer
->vertex_data
);
581 buffer
->vertex_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbvert
* sizeof(D3DTLVERTEX
));
582 buffer
->nb_vertices
= nbvert
;
585 _dump_executedata(data
);
590 /*****************************************************************************
591 * IDirect3DExecuteBuffer::GetExecuteData
593 * Returns the data in the execute buffer
596 * Data: Pointer to a D3DEXECUTEDATA structure used to return data
601 *****************************************************************************/
602 static HRESULT WINAPI
d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer
*iface
, D3DEXECUTEDATA
*data
)
604 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
607 TRACE("iface %p, data %p.\n", iface
, data
);
609 dwSize
= data
->dwSize
;
610 memcpy(data
, &buffer
->data
, dwSize
);
614 TRACE("Returning data :\n");
615 _dump_executedata(data
);
621 /*****************************************************************************
622 * IDirect3DExecuteBuffer::Validate
624 * DirectX 5 SDK: "The IDirect3DExecuteBuffer::Validate method is not
625 * currently implemented"
631 * DDERR_UNSUPPORTED, because it's not implemented in Windows.
633 *****************************************************************************/
634 static HRESULT WINAPI
d3d_execute_buffer_Validate(IDirect3DExecuteBuffer
*iface
,
635 DWORD
*offset
, LPD3DVALIDATECALLBACK callback
, void *context
, DWORD reserved
)
637 TRACE("iface %p, offset %p, callback %p, context %p, reserved %#x.\n",
638 iface
, offset
, callback
, context
, reserved
);
640 WARN("Not implemented.\n");
642 return DDERR_UNSUPPORTED
; /* Unchecked */
645 /*****************************************************************************
646 * IDirect3DExecuteBuffer::Optimize
648 * DirectX5 SDK: "The IDirect3DExecuteBuffer::Optimize method is not
649 * currently supported"
652 * Dummy: Seems to be an unused dummy ;)
655 * DDERR_UNSUPPORTED, because it's not implemented in Windows.
657 *****************************************************************************/
658 static HRESULT WINAPI
d3d_execute_buffer_Optimize(IDirect3DExecuteBuffer
*iface
, DWORD reserved
)
660 TRACE("iface %p, reserved %#x.\n", iface
, reserved
);
662 WARN("Not implemented.\n");
664 return DDERR_UNSUPPORTED
; /* Unchecked */
667 static const struct IDirect3DExecuteBufferVtbl d3d_execute_buffer_vtbl
=
669 d3d_execute_buffer_QueryInterface
,
670 d3d_execute_buffer_AddRef
,
671 d3d_execute_buffer_Release
,
672 d3d_execute_buffer_Initialize
,
673 d3d_execute_buffer_Lock
,
674 d3d_execute_buffer_Unlock
,
675 d3d_execute_buffer_SetExecuteData
,
676 d3d_execute_buffer_GetExecuteData
,
677 d3d_execute_buffer_Validate
,
678 d3d_execute_buffer_Optimize
,
681 HRESULT
d3d_execute_buffer_init(struct d3d_execute_buffer
*execute_buffer
,
682 struct d3d_device
*device
, D3DEXECUTEBUFFERDESC
*desc
)
684 execute_buffer
->IDirect3DExecuteBuffer_iface
.lpVtbl
= &d3d_execute_buffer_vtbl
;
685 execute_buffer
->ref
= 1;
686 execute_buffer
->d3ddev
= device
;
688 /* Initializes memory */
689 memcpy(&execute_buffer
->desc
, desc
, desc
->dwSize
);
691 /* No buffer given */
692 if (!(execute_buffer
->desc
.dwFlags
& D3DDEB_LPDATA
))
693 execute_buffer
->desc
.lpData
= NULL
;
695 /* No buffer size given */
696 if (!(execute_buffer
->desc
.dwFlags
& D3DDEB_BUFSIZE
))
697 execute_buffer
->desc
.dwBufferSize
= 0;
699 /* Create buffer if asked */
700 if (!execute_buffer
->desc
.lpData
&& execute_buffer
->desc
.dwBufferSize
)
702 execute_buffer
->need_free
= TRUE
;
703 execute_buffer
->desc
.lpData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, execute_buffer
->desc
.dwBufferSize
);
704 if (!execute_buffer
->desc
.lpData
)
706 ERR("Failed to allocate execute buffer data.\n");
707 return DDERR_OUTOFMEMORY
;
711 execute_buffer
->desc
.dwFlags
|= D3DDEB_LPDATA
;
716 struct d3d_execute_buffer
*unsafe_impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer
*iface
)
720 assert(iface
->lpVtbl
== &d3d_execute_buffer_vtbl
);
722 return impl_from_IDirect3DExecuteBuffer(iface
);