175 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2010 Keith Packard
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that copyright
 | |
|  * notice and this permission notice appear in supporting documentation, and
 | |
|  * that the name of the copyright holders not be used in advertising or
 | |
|  * publicity pertaining to distribution of the software without specific,
 | |
|  * written prior permission.  The copyright holders make no representations
 | |
|  * about the suitability of this software for any purpose.  It is provided "as
 | |
|  * is" without express or implied warranty.
 | |
|  *
 | |
|  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 | |
|  * OF THIS SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #include "randrstr.h"
 | |
| 
 | |
| Bool
 | |
| miRRSetScreenConfig(ScreenPtr screen,
 | |
| 		    RRScreenConfigPtr screen_config)
 | |
| {
 | |
|     RRScreenConfigRec	old_screen_config;
 | |
| 
 | |
|     RRScreenCurrentConfig(screen, &old_screen_config);
 | |
| 
 | |
|     /* Check and see if nothing has changed */
 | |
|     if (old_screen_config.screen_width == screen_config->screen_width &&
 | |
| 	old_screen_config.screen_height == screen_config->screen_height &&
 | |
| 	old_screen_config.screen_pixmap_width == screen_config->screen_pixmap_width &&
 | |
| 	old_screen_config.screen_pixmap_height == screen_config->screen_pixmap_height &&
 | |
| 	old_screen_config.mm_width == screen_config->mm_width &&
 | |
| 	old_screen_config.mm_height == screen_config->mm_height)
 | |
| 	return TRUE;
 | |
| 
 | |
|     return RRScreenSizeSet(screen,
 | |
| 			   screen_config->screen_width,
 | |
| 			   screen_config->screen_height,
 | |
| 			   screen_config->screen_pixmap_width,
 | |
| 			   screen_config->screen_pixmap_height,
 | |
| 			   screen_config->mm_width,
 | |
| 			   screen_config->mm_height);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config)
 | |
| {
 | |
|     int	x = crtc_config->x, y = crtc_config->y;
 | |
| 
 | |
|     if (crtc_config->pixmap) {
 | |
| 	x = crtc_config->pixmap_x;
 | |
| 	y = crtc_config->pixmap_y;
 | |
|     }
 | |
|     if (!RRCrtcSet(crtc_config->crtc,
 | |
| 		   crtc_config->mode,
 | |
| 		   x,
 | |
| 		   y,
 | |
| 		   crtc_config->rotation,
 | |
| 		   crtc_config->numOutputs,
 | |
| 		   crtc_config->outputs,
 | |
| 		   crtc_config->pixmap))
 | |
| 	return FALSE;
 | |
|     RRCrtcSpriteTransformSet(crtc_config->crtc,
 | |
| 			     &crtc_config->sprite_position_transform,
 | |
| 			     &crtc_config->sprite_image_transform,
 | |
| 			     &crtc_config->sprite_position_f_transform,
 | |
| 			     &crtc_config->sprite_image_f_transform);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| miRRDisableCrtc(RRCrtcPtr crtc)
 | |
| {
 | |
|     RRCrtcConfigRec	off_config;
 | |
| 
 | |
|     memset(&off_config, '\0', sizeof (RRCrtcConfigRec));
 | |
|     off_config.crtc = crtc;
 | |
|     return miRRSetCrtcConfig(&off_config);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * If the current crtc configuration doesn't fit
 | |
|  * with the new screen config, disable it
 | |
|  */
 | |
| Bool
 | |
| miRRCheckDisableCrtc(RRScreenConfigPtr new_screen_config,
 | |
| 		     RRCrtcConfigPtr old_crtc_config)
 | |
| {
 | |
|     RRCrtcPtr crtc = old_crtc_config->crtc;
 | |
| 
 | |
|     /* If it's already disabled, we're done */
 | |
|     if (!old_crtc_config->mode)
 | |
| 	return TRUE;
 | |
| 
 | |
|     /* If the crtc isn't scanning from the screen pixmap,
 | |
|      * we're done
 | |
|      */
 | |
|     if (old_crtc_config->pixmap)
 | |
| 	return TRUE;
 | |
| 
 | |
|     /* If the new screen configuration covers the existing CRTC space,
 | |
|      * we're done
 | |
|      */
 | |
|     if (RRScreenCoversCrtc(new_screen_config, old_crtc_config,
 | |
| 			   &crtc->client_current_transform, NULL))
 | |
| 	return TRUE;
 | |
| 
 | |
|     /* Disable the crtc and let it get re-enabled */
 | |
|     return miRRDisableCrtc(crtc);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| miRRSetCrtcConfigs(ScreenPtr screen,
 | |
| 		   RRScreenConfigPtr screen_config,
 | |
| 		   RRCrtcConfigPtr crtc_configs,
 | |
| 		   int num_configs)
 | |
| {
 | |
|     RRScreenConfigRec	old_screen_config;
 | |
|     RRCrtcConfigPtr	old_crtc_configs;
 | |
|     int			i;
 | |
| 
 | |
|     /*
 | |
|      * Save existing state
 | |
|      */
 | |
| 
 | |
|     RRScreenCurrentConfig(screen, &old_screen_config);
 | |
|     old_crtc_configs = calloc(num_configs, sizeof (RRCrtcConfigRec));
 | |
|     if (!old_crtc_configs)
 | |
| 	return FALSE;
 | |
| 
 | |
|     for (i = 0; i < num_configs; i++)
 | |
| 	if (!RRCrtcCurrentConfig(crtc_configs[i].crtc, &old_crtc_configs[i]))
 | |
| 	    goto fail_save;
 | |
|     /*
 | |
|      * Set the new configuration. If anything goes wrong,
 | |
|      * bail and restore the old configuration
 | |
|      */
 | |
|     for (i = 0; i < num_configs; i++)
 | |
| 	if (!miRRCheckDisableCrtc(screen_config, &old_crtc_configs[i]))
 | |
| 	    goto fail_disable;
 | |
| 
 | |
|     if (!miRRSetScreenConfig(screen, screen_config))
 | |
| 	goto fail_set_screen;
 | |
| 
 | |
|     for (i = 0; i < num_configs; i++)
 | |
| 	if (!miRRSetCrtcConfig(&crtc_configs[i]))
 | |
| 	    goto fail_set_crtc;
 | |
| 
 | |
|     RRFreeCrtcConfigs(old_crtc_configs, num_configs);
 | |
|     return TRUE;
 | |
| 
 | |
| fail_set_crtc:
 | |
|     /*
 | |
|      * Restore the previous configuration. Ignore any errors
 | |
|      * as we just need to hope that the driver can manage to
 | |
|      * get back to the previous state without trouble.
 | |
|      */
 | |
|     for (i = 0; i < num_configs; i++)
 | |
| 	(void) miRRDisableCrtc(old_crtc_configs[i].crtc);
 | |
|     (void) miRRSetScreenConfig(screen, &old_screen_config);
 | |
| fail_set_screen:
 | |
| fail_disable:
 | |
|     for (i = 0; i < num_configs; i++)
 | |
| 	(void) miRRSetCrtcConfig(&old_crtc_configs[i]);
 | |
| fail_save:
 | |
|     RRFreeCrtcConfigs(old_crtc_configs, num_configs);
 | |
|     return FALSE;
 | |
| }
 |