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 FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n"); 301 if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR) 302 FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n"); 303 304 switch (op) 305 { 306 case D3DPROCESSVERTICES_TRANSFORMLIGHT: 307 case D3DPROCESSVERTICES_TRANSFORM: 308 wined3d_device_set_stream_source(device->wined3d_device, 0, 309 buffer->src_vertex_buffer, buffer->src_vertex_pos, sizeof(D3DVERTEX)); 310 if (op == D3DPROCESSVERTICES_TRANSFORMLIGHT) 311 { 312 wined3d_device_set_vertex_declaration(device->wined3d_device, 313 ddraw_find_decl(device->ddraw, D3DFVF_VERTEX)); 314 wined3d_device_set_render_state(device->wined3d_device, 315 WINED3D_RS_LIGHTING, TRUE); 316 } 317 else 318 { 319 wined3d_device_set_vertex_declaration(device->wined3d_device, 320 ddraw_find_decl(device->ddraw, D3DFVF_LVERTEX)); 321 wined3d_device_set_render_state(device->wined3d_device, 322 WINED3D_RS_LIGHTING, FALSE); 323 } 324 325 wined3d_device_process_vertices(device->wined3d_device, ci->wStart, ci->wDest, 326 ci->dwCount, buffer->dst_vertex_buffer, NULL, 0, D3DFVF_TLVERTEX); 327 break; 328 329 case D3DPROCESSVERTICES_COPY: 330 box.left = (buffer->src_vertex_pos + ci->wStart) * sizeof(D3DTLVERTEX); 331 box.right = box.left + ci->dwCount * sizeof(D3DTLVERTEX); 332 box.top = box.front = 0; 333 box.bottom = box.back = 1; 334 wined3d_device_copy_sub_resource_region(device->wined3d_device, 335 wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0, 336 ci->wDest * sizeof(D3DTLVERTEX), 0, 0, 337 wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, &box); 338 break; 339 340 default: 341 FIXME("Unhandled vertex processing op %#x.\n", op); 342 break; 343 } 344 345 instr += size; 346 } 347 break; 348 349 case D3DOP_TEXTURELOAD: 350 TRACE("TEXTURELOAD (%u)\n", count); 351 352 for (i = 0; i < count; ++i) 353 { 354 D3DTEXTURELOAD *ci = (D3DTEXTURELOAD *)instr; 355 struct ddraw_surface *dst, *src; 356 357 instr += size; 358 359 if (!(dst = ddraw_get_object(&device->handle_table, 360 ci->hDestTexture - 1, DDRAW_HANDLE_SURFACE))) 361 { 362 WARN("Invalid destination texture handle %#x.\n", ci->hDestTexture); 363 continue; 364 } 365 if (!(src = ddraw_get_object(&device->handle_table, 366 ci->hSrcTexture - 1, DDRAW_HANDLE_SURFACE))) 367 { 368 WARN("Invalid source texture handle %#x.\n", ci->hSrcTexture); 369 continue; 370 } 371 372 IDirect3DTexture2_Load(&dst->IDirect3DTexture2_iface, &src->IDirect3DTexture2_iface); 373 } 374 break; 375 376 case D3DOP_EXIT: 377 TRACE("EXIT (%u)\n", count); 378 instr += size; 379 goto end_of_buffer; 380 381 case D3DOP_BRANCHFORWARD: 382 TRACE("BRANCHFORWARD (%d)\n", count); 383 for (i = 0; i < count; ++i) 384 { 385 D3DBRANCH *ci = (D3DBRANCH *)instr; 386 387 if ((buffer->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) 388 { 389 if (!ci->bNegate) 390 { 391 TRACE(" Branch to %d\n", ci->dwOffset); 392 if (ci->dwOffset) { 393 instr = (char*)current + ci->dwOffset; 394 break; 395 } 396 } 397 } 398 else 399 { 400 if (ci->bNegate) 401 { 402 TRACE(" Branch to %d\n", ci->dwOffset); 403 if (ci->dwOffset) { 404 instr = (char*)current + ci->dwOffset; 405 break; 406 } 407 } 408 } 409 410 instr += size; 411 } 412 break; 413 414 case D3DOP_SPAN: 415 WARN("SPAN-s (%u)\n", count); 416 instr += count * size; 417 break; 418 419 case D3DOP_SETSTATUS: 420 TRACE("SETSTATUS (%d)\n", count); 421 for (i = 0; i < count; ++i) 422 { 423 buffer->data.dsStatus = *(D3DSTATUS *)instr; 424 instr += size; 425 } 426 break; 427 428 default: 429 ERR("Unhandled OpCode %#x.\n",current->bOpcode); 430 instr += count * size; 431 break; 432 } 433 } 434 435 end_of_buffer: 436 return D3D_OK; 437 } 438 439 static inline struct d3d_execute_buffer *impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface) 440 { 441 return CONTAINING_RECORD(iface, struct d3d_execute_buffer, IDirect3DExecuteBuffer_iface); 442 } 443 444 static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID iid, void **out) 445 { 446 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); 447 448 if (IsEqualGUID(&IID_IDirect3DExecuteBuffer, iid) 449 || IsEqualGUID(&IID_IUnknown, iid)) 450 { 451 IDirect3DExecuteBuffer_AddRef(iface); 452 *out = iface; 453 return S_OK; 454 } 455 456 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); 457 458 *out = NULL; 459 return E_NOINTERFACE; 460 } 461 462 /***************************************************************************** 463 * IDirect3DExecuteBuffer::AddRef 464 * 465 * A normal AddRef method, nothing special 466 * 467 * Returns: 468 * The new refcount 469 * 470 *****************************************************************************/ 471 static ULONG WINAPI d3d_execute_buffer_AddRef(IDirect3DExecuteBuffer *iface) 472 { 473 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 474 ULONG ref = InterlockedIncrement(&buffer->ref); 475 476 TRACE("%p increasing refcount to %u.\n", buffer, ref); 477 478 return ref; 479 } 480 481 /***************************************************************************** 482 * IDirect3DExecuteBuffer::Release 483 * 484 * A normal Release method, nothing special 485 * 486 * Returns: 487 * The new refcount 488 * 489 *****************************************************************************/ 490 static ULONG WINAPI d3d_execute_buffer_Release(IDirect3DExecuteBuffer *iface) 491 { 492 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 493 ULONG ref = InterlockedDecrement(&buffer->ref); 494 495 TRACE("%p decreasing refcount to %u.\n", buffer, ref); 496 497 if (!ref) 498 { 499 if (buffer->need_free) 500 HeapFree(GetProcessHeap(), 0, buffer->desc.lpData); 501 if (buffer->index_buffer) 502 wined3d_buffer_decref(buffer->index_buffer); 503 if (buffer->dst_vertex_buffer) 504 { 505 wined3d_buffer_decref(buffer->src_vertex_buffer); 506 wined3d_buffer_decref(buffer->dst_vertex_buffer); 507 } 508 HeapFree(GetProcessHeap(), 0, buffer); 509 } 510 511 return ref; 512 } 513 514 /***************************************************************************** 515 * IDirect3DExecuteBuffer::Initialize 516 * 517 * Initializes the Execute Buffer. This method exists for COM compliance 518 * Nothing to do here. 519 * 520 * Returns: 521 * D3D_OK 522 * 523 *****************************************************************************/ 524 static HRESULT WINAPI d3d_execute_buffer_Initialize(IDirect3DExecuteBuffer *iface, 525 IDirect3DDevice *device, D3DEXECUTEBUFFERDESC *desc) 526 { 527 TRACE("iface %p, device %p, desc %p.\n", iface, device, desc); 528 529 return D3D_OK; 530 } 531 532 /***************************************************************************** 533 * IDirect3DExecuteBuffer::Lock 534 * 535 * Locks the buffer, so the app can write into it. 536 * 537 * Params: 538 * Desc: Pointer to return the buffer description. This Description contains 539 * a pointer to the buffer data. 540 * 541 * Returns: 542 * This implementation always returns D3D_OK 543 * 544 *****************************************************************************/ 545 static HRESULT WINAPI d3d_execute_buffer_Lock(IDirect3DExecuteBuffer *iface, D3DEXECUTEBUFFERDESC *desc) 546 { 547 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 548 DWORD dwSize; 549 550 TRACE("iface %p, desc %p.\n", iface, desc); 551 552 dwSize = desc->dwSize; 553 memcpy(desc, &buffer->desc, dwSize); 554 555 if (TRACE_ON(ddraw)) 556 { 557 TRACE(" Returning description :\n"); 558 _dump_D3DEXECUTEBUFFERDESC(desc); 559 } 560 return D3D_OK; 561 } 562 563 /***************************************************************************** 564 * IDirect3DExecuteBuffer::Unlock 565 * 566 * Unlocks the buffer. We don't have anything to do here 567 * 568 * Returns: 569 * This implementation always returns D3D_OK 570 * 571 *****************************************************************************/ 572 static HRESULT WINAPI d3d_execute_buffer_Unlock(IDirect3DExecuteBuffer *iface) 573 { 574 TRACE("iface %p.\n", iface); 575 576 return D3D_OK; 577 } 578 579 /***************************************************************************** 580 * IDirect3DExecuteBuffer::SetExecuteData 581 * 582 * Sets the execute data. This data is used to describe the buffer's content 583 * 584 * Params: 585 * Data: Pointer to a D3DEXECUTEDATA structure containing the data to 586 * assign 587 * 588 * Returns: 589 * D3D_OK on success 590 * DDERR_OUTOFMEMORY if the vertex buffer allocation failed 591 * 592 *****************************************************************************/ 593 static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data) 594 { 595 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 596 struct wined3d_map_desc map_desc; 597 struct wined3d_box box = {0}; 598 HRESULT hr; 599 600 TRACE("iface %p, data %p.\n", iface, data); 601 602 /* Skip past previous vertex data. */ 603 buffer->src_vertex_pos += buffer->data.dwVertexCount; 604 605 if (buffer->vertex_size < data->dwVertexCount) 606 { 607 unsigned int new_size = max(data->dwVertexCount, buffer->vertex_size * 2); 608 struct wined3d_buffer *src_buffer, *dst_buffer; 609 610 hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DVERTEX), 611 WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, WINED3D_POOL_SYSTEM_MEM, 612 NULL, &ddraw_null_wined3d_parent_ops, &src_buffer); 613 if (FAILED(hr)) 614 return hr; 615 616 hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DTLVERTEX), 617 WINED3DUSAGE_STATICDECL, WINED3D_POOL_DEFAULT, 618 NULL, &ddraw_null_wined3d_parent_ops, &dst_buffer); 619 if (FAILED(hr)) 620 { 621 wined3d_buffer_decref(src_buffer); 622 return hr; 623 } 624 625 if (buffer->dst_vertex_buffer) 626 { 627 wined3d_buffer_decref(buffer->src_vertex_buffer); 628 wined3d_buffer_decref(buffer->dst_vertex_buffer); 629 } 630 buffer->src_vertex_buffer = src_buffer; 631 buffer->dst_vertex_buffer = dst_buffer; 632 buffer->vertex_size = new_size; 633 buffer->src_vertex_pos = 0; 634 } 635 else if (buffer->vertex_size - data->dwVertexCount < buffer->src_vertex_pos) 636 { 637 buffer->src_vertex_pos = 0; 638 } 639 640 if (data->dwVertexCount) 641 { 642 box.left = buffer->src_vertex_pos * sizeof(D3DVERTEX); 643 box.right = box.left + data->dwVertexCount * sizeof(D3DVERTEX); 644 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0, 645 &map_desc, &box, buffer->src_vertex_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); 646 if (FAILED(hr)) 647 return hr; 648 649 memcpy(map_desc.data, ((BYTE *)buffer->desc.lpData) + data->dwVertexOffset, 650 data->dwVertexCount * sizeof(D3DVERTEX)); 651 652 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->src_vertex_buffer), 0); 653 } 654 655 memcpy(&buffer->data, data, data->dwSize); 656 657 if (TRACE_ON(ddraw)) 658 _dump_executedata(data); 659 660 return D3D_OK; 661 } 662 663 /***************************************************************************** 664 * IDirect3DExecuteBuffer::GetExecuteData 665 * 666 * Returns the data in the execute buffer 667 * 668 * Params: 669 * Data: Pointer to a D3DEXECUTEDATA structure used to return data 670 * 671 * Returns: 672 * D3D_OK on success 673 * 674 *****************************************************************************/ 675 static HRESULT WINAPI d3d_execute_buffer_GetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data) 676 { 677 struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); 678 DWORD dwSize; 679 680 TRACE("iface %p, data %p.\n", iface, data); 681 682 dwSize = data->dwSize; 683 memcpy(data, &buffer->data, dwSize); 684 685 if (TRACE_ON(ddraw)) 686 { 687 TRACE("Returning data :\n"); 688 _dump_executedata(data); 689 } 690 691 return DD_OK; 692 } 693 694 /***************************************************************************** 695 * IDirect3DExecuteBuffer::Validate 696 * 697 * DirectX 5 SDK: "The IDirect3DExecuteBuffer::Validate method is not 698 * currently implemented" 699 * 700 * Params: 701 * ? 702 * 703 * Returns: 704 * DDERR_UNSUPPORTED, because it's not implemented in Windows. 705 * 706 *****************************************************************************/ 707 static HRESULT WINAPI d3d_execute_buffer_Validate(IDirect3DExecuteBuffer *iface, 708 DWORD *offset, LPD3DVALIDATECALLBACK callback, void *context, DWORD reserved) 709 { 710 TRACE("iface %p, offset %p, callback %p, context %p, reserved %#x.\n", 711 iface, offset, callback, context, reserved); 712 713 WARN("Not implemented.\n"); 714 715 return DDERR_UNSUPPORTED; /* Unchecked */ 716 } 717 718 /***************************************************************************** 719 * IDirect3DExecuteBuffer::Optimize 720 * 721 * DirectX5 SDK: "The IDirect3DExecuteBuffer::Optimize method is not 722 * currently supported" 723 * 724 * Params: 725 * Dummy: Seems to be an unused dummy ;) 726 * 727 * Returns: 728 * DDERR_UNSUPPORTED, because it's not implemented in Windows. 729 * 730 *****************************************************************************/ 731 static HRESULT WINAPI d3d_execute_buffer_Optimize(IDirect3DExecuteBuffer *iface, DWORD reserved) 732 { 733 TRACE("iface %p, reserved %#x.\n", iface, reserved); 734 735 WARN("Not implemented.\n"); 736 737 return DDERR_UNSUPPORTED; /* Unchecked */ 738 } 739 740 static const struct IDirect3DExecuteBufferVtbl d3d_execute_buffer_vtbl = 741 { 742 d3d_execute_buffer_QueryInterface, 743 d3d_execute_buffer_AddRef, 744 d3d_execute_buffer_Release, 745 d3d_execute_buffer_Initialize, 746 d3d_execute_buffer_Lock, 747 d3d_execute_buffer_Unlock, 748 d3d_execute_buffer_SetExecuteData, 749 d3d_execute_buffer_GetExecuteData, 750 d3d_execute_buffer_Validate, 751 d3d_execute_buffer_Optimize, 752 }; 753 754 HRESULT d3d_execute_buffer_init(struct d3d_execute_buffer *execute_buffer, 755 struct d3d_device *device, D3DEXECUTEBUFFERDESC *desc) 756 { 757 execute_buffer->IDirect3DExecuteBuffer_iface.lpVtbl = &d3d_execute_buffer_vtbl; 758 execute_buffer->ref = 1; 759 execute_buffer->d3ddev = device; 760 761 /* Initializes memory */ 762 memcpy(&execute_buffer->desc, desc, desc->dwSize); 763 764 /* No buffer given */ 765 if (!(execute_buffer->desc.dwFlags & D3DDEB_LPDATA)) 766 execute_buffer->desc.lpData = NULL; 767 768 /* No buffer size given */ 769 if (!(execute_buffer->desc.dwFlags & D3DDEB_BUFSIZE)) 770 execute_buffer->desc.dwBufferSize = 0; 771 772 /* Create buffer if asked */ 773 if (!execute_buffer->desc.lpData && execute_buffer->desc.dwBufferSize) 774 { 775 execute_buffer->need_free = TRUE; 776 execute_buffer->desc.lpData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, execute_buffer->desc.dwBufferSize); 777 if (!execute_buffer->desc.lpData) 778 { 779 ERR("Failed to allocate execute buffer data.\n"); 780 return DDERR_OUTOFMEMORY; 781 } 782 } 783 784 execute_buffer->desc.dwFlags |= D3DDEB_LPDATA; 785 786 return D3D_OK; 787 } 788 789 struct d3d_execute_buffer *unsafe_impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface) 790 { 791 if (!iface) 792 return NULL; 793 assert(iface->lpVtbl == &d3d_execute_buffer_vtbl); 794 795 return impl_from_IDirect3DExecuteBuffer(iface); 796 } 797