From 47a8a6bd4412961b5b4c55927e21c25a36a9037b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 20 Dec 2007 23:40:12 +0100 Subject: [PATCH] wined3d: Implement and test vertex fixups with per stream offsets. --- dlls/d3d9/tests/visual.c | 99 ++++++++++++++++++++++--------------- dlls/wined3d/state.c | 5 +- dlls/wined3d/vertexbuffer.c | 25 ++++------ 3 files changed, 73 insertions(+), 56 deletions(-) diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 5062952af7b..2700e730cd8 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -5449,7 +5449,7 @@ struct vertex_floatcolor { static void fixed_function_decl_test(IDirect3DDevice9 *device) { HRESULT hr; - DWORD color, size; + DWORD color, size, i; void *data; static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, @@ -5818,9 +5818,6 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) /* This test is pointless without those two declarations: */ if(!dcl_color_2 || !dcl_ubyte_2) goto out; - hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0); - ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quads), (void **) &data, 0); ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr)); memcpy(data, quads, sizeof(quads)); @@ -5835,47 +5832,71 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DVertexBuffer9_Unlock(vb2); ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr); - hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3); - ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4); - ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); + for(i = 0; i < 2; i++) { + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DDevice9_BeginScene(device); - ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr)); - if(SUCCEEDED(hr)) { - hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2); - ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3); + ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); + if(i == 0) { + hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4); + } else { + hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 8, sizeof(DWORD) * 4); + } + ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2); - ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr)); + if(SUCCEEDED(hr)) { + hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2); + ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); + ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); - hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2); - ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); - hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2); + ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2); + ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); - hr = IDirect3DDevice9_EndScene(device); - ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2); + ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2); + ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr)); + } + + IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + if(i == 0) { + color = getPixelColor(device, 480, 360); + ok(color == 0x00ff0000, + "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 160, 120); + ok(color == 0x00ffffff, + "Unused quad returned color %08x, expected 0x00ffffff\n", color); + color = getPixelColor(device, 160, 360); + ok(color == 0x000000ff, + "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color); + color = getPixelColor(device, 480, 120); + ok(color == 0x000000ff, + "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x000000ff\n", color); + } else { + color = getPixelColor(device, 480, 360); + ok(color == 0x000000ff, + "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color); + color = getPixelColor(device, 160, 120); + ok(color == 0x00ffffff, + "Unused quad returned color %08x, expected 0x00ffffff\n", color); + color = getPixelColor(device, 160, 360); + ok(color == 0x00ff0000, + "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 480, 120); + ok(color == 0x00ff0000, + "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color); + } } - IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - color = getPixelColor(device, 480, 360); - ok(color == 0x00ff0000, - "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x00ff0000\n", color); - color = getPixelColor(device, 160, 120); - ok(color == 0x00ffffff, - "Unused quad returned color %08x, expected 0x00ffffff\n", color); - color = getPixelColor(device, 160, 360); - ok(color == 0x000000ff, - "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color); - color = getPixelColor(device, 480, 120); - ok(color == 0x000000ff, - "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x000000ff\n", color); - hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0); ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0); diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 71b0d3d64d7..08ad5c24b2f 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -2881,6 +2881,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi int i; UINT *offset = stateblock->streamOffset; IWineD3DVertexBufferImpl *vb; + DWORD_PTR shift_index; /* Default to no instancing */ stateblock->wineD3DDevice->instancedDraw = FALSE; @@ -2915,13 +2916,15 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride); TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]); TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType)); + shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]); + shift_index = shift_index % strided->u.input[i].dwStride; GL_EXTCALL(glVertexAttribPointerARB(i, WINED3D_ATR_SIZE(strided->u.input[i].dwType), WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), vb->conv_stride, - strided->u.input[i].lpData + vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData] + + strided->u.input[i].lpData + vb->conv_shift[shift_index] + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo])); diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c index 5bcf9044d59..7a67544f486 100644 --- a/dlls/wined3d/vertexbuffer.c +++ b/dlls/wined3d/vertexbuffer.c @@ -197,6 +197,8 @@ static inline BOOL process_converted_attribute(IWineD3DVertexBufferImpl *This, DWORD attrib_size; BOOL ret = FALSE; int i; + DWORD offset = This->resource.wineD3DDevice->stateBlock->streamOffset[attrib->streamNo]; + DWORD_PTR data; /* Check for some valid situations which cause us pain. One is if the buffer is used for * constant attributes(stride = 0), the other one is if the buffer is used on two streams @@ -223,13 +225,14 @@ static inline BOOL process_converted_attribute(IWineD3DVertexBufferImpl *This, } } + data = (((DWORD_PTR) attrib->lpData) + offset) % This->stride; attrib_size = WINED3D_ATR_SIZE(type) * WINED3D_ATR_TYPESIZE(type); for(i = 0; i < attrib_size; i++) { - if(This->conv_map[(DWORD_PTR) attrib->lpData + i] != conv_type) { - TRACE("Byte %ld in vertex changed\n", i + (DWORD_PTR) attrib->lpData); - TRACE("It was type %d, is %d now\n", This->conv_map[(DWORD_PTR) attrib->lpData + i], conv_type); + if(This->conv_map[(DWORD_PTR) data + i] != conv_type) { + TRACE("Byte %ld in vertex changed\n", i + (DWORD_PTR) data); + TRACE("It was type %d, is %d now\n", This->conv_map[(DWORD_PTR) data + i], conv_type); ret = TRUE; - This->conv_map[(DWORD_PTR) attrib->lpData + i] = conv_type; + This->conv_map[(DWORD_PTR) data + i] = conv_type; } } return ret; @@ -239,8 +242,7 @@ static inline BOOL check_attribute(IWineD3DVertexBufferImpl *This, const WineDir const BOOL check_d3dcolor, const BOOL is_ffp_position, const BOOL is_ffp_color, DWORD *stride_this_run, BOOL *float16_used) { BOOL ret = FALSE; - DWORD type, attrib_size; - int i; + DWORD type; /* Ignore attributes that do not have our vbo. After that check we can be sure that the attribute is * there, on nonexistant attribs the vbo is 0. @@ -271,16 +273,7 @@ static inline BOOL check_attribute(IWineD3DVertexBufferImpl *This, const WineDir } else if(is_ffp_position && type == WINED3DDECLTYPE_FLOAT4) { ret = process_converted_attribute(This, CONV_POSITIONT, attrib, stride_this_run, WINED3DDECLTYPE_FLOAT4); } else if(This->conv_map) { - attrib_size = WINED3D_ATR_SIZE(type) * WINED3D_ATR_TYPESIZE(type); - - for(i = 0; i < attrib_size; i++) { - if(This->conv_map[(DWORD_PTR) attrib->lpData + i] != CONV_NONE) { - TRACE("Byte %ld in vertex changed\n", i + (DWORD_PTR) attrib->lpData); - TRACE("It was type %d, is CONV_NONE now\n", This->conv_map[(DWORD_PTR) attrib->lpData + i]); - ret = TRUE; - This->conv_map[(DWORD_PTR) attrib->lpData + i] = CONV_NONE; - } - } + ret = process_converted_attribute(This, CONV_NONE, attrib, stride_this_run, type); } return ret; }