all repos — mgba @ f836a67863e66499c812c8d963d37ff56ad10638

mGBA Game Boy Advance Emulator

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}