static const render_primitive_list *drawgdi_window_get_primitives(win_window_info *window) { RECT client; GetClientRect(window->hwnd, &client); render_target_set_bounds(window->target, rect_width(&client), rect_height(&client), winvideo_monitor_get_aspect(window->monitor)); return render_target_get_primitives(window->target); }
static render_primitive_list *drawnone_window_get_primitives(win_window_info *window) { RECT client; GetClientRect(window->hwnd, &client); window->target->set_bounds(rect_width(&client), rect_height(&client), winvideo_monitor_get_aspect(window->monitor)); return &window->target->get_primitives(); }
static void blit_to_primary(win_window_info *window, int srcwidth, int srcheight) { dd_info *dd = window->drawdata; IDirectDrawSurface7 *target = (dd->back != NULL) ? dd->back : dd->primary; win_monitor_info *monitor = winwindow_video_window_monitor(window, NULL); DDBLTFX blitfx = { sizeof(DDBLTFX) }; RECT clear, outer, dest, source; INT32 dstwidth, dstheight; HRESULT result; // compute source rect source.left = source.top = 0; source.right = srcwidth; source.bottom = srcheight; // compute outer rect -- windowed version if (!window->fullscreen) { GetClientRect(window->hwnd, &outer); ClientToScreen(window->hwnd, &((LPPOINT)&outer)[0]); ClientToScreen(window->hwnd, &((LPPOINT)&outer)[1]); // adjust to be relative to the monitor outer.left -= monitor->info.rcMonitor.left; outer.right -= monitor->info.rcMonitor.left; outer.top -= monitor->info.rcMonitor.top; outer.bottom -= monitor->info.rcMonitor.top; } // compute outer rect -- full screen version else { calc_fullscreen_margins(window, dd->primarydesc.dwWidth, dd->primarydesc.dwHeight, &outer); } // if we're respecting the aspect ratio, we need to adjust to fit dstwidth = rect_width(&outer); dstheight = rect_height(&outer); if (!video_config.hwstretch) { // trim the source if necessary if (rect_width(&outer) < srcwidth) { source.left += (srcwidth - rect_width(&outer)) / 2; source.right = source.left + rect_width(&outer); } if (rect_height(&outer) < srcheight) { source.top += (srcheight - rect_height(&outer)) / 2; source.bottom = source.top + rect_height(&outer); } // match the destination and source sizes dstwidth = srcwidth = source.right - source.left; dstheight = srcheight = source.bottom - source.top; } else if (video_config.keepaspect) { // compute the appropriate visible area render_target_compute_visible_area(window->target, rect_width(&outer), rect_height(&outer), winvideo_monitor_get_aspect(monitor), render_target_get_orientation(window->target), &dstwidth, &dstheight); } // center within dest.left = outer.left + (rect_width(&outer) - dstwidth) / 2; dest.right = dest.left + dstwidth; dest.top = outer.top + (rect_height(&outer) - dstheight) / 2; dest.bottom = dest.top + dstheight; // compare against last destination; if different, force a redraw if (dest.left != dd->lastdest.left || dest.right != dd->lastdest.right || dest.top != dd->lastdest.top || dest.bottom != dd->lastdest.bottom) { dd->lastdest = dest; update_outer_rects(dd); } // clear outer rects if we need to if (dd->clearouter != 0) { dd->clearouter--; // clear the left edge if (dest.left > outer.left) { clear = outer; clear.right = dest.left; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); } // clear the right edge if (dest.right < outer.right) { clear = outer; clear.left = dest.right; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); } // clear the top edge if (dest.top > outer.top) { clear = outer; clear.bottom = dest.top; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); } // clear the bottom edge if (dest.bottom < outer.bottom) { clear = outer; clear.top = dest.bottom; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); } } // do the blit result = IDirectDrawSurface7_Blt(target, &dest, dd->blit, &source, DDBLT_WAIT, NULL); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X blitting to the screen\n", (int)result); // page flip if triple buffered if (window->fullscreen && dd->back != NULL) { result = IDirectDrawSurface7_Flip(dd->primary, NULL, DDFLIP_WAIT); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); } }
static void compute_blit_surface_size(win_window_info *window) { dd_info *dd = window->drawdata; INT32 newwidth, newheight; int xscale, yscale; RECT client; // start with the minimum size render_target_get_minimum_size(window->target, &newwidth, &newheight); // get the window's client rectangle GetClientRect(window->hwnd, &client); // hardware stretch case: apply prescale if (video_config.hwstretch) { int prescale = (video_config.prescale < 1) ? 1 : video_config.prescale; // clamp the prescale to something smaller than the target bounds xscale = prescale; while (xscale > 1 && newwidth * xscale > rect_width(&client)) xscale--; yscale = prescale; while (yscale > 1 && newheight * yscale > rect_height(&client)) yscale--; } // non stretch case else { INT32 target_width = rect_width(&client); INT32 target_height = rect_height(&client); float desired_aspect = 1.0f; // compute the appropriate visible area if we're trying to keepaspect if (video_config.keepaspect) { win_monitor_info *monitor = winwindow_video_window_monitor(window, NULL); render_target_compute_visible_area(window->target, target_width, target_height, winvideo_monitor_get_aspect(monitor), render_target_get_orientation(window->target), &target_width, &target_height); desired_aspect = (float)target_width / (float)target_height; } // 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) <= rect_width(&client) && 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) <= rect_height(&client) && 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 (rect_width(&client) - newwidth * xscale < rect_height(&client) - newheight * yscale) { while (xscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect)) xscale--; } else { while (yscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect)) 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; if (newwidth != dd->blitwidth || newheight != dd->blitheight) { // force some updates update_outer_rects(dd); mame_printf_verbose("DirectDraw: New blit size = %dx%d\n", newwidth, newheight); } dd->blitwidth = newwidth; dd->blitheight = newheight; }
static void constrain_to_aspect_ratio(win_window_info *window, RECT *rect, int adjustment) { win_monitor_info *monitor = winwindow_video_window_monitor(window, rect); INT32 extrawidth = wnd_extra_width(window); INT32 extraheight = wnd_extra_height(window); INT32 propwidth, propheight; INT32 minwidth, minheight; INT32 maxwidth, maxheight; INT32 viswidth, visheight; INT32 adjwidth, adjheight; float pixel_aspect; assert(GetCurrentThreadId() == window_threadid); // get the pixel aspect ratio for the target monitor pixel_aspect = winvideo_monitor_get_aspect(monitor); // determine the proposed width/height propwidth = rect_width(rect) - extrawidth; propheight = rect_height(rect) - 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: render_target_compute_visible_area(window->target, 10000, propheight, pixel_aspect, render_target_get_orientation(window->target), &propwidth, &propheight); break; case WMSZ_LEFT: case WMSZ_RIGHT: render_target_compute_visible_area(window->target, propwidth, 10000, pixel_aspect, render_target_get_orientation(window->target), &propwidth, &propheight); break; default: render_target_compute_visible_area(window->target, propwidth, propheight, pixel_aspect, render_target_get_orientation(window->target), &propwidth, &propheight); break; } // get the minimum width/height for the current layout render_target_get_minimum_size(window->target, &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 = rect_width(&monitor->info.rcMonitor) - extrawidth; maxheight = rect_height(&monitor->info.rcMonitor) - extraheight; } else { maxwidth = rect_width(&monitor->info.rcWork) - extrawidth; maxheight = rect_height(&monitor->info.rcWork) - 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 render_target_compute_visible_area(window->target, propwidth, propheight, pixel_aspect, render_target_get_orientation(window->target), &viswidth, &visheight); // compute the adjustments we need to make adjwidth = (viswidth + extrawidth) - rect_width(rect); adjheight = (visheight + extraheight) - rect_height(rect); // based on which corner we're adjusting, constrain in different ways switch (adjustment) { case WMSZ_BOTTOM: case WMSZ_BOTTOMRIGHT: case WMSZ_RIGHT: rect->right += adjwidth; rect->bottom += adjheight; break; case WMSZ_BOTTOMLEFT: rect->left -= adjwidth; rect->bottom += adjheight; break; case WMSZ_LEFT: case WMSZ_TOPLEFT: case WMSZ_TOP: rect->left -= adjwidth; rect->top -= adjheight; break; case WMSZ_TOPRIGHT: rect->right += adjwidth; rect->top -= adjheight; break; } }