1/*
2 * Copyright © 2014 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23
24#include "glamor_priv.h"
25#include "misyncshm.h"
26#include "misyncstr.h"
27
28#if XSYNC
29/*
30 * This whole file exists to wrap a sync fence trigger operation so
31 * that we can flush GL to provide serialization between the server
32 * and the shm fence client
33 */
34
35static DevPrivateKeyRec glamor_sync_fence_key;
36
37struct glamor_sync_fence {
38        SyncFenceSetTriggeredFunc set_triggered;
39};
40
41static inline struct glamor_sync_fence *
42glamor_get_sync_fence(SyncFence *fence)
43{
44    return (struct glamor_sync_fence *) dixLookupPrivate(&fence->devPrivates, &glamor_sync_fence_key);
45}
46
47static void
48glamor_sync_fence_set_triggered (SyncFence *fence)
49{
50	ScreenPtr screen = fence->pScreen;
51	glamor_screen_private *glamor = glamor_get_screen_private(screen);
52	struct glamor_sync_fence *glamor_fence = glamor_get_sync_fence(fence);
53
54	/* Flush pending rendering operations */
55        glamor_make_current(glamor);
56        glFlush();
57
58	fence->funcs.SetTriggered = glamor_fence->set_triggered;
59	fence->funcs.SetTriggered(fence);
60	glamor_fence->set_triggered = fence->funcs.SetTriggered;
61	fence->funcs.SetTriggered = glamor_sync_fence_set_triggered;
62}
63
64static void
65glamor_sync_create_fence(ScreenPtr screen,
66                        SyncFence *fence,
67                        Bool initially_triggered)
68{
69	glamor_screen_private *glamor = glamor_get_screen_private(screen);
70	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
71	struct glamor_sync_fence *glamor_fence = glamor_get_sync_fence(fence);
72
73	screen_funcs->CreateFence = glamor->saved_procs.sync_screen_funcs.CreateFence;
74	screen_funcs->CreateFence(screen, fence, initially_triggered);
75	glamor->saved_procs.sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
76	screen_funcs->CreateFence = glamor_sync_create_fence;
77
78	glamor_fence->set_triggered = fence->funcs.SetTriggered;
79	fence->funcs.SetTriggered = glamor_sync_fence_set_triggered;
80}
81#endif
82
83Bool
84glamor_sync_init(ScreenPtr screen)
85{
86#if XSYNC
87	glamor_screen_private   *glamor = glamor_get_screen_private(screen);
88	SyncScreenFuncsPtr      screen_funcs;
89
90	if (!dixPrivateKeyRegistered(&glamor_sync_fence_key)) {
91		if (!dixRegisterPrivateKey(&glamor_sync_fence_key,
92					   PRIVATE_SYNC_FENCE,
93					   sizeof (struct glamor_sync_fence)))
94			return FALSE;
95	}
96
97#ifdef HAVE_XSHMFENCE
98	if (!miSyncShmScreenInit(screen))
99		return FALSE;
100#else
101	if (!miSyncSetup(screen))
102		return FALSE;
103#endif
104
105	screen_funcs = miSyncGetScreenFuncs(screen);
106	glamor->saved_procs.sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
107	screen_funcs->CreateFence = glamor_sync_create_fence;
108#endif
109	return TRUE;
110}
111
112void
113glamor_sync_close(ScreenPtr screen)
114{
115#if XSYNC
116        glamor_screen_private   *glamor = glamor_get_screen_private(screen);
117        SyncScreenFuncsPtr      screen_funcs = miSyncGetScreenFuncs(screen);
118
119        if (screen_funcs)
120                screen_funcs->CreateFence = glamor->saved_procs.sync_screen_funcs.CreateFence;
121#endif
122}
123