float sdlvideo_monitor_get_aspect(sdl_monitor_info *monitor) { // refresh the monitor information and compute the aspect if (video_config.keepaspect) { sdlvideo_monitor_refresh(monitor); return monitor->aspect / ((float)monitor->monitor_width / (float)monitor->monitor_height); } return 0.0f; }
static void add_primary_monitor(void *data) { sdl_monitor_info ***tailptr = (sdl_monitor_info ***)data; sdl_monitor_info *monitor; // allocate a new monitor info monitor = global_alloc_clear(sdl_monitor_info); // copy in the data monitor->handle = 1; sdlvideo_monitor_refresh(monitor); // guess the aspect ratio assuming square pixels monitor->aspect = (float)(monitor->monitor_width) / (float)(monitor->monitor_height); // save the primary monitor handle primary_monitor = monitor; // hook us into the list **tailptr = monitor; *tailptr = &monitor->next; }
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 window->target->compute_minimum_size(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); window->target->compute_visible_area(target_width, target_height, sdlvideo_monitor_get_aspect(window->monitor), window->target->orientation(), 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 (window->target->zoom_to_screen() && (video_config.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; }
static void constrain_to_aspect_ratio(sdl_window_info *window, int *window_width, int *window_height, int adjustment) { INT32 extrawidth = 0; INT32 extraheight = 0; INT32 propwidth, propheight; INT32 minwidth, minheight; INT32 maxwidth, maxheight; INT32 viswidth, visheight; float pixel_aspect; // make sure the monitor is up-to-date sdlvideo_monitor_refresh(window->monitor); // get the pixel aspect ratio for the target monitor pixel_aspect = sdlvideo_monitor_get_aspect(window->monitor); // determine the proposed width/height propwidth = *window_width - extrawidth; propheight = *window_height - extraheight; // based on which edge we are adjusting, take either the width, height, or both as gospel // and scale to fit using that as our parameter switch (adjustment) { case WMSZ_BOTTOM: case WMSZ_TOP: window->target->compute_visible_area(10000, propheight, pixel_aspect, window->target->orientation(), propwidth, propheight); break; case WMSZ_LEFT: case WMSZ_RIGHT: window->target->compute_visible_area(propwidth, 10000, pixel_aspect, window->target->orientation(), propwidth, propheight); break; default: window->target->compute_visible_area(propwidth, propheight, pixel_aspect, window->target->orientation(), propwidth, propheight); break; } // get the minimum width/height for the current layout window->target->compute_minimum_size(minwidth, minheight); // clamp against the absolute minimum propwidth = MAX(propwidth, MIN_WINDOW_DIM); propheight = MAX(propheight, MIN_WINDOW_DIM); // clamp against the minimum width and height propwidth = MAX(propwidth, minwidth); propheight = MAX(propheight, minheight); // clamp against the maximum (fit on one screen for full screen mode) if (window->fullscreen) { maxwidth = window->monitor->center_width - extrawidth; maxheight = window->monitor->center_height - extraheight; } else { maxwidth = window->monitor->center_width - extrawidth; maxheight = window->monitor->center_height - extraheight; // further clamp to the maximum width/height in the window if (window->maxwidth != 0) maxwidth = MIN(maxwidth, window->maxwidth + extrawidth); if (window->maxheight != 0) maxheight = MIN(maxheight, window->maxheight + extraheight); } // clamp to the maximum propwidth = MIN(propwidth, maxwidth); propheight = MIN(propheight, maxheight); // compute the visible area based on the proposed rectangle window->target->compute_visible_area(propwidth, propheight, pixel_aspect, window->target->orientation(), viswidth, visheight); *window_width = viswidth; *window_height = visheight; }