ddraw: Use d3d buffers for executebuffer data.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmx.at>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Stefan Dösinger 2016-10-30 07:02:21 -07:00 committed by Alexandre Julliard
parent cc77571898
commit b7c9d14e8e
2 changed files with 101 additions and 30 deletions

View File

@ -525,8 +525,9 @@ struct d3d_execute_buffer
/* This buffer will store the transformed vertices */ /* This buffer will store the transformed vertices */
void *vertex_data; void *vertex_data;
WORD *indices; WORD *indices;
unsigned int nb_indices; unsigned int index_size;
unsigned int nb_vertices; unsigned int vertex_size;
struct wined3d_buffer *dst_vertex_buffer, *index_buffer;
/* This flags is set to TRUE if we allocated ourselves the /* This flags is set to TRUE if we allocated ourselves the
* data buffer * data buffer

View File

@ -70,6 +70,9 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
DWORD is = buffer->data.dwInstructionOffset; DWORD is = buffer->data.dwInstructionOffset;
char *instr = (char *)buffer->desc.lpData + is; char *instr = (char *)buffer->desc.lpData + is;
unsigned int i; unsigned int i;
struct wined3d_map_desc map_desc;
struct wined3d_box box = {0};
HRESULT hr;
if (viewport->active_device != device) if (viewport->active_device != device)
{ {
@ -108,21 +111,42 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
case D3DOP_TRIANGLE: case D3DOP_TRIANGLE:
{ {
D3DTLVERTEX *tl_vx = buffer->vertex_data; WORD *indices;
TRACE("TRIANGLE (%d)\n", count); TRACE("TRIANGLE (%d)\n", count);
if (buffer->nb_indices < count * 3) if (!count)
break;
if (buffer->index_size < count * 3)
{ {
buffer->nb_indices = count * 3; struct wined3d_buffer *new_buffer;
HeapFree(GetProcessHeap(), 0, buffer->indices); unsigned int new_size = max(buffer->index_size * 2, count * 3);
buffer->indices = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer->indices) * buffer->nb_indices);
hr = wined3d_buffer_create_ib(device->wined3d_device, new_size * sizeof(*indices),
WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, WINED3D_POOL_DEFAULT,
NULL, &ddraw_null_wined3d_parent_ops, &new_buffer);
if (FAILED(hr))
return hr;
buffer->index_size = new_size;
if (buffer->index_buffer)
wined3d_buffer_decref(buffer->index_buffer);
buffer->index_buffer = new_buffer;
} }
box.left = 0;
box.right = count * 3 * sizeof(*indices);
hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->index_buffer), 0,
&map_desc, &box, WINED3D_MAP_DISCARD);
if (FAILED(hr))
return hr;
indices = map_desc.data;
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
D3DTRIANGLE *ci = (D3DTRIANGLE *)instr; D3DTRIANGLE *ci = (D3DTRIANGLE *)instr;
TRACE(" v1: %d v2: %d v3: %d\n",ci->u1.v1, ci->u2.v2, ci->u3.v3); TRACE(" v1: %d v2: %d v3: %d\n",ci->u1.v1, ci->u2.v2, ci->u3.v3);
TRACE(" Flags : "); TRACE(" Flags : ");
if (TRACE_ON(ddraw)) if (TRACE_ON(ddraw))
{ {
/* Wireframe */ /* Wireframe */
@ -143,14 +167,21 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
TRACE("STARTFLAT(%u) ", ci->wFlags); TRACE("STARTFLAT(%u) ", ci->wFlags);
TRACE("\n"); TRACE("\n");
} }
buffer->indices[(i * 3) ] = ci->u1.v1; indices[(i * 3) ] = ci->u1.v1;
buffer->indices[(i * 3) + 1] = ci->u2.v2; indices[(i * 3) + 1] = ci->u2.v2;
buffer->indices[(i * 3) + 2] = ci->u3.v3; indices[(i * 3) + 2] = ci->u3.v3;
instr += size; instr += size;
} }
IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX, tl_vx, buffer->nb_vertices, wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->index_buffer), 0);
buffer->indices, count * 3, 0);
wined3d_device_set_stream_source(device->wined3d_device, 0,
buffer->dst_vertex_buffer, 0, sizeof(D3DTLVERTEX));
wined3d_device_set_vertex_declaration(device->wined3d_device,
ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX));
wined3d_device_set_index_buffer(device->wined3d_device, buffer->index_buffer, WINED3DFMT_R16_UINT, 0);
wined3d_device_set_primitive_type(device->wined3d_device, WINED3D_PT_TRIANGLELIST);
wined3d_device_draw_indexed_primitive(device->wined3d_device, 0, count * 3);
} break; } break;
case D3DOP_MATRIXLOAD: case D3DOP_MATRIXLOAD:
@ -273,8 +304,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr; D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr;
D3DTLVERTEX *dst = (D3DTLVERTEX *)buffer->vertex_data + ci->wDest;
DWORD op = ci->dwFlags & D3DPROCESSVERTICES_OPMASK; DWORD op = ci->dwFlags & D3DPROCESSVERTICES_OPMASK;
D3DTLVERTEX *src, *dst;
TRACE(" start %u, dest %u, count %u, flags %#x.\n", TRACE(" start %u, dest %u, count %u, flags %#x.\n",
ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags); ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags);
@ -295,6 +326,14 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
if (!once++) if (!once++)
FIXME("Lighting not implemented.\n"); FIXME("Lighting not implemented.\n");
box.left = ci->wDest * sizeof(*dst);
box.right = (ci->wDest + ci->dwCount) * sizeof(*dst);
hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0,
&map_desc, &box, 0);
if (FAILED(hr))
return hr;
dst = map_desc.data;
for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx) for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx)
{ {
transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1, transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1,
@ -305,6 +344,9 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
dst[vtx_idx].u7.tu = src[vtx_idx].u7.tu; dst[vtx_idx].u7.tu = src[vtx_idx].u7.tu;
dst[vtx_idx].u8.tv = src[vtx_idx].u8.tv; dst[vtx_idx].u8.tv = src[vtx_idx].u8.tv;
} }
wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0);
break; break;
} }
@ -313,6 +355,14 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
const D3DLVERTEX *src = (D3DLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart; const D3DLVERTEX *src = (D3DLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
unsigned int vtx_idx; unsigned int vtx_idx;
box.left = ci->wDest * sizeof(*dst);
box.right = (ci->wDest + ci->dwCount) * sizeof(*dst);
hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0,
&map_desc, &box, 0);
if (FAILED(hr))
return hr;
dst = map_desc.data;
for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx) for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx)
{ {
transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1, transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1,
@ -322,16 +372,25 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
dst[vtx_idx].u7.tu = src[vtx_idx].u6.tu; dst[vtx_idx].u7.tu = src[vtx_idx].u6.tu;
dst[vtx_idx].u8.tv = src[vtx_idx].u7.tv; dst[vtx_idx].u8.tv = src[vtx_idx].u7.tv;
} }
wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0);
break; break;
} }
case D3DPROCESSVERTICES_COPY: case D3DPROCESSVERTICES_COPY:
{ box.left = ci->wDest * sizeof(*src);
const D3DTLVERTEX *src = (D3DTLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart; box.right = (ci->wDest + ci->dwCount) * sizeof(*src);
hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0,
&map_desc, &box, 0);
if (FAILED(hr))
return hr;
memcpy(dst, src, ci->dwCount * sizeof(*dst)); src = (D3DTLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
memcpy(map_desc.data, src, ci->dwCount * sizeof(*src));
wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->dst_vertex_buffer), 0);
break; break;
}
default: default:
FIXME("Unhandled vertex processing op %#x.\n", op); FIXME("Unhandled vertex processing op %#x.\n", op);
@ -476,8 +535,10 @@ static ULONG WINAPI d3d_execute_buffer_Release(IDirect3DExecuteBuffer *iface)
{ {
if (buffer->need_free) if (buffer->need_free)
HeapFree(GetProcessHeap(), 0, buffer->desc.lpData); HeapFree(GetProcessHeap(), 0, buffer->desc.lpData);
HeapFree(GetProcessHeap(), 0, buffer->vertex_data); if (buffer->index_buffer)
HeapFree(GetProcessHeap(), 0, buffer->indices); wined3d_buffer_decref(buffer->index_buffer);
if (buffer->dst_vertex_buffer)
wined3d_buffer_decref(buffer->dst_vertex_buffer);
HeapFree(GetProcessHeap(), 0, buffer); HeapFree(GetProcessHeap(), 0, buffer);
} }
@ -566,19 +627,28 @@ static HRESULT WINAPI d3d_execute_buffer_Unlock(IDirect3DExecuteBuffer *iface)
static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data) static HRESULT WINAPI d3d_execute_buffer_SetExecuteData(IDirect3DExecuteBuffer *iface, D3DEXECUTEDATA *data)
{ {
struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface); struct d3d_execute_buffer *buffer = impl_from_IDirect3DExecuteBuffer(iface);
DWORD nbvert;
TRACE("iface %p, data %p.\n", iface, data); TRACE("iface %p, data %p.\n", iface, data);
memcpy(&buffer->data, data, data->dwSize); memcpy(&buffer->data, data, data->dwSize);
/* Get the number of vertices in the execute buffer */ if (buffer->vertex_size < data->dwVertexCount)
nbvert = buffer->data.dwVertexCount; {
HRESULT hr;
unsigned int new_size = max(data->dwVertexCount, buffer->vertex_size * 2);
struct wined3d_buffer *dst_buffer;
/* Prepares the transformed vertex buffer */ hr = wined3d_buffer_create_vb(buffer->d3ddev->wined3d_device, new_size * sizeof(D3DTLVERTEX),
HeapFree(GetProcessHeap(), 0, buffer->vertex_data); WINED3DUSAGE_STATICDECL, WINED3D_POOL_DEFAULT,
buffer->vertex_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbvert * sizeof(D3DTLVERTEX)); NULL, &ddraw_null_wined3d_parent_ops, &dst_buffer);
buffer->nb_vertices = nbvert; if (FAILED(hr))
return hr;
if (buffer->dst_vertex_buffer)
wined3d_buffer_decref(buffer->dst_vertex_buffer);
buffer->dst_vertex_buffer = dst_buffer;
buffer->vertex_size = new_size;
}
if (TRACE_ON(ddraw)) if (TRACE_ON(ddraw))
_dump_executedata(data); _dump_executedata(data);