[PATCH 4/6] wined3d: Create texture views for shader resource views.

Józef Kucia jkucia at codeweavers.com
Mon Jun 6 04:39:05 CDT 2016


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
 dlls/wined3d/context.c         |  11 +--
 dlls/wined3d/utils.c           |  21 +++++
 dlls/wined3d/view.c            | 175 +++++++++++++++++++++++++++++++++++++++--
 dlls/wined3d/wined3d_private.h |   9 +++
 4 files changed, 201 insertions(+), 15 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 845ca1d..e748f63 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -3292,7 +3292,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
     struct wined3d_shader_sampler_map_entry *entry;
     struct wined3d_shader_resource_view *view;
     struct wined3d_sampler *sampler;
-    struct wined3d_texture *texture;
     struct wined3d_shader *shader;
     unsigned int i, j, count;
     GLuint sampler_name;
@@ -3332,12 +3331,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
                 continue;
             }
 
-            if (view->resource->type == WINED3D_RTYPE_BUFFER)
-            {
-                FIXME("Buffer shader resources not supported.\n");
-                continue;
-            }
-
             if (entry->sampler_idx == WINED3D_SAMPLER_DEFAULT)
                 sampler_name = device->default_sampler;
             else if ((sampler = state->sampler[shader_types[i].type][entry->sampler_idx]))
@@ -3345,12 +3338,10 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
             else
                 sampler_name = device->null_sampler;
 
-            texture = texture_from_resource(view->resource);
             context_active_texture(context, gl_info, shader_types[i].base_idx + entry->bind_idx);
-            wined3d_texture_bind(texture, context, FALSE);
-
             GL_EXTCALL(glBindSampler(shader_types[i].base_idx + entry->bind_idx, sampler_name));
             checkGLcall("glBindSampler");
+            wined3d_shader_resource_view_bind(view, context);
         }
     }
 }
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 97c3e19..4831ac3 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1661,6 +1661,7 @@ static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
         format->block_width = typeless_format->block_width;
         format->block_height = typeless_format->block_height;
         format->block_byte_count = typeless_format->block_byte_count;
+        format->typeless_id = typeless_format->id;
 
         for (j = 0; j < strlen(typed_formats[i].channels); ++j)
         {
@@ -3731,6 +3732,26 @@ const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type)
     }
 }
 
+const char *debug_d3dviewtype(enum wined3d_view_type view_type)
+{
+    switch (view_type)
+    {
+#define WINED3D_TO_STR(x) case x: return #x
+        WINED3D_TO_STR(WINED3D_VTYPE_BUFFER);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_1D);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_1D_ARRAY);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_2D);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_2D_ARRAY);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_3D);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_CUBE);
+        WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_CUBE_ARRAY);
+#undef WINED3D_TO_STR
+        default:
+            FIXME("Unrecognized view type %#x.\n", view_type);
+            return "unrecognized";
+    }
+}
+
 const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type)
 {
     switch (primitive_type)
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index b12edec..46e2c26 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -24,6 +24,55 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
+static BOOL gl_internal_format_equal(const struct wined3d_format *format1,
+        const struct wined3d_format *format2)
+{
+    return format1->id == format2->id
+            || (format1->glInternal == format2->glInternal
+            && format1->glGammaInternal == format2->glGammaInternal
+            && format1->rtInternal == format2->rtInternal);
+}
+
+static BOOL gl_texture_view_compatible(const struct wined3d_format *format1,
+        const struct wined3d_format *format2, enum wined3d_gl_resource_type gl_type)
+{
+    return gl_internal_format_equal(format1, format2)
+            || (format1->typeless_id == format2->typeless_id
+            && !(format1->flags[gl_type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+            && !(format2->flags[gl_type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)));
+}
+
+static GLenum gl_texture_view_target(GLenum texture_target, enum wined3d_view_type view_type)
+{
+    static const struct
+    {
+        GLenum texture_target;
+        enum wined3d_view_type view_type;
+        GLenum view_target;
+    }
+    view_types[] =
+    {
+        {GL_TEXTURE_2D,       WINED3D_VTYPE_TEXTURE_2D,       GL_TEXTURE_2D},
+        {GL_TEXTURE_2D,       WINED3D_VTYPE_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY},
+        {GL_TEXTURE_2D_ARRAY, WINED3D_VTYPE_TEXTURE_2D,       GL_TEXTURE_2D},
+        {GL_TEXTURE_2D_ARRAY, WINED3D_VTYPE_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY},
+        {GL_TEXTURE_2D_ARRAY, WINED3D_VTYPE_TEXTURE_CUBE,     GL_TEXTURE_CUBE_MAP},
+        {GL_TEXTURE_3D,       WINED3D_VTYPE_TEXTURE_3D,       GL_TEXTURE_3D},
+    };
+
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(view_types); ++i)
+    {
+        if (view_types[i].texture_target == texture_target && view_types[i].view_type == view_type)
+            return view_types[i].view_target;
+    }
+
+    FIXME("Unhandled view type %s for texture target %#x.\n",
+            debug_d3dviewtype(view_type), texture_target);
+    return texture_target;
+}
+
 ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
 {
     ULONG refcount = InterlockedIncrement(&view->refcount);
@@ -185,6 +234,14 @@ ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_v
 
     if (!refcount)
     {
+        if (view->object)
+        {
+            struct wined3d_context *context = context_acquire(view->resource->device, NULL);
+            const struct wined3d_gl_info *gl_info = context->gl_info;
+            gl_info->gl_ops.gl.p_glDeleteTextures(1, &view->object);
+            checkGLcall("glDeleteTextures");
+            context_release(context);
+        }
         /* Call wined3d_object_destroyed() before releasing the resource,
          * since releasing the resource may end up destroying the parent. */
         view->parent_ops->wined3d_object_destroyed(view->parent);
@@ -202,11 +259,97 @@ void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader
     return view->parent;
 }
 
+static void wined3d_shader_resource_view_create_texture_view(struct wined3d_shader_resource_view *view,
+        const struct wined3d_shader_resource_view_desc *desc, const struct wined3d_format *view_format,
+        struct wined3d_texture *texture)
+{
+    struct wined3d_context *context = context_acquire(texture->resource.device, NULL);
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct gl_texture *gl_texture;
+
+    if (!gl_info->supported[ARB_TEXTURE_VIEW])
+    {
+        context_release(context);
+        FIXME("OpenGL implementation does not support texture views.\n");
+        return;
+    }
+
+    view->target = gl_texture_view_target(texture->target, desc->view_type);
+
+    wined3d_texture_prepare_texture(texture, context, FALSE);
+    gl_texture = wined3d_texture_get_gl_texture(texture, FALSE);
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &view->object);
+    GL_EXTCALL(glTextureView(view->object, view->target, gl_texture->name, view_format->glInternal,
+            desc->u.texture.level_idx, desc->u.texture.level_count,
+            desc->u.texture.layer_idx, desc->u.texture.layer_count));
+    checkGLcall("Create texture view");
+
+    context_release(context);
+}
+
+static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
+        const struct wined3d_shader_resource_view_desc *desc, struct wined3d_resource *resource,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
+    const struct wined3d_format *view_format;
+
+    view_format = wined3d_get_format(gl_info, desc->format_id);
+
+    view->refcount = 1;
+    view->parent = parent;
+    view->parent_ops = parent_ops;
+
+    view->target = GL_NONE;
+    view->object = 0;
+
+    if (resource->type == WINED3D_RTYPE_BUFFER)
+    {
+        FIXME("Buffer shader resource views not supported.\n");
+    }
+    else
+    {
+        struct wined3d_texture *texture = texture_from_resource(resource);
+
+        if (desc->u.texture.level_idx >= texture->level_count
+                || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
+                || desc->u.texture.layer_idx >= texture->layer_count
+                || desc->u.texture.layer_count > texture->layer_count - desc->u.texture.layer_idx)
+            return E_FAIL;
+
+        if (gl_internal_format_equal(resource->format, view_format)
+                && gl_texture_view_target(texture->target, desc->view_type) == texture->target
+                && !desc->u.texture.level_idx && desc->u.texture.level_count == texture->level_count
+                && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture->layer_count)
+        {
+            TRACE("Creating identity shader resource view.\n");
+        }
+        else if (texture->swapchain && texture->swapchain->desc.backbuffer_count > 1)
+        {
+            FIXME("Swapchain shader resource views not supported.\n");
+        }
+        else if (gl_texture_view_compatible(resource->format, view_format, resource->gl_type))
+        {
+            wined3d_shader_resource_view_create_texture_view(view, desc, view_format, texture);
+        }
+        else
+        {
+            FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
+                    debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
+        }
+    }
+    wined3d_resource_incref(view->resource = resource);
+
+    return WINED3D_OK;
+}
+
 HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_shader_resource_view_desc *desc,
         struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
         struct wined3d_shader_resource_view **view)
 {
     struct wined3d_shader_resource_view *object;
+    HRESULT hr;
 
     TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
             desc, resource, parent, parent_ops, view);
@@ -214,14 +357,36 @@ HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_shader_re
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    object->refcount = 1;
-    object->resource = resource;
-    wined3d_resource_incref(resource);
-    object->parent = parent;
-    object->parent_ops = parent_ops;
+    if (FAILED(hr = wined3d_shader_resource_view_init(object, desc, resource, parent, parent_ops)))
+    {
+        HeapFree(GetProcessHeap(), 0, object);
+        WARN("Failed to initialise view, hr %#x.\n", hr);
+        return hr;
+    }
 
     TRACE("Created shader resource view %p.\n", object);
     *view = object;
 
     return WINED3D_OK;
 }
+
+void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
+        struct wined3d_context *context)
+{
+    struct wined3d_texture *texture;
+
+    if (view->object)
+    {
+        context_bind_texture(context, view->target, view->object);
+        return;
+    }
+
+    if (view->resource->type == WINED3D_RTYPE_BUFFER)
+    {
+        FIXME("Buffer shader resources not supported.\n");
+        return;
+    }
+
+    texture = wined3d_texture_from_resource(view->resource);
+    wined3d_texture_bind(texture, context, FALSE);
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f9a8ffa..4c7eaae 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3077,8 +3077,14 @@ struct wined3d_shader_resource_view
     struct wined3d_resource *resource;
     void *parent;
     const struct wined3d_parent_ops *parent_ops;
+
+    GLenum target;
+    GLuint object;
 };
 
+void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
+        struct wined3d_context *context) DECLSPEC_HIDDEN;
+
 struct wined3d_swapchain_ops
 {
     void (*swapchain_present)(struct wined3d_swapchain *swapchain,
@@ -3148,6 +3154,7 @@ const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state) DECLSP
 const char *debug_d3dtop(enum wined3d_texture_op d3dtop) DECLSPEC_HIDDEN;
 const char *debug_d3dtstype(enum wined3d_transform_state tstype) DECLSPEC_HIDDEN;
 const char *debug_d3dpool(enum wined3d_pool pool) DECLSPEC_HIDDEN;
+const char *debug_d3dviewtype(enum wined3d_view_type view_type) DECLSPEC_HIDDEN;
 const char *debug_fboattachment(GLenum attachment) DECLSPEC_HIDDEN;
 const char *debug_fbostatus(GLenum status) DECLSPEC_HIDDEN;
 const char *debug_glerror(GLenum error) DECLSPEC_HIDDEN;
@@ -3532,6 +3539,8 @@ struct wined3d_format
     struct color_fixup_desc color_fixup;
     void (*convert)(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
             UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth);
+
+    enum wined3d_format_id typeless_id;
 };
 
 const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
-- 
2.7.3




More information about the wine-patches mailing list