Mercurial > repos > blastem
diff render_sdl.c @ 1983:a7b753e260a2 mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 09 May 2020 23:39:44 -0700 |
parents | 81df9aa2de9b |
children | 3537514ea206 |
line wrap: on
line diff
--- a/render_sdl.c Sun Apr 19 00:59:49 2020 -0700 +++ b/render_sdl.c Sat May 09 23:39:44 2020 -0700 @@ -50,7 +50,14 @@ static SDL_cond *audio_ready, *frame_ready; static uint8_t quitting = 0; -static uint8_t sync_to_audio, run_on_audio_thread; +enum { + SYNC_AUDIO, + SYNC_AUDIO_THREAD, + SYNC_VIDEO, + SYNC_EXTERNAL +}; + +static uint8_t sync_src; static uint32_t min_buffered; uint32_t **frame_buffers; @@ -64,12 +71,12 @@ uint8_t render_is_audio_sync(void) { - return sync_to_audio || run_on_audio_thread; + return sync_src < SYNC_VIDEO; } uint8_t render_should_release_on_exit(void) { - return !run_on_audio_thread; + return sync_src != SYNC_AUDIO_THREAD; } void render_buffer_consumed(audio_source *src) @@ -120,7 +127,7 @@ void render_lock_audio() { - if (sync_to_audio) { + if (sync_src == SYNC_AUDIO) { SDL_LockMutex(audio_mutex); } else { SDL_LockAudio(); @@ -129,7 +136,7 @@ void render_unlock_audio() { - if (sync_to_audio) { + if (sync_src == SYNC_AUDIO) { SDL_UnlockMutex(audio_mutex); } else { SDL_UnlockAudio(); @@ -164,34 +171,40 @@ void render_audio_created(audio_source *source) { - if (sync_to_audio && SDL_GetAudioStatus() == SDL_AUDIO_PAUSED) { + if (render_is_audio_sync()) { SDL_PauseAudio(0); } - if (current_system) { - current_system->request_exit(current_system); + if (current_system && sync_src == SYNC_AUDIO_THREAD) { + system_request_exit(current_system, 0); } } void render_source_paused(audio_source *src, uint8_t remaining_sources) { - if (sync_to_audio) { + if (sync_src == SYNC_AUDIO) { SDL_CondSignal(audio_ready); } - if (!remaining_sources) { - SDL_PauseAudio(0); + if (!remaining_sources && render_is_audio_sync()) { + SDL_PauseAudio(1); + if (sync_src == SYNC_AUDIO_THREAD) { + SDL_CondSignal(frame_ready); + } } } void render_source_resumed(audio_source *src) { - if (sync_to_audio) { + if (render_is_audio_sync()) { SDL_PauseAudio(0); } + if (current_system && sync_src == SYNC_AUDIO_THREAD) { + system_request_exit(current_system, 0); + } } void render_do_audio_ready(audio_source *src) { - if (run_on_audio_thread) { + if (sync_src == SYNC_AUDIO_THREAD) { int16_t *tmp = src->front; src->front = src->back; src->back = tmp; @@ -199,9 +212,9 @@ src->buffer_pos = 0; if (all_sources_ready()) { //we've emulated far enough to fill the current buffer - current_system->request_exit(current_system); + system_request_exit(current_system, 0); } - } else if (sync_to_audio) { + } else if (sync_src == SYNC_AUDIO) { SDL_LockMutex(audio_mutex); while (src->front_populated) { SDL_CondWait(src->opaque, audio_mutex); @@ -253,8 +266,21 @@ #endif } +static uint8_t external_sync; +void render_set_external_sync(uint8_t ext_sync_on) +{ + if (ext_sync_on != external_sync) { + external_sync = ext_sync_on; + if (windowed_width) { + //only do this if render_init has already been called + render_config_updated(); + } + } +} + #ifndef DISABLE_OPENGL -static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, at_pos; +static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, un_texsize, at_pos; +static int tex_width, tex_height; static GLfloat vertex_data_default[] = { -1.0f, -1.0f, @@ -360,6 +386,15 @@ char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval; GLint filter = strcmp(scaling, "linear") ? GL_NEAREST : GL_LINEAR; glGenTextures(3, textures); + def.ptrval = "off"; + char *npot_textures = tern_find_path_default(config, "video\0npot_textures\0", def, TVAL_PTR).ptrval; + if (!strcmp(npot_textures, "on")) { + tex_width = LINEBUF_SIZE; + tex_height = 294; //PAL height with full borders + } else { + tex_width = tex_height = 512; + } + printf("Using %dx%d textures\n", tex_width, tex_height); for (int i = 0; i < 3; i++) { glBindTexture(GL_TEXTURE_2D, textures[i]); @@ -369,7 +404,7 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (i < 2) { //TODO: Fixme for PAL + invalid display mode - glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 512, 512, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf); + glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, tex_width, tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf); } else { uint32_t blank = 255 << 24; glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, &blank); @@ -398,6 +433,7 @@ un_textures[1] = glGetUniformLocation(program, "textures[1]"); un_width = glGetUniformLocation(program, "width"); un_height = glGetUniformLocation(program, "height"); + un_texsize = glGetUniformLocation(program, "texsize"); at_pos = glGetAttribLocation(program, "pos"); } @@ -913,7 +949,17 @@ } debug_message("config says: %d\n", samples); desired.samples = samples*2; - desired.callback = sync_to_audio ? audio_callback : run_on_audio_thread ? audio_callback_run_on_audio : audio_callback_drc; + switch (sync_src) + { + case SYNC_AUDIO: + desired.callback = audio_callback; + break; + case SYNC_AUDIO_THREAD: + desired.callback = audio_callback_run_on_audio; + break; + default: + desired.callback = audio_callback_drc; + } desired.userdata = NULL; if (SDL_OpenAudio(&desired, &actual) < 0) { @@ -943,12 +989,31 @@ } tern_val def = {.ptrval = "audio"}; - char *sync_src = tern_find_path_default(config, "system\0sync_source\0", def, TVAL_PTR).ptrval; - sync_to_audio = !strcmp(sync_src, "audio"); - run_on_audio_thread = !strcmp(sync_src, "audio_thread"); + if (external_sync) { + sync_src = SYNC_EXTERNAL; + } else { + char *sync_src_str = tern_find_path_default(config, "system\0sync_source\0", def, TVAL_PTR).ptrval; + if (!strcmp(sync_src_str, "audio")) { + sync_src = SYNC_AUDIO; + } else if (!strcmp(sync_src_str, "audio_thread")) { + sync_src = SYNC_AUDIO_THREAD; + } else { + sync_src = SYNC_VIDEO; + } + } + + if (!num_buffers && (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL)) { + frame_mutex = SDL_CreateMutex(); + free_buffer_mutex = SDL_CreateMutex(); + frame_ready = SDL_CreateCond(); + buffer_storage = 4; + frame_buffers = calloc(buffer_storage, sizeof(uint32_t*)); + frame_buffers[0] = texture_buf; + num_buffers = 1; + } const char *vsync; - if (sync_to_audio) { + if (sync_src == SYNC_AUDIO) { def.ptrval = "off"; vsync = tern_find_path_default(config, "video\0vsync\0", def, TVAL_PTR).ptrval; } else { @@ -1108,16 +1173,6 @@ audio_mutex = SDL_CreateMutex(); audio_ready = SDL_CreateCond(); - if (run_on_audio_thread) { - frame_mutex = SDL_CreateMutex(); - free_buffer_mutex = SDL_CreateMutex(); - frame_ready = SDL_CreateCond(); - buffer_storage = 4; - frame_buffers = calloc(buffer_storage, sizeof(uint32_t*)); - frame_buffers[0] = texture_buf; - num_buffers = 1; - } - init_audio(); uint32_t db_size; @@ -1136,13 +1191,10 @@ atexit(render_quit); } -#include<unistd.h> static int in_toggle; void render_config_updated(void) { - uint8_t old_sync_to_audio = sync_to_audio; - free_surfaces(); #ifndef DISABLE_OPENGL if (render_gl) { @@ -1336,14 +1388,14 @@ uint32_t locked_pitch; uint32_t *render_get_framebuffer(uint8_t which, int *pitch) { - if (run_on_audio_thread) { + if (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL) { *pitch = LINEBUF_SIZE * sizeof(uint32_t); uint32_t *buffer; SDL_LockMutex(free_buffer_mutex); if (num_buffers) { buffer = frame_buffers[--num_buffers]; } else { - buffer = calloc(512*512, sizeof(uint32_t)); + buffer = calloc(tex_width*(tex_height + 1), sizeof(uint32_t)); } SDL_UnlockMutex(free_buffer_mutex); locked_pixels = buffer; @@ -1362,14 +1414,14 @@ warning("Request for invalid framebuffer number %d\n", which); return NULL; } - void *pixels; - if (SDL_LockTexture(sdl_textures[which], NULL, &pixels, pitch) < 0) { + uint8_t *pixels; + if (SDL_LockTexture(sdl_textures[which], NULL, (void **)&pixels, pitch) < 0) { warning("Failed to lock texture: %s\n", SDL_GetError()); return NULL; } static uint8_t last; if (which <= FRAMEBUFFER_EVEN) { - locked_pixels = pixels; + locked_pixels = (uint32_t *)pixels; if (which == FRAMEBUFFER_EVEN) { pixels += *pitch; } @@ -1379,7 +1431,7 @@ } last = which; } - return pixels; + return (uint32_t *)pixels; #ifndef DISABLE_OPENGL } #endif @@ -1408,7 +1460,7 @@ static void process_framebuffer(uint32_t *buffer, uint8_t which, int width) { static uint8_t last; - if (!render_is_audio_sync() && which <= FRAMEBUFFER_EVEN && source_frame_count < 0) { + if (sync_src == SYNC_VIDEO && which <= FRAMEBUFFER_EVEN && source_frame_count < 0) { source_frame++; if (source_frame >= source_hz) { source_frame = 0; @@ -1464,7 +1516,7 @@ } } else { #endif - //TODO: Support run_on_audio_thread for render API framebuffers + //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers if (which <= FRAMEBUFFER_EVEN && last != which) { uint8_t *cur_dst = (uint8_t *)locked_pixels; uint8_t *cur_saved = (uint8_t *)texture_buf; @@ -1613,7 +1665,7 @@ void render_framebuffer_updated(uint8_t which, int width) { - if (run_on_audio_thread) { + if (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL) { SDL_LockMutex(frame_mutex); while (frame_queue_len == 4) { SDL_CondSignal(frame_ready); @@ -1651,25 +1703,29 @@ void render_video_loop(void) { - if (!run_on_audio_thread) { + if (sync_src != SYNC_AUDIO_THREAD && sync_src != SYNC_EXTERNAL) { return; } - SDL_PauseAudio(0); SDL_LockMutex(frame_mutex); for(;;) { - while (!frame_queue_len) + while (!frame_queue_len && SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) { SDL_CondWait(frame_ready, frame_mutex); } - for (int i = 0; i < frame_queue_len; i++) + while (frame_queue_len) { frame f = frame_queue[frame_queue_read++]; frame_queue_read &= 0x3; + frame_queue_len--; + SDL_UnlockMutex(frame_mutex); process_framebuffer(f.buffer, f.which, f.width); release_buffer(f.buffer); + SDL_LockMutex(frame_mutex); } - frame_queue_len = 0; + if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) { + break; + } } SDL_UnlockMutex(frame_mutex); @@ -1699,6 +1755,7 @@ glUniform1f(un_width, render_emulated_width()); glUniform1f(un_height, last_height); + glUniform2f(un_texsize, tex_width, tex_height); glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); @@ -1974,3 +2031,9 @@ } return 0xFF; } + +uint8_t render_create_thread(render_thread *thread, const char *name, render_thread_fun fun, void *data) +{ + *thread = SDL_CreateThread(fun, name, data); + return *thread != 0; +}