randr: Implement RRSetCrtcConfigs

This provides a driver-independent implementation of the
RRSetCrtcConfigs API by simply using the existing interfaces.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Aaron Plattner <aplattner@nvidia.com>
This commit is contained in:
Keith Packard 2010-12-04 19:22:11 -08:00
parent 66294afcab
commit d94a035ea9
6 changed files with 750 additions and 44 deletions

View File

@ -1797,6 +1797,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
pScrn->PointerMoved = xf86RandR12PointerMoved; pScrn->PointerMoved = xf86RandR12PointerMoved;
pScrn->ChangeGamma = xf86RandR12ChangeGamma; pScrn->ChangeGamma = xf86RandR12ChangeGamma;
rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform; rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
rp->rrSetCrtcConfigs = miRRSetCrtcConfigs;
randrp->orig_EnterVT = pScrn->EnterVT; randrp->orig_EnterVT = pScrn->EnterVT;
pScrn->EnterVT = xf86RandR12EnterVT; pScrn->EnterVT = xf86RandR12EnterVT;

View File

@ -22,7 +22,9 @@ librandr_la_SOURCES = \
rrsdispatch.c \ rrsdispatch.c \
rrsprite.c \ rrsprite.c \
rrtransform.h \ rrtransform.h \
rrtransform.c rrtransform.c \
mirrcrtc.c
if XINERAMA if XINERAMA
librandr_la_SOURCES += ${XINERAMA_SRCS} librandr_la_SOURCES += ${XINERAMA_SRCS}

169
randr/mirrcrtc.c Normal file
View File

@ -0,0 +1,169 @@
/*
* 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;
/* XXX deal with separate pixmap/screen sizes */
if (screen_config->screen_pixmap_width != screen_config->screen_width ||
screen_config->screen_pixmap_height != screen_config->screen_height)
return FALSE;
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->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;
}
return RRCrtcSet(crtc_config->crtc,
crtc_config->mode,
x,
y,
crtc_config->rotation,
crtc_config->numOutputs,
crtc_config->outputs);
}
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;
}

View File

@ -78,6 +78,8 @@ typedef struct _rrMode RRModeRec, *RRModePtr;
typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr;
typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr;
typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr;
typedef struct _rrScreenConfig RRScreenConfigRec, *RRScreenConfigPtr;
typedef struct _rrCrtcConfig RRCrtcConfigRec, *RRCrtcConfigPtr;
typedef struct _rrOutput RROutputRec, *RROutputPtr; typedef struct _rrOutput RROutputRec, *RROutputPtr;
struct _rrMode { struct _rrMode {
@ -135,6 +137,28 @@ struct _rrCrtc {
struct pict_f_transform f_sprite_image_inverse; /* image from crtc */ struct pict_f_transform f_sprite_image_inverse; /* image from crtc */
}; };
struct _rrScreenConfig {
CARD16 screen_pixmap_width;
CARD16 screen_pixmap_height;
CARD16 screen_width;
CARD16 screen_height;
CARD32 mm_width;
CARD32 mm_height;
};
struct _rrCrtcConfig {
RRCrtcPtr crtc;
int x, y;
RRModePtr mode;
Rotation rotation;
int numOutputs;
RROutputPtr *outputs;
struct pict_f_transform sprite_position_transform;
struct pict_f_transform sprite_image_transform;
PixmapPtr pixmap;
int pixmap_x, pixmap_y;
};
struct _rrOutput { struct _rrOutput {
RROutput id; RROutput id;
ScreenPtr pScreen; ScreenPtr pScreen;
@ -251,6 +275,11 @@ typedef void (*RRGetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
struct pict_f_transform *position_transform, struct pict_f_transform *position_transform,
struct pict_f_transform *image_transform); struct pict_f_transform *image_transform);
typedef Bool (*RRSetCrtcConfigsPtr) (ScreenPtr screen,
RRScreenConfigPtr screen_config,
RRCrtcConfigPtr crtc_configs,
int num_configs);
typedef struct _rrScrPriv { typedef struct _rrScrPriv {
/* /*
* 'public' part of the structure; DDXen fill this in * 'public' part of the structure; DDXen fill this in
@ -276,6 +305,7 @@ typedef struct _rrScrPriv {
#endif #endif
RRSetCrtcSpriteTransformPtr rrSetCrtcSpriteTransform; RRSetCrtcSpriteTransformPtr rrSetCrtcSpriteTransform;
RRGetCrtcSpriteTransformPtr rrGetCrtcSpriteTransform; RRGetCrtcSpriteTransformPtr rrGetCrtcSpriteTransform;
RRSetCrtcConfigsPtr rrSetCrtcConfigs;
/* /*
* Private part of the structure; not considered part of the ABI * Private part of the structure; not considered part of the ABI
@ -428,6 +458,10 @@ RRScreenSizeSet (ScreenPtr pScreen,
CARD32 mmWidth, CARD32 mmWidth,
CARD32 mmHeight); CARD32 mmHeight);
extern _X_EXPORT void
RRScreenCurrentConfig(ScreenPtr screen,
RRScreenConfigPtr screen_config);
/* /*
* Send ConfigureNotify event to root window when 'something' happens * Send ConfigureNotify event to root window when 'something' happens
*/ */
@ -670,6 +704,38 @@ RRCrtcInit (void);
extern _X_EXPORT void extern _X_EXPORT void
RRCrtcInitErrorValue (void); RRCrtcInitErrorValue (void);
/*
* Free a set of crtc configs and their attached output arrays
*/
void
RRFreeCrtcConfigs(RRCrtcConfigPtr configs, int num_configs);
/*
* Convert the current crtc configuration into an RRCrtcConfig
*/
extern _X_EXPORT Bool
RRCrtcCurrentConfig(RRCrtcPtr crtc,
RRCrtcConfigPtr crtc_config);
/*
* Figure out whether the specific crtc_config can fit
* within the screen_config
*/
Bool
RRScreenCoversCrtc(RRScreenConfigPtr screen_config,
RRCrtcConfigPtr crtc_config,
RRTransformPtr client_transform,
XID *errorValue);
/*
* Set a screen and set of crtc configurations in one operation
*/
Bool
RRSetCrtcConfigs(ScreenPtr screen,
RRScreenConfigPtr screen_config,
RRCrtcConfigPtr crtc_configs,
int num_configs);
/* /*
* Crtc dispatch * Crtc dispatch
*/ */
@ -695,6 +761,9 @@ ProcRRSetCrtcTransform (ClientPtr client);
extern _X_EXPORT int extern _X_EXPORT int
ProcRRGetCrtcTransform (ClientPtr client); ProcRRGetCrtcTransform (ClientPtr client);
extern _X_EXPORT int
ProcRRSetCrtcConfigs (ClientPtr client);
int int
ProcRRGetPanning (ClientPtr client); ProcRRGetPanning (ClientPtr client);
@ -916,6 +985,27 @@ extern _X_EXPORT void
RRXineramaExtensionInit(void); RRXineramaExtensionInit(void);
#endif #endif
/* mirrcrtc.c */
Bool
miRRSetScreenConfig(ScreenPtr screen,
RRScreenConfigPtr screen_config);
Bool
miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config);
Bool
miRRDisableCrtc(RRCrtcPtr crtc);
Bool
miRRCheckDisableCrtc(RRScreenConfigPtr new_screen_config,
RRCrtcConfigPtr old_crtc_config);
Bool
miRRSetCrtcConfigs(ScreenPtr screen,
RRScreenConfigPtr screen_config,
RRCrtcConfigPtr crtc_configs,
int num_configs);
#endif /* _RANDRSTR_H_ */ #endif /* _RANDRSTR_H_ */
/* /*

View File

@ -90,6 +90,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
crtc->devPrivate = devPrivate; crtc->devPrivate = devPrivate;
RRTransformInit (&crtc->client_pending_transform); RRTransformInit (&crtc->client_pending_transform);
RRTransformInit (&crtc->client_current_transform); RRTransformInit (&crtc->client_current_transform);
pixman_transform_init_identity (&crtc->client_sprite_position_transform);
pixman_transform_init_identity (&crtc->client_sprite_image_transform);
pixman_transform_init_identity (&crtc->transform); pixman_transform_init_identity (&crtc->transform);
pixman_f_transform_init_identity (&crtc->f_transform); pixman_f_transform_init_identity (&crtc->f_transform);
pixman_f_transform_init_identity (&crtc->f_inverse); pixman_f_transform_init_identity (&crtc->f_inverse);
@ -392,6 +394,59 @@ RRCrtcSet (RRCrtcPtr crtc,
return ret; return ret;
} }
void
RRFreeCrtcConfigs(RRCrtcConfigPtr configs, int num_configs)
{
int i;
for (i = 0; i < num_configs; i++)
free(configs[i].outputs);
free(configs);
}
Bool
RRCrtcCurrentConfig(RRCrtcPtr crtc,
RRCrtcConfigPtr crtc_config)
{
crtc_config->crtc = crtc;
crtc_config->x = crtc->x;
crtc_config->y = crtc->y;
crtc_config->mode = crtc->mode;
crtc_config->rotation = crtc->rotation;
crtc_config->numOutputs = crtc->numOutputs;
crtc_config->outputs = calloc(crtc->numOutputs, sizeof (RROutputPtr));
if (!crtc_config->outputs)
return FALSE;
memcpy(crtc_config->outputs, crtc->outputs, crtc->numOutputs * sizeof (RROutputPtr));
crtc_config->sprite_position_transform = crtc->client_sprite_f_position_transform;
crtc_config->sprite_image_transform = crtc->client_sprite_f_image_transform;
/* XXX add pixmap stuff */
crtc_config->pixmap = NULL;
crtc_config->pixmap_x = 0;
crtc_config->pixmap_y = 0;
return TRUE;
}
/*
* Request that a set of crtcs be configured at the same
* time on a single screen
*/
Bool
RRSetCrtcConfigs(ScreenPtr screen,
RRScreenConfigPtr screen_config,
RRCrtcConfigPtr crtc_configs,
int num_configs)
{
rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
if (!scr_priv)
return FALSE;
return (*scr_priv->rrSetCrtcConfigs)(screen, screen_config, crtc_configs, num_configs);
}
/* /*
* Return crtc transform * Return crtc transform
*/ */
@ -630,6 +685,44 @@ RRCrtcTransformSet (RRCrtcPtr crtc,
return Success; return Success;
} }
/*
* Figure out whether the specific crtc_config can fit
* within the screen_config
*/
Bool
RRScreenCoversCrtc(RRScreenConfigPtr screen_config,
RRCrtcConfigPtr crtc_config,
RRTransformPtr client_transform,
XID *errorValue)
{
int source_width;
int source_height;
struct pixman_f_transform f_transform;
RRTransformCompute (crtc_config->x, crtc_config->y,
crtc_config->mode->mode.width, crtc_config->mode->mode.height,
crtc_config->rotation,
client_transform,
&crtc_config->sprite_position_transform,
&crtc_config->sprite_image_transform,
NULL, &f_transform, NULL, NULL, NULL, NULL);
RRModeGetScanoutSize (crtc_config->mode, &f_transform,
&source_width, &source_height);
if (crtc_config->x + source_width > screen_config->screen_pixmap_width) {
if (errorValue)
*errorValue = crtc_config->x;
return FALSE;
}
if (crtc_config->y + source_height > screen_config->screen_pixmap_height) {
if (errorValue)
*errorValue = crtc_config->y;
return FALSE;
}
return TRUE;
}
/* /*
* Initialize crtc type * Initialize crtc type
*/ */
@ -1360,3 +1453,336 @@ ProcRRGetCrtcTransform (ClientPtr client)
free(reply); free(reply);
return Success; return Success;
} }
static void
pixman_f_transform_from_xRenderTransform(struct pixman_f_transform *f_transform,
xRenderTransform *x_transform)
{
struct pixman_transform transform;
PictTransform_from_xRenderTransform(&transform, x_transform);
pixman_f_transform_from_pixman_transform(f_transform, &transform);
}
static int
RRConvertCrtcConfig(ClientPtr client, ScreenPtr screen,
RRScreenConfigPtr screen_config,
RRCrtcConfigPtr config, xRRCrtcConfig *x,
RROutput *outputIds)
{
RRCrtcPtr crtc;
RROutputPtr *outputs;
rrScrPrivPtr scr_priv;
RRModePtr mode;
PixmapPtr pixmap;
int rc, i, j;
Rotation rotation;
VERIFY_RR_CRTC(x->crtc, crtc, DixSetAttrAccess);
if (x->mode == None)
{
mode = NULL;
if (x->nOutput > 0)
return BadMatch;
}
else
{
VERIFY_RR_MODE(x->mode, mode, DixSetAttrAccess);
if (x->nOutput == 0)
return BadMatch;
}
if (x->nOutput)
{
outputs = malloc(x->nOutput * sizeof (RROutputPtr));
if (!outputs)
return BadAlloc;
}
else
outputs = NULL;
if (x->pixmap == None)
pixmap = NULL;
else
{
rc = dixLookupResourceByType((pointer *) &pixmap, x->pixmap,
RT_PIXMAP, client, DixWriteAccess);
if (rc != Success) {
free(outputs);
return rc;
}
/* XXX check to make sure this is a scanout pixmap */
}
for (i = 0; i < x->nOutput; i++)
{
rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i],
RROutputType, client, DixSetAttrAccess);
if (rc != Success)
{
free(outputs);
return rc;
}
/* validate crtc for this output */
for (j = 0; j < outputs[i]->numCrtcs; j++)
if (outputs[i]->crtcs[j] == crtc)
break;
if (j == outputs[i]->numCrtcs)
{
free(outputs);
return BadMatch;
}
/* validate mode for this output */
for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
{
RRModePtr m = (j < outputs[i]->numModes ?
outputs[i]->modes[j] :
outputs[i]->userModes[j - outputs[i]->numModes]);
if (m == mode)
break;
}
if (j == outputs[i]->numModes + outputs[i]->numUserModes)
{
free(outputs);
return BadMatch;
}
}
/* validate clones */
for (i = 0; i < x->nOutput; i++)
{
for (j = 0; j < x->nOutput; j++)
{
int k;
if (i == j)
continue;
for (k = 0; k < outputs[i]->numClones; k++)
{
if (outputs[i]->clones[k] == outputs[j])
break;
}
if (k == outputs[i]->numClones)
{
free(outputs);
return BadMatch;
}
}
}
if (crtc->pScreen != screen)
return BadMatch;
scr_priv = rrGetScrPriv(screen);
config->crtc = crtc;
config->x = x->x;
config->y = x->y;
config->mode = mode;
config->rotation = x->rotation;
config->numOutputs = x->nOutput;
config->outputs = outputs;
pixman_f_transform_from_xRenderTransform(&config->sprite_position_transform,
&x->spritePositionTransform);
pixman_f_transform_from_xRenderTransform(&config->sprite_image_transform,
&x->spriteImageTransform);
config->pixmap = pixmap;
config->pixmap_x = x->xPixmap;
config->pixmap_y = x->yPixmap;
/*
* Validate requested rotation
*/
rotation = (Rotation) x->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = x->rotation;
free(outputs);
return BadValue;
}
if (mode)
{
if ((~crtc->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = x->rotation;
free(outputs);
return BadMatch;
}
/*
* If scanning out from another pixmap, make sure the mode
* fits
*/
if (pixmap)
{
if (x->xPixmap + mode->mode.width > pixmap->drawable.width) {
client->errorValue = x->xPixmap;
free(outputs);
return BadValue;
}
if (x->yPixmap + mode->mode.height > pixmap->drawable.height) {
client->errorValue = x->yPixmap;
free(outputs);
return BadValue;
}
}
/*
* Check screen size bounds if the DDX provides a 1.2 interface
* for setting screen size. Else, assume the CrtcSet sets
* the size along with the mode. If the driver supports transforms,
* then it must allow crtcs to display a subset of the screen, so
* only do this check for drivers without transform support.
*/
else if (scr_priv->rrScreenSetSize && !crtc->transforms)
{
if (!RRScreenCoversCrtc(screen_config, config,
&crtc->client_pending_transform,
&client->errorValue))
{
free(outputs);
return BadValue;
}
}
}
return Success;
}
int
ProcRRSetCrtcConfigs (ClientPtr client)
{
REQUEST(xRRSetCrtcConfigsReq);
xRRSetCrtcConfigsReply rep;
DrawablePtr drawable;
ScreenPtr screen;
rrScrPrivPtr scr_priv;
xRRCrtcConfig *x_configs;
RRScreenConfigRec screen_config;
RRCrtcConfigPtr configs;
RROutput *output_ids;
int num_configs;
int rc, i;
int extra_len;
int num_output_ids;
REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigsReq);
extra_len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcConfigsReq));
num_configs = stuff->nConfigs;
/* Check request length against number of configs specified */
if (num_configs * (sizeof (xRRCrtcConfig) >> 2) > extra_len)
return BadLength;
extra_len -= num_configs * (sizeof (xRRCrtcConfig) >> 2);
x_configs = (xRRCrtcConfig *) (stuff + 1);
/* Check remaining request length against number of outputs */
num_output_ids = 0;
for (i = 0; i < num_configs; i++)
num_output_ids += x_configs[i].nOutput;
if (extra_len != num_output_ids)
return BadLength;
rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
if (rc != Success)
return rc;
screen = drawable->pScreen;
scr_priv = rrGetScrPriv(screen);
if (!scr_priv)
{
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0)
{
client->errorValue = 0;
return BadValue;
}
if (stuff->screenPixmapWidth < scr_priv->minWidth ||
scr_priv->maxWidth < stuff->screenPixmapWidth)
{
client->errorValue = stuff->screenPixmapWidth;
return BadValue;
}
if (stuff->screenPixmapHeight < scr_priv->minHeight ||
scr_priv->maxHeight < stuff->screenPixmapHeight)
{
client->errorValue = stuff->screenPixmapHeight;
return BadValue;
}
screen_config.screen_pixmap_width = stuff->screenPixmapWidth;
screen_config.screen_pixmap_height = stuff->screenPixmapHeight;
screen_config.screen_width = stuff->screenWidth;
screen_config.screen_height = stuff->screenHeight;
screen_config.mm_width = stuff->widthInMillimeters;
screen_config.mm_height = stuff->heightInMillimeters;
if (num_configs == 0)
return Success;
output_ids = (RROutput *) (x_configs + num_configs);
/*
* Convert protocol crtc configurations into
* server crtc configurations
*/
configs = calloc(num_configs, sizeof (RRCrtcConfigRec));
if (!configs)
return BadAlloc;
for (i = 0; i < num_configs; i++) {
rc = RRConvertCrtcConfig(client, screen, &screen_config,
&configs[i],
&x_configs[i], output_ids);
if (rc != Success) {
rep.status = RRSetConfigFailed;
goto sendReply;
}
output_ids += x_configs[i].nOutput;
}
if (!RRSetCrtcConfigs (screen, &screen_config, configs, num_configs))
{
rep.status = RRSetConfigFailed;
goto sendReply;
}
rep.status = RRSetConfigSuccess;
scr_priv->lastSetTime = currentTime;
sendReply:
RRFreeCrtcConfigs(configs, num_configs);
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
if (client->swapped)
{
int n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
}
WriteToClient(client, sizeof(xRRSetCrtcConfigsReply), (char *)&rep);
return Success;
}

View File

@ -190,6 +190,24 @@ RRScreenSizeSet (ScreenPtr pScreen,
return FALSE; return FALSE;
} }
/*
* Compute an RRScreenConfig from the current screen information
*/
void
RRScreenCurrentConfig(ScreenPtr screen,
RRScreenConfigPtr screen_config)
{
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
WindowPtr root = screen->root;
screen_config->screen_pixmap_width = screen_pixmap->drawable.width;
screen_config->screen_pixmap_height = screen_pixmap->drawable.height;
screen_config->screen_width = root->drawable.width;
screen_config->screen_height = root->drawable.height;
screen_config->mm_width = screen->mmWidth;
screen_config->mm_height = screen->mmHeight;
}
/* /*
* Retrieve valid screen size range * Retrieve valid screen size range
*/ */