mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 11:00:11 +01:00
gallium: move etnaviv screen_lookup_or_create function to common code
Signed-off-by: Eric Engestrom <eric@igalia.com> Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20180>
This commit is contained in:
parent
1dea6aea20
commit
013f05872c
6 changed files with 165 additions and 131 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue