mirror of https://github.com/mgba-emu/mgba.git
GBA Thread: Split GBASync into a separate file
This commit is contained in:
parent
79e06612cb
commit
40ae214a7d
1
CHANGES
1
CHANGES
|
@ -63,6 +63,7 @@ Misc:
|
|||
- Qt: Replace pause-after-frame mutex with an atomic
|
||||
- Util: Allow disabling the threading code entirely
|
||||
- GBA: SIO logging layer
|
||||
- GBA Thread: Split GBASync into a separate file
|
||||
|
||||
0.2.1: (2015-05-13)
|
||||
Bugfixes:
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "thread.h"
|
||||
|
||||
static void _changeVideoSync(struct GBASync* sync, bool frameOn) {
|
||||
// Make sure the video thread can process events while the GBA thread is paused
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
if (frameOn != sync->videoFrameOn) {
|
||||
sync->videoFrameOn = frameOn;
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
}
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
void GBASyncPostFrame(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
++sync->videoFramePending;
|
||||
--sync->videoFrameSkip;
|
||||
if (sync->videoFrameSkip < 0) {
|
||||
do {
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
if (sync->videoFrameWait) {
|
||||
ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex);
|
||||
}
|
||||
} while (sync->videoFrameWait && sync->videoFramePending);
|
||||
}
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
void GBASyncForceFrame(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip) {
|
||||
if (!sync) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
ConditionWake(&sync->videoFrameRequiredCond);
|
||||
if (!sync->videoFrameOn && !sync->videoFramePending) {
|
||||
return false;
|
||||
}
|
||||
if (sync->videoFrameOn) {
|
||||
if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sync->videoFramePending = 0;
|
||||
sync->videoFrameSkip = frameskip;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GBASyncWaitFrameEnd(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
bool GBASyncDrawingFrame(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return sync->videoFrameSkip <= 0;
|
||||
}
|
||||
|
||||
void GBASyncSetVideoSync(struct GBASync* sync, bool wait) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
_changeVideoSync(sync, wait);
|
||||
}
|
||||
|
||||
void GBASyncProduceAudio(struct GBASync* sync, bool wait) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sync->audioWait && wait) {
|
||||
// TODO loop properly in event of spurious wakeups
|
||||
ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
|
||||
}
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
||||
void GBASyncLockAudio(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
||||
void GBASyncUnlockAudio(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
||||
void GBASyncConsumeAudio(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConditionWake(&sync->audioRequiredCond);
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef GBA_SYNC_H
|
||||
#define GBA_SYNC_H
|
||||
|
||||
#include "util/common.h"
|
||||
|
||||
#include "util/threading.h"
|
||||
|
||||
struct GBASync {
|
||||
int videoFramePending;
|
||||
bool videoFrameWait;
|
||||
int videoFrameSkip;
|
||||
bool videoFrameOn;
|
||||
Mutex videoFrameMutex;
|
||||
Condition videoFrameAvailableCond;
|
||||
Condition videoFrameRequiredCond;
|
||||
|
||||
bool audioWait;
|
||||
Condition audioRequiredCond;
|
||||
Mutex audioBufferMutex;
|
||||
};
|
||||
|
||||
void GBASyncPostFrame(struct GBASync* sync);
|
||||
void GBASyncForceFrame(struct GBASync* sync);
|
||||
bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip);
|
||||
void GBASyncWaitFrameEnd(struct GBASync* sync);
|
||||
bool GBASyncDrawingFrame(struct GBASync* sync);
|
||||
void GBASyncSetVideoSync(struct GBASync* sync, bool wait);
|
||||
|
||||
void GBASyncProduceAudio(struct GBASync* sync, bool wait);
|
||||
void GBASyncLockAudio(struct GBASync* sync);
|
||||
void GBASyncUnlockAudio(struct GBASync* sync);
|
||||
void GBASyncConsumeAudio(struct GBASync* sync);
|
||||
|
||||
#endif
|
|
@ -93,19 +93,7 @@ static void _pauseThread(struct GBAThread* threadContext, bool onThread) {
|
|||
_waitUntilNotState(threadContext, THREAD_PAUSING);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _changeVideoSync(struct GBASync* sync, bool frameOn) {
|
||||
// Make sure the video thread can process events while the GBA thread is paused
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
if (frameOn != sync->videoFrameOn) {
|
||||
sync->videoFrameOn = frameOn;
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
}
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_THREADING
|
||||
static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||
#ifdef USE_PTHREADS
|
||||
pthread_once(&_contextOnce, _createTLS);
|
||||
|
@ -631,7 +619,7 @@ void GBAThreadPause(struct GBAThread* threadContext) {
|
|||
}
|
||||
MutexUnlock(&threadContext->stateMutex);
|
||||
|
||||
_changeVideoSync(&threadContext->sync, frameOn);
|
||||
GBASyncSetVideoSync(&threadContext->sync, frameOn);
|
||||
}
|
||||
|
||||
void GBAThreadUnpause(struct GBAThread* threadContext) {
|
||||
|
@ -645,7 +633,7 @@ void GBAThreadUnpause(struct GBAThread* threadContext) {
|
|||
}
|
||||
MutexUnlock(&threadContext->stateMutex);
|
||||
|
||||
_changeVideoSync(&threadContext->sync, frameOn);
|
||||
GBASyncSetVideoSync(&threadContext->sync, frameOn);
|
||||
}
|
||||
|
||||
bool GBAThreadIsPaused(struct GBAThread* threadContext) {
|
||||
|
@ -672,7 +660,7 @@ void GBAThreadTogglePause(struct GBAThread* threadContext) {
|
|||
}
|
||||
MutexUnlock(&threadContext->stateMutex);
|
||||
|
||||
_changeVideoSync(&threadContext->sync, frameOn);
|
||||
GBASyncSetVideoSync(&threadContext->sync, frameOn);
|
||||
}
|
||||
|
||||
void GBAThreadPauseFromThread(struct GBAThread* threadContext) {
|
||||
|
@ -685,7 +673,7 @@ void GBAThreadPauseFromThread(struct GBAThread* threadContext) {
|
|||
}
|
||||
MutexUnlock(&threadContext->stateMutex);
|
||||
|
||||
_changeVideoSync(&threadContext->sync, frameOn);
|
||||
GBASyncSetVideoSync(&threadContext->sync, frameOn);
|
||||
}
|
||||
|
||||
#ifdef USE_PTHREADS
|
||||
|
@ -722,113 +710,3 @@ struct GBAThread* GBAThreadGetContext(void) {
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GBASyncPostFrame(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
++sync->videoFramePending;
|
||||
--sync->videoFrameSkip;
|
||||
if (sync->videoFrameSkip < 0) {
|
||||
do {
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
if (sync->videoFrameWait) {
|
||||
ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex);
|
||||
}
|
||||
} while (sync->videoFrameWait && sync->videoFramePending);
|
||||
}
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
void GBASyncForceFrame(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip) {
|
||||
if (!sync) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
ConditionWake(&sync->videoFrameRequiredCond);
|
||||
if (!sync->videoFrameOn && !sync->videoFramePending) {
|
||||
return false;
|
||||
}
|
||||
if (sync->videoFrameOn) {
|
||||
if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sync->videoFramePending = 0;
|
||||
sync->videoFrameSkip = frameskip;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GBASyncWaitFrameEnd(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
||||
bool GBASyncDrawingFrame(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return sync->videoFrameSkip <= 0;
|
||||
}
|
||||
|
||||
void GBASyncSetVideoSync(struct GBASync* sync, bool wait) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
_changeVideoSync(sync, wait);
|
||||
}
|
||||
|
||||
void GBASyncProduceAudio(struct GBASync* sync, bool wait) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sync->audioWait && wait) {
|
||||
// TODO loop properly in event of spurious wakeups
|
||||
ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
|
||||
}
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
||||
void GBASyncLockAudio(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
||||
void GBASyncUnlockAudio(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
||||
void GBASyncConsumeAudio(struct GBASync* sync) {
|
||||
if (!sync) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConditionWake(&sync->audioRequiredCond);
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "gba/gba.h"
|
||||
#include "gba/input.h"
|
||||
#include "gba/supervisor/overrides.h"
|
||||
#include "gba/supervisor/sync.h"
|
||||
|
||||
#include "util/threading.h"
|
||||
|
||||
|
@ -35,20 +36,6 @@ enum ThreadState {
|
|||
THREAD_CRASHED
|
||||
};
|
||||
|
||||
struct GBASync {
|
||||
int videoFramePending;
|
||||
bool videoFrameWait;
|
||||
int videoFrameSkip;
|
||||
bool videoFrameOn;
|
||||
Mutex videoFrameMutex;
|
||||
Condition videoFrameAvailableCond;
|
||||
Condition videoFrameRequiredCond;
|
||||
|
||||
bool audioWait;
|
||||
Condition audioRequiredCond;
|
||||
Mutex audioBufferMutex;
|
||||
};
|
||||
|
||||
struct GBAThread {
|
||||
// Output
|
||||
enum ThreadState state;
|
||||
|
@ -143,16 +130,4 @@ struct GBAThread* GBAThreadGetContext(void);
|
|||
void GBAThreadTakeScreenshot(struct GBAThread* threadContext);
|
||||
#endif
|
||||
|
||||
void GBASyncPostFrame(struct GBASync* sync);
|
||||
void GBASyncForceFrame(struct GBASync* sync);
|
||||
bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip);
|
||||
void GBASyncWaitFrameEnd(struct GBASync* sync);
|
||||
bool GBASyncDrawingFrame(struct GBASync* sync);
|
||||
void GBASyncSetVideoSync(struct GBASync* sync, bool wait);
|
||||
|
||||
void GBASyncProduceAudio(struct GBASync* sync, bool wait);
|
||||
void GBASyncLockAudio(struct GBASync* sync);
|
||||
void GBASyncUnlockAudio(struct GBASync* sync);
|
||||
void GBASyncConsumeAudio(struct GBASync* sync);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "gba/io.h"
|
||||
#include "gba/serialize.h"
|
||||
#include "gba/supervisor/rr.h"
|
||||
#include "gba/supervisor/thread.h"
|
||||
#include "gba/supervisor/sync.h"
|
||||
|
||||
#include "util/memory.h"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef FFMPEG_ENCODER
|
||||
#define FFMPEG_ENCODER
|
||||
|
||||
#include "gba/supervisor/thread.h"
|
||||
#include "gba/gba.h"
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef IMAGEMAGICK_GIF_ENCODER
|
||||
#define IMAGEMAGICK_GIF_ENCODER
|
||||
|
||||
#include "gba/supervisor/thread.h"
|
||||
#include "gba/gba.h"
|
||||
|
||||
#define MAGICKCORE_HDRI_ENABLE 0
|
||||
#define MAGICKCORE_QUANTUM_DEPTH 8
|
||||
|
|
Loading…
Reference in New Issue