1/*
2 * Copyright © 2013-2014 Intel Corporation
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#include "intel.h"
24#include "misyncshm.h"
25#include "misyncstr.h"
26
27/*
28 * This whole file exists to wrap a sync fence trigger operation
29 * so that we can flush the batch buffer to provide serialization
30 * between the server and the shm fence client
31 */
32
33static DevPrivateKeyRec intel_sync_fence_private_key;
34
35typedef struct _intel_sync_fence_private {
36        SyncFenceSetTriggeredFunc set_triggered;
37} intel_sync_fence_private;
38
39#define SYNC_FENCE_PRIV(pFence)                                         \
40        (intel_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &intel_sync_fence_private_key)
41
42static void
43intel_sync_fence_set_triggered (SyncFence *fence)
44{
45	ScreenPtr screen = fence->pScreen;
46	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
47	intel_screen_private *intel = intel_get_screen_private(scrn);
48	intel_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
49
50	/* Flush pending rendering operations */
51	if (intel->flush_rendering)
52		intel->flush_rendering(intel);
53
54	fence->funcs.SetTriggered = private->set_triggered;
55	fence->funcs.SetTriggered(fence);
56	private->set_triggered = fence->funcs.SetTriggered;
57	fence->funcs.SetTriggered = intel_sync_fence_set_triggered;
58}
59
60static void
61intel_sync_create_fence(ScreenPtr screen,
62                        SyncFence *fence,
63                        Bool initially_triggered)
64{
65	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
66	intel_screen_private *intel = intel_get_screen_private(scrn);
67	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
68	intel_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
69
70	screen_funcs->CreateFence = intel->save_sync_screen_funcs.CreateFence;
71	screen_funcs->CreateFence(screen, fence, initially_triggered);
72	intel->save_sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
73	screen_funcs->CreateFence = intel_sync_create_fence;
74
75	private->set_triggered = fence->funcs.SetTriggered;
76	fence->funcs.SetTriggered = intel_sync_fence_set_triggered;
77}
78
79Bool
80intel_sync_init(ScreenPtr screen)
81{
82	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
83	intel_screen_private *intel = intel_get_screen_private(scrn);
84	SyncScreenFuncsPtr screen_funcs;
85
86	if (!miSyncShmScreenInit(screen))
87		return FALSE;
88
89	if (!dixPrivateKeyRegistered(&intel_sync_fence_private_key)) {
90		if (!dixRegisterPrivateKey(&intel_sync_fence_private_key,
91					   PRIVATE_SYNC_FENCE,
92					   sizeof (intel_sync_fence_private)))
93			return FALSE;
94	}
95
96	screen_funcs = miSyncGetScreenFuncs(screen);
97	intel->save_sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
98	screen_funcs->CreateFence = intel_sync_create_fence;
99	return TRUE;
100}
101
102void
103intel_sync_close(ScreenPtr screen)
104{
105        ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
106        intel_screen_private *intel = intel_get_screen_private(scrn);
107        SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
108
109        if (screen_funcs)
110                screen_funcs->CreateFence = intel->save_sync_screen_funcs.CreateFence;
111}
112