From 46807540edc03a87d593b58f88a07ed6e3190bd7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 6 Oct 2021 02:26:30 +0200 Subject: [PATCH] Rewritten renderer blitting, fixes flickering when inversion or grayscale is used. --- src/config.c | 41 +++++++++++++++--------------- src/include/86box/video.h | 4 +++ src/unix/unix_sdl.c | 5 +++- src/video/video.c | 52 +++++++++++++++++---------------------- src/vnc.c | 5 +++- src/win/win_opengl.c | 5 +++- src/win/win_sdl.c | 23 ++++++++++------- src/win/win_ui.c | 2 ++ 8 files changed, 76 insertions(+), 61 deletions(-) diff --git a/src/config.c b/src/config.c index e0928cabe..7323b6a81 100644 --- a/src/config.c +++ b/src/config.c @@ -2056,28 +2056,29 @@ config_load(void) cassette_ui_writeprot = 0; config_log("Config file not present or invalid!\n"); - return; + } else { + load_general(); /* General */ + load_machine(); /* Machine */ + load_video(); /* Video */ + load_input_devices(); /* Input devices */ + load_sound(); /* Sound */ + load_network(); /* Network */ + load_ports(); /* Ports (COM & LPT) */ + load_storage_controllers(); /* Storage controllers */ + load_hard_disks(); /* Hard disks */ + load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ + /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ + load_floppy_drives(); /* Floppy drives */ + load_other_removable_devices(); /* Other removable devices */ + load_other_peripherals(); /* Other peripherals */ + + /* Mark the configuration as changed. */ + config_changed = 1; + + config_log("Config loaded.\n\n"); } - load_general(); /* General */ - load_machine(); /* Machine */ - load_video(); /* Video */ - load_input_devices(); /* Input devices */ - load_sound(); /* Sound */ - load_network(); /* Network */ - load_ports(); /* Ports (COM & LPT) */ - load_storage_controllers(); /* Storage controllers */ - load_hard_disks(); /* Hard disks */ - load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */ - /* TODO: Backwards compatibility, get rid of this when enough time has passed. */ - load_floppy_drives(); /* Floppy drives */ - load_other_removable_devices(); /* Other removable devices */ - load_other_peripherals(); /* Other peripherals */ - - /* Mark the configuration as changed. */ - config_changed = 1; - - config_log("Config loaded.\n\n"); + video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; } diff --git a/src/include/86box/video.h b/src/include/86box/video.h index e22eda015..c8cff07f8 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -133,6 +133,10 @@ extern int readflash; /* Function handler pointers. */ extern void (*video_recalctimings)(void); +extern void * __cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size); + +extern void video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len); +extern void * __cdecl video_transform_copy(void *_Dst, const void *_Src, size_t _Size); /* Table functions. */ diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index a61d338e6..4c309144f 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -133,7 +133,10 @@ sdl_blit_shim(int x, int y, int w, int h) params.y = y; params.w = w; params.h = h; - if (!(!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL))) memcpy(interpixels, &(buffer32->line[y][x]), h * (2048 + 64) * sizeof(uint32_t)); + if (!(!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL))) + video_copy(interpixels, &(buffer32->line[y][x]), h * (2048 + 64) * sizeof(uint32_t)); + if (screenshots) + video_screenshot(interpixels, 0, 0, (2048 + 64)); blitreq = 1; video_blit_complete(); } diff --git a/src/video/video.c b/src/video/video.c index 1258b1824..332f8bbaf 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -114,6 +114,8 @@ static const video_timings_t *vid_timings; static uint32_t cga_2_table[16]; static uint8_t thread_run = 0; +void * __cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size) = memcpy; + PALETTE cgapal = { {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, @@ -317,7 +319,7 @@ static png_infop info_ptr; static void -video_take_screenshot(const char *fn) +video_take_screenshot(const char *fn, uint32_t *buf, int start_x, int start_y, int row_len) { int i, x, y; png_bytep *b_rgb = NULL; @@ -363,10 +365,10 @@ video_take_screenshot(const char *fn) for (y = 0; y < blit_data.h; ++y) { b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); for (x = 0; x < blit_data.w; ++x) { - if (buffer32 == NULL) + if (buf == NULL) memset(&(b_rgb[y][x * 3]), 0x00, 3); else { - temp = buffer32->line[blit_data.y + y][blit_data.x + x]; + temp = buf[((start_y + y) * row_len) + start_x + x]; b_rgb[y][x * 3] = (temp >> 16) & 0xff; b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff; b_rgb[y][(x * 3) + 2] = temp & 0xff; @@ -390,8 +392,8 @@ video_take_screenshot(const char *fn) } -static void -video_screenshot(void) +void +video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len) { char path[1024], fn[128]; @@ -410,50 +412,42 @@ video_screenshot(void) video_log("taking screenshot to: %s\n", path); - video_take_screenshot((const char *) path); + video_take_screenshot((const char *) path, buf, start_x, start_y, row_len); png_destroy_write_struct(&png_ptr, &info_ptr); + + screenshots--; } -static void -video_transform_copy(uint32_t *dst, uint32_t *src, int len) +void * __cdecl +video_transform_copy(void *_Dst, const void *_Src, size_t _Size) { int i; + uint32_t *dest_ex = (uint32_t *) _Dst; + uint32_t *src_ex = (uint32_t *) _Src; - if ((dst != NULL) && (src != NULL)) { - for (i = 0; i < len; i++) { - *dst = video_color_transform(*src); - dst++; - src++; + _Size /= sizeof(uint32_t); + + if ((dest_ex != NULL) && (src_ex != NULL)) { + for (i = 0; i < _Size; i++) { + *dest_ex = video_color_transform(*src_ex); + dest_ex++; + src_ex++; } } + + return _Dst; } static void blit_thread(void *param) { - int yy; - while (thread_run) { thread_wait_event(blit_data.wake_blit_thread, -1); thread_reset_event(blit_data.wake_blit_thread); MTR_BEGIN("video", "blit_thread"); - if ((video_grayscale || invert_display) && (blit_data.h > 0)) { - for (yy = 0; yy < blit_data.h; yy++) { - if (((blit_data.y + yy) >= 0) && ((blit_data.y + yy) < buffer32->h)) { - video_transform_copy(&(buffer32->line[blit_data.y + yy][blit_data.x]), &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w); - } - } - } - - if (screenshots) { - video_screenshot(); - screenshots--; - video_log("screenshot taken, %i left\n", screenshots); - } - if (blit_func) blit_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); diff --git a/src/vnc.c b/src/vnc.c index 371e03803..363c6205d 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -179,8 +179,11 @@ vnc_blit(int x, int y, int w, int h) p = (uint32_t *)&(((uint32_t *)rfb->frameBuffer)[yy*VNC_MAX_X]); if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - memcpy(p, &(buffer32->line[yy]), w*sizeof(uint32_t)); + video_copy(p, &(buffer32->line[yy]), w*sizeof(uint32_t)); } + + if (screenshots) + video_screenshot((uint32_t *) rfb->frameBuffer, 0, 0, ROW_LENGTH); video_blit_complete(); diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index b2c338a31..69190b6b1 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -816,7 +816,10 @@ static void opengl_blit(int x, int y, int w, int h) return; } - memcpy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t)); + video_copy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t)); + + if (screenshots) + video_screenshot(blit_info[write_pos].buffer, 0, 0, ROW_LENGTH); video_blit_complete(); diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 62a77551b..e8bdd6e0d 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -232,7 +232,8 @@ static void sdl_blit(int x, int y, int w, int h) { SDL_Rect r_src; - int ret; + void *pixeldata; + int pitch, ret; if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); @@ -241,17 +242,21 @@ sdl_blit(int x, int y, int w, int h) SDL_LockMutex(sdl_mutex); - r_src.x = x; - r_src.y = y; - r_src.w = w; - r_src.h = h; - SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * sizeof(uint32_t)); + SDL_LockTexture(sdl_tex, 0, &pixeldata, &pitch); + + video_copy(pixeldata, &(buffer32->line[y][x]), h * (2048 + 64) * sizeof(uint32_t)); + + if (screenshots) + video_screenshot((uint32_t *) pixeldata, 0, 0, (2048 + 64)); + + SDL_UnlockTexture(sdl_tex); + video_blit_complete(); SDL_RenderClear(sdl_render); - r_src.x = x; - r_src.y = y; + r_src.x = 0; + r_src.y = 0; r_src.w = w; r_src.h = h; @@ -353,7 +358,7 @@ sdl_init_texture(void) sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); + SDL_TEXTUREACCESS_STREAMING, (2048 + 64), (2048 + 64)); } diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 6a38045c9..9b1f64d5d 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -822,6 +822,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_VID_INVERT: video_toggle_option(hmenu, &invert_display, IDM_VID_INVERT); + video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; break; case IDM_VID_OVERSCAN: @@ -854,6 +855,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_VID_GRAY_WHITE: CheckMenuItem(hmenu, IDM_VID_GRAY_RGB+video_grayscale, MF_UNCHECKED); video_grayscale = LOWORD(wParam) - IDM_VID_GRAY_RGB; + video_copy = (video_grayscale || invert_display) ? video_transform_copy : memcpy; CheckMenuItem(hmenu, IDM_VID_GRAY_RGB+video_grayscale, MF_CHECKED); device_force_redraw(); config_save();