xserver-multidpi/randr/mirrcrtc.c
Keith Packard 752c368421 Separate out screen size and screen pixmap sizes in RRScreenSizeSet
This provides for separate sizes for the screen scanout and rendering
buffer and the application-visible screen size.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Aaron Plattner <aplattner@nvidia.com>
2010-12-06 20:09:04 -08:00

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;
}