all repos — mgba @ 2d6087aa985fc401b1753f4482f07a512828f170

mGBA Game Boy Advance Emulator

src/core/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 <mgba/core/sync.h>
  7
  8#include <mgba/core/blip_buf.h>
  9
 10static void _changeVideoSync(struct mCoreSync* sync, bool wait) {
 11	// Make sure the video thread can process events while the GBA thread is paused
 12	MutexLock(&sync->videoFrameMutex);
 13	if (wait != sync->videoFrameWait) {
 14		sync->videoFrameWait = wait;
 15		ConditionWake(&sync->videoFrameAvailableCond);
 16	}
 17	MutexUnlock(&sync->videoFrameMutex);
 18}
 19
 20void mCoreSyncPostFrame(struct mCoreSync* sync) {
 21	if (!sync) {
 22		return;
 23	}
 24
 25	MutexLock(&sync->videoFrameMutex);
 26	++sync->videoFramePending;
 27	do {
 28		ConditionWake(&sync->videoFrameAvailableCond);
 29		if (sync->videoFrameWait) {
 30			ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex);
 31		}
 32	} while (sync->videoFrameWait && sync->videoFramePending);
 33	MutexUnlock(&sync->videoFrameMutex);
 34}
 35
 36void mCoreSyncForceFrame(struct mCoreSync* sync) {
 37	if (!sync) {
 38		return;
 39	}
 40
 41	MutexLock(&sync->videoFrameMutex);
 42	ConditionWake(&sync->videoFrameAvailableCond);
 43	MutexUnlock(&sync->videoFrameMutex);
 44}
 45
 46bool mCoreSyncWaitFrameStart(struct mCoreSync* sync) {
 47	if (!sync) {
 48		return true;
 49	}
 50
 51	MutexLock(&sync->videoFrameMutex);
 52	if (!sync->videoFrameWait && !sync->videoFramePending) {
 53		return false;
 54	}
 55	if (sync->videoFrameWait) {
 56		ConditionWake(&sync->videoFrameRequiredCond);
 57		if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) {
 58			return false;
 59		}
 60	}
 61	sync->videoFramePending = 0;
 62	return true;
 63}
 64
 65void mCoreSyncWaitFrameEnd(struct mCoreSync* sync) {
 66	if (!sync) {
 67		return;
 68	}
 69
 70	ConditionWake(&sync->videoFrameRequiredCond);
 71	MutexUnlock(&sync->videoFrameMutex);
 72}
 73
 74void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait) {
 75	if (!sync) {
 76		return;
 77	}
 78
 79	_changeVideoSync(sync, wait);
 80}
 81
 82bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) {
 83	if (!sync) {
 84		return true;
 85	}
 86
 87	size_t produced = blip_samples_avail(buf);
 88	size_t producedNew = produced;
 89	while (sync->audioWait && producedNew >= samples) {
 90		ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
 91		produced = producedNew;
 92		producedNew = blip_samples_avail(buf);
 93	}
 94	MutexUnlock(&sync->audioBufferMutex);
 95	return producedNew != produced;
 96}
 97
 98void mCoreSyncLockAudio(struct mCoreSync* sync) {
 99	if (!sync) {
100		return;
101	}
102
103	MutexLock(&sync->audioBufferMutex);
104}
105
106void mCoreSyncUnlockAudio(struct mCoreSync* sync) {
107	if (!sync) {
108		return;
109	}
110
111	MutexUnlock(&sync->audioBufferMutex);
112}
113
114void mCoreSyncConsumeAudio(struct mCoreSync* sync) {
115	if (!sync) {
116		return;
117	}
118
119	ConditionWake(&sync->audioRequiredCond);
120	MutexUnlock(&sync->audioBufferMutex);
121}