virgl: get readback-formats from host
authorErik Faye-Lund <erik.faye-lund@collabora.com>
Fri, 5 Apr 2019 06:13:37 +0000 (08:13 +0200)
committerErik Faye-Lund <erik.faye-lund@collabora.com>
Wed, 17 Apr 2019 07:27:08 +0000 (07:27 +0000)
Signed-off-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
src/gallium/drivers/virgl/virgl_hw.h
src/gallium/drivers/virgl/virgl_screen.c
src/gallium/drivers/virgl/virgl_screen.h

index 949a1f545e7ca2400817d6f21a23a7637673648b..bc6803faa033bc97028c5b6e3ddbdccc8bca48a0 100644 (file)
@@ -371,6 +371,7 @@ struct virgl_caps_v2 {
         uint32_t max_combined_atomic_counters;
         uint32_t max_combined_atomic_counter_buffers;
         uint32_t host_feature_check_version;
+        struct virgl_supported_format_mask supported_readback_formats;
 };
 
 union virgl_caps {
index 66fadddc2629e4b433f64f10373cb64669d48e83..65106dbb6160c819c5b6c1503c97f2481be9a0f5 100644 (file)
@@ -530,6 +530,27 @@ virgl_get_compute_param(struct pipe_screen *screen,
    return 0;
 }
 
+static boolean
+has_format_bit(struct virgl_supported_format_mask *mask,
+               enum virgl_formats fmt)
+{
+   assert(fmt < VIRGL_FORMAT_MAX);
+   unsigned val = (unsigned)fmt;
+   unsigned idx = val / 32;
+   unsigned bit = val % 32;
+   assert(idx < ARRAY_SIZE(mask->bitmask));
+   return (mask->bitmask[val / 32] & (1u << bit)) != 0;
+}
+
+boolean
+virgl_has_readback_format(struct pipe_screen *screen,
+                          enum virgl_formats fmt)
+{
+   struct virgl_screen *vscreen = virgl_screen(screen);
+   return has_format_bit(&vscreen->caps.caps.v2.supported_readback_formats,
+                         fmt);
+}
+
 static boolean
 virgl_is_vertex_format_supported(struct pipe_screen *screen,
                                  enum pipe_format format)
@@ -779,6 +800,24 @@ virgl_destroy_screen(struct pipe_screen *screen)
    FREE(vscreen);
 }
 
+static void
+fixup_readback_format(union virgl_caps *caps)
+{
+   const size_t size = ARRAY_SIZE(caps->v2.supported_readback_formats.bitmask);
+   for (int i = 0; i < size; ++i) {
+      if (caps->v2.supported_readback_formats.bitmask[i] != 0)
+         return; /* we got some formats, we definately have a new protocol */
+   }
+
+   /* old protocol used; fall back to considering all sampleable formats valid
+    * readback-formats
+    */
+   for (int i = 0; i < size; ++i) {
+      caps->v2.supported_readback_formats.bitmask[i] =
+         caps->v1.sampler.bitmask[i];
+   }
+}
+
 struct pipe_screen *
 virgl_create_screen(struct virgl_winsys *vws)
 {
@@ -809,6 +848,7 @@ virgl_create_screen(struct virgl_winsys *vws)
    virgl_init_screen_resource_functions(&screen->base);
 
    vws->get_caps(vws, &screen->caps);
+   fixup_readback_format(&screen->caps.caps);
 
    screen->refcnt = 1;
 
index 97a656fe8eb007828a0c0ad3da04b098c372eba2..0256d471f2234a8405a2044635ca21a70da367de 100644 (file)
@@ -55,6 +55,9 @@ virgl_screen(struct pipe_screen *pipe)
    return (struct virgl_screen *)pipe;
 }
 
+boolean
+virgl_has_readback_format(struct pipe_screen *screen, enum virgl_formats fmt);
+
 #define VIRGL_MAP_BUFFER_ALIGNMENT 64
 
 #endif