diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index dfaee3b2db3..cc13413faf5 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -1479,6 +1479,91 @@ static void maxmip_test(IDirect3DDevice9 *device) IDirect3DTexture9_Release(texture); } +static void release_buffer_test(IDirect3DDevice9 *device) +{ + IDirect3DVertexBuffer9 *vb = NULL; + IDirect3DIndexBuffer9 *ib = NULL; + HRESULT hr; + BYTE *data; + long ref; + + static const struct vertex quad[] = { + {-1.0, -1.0, 0.1, 0xffff0000}, + {-1.0, 1.0, 0.1, 0xffff0000}, + { 1.0, 1.0, 0.1, 0xffff0000}, + + {-1.0, -1.0, 0.1, 0xff00ff00}, + {-1.0, 1.0, 0.1, 0xff00ff00}, + { 1.0, 1.0, 0.1, 0xff00ff00} + }; + short indices[] = {3, 4, 5}; + + /* Index and vertex buffers should always be createable */ + hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE, + D3DPOOL_MANAGED, &vb, NULL); + ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr)); + if(!vb) { + skip("Failed to create a vertex buffer\n"); + return; + } + hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %s\n", DXGetErrorString9(hr)); + if(!ib) { + skip("Failed to create an index buffer\n"); + return; + } + + hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0); + ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr)); + memcpy(data, quad, sizeof(quad)); + hr = IDirect3DVertexBuffer9_Unlock(vb); + ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0); + ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr)); + memcpy(data, indices, sizeof(indices)); + hr = IDirect3DIndexBuffer9_Unlock(ib); + ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_SetIndices(device, ib); + ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0])); + ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); + ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr)); + + /* Now destroy the bound index buffer and draw again */ + ref = IDirect3DIndexBuffer9_Release(ib); + ok(ref == 0, "Index Buffer reference count is %08ld\n", ref); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr); + if(SUCCEEDED(hr)) + { + /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from + * making assumptions about the indices or vertices + */ + hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1); + ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr); + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr); + } + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr); + + hr = IDirect3DDevice9_SetIndices(device, NULL); + ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr); + hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0); + ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr); + + /* Index buffer was already destroyed as part of the test */ + IDirect3DVertexBuffer9_Release(vb); +} + START_TEST(visual) { IDirect3DDevice9 *device_ptr; @@ -1553,6 +1638,7 @@ START_TEST(visual) skip("No mipmap support\n"); } offscreen_test(device_ptr); + release_buffer_test(device_ptr); if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0)) { diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 43d801f3365..9e988e5155d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2796,6 +2796,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWine if(oldIdxs != pIndexData) { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); + if(pIndexData) IWineD3DIndexBuffer_AddRef(pIndexData); + if(oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs); } return WINED3D_OK; } @@ -4785,6 +4787,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice * UINT VertexStreamZeroStride) { int idxStride; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DIndexBuffer *ib; TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), @@ -4815,7 +4818,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice * /* MSDN specifies stream zero settings and index buffer must be set to NULL */ This->stateBlock->streamSource[0] = NULL; This->stateBlock->streamStride[0] = 0; - This->stateBlock->pIndexData = NULL; + ib = This->stateBlock->pIndexData; + if(ib) { + IWineD3DIndexBuffer_Release(ib); + This->stateBlock->pIndexData = NULL; + } /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call * SetStreamSource to specify a vertex buffer */ diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index b7b64a5f0b7..772bd788719 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -262,6 +262,7 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) { } } } + if(This->pIndexData) IWineD3DIndexBuffer_Release(This->pIndexData); }