diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index dafef5e72..d1ff3c8fc 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -142,6 +142,7 @@ extern void ioctl_close(uint8_t id); typedef void thread_t; typedef void event_t; typedef void mutex_t; +typedef void lightmutex_t; extern thread_t *thread_create(void (*thread_func)(void *param), void *param); extern void thread_kill(thread_t *arg); @@ -157,6 +158,13 @@ extern void thread_close_mutex(mutex_t *arg); extern int thread_wait_mutex(mutex_t *arg); extern int thread_release_mutex(mutex_t *mutex); +#define LIGHT_MUTEX_DEFAULT_SPIN_COUNT 1024 + +lightmutex_t *thread_create_light_mutex(); +lightmutex_t *thread_create_light_mutex_and_spin_count(unsigned int spin_count); +int thread_wait_light_mutex(lightmutex_t *lightmutex); +int thread_release_light_mutex(lightmutex_t *lightmutex); +void thread_close_light_mutex(lightmutex_t *lightmutex); /* Other stuff. */ extern void startblit(void); diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 85b97c7d2..c5848a74e 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -489,6 +489,10 @@ typedef struct voodoo_t uint64_t time; int render_time[4]; + int force_blit_count; + int can_blit; + lightmutex_t* force_blit_mutex; + int use_recompiler; void *codegen_data; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index c806bf243..2aac6761b 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -514,6 +514,12 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) if (voodoo->initEnable & 0x01) { voodoo->fbiInit0 = val; + thread_wait_light_mutex(voodoo->force_blit_mutex); + voodoo->can_blit = (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) ? 1 : 0; + if (!voodoo->can_blit) + voodoo->force_blit_count = 0; + thread_release_light_mutex(voodoo->force_blit_mutex); + if (voodoo->set->nr_cards == 2) svga_set_override(voodoo->svga, (voodoo->set->voodoos[0]->fbiInit0 | voodoo->set->voodoos[1]->fbiInit0) & 1); else @@ -877,6 +883,24 @@ static void voodoo_speed_changed(void *p) // voodoo_log("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); } +static void voodoo_force_blit(void *p) +{ + voodoo_set_t *voodoo_set = (voodoo_set_t *)p; + + thread_wait_light_mutex(voodoo_set->voodoos[0]->force_blit_mutex); + if(voodoo_set->voodoos[0]->can_blit) { + voodoo_set->voodoos[0]->force_blit_count++; + } + thread_release_light_mutex(voodoo_set->voodoos[0]->force_blit_mutex); + if(voodoo_set->nr_cards == 2) { + thread_wait_light_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + if(voodoo_set->voodoos[1]->can_blit) { + voodoo_set->voodoos[1]->force_blit_count++; + } + thread_release_light_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + } +} + void *voodoo_card_init() { int c; @@ -1014,6 +1038,10 @@ void *voodoo_card_init() voodoo->disp_buffer = 0; voodoo->draw_buffer = 1; + + voodoo->force_blit_count = 0; + voodoo->can_blit = 0; + voodoo->force_blit_mutex = thread_create_light_mutex(); return voodoo; } @@ -1128,6 +1156,10 @@ void *voodoo_2d3d_card_init(int type) voodoo->disp_buffer = 0; voodoo->draw_buffer = 1; + voodoo->force_blit_count = 0; + voodoo->can_blit = 0; + voodoo->force_blit_mutex = thread_create_light_mutex(); + return voodoo; } @@ -1241,6 +1273,9 @@ void voodoo_card_close(voodoo_t *voodoo) free(voodoo->tex_mem[1]); free(voodoo->tex_mem[0]); } + + thread_close_light_mutex(voodoo->force_blit_mutex); + free(voodoo); } @@ -1386,6 +1421,6 @@ const device_t voodoo_device = NULL, { NULL }, voodoo_speed_changed, - NULL, + voodoo_force_blit, voodoo_config }; diff --git a/src/video/vid_voodoo_display.c b/src/video/vid_voodoo_display.c index 5d3ad6e81..dfd74969a 100644 --- a/src/video/vid_voodoo_display.c +++ b/src/video/vid_voodoo_display.c @@ -645,7 +645,16 @@ skip_draw: { if (voodoo->line == voodoo->v_disp) { - if (voodoo->dirty_line_high > voodoo->dirty_line_low) + int force_blit = 0; + thread_wait_light_mutex(voodoo->force_blit_mutex); + if(voodoo->force_blit_count) { + force_blit = 1; + if(--voodoo->force_blit_count < 0) + voodoo->force_blit_count = 0; + } + thread_release_light_mutex(voodoo->force_blit_mutex); + + if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit) svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); if (voodoo->clutData_dirty) { diff --git a/src/win/win_thread.c b/src/win/win_thread.c index 000c96706..ba73bfbc3 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -167,3 +167,60 @@ thread_release_mutex(mutex_t *mutex) return(!!ReleaseMutex((HANDLE)mutex)); } + + +lightmutex_t * +thread_create_light_mutex() +{ + return thread_create_light_mutex_and_spin_count(LIGHT_MUTEX_DEFAULT_SPIN_COUNT); +} + + +lightmutex_t * +thread_create_light_mutex_and_spin_count(unsigned int spin_count) +{ + lightmutex_t *lightmutex = malloc(sizeof(CRITICAL_SECTION)); + + InitializeCriticalSectionAndSpinCount(lightmutex, spin_count); + + return lightmutex; +} + + +int +thread_wait_light_mutex(lightmutex_t *lightmutex) +{ + if (lightmutex == NULL) return(0); + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)lightmutex; + + EnterCriticalSection(critsec); + + return 1; +} + + +int +thread_release_light_mutex(lightmutex_t *lightmutex) +{ + if (lightmutex == NULL) return(0); + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)lightmutex; + + LeaveCriticalSection(critsec); + + return 1; +} + + +void +thread_close_light_mutex(lightmutex_t *lightmutex) +{ + if (lightmutex == NULL) return; + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)lightmutex; + + DeleteCriticalSection(critsec); + + free(critsec); +}