[Mesa-dev] [PATCH 3/4] gallium: add pipe_screen::check_resource_capability

Marek Olšák maraeo at gmail.com
Mon Oct 9 17:05:05 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

This is optional (and no CAP).

Implemented by radeonsi, ddebug, rbug, trace.
---
 src/gallium/drivers/ddebug/dd_screen.c    | 11 +++++++++++
 src/gallium/drivers/radeon/r600_texture.c | 21 +++++++++++++++++++++
 src/gallium/drivers/rbug/rbug_screen.c    | 14 ++++++++++++++
 src/gallium/drivers/trace/tr_screen.c     | 11 +++++++++++
 src/gallium/include/pipe/p_screen.h       | 17 +++++++++++++++++
 5 files changed, 74 insertions(+)

diff --git a/src/gallium/drivers/ddebug/dd_screen.c b/src/gallium/drivers/ddebug/dd_screen.c
index c518f5f..caf31f6 100644
--- a/src/gallium/drivers/ddebug/dd_screen.c
+++ b/src/gallium/drivers/ddebug/dd_screen.c
@@ -301,20 +301,30 @@ dd_screen_resource_get_handle(struct pipe_screen *_screen,
                               struct pipe_resource *resource,
                               struct winsys_handle *handle,
                               unsigned usage)
 {
    struct pipe_screen *screen = dd_screen(_screen)->screen;
    struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;
 
    return screen->resource_get_handle(screen, pipe, resource, handle, usage);
 }
 
+static bool
+dd_screen_check_resource_capability(struct pipe_screen *_screen,
+                                    struct pipe_resource *resource,
+                                    unsigned bind)
+{
+   struct pipe_screen *screen = dd_screen(_screen)->screen;
+
+   return screen->check_resource_capability(screen, resource, bind);
+}
+
 
 /********************************************************************
  * fence
  */
 
 static void
 dd_screen_fence_reference(struct pipe_screen *_screen,
                           struct pipe_fence_handle **pdst,
                           struct pipe_fence_handle *src)
 {
@@ -460,20 +470,21 @@ ddebug_screen_create(struct pipe_screen *screen)
    /* get_compute_param */
    SCR_INIT(get_timestamp);
    dscreen->base.context_create = dd_screen_context_create;
    dscreen->base.is_format_supported = dd_screen_is_format_supported;
    /* is_video_format_supported */
    SCR_INIT(can_create_resource);
    dscreen->base.resource_create = dd_screen_resource_create;
    dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
    SCR_INIT(resource_from_memobj);
    SCR_INIT(resource_from_user_memory);
+   SCR_INIT(check_resource_capability);
    dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
    SCR_INIT(resource_changed);
    dscreen->base.resource_destroy = dd_screen_resource_destroy;
    SCR_INIT(flush_frontbuffer);
    SCR_INIT(fence_reference);
    SCR_INIT(fence_finish);
    SCR_INIT(memobj_create_from_handle);
    SCR_INIT(memobj_destroy);
    SCR_INIT(get_driver_query_info);
    SCR_INIT(get_driver_query_group_info);
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index 78d49c2..a237c3c 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -2871,25 +2871,46 @@ r600_texture_from_memobj(struct pipe_screen *screen,
 
 	rtex->resource.b.is_shared = true;
 	rtex->resource.external_usage = PIPE_HANDLE_USAGE_READ_WRITE;
 
 	if (rscreen->apply_opaque_metadata)
 		rscreen->apply_opaque_metadata(rscreen, rtex, &metadata);
 
 	return &rtex->resource.b.b;
 }
 
+static bool si_check_resource_capability(struct pipe_screen *screen,
+					 struct pipe_resource *resource,
+					 unsigned bind)
+{
+	struct r600_texture *tex = (struct r600_texture*)resource;
+
+	/* Buffers only support the linear flag. */
+	if (resource->target == PIPE_BUFFER)
+		return (bind & ~PIPE_BIND_LINEAR) == 0;
+
+	if (bind & PIPE_BIND_LINEAR && !tex->surface.is_linear)
+		return false;
+
+	if (bind & PIPE_BIND_SCANOUT && !tex->surface.is_displayable)
+		return false;
+
+	/* TODO: PIPE_BIND_CURSOR - do we care? */
+	return true;
+}
+
 void si_init_screen_texture_functions(struct r600_common_screen *rscreen)
 {
 	rscreen->b.resource_from_handle = r600_texture_from_handle;
 	rscreen->b.resource_get_handle = r600_texture_get_handle;
 	rscreen->b.resource_from_memobj = r600_texture_from_memobj;
 	rscreen->b.memobj_create_from_handle = r600_memobj_from_handle;
 	rscreen->b.memobj_destroy = r600_memobj_destroy;
+	rscreen->b.check_resource_capability = si_check_resource_capability;
 }
 
 void si_init_context_texture_functions(struct r600_common_context *rctx)
 {
 	rctx->b.create_surface = r600_create_surface;
 	rctx->b.surface_destroy = r600_surface_destroy;
 	rctx->b.clear_texture = r600_clear_texture;
 }
diff --git a/src/gallium/drivers/rbug/rbug_screen.c b/src/gallium/drivers/rbug/rbug_screen.c
index b12f029..2477edb 100644
--- a/src/gallium/drivers/rbug/rbug_screen.c
+++ b/src/gallium/drivers/rbug/rbug_screen.c
@@ -176,20 +176,33 @@ rbug_screen_resource_from_handle(struct pipe_screen *_screen,
    struct pipe_screen *screen = rb_screen->screen;
    struct pipe_resource *result;
 
    result = screen->resource_from_handle(screen, templ, handle, usage);
 
    result = rbug_resource_create(rbug_screen(_screen), result);
 
    return result;
 }
 
+static bool
+rbug_screen_check_resource_capability(struct pipe_screen *_screen,
+                                      struct pipe_resource *_resource,
+                                      unsigned bind)
+{
+   struct rbug_screen *rb_screen = rbug_screen(_screen);
+   struct rbug_resource *rb_resource = rbug_resource(_resource);
+   struct pipe_screen *screen = rb_screen->screen;
+   struct pipe_resource *resource = rb_resource->resource;
+
+   return screen->check_resource_capability(screen, resource, bind);
+}
+
 static boolean
 rbug_screen_resource_get_handle(struct pipe_screen *_screen,
                                 struct pipe_context *_pipe,
                                 struct pipe_resource *_resource,
                                 struct winsys_handle *handle,
                                 unsigned usage)
 {
    struct rbug_screen *rb_screen = rbug_screen(_screen);
    struct rbug_context *rb_pipe = rbug_context(_pipe);
    struct rbug_resource *rb_resource = rbug_resource(_resource);
@@ -294,20 +307,21 @@ rbug_screen_create(struct pipe_screen *screen)
    rb_screen->base.get_vendor = rbug_screen_get_vendor;
    SCR_INIT(get_disk_shader_cache);
    rb_screen->base.get_device_vendor = rbug_screen_get_device_vendor;
    rb_screen->base.get_param = rbug_screen_get_param;
    rb_screen->base.get_shader_param = rbug_screen_get_shader_param;
    rb_screen->base.get_paramf = rbug_screen_get_paramf;
    rb_screen->base.is_format_supported = rbug_screen_is_format_supported;
    rb_screen->base.context_create = rbug_screen_context_create;
    rb_screen->base.resource_create = rbug_screen_resource_create;
    rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle;
+   SCR_INIT(check_resource_capability);
    rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle;
    SCR_INIT(resource_changed);
    rb_screen->base.resource_destroy = rbug_screen_resource_destroy;
    rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer;
    rb_screen->base.fence_reference = rbug_screen_fence_reference;
    rb_screen->base.fence_finish = rbug_screen_fence_finish;
 
    rb_screen->screen = screen;
 
    rb_screen->private_context = screen->context_create(screen, NULL, 0);
diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
index 539b17e..d5a8124 100644
--- a/src/gallium/drivers/trace/tr_screen.c
+++ b/src/gallium/drivers/trace/tr_screen.c
@@ -372,20 +372,30 @@ trace_screen_resource_from_handle(struct pipe_screen *_screen,
 
    /* TODO trace call */
 
    result = screen->resource_from_handle(screen, templ, handle, usage);
 
    if (result)
       result->screen = _screen;
    return result;
 }
 
+static bool
+trace_screen_check_resource_capability(struct pipe_screen *_screen,
+                                       struct pipe_resource *resource,
+                                       unsigned bind)
+{
+   struct pipe_screen *screen = trace_screen(_screen)->screen;
+
+   return screen->check_resource_capability(screen, resource, bind);
+}
+
 static boolean
 trace_screen_resource_get_handle(struct pipe_screen *_screen,
                                  struct pipe_context *_pipe,
                                 struct pipe_resource *resource,
                                 struct winsys_handle *handle,
                                  unsigned usage)
 {
    struct trace_screen *tr_screen = trace_screen(_screen);
    struct trace_context *tr_pipe = _pipe ? trace_context(_pipe) : NULL;
    struct pipe_screen *screen = tr_screen->screen;
@@ -629,20 +639,21 @@ trace_screen_create(struct pipe_screen *screen)
    SCR_INIT(get_disk_shader_cache);
    tr_scr->base.get_param = trace_screen_get_param;
    tr_scr->base.get_shader_param = trace_screen_get_shader_param;
    tr_scr->base.get_paramf = trace_screen_get_paramf;
    tr_scr->base.get_compute_param = trace_screen_get_compute_param;
    tr_scr->base.is_format_supported = trace_screen_is_format_supported;
    assert(screen->context_create);
    tr_scr->base.context_create = trace_screen_context_create;
    tr_scr->base.resource_create = trace_screen_resource_create;
    tr_scr->base.resource_from_handle = trace_screen_resource_from_handle;
+   SCR_INIT(check_resource_capability);
    tr_scr->base.resource_get_handle = trace_screen_resource_get_handle;
    SCR_INIT(resource_from_memobj);
    SCR_INIT(resource_changed);
    tr_scr->base.resource_destroy = trace_screen_resource_destroy;
    tr_scr->base.fence_reference = trace_screen_fence_reference;
    tr_scr->base.fence_finish = trace_screen_fence_finish;
    SCR_INIT(memobj_create_from_handle);
    SCR_INIT(memobj_destroy);
    tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer;
    tr_scr->base.get_timestamp = trace_screen_get_timestamp;
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
index 8c6028a..c249c7d 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -198,20 +198,37 @@ struct pipe_screen {
 
    /**
     * Create a resource from user memory. This maps the user memory into
     * the device address space.
     */
    struct pipe_resource * (*resource_from_user_memory)(struct pipe_screen *,
                                                        const struct pipe_resource *t,
                                                        void *user_memory);
 
    /**
+    * Unlike pipe_resource::bind, which describes what state trackers want,
+    * resources can have much greater capabilities in practice, often implied
+    * by the tiling layout or memory placement. This function allows querying
+    * whether a capability is supported beyond what was requested by state
+    * trackers. It's also useful for querying capabilities of imported
+    * resources where the capabilities are unknown at first.
+    *
+    * Only these flags are allowed:
+    * - PIPE_BIND_SCANOUT
+    * - PIPE_BIND_CURSOR
+    * - PIPE_BIND_LINEAR
+    */
+   bool (*check_resource_capability)(struct pipe_screen *screen,
+                                     struct pipe_resource *resource,
+                                     unsigned bind);
+
+   /**
     * Get a winsys_handle from a texture. Some platforms/winsys requires
     * that the texture is created with a special usage flag like
     * DISPLAYTARGET or PRIMARY.
     *
     * The context parameter can optionally be used to flush the resource and
     * the context to make sure the resource is coherent with whatever user
     * will use it. Some drivers may also use the context to convert
     * the resource into a format compatible for sharing. The use case is
     * OpenGL-OpenCL interop. The context parameter is allowed to be NULL.
     *
-- 
2.7.4



More information about the mesa-dev mailing list