wined3d: Create and destroy surface DCs through the CS.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2017-03-17 13:33:16 +01:00 committed by Alexandre Julliard
parent d9d5dcee2b
commit ad46b67674
3 changed files with 122 additions and 121 deletions

View File

@ -252,104 +252,6 @@ static void get_color_masks(const struct wined3d_format *format, DWORD *masks)
masks[2] = ((1u << format->blue_size) - 1) << format->blue_offset; masks[2] = ((1u << format->blue_size) - 1) << format->blue_offset;
} }
void wined3d_surface_destroy_dc(struct wined3d_surface *surface)
{
unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
struct wined3d_texture *texture = surface->container;
struct wined3d_device *device = texture->resource.device;
const struct wined3d_gl_info *gl_info = NULL;
D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
struct wined3d_context *context = NULL;
struct wined3d_bo_address data;
NTSTATUS status;
if (!surface->dc)
{
ERR("Surface %p has no DC.\n", surface);
return;
}
TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap);
destroy_desc.hDc = surface->dc;
destroy_desc.hBitmap = surface->bitmap;
if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
ERR("Failed to destroy dc, status %#x.\n", status);
surface->dc = NULL;
surface->bitmap = NULL;
if (device->d3d_initialized)
{
context = context_acquire(device, NULL, 0);
gl_info = context->gl_info;
}
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
if (context)
context_release(context);
}
HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface)
{
unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface);
struct wined3d_texture *texture = surface->container;
const struct wined3d_format *format = texture->resource.format;
struct wined3d_device *device = texture->resource.device;
const struct wined3d_gl_info *gl_info = NULL;
struct wined3d_context *context = NULL;
unsigned int row_pitch, slice_pitch;
struct wined3d_bo_address data;
D3DKMT_CREATEDCFROMMEMORY desc;
NTSTATUS status;
TRACE("surface %p.\n", surface);
if (!format->ddi_format)
{
WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
return WINED3DERR_INVALIDCALL;
}
wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch);
if (device->d3d_initialized)
{
context = context_acquire(device, NULL, 0);
gl_info = context->gl_info;
}
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
desc.pMemory = wined3d_texture_map_bo_address(&data, texture->sub_resources[sub_resource_idx].size,
gl_info, GL_PIXEL_UNPACK_BUFFER, 0);
if (context)
context_release(context);
desc.Format = format->ddi_format;
desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level);
desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level);
desc.Pitch = row_pitch;
desc.hDeviceDc = CreateCompatibleDC(NULL);
desc.pColorTable = NULL;
status = D3DKMTCreateDCFromMemory(&desc);
DeleteDC(desc.hDeviceDc);
if (status)
{
WARN("Failed to create DC, status %#x.\n", status);
return WINED3DERR_INVALIDCALL;
}
surface->dc = desc.hDc;
surface->bitmap = desc.hBitmap;
TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface);
return WINED3D_OK;
}
static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r) static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r)
{ {
unsigned int t; unsigned int t;

View File

@ -1212,6 +1212,114 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
return WINED3D_OK; return WINED3D_OK;
} }
static void texture2d_create_dc(void *object)
{
const struct wined3d_gl_info *gl_info = NULL;
struct wined3d_surface *surface = object;
struct wined3d_context *context = NULL;
const struct wined3d_format *format;
unsigned int row_pitch, slice_pitch;
struct wined3d_texture *texture;
struct wined3d_bo_address data;
D3DKMT_CREATEDCFROMMEMORY desc;
unsigned int sub_resource_idx;
struct wined3d_device *device;
NTSTATUS status;
TRACE("surface %p.\n", surface);
texture = surface->container;
sub_resource_idx = surface_get_sub_resource_idx(surface);
device = texture->resource.device;
format = texture->resource.format;
if (!format->ddi_format)
{
WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
return;
}
if (device->d3d_initialized)
{
context = context_acquire(device, NULL, 0);
gl_info = context->gl_info;
}
wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
desc.pMemory = wined3d_texture_map_bo_address(&data, texture->sub_resources[sub_resource_idx].size,
gl_info, GL_PIXEL_UNPACK_BUFFER, 0);
if (context)
context_release(context);
desc.Format = format->ddi_format;
desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level);
desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level);
desc.Pitch = row_pitch;
desc.hDeviceDc = CreateCompatibleDC(NULL);
desc.pColorTable = NULL;
status = D3DKMTCreateDCFromMemory(&desc);
DeleteDC(desc.hDeviceDc);
if (status)
{
WARN("Failed to create DC, status %#x.\n", status);
return;
}
surface->dc = desc.hDc;
surface->bitmap = desc.hBitmap;
TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface);
}
static void texture2d_destroy_dc(void *object)
{
const struct wined3d_gl_info *gl_info = NULL;
struct wined3d_surface *surface = object;
D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
struct wined3d_context *context = NULL;
struct wined3d_texture *texture;
struct wined3d_bo_address data;
unsigned int sub_resource_idx;
struct wined3d_device *device;
NTSTATUS status;
texture = surface->container;
sub_resource_idx = surface_get_sub_resource_idx(surface);
device = texture->resource.device;
if (!surface->dc)
{
ERR("Surface %p has no DC.\n", surface);
return;
}
TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap);
destroy_desc.hDc = surface->dc;
destroy_desc.hBitmap = surface->bitmap;
if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
ERR("Failed to destroy dc, status %#x.\n", status);
surface->dc = NULL;
surface->bitmap = NULL;
if (device->d3d_initialized)
{
context = context_acquire(device, NULL, 0);
gl_info = context->gl_info;
}
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER);
if (context)
context_release(context);
}
HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height, HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height,
enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type,
UINT multisample_quality, void *mem, UINT pitch) UINT multisample_quality, void *mem, UINT pitch)
@ -1271,7 +1379,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
surface = sub_resource->u.surface; surface = sub_resource->u.surface;
if (surface->dc) if (surface->dc)
{ {
wined3d_surface_destroy_dc(surface); wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface);
create_dib = TRUE; create_dib = TRUE;
} }
@ -1332,7 +1440,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
wined3d_texture_invalidate_location(texture, 0, ~valid_location); wined3d_texture_invalidate_location(texture, 0, ~valid_location);
if (create_dib) if (create_dib)
wined3d_surface_create_dc(surface); wined3d_cs_init_object(device->cs, texture2d_create_dc, surface);
return WINED3D_OK; return WINED3D_OK;
} }
@ -1683,7 +1791,7 @@ static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
} }
if (surface->dc) if (surface->dc)
wined3d_surface_destroy_dc(surface); texture2d_destroy_dc(surface);
if (surface->overlay_dest) if (surface->overlay_dest)
list_remove(&surface->overlay_entry); list_remove(&surface->overlay_entry);
@ -2206,11 +2314,14 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface); TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface);
if (((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D))
&& FAILED(hr = wined3d_surface_create_dc(surface)))
{ {
wined3d_texture_cleanup_sync(texture); wined3d_cs_init_object(device->cs, texture2d_create_dc, surface);
return hr; if (!surface->dc)
{
wined3d_texture_cleanup_sync(texture);
return WINED3DERR_INVALIDCALL;
}
} }
} }
} }
@ -2984,9 +3095,7 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
{ {
struct wined3d_device *device = texture->resource.device; struct wined3d_device *device = texture->resource.device;
struct wined3d_texture_sub_resource *sub_resource; struct wined3d_texture_sub_resource *sub_resource;
struct wined3d_context *context = NULL;
struct wined3d_surface *surface; struct wined3d_surface *surface;
HRESULT hr = WINED3D_OK;
TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc);
@ -3011,17 +3120,9 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
if (device->d3d_initialized)
context = context_acquire(device, NULL, 0);
wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding);
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding);
if (!surface->dc) if (!surface->dc)
hr = wined3d_surface_create_dc(surface); wined3d_cs_init_object(device->cs, texture2d_create_dc, surface);
if (context) if (!surface->dc)
context_release(context);
if (FAILED(hr))
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
@ -3032,7 +3133,7 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
*dc = surface->dc; *dc = surface->dc;
TRACE("Returning dc %p.\n", *dc); TRACE("Returning dc %p.\n", *dc);
return hr; return WINED3D_OK;
} }
HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc) HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc)
@ -3064,7 +3165,7 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
} }
if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D))
wined3d_surface_destroy_dc(surface); wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface);
--sub_resource->map_count; --sub_resource->map_count;
if (!--texture->resource.map_count && texture->update_map_binding) if (!--texture->resource.map_count && texture->update_map_binding)

View File

@ -3061,8 +3061,6 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
HRESULT surface_color_fill(struct wined3d_surface *s, HRESULT surface_color_fill(struct wined3d_surface *s,
const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN;
HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
void wined3d_surface_destroy_dc(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
struct wined3d_context *context) DECLSPEC_HIDDEN; struct wined3d_context *context) DECLSPEC_HIDDEN;
BOOL surface_load_location(struct wined3d_surface *surface, BOOL surface_load_location(struct wined3d_surface *surface,