1 /* Direct3D ExecuteBuffer 2 * Copyright (c) 1998-2004 Lionel ULMER 3 * Copyright (c) 2002-2004 Christian Costa 4 * Copyright (c) 2006 Stefan Dösinger 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include "ddraw_private.h" 22 23 /***************************************************************************** 24 * _dump_executedata 25 * _dump_D3DEXECUTEBUFFERDESC 26 * 27 * Debug functions which write the executebuffer data to the console 28 * 29 *****************************************************************************/ 30 31 static void _dump_executedata(const D3DEXECUTEDATA *lpData) { 32 TRACE("dwSize : %d\n", lpData->dwSize); 33 TRACE("Vertex Offset : %d Count : %d\n", lpData->dwVertexOffset, lpData->dwVertexCount); 34 TRACE("Instruction Offset : %d Length : %d\n", lpData->dwInstructionOffset, lpData->dwInstructionLength); 35 TRACE("HVertex Offset : %d\n", lpData->dwHVertexOffset); 36 } 37 38 static void _dump_D3DEXECUTEBUFFERDESC(const D3DEXECUTEBUFFERDESC *lpDesc) { 39 TRACE("dwSize : %d\n", lpDesc->dwSize); 40 TRACE("dwFlags : %x\n", lpDesc->dwFlags); 41 TRACE("dwCaps : %x\n", lpDesc->dwCaps); 42 TRACE("dwBufferSize : %d\n", lpDesc->dwBufferSize); 43 TRACE("lpData : %p\n", lpDesc->lpData); 44 } 45 46 HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, 47 struct d3d_device *device, struct d3d_viewport *viewport) 48 { 49 DWORD is = buffer->data.dwInstructionOffset; 50 char *instr = (char *)buffer->desc.lpData + is; 51 unsigned int i, primitive_size; 52 struct wined3d_map_desc map_desc; 53 struct wined3d_box box = {0}; 54 HRESULT hr; 55 56 if (viewport->active_device != device) 57 { 58 WARN("Viewport %p active device is %p.\n", 59 viewport, viewport->active_device); 60 return DDERR_INVALIDPARAMS; 61 } 62 63 /* Activate the viewport */ 64 viewport_activate(viewport, FALSE); 65 66 TRACE("ExecuteData :\n"); 67 if (TRACE_ON(ddraw)) 68 _dump_executedata(&(buffer->data)); 69 70 for (;;) 71 { 72 D3DINSTRUCTION *current = (D3DINSTRUCTION *)instr; 73 BYTE size; 74 WORD count; 75 76 count = current->wCount; 77 size = current->bSize; 78 instr += sizeof(*current); 79 primitive_size = 0; 80 81 switch (current->bOpcode) 82 { 83 case D3DOP_POINT: 84 { 85 const D3DPOINT *p = (D3DPOINT *)instr; 86 wined3d_device_set_primitive_type(device->wined3d_device, WINED3D_PT_POINTLIST, 0); 87 wined3d_device_set_stream_source(device->wined3d_device, 0, 88 buffer->dst_vertex_buffer, 0, sizeof(D3DTLVERTEX)); 89 wined3d_device_set_vertex_declaration(device->wined3d_device, 90 ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX)); 91 92 for (i = 0; i < count; ++i) 93 wined3d_device_draw_primitive(device->wined3d_device, p[i].wFirst, p[i].wCount); 94 95 instr += sizeof(*p) * count; 96 break; 97 } 98 99 case D3DOP_LINE: 100 primitive_size = 2; 101 wined3d_device_set_primitive_type(device->wined3d_device, WINED3D_PT_LINELIST, 0); 102 /* Drop through. */ 103 case D3DOP_TRIANGLE: 104 { 105 WORD *indices; 106 unsigned int index_pos = buffer->index_pos, index_count; 107 TRACE("TRIANGLE (%d)\n", count); 108 109 if (!count) 110 break; 111 112 if (!primitive_size) 113 { 114 wined3d_device_set_primitive_type(device->wined3d_device, WINED3D_PT_TRIANGLELIST, 0); 115 primitive_size = 3; 116 } 117 118 index_count = count * primitive_size; 119 120 if (buffer->index_size < index_count) 121 { 122 struct wined3d_buffer *new_buffer; 123 unsigned int new_size = max(buffer->index_size * 2, index_count); 124 125 hr = wined3d_buffer_create_ib(device->wined3d_device, new_size * sizeof(*indices), 126 WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, WINED3D_POOL_DEFAULT, 127 NULL, &ddraw_null_wined3d_parent_ops, &new_buffer); 128 if (FAILED(hr)) 129 return hr; 130 131 buffer->index_size = new_size; 132 if (buffer->index_buffer) 133 wined3d_buffer_decref(buffer->index_buffer); 134 buffer->index_buffer = new_buffer; 135 index_pos = 0; 136 } 137 else if (buffer->index_size - index_count < index_pos) 138 { 139 index_pos = 0; 140 } 141 142 box.left = index_pos * sizeof(*indices); 143 box.right = (index_pos + index_count) * sizeof(*indices); 144 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->index_buffer), 0, 145 &map_desc, &box, index_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); 146 if (FAILED(hr)) 147 return hr; 148 indices = map_desc.data; 149 150 for (i = 0; i < count; ++i) 151 { 152 D3DTRIANGLE *ci = (D3DTRIANGLE *)instr; 153 TRACE(" v1: %d v2: %d v3: %d\n",ci->u1.v1, ci->u2.v2, ci->u3.v3); 154 TRACE(" Flags : "); 155 if (TRACE_ON(ddraw)) 156 { 157 /* Wireframe */ 158 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) 159 TRACE("EDGEENABLE1 "); 160 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2) 161 TRACE("EDGEENABLE2 "); 162 if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1) 163 TRACE("EDGEENABLE3 "); 164 /* Strips / Fans */ 165 if (ci->wFlags == D3DTRIFLAG_EVEN) 166 TRACE("EVEN "); 167 if (ci->wFlags == D3DTRIFLAG_ODD) 168 TRACE("ODD "); 169 if (ci->wFlags == D3DTRIFLAG_START) 170 TRACE("START "); 171 if ((ci->wFlags > 0) && (ci->wFlags < 30)) 172 TRACE("STARTFLAT(%u) ", ci->wFlags); 173 TRACE("\n"); 174 } 175 176 switch (primitive_size) 177 { 178 case 3: 179 indices[(i * primitive_size) + 2] = ci->u3.v3; 180 /* Drop through. */ 181 case 2: 182 indices[(i * primitive_size) + 1] = ci->u2.v2; 183 indices[(i * primitive_size) ] = ci->u1.v1; 184 } 185 instr += size; 186 } 187 188 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->index_buffer), 0); 189 190 wined3d_device_set_stream_source(device->wined3d_device, 0, 191 buffer->dst_vertex_buffer, 0, sizeof(D3DTLVERTEX)); 192 wined3d_device_set_vertex_declaration(device->wined3d_device, 193 ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX)); 194 wined3d_device_set_index_buffer(device->wined3d_device, buffer->index_buffer, WINED3DFMT_R16_UINT, 0); 195 wined3d_device_draw_indexed_primitive(device->wined3d_device, index_pos, index_count); 196 197 buffer->index_pos = index_pos + index_count; 198 break; 199 } 200 201 case D3DOP_MATRIXLOAD: 202 WARN("MATRIXLOAD-s (%u)\n", count); 203 instr += count * size; 204 break; 205 206 case D3DOP_MATRIXMULTIPLY: 207 TRACE("MATRIXMULTIPLY (%d)\n", count); 208 for (i = 0; i < count; ++i) 209 { 210 D3DMATRIXMULTIPLY *ci = (D3DMATRIXMULTIPLY *)instr; 211 D3DMATRIX *a, *b, *c; 212 213 a = ddraw_get_object(&device->handle_table, ci->hDestMatrix - 1, DDRAW_HANDLE_MATRIX); 214 b = ddraw_get_object(&device->handle_table, ci->hSrcMatrix1 - 1, DDRAW_HANDLE_MATRIX); 215 c = ddraw_get_object(&device->handle_table, ci->hSrcMatrix2 - 1, DDRAW_HANDLE_MATRIX); 216 217 if (!a || !b || !c) 218 { 219 ERR("Invalid matrix handle (a %#x -> %p, b %#x -> %p, c %#x -> %p).\n", 220 ci->hDestMatrix, a, ci->hSrcMatrix1, b, ci->hSrcMatrix2, c); 221 } 222 else 223 { 224 TRACE("dst %p, src1 %p, src2 %p.\n", a, b, c); 225 multiply_matrix(a, c, b); 226 } 227 228 instr += size; 229 } 230 break; 231 232 case D3DOP_STATETRANSFORM: 233 TRACE("STATETRANSFORM (%d)\n", count); 234 for (i = 0; i < count; ++i) 235 { 236 D3DSTATE *ci = (D3DSTATE *)instr; 237 D3DMATRIX *m; 238 239 m = ddraw_get_object(&device->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATRIX); 240 if (!m) 241 { 242 ERR("Invalid matrix handle %#x.\n", ci->u2.dwArg[0]); 243 } 244 else 245 { 246 if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_WORLD) 247 device->world = ci->u2.dwArg[0]; 248 if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_VIEW) 249 device->view = ci->u2.dwArg[0]; 250 if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_PROJECTION) 251 device->proj = ci->u2.dwArg[0]; 252 IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, 253 ci->u1.dtstTransformStateType, m); 254 } 255 256 instr += size; 257 } 258 break; 259 260 case D3DOP_STATELIGHT: 261 TRACE("STATELIGHT (%d)\n", count); 262 for (i = 0; i < count; ++i) 263 { 264 D3DSTATE *ci = (D3DSTATE *)instr; 265 266 if (FAILED(IDirect3DDevice3_SetLightState(&device->IDirect3DDevice3_iface, 267 ci->u1.dlstLightStateType, ci->u2.dwArg[0]))) 268 WARN("Failed to set light state.\n"); 269 270 instr += size; 271 } 272 break; 273 274 case D3DOP_STATERENDER: 275 TRACE("STATERENDER (%d)\n", count); 276 for (i = 0; i < count; ++i) 277 { 278 D3DSTATE *ci = (D3DSTATE *)instr; 279 280 if (FAILED(IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, 281 ci->u1.drstRenderStateType, ci->u2.dwArg[0]))) 282 WARN("Failed to set render state.\n"); 283 284 instr += size; 285 } 286 break; 287 288 case D3DOP_PROCESSVERTICES: 289 TRACE("PROCESSVERTICES (%d)\n", count); 290 291 for (i = 0; i < count; ++i) 292 { 293 D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr; 294 DWORD op = ci->dwFlags & D3DPROCESSVERTICES_OPMASK; 295 296 TRACE(" start %u, dest %u, count %u, flags %#x.\n", 297 ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags); 298 299 if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS) 300 { 301 static int once; 302 if (!once++) FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n"); 303 } 304 if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR) 305 FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n"); 306 307 switch (op) 308 { 309 case D3DPROCESSVERTICES_TRANSFORMLIGHT: 310 case D3DPROCESSVERTICES_TRANSFORM: 311 wined3d_device_set_stream_source(device->wined3d_device, 0, 312 buffer->src_vertex_buffer, buffer->src_vertex_pos, sizeof(D3DVERTEX)); 313 if (op == D3DPROCESSVERTICES_TRANSFORMLIGHT) 314 { 315 wined3d_device_set_vertex_declaration(device->wined3d_device, 316 ddraw_find_decl(device->ddraw, D3DFVF_VERTEX)); 317 wined3d_device_set_render_state(device->wined3d_device, 318 WINED3D_RS_LIGHTING, TRUE); 319 } 320 else 321 { 322 wined3d_device_set_vertex_declaration(device->wined3d_device, 323 ddraw_find_decl(device->ddraw, D3DFVF_LVERTEX)); 324 wined3d_device_set_render_state(device->wined3d_device, 325 WINED3D_RS_LIGHTING, FALSE); 326 } 327 328 wined3d_device_process_vertices(device->wined3d_device, ci->wStart, ci->wDest, 329 ci->dwCount, buffer->dst_vertex_buffer, NULL, 0, D3DFVF_TLVERTEX); 330 break; 331 332 case D3DPROCESSVERTICES_COPY: 333 box.left = (buffer->src_vertex_pos + ci->wStart) * sizeof(D3DTLVERTEX); 334 box.right = box.left + ci->dwCount * sizeof(D3DTLVERTEX); 335 box.top = box.front = 0; 336 box.bottom = box.back = 1; 337 wined3d_device_copy_sub_resource_region(device->wined3d_device, 338 wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0, 339 ci->wDest * sizeof(D3DTLVERTEX), 0, 0, 340 wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box); 341 break; 342 343 default: 344 FIXME("Unhandled vertex processing op %#x.\n", op); 345 break; 346 } 347 348 instr += size; 349 } 350 break; 351 352 case D3DOP_TEXTURELOAD: 353 TRACE("TEXTURELOAD (%u)\n", count); 354 355 for (i = 0; i < count; ++i) 356 { 357 D3DTEXTURELOAD *ci = (D3DTEXTURELOAD *)instr; 358 struct ddraw_surface *dst, *src; 359 360 instr += size; 361 362 if (!(dst = ddraw_get_object(&device->handle_table, 363 ci->hDestTexture - 1, DDRAW_HANDLE_SURFACE))) 364 { 365 WARN("Invalid destination texture handle %#x.\n", ci->hDestTexture); 366 continue; 367 } 368 if (!(src = ddraw_get_object(&device->handle_table, 369 ci->hSrcTexture - 1, DDRAW_HANDLE_SURFACE))) 370 { 371 WARN("Invalid source texture handle %#x.\n", ci->hSrcTexture); 372 continue; 373 } 374 375 IDirect3DTexture2_Load(&dst->IDirect3DTexture2_iface, &src->IDirect3DTexture2_iface); 376 } 377 break; 378 379 case D3DOP_EXIT: 380 TRACE("EXIT (%u)\n", count); 381 instr += size; 382 goto end_of_buffer; 383 384 case D3DOP_BRANCHFORWARD: 385 TRACE("BRANCHFORWARD (%d)\n", count); 386 for (i = 0; i < count; ++i) 387 { 388 D3DBRANCH *ci = (D3DBRANCH *)instr; 389 390 if ((buffer->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) 391 { 392 if (!ci->bNegate) 393 { 394 TRACE(" Branch to %d\n", ci->dwOffset); 395 if (ci->dwOffset) { 396 instr = (char*)current + ci->dwOffset; 397 break; 398 } 399 } 400 } 401 else 402 { 403 if (ci->bNegate) 404 { 405 TRACE(" Branch to %d\n", ci->dwOffset); 406 if (ci->dwOffset) { 407 instr = (char*)current + ci->dwOffset; 408 break; 409 } 410 } 411 } 412 413 instr += size; 414 } 415 break; 416 417 case D3DOP_SPAN: 418 WARN("SPAN-s (%u)\n", count); 419 instr += count * size; 420 break; 421 422 case D3DOP_SETSTATUS: 423 TRACE("SETSTATUS (%d)\n", count); 424 for (i = 0; i < count; ++i) 425 { 426 buffer->data.dsStatus = *(D3DSTATUS *)instr; 427 instr += size; 428 } 429 break; 430 431 default: 432 ERR("Unhandled OpCode %#x.\n",current->bOpcode); 433 instr += count * size; 434 break; 435 } 436 } 437 438 end_of_buffer: 439 return D3D_OK; 440 } 441 442 static inline struct d3d_execute_buffer *impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface) 443 { 444 return CONTAINING_RECORD(iface, struct d3d_execute_buffer, IDirect3DExecuteBuffer_iface); 445 } 446 447 static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID iid, void **out) 448 { 449 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); 450 451 if (IsEqualGUID(&IID_IDirect3DExecuteBuffer, iid) 452 || IsEqualGUID(&IID_IUnknown, iid)) 453 { 454 IDirect3DExecuteBuffer_AddRef(iface); 455 *out = iface; 456 return S_OK; 457 } 458 459 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); 460 461 *out = NULL; 462 return E_NOINTERFACE; 463 } 464 465 /***************************************************************************** 466 * IDirect3DExecuteBuffer::AddRef 467 * 468 * A normal AddRef method, nothing special 469 * 470 * Returns: 471 * The new refcount 472 * 473 *****************************************************************************/ 474 static ULONG WINAPI d3d_execute_buffer_AddRef(IDirect3DExecuteBuffer *iface) 475 { 476 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 477 ULONG ref = InterlockedIncrement(&buffer->ref); 478 479 TRACE("%p increasing refcount to %u.\n", buffer, ref); 480 481 return ref; 482 } 483 484 /***************************************************************************** 485 * IDirect3DExecuteBuffer::Release 486 * 487 * A normal Release method, nothing special 488 * 489 * Returns: 490 * The new refcount 491 * 492 *****************************************************************************/ 493 static ULONG WINAPI d3d_execute_buffer_Release(IDirect3DExecuteBuffer *iface) 494 { 495 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 496 ULONG ref = InterlockedDecrement(&buffer->ref); 497 498 TRACE("%p decreasing refcount to %u.\n", buffer, ref); 499 500 if (!ref) 501 { 502 if (buffer->need_free) 503 HeapFree(GetProcessHeap(), 0, buffer->desc.lpData); 504 if (buffer->index_buffer) 505 wined3d_buffer_decref(buffer->index_buffer); 506 if (buffer->dst_vertex_buffer) 507 { 508 wined3d_buffer_decref(buffer->src_vertex_buffer); 509 wined3d_buffer_decref(buffer->dst_vertex_buffer); 510 } 511 HeapFree(GetProcessHeap(), 0, buffer); 512 } 513 514 return ref; 515 } 516 517 /***************************************************************************** 518 * IDirect3DExecuteBuffer::Initialize 519 * 520 * Initializes the Execute Buffer. This method exists for COM compliance 521 * Nothing to do here. 522 * 523 * Returns: 524 * D3D_OK 525 * 526 *****************************************************************************/ 527 static HRESULT WINAPI d3d_execute_buffer_Initialize(IDirect3DExecuteBuffer *iface, 528 IDirect3DDevice *device, D3DEXECUTEBUFFERDESC *desc) 529 { 530 TRACE("iface %p, device %p, desc %p.\n", iface, device, desc); 531 532 return D3D_OK; 533 } 534 535 /***************************************************************************** 536 * IDirect3DExecuteBuffer::Lock 537 * 538 * Locks the buffer, so the app can write into it. 539 * 540 * Params: 541 * Desc: Pointer to return the buffer description. This Description contains 542 * a pointer to the buffer data. 543 * 544 * Returns: 545 * This implementation always returns D3D_OK 546 * 547 *****************************************************************************/ 548 static HRESULT WINAPI d3d_execute_buffer_Lock(IDirect3DExecuteBuffer *iface, D3DEXECUTEBUFFERDESC *desc) 549 { 550 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 551 DWORD dwSize; 552 553 TRACE("iface %p, desc %p.\n", iface, desc); 554 555 dwSize = desc->dwSize; 556 memcpy(desc, &buffer->desc, dwSize); 557 558 if (TRACE_ON(ddraw)) 559 { 560 TRACE(" Returning description :\n"); 561 _dump_D3DEXECUTEBUFFERDESC(desc); 562 } 563 return D3D_OK; 564 } 565 566 /***************************************************************************** 567 * IDirect3DExecuteBuffer::Unlock 568 * 569 * Unlocks the buffer. We don't have anything to do here 570 * 571 * Returns: 572 * This implementation always returns D3D_OK 573 * 574 *****************************************************************************/ 575 static HRESULT WINAPI d3d_execute_buffer_Unlock(IDirect3DExecuteBuffer *iface) 576 { 577 TRACE("iface %p.\n", iface); 578 579 return D3D_OK; 580 } 581 582 /***************************************************************************** 583 * IDirect3DExecuteBuffer::SetExecuteData 584 * 585 * Sets the execute data. This data is used to describe the buffer's content 586 * 587 * Params: 588 * Data: Pointer to a D3DEXECUTEDATA structure containing the data to 589 * assign 590 * 591 * Returns: 592 * D3D_OK on success 593 * DDERR_OUTOFMEMORY if the vertex buffer allocation failed 594 * 595 *****************************************************************************/ 596 static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data) 597 { 598 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 599 struct wined3d_map_desc map_desc; 600 struct wined3d_box box = {0}; 601 HRESULT hr; 602 603 TRACE("iface %p, data %p.\n", iface, data); 604 605 /* Skip past previous vertex data. */ 606 buffer->src_vertex_pos += buffer->data.dwVertexCount; 607 608 if (buffer->vertex_size < data->dwVertexCount) 609 { 610 unsigned int new_size = max(data->dwVertexCount, buffer->vertex_size * 2); 611 struct wined3d_buffer *src_buffer, *dst_buffer; 612 613 hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DVERTEX), 614 WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, WINED3D_POOL_SYSTEM_MEM, 615 NULL, &ddraw_null_wined3d_parent_ops, &src_buffer); 616 if (FAILED(hr)) 617 return hr; 618 619 hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DTLVERTEX), 620 WINED3DUSAGE_STATICDECL, WINED3D_POOL_DEFAULT, 621 NULL, &ddraw_null_wined3d_parent_ops, &dst_buffer); 622 if (FAILED(hr)) 623 { 624 wined3d_buffer_decref(src_buffer); 625 return hr; 626 } 627 628 if (buffer->dst_vertex_buffer) 629 { 630 wined3d_buffer_decref(buffer->src_vertex_buffer); 631 wined3d_buffer_decref(buffer->dst_vertex_buffer); 632 } 633 buffer->src_vertex_buffer = src_buffer; 634 buffer->dst_vertex_buffer = dst_buffer; 635 buffer->vertex_size = new_size; 636 buffer->src_vertex_pos = 0; 637 } 638 else if (buffer->vertex_size - data->dwVertexCount < buffer->src_vertex_pos) 639 { 640 buffer->src_vertex_pos = 0; 641 } 642 643 if (data->dwVertexCount) 644 { 645 box.left = buffer->src_vertex_pos * sizeof(D3DVERTEX); 646 box.right = box.left + data->dwVertexCount * sizeof(D3DVERTEX); 647 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, 648 &map_desc, &box, buffer->src_vertex_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); 649 if (FAILED(hr)) 650 return hr; 651 652 memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset, 653 data->dwVertexCount * sizeof(D3DVERTEX)); 654 655 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0); 656 } 657 658 memcpy(&buffer->data, data, data->dwSize); 659 660 if (TRACE_ON(ddraw)) 661 _dump_executedata(data); 662 663 return D3D_OK; 664 } 665 666 /***************************************************************************** 667 * IDirect3DExecuteBuffer::GetExecuteData 668 * 669 * Returns the data in the execute buffer 670 * 671 * Params: 672 * Data: Pointer to a D3DEXECUTEDATA structure used to return data 673 * 674 * Returns: 675 * D3D_OK on success 676 * 677 *****************************************************************************/ 678 static HRESULT WINAPI d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data) 679 { 680 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 681 DWORD dwSize; 682 683 TRACE("iface %p, data %p.\n", iface, data); 684 685 dwSize = data->dwSize; 686 memcpy(data, &buffer->data, dwSize); 687 688 if (TRACE_ON(ddraw)) 689 { 690 TRACE("Returning data :\n"); 691 _dump_executedata(data); 692 } 693 694 return DD_OK; 695 } 696 697 /***************************************************************************** 698 * IDirect3DExecuteBuffer::Validate 699 * 700 * DirectX 5 SDK: "The IDirect3DExecuteBuffer::Validate method is not 701 * currently implemented" 702 * 703 * Params: 704 * ? 705 * 706 * Returns: 707 * DDERR_UNSUPPORTED, because it's not implemented in Windows. 708 * 709 *****************************************************************************/ 710 static HRESULT WINAPI d3d_execute_buffer_Validate(IDirect3DExecuteBuffer *iface, 711 DWORD *offset, LPD3DVALIDATECALLBACK callback, void *context, DWORD reserved) 712 { 713 TRACE("iface %p, offset %p, callback %p, context %p, reserved %#x.\n", 714 iface, offset, callback, context, reserved); 715 716 WARN("Not implemented.\n"); 717 718 return DDERR_UNSUPPORTED; /* Unchecked */ 719 } 720 721 /***************************************************************************** 722 * IDirect3DExecuteBuffer::Optimize 723 * 724 * DirectX5 SDK: "The IDirect3DExecuteBuffer::Optimize method is not 725 * currently supported" 726 * 727 * Params: 728 * Dummy: Seems to be an unused dummy ;) 729 * 730 * Returns: 731 * DDERR_UNSUPPORTED, because it's not implemented in Windows. 732 * 733 *****************************************************************************/ 734 static HRESULT WINAPI d3d_execute_buffer_Optimize(IDirect3DExecuteBuffer *iface, DWORD reserved) 735 { 736 TRACE("iface %p, reserved %#x.\n", iface, reserved); 737 738 WARN("Not implemented.\n"); 739 740 return DDERR_UNSUPPORTED; /* Unchecked */ 741 } 742 743 static const struct IDirect3DExecuteBufferVtbl d3d_execute_buffer_vtbl = 744 { 745 d3d_execute_buffer_QueryInterface, 746 d3d_execute_buffer_AddRef, 747 d3d_execute_buffer_Release, 748 d3d_execute_buffer_Initialize, 749 d3d_execute_buffer_Lock, 750 d3d_execute_buffer_Unlock, 751 d3d_execute_buffer_SetExecuteData, 752 d3d_execute_buffer_GetExecuteData, 753 d3d_execute_buffer_Validate, 754 d3d_execute_buffer_Optimize, 755 }; 756 757 HRESULT d3d_execute_buffer_init(struct d3d_execute_buffer *execute_buffer, 758 struct d3d_device *device, D3DEXECUTEBUFFERDESC *desc) 759 { 760 execute_buffer->IDirect3DExecuteBuffer_iface.lpVtbl = &d3d_execute_buffer_vtbl; 761 execute_buffer->ref = 1; 762 execute_buffer->d3ddev = device; 763 764 /* Initializes memory */ 765 memcpy(&execute_buffer->desc, desc, desc->dwSize); 766 767 /* No buffer given */ 768 if (!(execute_buffer->desc.dwFlags & D3DDEB_LPDATA)) 769 execute_buffer->desc.lpData = NULL; 770 771 /* No buffer size given */ 772 if (!(execute_buffer->desc.dwFlags & D3DDEB_BUFSIZE)) 773 execute_buffer->desc.dwBufferSize = 0; 774 775 /* Create buffer if asked */ 776 if (!execute_buffer->desc.lpData && execute_buffer->desc.dwBufferSize) 777 { 778 execute_buffer->need_free = TRUE; 779 execute_buffer->desc.lpData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, execute_buffer->desc.dwBufferSize); 780 if (!execute_buffer->desc.lpData) 781 { 782 ERR("Failed to allocate execute buffer data.\n"); 783 return DDERR_OUTOFMEMORY; 784 } 785 } 786 787 execute_buffer->desc.dwFlags |= D3DDEB_LPDATA; 788 789 return D3D_OK; 790 } 791 792 struct d3d_execute_buffer *unsafe_impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface) 793 { 794 if (!iface) 795 return NULL; 796 assert(iface->lpVtbl == &d3d_execute_buffer_vtbl); 797 798 return impl_from_IDirect3DExecuteBuffer(iface); 799 } 800