diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 7059e21cc9a..802a6dd9db2 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -599,7 +599,6 @@ static void device_load_logo(struct wined3d_device *device, const char *filename { struct wined3d_color_key color_key; struct wined3d_resource_desc desc; - struct wined3d_surface *surface; HBITMAP hbm; BITMAP bm; HRESULT hr; @@ -639,14 +638,13 @@ static void device_load_logo(struct wined3d_device *device, const char *filename ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr); goto out; } - surface = surface_from_resource(wined3d_texture_get_sub_resource(device->logo_texture, 0)); if (dcb) { - if (FAILED(hr = wined3d_surface_getdc(surface, &dcs))) + if (FAILED(hr = wined3d_texture_get_dc(device->logo_texture, 0, &dcs))) goto out; BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY); - wined3d_surface_releasedc(surface, dcs); + wined3d_texture_release_dc(device->logo_texture, 0, dcs); color_key.color_space_low_value = 0; color_key.color_space_high_value = 0; @@ -654,10 +652,12 @@ static void device_load_logo(struct wined3d_device *device, const char *filename } else { - const RECT rect = {0, 0, surface->resource.width, surface->resource.height}; const struct wined3d_color c = {1.0f, 1.0f, 1.0f, 1.0f}; + const RECT rect = {0, 0, desc.width, desc.height}; + struct wined3d_surface *surface; /* Fill the surface with a white color to show that wined3d is there */ + surface = surface_from_resource(wined3d_texture_get_sub_resource(device->logo_texture, 0)); surface_color_fill(surface, &rect, &c); } diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 57ab90c5b8e..2698d095207 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -356,7 +356,7 @@ static void get_color_masks(const struct wined3d_format *format, DWORD *masks) masks[2] = ((1u << format->blue_size) - 1) << format->blue_offset; } -static HRESULT surface_create_dib_section(struct wined3d_surface *surface) +HRESULT surface_create_dib_section(struct wined3d_surface *surface) { const struct wined3d_format *format = surface->resource.format; unsigned int format_flags = surface->container->resource.format_flags; @@ -2580,98 +2580,6 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, return WINED3D_OK; } -HRESULT 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); - - /* Give more detailed info for ddraw. */ - if (surface->flags & SFLAG_DCINUSE) - return WINEDDERR_DCALREADYCREATED; - - /* Can't GetDC if the surface is locked. */ - 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 (FAILED(hr = surface_create_dib_section(surface))) - { - 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, context, WINED3D_LOCATION_DIB); - surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB); - - if (context) - context_release(context); - - surface->flags |= SFLAG_DCINUSE; - surface->resource.map_count++; - - *dc = surface->hDC; - TRACE("Returning dc %p.\n", *dc); - - return WINED3D_OK; -} - -HRESULT wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) -{ - TRACE("surface %p, dc %p.\n", surface, dc); - - if (!(surface->flags & SFLAG_DCINUSE)) - return WINEDDERR_NODC; - - if (surface->hDC != dc) - { - WARN("Application tries to release invalid DC %p, surface DC is %p.\n", - dc, surface->hDC); - return WINEDDERR_NODC; - } - - surface->resource.map_count--; - surface->flags &= ~SFLAG_DCINUSE; - - if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY - || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM - && surface->resource.map_binding != WINED3D_LOCATION_DIB)) - { - /* The game Salammbo modifies the surface contents without mapping the surface between - * a GetDC/ReleaseDC operation and flipping the surface. If the DIB remains the active - * copy and is copied to the screen, this update, which draws the mouse pointer, is lost. - * Do not only copy the DIB to the map location, but also make sure the map location is - * copied back to the DIB in the next getdc call. - * - * The same consideration applies to user memory surfaces. */ - 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; -} - static void read_from_framebuffer(struct wined3d_surface *surface, struct wined3d_context *old_ctx, DWORD dst_location) { @@ -5411,7 +5319,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text /* Similar to lockable rendertargets above, creating the DIB section * during surface initialization prevents the sysmem pointer from changing - * after a wined3d_surface_getdc() call. */ + * after a wined3d_texture_get_dc() call. */ if ((desc->usage & WINED3DUSAGE_OWNDC) && !surface->hDC && SUCCEEDED(surface_create_dib_section(surface))) surface->resource.map_binding = WINED3D_LOCATION_DIB; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index fa948ffc540..ee2d17e5c9a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1514,7 +1514,11 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC *dc) { + struct wined3d_device *device = texture->resource.device; + struct wined3d_context *context = NULL; struct wined3d_resource *sub_resource; + struct wined3d_surface *surface; + HRESULT hr; TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); @@ -1527,12 +1531,55 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i return WINED3DERR_INVALIDCALL; } - return wined3d_surface_getdc(surface_from_resource(sub_resource), dc); + surface = surface_from_resource(sub_resource); + + /* Give more detailed info for ddraw. */ + if (surface->flags & SFLAG_DCINUSE) + return WINEDDERR_DCALREADYCREATED; + + /* Can't GetDC if the surface is locked. */ + if (surface->resource.map_count) + return WINED3DERR_INVALIDCALL; + + if (device->d3d_initialized) + context = context_acquire(device, NULL); + + /* Create a DIB section if there isn't a dc yet. */ + if (!surface->hDC) + { + if (FAILED(hr = surface_create_dib_section(surface))) + { + 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, context, WINED3D_LOCATION_DIB); + surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB); + + if (context) + context_release(context); + + surface->flags |= SFLAG_DCINUSE; + surface->resource.map_count++; + + *dc = surface->hDC; + TRACE("Returning dc %p.\n", *dc); + + return WINED3D_OK; } HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc) { + struct wined3d_device *device = texture->resource.device; + struct wined3d_context *context = NULL; struct wined3d_resource *sub_resource; + struct wined3d_surface *surface; TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); @@ -1545,5 +1592,41 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign return WINED3DERR_INVALIDCALL; } - return wined3d_surface_releasedc(surface_from_resource(sub_resource), dc); + surface = surface_from_resource(sub_resource); + + if (!(surface->flags & SFLAG_DCINUSE)) + return WINEDDERR_NODC; + + if (surface->hDC != dc) + { + WARN("Application tries to release invalid DC %p, surface DC is %p.\n", + dc, surface->hDC); + return WINEDDERR_NODC; + } + + surface->resource.map_count--; + surface->flags &= ~SFLAG_DCINUSE; + + if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY + || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM + && surface->resource.map_binding != WINED3D_LOCATION_DIB)) + { + /* The game Salammbo modifies the surface contents without mapping the surface between + * a GetDC/ReleaseDC operation and flipping the surface. If the DIB remains the active + * copy and is copied to the screen, this update, which draws the mouse pointer, is lost. + * Do not only copy the DIB to the map location, but also make sure the map location is + * copied back to the DIB in the next getdc call. + * + * The same consideration applies to user memory surfaces. */ + + 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; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5474c7ff6f7..7ab2ae84b82 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2506,8 +2506,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst void surface_set_dirty(struct wined3d_surface *surface) DECLSPEC_HIDDEN; HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; +HRESULT surface_create_dib_section(struct wined3d_surface *surface) DECLSPEC_HIDDEN; GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) DECLSPEC_HIDDEN; -HRESULT wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) DECLSPEC_HIDDEN; 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; @@ -2521,7 +2521,6 @@ HRESULT surface_load_location(struct wined3d_surface *surface, void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; void wined3d_surface_prepare(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; -HRESULT wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) DECLSPEC_HIDDEN; void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const struct wined3d_surface *rt) DECLSPEC_HIDDEN; void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level) DECLSPEC_HIDDEN;