diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0841fabdd..ad339040f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,7 +27,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1) endif() -if(CPPTHREADS) +if(WIN32) + target_sources(86Box PRIVATE qt/win_thread.c) +else() target_sources(86Box PRIVATE thread.cpp) endif() diff --git a/src/qt/win_thread.c b/src/qt/win_thread.c new file mode 100644 index 000000000..9a4f046b3 --- /dev/null +++ b/src/qt/win_thread.c @@ -0,0 +1,179 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implement threads and mutexes for the Win32 platform. + * + * + * + * Authors: Sarah Walker, + * Fred N. van Kempen, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/thread.h> + +typedef struct { + HANDLE handle; +} win_event_t; + +/* For compatibility with thread.h, but Win32 does not allow named threads. */ +thread_t * +thread_create_named(void (*func)(void *param), void *param, UNUSED(const char *name)) +{ + uintptr_t bt = _beginthread(func, 0, param); + return ((thread_t *) bt); +} + +int +thread_test_mutex(thread_t *arg) +{ + if (arg == NULL) + return (0); + + return (WaitForSingleObject(arg, 0) == WAIT_OBJECT_0) ? 1 : 0; +} + +int +thread_wait(thread_t *arg) +{ + if (arg == NULL) + return (0); + + if (WaitForSingleObject(arg, INFINITE)) + return (1); + + return (0); +} + +event_t * +thread_create_event(void) +{ + win_event_t *ev = malloc(sizeof(win_event_t)); + + ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL); + + return ((event_t *) ev); +} + +void +thread_set_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return; + + SetEvent(ev->handle); +} + +void +thread_reset_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return; + + ResetEvent(ev->handle); +} + +int +thread_wait_event(event_t *arg, int timeout) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return (0); + + if (ev->handle == NULL) + return (0); + + if (timeout == -1) + timeout = INFINITE; + + if (WaitForSingleObject(ev->handle, timeout)) + return (1); + + return (0); +} + +void +thread_destroy_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return; + + CloseHandle(ev->handle); + + free(ev); +} + +mutex_t * +thread_create_mutex(void) +{ + mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION)); + + InitializeCriticalSection(mutex); + + return mutex; +} + +int +thread_wait_mutex(mutex_t *mutex) +{ + if (mutex == NULL) + return (0); + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; + + EnterCriticalSection(critsec); + + return 1; +} + +int +thread_release_mutex(mutex_t *mutex) +{ + if (mutex == NULL) + return (0); + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; + + LeaveCriticalSection(critsec); + + return 1; +} + +void +thread_close_mutex(mutex_t *mutex) +{ + if (mutex == NULL) + return; + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; + + DeleteCriticalSection(critsec); + + free(critsec); +} diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 155380480..24f325c49 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -1804,13 +1804,34 @@ fifo_thread(void *param) { } static void -s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) { +s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) +{ fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; + int limit = 0; - if (FIFO_FULL) { - thread_reset_event(virge->fifo_not_full_event); - if (FIFO_FULL) - thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + if (type == FIFO_WRITE_DWORD) { + switch (addr & 0xfffc) { + case 0xa500: + if (val & CMD_SET_AE) + limit = 1; + break; + default: + break; + } + } + + if (limit) { + if (FIFO_ENTRIES >= 16) { + thread_reset_event(virge->fifo_not_full_event); + if (FIFO_ENTRIES >= 16) + thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } else { + if (FIFO_FULL) { + thread_reset_event(virge->fifo_not_full_event); + if (FIFO_FULL) + thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } } fifo->val = val; @@ -2190,13 +2211,13 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) { for (y = 0; y < 4; y++) { for (x = 0; x < 8; x++) { if (virge->s3d.mono_pat_0 & (1 << (x + y * 8))) - mono_pattern[y * 8 + x] = virge->s3d.pat_fg_clr; + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr; else - mono_pattern[y * 8 + x] = virge->s3d.pat_bg_clr; + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr; if (virge->s3d.mono_pat_1 & (1 << (x + y * 8))) - mono_pattern[(y + 4) * 8 + x] = virge->s3d.pat_fg_clr; + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr; else - mono_pattern[(y + 4) * 8 + x] = virge->s3d.pat_bg_clr; + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr; } } } @@ -3312,7 +3333,7 @@ tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; } - + if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) { uint32_t src_col; int src_r = 0; @@ -3375,7 +3396,7 @@ tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int virge->pixel_count++; } } - + tri_skip_line: state->x1 += dx1; state->x2 += dx2;