4 #include "pipe/p_context.h"
5 #include "pipe/p_state.h"
6 #include "util/format/u_format.h"
7 #include "util/os_file.h"
8 #include "util/u_memory.h"
9 #include "util/u_inlines.h"
10 #include "util/u_hash_table.h"
11 #include "util/u_pointer.h"
12 #include "os/os_thread.h"
14 #include "nouveau_drm_public.h"
16 #include "nouveau/nouveau_winsys.h"
17 #include "nouveau/nouveau_screen.h"
19 #include <nvif/class.h>
20 #include <nvif/cl0080.h>
22 static struct hash_table
*fd_tab
= NULL
;
24 static mtx_t nouveau_screen_mutex
= _MTX_INITIALIZER_NP
;
26 bool nouveau_drm_screen_unref(struct nouveau_screen
*screen
)
29 if (screen
->refcount
== -1)
32 mtx_lock(&nouveau_screen_mutex
);
33 ret
= --screen
->refcount
;
36 _mesa_hash_table_remove_key(fd_tab
, intptr_to_pointer(screen
->drm
->fd
));
37 mtx_unlock(&nouveau_screen_mutex
);
41 PUBLIC
struct pipe_screen
*
42 nouveau_drm_screen_create(int fd
)
44 struct nouveau_drm
*drm
= NULL
;
45 struct nouveau_device
*dev
= NULL
;
46 struct nouveau_screen
*(*init
)(struct nouveau_device
*);
47 struct nouveau_screen
*screen
= NULL
;
50 mtx_lock(&nouveau_screen_mutex
);
52 fd_tab
= util_hash_table_create_fd_keys();
54 mtx_unlock(&nouveau_screen_mutex
);
59 screen
= util_hash_table_get(fd_tab
, intptr_to_pointer(fd
));
62 mtx_unlock(&nouveau_screen_mutex
);
66 /* Since the screen re-use is based on the device node and not the fd,
67 * create a copy of the fd to be owned by the device. Otherwise a
68 * scenario could occur where two screens are created, and the first
69 * one is shut down, along with the fd being closed. The second
70 * (identical) screen would now have a reference to the closed fd. We
71 * avoid this by duplicating the original fd. Note that
72 * nouveau_device_wrap does not close the fd in case of a device
75 dupfd
= os_dupfd_cloexec(fd
);
77 ret
= nouveau_drm_new(dupfd
, &drm
);
81 ret
= nouveau_device_new(&drm
->client
, NV_DEVICE
,
82 &(struct nv_device_v0
) {
84 }, sizeof(struct nv_device_v0
), &dev
);
88 switch (dev
->chipset
& ~0xf) {
92 init
= nv30_screen_create
;
98 init
= nv50_screen_create
;
110 init
= nvc0_screen_create
;
113 debug_printf("%s: unknown chipset nv%02x\n", __func__
,
119 if (!screen
|| !screen
->base
.context_create
)
122 /* Use dupfd in hash table, to avoid errors if the original fd gets
123 * closed by its owner. The hash key needs to live at least as long as
126 _mesa_hash_table_insert(fd_tab
, intptr_to_pointer(dupfd
), screen
);
127 screen
->refcount
= 1;
128 mtx_unlock(&nouveau_screen_mutex
);
129 return &screen
->base
;
133 screen
->base
.destroy(&screen
->base
);
135 nouveau_device_del(&dev
);
136 nouveau_drm_del(&drm
);
139 mtx_unlock(&nouveau_screen_mutex
);