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;
|
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
renderer->mutex = mutex;
|
renderer->mutex = mutex;
|
||||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
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_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) {
|
static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) {
|
||||||
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
|
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
|
||||||
|
|
||||||
pthread_mutex_destroy(&softwareRenderer->mutex);
|
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) {
|
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);
|
pthread_mutex_lock(&softwareRenderer->mutex);
|
||||||
renderer->framesPending++;
|
renderer->framesPending++;
|
||||||
|
pthread_cond_broadcast(&softwareRenderer->upCond);
|
||||||
if (!renderer->turbo) {
|
if (!renderer->turbo) {
|
||||||
pthread_cond_wait(&softwareRenderer->cond, &softwareRenderer->mutex);
|
pthread_cond_wait(&softwareRenderer->downCond, &softwareRenderer->mutex);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&softwareRenderer->mutex);
|
pthread_mutex_unlock(&softwareRenderer->mutex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ struct GBAVideoSoftwareRenderer {
|
||||||
uint16_t* row;
|
uint16_t* row;
|
||||||
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t upCond;
|
||||||
|
pthread_cond_t downCond;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);
|
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);
|
||||||
|
|
16
src/main.c
16
src/main.c
|
@ -9,6 +9,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
struct GLSoftwareRenderer {
|
struct GLSoftwareRenderer {
|
||||||
|
@ -118,12 +119,21 @@ static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer*
|
||||||
|
|
||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
pthread_mutex_lock(&renderer->d.mutex);
|
pthread_mutex_lock(&renderer->d.mutex);
|
||||||
pthread_cond_broadcast(&renderer->d.cond);
|
pthread_cond_broadcast(&renderer->d.downCond);
|
||||||
pthread_mutex_unlock(&renderer->d.mutex);
|
pthread_mutex_unlock(&renderer->d.mutex);
|
||||||
} else {
|
} 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);
|
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)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
|
Loading…
Reference in New Issue