Mercurial > repos > blastem
comparison render_sdl.c @ 2685:da2e06c42d16
Add a compile-time flag to use RGB565 instead of ABGR/ARGB
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 30 Mar 2025 00:06:53 -0700 |
parents | 69c1093f8726 |
children | 05915f01046d |
comparison
equal
deleted
inserted
replaced
2684:c649bcc18487 | 2685:da2e06c42d16 |
---|---|
42 uint32_t width; | 42 uint32_t width; |
43 uint32_t height; | 43 uint32_t height; |
44 uint8_t num_static; | 44 uint8_t num_static; |
45 #ifndef DISABLE_OPENGL | 45 #ifndef DISABLE_OPENGL |
46 SDL_GLContext *gl_context; | 46 SDL_GLContext *gl_context; |
47 uint32_t *texture_buf; | 47 pixel_t *texture_buf; |
48 uint32_t tex_width; | 48 uint32_t tex_width; |
49 uint32_t tex_height; | 49 uint32_t tex_height; |
50 GLuint gl_texture[2]; | 50 GLuint gl_texture[2]; |
51 GLuint *gl_static_images; | 51 GLuint *gl_static_images; |
52 GLuint vshader; | 52 GLuint vshader; |
92 }; | 92 }; |
93 | 93 |
94 static uint8_t sync_src; | 94 static uint8_t sync_src; |
95 static uint32_t min_buffered; | 95 static uint32_t min_buffered; |
96 | 96 |
97 uint32_t **frame_buffers; | 97 pixel_t **frame_buffers; |
98 uint32_t num_buffers; | 98 uint32_t num_buffers; |
99 uint32_t buffer_storage; | 99 uint32_t buffer_storage; |
100 | 100 |
101 uint32_t render_min_buffered(void) | 101 uint32_t render_min_buffered(void) |
102 { | 102 { |
337 uint8_t render_fullscreen(void) | 337 uint8_t render_fullscreen(void) |
338 { | 338 { |
339 return is_fullscreen; | 339 return is_fullscreen; |
340 } | 340 } |
341 | 341 |
342 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) | 342 pixel_t render_map_color(uint8_t r, uint8_t g, uint8_t b) |
343 { | 343 { |
344 #ifdef USE_RGB565 | |
345 return r << 8 & 0xF800 | g << 3 & 0x07E0 | b >> 3; | |
346 #else | |
344 #ifdef USE_GLES | 347 #ifdef USE_GLES |
345 return 255UL << 24 | b << 16 | g << 8 | r; | 348 return 255UL << 24 | b << 16 | g << 8 | r; |
346 #else | 349 #else |
347 return 255UL << 24 | r << 16 | g << 8 | b; | 350 return 255UL << 24 | r << 16 | g << 8 | b; |
351 #endif | |
348 #endif | 352 #endif |
349 } | 353 } |
350 | 354 |
351 static uint8_t external_sync; | 355 static uint8_t external_sync; |
352 void render_set_external_sync(uint8_t ext_sync_on) | 356 void render_set_external_sync(uint8_t ext_sync_on) |
455 } | 459 } |
456 return ret; | 460 return ret; |
457 } | 461 } |
458 #endif | 462 #endif |
459 | 463 |
460 static uint32_t texture_buf[512 * 513]; | 464 static pixel_t texture_buf[512 * 513]; |
461 #ifdef DISABLE_OPENGL | 465 #ifdef DISABLE_OPENGL |
466 #ifdef USE_RGB565 | |
467 #define RENDER_FORMAT SDL_PIXELFORMAT_RGB565 | |
468 #else | |
462 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 | 469 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 |
463 #else | 470 #endif |
471 #else //DISABLE_OPENGL | |
472 #ifdef USE_RGB565 | |
473 #define INTERNAL_FORMAT GL_RGB | |
474 #define SRC_FORMAT GL_RGB | |
475 #define SRC_TYPE GL_UNSIGNED_SHORT_5_6_5 | |
476 #define RENDER_FORMAT SDL_PIXELFORMAT_RGB565 | |
477 #else //USE_RGB565 | |
478 #define SRC_TYPE GL_UNSIGNED_BYTE | |
464 #ifdef USE_GLES | 479 #ifdef USE_GLES |
465 #define INTERNAL_FORMAT GL_RGBA | 480 #define INTERNAL_FORMAT GL_RGBA |
466 #define SRC_FORMAT GL_RGBA | 481 #define SRC_FORMAT GL_RGBA |
467 #define RENDER_FORMAT SDL_PIXELFORMAT_ABGR8888 | 482 #define RENDER_FORMAT SDL_PIXELFORMAT_ABGR8888 |
468 #else | 483 #else //USE_GLES |
469 #define INTERNAL_FORMAT GL_RGBA8 | 484 #define INTERNAL_FORMAT GL_RGBA8 |
470 #define SRC_FORMAT GL_BGRA | 485 #define SRC_FORMAT GL_BGRA |
471 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 | 486 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 |
472 #endif | 487 #endif //USE_GLES |
488 #endif //USE_RGB565 | |
489 | |
490 #ifdef USE_GLES | |
491 #define SRC_FORMAT32 GL_RGBA | |
492 #else | |
493 #define SRC_FORMAT32 GL_BGRA | |
494 #endif | |
495 | |
473 static void gl_setup() | 496 static void gl_setup() |
474 { | 497 { |
475 tern_val def = {.ptrval = "linear"}; | 498 tern_val def = {.ptrval = "linear"}; |
476 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval; | 499 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval; |
477 GLint filter = strcmp(scaling, "linear") ? GL_NEAREST : GL_LINEAR; | 500 GLint filter = strcmp(scaling, "linear") ? GL_NEAREST : GL_LINEAR; |
492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); | 515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); |
493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 516 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
494 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
495 if (i < 2) { | 518 if (i < 2) { |
496 //TODO: Fixme for PAL + invalid display mode | 519 //TODO: Fixme for PAL + invalid display mode |
497 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, tex_width, tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf); | 520 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, tex_width, tex_height, 0, SRC_FORMAT, SRC_TYPE, texture_buf); |
498 } else { | 521 } else { |
499 uint32_t blank = 255UL << 24; | 522 pixel_t blank = render_map_color(0, 0, 0); |
500 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, &blank); | 523 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, SRC_TYPE, &blank); |
501 } | 524 } |
502 } | 525 } |
503 glGenBuffers(2, buffers); | 526 glGenBuffers(2, buffers); |
504 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); | 527 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); |
505 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); | 528 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); |
536 glDeleteShader(vshader); | 559 glDeleteShader(vshader); |
537 glDeleteShader(fshader); | 560 glDeleteShader(fshader); |
538 glDeleteBuffers(2, buffers); | 561 glDeleteBuffers(2, buffers); |
539 glDeleteTextures(3, textures); | 562 glDeleteTextures(3, textures); |
540 } | 563 } |
541 #endif | 564 #endif //DISABLE_OPENGL |
542 | 565 |
543 static uint8_t texture_init; | 566 static uint8_t texture_init; |
544 static void render_alloc_surfaces() | 567 static void render_alloc_surfaces() |
545 { | 568 { |
546 if (texture_init) { | 569 if (texture_init) { |
1188 if (!num_buffers && (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL)) { | 1211 if (!num_buffers && (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL)) { |
1189 frame_mutex = SDL_CreateMutex(); | 1212 frame_mutex = SDL_CreateMutex(); |
1190 free_buffer_mutex = SDL_CreateMutex(); | 1213 free_buffer_mutex = SDL_CreateMutex(); |
1191 frame_ready = SDL_CreateCond(); | 1214 frame_ready = SDL_CreateCond(); |
1192 buffer_storage = 4; | 1215 buffer_storage = 4; |
1193 frame_buffers = calloc(buffer_storage, sizeof(uint32_t*)); | 1216 frame_buffers = calloc(buffer_storage, sizeof(pixel_t*)); |
1194 frame_buffers[0] = texture_buf; | 1217 frame_buffers[0] = texture_buf; |
1195 num_buffers = 1; | 1218 num_buffers = 1; |
1196 } | 1219 } |
1197 | 1220 |
1198 const char *vsync; | 1221 const char *vsync; |
1686 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 1709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
1687 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 1710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
1688 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 1711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1689 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 1712 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1690 if (i) { | 1713 if (i) { |
1691 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, extras[win_idx].color); | 1714 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, SRC_TYPE, extras[win_idx].color); |
1692 } else { | 1715 } else { |
1693 extras[win_idx].tex_width = width; | 1716 extras[win_idx].tex_width = width; |
1694 extras[win_idx].tex_height = height; | 1717 extras[win_idx].tex_height = height; |
1695 char *npot_textures = tern_find_path_default(config, "video\0npot_textures\0", (tern_val){.ptrval = "off"}, TVAL_PTR).ptrval; | 1718 char *npot_textures = tern_find_path_default(config, "video\0npot_textures\0", (tern_val){.ptrval = "off"}, TVAL_PTR).ptrval; |
1696 if (strcmp(npot_textures, "on")) { | 1719 if (strcmp(npot_textures, "on")) { |
1697 extras[win_idx].tex_width = nearest_pow2(width); | 1720 extras[win_idx].tex_width = nearest_pow2(width); |
1698 extras[win_idx].tex_height = nearest_pow2(height); | 1721 extras[win_idx].tex_height = nearest_pow2(height); |
1699 } | 1722 } |
1700 extras[win_idx].texture_buf = calloc(extras[win_idx].tex_width * extras[win_idx].tex_height, sizeof(uint32_t)); | 1723 extras[win_idx].texture_buf = calloc(PITCH_PIXEL_T(extras[win_idx].tex_width) * extras[win_idx].tex_height, sizeof(pixel_t)); |
1701 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, extras[win_idx].tex_width, extras[win_idx].tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, extras[win_idx].texture_buf); | 1724 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); |
1702 } | 1725 } |
1703 } | 1726 } |
1704 glGenBuffers(3, extras[win_idx].gl_buffers); | 1727 glGenBuffers(3, extras[win_idx].gl_buffers); |
1705 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]); | 1728 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]); |
1706 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data_default), vertex_data_default, GL_STATIC_DRAW); | 1729 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data_default), vertex_data_default, GL_STATIC_DRAW); |
1874 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 1897 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
1875 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 1898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
1876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 1899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1877 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 1900 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1878 //TODO: maybe make this respect the npot texture setting? | 1901 //TODO: maybe make this respect the npot texture setting? |
1879 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, width, height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, pixels); | 1902 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, width, height, 0, SRC_FORMAT32, GL_UNSIGNED_BYTE, pixels); |
1880 } else | 1903 } else |
1881 #endif | 1904 #endif |
1882 { | 1905 { |
1883 extra->static_images[img_index] = SDL_CreateTexture(extra->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height); | 1906 extra->static_images[img_index] = SDL_CreateTexture(extra->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height); |
1884 SDL_UpdateTexture(extra->static_images[img_index], NULL, pixels, sizeof(uint32_t) * width); | 1907 SDL_UpdateTexture(extra->static_images[img_index], NULL, pixels, sizeof(pixel_t) * width); |
1885 } | 1908 } |
1886 free(pixels); | 1909 free(pixels); |
1887 return img_index; | 1910 return img_index; |
1888 } | 1911 } |
1889 | 1912 |
1961 extra_update_verts(extra, x, y, width, height); | 1984 extra_update_verts(extra, x, y, width, height); |
1962 extra->color[0] = b; | 1985 extra->color[0] = b; |
1963 extra->color[1] = g; | 1986 extra->color[1] = g; |
1964 extra->color[2] = r; | 1987 extra->color[2] = r; |
1965 glBindTexture(GL_TEXTURE_2D, extra->gl_texture[1]); | 1988 glBindTexture(GL_TEXTURE_2D, extra->gl_texture[1]); |
1966 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, SRC_FORMAT, GL_UNSIGNED_BYTE, extra->color); | 1989 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, SRC_FORMAT, SRC_TYPE, extra->color); |
1967 extra_draw_quad(extra, extra->gl_texture[1], 1.0f, 1.0f); | 1990 extra_draw_quad(extra, extra->gl_texture[1], 1.0f, 1.0f); |
1968 } | 1991 } |
1969 #endif | 1992 #endif |
1970 } | 1993 } |
1971 | 1994 |
1980 SDL_GL_SwapWindow(extras[win_idx].win); | 2003 SDL_GL_SwapWindow(extras[win_idx].win); |
1981 } | 2004 } |
1982 #endif | 2005 #endif |
1983 } | 2006 } |
1984 | 2007 |
1985 uint32_t *locked_pixels; | 2008 pixel_t *locked_pixels; |
1986 uint32_t locked_pitch; | 2009 uint32_t locked_pitch; |
1987 uint32_t *render_get_framebuffer(uint8_t which, int *pitch) | 2010 pixel_t *render_get_framebuffer(uint8_t which, int *pitch) |
1988 { | 2011 { |
1989 if (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL) { | 2012 if (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL) { |
1990 *pitch = LINEBUF_SIZE * sizeof(uint32_t); | 2013 *pitch = PITCH_BYTES(LINEBUF_SIZE); |
1991 uint32_t *buffer; | 2014 pixel_t *buffer; |
1992 SDL_LockMutex(free_buffer_mutex); | 2015 SDL_LockMutex(free_buffer_mutex); |
1993 if (num_buffers) { | 2016 if (num_buffers) { |
1994 buffer = frame_buffers[--num_buffers]; | 2017 buffer = frame_buffers[--num_buffers]; |
1995 } else { | 2018 } else { |
1996 buffer = calloc(tex_width*(tex_height + 1), sizeof(uint32_t)); | 2019 buffer = calloc(tex_width*(tex_height + 1), sizeof(pixel_t)); |
1997 } | 2020 } |
1998 SDL_UnlockMutex(free_buffer_mutex); | 2021 SDL_UnlockMutex(free_buffer_mutex); |
1999 locked_pixels = buffer; | 2022 locked_pixels = buffer; |
2000 return buffer; | 2023 return buffer; |
2001 } | 2024 } |
2002 #ifndef DISABLE_OPENGL | 2025 #ifndef DISABLE_OPENGL |
2003 if (render_gl && which <= FRAMEBUFFER_EVEN) { | 2026 if (render_gl && which <= FRAMEBUFFER_EVEN) { |
2004 *pitch = LINEBUF_SIZE * sizeof(uint32_t); | 2027 *pitch = PITCH_BYTES(LINEBUF_SIZE); |
2005 return texture_buf; | 2028 return texture_buf; |
2006 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { | 2029 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { |
2007 uint8_t win_idx = which - FRAMEBUFFER_USER_START; | 2030 uint8_t win_idx = which - FRAMEBUFFER_USER_START; |
2008 *pitch = extras[win_idx].width * sizeof(uint32_t); | 2031 *pitch = PITCH_BYTES(extras[win_idx].width); |
2009 return extras[win_idx].texture_buf; | 2032 return extras[win_idx].texture_buf; |
2010 } else { | 2033 } else { |
2011 #endif | 2034 #endif |
2012 if (which == FRAMEBUFFER_UI && !sdl_textures[which]) { | 2035 if (which == FRAMEBUFFER_UI && !sdl_textures[which]) { |
2013 sdl_textures[which] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, main_width, main_height); | 2036 sdl_textures[which] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, main_width, main_height); |
2028 warning("Failed to lock texture: %s\n", SDL_GetError()); | 2051 warning("Failed to lock texture: %s\n", SDL_GetError()); |
2029 return NULL; | 2052 return NULL; |
2030 } | 2053 } |
2031 static uint8_t last; | 2054 static uint8_t last; |
2032 if (which <= FRAMEBUFFER_EVEN) { | 2055 if (which <= FRAMEBUFFER_EVEN) { |
2033 locked_pixels = (uint32_t *)pixels; | 2056 locked_pixels = (pixel_t *)pixels; |
2034 if (which == FRAMEBUFFER_EVEN) { | 2057 if (which == FRAMEBUFFER_EVEN) { |
2035 pixels += *pitch; | 2058 pixels += *pitch; |
2036 } | 2059 } |
2037 locked_pitch = *pitch; | 2060 locked_pitch = *pitch; |
2038 if (which != last) { | 2061 if (which != last) { |
2039 *pitch *= 2; | 2062 *pitch *= 2; |
2040 } | 2063 } |
2041 last = which; | 2064 last = which; |
2042 } | 2065 } |
2043 return (uint32_t *)pixels; | 2066 return (pixel_t *)pixels; |
2044 #ifndef DISABLE_OPENGL | 2067 #ifndef DISABLE_OPENGL |
2045 } | 2068 } |
2046 #endif | 2069 #endif |
2047 } | 2070 } |
2048 | 2071 |
2049 static void release_buffer(uint32_t *buffer) | 2072 static void release_buffer(pixel_t *buffer) |
2050 { | 2073 { |
2051 SDL_LockMutex(free_buffer_mutex); | 2074 SDL_LockMutex(free_buffer_mutex); |
2052 if (num_buffers == buffer_storage) { | 2075 if (num_buffers == buffer_storage) { |
2053 buffer_storage *= 2; | 2076 buffer_storage *= 2; |
2054 frame_buffers = realloc(frame_buffers, sizeof(uint32_t*)*buffer_storage); | 2077 frame_buffers = realloc(frame_buffers, sizeof(pixel_t*)*buffer_storage); |
2055 } | 2078 } |
2056 frame_buffers[num_buffers++] = buffer; | 2079 frame_buffers[num_buffers++] = buffer; |
2057 SDL_UnlockMutex(free_buffer_mutex); | 2080 SDL_UnlockMutex(free_buffer_mutex); |
2058 } | 2081 } |
2059 | 2082 |
2064 #define FPS_INTERVAL 1000 | 2087 #define FPS_INTERVAL 1000 |
2065 #endif | 2088 #endif |
2066 | 2089 |
2067 static uint32_t last_width, last_height; | 2090 static uint32_t last_width, last_height; |
2068 static uint8_t interlaced, last_field; | 2091 static uint8_t interlaced, last_field; |
2069 static void process_framebuffer(uint32_t *buffer, uint8_t which, int width) | 2092 static void process_framebuffer(pixel_t *buffer, uint8_t which, int width) |
2070 { | 2093 { |
2071 if (sync_src == SYNC_VIDEO && which <= FRAMEBUFFER_EVEN && source_frame_count < 0) { | 2094 if (sync_src == SYNC_VIDEO && which <= FRAMEBUFFER_EVEN && source_frame_count < 0) { |
2072 source_frame++; | 2095 source_frame++; |
2073 if (source_frame >= source_hz) { | 2096 if (source_frame >= source_hz) { |
2074 source_frame = 0; | 2097 source_frame = 0; |
2098 } | 2121 } |
2099 free(screenshot_path); | 2122 free(screenshot_path); |
2100 screenshot_path = NULL; | 2123 screenshot_path = NULL; |
2101 } | 2124 } |
2102 interlaced = last_field != which; | 2125 interlaced = last_field != which; |
2103 buffer += overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; | 2126 buffer += overscan_left[video_standard] + PITCH_PIXEL_T(LINEBUF_SIZE) * overscan_top[video_standard]; |
2104 } | 2127 } |
2105 #ifndef DISABLE_OPENGL | 2128 #ifndef DISABLE_OPENGL |
2106 if (render_gl && which <= FRAMEBUFFER_EVEN) { | 2129 if (render_gl && which <= FRAMEBUFFER_EVEN) { |
2107 SDL_GL_MakeCurrent(main_window, main_context); | 2130 SDL_GL_MakeCurrent(main_window, main_context); |
2108 glBindTexture(GL_TEXTURE_2D, textures[which]); | 2131 glBindTexture(GL_TEXTURE_2D, textures[which]); |
2109 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, GL_UNSIGNED_BYTE, buffer); | 2132 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, SRC_TYPE, buffer); |
2110 | 2133 |
2111 if (screenshot_file) { | 2134 if (screenshot_file) { |
2112 //properly supporting interlaced modes here is non-trivial, so only save the odd field for now | 2135 //properly supporting interlaced modes here is non-trivial, so only save the odd field for now |
2113 #ifndef DISABLE_ZLIB | 2136 #ifndef DISABLE_ZLIB |
2114 if (!strcasecmp(ext, "png")) { | 2137 if (!strcasecmp(ext, "png")) { |
2115 free(ext); | 2138 free(ext); |
2116 save_png(screenshot_file, buffer, width, height, LINEBUF_SIZE*sizeof(uint32_t)); | 2139 save_png(screenshot_file, buffer, width, height, PITCH_BYTES(LINEBUF_SIZE)); |
2117 } else { | 2140 } else { |
2118 free(ext); | 2141 free(ext); |
2119 #endif | 2142 #endif |
2120 save_ppm(screenshot_file, buffer, width, height, LINEBUF_SIZE*sizeof(uint32_t)); | 2143 save_ppm(screenshot_file, buffer, width, height, PITCH_BYTES(LINEBUF_SIZE)); |
2121 #ifndef DISABLE_ZLIB | 2144 #ifndef DISABLE_ZLIB |
2122 } | 2145 } |
2123 #endif | 2146 #endif |
2124 } | 2147 } |
2125 #ifndef DISABLE_ZLIB | 2148 #ifndef DISABLE_ZLIB |
2126 if (apng_file) { | 2149 if (apng_file) { |
2127 if (!apng) { | 2150 if (!apng) { |
2128 //TODO: more precise frame rate | 2151 //TODO: more precise frame rate |
2129 apng = start_apng(apng_file, width, height, video_standard == VID_PAL ? 50.0 : 60.0); | 2152 apng = start_apng(apng_file, width, height, video_standard == VID_PAL ? 50.0 : 60.0); |
2130 } | 2153 } |
2131 save_png24_frame(apng_file, buffer, apng, width, height, LINEBUF_SIZE*sizeof(uint32_t)); | 2154 save_png24_frame(apng_file, buffer, apng, width, height, PITCH_BYTES(LINEBUF_SIZE)); |
2132 } | 2155 } |
2133 #endif | 2156 #endif |
2134 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { | 2157 } else if (render_gl && which >= FRAMEBUFFER_USER_START) { |
2135 uint8_t win_idx = which - FRAMEBUFFER_USER_START; | 2158 uint8_t win_idx = which - FRAMEBUFFER_USER_START; |
2136 SDL_GL_MakeCurrent(extras[win_idx].win, extras[win_idx].gl_context); | 2159 SDL_GL_MakeCurrent(extras[win_idx].win, extras[win_idx].gl_context); |
2137 glBindTexture(GL_TEXTURE_2D, extras[win_idx].gl_texture[0]); | 2160 glBindTexture(GL_TEXTURE_2D, extras[win_idx].gl_texture[0]); |
2138 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extras[win_idx].width, extras[win_idx].height, SRC_FORMAT, GL_UNSIGNED_BYTE, buffer); | 2161 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extras[win_idx].width, extras[win_idx].height, SRC_FORMAT, SRC_TYPE, buffer); |
2139 } else { | 2162 } else { |
2140 #endif | 2163 #endif |
2141 uint32_t shot_height = height; | 2164 uint32_t shot_height = height; |
2142 //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers | 2165 //TODO: Support SYNC_AUDIO_THREAD/SYNC_EXTERNAL for render API framebuffers |
2143 if (which <= FRAMEBUFFER_EVEN && last_field != which) { | 2166 if (which <= FRAMEBUFFER_EVEN && last_field != which) { |
2296 source_frame_count = frame_repeat[source_frame]; | 2319 source_frame_count = frame_repeat[source_frame]; |
2297 } | 2320 } |
2298 } | 2321 } |
2299 | 2322 |
2300 typedef struct { | 2323 typedef struct { |
2301 uint32_t *buffer; | 2324 pixel_t *buffer; |
2302 int width; | 2325 int width; |
2303 uint8_t which; | 2326 uint8_t which; |
2304 } frame; | 2327 } frame; |
2305 frame frame_queue[4]; | 2328 frame frame_queue[4]; |
2306 int frame_queue_len, frame_queue_read, frame_queue_write; | 2329 int frame_queue_len, frame_queue_read, frame_queue_write; |
2335 }; | 2358 }; |
2336 frame_queue_write &= 0x3; | 2359 frame_queue_write &= 0x3; |
2337 frame_queue_len++; | 2360 frame_queue_len++; |
2338 SDL_CondSignal(frame_ready); | 2361 SDL_CondSignal(frame_ready); |
2339 SDL_UnlockMutex(frame_mutex); | 2362 SDL_UnlockMutex(frame_mutex); |
2363 #ifdef __ANDROID__ | |
2364 if (which <= FRAMEBUFFER_EVEN) { | |
2365 static uint32_t frame_counter, start; | |
2366 frame_counter++; | |
2367 uint32_t last_frame= SDL_GetTicks(); | |
2368 if ((last_frame - start) > FPS_INTERVAL) { | |
2369 if (start && (last_frame-start)) { | |
2370 debug_message("%s - %.1f fps (emulated)", caption, ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0)); | |
2371 } | |
2372 start = last_frame; | |
2373 frame_counter = 0; | |
2374 } | |
2375 } | |
2376 #endif | |
2340 return; | 2377 return; |
2341 } | 2378 } |
2342 //TODO: Maybe fixme for render API | 2379 //TODO: Maybe fixme for render API |
2343 process_framebuffer(which < FRAMEBUFFER_USER_START ? texture_buf : extras[which - FRAMEBUFFER_USER_START].texture_buf, which, width); | 2380 process_framebuffer(which < FRAMEBUFFER_USER_START ? texture_buf : extras[which - FRAMEBUFFER_USER_START].texture_buf, which, width); |
2344 } | 2381 } |