summaryrefslogtreecommitdiff
path: root/src/nouveau_sync.c
blob: e39493252bd909b3c4e543f98fafe67472e28d4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright 2013 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs <bskeggs@redhat.com>
 */

#include "nouveau_sync.h"

static DevPrivateKeyRec nouveau_syncobj_key;

struct nouveau_syncobj {
	SyncFenceSetTriggeredFunc SetTriggered;
};

#define nouveau_syncobj(fence)                                                 \
	dixLookupPrivate(&(fence)->devPrivates, &nouveau_syncobj_key)

struct nouveau_syncctx {
	SyncScreenCreateFenceFunc CreateFence;
};

#define nouveau_syncctx(screen) ({                                             \
	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);                           \
	NVPtr pNv = NVPTR(scrn);                                               \
	pNv->sync;                                                             \
})

static void
nouveau_syncobj_flush(SyncFence *fence)
{
	struct nouveau_syncobj *pobj = nouveau_syncobj(fence);
	ScrnInfoPtr scrn = xf86ScreenToScrn(fence->pScreen);
	NVPtr pNv = NVPTR(scrn);
	SyncFenceFuncsPtr func = &fence->funcs;

	nouveau_pushbuf_kick(pNv->pushbuf, pNv->channel);
	if (pNv->ce_pushbuf)
		nouveau_pushbuf_kick(pNv->ce_pushbuf, pNv->ce_channel);

	swap(pobj, func, SetTriggered);
	func->SetTriggered(fence);
	swap(pobj, func, SetTriggered);
}

static void
nouveau_syncobj_new(ScreenPtr screen, SyncFence *fence, Bool triggered)
{
	struct nouveau_syncctx *priv = nouveau_syncctx(screen);
	struct nouveau_syncobj *pobj = nouveau_syncobj(fence);
	SyncScreenFuncsPtr sync = miSyncGetScreenFuncs(screen);
	SyncFenceFuncsPtr func = &fence->funcs;

	swap(priv, sync, CreateFence);
	sync->CreateFence(screen, fence, triggered);
	swap(priv, sync, CreateFence);

	wrap(pobj, func, SetTriggered, nouveau_syncobj_flush);
}

void
nouveau_sync_fini(ScreenPtr screen)
{
	struct nouveau_syncctx *priv = nouveau_syncctx(screen);
	SyncScreenFuncsPtr sync = miSyncGetScreenFuncs(screen);
	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
	NVPtr pNv = NVPTR(scrn);

	unwrap(priv, sync, CreateFence);

	pNv->sync = NULL;
	free(priv);
}

Bool
nouveau_sync_init(ScreenPtr screen)
{
	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
	NVPtr pNv = NVPTR(scrn);
	struct nouveau_syncctx *priv;
	SyncScreenFuncsPtr sync;

	priv = pNv->sync = calloc(1, sizeof(*priv));
	if (!priv)
		return FALSE;

	if (!dixPrivateKeyRegistered(&nouveau_syncobj_key) &&
	    !dixRegisterPrivateKey(&nouveau_syncobj_key, PRIVATE_SYNC_FENCE,
				   sizeof(struct nouveau_syncobj)))
		return FALSE;

	if (!miSyncShmScreenInit(screen))
		return FALSE;
	sync = miSyncGetScreenFuncs(screen);
	wrap(priv, sync, CreateFence, nouveau_syncobj_new);
	return TRUE;
}