Module: wine Branch: master Commit: 7e62acc62e3d5f0e6fd199caab34b26f35b2326d URL: http://source.winehq.org/git/wine.git/?a=commit;h=7e62acc62e3d5f0e6fd199caab...
Author: Stefan Dösinger stefan@codeweavers.com Date: Thu Jan 24 00:39:10 2013 +0100
ddraw: Implement DrawPrimitiveStrided with regular draws.
---
dlls/ddraw/device.c | 142 ++++++++++++++++++++++++++++++--------------------- 1 files changed, 83 insertions(+), 59 deletions(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 76bdcff..faf7146 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -3806,82 +3806,106 @@ static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIP * (For details, see IWineD3DDevice::DrawPrimitiveStrided) * *****************************************************************************/ -static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, - DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags) +static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf) { - struct d3d_device *device = impl_from_IDirect3DDevice7(iface); - struct wined3d_strided_data wined3d_strided; - DWORD i; - HRESULT hr; + DWORD i, tex, offset;
- TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n", - iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags); - - memset(&wined3d_strided, 0, sizeof(wined3d_strided)); - /* Get the strided data right. the wined3d structure is a bit bigger - * Watch out: The contents of the strided data are determined by the fvf, - * not by the members set in D3DDrawPrimStrideData. So it's valid - * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is - * not set in the fvf. - */ - if(VertexType & D3DFVF_POSITION_MASK) + for (i = 0; i < count; i++) { - wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT; - wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData; - wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride; - if (VertexType & D3DFVF_XYZRHW) + /* The contents of the strided data are determined by the fvf, + * not by the members set in src. So it's valid + * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is + * not set in the fvf. */ + if (fvf & D3DFVF_POSITION_MASK) { - wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT; - wined3d_strided.position_transformed = TRUE; + offset = i * src->position.dwStride; + if (fvf & D3DFVF_XYZRHW) + { + memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float)); + dst += 4 * sizeof(float); + } + else + { + memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float)); + dst += 3 * sizeof(float); + } } - else + + if (fvf & D3DFVF_NORMAL) { - wined3d_strided.position_transformed = FALSE; + offset = i * src->normal.dwStride; + memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float)); + dst += 3 * sizeof(float); } - }
- if (VertexType & D3DFVF_NORMAL) - { - wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT; - wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData; - wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride; - } - - if (VertexType & D3DFVF_DIFFUSE) - { - wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM; - wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData; - wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride; - } + if (fvf & D3DFVF_DIFFUSE) + { + offset = i * src->diffuse.dwStride; + memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD)); + dst += sizeof(DWORD); + }
- if (VertexType & D3DFVF_SPECULAR) - { - wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM; - wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData; - wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride; - } + if (fvf & D3DFVF_SPECULAR) + { + offset = i * src->specular.dwStride; + memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD)); + dst += sizeof(DWORD); + }
- for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i) - { - switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i)) + for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex) { - case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break; - case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break; - case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break; - case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break; - default: ERR("Unexpected texture coordinate size %d\n", - GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i)); + DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex); + offset = i * src->textureCoords[tex].dwStride; + memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float)); + dst += attrib_count * sizeof(float); } - wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData; - wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride; } +} + +static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags) +{ + struct d3d_device *device = impl_from_IDirect3DDevice7(iface); + HRESULT hr; + UINT dst_stride = get_flexible_vertex_size(VertexType); + UINT dst_size = dst_stride * VertexCount; + UINT vb_pos, align; + BYTE *dst_data; + + TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n", + iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
- /* WineD3D doesn't need the FVF here */ wined3d_mutex_lock(); + hr = d3d_device_prepare_vertex_buffer(device, dst_size); + if (FAILED(hr)) + goto done; + + vb_pos = device->vertex_buffer_pos; + align = vb_pos % dst_stride; + if (align) align = dst_stride - align; + if (vb_pos + dst_size + align > device->vertex_buffer_size) + vb_pos = 0; + else + vb_pos += align; + + hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data, + vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); + if (FAILED(hr)) + goto done; + pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType); + wined3d_buffer_unmap(device->vertex_buffer); + device->vertex_buffer_pos = vb_pos + dst_size; + + hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride); + if (FAILED(hr)) + goto done; + wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType)); + wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType); - hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided); - wined3d_mutex_unlock(); + hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, VertexCount);
+done: + wined3d_mutex_unlock(); return hr; }