src/gba/context/sync.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "sync.h"
7
8static void _changeVideoSync(struct GBASync* sync, bool frameOn) {
9 // Make sure the video thread can process events while the GBA thread is paused
10 MutexLock(&sync->videoFrameMutex);
11 if (frameOn != sync->videoFrameOn) {
12 sync->videoFrameOn = frameOn;
13 ConditionWake(&sync->videoFrameAvailableCond);
14 }
15 MutexUnlock(&sync->videoFrameMutex);
16}
17
18void GBASyncPostFrame(struct GBASync* sync) {
19 if (!sync) {
20 return;
21 }
22
23 MutexLock(&sync->videoFrameMutex);
24 ++sync->videoFramePending;
25 do {
26 ConditionWake(&sync->videoFrameAvailableCond);
27 if (sync->videoFrameWait) {
28 ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex);
29 }
30 } while (sync->videoFrameWait && sync->videoFramePending);
31 MutexUnlock(&sync->videoFrameMutex);
32}
33
34void GBASyncForceFrame(struct GBASync* sync) {
35 if (!sync) {
36 return;
37 }
38
39 MutexLock(&sync->videoFrameMutex);
40 ConditionWake(&sync->videoFrameAvailableCond);
41 MutexUnlock(&sync->videoFrameMutex);
42}
43
44bool GBASyncWaitFrameStart(struct GBASync* sync) {
45 if (!sync) {
46 return true;
47 }
48
49 MutexLock(&sync->videoFrameMutex);
50 ConditionWake(&sync->videoFrameRequiredCond);
51 if (!sync->videoFrameOn && !sync->videoFramePending) {
52 return false;
53 }
54 if (sync->videoFrameOn) {
55 if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) {
56 return false;
57 }
58 }
59 sync->videoFramePending = 0;
60 return true;
61}
62
63void GBASyncWaitFrameEnd(struct GBASync* sync) {
64 if (!sync) {
65 return;
66 }
67
68 MutexUnlock(&sync->videoFrameMutex);
69}
70
71void GBASyncSetVideoSync(struct GBASync* sync, bool wait) {
72 if (!sync) {
73 return;
74 }
75
76 _changeVideoSync(sync, wait);
77}
78
79void GBASyncProduceAudio(struct GBASync* sync, bool wait) {
80 if (!sync) {
81 return;
82 }
83
84 if (sync->audioWait && wait) {
85 // TODO loop properly in event of spurious wakeups
86 ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
87 }
88 MutexUnlock(&sync->audioBufferMutex);
89}
90
91void GBASyncLockAudio(struct GBASync* sync) {
92 if (!sync) {
93 return;
94 }
95
96 MutexLock(&sync->audioBufferMutex);
97}
98
99void GBASyncUnlockAudio(struct GBASync* sync) {
100 if (!sync) {
101 return;
102 }
103
104 MutexUnlock(&sync->audioBufferMutex);
105}
106
107void GBASyncConsumeAudio(struct GBASync* sync) {
108 if (!sync) {
109 return;
110 }
111
112 ConditionWake(&sync->audioRequiredCond);
113 MutexUnlock(&sync->audioBufferMutex);
114}