From 973de3f59c7d47602fe68c8cecf8fc3dbc59bcff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 15 Oct 2015 22:41:12 +0200 Subject: [PATCH] wined3d: Pass a context to surface_load_location. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Dösinger Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/context.c | 4 +- dlls/wined3d/device.c | 22 +++---- dlls/wined3d/drawprim.c | 28 ++++---- dlls/wined3d/surface.c | 115 +++++++++++++++++++-------------- dlls/wined3d/swapchain.c | 8 +-- dlls/wined3d/texture.c | 7 +- dlls/wined3d/wined3d_private.h | 5 +- 7 files changed, 107 insertions(+), 82 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index dc4199a45e3..eee0274ba6e 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2277,7 +2277,7 @@ static BOOL match_depth_stencil_format(const struct wined3d_format *existing, return TRUE; } -/* The caller provides a context */ +/* Context activation is done by the caller. */ static void context_validate_onscreen_formats(struct wined3d_context *context, const struct wined3d_rendertarget_view *depth_stencil) { @@ -2293,7 +2293,7 @@ static void context_validate_onscreen_formats(struct wined3d_context *context, WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n"); /* The currently active context is the necessary context to access the swapchain's onscreen buffers */ - surface_load_location(context->current_rt, WINED3D_LOCATION_TEXTURE_RGB); + surface_load_location(context->current_rt, context, WINED3D_LOCATION_TEXTURE_RGB); swapchain->render_to_fbo = TRUE; swapchain_update_draw_bindings(swapchain); context_set_render_offscreen(context, TRUE); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 0d607ee7f6a..3a55e0429e6 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -300,6 +300,15 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c unsigned int i; RECT ds_rect; + context = context_acquire(device, target); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping clear.\n"); + return; + } + gl_info = context->gl_info; + /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true * for the cleared parts, and the untouched parts. @@ -314,19 +323,10 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c { struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]); if (rt) - surface_load_location(rt, rt->container->resource.draw_binding); + surface_load_location(rt, context, rt->container->resource.draw_binding); } } - context = context_acquire(device, target); - if (!context->valid) - { - context_release(context); - WARN("Invalid context, skipping clear.\n"); - return; - } - gl_info = context->gl_info; - if (target) { render_offscreen = context->render_offscreen; @@ -4015,7 +4015,7 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str && src_rect.bottom == sub_resource->height) wined3d_texture_prepare_texture(texture, context, FALSE); else - surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); + surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_bind_and_dirtify(texture, context, FALSE); wined3d_surface_upload_data(surface, gl_info, resource->format, diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index dcfebe44d49..d2d3bce5168 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -611,20 +611,6 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co if (!index_count) return; - if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) - { - /* Invalidate the back buffer memory so LockRect will read it the next time */ - for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) - { - struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); - if (target) - { - surface_load_location(target, target->container->resource.draw_binding); - surface_invalidate_location(target, ~target->container->resource.draw_binding); - } - } - } - context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); if (!context->valid) { @@ -634,6 +620,20 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co } gl_info = context->gl_info; + if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) + { + /* Invalidate the back buffer memory so LockRect will read it the next time */ + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { + struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); + if (target) + { + surface_load_location(target, context, target->container->resource.draw_binding); + surface_invalidate_location(target, ~target->container->resource.draw_binding); + } + } + } + if (device->fb.depth_stencil) { /* Note that this depends on the context_acquire() call above to set diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 1f92d1e996c..4be666e3680 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -751,7 +751,11 @@ static void surface_unmap(struct wined3d_surface *surface) } if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface->container) - surface_load_location(surface, surface->container->resource.draw_binding); + { + context = context_acquire(device, surface); + surface_load_location(surface, context, surface->container->resource.draw_binding); + context_release(context); + } else if (surface->container->resource.format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) FIXME("Depth / stencil buffer locking is not implemented.\n"); } @@ -804,12 +808,6 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, if (src_mask & WINED3DFMT_FLAG_STENCIL) gl_mask |= GL_STENCIL_BUFFER_BIT; - /* Make sure the locations are up-to-date. Loading the destination - * surface isn't required if the entire surface is overwritten. */ - surface_load_location(src_surface, src_location); - if (!surface_is_full_rect(dst_surface, dst_rect)) - surface_load_location(dst_surface, dst_location); - context = context_acquire(device, NULL); if (!context->valid) { @@ -818,6 +816,12 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, return; } + /* Make sure the locations are up-to-date. Loading the destination + * surface isn't required if the entire surface is overwritten. */ + surface_load_location(src_surface, context, src_location); + if (!surface_is_full_rect(dst_surface, dst_rect)) + surface_load_location(dst_surface, context, dst_location); + gl_info = context->gl_info; context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location); @@ -905,9 +909,9 @@ static void surface_blt_fbo(const struct wined3d_device *device, * surface isn't required if the entire surface is overwritten. (And is * in fact harmful if we're being called by surface_load_location() with * the purpose of loading the destination surface.) */ - surface_load_location(src_surface, src_location); + surface_load_location(src_surface, old_ctx, src_location); if (!surface_is_full_rect(dst_surface, &dst_rect)) - surface_load_location(dst_surface, dst_location); + surface_load_location(dst_surface, old_ctx, dst_location); if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface; else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface; @@ -1134,6 +1138,9 @@ static void surface_unload(struct wined3d_resource *resource) TRACE("surface %p.\n", surface); + context = context_acquire(device, NULL); + gl_info = context->gl_info; + if (resource->pool == WINED3D_POOL_DEFAULT) { /* Default pool resources are supposed to be destroyed before Reset is called. @@ -1159,13 +1166,10 @@ static void surface_unload(struct wined3d_resource *resource) else { surface_prepare_map_memory(surface); - surface_load_location(surface, surface->resource.map_binding); + surface_load_location(surface, context, surface->resource.map_binding); surface_invalidate_location(surface, ~surface->resource.map_binding); } - context = context_acquire(device, NULL); - gl_info = context->gl_info; - /* Destroy PBOs, but load them into real sysmem before */ if (surface->pbo) surface_remove_pbo(surface, gl_info); @@ -1659,7 +1663,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P if (update_w == dst_w && update_h == dst_h) wined3d_texture_prepare_texture(dst_surface->container, context, FALSE); else - surface_load_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); + surface_load_location(dst_surface, context, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_bind_and_dirtify(dst_surface->container, context, FALSE); surface_get_memory(src_surface, &data, src_surface->locations); @@ -1775,7 +1779,8 @@ GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) return GL_BACK; } -void surface_load(struct wined3d_surface *surface, BOOL srgb) +/* Context activation is done by the caller. */ +void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) { DWORD location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; @@ -1791,7 +1796,7 @@ void surface_load(struct wined3d_surface *surface, BOOL srgb) } TRACE("Reloading because surface is dirty.\n"); - surface_load_location(surface, location); + surface_load_location(surface, context, location); surface_evict_sysmem(surface); } @@ -2530,10 +2535,16 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, } else { + struct wined3d_context *context = NULL; + if (surface->resource.usage & WINED3DUSAGE_DYNAMIC) WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n"); - surface_load_location(surface, surface->resource.map_binding); + if (surface->resource.device->d3d_initialized) + context = context_acquire(surface->resource.device, NULL); + surface_load_location(surface, context, surface->resource.map_binding); + if (context) + context_release(context); } if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) @@ -2615,6 +2626,8 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) { HRESULT hr; + struct wined3d_device *device = surface->resource.device; + struct wined3d_context *context = NULL; TRACE("surface %p, dc %p.\n", surface, dc); @@ -2626,26 +2639,36 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) if (surface->resource.map_count) return WINED3DERR_INVALIDCALL; + if (device->d3d_initialized) + context = context_acquire(surface->resource.device, NULL); + /* Create a DIB section if there isn't a dc yet. */ if (!surface->hDC) { if (surface->flags & SFLAG_CLIENT) { - surface_load_location(surface, WINED3D_LOCATION_SYSMEM); + surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM); surface_release_client_storage(surface); } hr = surface_create_dib_section(surface); if (FAILED(hr)) - return WINED3DERR_INVALIDCALL; + { + if (context) + context_release(context); + return WINED3DERR_INVALIDCALL; + } if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM || surface->pbo)) surface->resource.map_binding = WINED3D_LOCATION_DIB; } - surface_load_location(surface, WINED3D_LOCATION_DIB); + surface_load_location(surface, context, WINED3D_LOCATION_DIB); surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB); + if (context) + context_release(context); + surface->flags |= SFLAG_DCINUSE; surface->resource.map_count++; @@ -2683,8 +2706,16 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) * copied back to the DIB in the next getdc call. * * The same consideration applies to user memory surfaces. */ - surface_load_location(surface, surface->resource.map_binding); + struct wined3d_device *device = surface->resource.device; + struct wined3d_context *context = NULL; + + if (device->d3d_initialized) + context = context_acquire(device, NULL); + + surface_load_location(surface, context, surface->resource.map_binding); surface_invalidate_location(surface, WINED3D_LOCATION_DIB); + if (context) + context_release(context); } return WINED3D_OK; @@ -3847,7 +3878,7 @@ static void surface_load_sysmem(struct wined3d_surface *surface, } if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) - surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); + surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); /* Download the surface to system memory. */ if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) @@ -3883,7 +3914,7 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface, } surface_get_rect(surface, NULL, &r); - surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); + surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); surface_blt_to_drawable(surface->resource.device, context, WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r); @@ -3956,7 +3987,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, /* Performance warning... */ FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface); surface_prepare_map_memory(surface); - surface_load_location(surface, surface->resource.map_binding); + surface_load_location(surface, context, surface->resource.map_binding); } } else @@ -3967,7 +3998,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, /* Performance warning... */ FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface); surface_prepare_map_memory(surface); - surface_load_location(surface, surface->resource.map_binding); + surface_load_location(surface, context, surface->resource.map_binding); } } @@ -3976,7 +4007,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); /* Lets hope we get it from somewhere... */ surface_prepare_system_memory(surface); - surface_load_location(surface, WINED3D_LOCATION_SYSMEM); + surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM); } wined3d_texture_prepare_texture(texture, context, srgb); @@ -4002,7 +4033,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, surface->resource.map_binding = WINED3D_LOCATION_SYSMEM; surface_prepare_map_memory(surface); - surface_load_location(surface, surface->resource.map_binding); + surface_load_location(surface, context, surface->resource.map_binding); surface_remove_pbo(surface, gl_info); } @@ -4070,11 +4101,10 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect); } -HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) +/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */ +HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) { - struct wined3d_device *device = surface->resource.device; HRESULT hr; - struct wined3d_context *context = NULL; TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); @@ -4083,9 +4113,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) if (location == WINED3D_LOCATION_TEXTURE_RGB && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) { - context = context_acquire(device, NULL); surface_load_ds_location(surface, context, location); - context_release(context); return WINED3D_OK; } else if (location & surface->locations @@ -4129,33 +4157,22 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) case WINED3D_LOCATION_USER_MEMORY: case WINED3D_LOCATION_SYSMEM: case WINED3D_LOCATION_BUFFER: - if (device->d3d_initialized) - context = context_acquire(device, NULL); surface_load_sysmem(surface, context, location); - if (context) - context_release(context); break; case WINED3D_LOCATION_DRAWABLE: - context = context_acquire(device, NULL); - hr = surface_load_drawable(surface, context); - context_release(context); - if (FAILED(hr)) + if (FAILED(hr = surface_load_drawable(surface, context))) return hr; break; case WINED3D_LOCATION_RB_RESOLVED: - context = context_acquire(device, NULL); surface_multisample_resolve(surface, context); - context_release(context); break; case WINED3D_LOCATION_TEXTURE_RGB: case WINED3D_LOCATION_TEXTURE_SRGB: - context = context_acquire(device, NULL); - hr = surface_load_texture(surface, context, location == WINED3D_LOCATION_TEXTURE_SRGB); - context_release(context); - if (FAILED(hr)) + if (FAILED(hr = surface_load_texture(surface, context, + location == WINED3D_LOCATION_TEXTURE_SRGB))) return hr; break; @@ -5274,7 +5291,11 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect))) { if (!wined3d_resource_is_offscreen(&dst_surface->container->resource)) - surface_load_location(dst_surface, dst_surface->container->resource.draw_binding); + { + struct wined3d_context *context = context_acquire(device, dst_surface); + surface_load_location(dst_surface, context, dst_surface->container->resource.draw_binding); + context_release(context); + } return WINED3D_OK; } } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 0a1373f7f19..27bcf703725 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -309,7 +309,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, if (backbuffer->resource.multisample_type) { location = WINED3D_LOCATION_RB_RESOLVED; - surface_load_location(backbuffer, location); + surface_load_location(backbuffer, context, location); } context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); @@ -511,14 +511,14 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT */ if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - surface_load_location(back_buffer, WINED3D_LOCATION_TEXTURE_RGB); + surface_load_location(back_buffer, context, WINED3D_LOCATION_TEXTURE_RGB); surface_invalidate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); swapchain->render_to_fbo = TRUE; swapchain_update_draw_bindings(swapchain); } else { - surface_load_location(back_buffer, back_buffer->container->resource.draw_binding); + surface_load_location(back_buffer, context, back_buffer->container->resource.draw_binding); } if (swapchain->render_to_fbo) @@ -611,7 +611,7 @@ void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *r TRACE("Copying surface %p to screen.\n", front); - surface_load_location(front, WINED3D_LOCATION_DIB); + surface_load_location(front, NULL, WINED3D_LOCATION_DIB); src_dc = front->hDC; window = swapchain->win_handle; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index d5f959198a6..f00553ae82b 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -762,16 +762,19 @@ static HRESULT wined3d_texture_upload_data(struct wined3d_texture *texture, static void texture2d_sub_resource_load(struct wined3d_resource *sub_resource, struct wined3d_context *context, BOOL srgb) { - surface_load(surface_from_resource(sub_resource), srgb); + surface_load(surface_from_resource(sub_resource), context, srgb); } static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource, const struct wined3d_box *dirty_region) { struct wined3d_surface *surface = surface_from_resource(sub_resource); + struct wined3d_context *context; surface_prepare_map_memory(surface); - surface_load_location(surface, surface->resource.map_binding); + context = context_acquire(surface->resource.device, NULL); + surface_load_location(surface, context, surface->resource.map_binding); + context_release(context); surface_invalidate_location(surface, ~surface->resource.map_binding); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 68d420b5ac9..4f4a98493d8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2445,12 +2445,13 @@ GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) DECLSPEC_HID void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context, unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; -void surface_load(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN; +void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct wined3d_context *context) DECLSPEC_HIDDEN; -HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; +HRESULT surface_load_location(struct wined3d_surface *surface, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; void surface_prepare_rb(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN;