Module: Mesa
Branch: main
Commit: 013f05872c81ba2ac98b03fa4b8711e1b95b64b6
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=013f05872c81ba2ac98b03fa4b8711e1b95b64b6

Author: Eric Engestrom <[email protected]>
Date:   Fri Dec  9 20:52:15 2022 +0000

gallium: move etnaviv screen_lookup_or_create function to common code

Signed-off-by: Eric Engestrom <[email protected]>
Acked-by: Alyssa Rosenzweig <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20180>

---

 src/gallium/auxiliary/util/u_screen.c              | 132 +++++++++++++++++++++
 src/gallium/auxiliary/util/u_screen.h              |  11 ++
 src/gallium/drivers/etnaviv/etnaviv_screen.c       |   9 +-
 src/gallium/drivers/etnaviv/etnaviv_screen.h       |   3 -
 src/gallium/include/pipe/p_screen.h                |  10 ++
 .../winsys/etnaviv/drm/etnaviv_drm_winsys.c        | 131 +-------------------
 6 files changed, 165 insertions(+), 131 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_screen.c 
b/src/gallium/auxiliary/util/u_screen.c
index c66bf9c9b70..235b544f5a3 100644
--- a/src/gallium/auxiliary/util/u_screen.c
+++ b/src/gallium/auxiliary/util/u_screen.c
@@ -21,10 +21,16 @@
  * IN THE SOFTWARE.
  */
 
+#include <sys/stat.h>
+
 #include "pipe/p_screen.h"
 #include "util/u_screen.h"
 #include "util/u_debug.h"
+#include "util/os_file.h"
 #include "util/os_time.h"
+#include "util/simple_mtx.h"
+#include "util/u_hash_table.h"
+#include "util/u_pointer.h"
 
 /**
  * Helper to use from a pipe_screen->get_param() implementation to return
@@ -536,3 +542,129 @@ uint64_t u_default_get_timestamp(UNUSED struct 
pipe_screen *screen)
 {
    return os_time_get_nano();
 }
+
+static uint32_t
+hash_file_description(const void *key)
+{
+   int fd = pointer_to_intptr(key);
+   struct stat stat;
+
+   // File descriptions can't be hashed, but it should be safe to assume
+   // that the same file description will always refer to he same file
+   if (fstat(fd, &stat) == -1)
+      return ~0; // Make sure fstat failing won't result in a random hash
+
+   return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
+}
+
+
+static bool
+equal_file_description(const void *key1, const void *key2)
+{
+   int ret;
+   int fd1 = pointer_to_intptr(key1);
+   int fd2 = pointer_to_intptr(key2);
+   struct stat stat1, stat2;
+
+   // If the file descriptors are the same, the file description will be too
+   // This will also catch sentinels, such as -1
+   if (fd1 == fd2)
+      return true;
+
+   ret = os_same_file_description(fd1, fd2);
+   if (ret >= 0)
+      return (ret == 0);
+
+   {
+      static bool has_warned;
+      if (!has_warned)
+         fprintf(stderr, "os_same_file_description couldn't determine if "
+                 "two DRM fds reference the same file description. (%s)\n"
+                 "Let's just assume that file descriptors for the same file 
probably"
+                 "share the file description instead. This may cause problems 
when"
+                 "that isn't the case.\n", strerror(errno));
+      has_warned = true;
+   }
+
+   // Let's at least check that it's the same file, different files can't
+   // have the same file descriptions
+   fstat(fd1, &stat1);
+   fstat(fd2, &stat2);
+
+   return stat1.st_dev == stat2.st_dev &&
+          stat1.st_ino == stat2.st_ino &&
+          stat1.st_rdev == stat2.st_rdev;
+}
+
+
+static struct hash_table *
+hash_table_create_file_description_keys(void)
+{
+   return _mesa_hash_table_create(NULL, hash_file_description, 
equal_file_description);
+}
+
+static struct hash_table *fd_tab = NULL;
+
+static simple_mtx_t screen_mutex = SIMPLE_MTX_INITIALIZER;
+
+static void
+drm_screen_destroy(struct pipe_screen *pscreen)
+{
+   boolean destroy;
+
+   simple_mtx_lock(&screen_mutex);
+   destroy = --pscreen->refcnt == 0;
+   if (destroy) {
+      int fd = pscreen->get_screen_fd(pscreen);
+      _mesa_hash_table_remove_key(fd_tab, intptr_to_pointer(fd));
+
+      if (!fd_tab->entries) {
+         _mesa_hash_table_destroy(fd_tab, NULL);
+         fd_tab = NULL;
+      }
+   }
+   simple_mtx_unlock(&screen_mutex);
+
+   if (destroy) {
+      pscreen->destroy = pscreen->winsys_priv;
+      pscreen->destroy(pscreen);
+   }
+}
+
+struct pipe_screen *
+u_pipe_screen_lookup_or_create(int gpu_fd,
+                               const struct pipe_screen_config *config,
+                               struct renderonly *ro,
+                               pipe_screen_create_function screen_create)
+{
+   struct pipe_screen *pscreen = NULL;
+
+   simple_mtx_lock(&screen_mutex);
+   if (!fd_tab) {
+      fd_tab = hash_table_create_file_description_keys();
+      if (!fd_tab)
+         goto unlock;
+   }
+
+   pscreen = util_hash_table_get(fd_tab, intptr_to_pointer(gpu_fd));
+   if (pscreen) {
+      pscreen->refcnt++;
+   } else {
+      pscreen = screen_create(gpu_fd, config, ro);
+      if (pscreen) {
+         pscreen->refcnt = 1;
+         int fd = pscreen->get_screen_fd(pscreen);
+         _mesa_hash_table_insert(fd_tab, intptr_to_pointer(fd), pscreen);
+
+         /* Bit of a hack, to avoid circular linkage dependency,
+          * ie. pipe driver having to call in to winsys, we
+          * override the pipe drivers screen->destroy() */
+         pscreen->winsys_priv = pscreen->destroy;
+         pscreen->destroy = drm_screen_destroy;
+      }
+   }
+
+unlock:
+   simple_mtx_unlock(&screen_mutex);
+   return pscreen;
+}
diff --git a/src/gallium/auxiliary/util/u_screen.h 
b/src/gallium/auxiliary/util/u_screen.h
index 22b2f378bbd..04f41c1dd18 100644
--- a/src/gallium/auxiliary/util/u_screen.h
+++ b/src/gallium/auxiliary/util/u_screen.h
@@ -24,6 +24,8 @@
 #include <stdint.h>
 
 struct pipe_screen;
+struct pipe_screen_config;
+struct renderonly;
 enum pipe_cap;
 
 #ifdef __cplusplus
@@ -36,6 +38,15 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen,
 
 uint64_t u_default_get_timestamp(struct pipe_screen *screen);
 
+typedef struct pipe_screen * (*pipe_screen_create_function)
+   (int fd, const struct pipe_screen_config *config, struct renderonly *ro);
+
+struct pipe_screen *
+u_pipe_screen_lookup_or_create(int fd,
+                               const struct pipe_screen_config *config,
+                               struct renderonly *ro,
+                               pipe_screen_create_function screen_create);
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c 
b/src/gallium/drivers/etnaviv/etnaviv_screen.c
index 2512194e26e..c811f08b3cb 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
@@ -1076,6 +1076,13 @@ etna_get_disk_shader_cache(struct pipe_screen *pscreen)
    return compiler->disk_cache;
 }
 
+static int
+etna_screen_get_fd(struct pipe_screen *pscreen)
+{
+   struct etna_screen *screen = etna_screen(pscreen);
+   return etna_device_fd(screen->dev);
+}
+
 struct pipe_screen *
 etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu,
                    struct renderonly *ro)
@@ -1091,7 +1098,6 @@ etna_screen_create(struct etna_device *dev, struct 
etna_gpu *gpu,
    screen->dev = dev;
    screen->gpu = gpu;
    screen->ro = ro;
-   screen->refcnt = 1;
 
    screen->drm_version = etnaviv_device_version(screen->dev);
    etna_mesa_debug = debug_get_option_etna_mesa_debug();
@@ -1218,6 +1224,7 @@ etna_screen_create(struct etna_device *dev, struct 
etna_gpu *gpu,
       screen->features[viv_chipMinorFeatures2] &= 
~chipMinorFeatures2_LINEAR_PE;
 
    pscreen->destroy = etna_screen_destroy;
+   pscreen->get_screen_fd = etna_screen_get_fd;
    pscreen->get_param = etna_screen_get_param;
    pscreen->get_paramf = etna_screen_get_paramf;
    pscreen->get_shader_param = etna_screen_get_shader_param;
diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.h 
b/src/gallium/drivers/etnaviv/etnaviv_screen.h
index c9f7af50f60..c664218d8e6 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.h
@@ -72,9 +72,6 @@ enum viv_features_word {
 struct etna_screen {
    struct pipe_screen base;
 
-   int refcnt;
-   void *winsys_priv;
-
    struct etna_device *dev;
    struct etna_gpu *gpu;
    struct etna_pipe *pipe;
diff --git a/src/gallium/include/pipe/p_screen.h 
b/src/gallium/include/pipe/p_screen.h
index 3ee2687b9cb..9ee59c91518 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -86,6 +86,16 @@ typedef void (*pipe_driver_thread_func)(void *job, void 
*gdata, int thread_index
  * context.
  */
 struct pipe_screen {
+   int refcnt;
+   void *winsys_priv;
+
+   /**
+    * Get the fd associated with the screen
+    * The fd returned is considered read-only, and in particular will not
+    * be close()d. It must remain valid for as long as the screen exists.
+    */
+   int (*get_screen_fd)(struct pipe_screen *);
+
    /**
     * Atomically incremented by drivers to track the number of contexts.
     * If it's 0, it can be assumed that contexts are not tracked.
diff --git a/src/gallium/winsys/etnaviv/drm/etnaviv_drm_winsys.c 
b/src/gallium/winsys/etnaviv/drm/etnaviv_drm_winsys.c
index e69380eb4cb..c9145348c0d 100644
--- a/src/gallium/winsys/etnaviv/drm/etnaviv_drm_winsys.c
+++ b/src/gallium/winsys/etnaviv/drm/etnaviv_drm_winsys.c
@@ -26,10 +26,7 @@
 
 #include <sys/stat.h>
 
-#include "util/os_file.h"
-#include "util/simple_mtx.h"
-#include "util/u_hash_table.h"
-#include "util/u_pointer.h"
+#include "util/u_screen.h"
 
 #include "etnaviv/etnaviv_screen.h"
 #include "etnaviv/hw/common.xml.h"
@@ -37,66 +34,9 @@
 
 #include <stdio.h>
 
-static uint32_t hash_file_description(const void *key)
-{
-   int fd = pointer_to_intptr(key);
-   struct stat stat;
-
-   // File descriptions can't be hashed, but it should be safe to assume
-   // that the same file description will always refer to he same file
-   if(fstat(fd, &stat) == -1)
-      return ~0; // Make sure fstat failing won't result in a random hash
-
-   return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
-}
-
-
-static bool equal_file_description(const void *key1, const void *key2)
-{
-   int ret;
-   int fd1 = pointer_to_intptr(key1);
-   int fd2 = pointer_to_intptr(key2);
-   struct stat stat1, stat2;
-
-   // If the file descriptors are the same, the file description will be too
-   // This will also catch sentinels, such as -1
-   if (fd1 == fd2)
-      return true;
-
-   ret = os_same_file_description(fd1, fd2);
-   if (ret >= 0)
-      return (ret == 0);
-
-   {
-      static bool has_warned;
-      if (!has_warned)
-         fprintf(stderr, "os_same_file_description couldn't determine if "
-                 "two DRM fds reference the same file description. (%s)\n"
-                 "Let's just assume that file descriptors for the same file 
probably"
-                 "share the file description instead. This may cause problems 
when"
-                 "that isn't the case.\n", strerror(errno));
-      has_warned = true;
-   }
-
-   // Let's at least check that it's the same file, different files can't
-   // have the same file descriptions
-   fstat(fd1, &stat1);
-   fstat(fd2, &stat2);
-
-   return stat1.st_dev == stat2.st_dev &&
-          stat1.st_ino == stat2.st_ino &&
-          stat1.st_rdev == stat2.st_rdev;
-}
-
-
-static struct hash_table *
-hash_table_create_file_description_keys(void)
-{
-   return _mesa_hash_table_create(NULL, hash_file_description, 
equal_file_description);
-}
 
 static struct pipe_screen *
-screen_create(int gpu_fd, struct renderonly *ro)
+screen_create(int gpu_fd, const struct pipe_screen_config *config, struct 
renderonly *ro)
 {
    struct etna_device *dev;
    struct etna_gpu *gpu;
@@ -127,77 +67,14 @@ screen_create(int gpu_fd, struct renderonly *ro)
    return etna_screen_create(dev, gpu, ro);
 }
 
-static struct hash_table *fd_tab = NULL;
-
-static simple_mtx_t etna_screen_mutex = SIMPLE_MTX_INITIALIZER;
-
-static void
-etna_drm_screen_destroy(struct pipe_screen *pscreen)
-{
-   struct etna_screen *screen = etna_screen(pscreen);
-   boolean destroy;
-
-   simple_mtx_lock(&etna_screen_mutex);
-   destroy = --screen->refcnt == 0;
-   if (destroy) {
-      int fd = etna_device_fd(screen->dev);
-      _mesa_hash_table_remove_key(fd_tab, intptr_to_pointer(fd));
-
-      if (!fd_tab->entries) {
-         _mesa_hash_table_destroy(fd_tab, NULL);
-         fd_tab = NULL;
-      }
-   }
-   simple_mtx_unlock(&etna_screen_mutex);
-
-   if (destroy) {
-      pscreen->destroy = screen->winsys_priv;
-      pscreen->destroy(pscreen);
-   }
-}
-
-static struct pipe_screen *
-etna_lookup_or_create_screen(int gpu_fd, struct renderonly *ro)
-{
-   struct pipe_screen *pscreen = NULL;
-
-   simple_mtx_lock(&etna_screen_mutex);
-   if (!fd_tab) {
-      fd_tab = hash_table_create_file_description_keys();
-      if (!fd_tab)
-         goto unlock;
-   }
-
-   pscreen = util_hash_table_get(fd_tab, intptr_to_pointer(gpu_fd));
-   if (pscreen) {
-      etna_screen(pscreen)->refcnt++;
-   } else {
-      pscreen = screen_create(gpu_fd, ro);
-      if (pscreen) {
-         int fd = etna_device_fd(etna_screen(pscreen)->dev);
-         _mesa_hash_table_insert(fd_tab, intptr_to_pointer(fd), pscreen);
-
-         /* Bit of a hack, to avoid circular linkage dependency,
-         * ie. pipe driver having to call in to winsys, we
-         * override the pipe drivers screen->destroy() */
-         etna_screen(pscreen)->winsys_priv = pscreen->destroy;
-         pscreen->destroy = etna_drm_screen_destroy;
-      }
-   }
-
-unlock:
-   simple_mtx_unlock(&etna_screen_mutex);
-   return pscreen;
-}
-
 struct pipe_screen *
 etna_drm_screen_create_renderonly(struct renderonly *ro)
 {
-   return etna_lookup_or_create_screen(ro->gpu_fd, ro);
+   return u_pipe_screen_lookup_or_create(ro->gpu_fd, NULL, ro, screen_create);
 }
 
 struct pipe_screen *
 etna_drm_screen_create(int fd)
 {
-   return etna_lookup_or_create_screen(fd, NULL);
+   return u_pipe_screen_lookup_or_create(fd, NULL, NULL, screen_create);
 }

Reply via email to