winsys/nouveau: Rework to use u_pipe_screen_lookup_or_create

All the boilerplate can be removed to use u_pipe_screen_lookup_or_create
instead.

Signed-off-by: Mary Guillemard <mary@mary.zone>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31667>
This commit is contained in:
Mary Guillemard
2024-10-15 23:16:31 +02:00
parent 019770f026
commit f9e72b7fcb
7 changed files with 41 additions and 96 deletions
+1 -6
View File
@@ -317,12 +317,7 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
*/
screen->drm = nouveau_drm(&dev->object);
screen->device = dev;
/*
* this is initialized to 1 in nouveau_drm_screen_create after screen
* is fully constructed and added to the global screen list.
*/
screen->refcount = -1;
screen->initialized = false;
if (dev->chipset < 0xc0) {
data = &nv04_data;
+1 -3
View File
@@ -32,7 +32,7 @@ struct nouveau_screen {
char chipset_name[8];
int refcount;
bool initialized;
unsigned transfer_pushbuf_threshold;
@@ -137,8 +137,6 @@ nouveau_screen(struct pipe_screen *pscreen)
return (struct nouveau_screen *)pscreen;
}
bool nouveau_drm_screen_unref(struct nouveau_screen *screen);
bool
nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,
struct nouveau_bo *bo,
@@ -534,7 +534,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
{
struct nv30_screen *screen = nv30_screen(pscreen);
if (!nouveau_drm_screen_unref(&screen->base))
if (!screen->base.initialized)
return;
nouveau_bo_ref(NULL, &screen->notify);
@@ -472,7 +472,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
{
struct nv50_screen *screen = nv50_screen(pscreen);
if (!nouveau_drm_screen_unref(&screen->base))
if (!screen->base.initialized)
return;
if (screen->blitter)
@@ -608,7 +608,7 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
{
struct nvc0_screen *screen = nvc0_screen(pscreen);
if (!nouveau_drm_screen_unref(&screen->base))
if (!screen->base.initialized)
return;
if (screen->blitter)
@@ -3,6 +3,8 @@
#define __NOUVEAU_DRM_PUBLIC_H__
struct pipe_screen;
struct pipe_screen_config;
struct renderonly;
struct pipe_screen *nouveau_drm_screen_create(int drmFD);
@@ -1,87 +1,34 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/format/u_format.h"
#include "util/os_file.h"
#include "util/simple_mtx.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_hash_table.h"
#include "util/u_pointer.h"
#include "util/u_thread.h"
#include "util/u_screen.h"
#include "renderonly/renderonly.h"
#include "nouveau_drm_public.h"
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_screen.h"
#include "nvif/class.h"
#include "nvif/cl0080.h"
static struct hash_table *fd_tab = NULL;
static simple_mtx_t nouveau_screen_mutex = SIMPLE_MTX_INITIALIZER;
bool nouveau_drm_screen_unref(struct nouveau_screen *screen)
{
int ret;
if (screen->refcount == -1)
return true;
simple_mtx_lock(&nouveau_screen_mutex);
ret = --screen->refcount;
assert(ret >= 0);
if (ret == 0)
_mesa_hash_table_remove_key(fd_tab, intptr_to_pointer(screen->drm->fd));
simple_mtx_unlock(&nouveau_screen_mutex);
return ret == 0;
}
PUBLIC struct pipe_screen *
nouveau_drm_screen_create(int fd)
static struct pipe_screen *
nouveau_screen_create(int fd, const struct pipe_screen_config *config,
struct renderonly *ro)
{
struct nouveau_drm *drm = NULL;
struct nouveau_device *dev = NULL;
struct nouveau_screen *(*init)(struct nouveau_device *);
struct nouveau_screen *screen = NULL;
int ret, dupfd;
int ret;
simple_mtx_lock(&nouveau_screen_mutex);
if (!fd_tab) {
fd_tab = util_hash_table_create_fd_keys();
if (!fd_tab) {
simple_mtx_unlock(&nouveau_screen_mutex);
return NULL;
}
}
screen = util_hash_table_get(fd_tab, intptr_to_pointer(fd));
if (screen) {
screen->refcount++;
simple_mtx_unlock(&nouveau_screen_mutex);
return &screen->base;
}
/* Since the screen re-use is based on the device node and not the fd,
* create a copy of the fd to be owned by the device. Otherwise a
* scenario could occur where two screens are created, and the first
* one is shut down, along with the fd being closed. The second
* (identical) screen would now have a reference to the closed fd. We
* avoid this by duplicating the original fd. Note that
* nouveau_device_wrap does not close the fd in case of a device
* creation error.
*/
dupfd = os_dupfd_cloexec(fd);
ret = nouveau_drm_new(dupfd, &drm);
ret = nouveau_drm_new(fd, &drm);
if (ret)
goto err;
return NULL;
ret = nouveau_device_new(&drm->client, &dev);
if (ret)
goto err;
goto err_dev_new;
switch (dev->chipset & ~0xf) {
case 0x30:
@@ -111,31 +58,34 @@ nouveau_drm_screen_create(int fd)
break;
default:
debug_printf("%s: unknown chipset nv%02x\n", __func__,
dev->chipset);
goto err;
dev->chipset);
goto err_screen_create;
}
screen = init(dev);
if (!screen || !screen->base.context_create)
goto err;
if (!screen)
goto err_screen_create;
/* Use dupfd in hash table, to avoid errors if the original fd gets
* closed by its owner. The hash key needs to live at least as long as
* the screen.
*/
_mesa_hash_table_insert(fd_tab, intptr_to_pointer(dupfd), screen);
screen->refcount = 1;
simple_mtx_unlock(&nouveau_screen_mutex);
if (!screen->base.context_create)
goto err_screen_init;
screen->initialized = true;
return &screen->base;
err:
if (screen) {
screen->base.destroy(&screen->base);
} else {
nouveau_device_del(&dev);
nouveau_drm_del(&drm);
close(dupfd);
}
simple_mtx_unlock(&nouveau_screen_mutex);
err_screen_init:
screen->base.destroy(&screen->base);
return NULL;
err_screen_create:
nouveau_device_del(&dev);
err_dev_new:
nouveau_drm_del(&drm);
return NULL;
}
PUBLIC struct pipe_screen *
nouveau_drm_screen_create(int fd)
{
return u_pipe_screen_lookup_or_create(os_dupfd_cloexec(fd), NULL, NULL,
nouveau_screen_create);
}