1/*
2 * Copyright © 2013-2014 Intel Corporation
3 * Copyright © 2015 Advanced Micro Devices, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission.  The copyright holders make no representations
12 * about the suitability of this software for any purpose.  It is provided "as
13 * is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 * OF THIS SOFTWARE.
22 */
23
24#include "amdgpu_drv.h"
25
26#ifdef HAVE_MISYNCSHM_H
27
28#include "misync.h"
29#include "misyncshm.h"
30#include "misyncstr.h"
31
32#include "amdgpu_glamor.h"
33
34/*
35 * This whole file exists to wrap a sync fence trigger operation
36 * so that we can flush the batch buffer to provide serialization
37 * between the server and the shm fence client
38 */
39
40static DevPrivateKeyRec amdgpu_sync_fence_private_key;
41
42typedef struct _amdgpu_sync_fence_private {
43        SyncFenceSetTriggeredFunc set_triggered;
44} amdgpu_sync_fence_private;
45
46#define SYNC_FENCE_PRIV(pFence)                                         \
47        (amdgpu_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &amdgpu_sync_fence_private_key)
48
49static void
50amdgpu_sync_fence_set_triggered (SyncFence *fence)
51{
52	ScreenPtr screen = fence->pScreen;
53	amdgpu_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
54
55	/* Flush pending rendering operations */
56	amdgpu_glamor_flush(xf86ScreenToScrn(screen));
57
58	fence->funcs.SetTriggered = private->set_triggered;
59	fence->funcs.SetTriggered(fence);
60	private->set_triggered = fence->funcs.SetTriggered;
61	fence->funcs.SetTriggered = amdgpu_sync_fence_set_triggered;
62}
63
64static void
65amdgpu_sync_create_fence(ScreenPtr screen,
66                        SyncFence *fence,
67                        Bool initially_triggered)
68{
69	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
70	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
71	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
72	amdgpu_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
73
74	screen_funcs->CreateFence = info->CreateFence;
75	screen_funcs->CreateFence(screen, fence, initially_triggered);
76	info->CreateFence = screen_funcs->CreateFence;
77	screen_funcs->CreateFence = amdgpu_sync_create_fence;
78
79	private->set_triggered = fence->funcs.SetTriggered;
80	fence->funcs.SetTriggered = amdgpu_sync_fence_set_triggered;
81}
82
83Bool
84amdgpu_sync_init(ScreenPtr screen)
85{
86	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
87	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
88	SyncScreenFuncsPtr screen_funcs;
89
90	if (!xf86LoaderCheckSymbol("miSyncShmScreenInit")) {
91		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
92			   "SYNC extension fences disabled because "
93			   "miSyncShmScreenInit symbol unresolved\n");
94		return FALSE;
95	}
96
97	if (!miSyncShmScreenInit(screen)) {
98		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
99			   "SYNC extension fences disabled because "
100			   "miSyncShmScreenInit failed\n");
101		return FALSE;
102	}
103
104	if (!dixPrivateKeyRegistered(&amdgpu_sync_fence_private_key)) {
105		if (!dixRegisterPrivateKey(&amdgpu_sync_fence_private_key,
106					   PRIVATE_SYNC_FENCE,
107					   sizeof (amdgpu_sync_fence_private))) {
108			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
109				   "SYNC extension fences disabled because "
110				   "dixRegisterPrivateKey failed\n");
111			return FALSE;
112		}
113	}
114
115	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
116		   "SYNC extension fences enabled\n");
117
118	screen_funcs = miSyncGetScreenFuncs(screen);
119	info->CreateFence = screen_funcs->CreateFence;
120	screen_funcs->CreateFence = amdgpu_sync_create_fence;
121	return TRUE;
122}
123
124void
125amdgpu_sync_close(ScreenPtr screen)
126{
127	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
128	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
129	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
130
131	if (screen_funcs && info->CreateFence)
132		screen_funcs->CreateFence = info->CreateFence;
133
134	info->CreateFence = NULL;
135}
136
137#else /* !HAVE_MISYNCSHM_H */
138
139Bool
140amdgpu_sync_init(ScreenPtr screen)
141{
142	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
143		   "SYNC extension fences disabled because misyncshm.h not "
144		   "available at build time\n");
145
146	return FALSE;
147}
148
149void
150amdgpu_sync_close(ScreenPtr screen)
151{
152}
153
154#endif
155