3 #include "pipe/p_context.h"
4 #include "pipe/p_state.h"
5 #include "util/u_format.h"
6 #include "util/u_memory.h"
7 #include "util/u_inlines.h"
8 #include "util/u_hash_table.h"
9 #include "os/os_thread.h"
11 #include "nouveau_drm_public.h"
13 #include "nouveau/nouveau_winsys.h"
14 #include "nouveau/nouveau_screen.h"
16 #include <nvif/class.h>
17 #include <nvif/cl0080.h>
19 static struct util_hash_table
*fd_tab
= NULL
;
21 pipe_static_mutex(nouveau_screen_mutex
);
23 bool nouveau_drm_screen_unref(struct nouveau_screen
*screen
)
26 if (screen
->refcount
== -1)
29 pipe_mutex_lock(nouveau_screen_mutex
);
30 ret
= --screen
->refcount
;
33 util_hash_table_remove(fd_tab
, intptr_to_pointer(screen
->drm
->fd
));
34 pipe_mutex_unlock(nouveau_screen_mutex
);
38 static unsigned hash_fd(void *key
)
40 int fd
= pointer_to_intptr(key
);
44 return stat
.st_dev
^ stat
.st_ino
^ stat
.st_rdev
;
47 static int compare_fd(void *key1
, void *key2
)
49 int fd1
= pointer_to_intptr(key1
);
50 int fd2
= pointer_to_intptr(key2
);
51 struct stat stat1
, stat2
;
55 return stat1
.st_dev
!= stat2
.st_dev
||
56 stat1
.st_ino
!= stat2
.st_ino
||
57 stat1
.st_rdev
!= stat2
.st_rdev
;
60 PUBLIC
struct pipe_screen
*
61 nouveau_drm_screen_create(int fd
)
63 struct nouveau_drm
*drm
= NULL
;
64 struct nouveau_device
*dev
= NULL
;
65 struct nouveau_screen
*(*init
)(struct nouveau_device
*);
66 struct nouveau_screen
*screen
= NULL
;
69 pipe_mutex_lock(nouveau_screen_mutex
);
71 fd_tab
= util_hash_table_create(hash_fd
, compare_fd
);
73 pipe_mutex_unlock(nouveau_screen_mutex
);
78 screen
= util_hash_table_get(fd_tab
, intptr_to_pointer(fd
));
81 pipe_mutex_unlock(nouveau_screen_mutex
);
85 /* Since the screen re-use is based on the device node and not the fd,
86 * create a copy of the fd to be owned by the device. Otherwise a
87 * scenario could occur where two screens are created, and the first
88 * one is shut down, along with the fd being closed. The second
89 * (identical) screen would now have a reference to the closed fd. We
90 * avoid this by duplicating the original fd. Note that
91 * nouveau_device_wrap does not close the fd in case of a device
96 ret
= nouveau_drm_new(dupfd
, &drm
);
100 ret
= nouveau_device_new(&drm
->client
, NV_DEVICE
,
101 &(struct nv_device_v0
) {
103 }, sizeof(struct nv_device_v0
), &dev
);
107 switch (dev
->chipset
& ~0xf) {
111 init
= nv30_screen_create
;
117 init
= nv50_screen_create
;
125 init
= nvc0_screen_create
;
128 debug_printf("%s: unknown chipset nv%02x\n", __func__
,
134 if (!screen
|| !screen
->base
.context_create
)
137 /* Use dupfd in hash table, to avoid errors if the original fd gets
138 * closed by its owner. The hash key needs to live at least as long as
141 util_hash_table_set(fd_tab
, intptr_to_pointer(dupfd
), screen
);
142 screen
->refcount
= 1;
143 pipe_mutex_unlock(nouveau_screen_mutex
);
144 return &screen
->base
;
148 screen
->base
.destroy(&screen
->base
);
150 nouveau_device_del(&dev
);
151 nouveau_drm_del(&drm
);
154 pipe_mutex_unlock(nouveau_screen_mutex
);