10d16fef4Smrg/*
20d16fef4Smrg * Copyright © 2013-2014 Intel Corporation
30d16fef4Smrg * Copyright © 2015 Advanced Micro Devices, Inc.
40d16fef4Smrg *
50d16fef4Smrg * Permission to use, copy, modify, distribute, and sell this software and its
60d16fef4Smrg * documentation for any purpose is hereby granted without fee, provided that
70d16fef4Smrg * the above copyright notice appear in all copies and that both that copyright
80d16fef4Smrg * notice and this permission notice appear in supporting documentation, and
90d16fef4Smrg * that the name of the copyright holders not be used in advertising or
100d16fef4Smrg * publicity pertaining to distribution of the software without specific,
110d16fef4Smrg * written prior permission.  The copyright holders make no representations
120d16fef4Smrg * about the suitability of this software for any purpose.  It is provided "as
130d16fef4Smrg * is" without express or implied warranty.
140d16fef4Smrg *
150d16fef4Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
160d16fef4Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
170d16fef4Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
180d16fef4Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
190d16fef4Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
200d16fef4Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
210d16fef4Smrg * OF THIS SOFTWARE.
220d16fef4Smrg */
230d16fef4Smrg
240d16fef4Smrg#include "radeon.h"
250d16fef4Smrg
260d16fef4Smrg#ifdef HAVE_MISYNCSHM_H
270d16fef4Smrg
280d16fef4Smrg#include "misync.h"
290d16fef4Smrg#include "misyncshm.h"
300d16fef4Smrg#include "misyncstr.h"
310d16fef4Smrg
320d16fef4Smrg/*
330d16fef4Smrg * This whole file exists to wrap a sync fence trigger operation
340d16fef4Smrg * so that we can flush the batch buffer to provide serialization
350d16fef4Smrg * between the server and the shm fence client
360d16fef4Smrg */
370d16fef4Smrg
380d16fef4Smrgstatic DevPrivateKeyRec radeon_sync_fence_private_key;
390d16fef4Smrg
400d16fef4Smrgtypedef struct _radeon_sync_fence_private {
410d16fef4Smrg        SyncFenceSetTriggeredFunc set_triggered;
420d16fef4Smrg} radeon_sync_fence_private;
430d16fef4Smrg
440d16fef4Smrg#define SYNC_FENCE_PRIV(pFence)                                         \
450d16fef4Smrg        (radeon_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &radeon_sync_fence_private_key)
460d16fef4Smrg
470d16fef4Smrgstatic void
480d16fef4Smrgradeon_sync_fence_set_triggered (SyncFence *fence)
490d16fef4Smrg{
500d16fef4Smrg	ScreenPtr screen = fence->pScreen;
510d16fef4Smrg	radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
520d16fef4Smrg
530d16fef4Smrg	/* Flush pending rendering operations */
540d16fef4Smrg	radeon_cs_flush_indirect(xf86ScreenToScrn(screen));
550d16fef4Smrg
560d16fef4Smrg	fence->funcs.SetTriggered = private->set_triggered;
570d16fef4Smrg	fence->funcs.SetTriggered(fence);
580d16fef4Smrg	private->set_triggered = fence->funcs.SetTriggered;
590d16fef4Smrg	fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
600d16fef4Smrg}
610d16fef4Smrg
620d16fef4Smrgstatic void
630d16fef4Smrgradeon_sync_create_fence(ScreenPtr screen,
640d16fef4Smrg                        SyncFence *fence,
650d16fef4Smrg                        Bool initially_triggered)
660d16fef4Smrg{
670d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
680d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(scrn);
690d16fef4Smrg	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
700d16fef4Smrg	radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
710d16fef4Smrg
720d16fef4Smrg	screen_funcs->CreateFence = info->CreateFence;
730d16fef4Smrg	screen_funcs->CreateFence(screen, fence, initially_triggered);
740d16fef4Smrg	info->CreateFence = screen_funcs->CreateFence;
750d16fef4Smrg	screen_funcs->CreateFence = radeon_sync_create_fence;
760d16fef4Smrg
770d16fef4Smrg	private->set_triggered = fence->funcs.SetTriggered;
780d16fef4Smrg	fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
790d16fef4Smrg}
800d16fef4Smrg
810d16fef4SmrgBool
820d16fef4Smrgradeon_sync_init(ScreenPtr screen)
830d16fef4Smrg{
840d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
850d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(scrn);
860d16fef4Smrg	SyncScreenFuncsPtr screen_funcs;
870d16fef4Smrg
880d16fef4Smrg	if (!xf86LoaderCheckSymbol("miSyncShmScreenInit")) {
890d16fef4Smrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
900d16fef4Smrg			   "SYNC extension fences disabled because "
910d16fef4Smrg			   "miSyncShmScreenInit symbol unresolved\n");
920d16fef4Smrg		return FALSE;
930d16fef4Smrg	}
940d16fef4Smrg
950d16fef4Smrg	if (!miSyncShmScreenInit(screen)) {
960d16fef4Smrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
970d16fef4Smrg			   "SYNC extension fences disabled because "
980d16fef4Smrg			   "miSyncShmScreenInit failed\n");
990d16fef4Smrg		return FALSE;
1000d16fef4Smrg	}
1010d16fef4Smrg
1020d16fef4Smrg	if (!dixPrivateKeyRegistered(&radeon_sync_fence_private_key)) {
1030d16fef4Smrg		if (!dixRegisterPrivateKey(&radeon_sync_fence_private_key,
1040d16fef4Smrg					   PRIVATE_SYNC_FENCE,
1050d16fef4Smrg					   sizeof (radeon_sync_fence_private))) {
1060d16fef4Smrg			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1070d16fef4Smrg				   "SYNC extension fences disabled because "
1080d16fef4Smrg				   "dixRegisterPrivateKey failed\n");
1090d16fef4Smrg			return FALSE;
1100d16fef4Smrg		}
1110d16fef4Smrg	}
1120d16fef4Smrg
1130d16fef4Smrg	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
1140d16fef4Smrg		   "SYNC extension fences enabled\n");
1150d16fef4Smrg
1160d16fef4Smrg	screen_funcs = miSyncGetScreenFuncs(screen);
1170d16fef4Smrg	info->CreateFence = screen_funcs->CreateFence;
1180d16fef4Smrg	screen_funcs->CreateFence = radeon_sync_create_fence;
1190d16fef4Smrg	return TRUE;
1200d16fef4Smrg}
1210d16fef4Smrg
1220d16fef4Smrgvoid
1230d16fef4Smrgradeon_sync_close(ScreenPtr screen)
1240d16fef4Smrg{
1250d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1260d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(scrn);
1270d16fef4Smrg	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
1280d16fef4Smrg
1290d16fef4Smrg	if (screen_funcs && info->CreateFence)
1300d16fef4Smrg		screen_funcs->CreateFence = info->CreateFence;
1310d16fef4Smrg
1320d16fef4Smrg	info->CreateFence = NULL;
1330d16fef4Smrg}
1340d16fef4Smrg
1350d16fef4Smrg#else /* !HAVE_MISYNCSHM_H */
1360d16fef4Smrg
1370d16fef4SmrgBool
1380d16fef4Smrgradeon_sync_init(ScreenPtr screen)
1390d16fef4Smrg{
1400d16fef4Smrg	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
1410d16fef4Smrg		   "SYNC extension fences disabled because misyncshm.h not "
1420d16fef4Smrg		   "available at build time\n");
1430d16fef4Smrg
1440d16fef4Smrg	return FALSE;
1450d16fef4Smrg}
1460d16fef4Smrg
1470d16fef4Smrgvoid
1480d16fef4Smrgradeon_sync_close(ScreenPtr screen)
1490d16fef4Smrg{
1500d16fef4Smrg}
1510d16fef4Smrg
1520d16fef4Smrg#endif
153