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