Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- a/render_sdl.c Sat Mar 29 23:54:45 2025 -0700 +++ b/render_sdl.c Sun Mar 30 00:06:53 2025 -0700 @@ -44,7 +44,7 @@ uint8_t num_static; #ifndef DISABLE_OPENGL SDL_GLContext *gl_context; - uint32_t *texture_buf; + pixel_t *texture_buf; uint32_t tex_width; uint32_t tex_height; GLuint gl_texture[2]; @@ -94,7 +94,7 @@ static uint8_t sync_src; static uint32_t min_buffered; -uint32_t **frame_buffers; +pixel_t **frame_buffers; uint32_t num_buffers; uint32_t buffer_storage; @@ -339,13 +339,17 @@ return is_fullscreen; } -uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b) +pixel_t render_map_color(uint8_t r, uint8_t g, uint8_t b) { +#ifdef USE_RGB565 + return r << 8 & 0xF800 | g << 3 & 0x07E0 | b >> 3; +#else #ifdef USE_GLES return 255UL << 24 | b << 16 | g << 8 | r; #else return 255UL << 24 | r << 16 | g << 8 | b; #endif +#endif } static uint8_t external_sync; @@ -457,19 +461,38 @@ } #endif -static uint32_t texture_buf[512 * 513]; +static pixel_t texture_buf[512 * 513]; #ifdef DISABLE_OPENGL +#ifdef USE_RGB565 +#define RENDER_FORMAT SDL_PIXELFORMAT_RGB565 +#else #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 -#else +#endif +#else //DISABLE_OPENGL +#ifdef USE_RGB565 +#define INTERNAL_FORMAT GL_RGB +#define SRC_FORMAT GL_RGB +#define SRC_TYPE GL_UNSIGNED_SHORT_5_6_5 +#define RENDER_FORMAT SDL_PIXELFORMAT_RGB565 +#else //USE_RGB565 +#define SRC_TYPE GL_UNSIGNED_BYTE #ifdef USE_GLES #define INTERNAL_FORMAT GL_RGBA #define SRC_FORMAT GL_RGBA #define RENDER_FORMAT SDL_PIXELFORMAT_ABGR8888 -#else +#else //USE_GLES #define INTERNAL_FORMAT GL_RGBA8 #define SRC_FORMAT GL_BGRA #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 +#endif //USE_GLES +#endif //USE_RGB565 + +#ifdef USE_GLES +#define SRC_FORMAT32 GL_RGBA +#else +#define SRC_FORMAT32 GL_BGRA #endif + static void gl_setup() { tern_val def = {.ptrval = "linear"}; @@ -494,10 +517,10 @@ 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, tex_width, tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf); + glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, tex_width, tex_height, 0, SRC_FORMAT, SRC_TYPE, texture_buf); } else { - uint32_t blank = 255UL << 24; - glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, &blank); + pixel_t blank = render_map_color(0, 0, 0); + glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, SRC_TYPE, &blank); } } glGenBuffers(2, buffers); @@ -538,7 +561,7 @@ glDeleteBuffers(2, buffers); glDeleteTextures(3, textures); } -#endif +#endif //DISABLE_OPENGL static uint8_t texture_init; static void render_alloc_surfaces() @@ -1190,7 +1213,7 @@ free_buffer_mutex = SDL_CreateMutex(); frame_ready = SDL_CreateCond(); buffer_storage = 4; - frame_buffers = calloc(buffer_storage, sizeof(uint32_t*)); + frame_buffers = calloc(buffer_storage, sizeof(pixel_t*)); frame_buffers[0] = texture_buf; num_buffers = 1; } @@ -1688,7 +1711,7 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (i) { - glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, extras[win_idx].color); + glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, SRC_TYPE, extras[win_idx].color); } else { extras[win_idx].tex_width = width; extras[win_idx].tex_height = height; @@ -1697,8 +1720,8 @@ extras[win_idx].tex_width = nearest_pow2(width); extras[win_idx].tex_height = nearest_pow2(height); } - extras[win_idx].texture_buf = calloc(extras[win_idx].tex_width * extras[win_idx].tex_height, sizeof(uint32_t)); - 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); + extras[win_idx].texture_buf = calloc(PITCH_PIXEL_T(extras[win_idx].tex_width) * extras[win_idx].tex_height, sizeof(pixel_t)); + 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); } } glGenBuffers(3, extras[win_idx].gl_buffers); @@ -1876,12 +1899,12 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //TODO: maybe make this respect the npot texture setting? - glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, width, height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, width, height, 0, SRC_FORMAT32, GL_UNSIGNED_BYTE, pixels); } else #endif { extra->static_images[img_index] = SDL_CreateTexture(extra->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height); - SDL_UpdateTexture(extra->static_images[img_index], NULL, pixels, sizeof(uint32_t) * width); + SDL_UpdateTexture(extra->static_images[img_index], NULL, pixels, sizeof(pixel_t) * width); } free(pixels); return img_index; @@ -1963,7 +1986,7 @@ extra->color[1] = g; extra->color[2] = r; glBindTexture(GL_TEXTURE_2D, extra->gl_texture[1]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, SRC_FORMAT, GL_UNSIGNED_BYTE, extra->color); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, SRC_FORMAT, SRC_TYPE, extra->color); extra_draw_quad(extra, extra->gl_texture[1], 1.0f, 1.0f); } #endif @@ -1982,18 +2005,18 @@ #endif } -uint32_t *locked_pixels; +pixel_t *locked_pixels; uint32_t locked_pitch; -uint32_t *render_get_framebuffer(uint8_t which, int *pitch) +pixel_t *render_get_framebuffer(uint8_t which, int *pitch) { if (sync_src == SYNC_AUDIO_THREAD || sync_src == SYNC_EXTERNAL) { - *pitch = LINEBUF_SIZE * sizeof(uint32_t); - uint32_t *buffer; + *pitch = PITCH_BYTES(LINEBUF_SIZE); + pixel_t *buffer; SDL_LockMutex(free_buffer_mutex); if (num_buffers) { buffer = frame_buffers[--num_buffers]; } else { - buffer = calloc(tex_width*(tex_height + 1), sizeof(uint32_t)); + buffer = calloc(tex_width*(tex_height + 1), sizeof(pixel_t)); } SDL_UnlockMutex(free_buffer_mutex); locked_pixels = buffer; @@ -2001,11 +2024,11 @@ } #ifndef DISABLE_OPENGL if (render_gl && which <= FRAMEBUFFER_EVEN) { - *pitch = LINEBUF_SIZE * sizeof(uint32_t); + *pitch = PITCH_BYTES(LINEBUF_SIZE); return texture_buf; } else if (render_gl && which >= FRAMEBUFFER_USER_START) { uint8_t win_idx = which - FRAMEBUFFER_USER_START; - *pitch = extras[win_idx].width * sizeof(uint32_t); + *pitch = PITCH_BYTES(extras[win_idx].width); return extras[win_idx].texture_buf; } else { #endif @@ -2030,7 +2053,7 @@ } static uint8_t last; if (which <= FRAMEBUFFER_EVEN) { - locked_pixels = (uint32_t *)pixels; + locked_pixels = (pixel_t *)pixels; if (which == FRAMEBUFFER_EVEN) { pixels += *pitch; } @@ -2040,18 +2063,18 @@ } last = which; } - return (uint32_t *)pixels; + return (pixel_t *)pixels; #ifndef DISABLE_OPENGL } #endif } -static void release_buffer(uint32_t *buffer) +static void release_buffer(pixel_t *buffer) { SDL_LockMutex(free_buffer_mutex); if (num_buffers == buffer_storage) { buffer_storage *= 2; - frame_buffers = realloc(frame_buffers, sizeof(uint32_t*)*buffer_storage); + frame_buffers = realloc(frame_buffers, sizeof(pixel_t*)*buffer_storage); } frame_buffers[num_buffers++] = buffer; SDL_UnlockMutex(free_buffer_mutex); @@ -2066,7 +2089,7 @@ static uint32_t last_width, last_height; static uint8_t interlaced, last_field; -static void process_framebuffer(uint32_t *buffer, uint8_t which, int width) +static void process_framebuffer(pixel_t *buffer, uint8_t which, int width) { if (sync_src == SYNC_VIDEO && which <= FRAMEBUFFER_EVEN && source_frame_count < 0) { source_frame++; @@ -2100,24 +2123,24 @@ screenshot_path = NULL; } interlaced = last_field != which; - buffer += overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; + buffer += overscan_left[video_standard] + PITCH_PIXEL_T(LINEBUF_SIZE) * overscan_top[video_standard]; } #ifndef DISABLE_OPENGL if (render_gl && which <= FRAMEBUFFER_EVEN) { SDL_GL_MakeCurrent(main_window, main_context); glBindTexture(GL_TEXTURE_2D, textures[which]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, GL_UNSIGNED_BYTE, buffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, SRC_TYPE, buffer); if (screenshot_file) { //properly supporting interlaced modes here is non-trivial, so only save the odd field for now #ifndef DISABLE_ZLIB if (!strcasecmp(ext, "png")) { free(ext); - save_png(screenshot_file, buffer, width, height, LINEBUF_SIZE*sizeof(uint32_t)); + save_png(screenshot_file, buffer, width, height, PITCH_BYTES(LINEBUF_SIZE)); } else { free(ext); #endif - save_ppm(screenshot_file, buffer, width, height, LINEBUF_SIZE*sizeof(uint32_t)); + save_ppm(screenshot_file, buffer, width, height, PITCH_BYTES(LINEBUF_SIZE)); #ifndef DISABLE_ZLIB } #endif @@ -2128,14 +2151,14 @@ //TODO: more precise frame rate apng = start_apng(apng_file, width, height, video_standard == VID_PAL ? 50.0 : 60.0); } - save_png24_frame(apng_file, buffer, apng, width, height, LINEBUF_SIZE*sizeof(uint32_t)); + save_png24_frame(apng_file, buffer, apng, width, height, PITCH_BYTES(LINEBUF_SIZE)); } #endif } else if (render_gl && which >= FRAMEBUFFER_USER_START) { uint8_t win_idx = which - FRAMEBUFFER_USER_START; SDL_GL_MakeCurrent(extras[win_idx].win, extras[win_idx].gl_context); glBindTexture(GL_TEXTURE_2D, extras[win_idx].gl_texture[0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extras[win_idx].width, extras[win_idx].height, SRC_FORMAT, GL_UNSIGNED_BYTE, buffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extras[win_idx].width, extras[win_idx].height, SRC_FORMAT, SRC_TYPE, buffer); } else { #endif uint32_t shot_height = height; @@ -2298,7 +2321,7 @@ } typedef struct { - uint32_t *buffer; + pixel_t *buffer; int width; uint8_t which; } frame; @@ -2337,6 +2360,20 @@ frame_queue_len++; SDL_CondSignal(frame_ready); SDL_UnlockMutex(frame_mutex); +#ifdef __ANDROID__ + if (which <= FRAMEBUFFER_EVEN) { + static uint32_t frame_counter, start; + frame_counter++; + uint32_t last_frame= SDL_GetTicks(); + if ((last_frame - start) > FPS_INTERVAL) { + if (start && (last_frame-start)) { + debug_message("%s - %.1f fps (emulated)", caption, ((float)frame_counter) / (((float)(last_frame-start)) / 1000.0)); + } + start = last_frame; + frame_counter = 0; + } + } +#endif return; } //TODO: Maybe fixme for render API