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);