int winwindow_video_window_create(int index, win_monitor_info *monitor, const win_window_config *config) { win_window_info *window, *win; char option[20]; assert(GetCurrentThreadId() == main_threadid); // allocate a new window object window = malloc_or_die(sizeof(*window)); memset(window, 0, sizeof(*window)); window->maxwidth = config->width; window->maxheight = config->height; window->refresh = config->refresh; window->monitor = monitor; window->fullscreen = !video_config.windowed; // see if we are safe for fullscreen window->fullscreen_safe = TRUE; for (win = win_window_list; win != NULL; win = win->next) if (win->monitor == monitor) window->fullscreen_safe = FALSE; // add us to the list *last_window_ptr = window; last_window_ptr = &window->next; // create a lock that we can use to skip blitting window->render_lock = osd_lock_alloc(); // load the layout window->target = render_target_alloc(NULL, 0); if (window->target == NULL) goto error; render_target_set_orientation(window->target, video_orientation); render_target_set_layer_config(window->target, video_config.layerconfig); // set the specific view sprintf(option, "view%d", index); set_starting_view(index, window, options_get_string(option)); // remember the current values in case they change window->targetview = render_target_get_view(window->target); window->targetorient = render_target_get_orientation(window->target); window->targetlayerconfig = render_target_get_layer_config(window->target); // make the window title if (video_config.numscreens == 1) sprintf(window->title, APPNAME ": %s [%s]", Machine->gamedrv->description, Machine->gamedrv->name); else sprintf(window->title, APPNAME ": %s [%s] - Screen %d", Machine->gamedrv->description, Machine->gamedrv->name, index); // set the initial maximized state window->startmaximized = options_get_bool("maximize"); // finish the window creation on the window thread if (multithreading_enabled) { // wait until the window thread is ready to respond to events WaitForSingleObject(window_thread_ready_event, INFINITE); PostThreadMessage(window_threadid, WM_USER_FINISH_CREATE_WINDOW, 0, (LPARAM)window); while (window->init_state == 0) Sleep(1); } else window->init_state = complete_create(window) ? -1 : 1; // handle error conditions if (window->init_state == -1) goto error; return 0; error: winwindow_video_window_destroy(window); return 1; }
void winwindow_video_window_update(win_window_info *window) { int targetview, targetorient, targetlayerconfig; assert(GetCurrentThreadId() == main_threadid); mtlog_add("winwindow_video_window_update: begin"); // see if the target has changed significantly in window mode targetview = render_target_get_view(window->target); targetorient = render_target_get_orientation(window->target); targetlayerconfig = render_target_get_layer_config(window->target); if (targetview != window->targetview || targetorient != window->targetorient || targetlayerconfig != window->targetlayerconfig) { window->targetview = targetview; window->targetorient = targetorient; window->targetlayerconfig = targetlayerconfig; // in window mode, reminimize/maximize if (!window->fullscreen) { if (window->isminimized) SendMessage(window->hwnd, WM_USER_SET_MINSIZE, 0, 0); if (window->ismaximized) SendMessage(window->hwnd, WM_USER_SET_MAXSIZE, 0, 0); } } // if we're visible and running and not in the middle of a resize, draw if (window->hwnd != NULL && window->target != NULL) { int got_lock = TRUE; mtlog_add("winwindow_video_window_update: try lock"); // only block if we're throttled if (video_config.throttle || timeGetTime() - last_update_time > 250) osd_lock_acquire(window->render_lock); else got_lock = osd_lock_try(window->render_lock); // only render if we were able to get the lock if (got_lock) { const render_primitive_list *primlist; mtlog_add("winwindow_video_window_update: got lock"); // don't hold the lock; we just used it to see if rendering was still happening osd_lock_release(window->render_lock); // ensure the target bounds are up-to-date, and then get the primitives primlist = (*draw.window_get_primitives)(window); // post a redraw request with the primitive list as a parameter last_update_time = timeGetTime(); mtlog_add("winwindow_video_window_update: PostMessage start"); if (multithreading_enabled) PostMessage(window->hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist); else SendMessage(window->hwnd, WM_USER_REDRAW, 0, (LPARAM)primlist); mtlog_add("winwindow_video_window_update: PostMessage end"); } } mtlog_add("winwindow_video_window_update: end"); }
void sdlwindow_blit_surface_size(sdl_window_info *window, int window_width, int window_height) { INT32 newwidth, newheight; int xscale = 1, yscale = 1; float desired_aspect = 1.0f; INT32 target_width = window_width; INT32 target_height = window_height; // start with the minimum size render_target_get_minimum_size(window->target, &newwidth, &newheight); // compute the appropriate visible area if we're trying to keepaspect if (video_config.keepaspect) { // make sure the monitor is up-to-date sdlvideo_monitor_refresh(window->monitor); render_target_compute_visible_area(window->target, target_width, target_height, sdlvideo_monitor_get_aspect(window->monitor), render_target_get_orientation(window->target), &target_width, &target_height); desired_aspect = (float)target_width / (float)target_height; } // non-integer scaling - often gives more pleasing results in full screen if (!video_config.fullstretch) { // compute maximum integral scaling to fit the window xscale = (target_width + 2) / newwidth; yscale = (target_height + 2) / newheight; // try a little harder to keep the aspect ratio if desired if (video_config.keepaspect) { // if we could stretch more in the X direction, and that makes a better fit, bump the xscale while (newwidth * (xscale + 1) <= window_width && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) xscale++; // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale while (newheight * (yscale + 1) <= window_height && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) yscale++; // now that we've maxed out, see if backing off the maximally stretched one makes a better fit if (window_width - newwidth * xscale < window_height - newheight * yscale) { while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) xscale--; } else { while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0)) yscale--; } } // ensure at least a scale factor of 1 if (xscale <= 0) xscale = 1; if (yscale <= 0) yscale = 1; // apply the final scale newwidth *= xscale; newheight *= yscale; } else { newwidth = target_width; newheight = target_height; } //FIXME: really necessary to distinguish for yuv_modes ? if ((render_target_get_layer_config(window->target) & LAYER_CONFIG_ZOOM_TO_SCREEN) && (window->scale_mode == VIDEO_SCALE_MODE_NONE )) newwidth = window_width; if ((window->blitwidth != newwidth) || (window->blitheight != newheight)) sdlwindow_clear(window); window->blitwidth = newwidth; window->blitheight = newheight; }