Commit 543a199d authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Only store dc_info for textures that require it.

parent 082abe4a
......@@ -549,7 +549,7 @@ static void swapchain_gdi_frontbuffer_updated(struct wined3d_swapchain *swapchai
TRACE("swapchain %p.\n", swapchain);
front = swapchain->front_buffer->sub_resources[0].dc_info;
front = &swapchain->front_buffer->dc_info[0];
if (swapchain->palette)
wined3d_palette_apply_to_dc(swapchain->palette, front->dc);
......@@ -589,8 +589,8 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain,
void *data;
HDC dc;
front = swapchain->front_buffer->sub_resources[0].dc_info;
back = swapchain->back_buffers[0]->sub_resources[0].dc_info;
front = &swapchain->front_buffer->dc_info[0];
back = &swapchain->back_buffers[0]->dc_info[0];
/* Flip the surface data. */
dc = front->dc;
......
......@@ -30,6 +30,12 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
#define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50
struct wined3d_texture_idx
{
struct wined3d_texture *texture;
unsigned int sub_resource_idx;
};
static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
{
return !(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU)
......@@ -652,6 +658,123 @@ static void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *text
}
}
static void wined3d_texture_create_dc(void *object)
{
const struct wined3d_texture_idx *idx = object;
struct wined3d_context *context = NULL;
unsigned int sub_resource_idx, level;
const struct wined3d_format *format;
unsigned int row_pitch, slice_pitch;
struct wined3d_texture *texture;
struct wined3d_dc_info *dc_info;
struct wined3d_bo_address data;
D3DKMT_CREATEDCFROMMEMORY desc;
struct wined3d_device *device;
NTSTATUS status;
TRACE("texture %p, sub_resource_idx %u.\n", idx->texture, idx->sub_resource_idx);
texture = idx->texture;
sub_resource_idx = idx->sub_resource_idx;
level = sub_resource_idx % texture->level_count;
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 (!texture->dc_info)
{
unsigned int sub_count = texture->level_count * texture->layer_count;
if (!(texture->dc_info = heap_calloc(sub_count, sizeof(*texture->dc_info))))
{
ERR("Failed to allocate DC info.\n");
return;
}
}
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);
wined3d_texture_get_pitch(texture, level, &row_pitch, &slice_pitch);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
desc.pMemory = context_map_bo_address(context, &data,
texture->sub_resources[sub_resource_idx].size,
GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE);
if (context)
context_release(context);
desc.Format = format->ddi_format;
desc.Width = wined3d_texture_get_level_width(texture, level);
desc.Height = wined3d_texture_get_level_height(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;
}
dc_info = &texture->dc_info[sub_resource_idx];
dc_info->dc = desc.hDc;
dc_info->bitmap = desc.hBitmap;
TRACE("Created DC %p, bitmap %p for texture %p, %u.\n", dc_info->dc, dc_info->bitmap, texture, sub_resource_idx);
}
static void wined3d_texture_destroy_dc(void *object)
{
const struct wined3d_texture_idx *idx = object;
D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
struct wined3d_context *context = NULL;
struct wined3d_texture *texture;
struct wined3d_dc_info *dc_info;
struct wined3d_bo_address data;
unsigned int sub_resource_idx;
struct wined3d_device *device;
NTSTATUS status;
texture = idx->texture;
sub_resource_idx = idx->sub_resource_idx;
device = texture->resource.device;
dc_info = &texture->dc_info[sub_resource_idx];
if (!dc_info->dc)
{
ERR("Sub-resource {%p, %u} has no DC.\n", texture, sub_resource_idx);
return;
}
TRACE("dc %p, bitmap %p.\n", dc_info->dc, dc_info->bitmap);
destroy_desc.hDc = dc_info->dc;
destroy_desc.hBitmap = dc_info->bitmap;
if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
ERR("Failed to destroy dc, status %#x.\n", status);
dc_info->dc = NULL;
dc_info->bitmap = NULL;
if (device->d3d_initialized)
context = context_acquire(device, NULL, 0);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
if (context)
context_release(context);
}
static void wined3d_texture_cleanup(struct wined3d_texture *texture)
{
unsigned int sub_count = texture->level_count * texture->layer_count;
......@@ -659,6 +782,7 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
struct wined3d_renderbuffer_entry *entry, *entry2;
const struct wined3d_gl_info *gl_info = NULL;
struct wined3d_context *context = NULL;
struct wined3d_dc_info *dc_info;
GLuint buffer_object;
unsigned int i;
......@@ -699,7 +823,20 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
if (context)
context_release(context);
texture->texture_ops->texture_cleanup_sub_resources(texture);
if ((dc_info = texture->dc_info))
{
for (i = 0; i < sub_count; ++i)
{
if (dc_info[i].dc)
{
struct wined3d_texture_idx texture_idx = {texture, i};
wined3d_texture_destroy_dc(&texture_idx);
}
}
heap_free(dc_info);
}
if (texture->overlay_info)
{
for (i = 0; i < sub_count; ++i)
......@@ -1334,118 +1471,6 @@ void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture
checkGLcall("set_compatible_renderbuffer");
}
struct wined3d_texture_idx
{
struct wined3d_texture *texture;
unsigned int sub_resource_idx;
};
static void texture2d_create_dc(void *object)
{
const struct wined3d_texture_idx *idx = object;
struct wined3d_context *context = NULL;
unsigned int sub_resource_idx, level;
const struct wined3d_format *format;
unsigned int row_pitch, slice_pitch;
struct wined3d_texture *texture;
struct wined3d_dc_info *dc_info;
struct wined3d_bo_address data;
D3DKMT_CREATEDCFROMMEMORY desc;
struct wined3d_device *device;
NTSTATUS status;
TRACE("texture %p, sub_resource_idx %u.\n", idx->texture, idx->sub_resource_idx);
texture = idx->texture;
sub_resource_idx = idx->sub_resource_idx;
level = sub_resource_idx % texture->level_count;
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);
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, level, &row_pitch, &slice_pitch);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
desc.pMemory = context_map_bo_address(context, &data,
texture->sub_resources[sub_resource_idx].size,
GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ | WINED3D_MAP_WRITE);
if (context)
context_release(context);
desc.Format = format->ddi_format;
desc.Width = wined3d_texture_get_level_width(texture, level);
desc.Height = wined3d_texture_get_level_height(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;
}
dc_info = texture->sub_resources[sub_resource_idx].dc_info;
dc_info->dc = desc.hDc;
dc_info->bitmap = desc.hBitmap;
TRACE("Created DC %p, bitmap %p for texture %p, %u.\n", dc_info->dc, dc_info->bitmap, texture, sub_resource_idx);
}
static void texture2d_destroy_dc(void *object)
{
const struct wined3d_texture_idx *idx = object;
D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
struct wined3d_context *context = NULL;
struct wined3d_texture *texture;
struct wined3d_dc_info *dc_info;
struct wined3d_bo_address data;
unsigned int sub_resource_idx;
struct wined3d_device *device;
NTSTATUS status;
texture = idx->texture;
sub_resource_idx = idx->sub_resource_idx;
device = texture->resource.device;
dc_info = texture->sub_resources[sub_resource_idx].dc_info;
if (!dc_info->dc)
{
ERR("Sub-resource {%p, %u} has no DC.\n", texture, sub_resource_idx);
return;
}
TRACE("dc %p, bitmap %p.\n", dc_info->dc, dc_info->bitmap);
destroy_desc.hDc = dc_info->dc;
destroy_desc.hBitmap = dc_info->bitmap;
if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
ERR("Failed to destroy dc, status %#x.\n", status);
dc_info->dc = NULL;
dc_info->bitmap = NULL;
if (device->d3d_initialized)
context = context_acquire(device, NULL, 0);
wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding);
context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER);
if (context)
context_release(context);
}
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,
UINT multisample_quality, void *mem, UINT pitch)
......@@ -1501,11 +1526,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
wined3d_resource_wait_idle(&texture->resource);
sub_resource = &texture->sub_resources[0];
if (sub_resource->dc_info->dc)
if (texture->dc_info && texture->dc_info[0].dc)
{
struct wined3d_texture_idx texture_idx = {texture, 0};
wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, &texture_idx);
wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx);
device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
create_dib = TRUE;
}
......@@ -1575,7 +1600,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
{
struct wined3d_texture_idx texture_idx = {texture, 0};
wined3d_cs_init_object(device->cs, texture2d_create_dc, &texture_idx);
wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
}
......@@ -1874,35 +1899,11 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi
wined3d_texture_allocate_gl_mutable_storage(texture, internal, format, gl_info);
}
static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
{
unsigned int sub_count = texture->level_count * texture->layer_count;
struct wined3d_texture_sub_resource *sub_resource;
struct wined3d_dc_info *dc_info;
unsigned int i;
for (i = 0; i < sub_count; ++i)
{
sub_resource = &texture->sub_resources[i];
if (!(dc_info = sub_resource->dc_info))
continue;
if (dc_info->dc)
{
struct wined3d_texture_idx texture_idx = {texture, i};
texture2d_destroy_dc(&texture_idx);
}
}
heap_free(texture->sub_resources[0].dc_info);
}
static const struct wined3d_texture_ops texture2d_ops =
{
texture2d_upload_data,
texture2d_load_location,
texture2d_prepare_texture,
texture2d_cleanup_sub_resources,
};
struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_resource *resource)
......@@ -2178,7 +2179,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
{
struct wined3d_device_parent *device_parent = device->device_parent;
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
struct wined3d_dc_info *dc_infos;
UINT pow2_width, pow2_height;
unsigned int sub_count, i;
HRESULT hr;
......@@ -2327,8 +2327,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
sub_count = level_count * layer_count;
if (sub_count / layer_count != level_count
|| !(dc_infos = heap_calloc(sub_count, sizeof(*dc_infos))))
if (sub_count / layer_count != level_count)
{
wined3d_texture_cleanup_sync(texture);
return E_OUTOFMEMORY;
......@@ -2338,7 +2337,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
{
if (!(texture->overlay_info = heap_calloc(sub_count, sizeof(*texture->overlay_info))))
{
heap_free(dc_infos);
wined3d_texture_cleanup_sync(texture);
return E_OUTOFMEMORY;
}
......@@ -2354,13 +2352,9 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
for (i = 0; i < sub_count; ++i)
{
struct wined3d_texture_sub_resource *sub_resource;
struct wined3d_dc_info *dc_info;
dc_info = &dc_infos[i];
sub_resource = &texture->sub_resources[i];
sub_resource->locations = WINED3D_LOCATION_DISCARDED;
sub_resource->dc_info = dc_info;
if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL))
{
wined3d_texture_validate_location(texture, i, WINED3D_LOCATION_SYSMEM);
......@@ -2385,9 +2379,9 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
{
struct wined3d_texture_idx texture_idx = {texture, i};
wined3d_cs_init_object(device->cs, texture2d_create_dc, &texture_idx);
wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
if (!dc_info->dc)
if (!texture->dc_info || !texture->dc_info[i].dc)
{
wined3d_texture_cleanup_sync(texture);
return WINED3DERR_INVALIDCALL;
......@@ -2670,16 +2664,11 @@ static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wi
}
}
static void texture3d_cleanup_sub_resources(struct wined3d_texture *texture)
{
}
static const struct wined3d_texture_ops texture3d_ops =
{
texture3d_upload_data,
texture3d_load_location,
texture3d_prepare_texture,
texture3d_cleanup_sub_resources,
};
static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
......@@ -3162,27 +3151,25 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i
return WINED3DERR_INVALIDCALL;
}
dc_info = sub_resource->dc_info;
if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
return WINED3DERR_INVALIDCALL;
if (!dc_info->dc)
if (!(dc_info = texture->dc_info) || !dc_info[sub_resource_idx].dc)
{
struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
wined3d_cs_init_object(device->cs, texture2d_create_dc, &texture_idx);
wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
if (!(dc_info = texture->dc_info) || !dc_info[sub_resource_idx].dc)
return WINED3DERR_INVALIDCALL;
}
if (!dc_info->dc)
return WINED3DERR_INVALIDCALL;
if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT))
texture->flags |= WINED3D_TEXTURE_DC_IN_USE;
++texture->resource.map_count;
++sub_resource->map_count;
*dc = dc_info->dc;
*dc = dc_info[sub_resource_idx].dc;
TRACE("Returning dc %p.\n", *dc);
return WINED3D_OK;
......@@ -3205,14 +3192,13 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
return WINED3DERR_INVALIDCALL;
}
dc_info = sub_resource->dc_info;
if (!(texture->flags & (WINED3D_TEXTURE_GET_DC_LENIENT | WINED3D_TEXTURE_DC_IN_USE)))
return WINED3DERR_INVALIDCALL;
if (dc_info->dc != dc)
if (!(dc_info = texture->dc_info) || dc_info[sub_resource_idx].dc != dc)
{
WARN("Application tries to release invalid DC %p, sub-resource DC is %p.\n", dc, dc_info->dc);
WARN("Application tries to release invalid DC %p, sub-resource DC is %p.\n",
dc, dc_info ? dc_info[sub_resource_idx].dc : NULL);
return WINED3DERR_INVALIDCALL;
}
......@@ -3220,7 +3206,7 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
{
struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, &texture_idx);
wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx);
device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
}
......
......@@ -3090,7 +3090,6 @@ struct wined3d_texture_ops
struct wined3d_context *context, DWORD location);
void (*texture_prepare_texture)(struct wined3d_texture *texture,
struct wined3d_context *context, BOOL srgb);
void (*texture_cleanup_sub_resources)(struct wined3d_texture *texture);
};
#define WINED3D_TEXTURE_COND_NP2 0x00000001
......@@ -3162,6 +3161,12 @@ struct wined3d_texture
RECT dst_rect;
} *overlay_info;
struct wined3d_dc_info
{
HBITMAP bitmap;
HDC dc;
} *dc_info;
struct list renderbuffers;
const struct wined3d_renderbuffer_entry *current_renderbuffer;
......@@ -3170,11 +3175,6 @@ struct wined3d_texture
void *parent;
const struct wined3d_parent_ops *parent_ops;
struct wined3d_dc_info
{
HBITMAP bitmap;
HDC dc;
} *dc_info;
unsigned int offset;
unsigned int size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment