Esempio n. 1
0
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);
	}
}
Esempio n. 2
0
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");
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
	}
}
Esempio n. 6
0
void droid_ios_video_render(render_target *our_target)
{
	int width, height;
        int minwidth, minheight;
	int viswidth, visheight;
        int aspect;

	if(myosd_video_threaded)
	   pthread_mutex_lock( &cond_mutex );

        if(currlist==NULL)
        {		                                 
                if(!myosd_inGame) 
                {
                    width  = viswidth = myosd_res_width;
                    height = visheight = myosd_res_height;
                    aspect = 0;
                }
		else if(myosd_force_pxaspect == 1)
		{                   
		    render_target_get_minimum_size(our_target, &minwidth, &minheight);   
                   
                    width = minwidth;
                    height = minheight;
		    viswidth = minwidth;
		    visheight = minheight;

                    aspect = 0;
 	        }
                else if(myosd_force_pxaspect==2)
		{
		   render_target_get_minimum_size(our_target, &minwidth, &minheight);
                   
                   width = minwidth;
                   height = minheight;

		   viswidth = minwidth;
		   visheight = minheight;
			   
                   int w,h;
		   render_target_compute_visible_area(our_target,minwidth,minheight,1,render_target_get_orientation(our_target),&w, &h);

		   if(visheight > h &&  abs((float)w/(float)h - 4.0f/3.0f) < 0.001)// 4/3 minimum
		   {
		       viswidth = w;
	  	       visheight = h;
		   }

		   if(viswidth > h * 16.0f/9.0f &&  abs((float)w/(float)h - 4.0f/3.0f) < 0.001)// 16/9 maximun
		   {
		       viswidth = h * 16.0f/9.0f;
	  	       visheight = h;
		   }

		   if(viswidth < w &&  abs((float)w/(float)h - 3.0f/4.0f) < 0.001)// 3/4 minimum
		   {
		       viswidth = w;
	  	       visheight = h;
		   }
		        
		   if(visheight > h && abs((float)w/(float)h - 3.0f/4.0f) < 0.001)// 3/4 maximun
		   {
		       viswidth = w ;
	  	       visheight = h;
		   }  
                  
                   aspect = 0;              
#ifdef ANDROID
//	__android_log_print(ANDROID_LOG_DEBUG, "VIS","FIN %d, %d",viswidth,visheight);
#endif
		}
		else //MAME standard
                {
                   if(myosd_auto_res==1)
                   {
		      render_target_get_minimum_size(our_target, &width, &height);

                      if(width > 640)
                      {
                         if(myosd_res_width > 640)
                            width = myosd_res_width;
                         else
                            width = 640;
                      }

                      if(height > 480) 
                      {
                          if(myosd_res_height > 480)
                             height = myosd_res_height;
                          else
                             height = 480;
                      }
                       
                      //calculate vis area to pass to GPU scaler instead MAME scaler. Performace and accurate!
		      render_target_compute_visible_area(our_target,width,height,1,render_target_get_orientation(our_target),&viswidth, &visheight);
                      aspect = 0;
		   }
		   else
		   {
                      width = myosd_res_width;
                      height = myosd_res_height; 			
                      viswidth = width ;
	              visheight = height;
                      aspect = width  / height;
		   }
                }

		if(width%2!=0)width++;

		// make that the size of our target
		render_target_set_bounds(our_target, width, height, aspect);

		currlist = render_target_get_primitives(our_target);

		curr_screen_width = width;
		curr_screen_height = height;
		curr_vis_area_screen_width = viswidth;
		curr_vis_area_screen_height = visheight;

		if(myosd_video_threaded)
		    pthread_cond_signal( &condition_var );
		else
	            droid_ios_video_draw();
    }


    if(myosd_video_threaded)
	   pthread_mutex_unlock( &cond_mutex );
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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:
			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 = 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
	render_target_compute_visible_area(window->target, propwidth, propheight, pixel_aspect, render_target_get_orientation(window->target), &viswidth, &visheight);

	*window_width = viswidth;
	*window_height = visheight;
}