[PATCH 3/5] wined3d: Only store dc_info for textures that require it.

Henri Verbeet hverbeet at codeweavers.com
Thu Mar 15 03:08:40 CDT 2018


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/swapchain.c       |   6 +-
 dlls/wined3d/texture.c         | 320 ++++++++++++++++++++---------------------
 dlls/wined3d/wined3d_private.h |  12 +-
 3 files changed, 162 insertions(+), 176 deletions(-)

diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index f7aebdb7f32..4903445a0f0 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -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;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 68615b49a5b..e5a83ce7cba 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -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);
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 786de2c6d12..718ee63a214 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -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;
 
-- 
2.11.0




More information about the wine-devel mailing list