From aa8487a4b3cec77ae38ada57bf81634cd2eaa6d2 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 19 Mar 2024 11:27:42 -0600 Subject: [PATCH] ddraw: Store wined3d state in d3d_device. --- dlls/ddraw/ddraw.c | 19 +++++------------ dlls/ddraw/ddraw_private.h | 3 --- dlls/ddraw/device.c | 53 +++++++++++++++++++++++++++------------------- dlls/ddraw/surface.c | 36 +++++++++++++++++++------------ dlls/ddraw/vertexbuffer.c | 9 ++++++-- dlls/wined3d/stateblock.c | 10 +++++++++ dlls/wined3d/wined3d.spec | 2 ++ include/wine/wined3d.h | 2 ++ 8 files changed, 79 insertions(+), 55 deletions(-) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index efbe01f3b8b..21497cd7a8b 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -437,7 +437,6 @@ static void ddraw_destroy(struct ddraw *This) if (This->wined3d_swapchain) ddraw_destroy_swapchain(This); - wined3d_stateblock_decref(This->state); wined3d_device_decref(This->wined3d_device); wined3d_decref(This->wined3d); @@ -797,6 +796,7 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL; struct wined3d_stateblock *stateblock; BOOL restore_state = FALSE; + struct d3d_device *device; RECT clip_rect; HRESULT hr; @@ -924,14 +924,15 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED)) wined3d_device_set_multithreaded(ddraw->wined3d_device); + device = ddraw->d3ddevice; if (ddraw->wined3d_swapchain) { - if (!(ddraw->flags & DDRAW_NO3D)) + if (!(ddraw->flags & DDRAW_NO3D) && device) { restore_state = TRUE; if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, - ddraw->state, WINED3D_SBT_ALL, &stateblock))) + device->state, WINED3D_SBT_ALL, &stateblock))) { ERR("Failed to create stateblock, hr %#lx.\n", hr); goto done; @@ -968,7 +969,7 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, wined3d_rendertarget_view_decref(rtv); } - wined3d_stateblock_apply(stateblock, ddraw->state); + wined3d_stateblock_apply(stateblock, device->state); wined3d_stateblock_decref(stateblock); } @@ -5127,15 +5128,5 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type de ddraw->immediate_context = wined3d_device_get_immediate_context(ddraw->wined3d_device); list_init(&ddraw->surface_list); - - if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, NULL, WINED3D_SBT_PRIMARY, &ddraw->state))) - { - ERR("Failed to create the primary stateblock, hr %#lx.\n", hr); - wined3d_device_decref(ddraw->wined3d_device); - wined3d_decref(ddraw->wined3d); - return hr; - } - ddraw->stateblock_state = wined3d_stateblock_get_state(ddraw->state); - return DD_OK; } diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 6fc93b91860..f5b38f8f9d6 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -132,9 +132,6 @@ struct ddraw struct FvfToDecl *decls; UINT numConvertedDecls, declArraySize; - struct wined3d_stateblock *state; - const struct wined3d_stateblock_state *stateblock_state; - unsigned int frames; DWORD prev_frame_time; }; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index f903455a177..59027a34ae1 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -284,10 +284,6 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) wined3d_device_context_set_rendertarget_views(This->immediate_context, 0, 1, &null_rtv, FALSE); - wined3d_stateblock_decref(This->state); - if (This->recording) - wined3d_stateblock_decref(This->recording); - /* Release the wined3d device. This won't destroy it. */ if (!wined3d_device_decref(This->wined3d_device)) ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device); @@ -325,6 +321,18 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface); } + wined3d_stateblock_decref(This->state); + if (This->recording) + wined3d_stateblock_decref(This->recording); + + /* Releasing the render target below may release the last reference to the ddraw object. Detach + * the device from it before so it doesn't try to save / restore state on the teared down device. */ + if (This->ddraw) + { + This->ddraw->d3ddevice = NULL; + This->ddraw = NULL; + } + TRACE("Releasing render target %p.\n", This->rt_iface); rt_iface = This->rt_iface; This->rt_iface = NULL; @@ -332,11 +340,6 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) IUnknown_Release(rt_iface); TRACE("Render target release done.\n"); - /* Releasing the render target above may have released the last - * reference to the ddraw object. */ - if (This->ddraw) - This->ddraw->d3ddevice = NULL; - /* Now free the structure */ free(This); wined3d_mutex_unlock(); @@ -6776,15 +6779,15 @@ enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device return WINED3D_ZB_TRUE; } -static void ddraw_reset_viewport_state(struct ddraw *ddraw) +static void device_reset_viewport_state(struct d3d_device *device) { struct wined3d_viewport vp; RECT rect; - wined3d_device_context_get_viewports(ddraw->immediate_context, NULL, &vp); - wined3d_stateblock_set_viewport(ddraw->state, &vp); - wined3d_device_context_get_scissor_rects(ddraw->immediate_context, NULL, &rect); - wined3d_stateblock_set_scissor_rect(ddraw->state, &rect); + wined3d_device_context_get_viewports(device->immediate_context, NULL, &vp); + wined3d_stateblock_set_viewport(device->state, &vp); + wined3d_device_context_get_scissor_rects(device->immediate_context, NULL, &rect); + wined3d_stateblock_set_scissor_rect(device->state, &rect); } static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, const GUID *guid, @@ -6838,13 +6841,19 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c device->legacy_projection = ident; device->legacy_clipspace = ident; + if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, NULL, WINED3D_SBT_PRIMARY, &device->state))) + { + ERR("Failed to create the primary stateblock, hr %#lx.\n", hr); + ddraw_handle_table_destroy(&device->handle_table); + return hr; + } + device->stateblock_state = wined3d_stateblock_get_state(device->state); + device->update_state = device->state; + /* This is for convenience. */ device->wined3d_device = ddraw->wined3d_device; device->immediate_context = ddraw->immediate_context; wined3d_device_incref(ddraw->wined3d_device); - device->update_state = device->state = ddraw->state; - device->stateblock_state = ddraw->stateblock_state; - wined3d_stateblock_incref(ddraw->state); wined3d_streaming_buffer_init(&device->vertex_buffer, WINED3D_BIND_VERTEX_BUFFER); wined3d_streaming_buffer_init(&device->index_buffer, WINED3D_BIND_INDEX_BUFFER); @@ -6865,19 +6874,19 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c ddraw->d3ddevice = device; - wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE, + wined3d_stateblock_set_render_state(device->state, WINED3D_RS_ZENABLE, d3d_device_update_depth_stencil(device)); if (version == 1) /* Color keying is initially enabled for version 1 devices. */ - wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_COLORKEYENABLE, TRUE); + wined3d_stateblock_set_render_state(device->state, WINED3D_RS_COLORKEYENABLE, TRUE); else if (version == 2) - wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_SPECULARENABLE, TRUE); + wined3d_stateblock_set_render_state(device->state, WINED3D_RS_SPECULARENABLE, TRUE); if (version < 7) { - wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_NORMALIZENORMALS, TRUE); + wined3d_stateblock_set_render_state(device->state, WINED3D_RS_NORMALIZENORMALS, TRUE); IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE); } - ddraw_reset_viewport_state(ddraw); + device_reset_viewport_state(device); return D3D_OK; } diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 1231fac05c8..8073bcd4d48 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -4346,7 +4346,7 @@ static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *ifa static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD) { struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); - HRESULT hr; + struct d3d_device *device; TRACE("iface %p, lod %lu.\n", iface, MaxLOD); @@ -4357,12 +4357,18 @@ static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD Ma return DDERR_INVALIDOBJECT; } - hr = wined3d_stateblock_set_texture_lod(surface->ddraw->state, surface->wined3d_texture, MaxLOD); - if (SUCCEEDED(hr) && surface->draw_texture) - hr = wined3d_stateblock_set_texture_lod(surface->ddraw->state, surface->draw_texture, MaxLOD); - wined3d_mutex_unlock(); + wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD); + if (surface->draw_texture) + wined3d_texture_set_lod(surface->draw_texture, MaxLOD); - return hr; + if ((device = surface->ddraw->d3ddevice)) + { + wined3d_stateblock_texture_changed(device->state, surface->wined3d_texture); + if (surface->draw_texture) + wined3d_stateblock_texture_changed(device->state, surface->draw_texture); + } + wined3d_mutex_unlock(); + return DD_OK; } /***************************************************************************** @@ -6761,20 +6767,21 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ if (ddraw->cooperative_level & DDSCL_EXCLUSIVE) { struct wined3d_swapchain_desc swapchain_desc; + struct d3d_device *device; wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc); swapchain_desc.backbuffer_width = mode.width; swapchain_desc.backbuffer_height = mode.height; swapchain_desc.backbuffer_format = mode.format_id; - if (ddraw->d3ddevice) + if ((device = ddraw->d3ddevice)) { - if (ddraw->d3ddevice->recording) - wined3d_stateblock_decref(ddraw->d3ddevice->recording); - ddraw->d3ddevice->recording = NULL; - ddraw->d3ddevice->update_state = ddraw->d3ddevice->state; + if (device->recording) + wined3d_stateblock_decref(device->recording); + device->recording = NULL; + device->update_state = device->state; + wined3d_stateblock_reset(device->state); } - wined3d_stateblock_reset(ddraw->state); if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device, &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE))) @@ -6784,8 +6791,9 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ return hr_ddraw_from_wined3d(hr); } - wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE, - !!swapchain_desc.enable_auto_depth_stencil); + if (device) + wined3d_stateblock_set_render_state(device->state, WINED3D_RS_ZENABLE, + !!swapchain_desc.enable_auto_depth_stencil); } } diff --git a/dlls/ddraw/vertexbuffer.c b/dlls/ddraw/vertexbuffer.c index 34f84b2466a..14f3c8a3ef2 100644 --- a/dlls/ddraw/vertexbuffer.c +++ b/dlls/ddraw/vertexbuffer.c @@ -75,6 +75,7 @@ static ULONG WINAPI d3d_vertex_buffer7_Release(IDirect3DVertexBuffer7 *iface) { struct d3d_vertex_buffer *buffer = impl_from_IDirect3DVertexBuffer7(iface); ULONG ref = InterlockedDecrement(&buffer->ref); + struct d3d_device *device; TRACE("%p decreasing refcount to %lu.\n", buffer, ref); @@ -85,8 +86,12 @@ static ULONG WINAPI d3d_vertex_buffer7_Release(IDirect3DVertexBuffer7 *iface) * stream source in wined3d and they should get unset there before * they are destroyed. */ wined3d_mutex_lock(); - if (buffer->ddraw->stateblock_state->streams[0].buffer == buffer->wined3d_buffer) - wined3d_stateblock_set_stream_source(buffer->ddraw->state, 0, NULL, 0, 0); + + if ((device = buffer->ddraw->d3ddevice)) + { + if (device->stateblock_state->streams[0].buffer == buffer->wined3d_buffer) + wined3d_stateblock_set_stream_source(device->state, 0, NULL, 0, 0); + } wined3d_vertex_declaration_decref(buffer->wined3d_declaration); wined3d_buffer_decref(buffer->wined3d_buffer); diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index a834a02fddf..1dcc3e3be49 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -3346,3 +3346,13 @@ unsigned int CDECL wined3d_stateblock_set_texture_lod(struct wined3d_stateblock return old; } + +void CDECL wined3d_stateblock_texture_changed(struct wined3d_stateblock *stateblock, + const struct wined3d_texture *texture) +{ + for (unsigned int i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) + { + if (stateblock->stateblock_state.textures[i] == texture) + stateblock->changed.textures |= (1u << i); + } +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index accb6f65658..fee5ed0dd7a 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -268,6 +268,7 @@ @ cdecl wined3d_stateblock_set_vs_consts_b(ptr long long ptr) @ cdecl wined3d_stateblock_set_vs_consts_f(ptr long long ptr) @ cdecl wined3d_stateblock_set_vs_consts_i(ptr long long ptr) +@ cdecl wined3d_stateblock_texture_changed(ptr ptr) @ cdecl wined3d_streaming_buffer_map(ptr ptr long long ptr ptr) @ cdecl wined3d_streaming_buffer_unmap(ptr) @@ -317,6 +318,7 @@ @ cdecl wined3d_texture_incref(ptr) @ cdecl wined3d_texture_release_dc(ptr long ptr) @ cdecl wined3d_texture_set_color_key(ptr long ptr) +@ cdecl wined3d_texture_set_lod(ptr long) @ cdecl wined3d_texture_set_overlay_position(ptr long long long) @ cdecl wined3d_texture_set_sub_resource_parent(ptr long ptr ptr) @ cdecl wined3d_texture_update_desc(ptr long ptr long) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 0b906886585..1336f10ff7a 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2884,6 +2884,8 @@ HRESULT __cdecl wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned unsigned int __cdecl wined3d_texture_get_level_count(const struct wined3d_texture *texture); unsigned int __cdecl wined3d_texture_get_lod(const struct wined3d_texture *texture); unsigned int __cdecl wined3d_texture_set_lod(struct wined3d_texture *texture, unsigned int lod); +void __cdecl wined3d_stateblock_texture_changed(struct wined3d_stateblock *stateblock, + const struct wined3d_texture *texture); HRESULT __cdecl wined3d_texture_get_overlay_position(const struct wined3d_texture *texture, unsigned int sub_resource_idx, LONG *x, LONG *y); void * __cdecl wined3d_texture_get_parent(const struct wined3d_texture *texture); -- 2.11.4.GIT