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