ddraw: Use wined3d_device_process_vertices for execute buffers.
[wine.git] / dlls / ddraw / executebuffer.c
blob1603e708c208260514018ff31969f87656a28221
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include "ddraw_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
28 /*****************************************************************************
29 * _dump_executedata
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 HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
52 struct d3d_device *device, struct d3d_viewport *viewport)
54 DWORD is = buffer->data.dwInstructionOffset;
55 char *instr = (char *)buffer->desc.lpData + is;
56 unsigned int i;
57 struct wined3d_map_desc map_desc;
58 struct wined3d_box box = {0};
59 HRESULT hr;
61 if (viewport->active_device != device)
63 WARN("Viewport %p active device is %p.\n",
64 viewport, viewport->active_device);
65 return DDERR_INVALIDPARAMS;
68 /* Activate the viewport */
69 viewport_activate(viewport, FALSE);
71 TRACE("ExecuteData :\n");
72 if (TRACE_ON(ddraw))
73 _dump_executedata(&(buffer->data));
75 for (;;)
77 D3DINSTRUCTION *current = (D3DINSTRUCTION *)instr;
78 BYTE size;
79 WORD count;
81 count = current->wCount;
82 size = current->bSize;
83 instr += sizeof(D3DINSTRUCTION);
85 switch (current->bOpcode) {
86 case D3DOP_POINT: {
87 WARN("POINT-s (%d)\n", count);
88 instr += count * size;
89 } break;
91 case D3DOP_LINE: {
92 WARN("LINE-s (%d)\n", count);
93 instr += count * size;
94 } break;
96 case D3DOP_TRIANGLE:
98 WORD *indices;
99 TRACE("TRIANGLE (%d)\n", count);
101 if (!count)
102 break;
104 if (buffer->index_size < count * 3)
106 struct wined3d_buffer *new_buffer;
107 unsigned int new_size = max(buffer->index_size * 2, count * 3);
109 hr = wined3d_buffer_create_ib(device->wined3d_device, new_size * sizeof(*indices),
110 WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, WINED3D_POOL_DEFAULT,
111 NULL, &ddraw_null_wined3d_parent_ops, &new_buffer);
112 if (FAILED(hr))
113 return hr;
115 buffer->index_size = new_size;
116 if (buffer->index_buffer)
117 wined3d_buffer_decref(buffer->index_buffer);
118 buffer->index_buffer = new_buffer;
121 box.left = 0;
122 box.right = count * 3 * sizeof(*indices);
123 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->index_buffer), 0,
124 &map_desc, &box, WINED3D_MAP_DISCARD);
125 if (FAILED(hr))
126 return hr;
127 indices = map_desc.data;
129 for (i = 0; i < count; ++i)
131 D3DTRIANGLE *ci = (D3DTRIANGLE *)instr;
132 TRACE(" v1: %d v2: %d v3: %d\n",ci->u1.v1, ci->u2.v2, ci->u3.v3);
133 TRACE(" Flags : ");
134 if (TRACE_ON(ddraw))
136 /* Wireframe */
137 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)
138 TRACE("EDGEENABLE1 ");
139 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2)
140 TRACE("EDGEENABLE2 ");
141 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)
142 TRACE("EDGEENABLE3 ");
143 /* Strips / Fans */
144 if (ci->wFlags == D3DTRIFLAG_EVEN)
145 TRACE("EVEN ");
146 if (ci->wFlags == D3DTRIFLAG_ODD)
147 TRACE("ODD ");
148 if (ci->wFlags == D3DTRIFLAG_START)
149 TRACE("START ");
150 if ((ci->wFlags > 0) && (ci->wFlags < 30))
151 TRACE("STARTFLAT(%u) ", ci->wFlags);
152 TRACE("\n");
154 indices[(i * 3) ] = ci->u1.v1;
155 indices[(i * 3) + 1] = ci->u2.v2;
156 indices[(i * 3) + 2] = ci->u3.v3;
157 instr += size;
160 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->index_buffer), 0);
162 wined3d_device_set_stream_source(device->wined3d_device, 0,
163 buffer->dst_vertex_buffer, 0, sizeof(D3DTLVERTEX));
164 wined3d_device_set_vertex_declaration(device->wined3d_device,
165 ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX));
166 wined3d_device_set_index_buffer(device->wined3d_device, buffer->index_buffer, WINED3DFMT_R16_UINT, 0);
167 wined3d_device_set_primitive_type(device->wined3d_device, WINED3D_PT_TRIANGLELIST);
168 wined3d_device_draw_indexed_primitive(device->wined3d_device, 0, count * 3);
169 } break;
171 case D3DOP_MATRIXLOAD:
172 WARN("MATRIXLOAD-s (%d)\n", count);
173 instr += count * size;
174 break;
176 case D3DOP_MATRIXMULTIPLY:
177 TRACE("MATRIXMULTIPLY (%d)\n", count);
178 for (i = 0; i < count; ++i)
180 D3DMATRIXMULTIPLY *ci = (D3DMATRIXMULTIPLY *)instr;
181 D3DMATRIX *a, *b, *c;
183 a = ddraw_get_object(&device->handle_table, ci->hDestMatrix - 1, DDRAW_HANDLE_MATRIX);
184 b = ddraw_get_object(&device->handle_table, ci->hSrcMatrix1 - 1, DDRAW_HANDLE_MATRIX);
185 c = ddraw_get_object(&device->handle_table, ci->hSrcMatrix2 - 1, DDRAW_HANDLE_MATRIX);
187 if (!a || !b || !c)
189 ERR("Invalid matrix handle (a %#x -> %p, b %#x -> %p, c %#x -> %p).\n",
190 ci->hDestMatrix, a, ci->hSrcMatrix1, b, ci->hSrcMatrix2, c);
192 else
194 TRACE("dst %p, src1 %p, src2 %p.\n", a, b, c);
195 multiply_matrix(a, c, b);
198 instr += size;
200 break;
202 case D3DOP_STATETRANSFORM:
203 TRACE("STATETRANSFORM (%d)\n", count);
204 for (i = 0; i < count; ++i)
206 D3DSTATE *ci = (D3DSTATE *)instr;
207 D3DMATRIX *m;
209 m = ddraw_get_object(&device->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATRIX);
210 if (!m)
212 ERR("Invalid matrix handle %#x.\n", ci->u2.dwArg[0]);
214 else
216 if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_WORLD)
217 device->world = ci->u2.dwArg[0];
218 if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_VIEW)
219 device->view = ci->u2.dwArg[0];
220 if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_PROJECTION)
221 device->proj = ci->u2.dwArg[0];
222 IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface,
223 ci->u1.dtstTransformStateType, m);
226 instr += size;
228 break;
230 case D3DOP_STATELIGHT:
231 TRACE("STATELIGHT (%d)\n", count);
232 for (i = 0; i < count; ++i)
234 D3DSTATE *ci = (D3DSTATE *)instr;
236 if (FAILED(IDirect3DDevice3_SetLightState(&device->IDirect3DDevice3_iface,
237 ci->u1.dlstLightStateType, ci->u2.dwArg[0])))
238 WARN("Failed to set light state.\n");
240 instr += size;
242 break;
244 case D3DOP_STATERENDER:
245 TRACE("STATERENDER (%d)\n", count);
246 for (i = 0; i < count; ++i)
248 D3DSTATE *ci = (D3DSTATE *)instr;
250 if (FAILED(IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
251 ci->u1.drstRenderStateType, ci->u2.dwArg[0])))
252 WARN("Failed to set render state.\n");
254 instr += size;
256 break;
258 case D3DOP_PROCESSVERTICES:
259 TRACE("PROCESSVERTICES (%d)\n", count);
261 for (i = 0; i < count; ++i)
263 D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr;
264 DWORD op = ci->dwFlags & D3DPROCESSVERTICES_OPMASK;
266 TRACE(" start %u, dest %u, count %u, flags %#x.\n",
267 ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags);
269 if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
270 FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
271 if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
272 FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n");
274 switch (op)
276 case D3DPROCESSVERTICES_TRANSFORMLIGHT:
277 case D3DPROCESSVERTICES_TRANSFORM:
278 wined3d_device_set_stream_source(device->wined3d_device, 0,
279 buffer->src_vertex_buffer, 0, sizeof(D3DVERTEX));
280 if (op == D3DPROCESSVERTICES_TRANSFORMLIGHT)
282 wined3d_device_set_vertex_declaration(device->wined3d_device,
283 ddraw_find_decl(device->ddraw, D3DFVF_VERTEX));
284 wined3d_device_set_render_state(device->wined3d_device,
285 WINED3D_RS_LIGHTING, TRUE);
287 else
289 wined3d_device_set_vertex_declaration(device->wined3d_device,
290 ddraw_find_decl(device->ddraw, D3DFVF_LVERTEX));
291 wined3d_device_set_render_state(device->wined3d_device,
292 WINED3D_RS_LIGHTING, FALSE);
295 wined3d_device_process_vertices(device->wined3d_device, ci->wStart, ci->wDest,
296 ci->dwCount, buffer->dst_vertex_buffer, NULL, 0, D3DFVF_TLVERTEX);
297 break;
299 case D3DPROCESSVERTICES_COPY:
300 box.left = ci->wStart * sizeof(D3DTLVERTEX);
301 box.right = (ci->wStart + ci->dwCount) * sizeof(D3DTLVERTEX);
302 box.top = box.front = 0;
303 box.bottom = box.back = 1;
304 wined3d_device_copy_sub_resource_region(device->wined3d_device,
305 wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0,
306 ci->wDest * sizeof(D3DTLVERTEX), 0, 0,
307 wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box);
308 break;
310 default:
311 FIXME("Unhandled vertex processing op %#x.\n", op);
312 break;
315 instr += size;
317 break;
319 case D3DOP_TEXTURELOAD: {
320 WARN("TEXTURELOAD-s (%d)\n", count);
322 instr += count * size;
323 } break;
325 case D3DOP_EXIT: {
326 TRACE("EXIT (%d)\n", count);
327 /* We did this instruction */
328 instr += size;
329 /* Exit this loop */
330 goto end_of_buffer;
331 } break;
333 case D3DOP_BRANCHFORWARD:
334 TRACE("BRANCHFORWARD (%d)\n", count);
335 for (i = 0; i < count; ++i)
337 D3DBRANCH *ci = (D3DBRANCH *)instr;
339 if ((buffer->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue)
341 if (!ci->bNegate)
343 TRACE(" Branch to %d\n", ci->dwOffset);
344 if (ci->dwOffset) {
345 instr = (char*)current + ci->dwOffset;
346 break;
349 } else {
350 if (ci->bNegate) {
351 TRACE(" Branch to %d\n", ci->dwOffset);
352 if (ci->dwOffset) {
353 instr = (char*)current + ci->dwOffset;
354 break;
359 instr += size;
361 break;
363 case D3DOP_SPAN: {
364 WARN("SPAN-s (%d)\n", count);
366 instr += count * size;
367 } break;
369 case D3DOP_SETSTATUS:
370 TRACE("SETSTATUS (%d)\n", count);
371 for (i = 0; i < count; ++i)
373 buffer->data.dsStatus = *(D3DSTATUS *)instr;
374 instr += size;
376 break;
378 default:
379 ERR("Unhandled OpCode %d !!!\n",current->bOpcode);
380 /* Try to save ... */
381 instr += count * size;
382 break;
386 end_of_buffer:
387 return D3D_OK;
390 static inline struct d3d_execute_buffer *impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface)
392 return CONTAINING_RECORD(iface, struct d3d_execute_buffer, IDirect3DExecuteBuffer_iface);
395 static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID iid, void **out)
397 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
399 if (IsEqualGUID(&IID_IDirect3DExecuteBuffer, iid)
400 || IsEqualGUID(&IID_IUnknown, iid))
402 IDirect3DExecuteBuffer_AddRef(iface);
403 *out = iface;
404 return S_OK;
407 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
409 *out = NULL;
410 return E_NOINTERFACE;
413 /*****************************************************************************
414 * IDirect3DExecuteBuffer::AddRef
416 * A normal AddRef method, nothing special
418 * Returns:
419 * The new refcount
421 *****************************************************************************/
422 static ULONG WINAPI d3d_execute_buffer_AddRef(IDirect3DExecuteBuffer *iface)
424 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
425 ULONG ref = InterlockedIncrement(&buffer->ref);
427 TRACE("%p increasing refcount to %u.\n", buffer, ref);
429 return ref;
432 /*****************************************************************************
433 * IDirect3DExecuteBuffer::Release
435 * A normal Release method, nothing special
437 * Returns:
438 * The new refcount
440 *****************************************************************************/
441 static ULONG WINAPI d3d_execute_buffer_Release(IDirect3DExecuteBuffer *iface)
443 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
444 ULONG ref = InterlockedDecrement(&buffer->ref);
446 TRACE("%p decreasing refcount to %u.\n", buffer, ref);
448 if (!ref)
450 if (buffer->need_free)
451 HeapFree(GetProcessHeap(), 0, buffer->desc.lpData);
452 if (buffer->index_buffer)
453 wined3d_buffer_decref(buffer->index_buffer);
454 if (buffer->dst_vertex_buffer)
456 wined3d_buffer_decref(buffer->src_vertex_buffer);
457 wined3d_buffer_decref(buffer->dst_vertex_buffer);
459 HeapFree(GetProcessHeap(), 0, buffer);
462 return ref;
465 /*****************************************************************************
466 * IDirect3DExecuteBuffer::Initialize
468 * Initializes the Execute Buffer. This method exists for COM compliance
469 * Nothing to do here.
471 * Returns:
472 * D3D_OK
474 *****************************************************************************/
475 static HRESULT WINAPI d3d_execute_buffer_Initialize(IDirect3DExecuteBuffer *iface,
476 IDirect3DDevice *device, D3DEXECUTEBUFFERDESC *desc)
478 TRACE("iface %p, device %p, desc %p.\n", iface, device, desc);
480 return D3D_OK;
483 /*****************************************************************************
484 * IDirect3DExecuteBuffer::Lock
486 * Locks the buffer, so the app can write into it.
488 * Params:
489 * Desc: Pointer to return the buffer description. This Description contains
490 * a pointer to the buffer data.
492 * Returns:
493 * This implementation always returns D3D_OK
495 *****************************************************************************/
496 static HRESULT WINAPI d3d_execute_buffer_Lock(IDirect3DExecuteBuffer *iface, D3DEXECUTEBUFFERDESC *desc)
498 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
499 DWORD dwSize;
501 TRACE("iface %p, desc %p.\n", iface, desc);
503 dwSize = desc->dwSize;
504 memcpy(desc, &buffer->desc, dwSize);
506 if (TRACE_ON(ddraw))
508 TRACE(" Returning description :\n");
509 _dump_D3DEXECUTEBUFFERDESC(desc);
511 return D3D_OK;
514 /*****************************************************************************
515 * IDirect3DExecuteBuffer::Unlock
517 * Unlocks the buffer. We don't have anything to do here
519 * Returns:
520 * This implementation always returns D3D_OK
522 *****************************************************************************/
523 static HRESULT WINAPI d3d_execute_buffer_Unlock(IDirect3DExecuteBuffer *iface)
525 TRACE("iface %p.\n", iface);
527 return D3D_OK;
530 /*****************************************************************************
531 * IDirect3DExecuteBuffer::SetExecuteData
533 * Sets the execute data. This data is used to describe the buffer's content
535 * Params:
536 * Data: Pointer to a D3DEXECUTEDATA structure containing the data to
537 * assign
539 * Returns:
540 * D3D_OK on success
541 * DDERR_OUTOFMEMORY if the vertex buffer allocation failed
543 *****************************************************************************/
544 static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data)
546 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
547 struct wined3d_map_desc map_desc;
548 struct wined3d_box box = {0};
549 HRESULT hr;
551 TRACE("iface %p, data %p.\n", iface, data);
553 if (buffer->vertex_size < data->dwVertexCount)
555 unsigned int new_size = max(data->dwVertexCount, buffer->vertex_size * 2);
556 struct wined3d_buffer *src_buffer, *dst_buffer;
558 hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DVERTEX),
559 WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, WINED3D_POOL_SYSTEM_MEM,
560 NULL, &ddraw_null_wined3d_parent_ops, &src_buffer);
561 if (FAILED(hr))
562 return hr;
564 hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DTLVERTEX),
565 WINED3DUSAGE_STATICDECL, WINED3D_POOL_DEFAULT,
566 NULL, &ddraw_null_wined3d_parent_ops, &dst_buffer);
567 if (FAILED(hr))
569 wined3d_buffer_decref(src_buffer);
570 return hr;
573 if (buffer->dst_vertex_buffer)
575 wined3d_buffer_decref(buffer->src_vertex_buffer);
576 wined3d_buffer_decref(buffer->dst_vertex_buffer);
578 buffer->src_vertex_buffer = src_buffer;
579 buffer->dst_vertex_buffer = dst_buffer;
580 buffer->vertex_size = new_size;
583 if (data->dwVertexCount)
585 box.left = 0;
586 box.right = data->dwVertexCount * sizeof(D3DVERTEX);
587 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0,
588 &map_desc, &box, WINED3D_MAP_DISCARD);
589 if (FAILED(hr))
590 return hr;
592 memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset, box.right);
594 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0);
597 memcpy(&buffer->data, data, data->dwSize);
599 if (TRACE_ON(ddraw))
600 _dump_executedata(data);
602 return D3D_OK;
605 /*****************************************************************************
606 * IDirect3DExecuteBuffer::GetExecuteData
608 * Returns the data in the execute buffer
610 * Params:
611 * Data: Pointer to a D3DEXECUTEDATA structure used to return data
613 * Returns:
614 * D3D_OK on success
616 *****************************************************************************/
617 static HRESULT WINAPI d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data)
619 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
620 DWORD dwSize;
622 TRACE("iface %p, data %p.\n", iface, data);
624 dwSize = data->dwSize;
625 memcpy(data, &buffer->data, dwSize);
627 if (TRACE_ON(ddraw))
629 TRACE("Returning data :\n");
630 _dump_executedata(data);
633 return DD_OK;
636 /*****************************************************************************
637 * IDirect3DExecuteBuffer::Validate
639 * DirectX 5 SDK: "The IDirect3DExecuteBuffer::Validate method is not
640 * currently implemented"
642 * Params:
645 * Returns:
646 * DDERR_UNSUPPORTED, because it's not implemented in Windows.
648 *****************************************************************************/
649 static HRESULT WINAPI d3d_execute_buffer_Validate(IDirect3DExecuteBuffer *iface,
650 DWORD *offset, LPD3DVALIDATECALLBACK callback, void *context, DWORD reserved)
652 TRACE("iface %p, offset %p, callback %p, context %p, reserved %#x.\n",
653 iface, offset, callback, context, reserved);
655 WARN("Not implemented.\n");
657 return DDERR_UNSUPPORTED; /* Unchecked */
660 /*****************************************************************************
661 * IDirect3DExecuteBuffer::Optimize
663 * DirectX5 SDK: "The IDirect3DExecuteBuffer::Optimize method is not
664 * currently supported"
666 * Params:
667 * Dummy: Seems to be an unused dummy ;)
669 * Returns:
670 * DDERR_UNSUPPORTED, because it's not implemented in Windows.
672 *****************************************************************************/
673 static HRESULT WINAPI d3d_execute_buffer_Optimize(IDirect3DExecuteBuffer *iface, DWORD reserved)
675 TRACE("iface %p, reserved %#x.\n", iface, reserved);
677 WARN("Not implemented.\n");
679 return DDERR_UNSUPPORTED; /* Unchecked */
682 static const struct IDirect3DExecuteBufferVtbl d3d_execute_buffer_vtbl =
684 d3d_execute_buffer_QueryInterface,
685 d3d_execute_buffer_AddRef,
686 d3d_execute_buffer_Release,
687 d3d_execute_buffer_Initialize,
688 d3d_execute_buffer_Lock,
689 d3d_execute_buffer_Unlock,
690 d3d_execute_buffer_SetExecuteData,
691 d3d_execute_buffer_GetExecuteData,
692 d3d_execute_buffer_Validate,
693 d3d_execute_buffer_Optimize,
696 HRESULT d3d_execute_buffer_init(struct d3d_execute_buffer *execute_buffer,
697 struct d3d_device *device, D3DEXECUTEBUFFERDESC *desc)
699 execute_buffer->IDirect3DExecuteBuffer_iface.lpVtbl = &d3d_execute_buffer_vtbl;
700 execute_buffer->ref = 1;
701 execute_buffer->d3ddev = device;
703 /* Initializes memory */
704 memcpy(&execute_buffer->desc, desc, desc->dwSize);
706 /* No buffer given */
707 if (!(execute_buffer->desc.dwFlags & D3DDEB_LPDATA))
708 execute_buffer->desc.lpData = NULL;
710 /* No buffer size given */
711 if (!(execute_buffer->desc.dwFlags & D3DDEB_BUFSIZE))
712 execute_buffer->desc.dwBufferSize = 0;
714 /* Create buffer if asked */
715 if (!execute_buffer->desc.lpData && execute_buffer->desc.dwBufferSize)
717 execute_buffer->need_free = TRUE;
718 execute_buffer->desc.lpData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, execute_buffer->desc.dwBufferSize);
719 if (!execute_buffer->desc.lpData)
721 ERR("Failed to allocate execute buffer data.\n");
722 return DDERR_OUTOFMEMORY;
726 execute_buffer->desc.dwFlags |= D3DDEB_LPDATA;
728 return D3D_OK;
731 struct d3d_execute_buffer *unsafe_impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface)
733 if (!iface)
734 return NULL;
735 assert(iface->lpVtbl == &d3d_execute_buffer_vtbl);
737 return impl_from_IDirect3DExecuteBuffer(iface);