From: Steve Schnepp steve.schnepp@pwkf.org
--- dlls/ddraw/ddraw_private.h | 2 + dlls/ddraw/device.c | 80 +++++++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 31 deletions(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 5c77e813311..325ff22c1ae 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -320,7 +320,9 @@ void *ddraw_get_object(struct ddraw_handle_table *t, DWORD handle, enum ddraw_ha #define D3D_BUFFER_SIZE (2 * 1024 * 1024) /* 2 MiB buffer */
struct d3d_device_buffer { + DWORD buffer_indice_count; DWORD buffer_vertex_count; + WORD buffer_indices[D3DMAXNUMVERTICES]; char buffer_vertices[D3D_BUFFER_SIZE]; };
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index e0a3b4ca5e6..ce5709c615f 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -35,7 +35,7 @@ WINE_DECLARE_DEBUG_CHANNEL(ddraw_perf); WINE_DECLARE_DEBUG_CHANNEL(ddraw_buffer);
static HRESULT ddraw_buffer_flush_d7(IDirect3DDevice7 *iface); -static int ddraw_buffer_add_d7(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, DWORD flags, UINT stride); +static HRESULT ddraw_buffer_add_d7(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, DWORD flags, UINT stride);
/* The device ID */ const GUID IID_D3DDEVICE_WineD3D = { @@ -3462,16 +3462,15 @@ static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface, stride = get_flexible_vertex_size(fvf); size = vertex_count * stride;
- if (primitive_type == D3DPT_TRIANGLELIST) { - // We are currently flushing the buffer - } else { - if (ddraw_buffer_add_d7(iface, primitive_type, fvf, vertices, vertex_count, flags, stride)) { - return D3D_OK; - } - // Cannot buffer, need to flush the rest, then process this one - ddraw_buffer_flush_d7(iface); + hr = ddraw_buffer_add_d7(iface, primitive_type, fvf, vertices, vertex_count, flags, stride); + if (hr == D3D_OK) { + /* Buffered successfuly -> returning immediatly :-) */ + return D3D_OK; }
+ // Cannot buffer, need to flush the rest, then process this one + ddraw_buffer_flush_d7(iface); + wined3d_mutex_lock();
hr = wined3d_streaming_buffer_upload(device->wined3d_device, @@ -6905,6 +6904,11 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c wined3d_streaming_buffer_init(&device->vertex_buffer, WINED3D_BIND_VERTEX_BUFFER); wined3d_streaming_buffer_init(&device->index_buffer, WINED3D_BIND_INDEX_BUFFER);
+ /* Initialize the ddraw triangle buffer. + * The 3 first vertices indexes will *always* be { 0, 1, 2 }. + */ + device->ddraw_device_buffer.buffer_vertex_count = 0; + /* Render to the back buffer */ rtv = ddraw_surface_get_rendertarget_view(target); if (FAILED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, 0, 1, &rtv, TRUE))) @@ -7004,41 +7008,51 @@ HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_su * * Note : it does transform D3DPT_TRIANGLEFAN into D3DPT_TRIANGLELIST. */ -static int ddraw_buffer_add_d7(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, DWORD flags, UINT stride) { +static HRESULT ddraw_buffer_add_d7(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, DWORD flags, UINT stride) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); + int buffer_indice_count_initial = device->ddraw_device_buffer.buffer_vertex_count;
- if (!TRACE_ON(ddraw_buffer)) return 0; - if (primitive_type != D3DPT_TRIANGLEFAN) return 0; - if (fvf != 0x2c4) return 0; - if (flags) return 0; + if (!TRACE_ON(ddraw_buffer)) return WINED3DERR_NOTAVAILABLE; + if (primitive_type != D3DPT_TRIANGLEFAN) return WINED3DERR_NOTAVAILABLE; + if (fvf != 0x2c4) return WINED3DERR_NOTAVAILABLE; + if (flags) return WINED3DERR_NOTAVAILABLE;
if (vertex_count < 3) { WARN("vertex_count %lu lower than 3. not buffering", vertex_count); - return 0; + return WINED3DERR_NOTAVAILABLE; }
- /* First triangle is simply copied over */ - memcpy(device->ddraw_device_buffer.buffer_vertices + device->ddraw_device_buffer.buffer_vertex_count * stride, vertices, stride * 3); - device->ddraw_device_buffer.buffer_vertex_count += 3; - TRACE_(ddraw_perf)("only %lu vertex count. buffering. buffer_vertex_count %lu stride %d\n", vertex_count, device->ddraw_device_buffer.buffer_vertex_count, stride); + /* append all the vertices to the buffer */ + memcpy(device->ddraw_device_buffer.buffer_vertices + device->ddraw_device_buffer.buffer_vertex_count * stride, vertices, vertex_count * stride); + + TRACE_(ddraw_perf)("vertex count %lu stride %d buffer_vertex_count %lu buffer_indice_count %lu\n", vertex_count, stride, + device->ddraw_device_buffer.buffer_vertex_count, device->ddraw_device_buffer.buffer_indice_count); + + /* Create the index */ + + /* The first triangle is the same, therefore the indices are simply copied over */ + device->ddraw_device_buffer.buffer_indices[device->ddraw_device_buffer.buffer_indice_count++] = device->ddraw_device_buffer.buffer_vertex_count++; + device->ddraw_device_buffer.buffer_indices[device->ddraw_device_buffer.buffer_indice_count++] = device->ddraw_device_buffer.buffer_vertex_count++; + device->ddraw_device_buffer.buffer_indices[device->ddraw_device_buffer.buffer_indice_count++] = device->ddraw_device_buffer.buffer_vertex_count++; + + TRACE_(ddraw_perf)("vertex count %lu stride %d buffer_vertex_count %lu buffer_indice_count %lu\n", vertex_count, stride, + device->ddraw_device_buffer.buffer_vertex_count, device->ddraw_device_buffer.buffer_indice_count);
/* Next triangles are recreated with : 2 next vertices then the 1rst one. * So, it will *increase* the number of total vertices from 4 to 6, 5 to 9, 6 to 12, ... */ for (int idx = 2; idx < vertex_count-1; idx ++) { /* Copy the 2 last ones */ - char* next_vertice = vertices; - next_vertice += idx * stride; - memcpy(device->ddraw_device_buffer.buffer_vertices + device->ddraw_device_buffer.buffer_vertex_count * stride, next_vertice, stride * 2); - device->ddraw_device_buffer.buffer_vertex_count += 2; + device->ddraw_device_buffer.buffer_indices[device->ddraw_device_buffer.buffer_indice_count++] = device->ddraw_device_buffer.buffer_vertex_count - 1; + device->ddraw_device_buffer.buffer_indices[device->ddraw_device_buffer.buffer_indice_count++] = device->ddraw_device_buffer.buffer_vertex_count; + device->ddraw_device_buffer.buffer_indices[device->ddraw_device_buffer.buffer_indice_count++] = buffer_indice_count_initial; + device->ddraw_device_buffer.buffer_vertex_count++;
- /* Copy the first again */ - memcpy(device->ddraw_device_buffer.buffer_vertices + device->ddraw_device_buffer.buffer_vertex_count * stride, vertices, stride); - device->ddraw_device_buffer.buffer_vertex_count += 1; - TRACE_(ddraw_perf)("idx %d buffer_vertex_count %lu stride %d\n", idx, device->ddraw_device_buffer.buffer_vertex_count, stride); + TRACE_(ddraw_perf)("idx %d vertex count %lu stride %d buffer_vertex_count %lu buffer_indice_count %lu\n", idx, vertex_count, stride, + device->ddraw_device_buffer.buffer_vertex_count, device->ddraw_device_buffer.buffer_indice_count); }
/* Buffered ! */ - return 1; + return D3D_OK; }
/* Flushing the buffer if it isn't empty. @@ -7049,7 +7063,7 @@ static int ddraw_buffer_add_d7(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primiti static HRESULT ddraw_buffer_flush_d7(IDirect3DDevice7 *iface) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
- TRACE_(ddraw_perf)("buffer_vertex_count %lu\n", device->ddraw_device_buffer.buffer_vertex_count); + TRACE_(ddraw_perf)("buffer_vertex_count %lu buffer_indice_count %lu\n", device->ddraw_device_buffer.buffer_vertex_count, device->ddraw_device_buffer.buffer_indice_count);
/* Nothing to do if it is empty */ if (! device->ddraw_device_buffer.buffer_vertex_count) return D3D_OK; @@ -7059,13 +7073,17 @@ static HRESULT ddraw_buffer_flush_d7(IDirect3DDevice7 *iface) { HRESULT ret; const DWORD from_flush_flags = 0xF0F0F0F0; // Using a specific flag to recognise & avoid recursion loops
- ret = d3d_device7_DrawPrimitive(iface, D3DPT_TRIANGLELIST, 0x2c4, device->ddraw_device_buffer.buffer_vertices, device->ddraw_device_buffer.buffer_vertex_count, from_flush_flags); + ret = d3d_device7_DrawIndexedPrimitive(iface, D3DPT_TRIANGLELIST, 0x2c4, + device->ddraw_device_buffer.buffer_vertices, device->ddraw_device_buffer.buffer_vertex_count, + device->ddraw_device_buffer.buffer_indices, device->ddraw_device_buffer.buffer_indice_count, + from_flush_flags);
if (ret != D3D_OK) FIXME("error in call delegation %ld", ret); }
- /* Flush the buffer */ + /* Reset the buffer */ device->ddraw_device_buffer.buffer_vertex_count = 0; + device->ddraw_device_buffer.buffer_indice_count = 0;
/* The error isn't really useful as it is too late, so always returning */ return D3D_OK;