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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
24 #include "ddraw_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
28 /*****************************************************************************
30 * _dump_D3DEXECUTEBUFFERDESC
32 * Debug functions which write the executebuffer data to the console
34 *****************************************************************************/
36 static void _dump_executedata(const D3DEXECUTEDATA
*lpData
) {
37 TRACE("dwSize : %d\n", lpData
->dwSize
);
38 TRACE("Vertex Offset : %d Count : %d\n", lpData
->dwVertexOffset
, lpData
->dwVertexCount
);
39 TRACE("Instruction Offset : %d Length : %d\n", lpData
->dwInstructionOffset
, lpData
->dwInstructionLength
);
40 TRACE("HVertex Offset : %d\n", lpData
->dwHVertexOffset
);
43 static void _dump_D3DEXECUTEBUFFERDESC(const D3DEXECUTEBUFFERDESC
*lpDesc
) {
44 TRACE("dwSize : %d\n", lpDesc
->dwSize
);
45 TRACE("dwFlags : %x\n", lpDesc
->dwFlags
);
46 TRACE("dwCaps : %x\n", lpDesc
->dwCaps
);
47 TRACE("dwBufferSize : %d\n", lpDesc
->dwBufferSize
);
48 TRACE("lpData : %p\n", lpDesc
->lpData
);
51 static void transform_vertex(D3DTLVERTEX
*dst
, const D3DMATRIX
*mat
,
52 const D3DVIEWPORT
*vp
, float x
, float y
, float z
)
54 dst
->u1
.sx
= (x
* mat
->_11
) + (y
* mat
->_21
) + (z
* mat
->_31
) + mat
->_41
;
55 dst
->u2
.sy
= (x
* mat
->_12
) + (y
* mat
->_22
) + (z
* mat
->_32
) + mat
->_42
;
56 dst
->u3
.sz
= (x
* mat
->_13
) + (y
* mat
->_23
) + (z
* mat
->_33
) + mat
->_43
;
57 dst
->u4
.rhw
= (x
* mat
->_14
) + (y
* mat
->_24
) + (z
* mat
->_34
) + mat
->_44
;
59 dst
->u1
.sx
= dst
->u1
.sx
/ dst
->u4
.rhw
* vp
->dvScaleX
+ vp
->dwX
+ vp
->dwWidth
/ 2;
60 dst
->u2
.sy
= -dst
->u2
.sy
/ dst
->u4
.rhw
* vp
->dvScaleY
+ vp
->dwY
+ vp
->dwHeight
/ 2;
61 dst
->u3
.sz
/= dst
->u4
.rhw
;
62 dst
->u4
.rhw
= 1.0f
/ dst
->u4
.rhw
;
65 HRESULT
d3d_execute_buffer_execute(struct d3d_execute_buffer
*buffer
,
66 struct d3d_device
*device
, struct d3d_viewport
*viewport
)
68 DWORD vs
= buffer
->data
.dwVertexOffset
;
69 DWORD is
= buffer
->data
.dwInstructionOffset
;
70 char *instr
= (char *)buffer
->desc
.lpData
+ is
;
73 if (viewport
->active_device
!= device
)
75 WARN("Viewport %p active device is %p.\n",
76 viewport
, viewport
->active_device
);
77 return DDERR_INVALIDPARAMS
;
80 /* Activate the viewport */
81 viewport_activate(viewport
, FALSE
);
83 TRACE("ExecuteData :\n");
85 _dump_executedata(&(buffer
->data
));
89 D3DINSTRUCTION
*current
= (D3DINSTRUCTION
*)instr
;
93 count
= current
->wCount
;
94 size
= current
->bSize
;
95 instr
+= sizeof(D3DINSTRUCTION
);
97 switch (current
->bOpcode
) {
99 WARN("POINT-s (%d)\n", count
);
100 instr
+= count
* size
;
104 WARN("LINE-s (%d)\n", count
);
105 instr
+= count
* size
;
110 D3DTLVERTEX
*tl_vx
= buffer
->vertex_data
;
111 TRACE("TRIANGLE (%d)\n", count
);
113 if (buffer
->nb_indices
< count
* 3)
115 buffer
->nb_indices
= count
* 3;
116 HeapFree(GetProcessHeap(), 0, buffer
->indices
);
117 buffer
->indices
= HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer
->indices
) * buffer
->nb_indices
);
120 for (i
= 0; i
< count
; ++i
)
122 D3DTRIANGLE
*ci
= (D3DTRIANGLE
*)instr
;
123 TRACE(" v1: %d v2: %d v3: %d\n",ci
->u1
.v1
, ci
->u2
.v2
, ci
->u3
.v3
);
128 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
129 TRACE("EDGEENABLE1 ");
130 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE2
)
131 TRACE("EDGEENABLE2 ");
132 if (ci
->wFlags
& D3DTRIFLAG_EDGEENABLE1
)
133 TRACE("EDGEENABLE3 ");
135 if (ci
->wFlags
== D3DTRIFLAG_EVEN
)
137 if (ci
->wFlags
== D3DTRIFLAG_ODD
)
139 if (ci
->wFlags
== D3DTRIFLAG_START
)
141 if ((ci
->wFlags
> 0) && (ci
->wFlags
< 30))
142 TRACE("STARTFLAT(%u) ", ci
->wFlags
);
145 buffer
->indices
[(i
* 3) ] = ci
->u1
.v1
;
146 buffer
->indices
[(i
* 3) + 1] = ci
->u2
.v2
;
147 buffer
->indices
[(i
* 3) + 2] = ci
->u3
.v3
;
150 IDirect3DDevice7_DrawIndexedPrimitive(&device
->IDirect3DDevice7_iface
,
151 D3DPT_TRIANGLELIST
, D3DFVF_TLVERTEX
, tl_vx
, buffer
->nb_vertices
,
152 buffer
->indices
, count
* 3, 0);
155 case D3DOP_MATRIXLOAD
:
156 WARN("MATRIXLOAD-s (%d)\n", count
);
157 instr
+= count
* size
;
160 case D3DOP_MATRIXMULTIPLY
:
161 TRACE("MATRIXMULTIPLY (%d)\n", count
);
162 for (i
= 0; i
< count
; ++i
)
164 D3DMATRIXMULTIPLY
*ci
= (D3DMATRIXMULTIPLY
*)instr
;
165 D3DMATRIX
*a
, *b
, *c
;
167 a
= ddraw_get_object(&device
->handle_table
, ci
->hDestMatrix
- 1, DDRAW_HANDLE_MATRIX
);
168 b
= ddraw_get_object(&device
->handle_table
, ci
->hSrcMatrix1
- 1, DDRAW_HANDLE_MATRIX
);
169 c
= ddraw_get_object(&device
->handle_table
, ci
->hSrcMatrix2
- 1, DDRAW_HANDLE_MATRIX
);
173 ERR("Invalid matrix handle (a %#x -> %p, b %#x -> %p, c %#x -> %p).\n",
174 ci
->hDestMatrix
, a
, ci
->hSrcMatrix1
, b
, ci
->hSrcMatrix2
, c
);
178 TRACE("dst %p, src1 %p, src2 %p.\n", a
, b
, c
);
179 multiply_matrix(a
, c
, b
);
186 case D3DOP_STATETRANSFORM
:
187 TRACE("STATETRANSFORM (%d)\n", count
);
188 for (i
= 0; i
< count
; ++i
)
190 D3DSTATE
*ci
= (D3DSTATE
*)instr
;
193 m
= ddraw_get_object(&device
->handle_table
, ci
->u2
.dwArg
[0] - 1, DDRAW_HANDLE_MATRIX
);
196 ERR("Invalid matrix handle %#x.\n", ci
->u2
.dwArg
[0]);
200 if (ci
->u1
.dtstTransformStateType
== D3DTRANSFORMSTATE_WORLD
)
201 device
->world
= ci
->u2
.dwArg
[0];
202 if (ci
->u1
.dtstTransformStateType
== D3DTRANSFORMSTATE_VIEW
)
203 device
->view
= ci
->u2
.dwArg
[0];
204 if (ci
->u1
.dtstTransformStateType
== D3DTRANSFORMSTATE_PROJECTION
)
205 device
->proj
= ci
->u2
.dwArg
[0];
206 IDirect3DDevice7_SetTransform(&device
->IDirect3DDevice7_iface
,
207 ci
->u1
.dtstTransformStateType
, m
);
214 case D3DOP_STATELIGHT
:
215 TRACE("STATELIGHT (%d)\n", count
);
216 for (i
= 0; i
< count
; ++i
)
218 D3DSTATE
*ci
= (D3DSTATE
*)instr
;
220 if (FAILED(IDirect3DDevice3_SetLightState(&device
->IDirect3DDevice3_iface
,
221 ci
->u1
.dlstLightStateType
, ci
->u2
.dwArg
[0])))
222 WARN("Failed to set light state.\n");
228 case D3DOP_STATERENDER
:
229 TRACE("STATERENDER (%d)\n", count
);
230 for (i
= 0; i
< count
; ++i
)
232 D3DSTATE
*ci
= (D3DSTATE
*)instr
;
234 if (FAILED(IDirect3DDevice3_SetRenderState(&device
->IDirect3DDevice3_iface
,
235 ci
->u1
.drstRenderStateType
, ci
->u2
.dwArg
[0])))
236 WARN("Failed to set render state.\n");
242 case D3DOP_PROCESSVERTICES
:
244 /* TODO: Share code with d3d_vertex_buffer7_ProcessVertices()
245 * and / or wined3d_device_process_vertices(). */
246 D3DMATRIX view_mat
, world_mat
, proj_mat
, mat
;
248 TRACE("PROCESSVERTICES (%d)\n", count
);
250 /* Get the transform and world matrix */
251 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
252 wined3d_device_get_transform(device
->wined3d_device
,
253 D3DTRANSFORMSTATE_VIEW
, (struct wined3d_matrix
*)&view_mat
);
254 wined3d_device_get_transform(device
->wined3d_device
,
255 D3DTRANSFORMSTATE_PROJECTION
, (struct wined3d_matrix
*)&proj_mat
);
256 wined3d_device_get_transform(device
->wined3d_device
,
257 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix
*)&world_mat
);
261 TRACE(" Projection Matrix:\n");
262 dump_D3DMATRIX(&proj_mat
);
263 TRACE(" View Matrix:\n");
264 dump_D3DMATRIX(&view_mat
);
265 TRACE(" World Matrix:\n");
266 dump_D3DMATRIX(&world_mat
);
269 multiply_matrix(&mat
, &view_mat
, &world_mat
);
270 multiply_matrix(&mat
, &proj_mat
, &mat
);
272 for (i
= 0; i
< count
; ++i
)
274 D3DPROCESSVERTICES
*ci
= (D3DPROCESSVERTICES
*)instr
;
275 D3DTLVERTEX
*dst
= (D3DTLVERTEX
*)buffer
->vertex_data
+ ci
->wDest
;
276 DWORD op
= ci
->dwFlags
& D3DPROCESSVERTICES_OPMASK
;
278 TRACE(" start %u, dest %u, count %u, flags %#x.\n",
279 ci
->wStart
, ci
->wDest
, ci
->dwCount
, ci
->dwFlags
);
281 if (ci
->dwFlags
& D3DPROCESSVERTICES_UPDATEEXTENTS
)
282 FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
283 if (ci
->dwFlags
& D3DPROCESSVERTICES_NOCOLOR
)
284 FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n");
288 case D3DPROCESSVERTICES_TRANSFORMLIGHT
:
290 const D3DVERTEX
*src
= (D3DVERTEX
*)((char *)buffer
->desc
.lpData
+ vs
) + ci
->wStart
;
291 unsigned int vtx_idx
;
292 static unsigned int once
;
295 FIXME("Lighting not implemented.\n");
297 for (vtx_idx
= 0; vtx_idx
< ci
->dwCount
; ++vtx_idx
)
299 transform_vertex(&dst
[vtx_idx
], &mat
, &viewport
->viewports
.vp1
,
300 src
[vtx_idx
].u1
.x
, src
[vtx_idx
].u2
.y
, src
[vtx_idx
].u3
.z
);
301 /* No lighting yet */
302 dst
[vtx_idx
].u5
.color
= 0xffffffff; /* Opaque white */
303 dst
[vtx_idx
].u6
.specular
= 0xff000000; /* No specular and no fog factor */
304 dst
[vtx_idx
].u7
.tu
= src
[vtx_idx
].u7
.tu
;
305 dst
[vtx_idx
].u8
.tv
= src
[vtx_idx
].u8
.tv
;
310 case D3DPROCESSVERTICES_TRANSFORM
:
312 const D3DLVERTEX
*src
= (D3DLVERTEX
*)((char *)buffer
->desc
.lpData
+ vs
) + ci
->wStart
;
313 unsigned int vtx_idx
;
315 for (vtx_idx
= 0; vtx_idx
< ci
->dwCount
; ++vtx_idx
)
317 transform_vertex(&dst
[vtx_idx
], &mat
, &viewport
->viewports
.vp1
,
318 src
[vtx_idx
].u1
.x
, src
[vtx_idx
].u2
.y
, src
[vtx_idx
].u3
.z
);
319 dst
[vtx_idx
].u5
.color
= src
[vtx_idx
].u4
.color
;
320 dst
[vtx_idx
].u6
.specular
= src
[vtx_idx
].u5
.specular
;
321 dst
[vtx_idx
].u7
.tu
= src
[vtx_idx
].u6
.tu
;
322 dst
[vtx_idx
].u8
.tv
= src
[vtx_idx
].u7
.tv
;
327 case D3DPROCESSVERTICES_COPY
:
329 const D3DTLVERTEX
*src
= (D3DTLVERTEX
*)((char *)buffer
->desc
.lpData
+ vs
) + ci
->wStart
;
331 memcpy(dst
, src
, ci
->dwCount
* sizeof(*dst
));
336 FIXME("Unhandled vertex processing op %#x.\n", op
);
345 case D3DOP_TEXTURELOAD
: {
346 WARN("TEXTURELOAD-s (%d)\n", count
);
348 instr
+= count
* size
;
352 TRACE("EXIT (%d)\n", count
);
353 /* We did this instruction */
359 case D3DOP_BRANCHFORWARD
:
360 TRACE("BRANCHFORWARD (%d)\n", count
);
361 for (i
= 0; i
< count
; ++i
)
363 D3DBRANCH
*ci
= (D3DBRANCH
*)instr
;
365 if ((buffer
->data
.dsStatus
.dwStatus
& ci
->dwMask
) == ci
->dwValue
)
369 TRACE(" Branch to %d\n", ci
->dwOffset
);
371 instr
= (char*)current
+ ci
->dwOffset
;
377 TRACE(" Branch to %d\n", ci
->dwOffset
);
379 instr
= (char*)current
+ ci
->dwOffset
;
390 WARN("SPAN-s (%d)\n", count
);
392 instr
+= count
* size
;
395 case D3DOP_SETSTATUS
:
396 TRACE("SETSTATUS (%d)\n", count
);
397 for (i
= 0; i
< count
; ++i
)
399 buffer
->data
.dsStatus
= *(D3DSTATUS
*)instr
;
405 ERR("Unhandled OpCode %d !!!\n",current
->bOpcode
);
406 /* Try to save ... */
407 instr
+= count
* size
;
416 static inline struct d3d_execute_buffer
*impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer
*iface
)
418 return CONTAINING_RECORD(iface
, struct d3d_execute_buffer
, IDirect3DExecuteBuffer_iface
);
421 static HRESULT WINAPI
d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer
*iface
, REFIID iid
, void **out
)
423 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
425 if (IsEqualGUID(&IID_IDirect3DExecuteBuffer
, iid
)
426 || IsEqualGUID(&IID_IUnknown
, iid
))
428 IDirect3DExecuteBuffer_AddRef(iface
);
433 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
436 return E_NOINTERFACE
;
439 /*****************************************************************************
440 * IDirect3DExecuteBuffer::AddRef
442 * A normal AddRef method, nothing special
447 *****************************************************************************/
448 static ULONG WINAPI
d3d_execute_buffer_AddRef(IDirect3DExecuteBuffer
*iface
)
450 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
451 ULONG ref
= InterlockedIncrement(&buffer
->ref
);
453 TRACE("%p increasing refcount to %u.\n", buffer
, ref
);
458 /*****************************************************************************
459 * IDirect3DExecuteBuffer::Release
461 * A normal Release method, nothing special
466 *****************************************************************************/
467 static ULONG WINAPI
d3d_execute_buffer_Release(IDirect3DExecuteBuffer
*iface
)
469 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
470 ULONG ref
= InterlockedDecrement(&buffer
->ref
);
472 TRACE("%p decreasing refcount to %u.\n", buffer
, ref
);
476 if (buffer
->need_free
)
477 HeapFree(GetProcessHeap(), 0, buffer
->desc
.lpData
);
478 HeapFree(GetProcessHeap(), 0, buffer
->vertex_data
);
479 HeapFree(GetProcessHeap(), 0, buffer
->indices
);
480 HeapFree(GetProcessHeap(), 0, buffer
);
486 /*****************************************************************************
487 * IDirect3DExecuteBuffer::Initialize
489 * Initializes the Execute Buffer. This method exists for COM compliance
490 * Nothing to do here.
495 *****************************************************************************/
496 static HRESULT WINAPI
d3d_execute_buffer_Initialize(IDirect3DExecuteBuffer
*iface
,
497 IDirect3DDevice
*device
, D3DEXECUTEBUFFERDESC
*desc
)
499 TRACE("iface %p, device %p, desc %p.\n", iface
, device
, desc
);
504 /*****************************************************************************
505 * IDirect3DExecuteBuffer::Lock
507 * Locks the buffer, so the app can write into it.
510 * Desc: Pointer to return the buffer description. This Description contains
511 * a pointer to the buffer data.
514 * This implementation always returns D3D_OK
516 *****************************************************************************/
517 static HRESULT WINAPI
d3d_execute_buffer_Lock(IDirect3DExecuteBuffer
*iface
, D3DEXECUTEBUFFERDESC
*desc
)
519 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
522 TRACE("iface %p, desc %p.\n", iface
, desc
);
524 dwSize
= desc
->dwSize
;
525 memcpy(desc
, &buffer
->desc
, dwSize
);
529 TRACE(" Returning description :\n");
530 _dump_D3DEXECUTEBUFFERDESC(desc
);
535 /*****************************************************************************
536 * IDirect3DExecuteBuffer::Unlock
538 * Unlocks the buffer. We don't have anything to do here
541 * This implementation always returns D3D_OK
543 *****************************************************************************/
544 static HRESULT WINAPI
d3d_execute_buffer_Unlock(IDirect3DExecuteBuffer
*iface
)
546 TRACE("iface %p.\n", iface
);
551 /*****************************************************************************
552 * IDirect3DExecuteBuffer::SetExecuteData
554 * Sets the execute data. This data is used to describe the buffer's content
557 * Data: Pointer to a D3DEXECUTEDATA structure containing the data to
562 * DDERR_OUTOFMEMORY if the vertex buffer allocation failed
564 *****************************************************************************/
565 static HRESULT WINAPI
d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer
*iface
, D3DEXECUTEDATA
*data
)
567 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
570 TRACE("iface %p, data %p.\n", iface
, data
);
572 memcpy(&buffer
->data
, data
, data
->dwSize
);
574 /* Get the number of vertices in the execute buffer */
575 nbvert
= buffer
->data
.dwVertexCount
;
577 /* Prepares the transformed vertex buffer */
578 HeapFree(GetProcessHeap(), 0, buffer
->vertex_data
);
579 buffer
->vertex_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbvert
* sizeof(D3DTLVERTEX
));
580 buffer
->nb_vertices
= nbvert
;
583 _dump_executedata(data
);
588 /*****************************************************************************
589 * IDirect3DExecuteBuffer::GetExecuteData
591 * Returns the data in the execute buffer
594 * Data: Pointer to a D3DEXECUTEDATA structure used to return data
599 *****************************************************************************/
600 static HRESULT WINAPI
d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer
*iface
, D3DEXECUTEDATA
*data
)
602 struct d3d_execute_buffer
*buffer
= impl_from_IDirect3DExecuteBuffer(iface
);
605 TRACE("iface %p, data %p.\n", iface
, data
);
607 dwSize
= data
->dwSize
;
608 memcpy(data
, &buffer
->data
, dwSize
);
612 TRACE("Returning data :\n");
613 _dump_executedata(data
);
619 /*****************************************************************************
620 * IDirect3DExecuteBuffer::Validate
622 * DirectX 5 SDK: "The IDirect3DExecuteBuffer::Validate method is not
623 * currently implemented"
629 * DDERR_UNSUPPORTED, because it's not implemented in Windows.
631 *****************************************************************************/
632 static HRESULT WINAPI
d3d_execute_buffer_Validate(IDirect3DExecuteBuffer
*iface
,
633 DWORD
*offset
, LPD3DVALIDATECALLBACK callback
, void *context
, DWORD reserved
)
635 TRACE("iface %p, offset %p, callback %p, context %p, reserved %#x.\n",
636 iface
, offset
, callback
, context
, reserved
);
638 WARN("Not implemented.\n");
640 return DDERR_UNSUPPORTED
; /* Unchecked */
643 /*****************************************************************************
644 * IDirect3DExecuteBuffer::Optimize
646 * DirectX5 SDK: "The IDirect3DExecuteBuffer::Optimize method is not
647 * currently supported"
650 * Dummy: Seems to be an unused dummy ;)
653 * DDERR_UNSUPPORTED, because it's not implemented in Windows.
655 *****************************************************************************/
656 static HRESULT WINAPI
d3d_execute_buffer_Optimize(IDirect3DExecuteBuffer
*iface
, DWORD reserved
)
658 TRACE("iface %p, reserved %#x.\n", iface
, reserved
);
660 WARN("Not implemented.\n");
662 return DDERR_UNSUPPORTED
; /* Unchecked */
665 static const struct IDirect3DExecuteBufferVtbl d3d_execute_buffer_vtbl
=
667 d3d_execute_buffer_QueryInterface
,
668 d3d_execute_buffer_AddRef
,
669 d3d_execute_buffer_Release
,
670 d3d_execute_buffer_Initialize
,
671 d3d_execute_buffer_Lock
,
672 d3d_execute_buffer_Unlock
,
673 d3d_execute_buffer_SetExecuteData
,
674 d3d_execute_buffer_GetExecuteData
,
675 d3d_execute_buffer_Validate
,
676 d3d_execute_buffer_Optimize
,
679 HRESULT
d3d_execute_buffer_init(struct d3d_execute_buffer
*execute_buffer
,
680 struct d3d_device
*device
, D3DEXECUTEBUFFERDESC
*desc
)
682 execute_buffer
->IDirect3DExecuteBuffer_iface
.lpVtbl
= &d3d_execute_buffer_vtbl
;
683 execute_buffer
->ref
= 1;
684 execute_buffer
->d3ddev
= device
;
686 /* Initializes memory */
687 memcpy(&execute_buffer
->desc
, desc
, desc
->dwSize
);
689 /* No buffer given */
690 if (!(execute_buffer
->desc
.dwFlags
& D3DDEB_LPDATA
))
691 execute_buffer
->desc
.lpData
= NULL
;
693 /* No buffer size given */
694 if (!(execute_buffer
->desc
.dwFlags
& D3DDEB_BUFSIZE
))
695 execute_buffer
->desc
.dwBufferSize
= 0;
697 /* Create buffer if asked */
698 if (!execute_buffer
->desc
.lpData
&& execute_buffer
->desc
.dwBufferSize
)
700 execute_buffer
->need_free
= TRUE
;
701 execute_buffer
->desc
.lpData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, execute_buffer
->desc
.dwBufferSize
);
702 if (!execute_buffer
->desc
.lpData
)
704 ERR("Failed to allocate execute buffer data.\n");
705 return DDERR_OUTOFMEMORY
;
709 execute_buffer
->desc
.dwFlags
|= D3DDEB_LPDATA
;
714 struct d3d_execute_buffer
*unsafe_impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer
*iface
)
718 assert(iface
->lpVtbl
== &d3d_execute_buffer_vtbl
);
720 return impl_from_IDirect3DExecuteBuffer(iface
);