[PATCH 1/5] wined3d: Make the adapter responsible for texture creation and destruction.

Henri Verbeet hverbeet at codeweavers.com
Tue Aug 13 03:31:36 CDT 2019


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/adapter_gl.c      |  86 +++++++++++
 dlls/wined3d/adapter_vk.c      |  54 +++++++
 dlls/wined3d/directx.c         |  53 +++++++
 dlls/wined3d/texture.c         | 336 ++++++++++++++++++++++++-----------------
 dlls/wined3d/wined3d_private.h |  38 +++++
 5 files changed, 425 insertions(+), 142 deletions(-)

diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index d32b66480a6..cf54468a76b 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4745,6 +4745,90 @@ static void adapter_gl_destroy_buffer(struct wined3d_buffer *buffer)
         wined3d_device_decref(device);
 }
 
+static HRESULT adapter_gl_create_texture(struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
+{
+    struct wined3d_texture_gl *texture_gl;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
+
+    if (!(texture_gl = wined3d_texture_allocate_object_memory(sizeof(*texture_gl), level_count, layer_count)))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_texture_gl_init(texture_gl, device, desc,
+            layer_count, level_count, flags, parent, parent_ops)))
+    {
+        WARN("Failed to initialise texture, hr %#x.\n", hr);
+        heap_free(texture_gl);
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", texture_gl);
+    *texture = &texture_gl->t;
+
+    return hr;
+}
+
+static void wined3d_texture_gl_destroy_object(void *object)
+{
+    struct wined3d_renderbuffer_entry *entry, *entry2;
+    struct wined3d_texture_gl *texture_gl = object;
+    const struct wined3d_gl_info *gl_info;
+    struct wined3d_context *context;
+    struct wined3d_device *device;
+
+    TRACE("texture_gl %p.\n", texture_gl);
+
+    if (!list_empty(&texture_gl->renderbuffers))
+    {
+        device = texture_gl->t.resource.device;
+        context = context_acquire(device, NULL, 0);
+        gl_info = wined3d_context_gl(context)->gl_info;
+
+        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture_gl->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+        {
+            TRACE("Deleting renderbuffer %u.\n", entry->id);
+            context_gl_resource_released(device, entry->id, TRUE);
+            gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+            heap_free(entry);
+        }
+
+        context_release(context);
+    }
+
+    wined3d_texture_gl_unload_texture(texture_gl);
+
+    heap_free(texture_gl);
+}
+
+static void adapter_gl_destroy_texture(struct wined3d_texture *texture)
+{
+    struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(texture);
+    struct wined3d_device *device = texture_gl->t.resource.device;
+    unsigned int swapchain_count = device->swapchain_count;
+
+    TRACE("texture_gl %p.\n", texture_gl);
+
+    /* Take a reference to the device, in case releasing the texture would
+     * cause the device to be destroyed. However, swapchain resources don't
+     * take a reference to the device, and we wouldn't want to increment the
+     * refcount on a device that's in the process of being destroyed. */
+    if (swapchain_count)
+        wined3d_device_incref(device);
+
+    wined3d_texture_sub_resources_destroyed(texture);
+    texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
+
+    wined3d_texture_cleanup(&texture_gl->t);
+    wined3d_cs_destroy_object(device->cs, wined3d_texture_gl_destroy_object, texture_gl);
+
+    if (swapchain_count)
+        wined3d_device_decref(device);
+}
+
 static HRESULT adapter_gl_create_rendertarget_view(const struct wined3d_view_desc *desc,
         struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_rendertarget_view **view)
@@ -4953,6 +5037,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops =
     adapter_gl_destroy_swapchain,
     adapter_gl_create_buffer,
     adapter_gl_destroy_buffer,
+    adapter_gl_create_texture,
+    adapter_gl_destroy_texture,
     adapter_gl_create_rendertarget_view,
     adapter_gl_destroy_rendertarget_view,
     adapter_gl_create_shader_resource_view,
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index c3a1832e353..f203e0f52e1 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -543,6 +543,58 @@ static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
         wined3d_device_decref(device);
 }
 
+static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
+{
+    struct wined3d_texture_vk *texture_vk;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
+
+    if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
+            layer_count, level_count, flags, parent, parent_ops)))
+    {
+        WARN("Failed to initialise texture, hr %#x.\n", hr);
+        heap_free(texture_vk);
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", texture_vk);
+    *texture = &texture_vk->t;
+
+    return hr;
+}
+
+static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
+{
+    struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
+    struct wined3d_device *device = texture_vk->t.resource.device;
+    unsigned int swapchain_count = device->swapchain_count;
+
+    TRACE("texture_vk %p.\n", texture_vk);
+
+    /* Take a reference to the device, in case releasing the texture would
+     * cause the device to be destroyed. However, swapchain resources don't
+     * take a reference to the device, and we wouldn't want to increment the
+     * refcount on a device that's in the process of being destroyed. */
+    if (swapchain_count)
+        wined3d_device_incref(device);
+
+    wined3d_texture_sub_resources_destroyed(texture);
+    texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
+
+    wined3d_texture_cleanup(&texture_vk->t);
+    wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
+
+    if (swapchain_count)
+        wined3d_device_decref(device);
+}
+
 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
         struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_rendertarget_view **view)
@@ -696,6 +748,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
     adapter_vk_destroy_swapchain,
     adapter_vk_create_buffer,
     adapter_vk_destroy_buffer,
+    adapter_vk_create_texture,
+    adapter_vk_destroy_texture,
     adapter_vk_create_rendertarget_view,
     adapter_vk_destroy_rendertarget_view,
     adapter_vk_create_shader_resource_view,
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 201a5cf7a09..3c18e0e402e 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2428,6 +2428,57 @@ static void adapter_no3d_destroy_buffer(struct wined3d_buffer *buffer)
         wined3d_device_decref(device);
 }
 
+static HRESULT adapter_no3d_create_texture(struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
+{
+    struct wined3d_texture *texture_no3d;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
+
+    if (!(texture_no3d = wined3d_texture_allocate_object_memory(sizeof(*texture_no3d), level_count, layer_count)))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_texture_no3d_init(texture_no3d, device, desc,
+            layer_count, level_count, flags, parent, parent_ops)))
+    {
+        WARN("Failed to initialise texture, hr %#x.\n", hr);
+        heap_free(texture_no3d);
+        return hr;
+    }
+
+    TRACE("Created texture %p.\n", texture_no3d);
+    *texture = texture_no3d;
+
+    return hr;
+}
+
+static void adapter_no3d_destroy_texture(struct wined3d_texture *texture)
+{
+    struct wined3d_device *device = texture->resource.device;
+    unsigned int swapchain_count = device->swapchain_count;
+
+    TRACE("texture %p.\n", texture);
+
+    /* Take a reference to the device, in case releasing the texture would
+     * cause the device to be destroyed. However, swapchain resources don't
+     * take a reference to the device, and we wouldn't want to increment the
+     * refcount on a device that's in the process of being destroyed. */
+    if (swapchain_count)
+        wined3d_device_incref(device);
+
+    wined3d_texture_sub_resources_destroyed(texture);
+    texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
+
+    wined3d_texture_cleanup(texture);
+    wined3d_cs_destroy_object(device->cs, heap_free, texture);
+
+    if (swapchain_count)
+        wined3d_device_decref(device);
+}
+
 static HRESULT adapter_no3d_create_rendertarget_view(const struct wined3d_view_desc *desc,
         struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_rendertarget_view **view)
@@ -2518,6 +2569,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops =
     adapter_no3d_destroy_swapchain,
     adapter_no3d_create_buffer,
     adapter_no3d_destroy_buffer,
+    adapter_no3d_create_texture,
+    adapter_no3d_destroy_texture,
     adapter_no3d_create_rendertarget_view,
     adapter_no3d_destroy_rendertarget_view,
     adapter_no3d_create_shader_resource_view,
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 467dd093a45..4d411bf33f2 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -32,6 +32,7 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 static const uint32_t wined3d_texture_sysmem_locations = WINED3D_LOCATION_SYSMEM
         | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER;
+static const struct wined3d_texture_ops texture_gl_ops;
 
 struct wined3d_texture_idx
 {
@@ -633,7 +634,7 @@ static void wined3d_texture_gl_allocate_immutable_storage(struct wined3d_texture
     checkGLcall("allocate immutable storage");
 }
 
-static void wined3d_texture_gl_unload_texture(struct wined3d_texture_gl *texture_gl)
+void wined3d_texture_gl_unload_texture(struct wined3d_texture_gl *texture_gl)
 {
     struct wined3d_device *device = texture_gl->t.resource.device;
     const struct wined3d_gl_info *gl_info = NULL;
@@ -678,7 +679,7 @@ static void wined3d_texture_gl_unload_texture(struct wined3d_texture_gl *texture
     resource_unload(&texture_gl->t.resource);
 }
 
-static void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *texture)
+void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *texture)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
     struct wined3d_texture_sub_resource *sub_resource;
@@ -821,97 +822,6 @@ static void wined3d_texture_destroy_dc(void *object)
         context_release(context);
 }
 
-static void wined3d_texture_cleanup(struct wined3d_texture *texture)
-{
-    unsigned int sub_count = texture->level_count * texture->layer_count;
-    struct wined3d_device *device = texture->resource.device;
-    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;
-
-    TRACE("texture %p.\n", texture);
-
-    for (i = 0; i < sub_count; ++i)
-    {
-        if (!(buffer_object = texture->sub_resources[i].buffer_object))
-            continue;
-
-        TRACE("Deleting buffer object %u.\n", buffer_object);
-
-        /* We may not be able to get a context in wined3d_texture_cleanup() in
-         * general, but if a buffer object was previously created we can. */
-        if (!context)
-        {
-            context = context_acquire(device, NULL, 0);
-            gl_info = wined3d_context_gl(context)->gl_info;
-        }
-
-        GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
-    }
-
-    if (context)
-        context_release(context);
-
-    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)
-        {
-            struct wined3d_overlay_info *info = &texture->overlay_info[i];
-            struct wined3d_overlay_info *overlay, *cur;
-
-            list_remove(&info->entry);
-            LIST_FOR_EACH_ENTRY_SAFE(overlay, cur, &info->overlays, struct wined3d_overlay_info, entry)
-            {
-                list_remove(&overlay->entry);
-            }
-        }
-        heap_free(texture->overlay_info);
-    }
-}
-
-static void wined3d_texture_gl_cleanup(struct wined3d_texture_gl *texture_gl)
-{
-    struct wined3d_device *device = texture_gl->t.resource.device;
-    struct wined3d_renderbuffer_entry *entry, *entry2;
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
-
-    if (!list_empty(&texture_gl->renderbuffers))
-    {
-        context = context_acquire(device, NULL, 0);
-        gl_info = wined3d_context_gl(context)->gl_info;
-
-        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture_gl->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-        {
-            TRACE("Deleting renderbuffer %u.\n", entry->id);
-            context_gl_resource_released(device, entry->id, TRUE);
-            gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
-            heap_free(entry);
-        }
-
-        context_release(context);
-    }
-
-    wined3d_texture_cleanup(&texture_gl->t);
-    wined3d_texture_gl_unload_texture(texture_gl);
-}
-
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain)
 {
     texture->swapchain = swapchain;
@@ -1201,20 +1111,83 @@ ULONG CDECL wined3d_texture_incref(struct wined3d_texture *texture)
     return refcount;
 }
 
-static void wined3d_texture_cleanup_sync(struct wined3d_texture *texture)
+static void wined3d_texture_destroy_object(void *object)
 {
-    wined3d_texture_sub_resources_destroyed(texture);
-    resource_cleanup(&texture->resource);
-    wined3d_resource_wait_idle(&texture->resource);
-    wined3d_texture_cleanup(texture);
+    const struct wined3d_gl_info *gl_info = NULL;
+    struct wined3d_texture *texture = object;
+    struct wined3d_context *context = NULL;
+    struct wined3d_dc_info *dc_info;
+    unsigned int sub_count;
+    GLuint buffer_object;
+    unsigned int i;
+
+    TRACE("texture %p.\n", texture);
+
+    sub_count = texture->level_count * texture->layer_count;
+    for (i = 0; i < sub_count; ++i)
+    {
+        if (!(buffer_object = texture->sub_resources[i].buffer_object))
+            continue;
+
+        TRACE("Deleting buffer object %u.\n", buffer_object);
+
+        /* We may not be able to get a context in
+         * wined3d_texture_destroy_object() in general, but if a buffer object
+         * was previously created we can. */
+        if (!context)
+        {
+            context = context_acquire(texture->resource.device, NULL, 0);
+            gl_info = wined3d_context_gl(context)->gl_info;
+        }
+
+        GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
+    }
+
+    if (context)
+        context_release(context);
+
+    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)
+        {
+            struct wined3d_overlay_info *info = &texture->overlay_info[i];
+            struct wined3d_overlay_info *overlay, *cur;
+
+            list_remove(&info->entry);
+            LIST_FOR_EACH_ENTRY_SAFE(overlay, cur, &info->overlays, struct wined3d_overlay_info, entry)
+            {
+                list_remove(&overlay->entry);
+            }
+        }
+        heap_free(texture->overlay_info);
+    }
 }
 
-static void wined3d_texture_destroy_object(void *object)
+void wined3d_texture_cleanup(struct wined3d_texture *texture)
 {
-    struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(object);
+    resource_cleanup(&texture->resource);
+    wined3d_cs_destroy_object(texture->resource.device->cs, wined3d_texture_destroy_object, texture);
+}
 
-    wined3d_texture_gl_cleanup(texture_gl);
-    heap_free(texture_gl);
+static void wined3d_texture_cleanup_sync(struct wined3d_texture *texture)
+{
+    wined3d_texture_sub_resources_destroyed(texture);
+    wined3d_texture_cleanup(texture);
+    wined3d_resource_wait_idle(&texture->resource);
 }
 
 ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture)
@@ -1234,13 +1207,10 @@ ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture)
         /* Wait for the texture to become idle if it's using user memory,
          * since the application is allowed to free that memory once the
          * texture is destroyed. Note that this implies that
-         * wined3d_texture_destroy_object() can't access that memory either. */
+         * the destroy handler can't access that memory either. */
         if (texture->user_memory)
             wined3d_resource_wait_idle(&texture->resource);
-        wined3d_texture_sub_resources_destroyed(texture);
-        texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
-        resource_cleanup(&texture->resource);
-        wined3d_cs_destroy_object(texture->resource.device->cs, wined3d_texture_destroy_object, texture);
+        texture->resource.device->adapter->adapter_ops->adapter_destroy_texture(texture);
     }
 
     return refcount;
@@ -1636,10 +1606,13 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     sub_resource->size = texture->slice_pitch;
     sub_resource->locations = WINED3D_LOCATION_DISCARDED;
 
-    if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
-        wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE;
-    else
-        wined3d_texture_gl(texture)->target = GL_TEXTURE_2D;
+    if (texture->texture_ops == &texture_gl_ops)
+    {
+        if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
+            wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE;
+        else
+            wined3d_texture_gl(texture)->target = GL_TEXTURE_2D;
+    }
 
     if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot
             && !d3d_info->texture_npot_conditional)
@@ -3642,27 +3615,17 @@ HRESULT CDECL wined3d_texture_get_sub_resource_desc(const struct wined3d_texture
     return WINED3D_OK;
 }
 
-static void *wined3d_texture_allocate_object_memory(SIZE_T s, SIZE_T level_count, SIZE_T layer_count)
-{
-    struct wined3d_texture *t;
-
-    if (level_count > ((~(SIZE_T)0 - s) / sizeof(*t->sub_resources)) / layer_count)
-        return NULL;
-
-    return heap_alloc_zero(s + level_count * layer_count * sizeof(*t->sub_resources));
-}
-
-static HRESULT wined3d_texture_gl_init(struct wined3d_texture_gl *texture_gl, struct wined3d_device *device,
+HRESULT wined3d_texture_gl_init(struct wined3d_texture_gl *texture_gl, struct wined3d_device *device,
         const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
-        DWORD flags, void *parent, const struct wined3d_parent_ops *parent_ops, void *sub_resources)
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     HRESULT hr;
 
-    TRACE("texture_gl %p, device %p, desc %p, layer_count %u, level_count %u, "
-            "flags %#x, parent %p, parent_ops %p, sub_resources %p.\n",
-            texture_gl, device, desc, layer_count, level_count,
-            flags, parent, parent_ops, sub_resources);
+    TRACE("texture_gl %p, device %p, desc %p, layer_count %u, "
+            "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
+            texture_gl, device, desc, layer_count,
+            level_count, flags, parent, parent_ops);
 
     if (!(desc->usage & WINED3DUSAGE_LEGACY_CUBEMAP) && layer_count > 1
             && !gl_info->supported[EXT_TEXTURE_ARRAY])
@@ -3718,7 +3681,7 @@ static HRESULT wined3d_texture_gl_init(struct wined3d_texture_gl *texture_gl, st
     list_init(&texture_gl->renderbuffers);
 
     if (FAILED(hr = wined3d_texture_init(&texture_gl->t, desc, layer_count, level_count,
-            flags, device, parent, parent_ops, sub_resources, &texture_gl_ops)))
+            flags, device, parent, parent_ops, &texture_gl[1], &texture_gl_ops)))
         return hr;
 
     if (texture_gl->t.resource.gl_type == WINED3D_GL_RES_TYPE_TEX_RECT)
@@ -3732,7 +3695,6 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
 {
     unsigned int sub_count = level_count * layer_count;
-    struct wined3d_texture_gl *object;
     unsigned int i;
     HRESULT hr;
 
@@ -3790,16 +3752,9 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
         }
     }
 
-    if (!(object = wined3d_texture_allocate_object_memory(sizeof(*object), level_count, layer_count)))
-        return E_OUTOFMEMORY;
-
-    if (FAILED(hr = wined3d_texture_gl_init(object, device, desc, layer_count,
-            level_count, flags, parent, parent_ops, &object[1])))
-    {
-        WARN("Failed to initialize texture, returning %#x.\n", hr);
-        heap_free(object);
+    if (FAILED(hr = device->adapter->adapter_ops->adapter_create_texture(device, desc,
+            layer_count, level_count, flags, parent, parent_ops, texture)))
         return hr;
-    }
 
     /* FIXME: We'd like to avoid ever allocating system memory for the texture
      * in this case. */
@@ -3809,14 +3764,13 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
 
         for (i = 0; i < sub_count; ++i)
         {
-            wined3d_texture_get_level_box(&object->t, i % object->t.level_count, &box);
-            wined3d_cs_emit_update_sub_resource(device->cs, &object->t.resource,
+            wined3d_texture_get_level_box(*texture, i % (*texture)->level_count, &box);
+            wined3d_cs_emit_update_sub_resource(device->cs, &(*texture)->resource,
                     i, &box, data[i].data, data[i].row_pitch, data[i].slice_pitch);
         }
     }
 
-    TRACE("Created texture %p.\n", object);
-    *texture = &object->t;
+    TRACE("Created texture %p.\n", *texture);
 
     return WINED3D_OK;
 }
@@ -3993,3 +3947,101 @@ void wined3d_texture_download_from_texture(struct wined3d_texture *dst_texture,
     wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, dst_location);
     wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_location);
 }
+
+static void wined3d_texture_no3d_upload_data(struct wined3d_context *context,
+        const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format,
+        const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch,
+        struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_location,
+        unsigned int dst_x, unsigned int dst_y, unsigned int dst_z)
+{
+    FIXME("Not implemented.\n");
+}
+
+static void wined3d_texture_no3d_download_data(struct wined3d_context *context,
+        struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, unsigned int src_location,
+        const struct wined3d_box *src_box, const struct wined3d_bo_address *dst_bo_addr,
+        const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z,
+        unsigned int dst_row_pitch, unsigned int dst_slice_pitch)
+{
+    FIXME("Not implemented.\n");
+}
+
+static BOOL wined3d_texture_no3d_load_location(struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location)
+{
+    TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
+            texture, sub_resource_idx, context, wined3d_debug_location(location));
+
+    if (location == WINED3D_LOCATION_USER_MEMORY || location == WINED3D_LOCATION_SYSMEM)
+        return TRUE;
+
+    ERR("Unhandled location %s.\n", wined3d_debug_location(location));
+
+    return FALSE;
+}
+
+static const struct wined3d_texture_ops wined3d_texture_no3d_ops =
+{
+    wined3d_texture_no3d_load_location,
+    wined3d_texture_no3d_upload_data,
+    wined3d_texture_no3d_download_data,
+};
+
+HRESULT wined3d_texture_no3d_init(struct wined3d_texture *texture_no3d, struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    TRACE("texture_no3d %p, device %p, desc %p, layer_count %u, "
+            "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
+            texture_no3d, device, desc, layer_count,
+            level_count, flags, parent, parent_ops);
+
+    return wined3d_texture_init(texture_no3d, desc, layer_count, level_count,
+            flags, device, parent, parent_ops, &texture_no3d[1], &wined3d_texture_no3d_ops);
+}
+
+static void wined3d_texture_vk_upload_data(struct wined3d_context *context,
+        const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format,
+        const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch,
+        struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_location,
+        unsigned int dst_x, unsigned int dst_y, unsigned int dst_z)
+{
+    FIXME("Not implemented.\n");
+}
+
+static void wined3d_texture_vk_download_data(struct wined3d_context *context,
+        struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, unsigned int src_location,
+        const struct wined3d_box *src_box, const struct wined3d_bo_address *dst_bo_addr,
+        const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z,
+        unsigned int dst_row_pitch, unsigned int dst_slice_pitch)
+{
+    FIXME("Not implemented.\n");
+}
+
+static BOOL wined3d_texture_vk_load_location(struct wined3d_texture *texture,
+        unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location)
+{
+    FIXME("Not implemented.\n");
+
+    return FALSE;
+}
+
+static const struct wined3d_texture_ops wined3d_texture_vk_ops =
+{
+    wined3d_texture_vk_load_location,
+    wined3d_texture_vk_upload_data,
+    wined3d_texture_vk_download_data,
+};
+
+HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    TRACE("texture_vk %p, device %p, desc %p, layer_count %u, "
+            "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
+            texture_vk, device, desc, layer_count,
+            level_count, flags, parent, parent_ops);
+
+    return wined3d_texture_init(&texture_vk->t, desc, layer_count, level_count,
+            flags, device, parent, parent_ops, &texture_vk[1], &wined3d_texture_vk_ops);
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 860cf03169d..e81d72b7db3 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2788,6 +2788,10 @@ struct wined3d_adapter_ops
             const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
             struct wined3d_buffer **buffer);
     void (*adapter_destroy_buffer)(struct wined3d_buffer *buffer);
+    HRESULT (*adapter_create_texture)(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
+            unsigned int layer_count, unsigned int level_count, uint32_t flags, void *parent,
+            const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
+    void (*adapter_destroy_texture)(struct wined3d_texture *texture);
     HRESULT (*adapter_create_rendertarget_view)(const struct wined3d_view_desc *desc,
             struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
             struct wined3d_rendertarget_view **view);
@@ -3551,6 +3555,16 @@ struct wined3d_texture
     } *sub_resources;
 };
 
+static inline void *wined3d_texture_allocate_object_memory(SIZE_T s, SIZE_T level_count, SIZE_T layer_count)
+{
+    struct wined3d_texture *t;
+
+    if (level_count > ((~(SIZE_T)0 - s) / sizeof(*t->sub_resources)) / layer_count)
+        return NULL;
+
+    return heap_alloc_zero(s + level_count * layer_count * sizeof(*t->sub_resources));
+}
+
 static inline struct wined3d_texture *texture_from_resource(struct wined3d_resource *resource)
 {
     return CONTAINING_RECORD(resource, struct wined3d_texture, resource);
@@ -3613,6 +3627,7 @@ void texture2d_read_from_framebuffer(struct wined3d_texture *texture, unsigned i
 
 HRESULT wined3d_texture_check_box_dimensions(const struct wined3d_texture *texture,
         unsigned int level, const struct wined3d_box *box) DECLSPEC_HIDDEN;
+void wined3d_texture_cleanup(struct wined3d_texture *texture) DECLSPEC_HIDDEN;
 void wined3d_texture_download_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
         struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx) DECLSPEC_HIDDEN;
 GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) DECLSPEC_HIDDEN;
@@ -3629,6 +3644,7 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned
 void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN;
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *texture) DECLSPEC_HIDDEN;
 void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture,
         HWND window, RECT *rect) DECLSPEC_HIDDEN;
 void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
@@ -3641,6 +3657,10 @@ void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, un
 void wined3d_texture_validate_location(struct wined3d_texture *texture,
         unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
 
+HRESULT wined3d_texture_no3d_init(struct wined3d_texture *texture_no3d, struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+
 void wined3d_gl_texture_swizzle_from_color_fixup(GLint swizzle[4], struct color_fixup_desc fixup) DECLSPEC_HIDDEN;
 
 struct gl_texture
@@ -3709,11 +3729,29 @@ void wined3d_texture_gl_bind(struct wined3d_texture_gl *texture_gl,
         struct wined3d_context_gl *context_gl, BOOL srgb) DECLSPEC_HIDDEN;
 void wined3d_texture_gl_bind_and_dirtify(struct wined3d_texture_gl *texture_gl,
         struct wined3d_context_gl *context_gl, BOOL srgb) DECLSPEC_HIDDEN;
+HRESULT wined3d_texture_gl_init(struct wined3d_texture_gl *texture_gl, struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 void wined3d_texture_gl_prepare_texture(struct wined3d_texture_gl *texture_gl,
         struct wined3d_context_gl *context_gl, BOOL srgb) DECLSPEC_HIDDEN;
 void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl *texture_gl,
         struct wined3d_context_gl *context_gl, unsigned int level,
         const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
+void wined3d_texture_gl_unload_texture(struct wined3d_texture_gl *texture_gl) DECLSPEC_HIDDEN;
+
+struct wined3d_texture_vk
+{
+    struct wined3d_texture t;
+};
+
+static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_texture *texture)
+{
+    return CONTAINING_RECORD(texture, struct wined3d_texture_vk, t);
+}
+
+HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wined3d_device *device,
+        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
+        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 struct wined3d_renderbuffer_entry
 {
-- 
2.11.0




More information about the wine-devel mailing list