all repos — mgba @ a37060d053d54399c75c813ad686fb2ffa071b6a

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 frameOn) {
 11	// Make sure the video thread can process events while the GBA thread is paused
 12	MutexLock(&sync->videoFrameMutex);
 13	if (frameOn != sync->videoFrameOn) {
 14		sync->videoFrameOn = frameOn;
 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	ConditionWake(&sync->videoFrameRequiredCond);
 53	if (!sync->videoFrameOn && !sync->videoFramePending) {
 54		return false;
 55	}
 56	if (sync->videoFrameOn) {
 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	MutexUnlock(&sync->videoFrameMutex);
 71}
 72
 73void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait) {
 74	if (!sync) {
 75		return;
 76	}
 77
 78	_changeVideoSync(sync, wait);
 79}
 80
 81bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) {
 82	if (!sync) {
 83		return true;
 84	}
 85
 86	size_t produced = blip_samples_avail(buf);
 87	size_t producedNew = produced;
 88	while (sync->audioWait && producedNew >= samples) {
 89		ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
 90		produced = producedNew;
 91		producedNew = blip_samples_avail(buf);
 92	}
 93	MutexUnlock(&sync->audioBufferMutex);
 94	return producedNew != produced;
 95}
 96
 97void mCoreSyncLockAudio(struct mCoreSync* sync) {
 98	if (!sync) {
 99		return;
100	}
101
102	MutexLock(&sync->audioBufferMutex);
103}
104
105void mCoreSyncUnlockAudio(struct mCoreSync* sync) {
106	if (!sync) {
107		return;
108	}
109
110	MutexUnlock(&sync->audioBufferMutex);
111}
112
113void mCoreSyncConsumeAudio(struct mCoreSync* sync) {
114	if (!sync) {
115		return;
116	}
117
118	ConditionWake(&sync->audioRequiredCond);
119	MutexUnlock(&sync->audioBufferMutex);
120}