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); }
