This one patch is a variation of the previous one, to allow continuous poll of the input devices during waiting for vblank.
diff -Nru a/src/osd/windows/drawdd.c b/src/osd/windows/drawdd.c
--- a/src/osd/windows/drawdd.c 2010-12-02 18:26:38.000000000 +0100
+++ b/src/osd/windows/drawdd.c 2011-01-09 18:43:57.000000000 +0100
@@ -55,6 +55,7 @@
// MAMEOS headers
#include "winmain.h"
#include "window.h"
+#include "input.h"
#include "config.h"
@@ -179,7 +180,7 @@
static int drawdd_window_init(win_window_info *window);
static void drawdd_window_destroy(win_window_info *window);
static render_primitive_list *drawdd_window_get_primitives(win_window_info *window);
-static int drawdd_window_draw(win_window_info *window, HDC dc, int update);
+static int drawdd_window_draw(win_window_info *window, HDC dc, int update, running_machine *machine);
// surface management
static int ddraw_create(win_window_info *window);
@@ -344,7 +345,7 @@
// drawdd_window_draw
//============================================================
-static int drawdd_window_draw(win_window_info *window, HDC dc, int update)
+static int drawdd_window_draw(win_window_info *window, HDC dc, int update, running_machine *machine)
{
dd_info *dd = (dd_info *)window->drawdata;
render_primitive *prim;
@@ -457,10 +458,12 @@
if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result);
// sync to VBLANK
- if ((video_config.waitvsync || video_config.syncrefresh) && window->machine->video().throttled() && (!window->fullscreen || dd->back == NULL))
+ if ((video_config.waitvsync || video_config.syncrefresh))
{
- result = IDirectDraw7_WaitForVerticalBlank(dd->ddraw, DDWAITVB_BLOCKBEGIN, NULL);
- if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result);
+ BOOL lpbIsInVB;
+ while (IDirectDraw7_GetVerticalBlankStatus(dd->ddraw, &lpbIsInVB) == DD_OK && lpbIsInVB == FALSE)
+ {
+ winwindow_process_events(machine, TRUE);
+ wininput_poll(machine);
+ }
}
// complete the blitting
diff -Nru a/src/osd/windows/video.c b/src/osd/windows/video.c
--- a/src/osd/windows/video.c 2010-11-06 18:24:58.000000000 +0100
+++ b/src/osd/windows/video.c 2011-01-09 18:48:50.000000000 +0100
@@ -221,7 +221,7 @@
// if we're not skipping this redraw, update all windows
if (!skip_redraw)
for (win_window_info *window = win_window_list; window != NULL; window = window->next)
- winwindow_video_window_update(window);
+ winwindow_video_window_update(window, &machine());
// poll the joystick values here
winwindow_process_events(&machine(), TRUE);
diff -Nru a/src/osd/windows/window.c b/src/osd/windows/window.c
--- a/src/osd/windows/window.c 2010-12-02 18:26:38.000000000 +0100
+++ b/src/osd/windows/window.c 2011-01-09 17:03:16.000000000 +0100
@@ -157,7 +157,7 @@
static void winwindow_exit(running_machine &machine);
static void winwindow_video_window_destroy(win_window_info *window);
-static void draw_video_contents(win_window_info *window, HDC dc, int update);
+static void draw_video_contents(win_window_info *window, HDC dc, int update, running_machine *machine);
static unsigned __stdcall thread_entry(void *param);
static int complete_create(win_window_info *window);
@@ -716,7 +716,7 @@
// (main thread)
//============================================================
-void winwindow_video_window_update(win_window_info *window)
+void winwindow_video_window_update(win_window_info *window, running_machine *machine)
{
int targetview, targetorient;
render_layer_config targetlayerconfig;
@@ -775,7 +775,16 @@
last_update_time = timeGetTime();
mtlog_add("winwindow_video_window_update: PostMessage start");
if (multithreading_enabled)
- PostMessage(window->hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist);
+ {
+ HDC hdc = GetDC(window->hwnd);
+
+ mtlog_add("winwindow_video_update: video update begin");
+ window->primlist = primlist;
+ draw_video_contents(window, hdc, FALSE, machine);
+ mtlog_add("winwindow_video_update: video update end");
+
+ ReleaseDC(window->hwnd, hdc);
+ }
else
SendMessage(window->hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist);
mtlog_add("winwindow_video_window_update: PostMessage end");
@@ -1215,7 +1224,8 @@
{
PAINTSTRUCT pstruct;
HDC hdc = BeginPaint(wnd, &pstruct);
- draw_video_contents(window, hdc, TRUE);
+ if (hdc)
+ draw_video_contents(window, hdc, TRUE, NULL);
if (win_has_menu(window))
DrawMenuBar(window->hwnd);
EndPaint(wnd, &pstruct);
@@ -1357,13 +1367,15 @@
case WM_USER_REDRAW:
{
HDC hdc = GetDC(wnd);
+ if (hdc)
+ {
+ mtlog_add("winwindow_video_window_proc: WM_USER_REDRAW begin");
+ window->primlist = (render_primitive_list *)lparam;
+ draw_video_contents(window, hdc, FALSE, NULL);
+ mtlog_add("winwindow_video_window_proc: WM_USER_REDRAW end");
- mtlog_add("winwindow_video_window_proc: WM_USER_REDRAW begin");
- window->primlist = (render_primitive_list *)lparam;
- draw_video_contents(window, hdc, FALSE);
- mtlog_add("winwindow_video_window_proc: WM_USER_REDRAW end");
-
- ReleaseDC(wnd, hdc);
+ ReleaseDC(wnd, hdc);
+ }
break;
}
@@ -1409,7 +1421,7 @@
// (window thread)
//============================================================
-static void draw_video_contents(win_window_info *window, HDC dc, int update)
+static void draw_video_contents(win_window_info *window, HDC dc, int update, running_machine *machine)
{
assert(GetCurrentThreadId() == window_threadid);
@@ -1433,7 +1445,7 @@
// otherwise, render with our drawing system
else
{
- (*draw.window_draw)(window, dc, update);
+ (*draw.window_draw)(window, dc, update, machine);
mtlog_add("draw_video_contents: drawing finished");
}
}
diff -Nru a/src/osd/windows/window.h b/src/osd/windows/window.h
--- a/src/osd/windows/window.h 2010-10-18 02:51:58.000000000 +0200
+++ b/src/osd/windows/window.h 2011-01-09 14:16:58.000000000 +0100
@@ -122,7 +122,7 @@
int (*window_init)(win_window_info *window);
render_primitive_list *(*window_get_primitives)(win_window_info *window);
- int (*window_draw)(win_window_info *window, HDC dc, int update);
+ int (*window_draw)(win_window_info *window, HDC dc, int update, running_machine *machine);
void (*window_destroy)(win_window_info *window);
};
@@ -149,7 +149,7 @@
BOOL winwindow_has_focus(void);
void winwindow_update_cursor_state(running_machine *machine);
-void winwindow_video_window_update(win_window_info *window);
+void winwindow_video_window_update(win_window_info *window, running_machine *machine);
win_monitor_info *winwindow_video_window_monitor(win_window_info *window, const RECT *proposed);
LRESULT CALLBACK winwindow_video_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
It's much more code, mainly because it needs that *machine param being passed down to the ddraw layer in order to poll the inputs there, something that is not designed to be used in that scope, so it's become rather dirty because of that. It's also repairing a bug with the last patch when draw_video_contents function could actually be called again from the windowproc while still being waiting from vblank, causing a null hdc.
This patch works when using syncrefresh 1, triplebuffer 0, throttle 0, multithreading 1. So instead of triplebuffer for vsynching+page flipping, we're directly blitting to the primary surface during vblank. Instead of using WaitForVerticalBlank I'm using GetVerticalBlankStatus, that tells us the vblank state without waiting, so I do a loop there to poll the input during the wait, and still can do it while using only two threads. I haven't put any sleep during that loop (should be done), but anyway the cpu usage does not go crazy.
Of course this works with single screen games, I guess that using this method to throttle with multiple screens would have unpredictable results. So think about this as experimental stuff.
That said, I notice no difference with this method and the default in Mame, so maybe they're already doing the best possible thing when polling inputs right after returning from the update video function. Maybe the Linux implementation can take any advantage of how that os works, I don't know. I've been messing these days with Mame source, only that small part of it, and I must say I'm amazed with it. Mame is a complex object, it takes days to get to understand just any of the modules, I believe there must be very few people, if any, that really have a full understanding of the whole thing in their heads.
UPDATE: I've added the {} that were missing after the 'while', so now should be doing what it was supposed to.