Mercurial > repos > blastem
comparison render_sdl.c @ 2693:46dba737b931
WIP Nuklear UI in VDP debug windows
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 19 Jun 2025 19:59:05 -0700 |
parents | 05915f01046d |
children | 84771c6e31c5 |
comparison
equal
deleted
inserted
replaced
2692:effbb52ab3f0 | 2693:46dba737b931 |
---|---|
32 | 32 |
33 #define MAX_EVENT_POLL_PER_FRAME 2 | 33 #define MAX_EVENT_POLL_PER_FRAME 2 |
34 | 34 |
35 | 35 |
36 typedef struct { | 36 typedef struct { |
37 SDL_Window *win; | 37 SDL_Window *win; |
38 SDL_Renderer *renderer; | 38 SDL_Renderer *renderer; |
39 SDL_Texture *sdl_texture; | 39 SDL_Texture *sdl_texture; |
40 SDL_Texture **static_images; | 40 SDL_Texture **static_images; |
41 window_close_handler on_close; | 41 window_close_handler on_close; |
42 ui_render_fun on_render; | |
43 event_handler on_event; | |
42 uint32_t width; | 44 uint32_t width; |
43 uint32_t height; | 45 uint32_t height; |
44 uint8_t num_static; | 46 uint8_t num_static; |
45 #ifndef DISABLE_OPENGL | 47 #ifndef DISABLE_OPENGL |
46 SDL_GLContext *gl_context; | 48 SDL_GLContext *gl_context; |
47 pixel_t *texture_buf; | 49 pixel_t *texture_buf; |
50 uint32_t orig_tex_width; | |
51 uint32_t orig_tex_height; | |
48 uint32_t tex_width; | 52 uint32_t tex_width; |
49 uint32_t tex_height; | 53 uint32_t tex_height; |
50 GLuint gl_texture[2]; | 54 GLuint gl_texture[2]; |
51 GLuint *gl_static_images; | 55 GLuint *gl_static_images; |
52 GLuint vshader; | 56 GLuint vshader; |
823 { | 827 { |
824 drag_drop_handler = handler; | 828 drag_drop_handler = handler; |
825 } | 829 } |
826 | 830 |
827 static event_handler custom_event_handler; | 831 static event_handler custom_event_handler; |
828 void render_set_event_handler(event_handler handler) | 832 void render_set_event_handler(uint8_t which, event_handler handler) |
829 { | 833 { |
830 custom_event_handler = handler; | 834 if (which < FRAMEBUFFER_USER_START) { |
835 custom_event_handler = handler; | |
836 } else { | |
837 extras[which - FRAMEBUFFER_USER_START].on_event = handler; | |
838 } | |
831 } | 839 } |
832 | 840 |
833 int render_find_joystick_index(SDL_JoystickID instanceID) | 841 int render_find_joystick_index(SDL_JoystickID instanceID) |
834 { | 842 { |
835 for (int i = 0; i < MAX_JOYSTICKS; i++) { | 843 for (int i = 0; i < MAX_JOYSTICKS; i++) { |
950 return ui * ui_scale_y + 0.5f; | 958 return ui * ui_scale_y + 0.5f; |
951 } | 959 } |
952 | 960 |
953 static int32_t handle_event(SDL_Event *event) | 961 static int32_t handle_event(SDL_Event *event) |
954 { | 962 { |
955 if (custom_event_handler) { | 963 SDL_Window *event_win = NULL; |
956 custom_event_handler(event); | |
957 } | |
958 switch (event->type) { | 964 switch (event->type) { |
959 case SDL_KEYDOWN: | 965 case SDL_KEYDOWN: |
960 handle_keydown(event->key.keysym.sym, scancode_map[event->key.keysym.scancode]); | 966 event_win = SDL_GetWindowFromID(event->key.windowID); |
967 if (event_win == main_window) { | |
968 handle_keydown(event->key.keysym.sym, scancode_map[event->key.keysym.scancode]); | |
969 } | |
961 break; | 970 break; |
962 case SDL_KEYUP: | 971 case SDL_KEYUP: |
963 handle_keyup(event->key.keysym.sym, scancode_map[event->key.keysym.scancode]); | 972 event_win = SDL_GetWindowFromID(event->key.windowID); |
973 if (event_win == main_window) { | |
974 handle_keyup(event->key.keysym.sym, scancode_map[event->key.keysym.scancode]); | |
975 } | |
964 break; | 976 break; |
965 case SDL_JOYBUTTONDOWN: | 977 case SDL_JOYBUTTONDOWN: |
978 event_win = main_window; | |
966 handle_joydown(render_find_joystick_index(event->jbutton.which), event->jbutton.button); | 979 handle_joydown(render_find_joystick_index(event->jbutton.which), event->jbutton.button); |
967 break; | 980 break; |
968 case SDL_JOYBUTTONUP: | 981 case SDL_JOYBUTTONUP: |
982 event_win = main_window; | |
969 handle_joyup(lock_joystick_index(render_find_joystick_index(event->jbutton.which), -1), event->jbutton.button); | 983 handle_joyup(lock_joystick_index(render_find_joystick_index(event->jbutton.which), -1), event->jbutton.button); |
970 break; | 984 break; |
971 case SDL_JOYHATMOTION: | 985 case SDL_JOYHATMOTION: |
986 event_win = main_window; | |
972 handle_joy_dpad(lock_joystick_index(render_find_joystick_index(event->jhat.which), -1), event->jhat.hat, event->jhat.value); | 987 handle_joy_dpad(lock_joystick_index(render_find_joystick_index(event->jhat.which), -1), event->jhat.hat, event->jhat.value); |
973 break; | 988 break; |
974 case SDL_JOYAXISMOTION: | 989 case SDL_JOYAXISMOTION: |
990 event_win = main_window; | |
975 handle_joy_axis(lock_joystick_index(render_find_joystick_index(event->jaxis.which), -1), event->jaxis.axis, event->jaxis.value); | 991 handle_joy_axis(lock_joystick_index(render_find_joystick_index(event->jaxis.which), -1), event->jaxis.axis, event->jaxis.value); |
976 break; | 992 break; |
977 case SDL_JOYDEVICEADDED: { | 993 case SDL_JOYDEVICEADDED: { |
978 int index = lowest_unused_joystick_index(); | 994 int index = lowest_unused_joystick_index(); |
979 if (index >= 0) { | 995 if (index >= 0) { |
1011 debug_message("Failed to find removed joystick with instance ID: %d\n", index); | 1027 debug_message("Failed to find removed joystick with instance ID: %d\n", index); |
1012 } | 1028 } |
1013 break; | 1029 break; |
1014 } | 1030 } |
1015 case SDL_MOUSEMOTION: | 1031 case SDL_MOUSEMOTION: |
1032 event_win = SDL_GetWindowFromID(event->motion.windowID); | |
1016 handle_mouse_moved(event->motion.which, event->motion.x * ui_scale_x + 0.5f, event->motion.y * ui_scale_y + 0.5f + overscan_top[video_standard], event->motion.xrel, event->motion.yrel); | 1033 handle_mouse_moved(event->motion.which, event->motion.x * ui_scale_x + 0.5f, event->motion.y * ui_scale_y + 0.5f + overscan_top[video_standard], event->motion.xrel, event->motion.yrel); |
1017 break; | 1034 break; |
1018 case SDL_MOUSEBUTTONDOWN: | 1035 case SDL_MOUSEBUTTONDOWN: |
1036 event_win = SDL_GetWindowFromID(event->button.windowID); | |
1019 handle_mousedown(event->button.which, event->button.button); | 1037 handle_mousedown(event->button.which, event->button.button); |
1020 break; | 1038 break; |
1021 case SDL_MOUSEBUTTONUP: | 1039 case SDL_MOUSEBUTTONUP: |
1040 event_win = SDL_GetWindowFromID(event->button.windowID); | |
1022 handle_mouseup(event->button.which, event->button.button); | 1041 handle_mouseup(event->button.which, event->button.button); |
1042 break; | |
1043 case SDL_MOUSEWHEEL: | |
1044 event_win = SDL_GetWindowFromID(event->wheel.windowID); | |
1045 break; | |
1046 case SDL_FINGERMOTION: | |
1047 case SDL_FINGERDOWN: | |
1048 case SDL_FINGERUP: | |
1049 event_win = SDL_GetWindowFromID(event->tfinger.windowID); | |
1023 break; | 1050 break; |
1024 case SDL_WINDOWEVENT: | 1051 case SDL_WINDOWEVENT: |
1025 switch (event->window.event) | 1052 switch (event->window.event) |
1026 { | 1053 { |
1027 case SDL_WINDOWEVENT_SIZE_CHANGED: | 1054 case SDL_WINDOWEVENT_SIZE_CHANGED: |
1028 if (!main_window) { | 1055 if (!main_window || SDL_GetWindowFromID(event->window.windowID) != main_window) { |
1029 break; | 1056 break; |
1030 } | 1057 } |
1031 need_ui_fb_resize = 1; | 1058 need_ui_fb_resize = 1; |
1032 #ifndef DISABLE_OPENGL | 1059 #ifndef DISABLE_OPENGL |
1033 if (render_gl) { | 1060 if (render_gl) { |
1074 } | 1101 } |
1075 } | 1102 } |
1076 break; | 1103 break; |
1077 } | 1104 } |
1078 break; | 1105 break; |
1106 case SDL_TEXTEDITING: | |
1107 event_win = SDL_GetWindowFromID(event->edit.windowID); | |
1108 break; | |
1109 #if SDL_VERSION_ATLEAST(2, 0, 22) | |
1110 case SDL_TEXTEDITING_EXT: | |
1111 event_win = SDL_GetWindowFromID(event->editExt.windowID); | |
1112 break; | |
1113 #endif | |
1114 case SDL_TEXTINPUT: | |
1115 event_win = SDL_GetWindowFromID(event->text.windowID); | |
1116 break; | |
1079 case SDL_DROPFILE: | 1117 case SDL_DROPFILE: |
1080 if (drag_drop_handler) { | 1118 if (drag_drop_handler) { |
1081 drag_drop_handler(strdup(event->drop.file)); | 1119 drag_drop_handler(strdup(event->drop.file)); |
1082 } | 1120 } |
1083 SDL_free(event->drop.file); | 1121 SDL_free(event->drop.file); |
1084 break; | 1122 break; |
1085 case SDL_QUIT: | 1123 case SDL_QUIT: |
1086 puts(""); | 1124 puts(""); |
1087 exit(0); | 1125 exit(0); |
1126 } | |
1127 if (event_win) { | |
1128 if (event_win == main_window) { | |
1129 if (custom_event_handler) { | |
1130 custom_event_handler(FRAMEBUFFER_UI, event); | |
1131 } | |
1132 } else { | |
1133 for (uint8_t i = 0; i < num_extras; i++) | |
1134 { | |
1135 if (extras[i].win == event_win) { | |
1136 if (extras[i].on_event) { | |
1137 extras[i].on_event(i + FRAMEBUFFER_USER_START, event); | |
1138 } | |
1139 break; | |
1140 } | |
1141 } | |
1142 } | |
1088 } | 1143 } |
1089 return 0; | 1144 return 0; |
1090 } | 1145 } |
1091 | 1146 |
1092 static void drain_events() | 1147 static void drain_events() |
1544 if (!was_paused) { | 1599 if (!was_paused) { |
1545 SDL_PauseAudio(0); | 1600 SDL_PauseAudio(0); |
1546 } | 1601 } |
1547 } | 1602 } |
1548 | 1603 |
1549 SDL_Window *render_get_window(void) | 1604 SDL_Window *render_get_window(uint8_t which) |
1550 { | 1605 { |
1606 SDL_Window *ret = which < FRAMEBUFFER_USER_START ? main_window : extras[which - FRAMEBUFFER_USER_START].win; | |
1551 #ifndef DISABLE_OPENGL | 1607 #ifndef DISABLE_OPENGL |
1552 if (render_gl) { | 1608 if (render_gl) { |
1553 SDL_GL_MakeCurrent(main_window, main_context); | 1609 SDL_GL_MakeCurrent(ret, which < FRAMEBUFFER_USER_START ? main_context : extras[which - FRAMEBUFFER_USER_START].gl_context); |
1554 } | 1610 } |
1555 #endif | 1611 #endif |
1556 return main_window; | 1612 return ret; |
1557 } | 1613 } |
1558 | 1614 |
1559 uint32_t render_audio_syncs_per_sec(void) | 1615 uint32_t render_audio_syncs_per_sec(void) |
1560 { | 1616 { |
1561 //sync samples with audio thread approximately every 8 lines when doing sync to video | 1617 //sync samples with audio thread approximately every 8 lines when doing sync to video |
1660 { | 1716 { |
1661 fprintf(stderr, "GL Message: %d, %d, %d - %s\n", source, type, severity, message); | 1717 fprintf(stderr, "GL Message: %d, %d, %d - %s\n", source, type, severity, message); |
1662 } | 1718 } |
1663 #endif | 1719 #endif |
1664 | 1720 |
1665 uint8_t render_create_window(char *caption, uint32_t width, uint32_t height, window_close_handler close_handler) | 1721 uint8_t render_create_window_tex(char *caption, uint32_t width, uint32_t height, uint32_t tex_width, uint32_t tex_height, window_close_handler close_handler) |
1666 { | 1722 { |
1667 uint8_t win_idx = 0xFF; | 1723 uint8_t win_idx = 0xFF; |
1668 for (int i = 0; i < num_extras; i++) | 1724 for (int i = 0; i < num_extras; i++) |
1669 { | 1725 { |
1670 if (!extras[i].win) { | 1726 if (!extras[i].win) { |
1716 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 1772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 1773 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1718 if (i) { | 1774 if (i) { |
1719 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, SRC_TYPE, extras[win_idx].color); | 1775 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, SRC_TYPE, extras[win_idx].color); |
1720 } else { | 1776 } else { |
1721 extras[win_idx].tex_width = width; | 1777 extras[win_idx].tex_width = extras[win_idx].orig_tex_width = tex_width; |
1722 extras[win_idx].tex_height = height; | 1778 extras[win_idx].tex_height = extras[win_idx].orig_tex_height = tex_height; |
1723 char *npot_textures = tern_find_path_default(config, "video\0npot_textures\0", (tern_val){.ptrval = "off"}, TVAL_PTR).ptrval; | 1779 char *npot_textures = tern_find_path_default(config, "video\0npot_textures\0", (tern_val){.ptrval = "off"}, TVAL_PTR).ptrval; |
1724 if (strcmp(npot_textures, "on")) { | 1780 if (strcmp(npot_textures, "on")) { |
1725 extras[win_idx].tex_width = nearest_pow2(width); | 1781 extras[win_idx].tex_width = nearest_pow2(tex_width); |
1726 extras[win_idx].tex_height = nearest_pow2(height); | 1782 extras[win_idx].tex_height = nearest_pow2(tex_height); |
1727 } | 1783 } |
1728 extras[win_idx].texture_buf = calloc(PITCH_PIXEL_T(extras[win_idx].tex_width) * extras[win_idx].tex_height, sizeof(pixel_t)); | 1784 extras[win_idx].texture_buf = calloc(PITCH_PIXEL_T(extras[win_idx].tex_width) * extras[win_idx].tex_height, sizeof(pixel_t)); |
1729 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, extras[win_idx].tex_width, extras[win_idx].tex_height, 0, SRC_FORMAT, SRC_TYPE, extras[win_idx].texture_buf); | 1785 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, extras[win_idx].tex_width, extras[win_idx].tex_height, 0, SRC_FORMAT, SRC_TYPE, extras[win_idx].texture_buf); |
1730 } | 1786 } |
1731 } | 1787 } |
1760 #endif | 1816 #endif |
1761 extras[win_idx].renderer = SDL_CreateRenderer(extras[win_idx].win, -1, SDL_RENDERER_ACCELERATED); | 1817 extras[win_idx].renderer = SDL_CreateRenderer(extras[win_idx].win, -1, SDL_RENDERER_ACCELERATED); |
1762 if (!extras[win_idx].renderer) { | 1818 if (!extras[win_idx].renderer) { |
1763 goto fail_renderer; | 1819 goto fail_renderer; |
1764 } | 1820 } |
1765 extras[win_idx].sdl_texture = SDL_CreateTexture(extras[win_idx].renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height); | 1821 extras[win_idx].sdl_texture = SDL_CreateTexture(extras[win_idx].renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, tex_width, tex_height); |
1766 if (!extras[win_idx].sdl_texture) { | 1822 if (!extras[win_idx].sdl_texture) { |
1767 goto fail_texture; | 1823 goto fail_texture; |
1768 } | 1824 } |
1769 #ifndef DISABLE_OPENGL | 1825 #ifndef DISABLE_OPENGL |
1770 } | 1826 } |
1777 fail_renderer: | 1833 fail_renderer: |
1778 SDL_DestroyWindow(extras[win_idx].win); | 1834 SDL_DestroyWindow(extras[win_idx].win); |
1779 fail_window: | 1835 fail_window: |
1780 return 0; | 1836 return 0; |
1781 } | 1837 } |
1838 | |
1839 uint8_t render_create_window(char *caption, uint32_t width, uint32_t height, window_close_handler close_handler) | |
1840 { | |
1841 return render_create_window_tex(caption, width, height, width, height, close_handler); | |
1842 } | |
1843 | |
1844 #ifndef DISABLE_OPENGL | |
1845 uint32_t render_get_window_texture(uint8_t which) | |
1846 { | |
1847 return extras[which - FRAMEBUFFER_USER_START].gl_texture[0]; | |
1848 } | |
1849 #endif | |
1782 | 1850 |
1783 void render_destroy_window(uint8_t which) | 1851 void render_destroy_window(uint8_t which) |
1784 { | 1852 { |
1785 uint8_t win_idx = which - FRAMEBUFFER_USER_START; | 1853 uint8_t win_idx = which - FRAMEBUFFER_USER_START; |
1786 if (extras[win_idx].renderer) { | 1854 if (extras[win_idx].renderer) { |
2031 if (render_gl && which <= FRAMEBUFFER_EVEN) { | 2099 if (render_gl && which <= FRAMEBUFFER_EVEN) { |
2032 *pitch = PITCH_BYTES(LINEBUF_SIZE); | 2100 *pitch = PITCH_BYTES(LINEBUF_SIZE); |
2033 return texture_buf; | 2101 return texture_buf; |
2034 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { | 2102 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { |
2035 uint8_t win_idx = which - FRAMEBUFFER_USER_START; | 2103 uint8_t win_idx = which - FRAMEBUFFER_USER_START; |
2036 *pitch = PITCH_BYTES(extras[win_idx].width); | 2104 *pitch = PITCH_BYTES(extras[win_idx].tex_width); |
2037 return extras[win_idx].texture_buf; | 2105 return extras[win_idx].texture_buf; |
2038 } else { | 2106 } else { |
2039 #endif | 2107 #endif |
2040 if (which == FRAMEBUFFER_UI && !sdl_textures[which]) { | 2108 if (which == FRAMEBUFFER_UI && !sdl_textures[which]) { |
2041 sdl_textures[which] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, main_width, main_height); | 2109 sdl_textures[which] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, main_width, main_height); |
2161 #endif | 2229 #endif |
2162 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { | 2230 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { |
2163 uint8_t win_idx = which - FRAMEBUFFER_USER_START; | 2231 uint8_t win_idx = which - FRAMEBUFFER_USER_START; |
2164 SDL_GL_MakeCurrent(extras[win_idx].win, extras[win_idx].gl_context); | 2232 SDL_GL_MakeCurrent(extras[win_idx].win, extras[win_idx].gl_context); |
2165 glBindTexture(GL_TEXTURE_2D, extras[win_idx].gl_texture[0]); | 2233 glBindTexture(GL_TEXTURE_2D, extras[win_idx].gl_texture[0]); |
2166 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extras[win_idx].width, extras[win_idx].height, SRC_FORMAT, SRC_TYPE, buffer); | 2234 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extras[win_idx].orig_tex_width, extras[win_idx].orig_tex_height, SRC_FORMAT, SRC_TYPE, buffer); |
2167 } else { | 2235 } else { |
2168 #endif | 2236 #endif |
2169 uint32_t shot_height = height; | 2237 uint32_t shot_height = height; |
2170 //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers | 2238 //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers |
2171 if (which <= FRAMEBUFFER_EVEN && last_field != which) { | 2239 if (which <= FRAMEBUFFER_EVEN && last_field != which) { |
2228 } | 2296 } |
2229 #ifndef DISABLE_OPENGL | 2297 #ifndef DISABLE_OPENGL |
2230 else { | 2298 else { |
2231 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | 2299 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
2232 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 2300 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
2233 | 2301 if (extras[win_idx].on_render) { |
2234 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]); | 2302 extras[win_idx].on_render(); |
2235 extra_draw_quad( | 2303 } else { |
2236 extras + win_idx, | 2304 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]); |
2237 extras[win_idx].gl_texture[0], | 2305 extra_draw_quad( |
2238 (float)extras[win_idx].width / (float)extras[win_idx].tex_width, | 2306 extras + win_idx, |
2239 (float)extras[win_idx].height / (float)extras[win_idx].tex_height | 2307 extras[win_idx].gl_texture[0], |
2240 ); | 2308 (float)extras[win_idx].orig_tex_width / (float)extras[win_idx].tex_width, |
2309 (float)extras[win_idx].orig_tex_height / (float)extras[win_idx].tex_height | |
2310 ); | |
2311 } | |
2241 | 2312 |
2242 SDL_GL_SwapWindow(extras[win_idx].win); | 2313 SDL_GL_SwapWindow(extras[win_idx].win); |
2243 } | 2314 } |
2244 #endif | 2315 #endif |
2245 } | 2316 } |
2333 frame frame_queue[4]; | 2404 frame frame_queue[4]; |
2334 int frame_queue_len, frame_queue_read, frame_queue_write; | 2405 int frame_queue_len, frame_queue_read, frame_queue_write; |
2335 | 2406 |
2336 void render_framebuffer_updated(uint8_t which, int width) | 2407 void render_framebuffer_updated(uint8_t which, int width) |
2337 { | 2408 { |
2338 if (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL) { | 2409 if (which < FRAMEBUFFER_USER_START && (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL)) { |
2339 SDL_LockMutex(frame_mutex); | 2410 SDL_LockMutex(frame_mutex); |
2340 while (frame_queue_len == 4) { | 2411 while (frame_queue_len == 4) { |
2341 SDL_CondSignal(frame_ready); | 2412 SDL_CondSignal(frame_ready); |
2342 SDL_UnlockMutex(frame_mutex); | 2413 SDL_UnlockMutex(frame_mutex); |
2343 SDL_Delay(1); | 2414 SDL_Delay(1); |
2415 | 2486 |
2416 SDL_UnlockMutex(frame_mutex); | 2487 SDL_UnlockMutex(frame_mutex); |
2417 } | 2488 } |
2418 | 2489 |
2419 static ui_render_fun render_ui; | 2490 static ui_render_fun render_ui; |
2420 void render_set_ui_render_fun(ui_render_fun fun) | 2491 void render_set_ui_render_fun(uint8_t which, ui_render_fun fun) |
2421 { | 2492 { |
2422 render_ui = fun; | 2493 if (which < FRAMEBUFFER_USER_START) { |
2494 render_ui = fun; | |
2495 } else { | |
2496 extras[which - FRAMEBUFFER_USER_START].on_render = fun; | |
2497 } | |
2423 } | 2498 } |
2424 | 2499 |
2425 static ui_render_fun frame_presented; | 2500 static ui_render_fun frame_presented; |
2426 void render_set_frame_presented_fun(ui_render_fun fun) | 2501 void render_set_frame_presented_fun(ui_render_fun fun) |
2427 { | 2502 { |