Mercurial > repos > blastem
comparison render_sdl.c @ 2372:6099d4906c0c
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 13 Nov 2023 23:48:10 -0800 |
parents | 6bcc2ab01ac6 |
children | 1c09f5be285b |
comparison
equal
deleted
inserted
replaced
2371:1fe5afe263f3 | 2372:6099d4906c0c |
---|---|
157 mix_buf = NULL; | 157 mix_buf = NULL; |
158 } | 158 } |
159 */ | 159 */ |
160 } | 160 } |
161 | 161 |
162 static uint8_t audio_active; | |
162 void *render_new_audio_opaque(void) | 163 void *render_new_audio_opaque(void) |
163 { | 164 { |
164 return SDL_CreateCond(); | 165 return SDL_CreateCond(); |
165 } | 166 } |
166 | 167 |
169 SDL_DestroyCond(opaque); | 170 SDL_DestroyCond(opaque); |
170 } | 171 } |
171 | 172 |
172 void render_audio_created(audio_source *source) | 173 void render_audio_created(audio_source *source) |
173 { | 174 { |
175 audio_active = 1; | |
174 if (sync_src == SYNC_AUDIO) { | 176 if (sync_src == SYNC_AUDIO) { |
175 //SDL_PauseAudio acquires the audio device lock, which is held while the callback runs | 177 //SDL_PauseAudio acquires the audio device lock, which is held while the callback runs |
176 //since our callback can itself be stuck waiting on the audio_ready condition variable | 178 //since our callback can itself be stuck waiting on the audio_ready condition variable |
177 //calling SDL_PauseAudio(0) again for audio sources after the first can deadlock | 179 //calling SDL_PauseAudio(0) again for audio sources after the first can deadlock |
178 //fortunately SDL_GetAudioStatus does not acquire the lock so is safe to call here | 180 //fortunately SDL_GetAudioStatus does not acquire the lock so is safe to call here |
190 if (sync_src == SYNC_AUDIO) { | 192 if (sync_src == SYNC_AUDIO) { |
191 SDL_CondSignal(audio_ready); | 193 SDL_CondSignal(audio_ready); |
192 } | 194 } |
193 if (!remaining_sources && render_is_audio_sync()) { | 195 if (!remaining_sources && render_is_audio_sync()) { |
194 SDL_PauseAudio(1); | 196 SDL_PauseAudio(1); |
197 audio_active = 0; | |
195 if (sync_src == SYNC_AUDIO_THREAD) { | 198 if (sync_src == SYNC_AUDIO_THREAD) { |
196 SDL_CondSignal(frame_ready); | 199 SDL_CondSignal(frame_ready); |
197 } | 200 } |
198 } | 201 } |
199 } | 202 } |
200 | 203 |
201 void render_source_resumed(audio_source *src) | 204 void render_source_resumed(audio_source *src) |
202 { | 205 { |
206 audio_active = 1; | |
203 if (sync_src == SYNC_AUDIO) { | 207 if (sync_src == SYNC_AUDIO) { |
204 //SDL_PauseAudio acquires the audio device lock, which is held while the callback runs | 208 //SDL_PauseAudio acquires the audio device lock, which is held while the callback runs |
205 //since our callback can itself be stuck waiting on the audio_ready condition variable | 209 //since our callback can itself be stuck waiting on the audio_ready condition variable |
206 //calling SDL_PauseAudio(0) again for audio sources after the first can deadlock | 210 //calling SDL_PauseAudio(0) again for audio sources after the first can deadlock |
207 //fortunately SDL_GetAudioStatus does not acquire the lock so is safe to call here | 211 //fortunately SDL_GetAudioStatus does not acquire the lock so is safe to call here |
1584 last_width = width; | 1588 last_width = width; |
1585 uint32_t height = which <= FRAMEBUFFER_EVEN | 1589 uint32_t height = which <= FRAMEBUFFER_EVEN |
1586 ? (video_standard == VID_PAL ? 294 : 243) - (overscan_top[video_standard] + overscan_bot[video_standard]) | 1590 ? (video_standard == VID_PAL ? 294 : 243) - (overscan_top[video_standard] + overscan_bot[video_standard]) |
1587 : 240; | 1591 : 240; |
1588 FILE *screenshot_file = NULL; | 1592 FILE *screenshot_file = NULL; |
1589 uint32_t shot_height, shot_width; | |
1590 char *ext; | 1593 char *ext; |
1594 width -= overscan_left[video_standard] + overscan_right[video_standard]; | |
1591 if (screenshot_path && which == FRAMEBUFFER_ODD) { | 1595 if (screenshot_path && which == FRAMEBUFFER_ODD) { |
1592 screenshot_file = fopen(screenshot_path, "wb"); | 1596 screenshot_file = fopen(screenshot_path, "wb"); |
1593 if (screenshot_file) { | 1597 if (screenshot_file) { |
1594 #ifndef DISABLE_ZLIB | 1598 #ifndef DISABLE_ZLIB |
1595 ext = path_extension(screenshot_path); | 1599 ext = path_extension(screenshot_path); |
1598 } else { | 1602 } else { |
1599 warning("Failed to open screenshot file %s for writing\n", screenshot_path); | 1603 warning("Failed to open screenshot file %s for writing\n", screenshot_path); |
1600 } | 1604 } |
1601 free(screenshot_path); | 1605 free(screenshot_path); |
1602 screenshot_path = NULL; | 1606 screenshot_path = NULL; |
1603 shot_height = height; | |
1604 shot_width = width; | |
1605 } | 1607 } |
1606 interlaced = last != which; | 1608 interlaced = last != which; |
1607 width -= overscan_left[video_standard] + overscan_right[video_standard]; | 1609 buffer += overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; |
1608 #ifndef DISABLE_OPENGL | 1610 #ifndef DISABLE_OPENGL |
1609 if (render_gl && which <= FRAMEBUFFER_EVEN) { | 1611 if (render_gl && which <= FRAMEBUFFER_EVEN) { |
1610 SDL_GL_MakeCurrent(main_window, main_context); | 1612 SDL_GL_MakeCurrent(main_window, main_context); |
1611 glBindTexture(GL_TEXTURE_2D, textures[which]); | 1613 glBindTexture(GL_TEXTURE_2D, textures[which]); |
1612 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, GL_UNSIGNED_BYTE, buffer + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]); | 1614 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, GL_UNSIGNED_BYTE, buffer); |
1613 | 1615 |
1614 if (screenshot_file) { | 1616 if (screenshot_file) { |
1615 //properly supporting interlaced modes here is non-trivial, so only save the odd field for now | 1617 //properly supporting interlaced modes here is non-trivial, so only save the odd field for now |
1616 #ifndef DISABLE_ZLIB | 1618 #ifndef DISABLE_ZLIB |
1617 if (!strcasecmp(ext, "png")) { | 1619 if (!strcasecmp(ext, "png")) { |
1618 free(ext); | 1620 free(ext); |
1619 save_png(screenshot_file, buffer, shot_width, shot_height, LINEBUF_SIZE*sizeof(uint32_t)); | 1621 save_png(screenshot_file, buffer, width, height, LINEBUF_SIZE*sizeof(uint32_t)); |
1620 } else { | 1622 } else { |
1621 free(ext); | 1623 free(ext); |
1622 #endif | 1624 #endif |
1623 save_ppm(screenshot_file, buffer, shot_width, shot_height, LINEBUF_SIZE*sizeof(uint32_t)); | 1625 save_ppm(screenshot_file, buffer, width, height, LINEBUF_SIZE*sizeof(uint32_t)); |
1624 #ifndef DISABLE_ZLIB | 1626 #ifndef DISABLE_ZLIB |
1625 } | 1627 } |
1626 #endif | 1628 #endif |
1627 } | 1629 } |
1628 #ifndef DISABLE_ZLIB | 1630 #ifndef DISABLE_ZLIB |
1629 if (apng_file) { | 1631 if (apng_file) { |
1630 if (!apng) { | 1632 if (!apng) { |
1631 //TODO: more precise frame rate | 1633 //TODO: more precise frame rate |
1632 apng = start_apng(apng_file, width, height, video_standard == VID_PAL ? 50.0 : 60.0); | 1634 apng = start_apng(apng_file, width, height, video_standard == VID_PAL ? 50.0 : 60.0); |
1633 } | 1635 } |
1634 save_png24_frame( | 1636 save_png24_frame(apng_file, buffer, apng, width, height, LINEBUF_SIZE*sizeof(uint32_t)); |
1635 apng_file, | |
1636 buffer + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard], | |
1637 apng, width, height, LINEBUF_SIZE*sizeof(uint32_t) | |
1638 ); | |
1639 } | 1637 } |
1640 #endif | 1638 #endif |
1641 } else { | 1639 } else { |
1642 #endif | 1640 #endif |
1641 uint32_t shot_height = height; | |
1643 //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers | 1642 //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers |
1644 if (which <= FRAMEBUFFER_EVEN && last != which) { | 1643 if (which <= FRAMEBUFFER_EVEN && last != which) { |
1645 uint8_t *cur_dst = (uint8_t *)locked_pixels; | 1644 uint8_t *cur_dst = (uint8_t *)locked_pixels; |
1646 uint8_t *cur_saved = (uint8_t *)texture_buf; | 1645 uint8_t *cur_saved = (uint8_t *)texture_buf; |
1647 uint32_t dst_off = which == FRAMEBUFFER_EVEN ? 0 : locked_pitch; | 1646 uint32_t dst_off = which == FRAMEBUFFER_EVEN ? 0 : locked_pitch; |
1665 shot_pitch *= 2; | 1664 shot_pitch *= 2; |
1666 } | 1665 } |
1667 #ifndef DISABLE_ZLIB | 1666 #ifndef DISABLE_ZLIB |
1668 if (!strcasecmp(ext, "png")) { | 1667 if (!strcasecmp(ext, "png")) { |
1669 free(ext); | 1668 free(ext); |
1670 save_png(screenshot_file, locked_pixels, shot_width, shot_height, shot_pitch); | 1669 save_png(screenshot_file, locked_pixels, width, shot_height, shot_pitch); |
1671 } else { | 1670 } else { |
1672 free(ext); | 1671 free(ext); |
1673 #endif | 1672 #endif |
1674 save_ppm(screenshot_file, locked_pixels, shot_width, shot_height, shot_pitch); | 1673 save_ppm(screenshot_file, locked_pixels, width, shot_height, shot_pitch); |
1675 #ifndef DISABLE_ZLIB | 1674 #ifndef DISABLE_ZLIB |
1676 } | 1675 } |
1677 #endif | 1676 #endif |
1678 } | 1677 } |
1679 SDL_UnlockTexture(sdl_textures[which]); | 1678 SDL_UnlockTexture(sdl_textures[which]); |
1832 } | 1831 } |
1833 SDL_PauseAudio(0); | 1832 SDL_PauseAudio(0); |
1834 SDL_LockMutex(frame_mutex); | 1833 SDL_LockMutex(frame_mutex); |
1835 for(;;) | 1834 for(;;) |
1836 { | 1835 { |
1837 while (!frame_queue_len && SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) | 1836 while (!frame_queue_len && audio_active) |
1838 { | 1837 { |
1839 SDL_CondWait(frame_ready, frame_mutex); | 1838 SDL_CondWait(frame_ready, frame_mutex); |
1840 } | 1839 } |
1841 while (frame_queue_len) | 1840 while (frame_queue_len) |
1842 { | 1841 { |
1846 SDL_UnlockMutex(frame_mutex); | 1845 SDL_UnlockMutex(frame_mutex); |
1847 process_framebuffer(f.buffer, f.which, f.width); | 1846 process_framebuffer(f.buffer, f.which, f.width); |
1848 release_buffer(f.buffer); | 1847 release_buffer(f.buffer); |
1849 SDL_LockMutex(frame_mutex); | 1848 SDL_LockMutex(frame_mutex); |
1850 } | 1849 } |
1851 if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) { | 1850 if (!audio_active) { |
1852 break; | 1851 break; |
1853 } | 1852 } |
1854 } | 1853 } |
1855 | 1854 |
1856 SDL_UnlockMutex(frame_mutex); | 1855 SDL_UnlockMutex(frame_mutex); |