mirror of https://github.com/mgba-emu/mgba.git
Dual condition-variable non-hacky waiting-on-frame
This commit is contained in:
parent
5122a236e0
commit
00dd5bdaa8
|
@ -46,7 +46,8 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
|
|||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
renderer->mutex = mutex;
|
||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
renderer->cond = cond;
|
||||
renderer->upCond = cond;
|
||||
renderer->downCond = cond;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,14 +94,16 @@ static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) {
|
|||
}
|
||||
|
||||
pthread_mutex_init(&softwareRenderer->mutex, 0);
|
||||
pthread_cond_init(&softwareRenderer->cond, 0);
|
||||
pthread_cond_init(&softwareRenderer->upCond, 0);
|
||||
pthread_cond_init(&softwareRenderer->downCond, 0);
|
||||
}
|
||||
|
||||
static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) {
|
||||
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
|
||||
|
||||
pthread_mutex_destroy(&softwareRenderer->mutex);
|
||||
pthread_cond_destroy(&softwareRenderer->cond);
|
||||
pthread_cond_destroy(&softwareRenderer->upCond);
|
||||
pthread_cond_destroy(&softwareRenderer->downCond);
|
||||
}
|
||||
|
||||
static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
|
||||
|
@ -210,8 +213,9 @@ static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* rendere
|
|||
|
||||
pthread_mutex_lock(&softwareRenderer->mutex);
|
||||
renderer->framesPending++;
|
||||
pthread_cond_broadcast(&softwareRenderer->upCond);
|
||||
if (!renderer->turbo) {
|
||||
pthread_cond_wait(&softwareRenderer->cond, &softwareRenderer->mutex);
|
||||
pthread_cond_wait(&softwareRenderer->downCond, &softwareRenderer->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&softwareRenderer->mutex);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,8 @@ struct GBAVideoSoftwareRenderer {
|
|||
uint16_t* row;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
pthread_cond_t upCond;
|
||||
pthread_cond_t downCond;
|
||||
};
|
||||
|
||||
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);
|
||||
|
|
16
src/main.c
16
src/main.c
|
@ -9,6 +9,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct GLSoftwareRenderer {
|
||||
|
@ -118,12 +119,21 @@ static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer*
|
|||
|
||||
SDL_GL_SwapBuffers();
|
||||
pthread_mutex_lock(&renderer->d.mutex);
|
||||
pthread_cond_broadcast(&renderer->d.cond);
|
||||
pthread_cond_broadcast(&renderer->d.downCond);
|
||||
pthread_mutex_unlock(&renderer->d.mutex);
|
||||
} else {
|
||||
while (!renderer->d.d.framesPending) {
|
||||
struct timeval tv;
|
||||
struct timespec ts;
|
||||
gettimeofday(&tv, 0);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000 + 800000;
|
||||
int err = pthread_cond_timedwait(&renderer->d.upCond, &renderer->d.mutex, &ts);
|
||||
if (err == ETIMEDOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&renderer->d.mutex);
|
||||
// We have no frame, let's just wait a sec to see if we get one.
|
||||
usleep(500);
|
||||
}
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
|
|
Loading…
Reference in New Issue