mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-02 14:28:05 +02:00
nouveau: create only 1 shared screen between vdpau and opengl
This fixes bug 73200 "vdpau-GL interop fails due to different screen objects" in the same way radeon does. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
This commit is contained in:
parent
572a8345bf
commit
fee0686c21
8 changed files with 100 additions and 4 deletions
|
|
@ -144,6 +144,12 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
|
|||
if (nv_dbg)
|
||||
nouveau_mesa_debug = atoi(nv_dbg);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (dev->chipset < 0xc0) {
|
||||
data = &nv04_data;
|
||||
size = sizeof(nv04_data);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ struct nouveau_screen {
|
|||
struct nouveau_client *client;
|
||||
struct nouveau_pushbuf *pushbuf;
|
||||
|
||||
int refcount;
|
||||
|
||||
unsigned vidmem_bindings; /* PIPE_BIND_* where VRAM placement is desired */
|
||||
unsigned sysmem_bindings; /* PIPE_BIND_* where GART placement is desired */
|
||||
unsigned lowmem_bindings; /* PIPE_BIND_* that require an address < 4 GiB */
|
||||
|
|
@ -112,6 +114,8 @@ nouveau_screen(struct pipe_screen *pscreen)
|
|||
return (struct nouveau_screen *)pscreen;
|
||||
}
|
||||
|
||||
boolean nouveau_drm_screen_unref(struct nouveau_screen *screen);
|
||||
|
||||
boolean
|
||||
nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,
|
||||
struct nouveau_bo *bo,
|
||||
|
|
|
|||
|
|
@ -302,6 +302,9 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
|
|||
{
|
||||
struct nv30_screen *screen = nv30_screen(pscreen);
|
||||
|
||||
if (!nouveau_drm_screen_unref(&screen->base))
|
||||
return;
|
||||
|
||||
if (screen->base.fence.current &&
|
||||
screen->base.fence.current->state >= NOUVEAU_FENCE_STATE_EMITTED) {
|
||||
nouveau_fence_wait(screen->base.fence.current);
|
||||
|
|
|
|||
|
|
@ -287,6 +287,9 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
|
|||
{
|
||||
struct nv50_screen *screen = nv50_screen(pscreen);
|
||||
|
||||
if (!nouveau_drm_screen_unref(&screen->base))
|
||||
return;
|
||||
|
||||
if (screen->base.fence.current) {
|
||||
nouveau_fence_wait(screen->base.fence.current);
|
||||
nouveau_fence_ref (NULL, &screen->base.fence.current);
|
||||
|
|
|
|||
|
|
@ -333,6 +333,9 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
|
|||
{
|
||||
struct nvc0_screen *screen = nvc0_screen(pscreen);
|
||||
|
||||
if (!nouveau_drm_screen_unref(&screen->base))
|
||||
return;
|
||||
|
||||
if (screen->base.fence.current) {
|
||||
nouveau_fence_wait(screen->base.fence.current);
|
||||
nouveau_fence_ref(NULL, &screen->base.fence.current);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
DRI_VERSION_SCRIPT = $(srcdir)/nouveau_dri.link
|
||||
include $(top_srcdir)/src/gallium/Automake.inc
|
||||
|
||||
AM_CFLAGS = \
|
||||
|
|
|
|||
6
src/gallium/targets/dri-nouveau/nouveau_dri.link
Normal file
6
src/gallium/targets/dri-nouveau/nouveau_dri.link
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
VERSION {
|
||||
global:
|
||||
__driDriverExtensions;
|
||||
nouveau_drm_screen_create;
|
||||
local: *;
|
||||
};
|
||||
|
|
@ -1,24 +1,83 @@
|
|||
#include <sys/stat.h>
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_hash_table.h"
|
||||
#include "os/os_thread.h"
|
||||
|
||||
#include "nouveau_drm_public.h"
|
||||
|
||||
#include "nouveau/nouveau_winsys.h"
|
||||
#include "nouveau/nouveau_screen.h"
|
||||
|
||||
struct pipe_screen *
|
||||
static struct util_hash_table *fd_tab = NULL;
|
||||
|
||||
pipe_static_mutex(nouveau_screen_mutex);
|
||||
|
||||
boolean nouveau_drm_screen_unref(struct nouveau_screen *screen)
|
||||
{
|
||||
int ret;
|
||||
if (screen->refcount == -1)
|
||||
return true;
|
||||
|
||||
pipe_mutex_lock(nouveau_screen_mutex);
|
||||
ret = --screen->refcount;
|
||||
assert(ret >= 0);
|
||||
if (ret == 0)
|
||||
util_hash_table_remove(fd_tab, intptr_to_pointer(screen->device->fd));
|
||||
pipe_mutex_unlock(nouveau_screen_mutex);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static unsigned hash_fd(void *key)
|
||||
{
|
||||
int fd = pointer_to_intptr(key);
|
||||
struct stat stat;
|
||||
fstat(fd, &stat);
|
||||
|
||||
return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
|
||||
}
|
||||
|
||||
static int compare_fd(void *key1, void *key2)
|
||||
{
|
||||
int fd1 = pointer_to_intptr(key1);
|
||||
int fd2 = pointer_to_intptr(key2);
|
||||
struct stat stat1, stat2;
|
||||
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;
|
||||
}
|
||||
|
||||
PUBLIC struct pipe_screen *
|
||||
nouveau_drm_screen_create(int fd)
|
||||
{
|
||||
struct nouveau_device *dev = NULL;
|
||||
struct pipe_screen *(*init)(struct nouveau_device *);
|
||||
struct nouveau_screen *screen;
|
||||
int ret;
|
||||
|
||||
pipe_mutex_lock(nouveau_screen_mutex);
|
||||
if (!fd_tab) {
|
||||
fd_tab = util_hash_table_create(hash_fd, compare_fd);
|
||||
if (!fd_tab)
|
||||
goto err;
|
||||
}
|
||||
|
||||
screen = util_hash_table_get(fd_tab, intptr_to_pointer(fd));
|
||||
if (screen) {
|
||||
screen->refcount++;
|
||||
pipe_mutex_unlock(nouveau_screen_mutex);
|
||||
return &screen->base;
|
||||
}
|
||||
|
||||
ret = nouveau_device_wrap(fd, 0, &dev);
|
||||
if (ret)
|
||||
return NULL;
|
||||
goto err;
|
||||
|
||||
switch (dev->chipset & ~0xf) {
|
||||
case 0x30:
|
||||
|
|
@ -42,8 +101,19 @@ nouveau_drm_screen_create(int fd)
|
|||
default:
|
||||
debug_printf("%s: unknown chipset nv%02x\n", __func__,
|
||||
dev->chipset);
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return init(dev);
|
||||
screen = (struct nouveau_screen*)init(dev);
|
||||
if (!screen)
|
||||
goto err;
|
||||
|
||||
util_hash_table_set(fd_tab, intptr_to_pointer(fd), screen);
|
||||
screen->refcount = 1;
|
||||
pipe_mutex_unlock(nouveau_screen_mutex);
|
||||
return &screen->base;
|
||||
|
||||
err:
|
||||
pipe_mutex_unlock(nouveau_screen_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue