2 * Copyright © 2006 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 RR10CurrentSizeID(ScreenPtr pScreen
);
29 * Edit connection information block so that new clients
30 * see the current screen size on connect
33 RREditConnectionInfo(ScreenPtr pScreen
)
35 xConnSetup
*connSetup
;
37 xPixmapFormat
*formats
;
44 connSetup
= (xConnSetup
*) ConnectionInfo
;
45 vendor
= (char *) connSetup
+ sizeof(xConnSetup
);
46 formats
= (xPixmapFormat
*) ((char *) vendor
+
47 pad_to_int32(connSetup
->nbytesVendor
));
48 root
= (xWindowRoot
*) ((char *) formats
+
49 sizeof(xPixmapFormat
) *
50 screenInfo
.numPixmapFormats
);
51 while (screen
!= pScreen
->myNum
) {
52 depth
= (xDepth
*) ((char *) root
+ sizeof(xWindowRoot
));
53 for (d
= 0; d
< root
->nDepths
; d
++) {
54 visual
= (xVisualType
*) ((char *) depth
+ sizeof(xDepth
));
55 depth
= (xDepth
*) ((char *) visual
+
56 depth
->nVisuals
* sizeof(xVisualType
));
58 root
= (xWindowRoot
*) ((char *) depth
);
61 root
->pixWidth
= pScreen
->width
;
62 root
->pixHeight
= pScreen
->height
;
63 root
->mmWidth
= pScreen
->mmWidth
;
64 root
->mmHeight
= pScreen
->mmHeight
;
68 RRSendConfigNotify(ScreenPtr pScreen
)
70 WindowPtr pWin
= pScreen
->root
;
72 .u
.configureNotify
.window
= pWin
->drawable
.id
,
73 .u
.configureNotify
.aboveSibling
= None
,
74 .u
.configureNotify
.x
= 0,
75 .u
.configureNotify
.y
= 0,
77 /* XXX xinerama stuff ? */
79 .u
.configureNotify
.width
= pWin
->drawable
.width
,
80 .u
.configureNotify
.height
= pWin
->drawable
.height
,
81 .u
.configureNotify
.borderWidth
= wBorderWidth(pWin
),
82 .u
.configureNotify
.override
= pWin
->overrideRedirect
84 event
.u
.u
.type
= ConfigureNotify
;
85 DeliverEvents(pWin
, &event
, 1, NullWindow
);
89 RRDeliverScreenEvent(ClientPtr client
, WindowPtr pWin
, ScreenPtr pScreen
)
92 RRCrtcPtr crtc
= pScrPriv
->numCrtcs
? pScrPriv
->crtcs
[0] : NULL
;
93 WindowPtr pRoot
= pScreen
->root
;
95 xRRScreenChangeNotifyEvent se
= {
96 .type
= RRScreenChangeNotify
+ RREventBase
,
97 .rotation
= (CARD8
) (crtc
? crtc
->rotation
: RR_Rotate_0
),
98 .timestamp
= pScrPriv
->lastSetTime
.milliseconds
,
99 .configTimestamp
= pScrPriv
->lastConfigTime
.milliseconds
,
100 .root
= pRoot
->drawable
.id
,
101 .window
= pWin
->drawable
.id
,
102 .subpixelOrder
= PictureGetSubpixelOrder(pScreen
),
104 .sizeID
= RR10CurrentSizeID(pScreen
)
107 if (se
.rotation
& (RR_Rotate_90
| RR_Rotate_270
)) {
108 se
.widthInPixels
= pScreen
->height
;
109 se
.heightInPixels
= pScreen
->width
;
110 se
.widthInMillimeters
= pScreen
->mmHeight
;
111 se
.heightInMillimeters
= pScreen
->mmWidth
;
114 se
.widthInPixels
= pScreen
->width
;
115 se
.heightInPixels
= pScreen
->height
;
116 se
.widthInMillimeters
= pScreen
->mmWidth
;
117 se
.heightInMillimeters
= pScreen
->mmHeight
;
120 WriteEventsToClient(client
, 1, (xEvent
*) &se
);
124 * Notify the extension that the screen size has been changed.
125 * The driver is responsible for calling this whenever it has changed
126 * the size of the screen
129 RRScreenSizeNotify(ScreenPtr pScreen
)
133 * Deliver ConfigureNotify events when root changes
136 if (pScrPriv
->width
== pScreen
->width
&&
137 pScrPriv
->height
== pScreen
->height
&&
138 pScrPriv
->mmWidth
== pScreen
->mmWidth
&&
139 pScrPriv
->mmHeight
== pScreen
->mmHeight
)
142 pScrPriv
->width
= pScreen
->width
;
143 pScrPriv
->height
= pScreen
->height
;
144 pScrPriv
->mmWidth
= pScreen
->mmWidth
;
145 pScrPriv
->mmHeight
= pScreen
->mmHeight
;
146 RRSetChanged(pScreen
);
147 /* pScrPriv->sizeChanged = TRUE; */
149 RRTellChanged(pScreen
);
150 RRSendConfigNotify(pScreen
);
151 RREditConnectionInfo(pScreen
);
153 RRPointerScreenConfigured(pScreen
);
155 * Fix pointer bounds and location
157 ScreenRestructured(pScreen
);
161 * Request that the screen be resized
164 RRScreenSizeSet(ScreenPtr pScreen
,
165 CARD16 width
, CARD16 height
, CARD32 mmWidth
, CARD32 mmHeight
)
169 #if RANDR_12_INTERFACE
170 if (pScrPriv
->rrScreenSetSize
) {
171 return (*pScrPriv
->rrScreenSetSize
) (pScreen
,
172 width
, height
, mmWidth
, mmHeight
);
175 #if RANDR_10_INTERFACE
176 if (pScrPriv
->rrSetConfig
) {
177 return TRUE
; /* can't set size separately */
184 * Retrieve valid screen size range
187 ProcRRGetScreenSizeRange(ClientPtr client
)
189 REQUEST(xRRGetScreenSizeRangeReq
);
190 xRRGetScreenSizeRangeReply rep
;
193 rrScrPrivPtr pScrPriv
;
196 REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq
);
197 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
201 pScreen
= pWin
->drawable
.pScreen
;
202 pScrPriv
= rrGetScrPriv(pScreen
);
204 rep
= (xRRGetScreenSizeRangeReply
) {
207 .sequenceNumber
= client
->sequence
,
212 if (!RRGetInfo(pScreen
, FALSE
))
214 rep
.minWidth
= pScrPriv
->minWidth
;
215 rep
.minHeight
= pScrPriv
->minHeight
;
216 rep
.maxWidth
= pScrPriv
->maxWidth
;
217 rep
.maxHeight
= pScrPriv
->maxHeight
;
220 rep
.maxWidth
= rep
.minWidth
= pScreen
->width
;
221 rep
.maxHeight
= rep
.minHeight
= pScreen
->height
;
223 if (client
->swapped
) {
224 swaps(&rep
.sequenceNumber
);
226 swaps(&rep
.minWidth
);
227 swaps(&rep
.minHeight
);
228 swaps(&rep
.maxWidth
);
229 swaps(&rep
.maxHeight
);
231 WriteToClient(client
, sizeof(xRRGetScreenSizeRangeReply
), &rep
);
236 ProcRRSetScreenSize(ClientPtr client
)
238 REQUEST(xRRSetScreenSizeReq
);
241 rrScrPrivPtr pScrPriv
;
244 REQUEST_SIZE_MATCH(xRRSetScreenSizeReq
);
245 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
249 pScreen
= pWin
->drawable
.pScreen
;
250 pScrPriv
= rrGetScrPriv(pScreen
);
254 if (stuff
->width
< pScrPriv
->minWidth
|| pScrPriv
->maxWidth
< stuff
->width
) {
255 client
->errorValue
= stuff
->width
;
258 if (stuff
->height
< pScrPriv
->minHeight
||
259 pScrPriv
->maxHeight
< stuff
->height
) {
260 client
->errorValue
= stuff
->height
;
263 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++) {
264 RRCrtcPtr crtc
= pScrPriv
->crtcs
[i
];
265 RRModePtr mode
= crtc
->mode
;
268 int source_width
= mode
->mode
.width
;
269 int source_height
= mode
->mode
.height
;
270 Rotation rotation
= crtc
->rotation
;
272 if (rotation
== RR_Rotate_90
|| rotation
== RR_Rotate_270
) {
273 source_width
= mode
->mode
.height
;
274 source_height
= mode
->mode
.width
;
277 if (crtc
->x
+ source_width
> stuff
->width
||
278 crtc
->y
+ source_height
> stuff
->height
)
282 if (stuff
->widthInMillimeters
== 0 || stuff
->heightInMillimeters
== 0) {
283 client
->errorValue
= 0;
286 if (!RRScreenSizeSet(pScreen
,
287 stuff
->width
, stuff
->height
,
288 stuff
->widthInMillimeters
,
289 stuff
->heightInMillimeters
)) {
296 #define update_totals(gpuscreen, pScrPriv) do { \
297 total_crtcs += pScrPriv->numCrtcs; \
298 total_outputs += pScrPriv->numOutputs; \
299 modes = RRModesForScreen(gpuscreen, &num_modes); \
302 for (j = 0; j < num_modes; j++) \
303 total_name_len += modes[j]->mode.nameLength; \
304 total_modes += num_modes; \
308 static inline void swap_modeinfos(xRRModeInfo
*modeinfos
, int i
)
310 swapl(&modeinfos
[i
].id
);
311 swaps(&modeinfos
[i
].width
);
312 swaps(&modeinfos
[i
].height
);
313 swapl(&modeinfos
[i
].dotClock
);
314 swaps(&modeinfos
[i
].hSyncStart
);
315 swaps(&modeinfos
[i
].hSyncEnd
);
316 swaps(&modeinfos
[i
].hTotal
);
317 swaps(&modeinfos
[i
].hSkew
);
318 swaps(&modeinfos
[i
].vSyncStart
);
319 swaps(&modeinfos
[i
].vSyncEnd
);
320 swaps(&modeinfos
[i
].vTotal
);
321 swaps(&modeinfos
[i
].nameLength
);
322 swapl(&modeinfos
[i
].modeFlags
);
325 #define update_arrays(gpuscreen, pScrPriv) do { \
326 for (j = 0; j < pScrPriv->numCrtcs; j++) { \
327 crtcs[crtc_count] = pScrPriv->crtcs[j]->id; \
328 if (client->swapped) \
329 swapl(&crtcs[crtc_count]); \
332 for (j = 0; j < pScrPriv->numOutputs; j++) { \
333 outputs[output_count] = pScrPriv->outputs[j]->id; \
334 if (client->swapped) \
335 swapl(&outputs[output_count]); \
340 modes = RRModesForScreen(gpuscreen, &num_modes); \
341 for (j = 0; j < num_modes; j++) { \
343 modeinfos[mode_count] = mode->mode; \
344 if (client->swapped) { \
345 swap_modeinfos(modeinfos, mode_count); \
347 memcpy(names, mode->name, mode->mode.nameLength); \
348 names += mode->mode.nameLength; \
356 rrGetMultiScreenResources(ClientPtr client
, Bool query
, ScreenPtr pScreen
)
359 int total_crtcs
, total_outputs
, total_modes
, total_name_len
;
360 int crtc_count
, output_count
, mode_count
;
362 rrScrPrivPtr pScrPriv
;
365 xRRGetScreenResourcesReply rep
;
366 unsigned long extraLen
;
370 xRRModeInfo
*modeinfos
;
373 /* we need to iterate all the GPU masters and all their output slaves */
379 pScrPriv
= rrGetScrPriv(pScreen
);
381 if (query
&& pScrPriv
)
382 if (!RRGetInfo(pScreen
, query
))
385 update_totals(pScreen
, pScrPriv
);
387 xorg_list_for_each_entry(iter
, &pScreen
->output_slave_list
, output_head
) {
388 pScrPriv
= rrGetScrPriv(iter
);
391 if (!RRGetInfo(iter
, query
))
393 update_totals(iter
, pScrPriv
);
396 ErrorF("reporting %d %d %d %d\n", total_crtcs
, total_outputs
, total_modes
, total_name_len
);
398 pScrPriv
= rrGetScrPriv(pScreen
);
399 rep
= (xRRGetScreenResourcesReply
) {
401 .sequenceNumber
= client
->sequence
,
403 .timestamp
= pScrPriv
->lastSetTime
.milliseconds
,
404 .configTimestamp
= pScrPriv
->lastConfigTime
.milliseconds
,
405 .nCrtcs
= total_crtcs
,
406 .nOutputs
= total_outputs
,
407 .nModes
= total_modes
,
408 .nbytesNames
= total_name_len
411 rep
.length
= (total_crtcs
+ total_outputs
+ total_modes
* bytes_to_int32(SIZEOF(xRRModeInfo
)) +
412 bytes_to_int32(rep
.nbytesNames
));
414 extraLen
= rep
.length
<< 2;
416 extra
= malloc(extraLen
);
424 crtcs
= (RRCrtc
*)extra
;
425 outputs
= (RROutput
*)(crtcs
+ total_crtcs
);
426 modeinfos
= (xRRModeInfo
*)(outputs
+ total_outputs
);
427 names
= (CARD8
*)(modeinfos
+ total_modes
);
434 pScrPriv
= rrGetScrPriv(pScreen
);
435 update_arrays(pScreen
, pScrPriv
);
437 xorg_list_for_each_entry(iter
, &pScreen
->output_slave_list
, output_head
) {
438 pScrPriv
= rrGetScrPriv(iter
);
440 update_arrays(iter
, pScrPriv
);
443 assert(bytes_to_int32((char *) names
- (char *) extra
) == rep
.length
);
444 if (client
->swapped
) {
445 swaps(&rep
.sequenceNumber
);
447 swapl(&rep
.timestamp
);
448 swapl(&rep
.configTimestamp
);
450 swaps(&rep
.nOutputs
);
452 swaps(&rep
.nbytesNames
);
454 WriteToClient(client
, sizeof(xRRGetScreenResourcesReply
), &rep
);
456 WriteToClient(client
, extraLen
, extra
);
463 rrGetScreenResources(ClientPtr client
, Bool query
)
465 REQUEST(xRRGetScreenResourcesReq
);
466 xRRGetScreenResourcesReply rep
;
469 rrScrPrivPtr pScrPriv
;
471 unsigned long extraLen
;
472 int i
, rc
, has_primary
= 0;
475 xRRModeInfo
*modeinfos
;
478 REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq
);
479 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
483 pScreen
= pWin
->drawable
.pScreen
;
484 pScrPriv
= rrGetScrPriv(pScreen
);
486 if (query
&& pScrPriv
)
487 if (!RRGetInfo(pScreen
, query
))
490 if (!xorg_list_is_empty(&pScreen
->output_slave_list
))
491 return rrGetMultiScreenResources(client
, query
, pScreen
);
494 rep
= (xRRGetScreenResourcesReply
) {
496 .sequenceNumber
= client
->sequence
,
498 .timestamp
= currentTime
.milliseconds
,
499 .configTimestamp
= currentTime
.milliseconds
,
512 modes
= RRModesForScreen(pScreen
, &num_modes
);
516 rep
= (xRRGetScreenResourcesReply
) {
518 .sequenceNumber
= client
->sequence
,
520 .timestamp
= pScrPriv
->lastSetTime
.milliseconds
,
521 .configTimestamp
= pScrPriv
->lastConfigTime
.milliseconds
,
522 .nCrtcs
= pScrPriv
->numCrtcs
,
523 .nOutputs
= pScrPriv
->numOutputs
,
529 for (i
= 0; i
< num_modes
; i
++)
530 rep
.nbytesNames
+= modes
[i
]->mode
.nameLength
;
532 rep
.length
= (pScrPriv
->numCrtcs
+
533 pScrPriv
->numOutputs
+
534 num_modes
* bytes_to_int32(SIZEOF(xRRModeInfo
)) +
535 bytes_to_int32(rep
.nbytesNames
));
537 extraLen
= rep
.length
<< 2;
539 extra
= malloc(extraLen
);
548 crtcs
= (RRCrtc
*) extra
;
549 outputs
= (RROutput
*) (crtcs
+ pScrPriv
->numCrtcs
);
550 modeinfos
= (xRRModeInfo
*) (outputs
+ pScrPriv
->numOutputs
);
551 names
= (CARD8
*) (modeinfos
+ num_modes
);
553 if (pScrPriv
->primaryOutput
&& pScrPriv
->primaryOutput
->crtc
) {
555 crtcs
[0] = pScrPriv
->primaryOutput
->crtc
->id
;
560 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++) {
562 pScrPriv
->primaryOutput
->crtc
== pScrPriv
->crtcs
[i
]) {
566 crtcs
[i
+ has_primary
] = pScrPriv
->crtcs
[i
]->id
;
568 swapl(&crtcs
[i
+ has_primary
]);
571 for (i
= 0; i
< pScrPriv
->numOutputs
; i
++) {
572 outputs
[i
] = pScrPriv
->outputs
[i
]->id
;
577 for (i
= 0; i
< num_modes
; i
++) {
578 RRModePtr mode
= modes
[i
];
580 modeinfos
[i
] = mode
->mode
;
581 if (client
->swapped
) {
582 swapl(&modeinfos
[i
].id
);
583 swaps(&modeinfos
[i
].width
);
584 swaps(&modeinfos
[i
].height
);
585 swapl(&modeinfos
[i
].dotClock
);
586 swaps(&modeinfos
[i
].hSyncStart
);
587 swaps(&modeinfos
[i
].hSyncEnd
);
588 swaps(&modeinfos
[i
].hTotal
);
589 swaps(&modeinfos
[i
].hSkew
);
590 swaps(&modeinfos
[i
].vSyncStart
);
591 swaps(&modeinfos
[i
].vSyncEnd
);
592 swaps(&modeinfos
[i
].vTotal
);
593 swaps(&modeinfos
[i
].nameLength
);
594 swapl(&modeinfos
[i
].modeFlags
);
596 memcpy(names
, mode
->name
, mode
->mode
.nameLength
);
597 names
+= mode
->mode
.nameLength
;
600 assert(bytes_to_int32((char *) names
- (char *) extra
) == rep
.length
);
603 if (client
->swapped
) {
604 swaps(&rep
.sequenceNumber
);
606 swapl(&rep
.timestamp
);
607 swapl(&rep
.configTimestamp
);
609 swaps(&rep
.nOutputs
);
611 swaps(&rep
.nbytesNames
);
613 WriteToClient(client
, sizeof(xRRGetScreenResourcesReply
), (char *) &rep
);
615 WriteToClient(client
, extraLen
, (char *) extra
);
622 ProcRRGetScreenResources(ClientPtr client
)
624 return rrGetScreenResources(client
, TRUE
);
628 ProcRRGetScreenResourcesCurrent(ClientPtr client
)
630 return rrGetScreenResources(client
, FALSE
);
633 typedef struct _RR10Data
{
634 RRScreenSizePtr sizes
;
639 } RR10DataRec
, *RR10DataPtr
;
642 * Convert 1.2 monitor data into 1.0 screen data
645 RR10GetData(ScreenPtr pScreen
, RROutputPtr output
)
648 RRScreenSizePtr size
;
649 int nmode
= output
->numModes
+ output
->numUserModes
;
651 RRScreenRatePtr refresh
;
656 /* Make sure there is plenty of space for any combination */
657 data
= malloc(sizeof(RR10DataRec
) +
658 sizeof(RRScreenSize
) * nmode
+
659 sizeof(RRScreenRate
) * nmode
+ sizeof(Bool
) * nmode
);
662 size
= (RRScreenSizePtr
) (data
+ 1);
663 refresh
= (RRScreenRatePtr
) (size
+ nmode
);
664 used
= (Bool
*) (refresh
+ nmode
);
665 memset(used
, '\0', sizeof(Bool
) * nmode
);
673 * find modes not yet listed
675 for (o
= 0; o
< output
->numModes
+ output
->numUserModes
; o
++) {
679 if (o
< output
->numModes
)
680 mode
= output
->modes
[o
];
682 mode
= output
->userModes
[o
- output
->numModes
];
685 size
[l
].id
= data
->nsize
;
686 size
[l
].width
= mode
->mode
.width
;
687 size
[l
].height
= mode
->mode
.height
;
688 if (output
->mmWidth
&& output
->mmHeight
) {
689 size
[l
].mmWidth
= output
->mmWidth
;
690 size
[l
].mmHeight
= output
->mmHeight
;
693 size
[l
].mmWidth
= pScreen
->mmWidth
;
694 size
[l
].mmHeight
= pScreen
->mmHeight
;
697 size
[l
].pRates
= &refresh
[data
->nrefresh
];
701 * Find all modes with matching size
703 for (os
= o
; os
< output
->numModes
+ output
->numUserModes
; os
++) {
704 if (os
< output
->numModes
)
705 mode
= output
->modes
[os
];
707 mode
= output
->userModes
[os
- output
->numModes
];
708 if (mode
->mode
.width
== size
[l
].width
&&
709 mode
->mode
.height
== size
[l
].height
) {
710 vRefresh
= RRVerticalRefresh(&mode
->mode
);
713 for (r
= 0; r
< size
[l
].nRates
; r
++)
714 if (vRefresh
== size
[l
].pRates
[r
].rate
)
716 if (r
== size
[l
].nRates
) {
717 size
[l
].pRates
[r
].rate
= vRefresh
;
718 size
[l
].pRates
[r
].mode
= mode
;
722 if (mode
== output
->crtc
->mode
) {
724 data
->refresh
= vRefresh
;
733 ProcRRGetScreenInfo(ClientPtr client
)
735 REQUEST(xRRGetScreenInfoReq
);
736 xRRGetScreenInfoReply rep
;
740 rrScrPrivPtr pScrPriv
;
742 unsigned long extraLen
;
745 REQUEST_SIZE_MATCH(xRRGetScreenInfoReq
);
746 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
750 pScreen
= pWin
->drawable
.pScreen
;
751 pScrPriv
= rrGetScrPriv(pScreen
);
754 if (!RRGetInfo(pScreen
, TRUE
))
757 output
= RRFirstOutput(pScreen
);
759 if (!pScrPriv
|| !output
) {
760 rep
= (xRRGetScreenInfoReply
) {
762 .setOfRotations
= RR_Rotate_0
,
763 .sequenceNumber
= client
->sequence
,
765 .root
= pWin
->drawable
.pScreen
->root
->drawable
.id
,
766 .timestamp
= currentTime
.milliseconds
,
767 .configTimestamp
= currentTime
.milliseconds
,
770 .rotation
= RR_Rotate_0
,
782 Bool has_rate
= RRClientKnowsRates(client
);
784 RRScreenSizePtr pSize
;
786 pData
= RR10GetData(pScreen
, output
);
790 rep
= (xRRGetScreenInfoReply
) {
792 .setOfRotations
= output
->crtc
->rotations
,
793 .sequenceNumber
= client
->sequence
,
795 .root
= pWin
->drawable
.pScreen
->root
->drawable
.id
,
796 .timestamp
= pScrPriv
->lastSetTime
.milliseconds
,
797 .configTimestamp
= pScrPriv
->lastConfigTime
.milliseconds
,
798 .rotation
= output
->crtc
->rotation
,
799 .nSizes
= pData
->nsize
,
800 .nrateEnts
= pData
->nrefresh
+ pData
->nsize
,
801 .sizeID
= pData
->size
,
802 .rate
= pData
->refresh
805 extraLen
= rep
.nSizes
* sizeof(xScreenSizes
);
807 extraLen
+= rep
.nrateEnts
* sizeof(CARD16
);
810 extra
= (CARD8
*) malloc(extraLen
);
820 * First comes the size information
822 size
= (xScreenSizes
*) extra
;
823 rates
= (CARD16
*) (size
+ rep
.nSizes
);
824 for (i
= 0; i
< pData
->nsize
; i
++) {
825 pSize
= &pData
->sizes
[i
];
826 size
->widthInPixels
= pSize
->width
;
827 size
->heightInPixels
= pSize
->height
;
828 size
->widthInMillimeters
= pSize
->mmWidth
;
829 size
->heightInMillimeters
= pSize
->mmHeight
;
830 if (client
->swapped
) {
831 swaps(&size
->widthInPixels
);
832 swaps(&size
->heightInPixels
);
833 swaps(&size
->widthInMillimeters
);
834 swaps(&size
->heightInMillimeters
);
838 *rates
= pSize
->nRates
;
839 if (client
->swapped
) {
843 for (j
= 0; j
< pSize
->nRates
; j
++) {
844 *rates
= pSize
->pRates
[j
].rate
;
845 if (client
->swapped
) {
854 data8
= (CARD8
*) rates
;
856 if (data8
- (CARD8
*) extra
!= extraLen
)
857 FatalError("RRGetScreenInfo bad extra len %ld != %ld\n",
858 (unsigned long) (data8
- (CARD8
*) extra
), extraLen
);
859 rep
.length
= bytes_to_int32(extraLen
);
861 if (client
->swapped
) {
862 swaps(&rep
.sequenceNumber
);
864 swapl(&rep
.timestamp
);
865 swapl(&rep
.configTimestamp
);
866 swaps(&rep
.rotation
);
870 swaps(&rep
.nrateEnts
);
872 WriteToClient(client
, sizeof(xRRGetScreenInfoReply
), &rep
);
874 WriteToClient(client
, extraLen
, extra
);
881 ProcRRSetScreenConfig(ClientPtr client
)
883 REQUEST(xRRSetScreenConfigReq
);
884 xRRSetScreenConfigReply rep
;
888 rrScrPrivPtr pScrPriv
;
898 RR10DataPtr pData
= NULL
;
899 RRScreenSizePtr pSize
;
904 if (RRClientKnowsRates(client
)) {
905 REQUEST_SIZE_MATCH(xRRSetScreenConfigReq
);
909 REQUEST_SIZE_MATCH(xRR1_0SetScreenConfigReq
);
913 rc
= dixLookupDrawable(&pDraw
, stuff
->drawable
, client
, 0, DixWriteAccess
);
917 pScreen
= pDraw
->pScreen
;
919 pScrPriv
= rrGetScrPriv(pScreen
);
921 time
= ClientTimeToServerTime(stuff
->timestamp
);
925 status
= RRSetConfigFailed
;
928 if (!RRGetInfo(pScreen
, FALSE
))
931 output
= RRFirstOutput(pScreen
);
934 status
= RRSetConfigFailed
;
941 * If the client's config timestamp is not the same as the last config
942 * timestamp, then the config information isn't up-to-date and
943 * can't even be validated.
945 * Note that the client only knows about the milliseconds part of the
946 * timestamp, so using CompareTimeStamps here would cause randr to suddenly
947 * stop working after several hours have passed (freedesktop bug #6502).
949 if (stuff
->configTimestamp
!= pScrPriv
->lastConfigTime
.milliseconds
) {
950 status
= RRSetConfigInvalidConfigTime
;
954 pData
= RR10GetData(pScreen
, output
);
958 if (stuff
->sizeID
>= pData
->nsize
) {
962 client
->errorValue
= stuff
->sizeID
;
966 pSize
= &pData
->sizes
[stuff
->sizeID
];
969 * Validate requested rotation
971 rotation
= (Rotation
) stuff
->rotation
;
973 /* test the rotation bits only! */
974 switch (rotation
& 0xf) {
984 client
->errorValue
= stuff
->rotation
;
989 if ((~crtc
->rotations
) & rotation
) {
991 * requested rotation or reflection not supported by screen
993 client
->errorValue
= stuff
->rotation
;
999 * Validate requested refresh
1002 rate
= (int) stuff
->rate
;
1007 for (i
= 0; i
< pSize
->nRates
; i
++) {
1008 if (pSize
->pRates
[i
].rate
== rate
)
1011 if (i
== pSize
->nRates
) {
1015 client
->errorValue
= rate
;
1019 mode
= pSize
->pRates
[i
].mode
;
1022 mode
= pSize
->pRates
[0].mode
;
1025 * Make sure the requested set-time is not older than
1028 if (CompareTimeStamps(time
, pScrPriv
->lastSetTime
) < 0) {
1029 status
= RRSetConfigInvalidTime
;
1034 * If the screen size is changing, adjust all of the other outputs
1035 * to fit the new size, mirroring as much as possible
1037 width
= mode
->mode
.width
;
1038 height
= mode
->mode
.height
;
1039 if (width
< pScrPriv
->minWidth
|| pScrPriv
->maxWidth
< width
) {
1040 client
->errorValue
= width
;
1044 if (height
< pScrPriv
->minHeight
|| pScrPriv
->maxHeight
< height
) {
1045 client
->errorValue
= height
;
1050 if (rotation
& (RR_Rotate_90
| RR_Rotate_270
)) {
1051 width
= mode
->mode
.height
;
1052 height
= mode
->mode
.width
;
1055 if (width
!= pScreen
->width
|| height
!= pScreen
->height
) {
1058 for (c
= 0; c
< pScrPriv
->numCrtcs
; c
++) {
1059 if (!RRCrtcSet(pScrPriv
->crtcs
[c
], NULL
, 0, 0, RR_Rotate_0
,
1061 status
= RRSetConfigFailed
;
1062 /* XXX recover from failure */
1066 if (!RRScreenSizeSet(pScreen
, width
, height
,
1067 pScreen
->mmWidth
, pScreen
->mmHeight
)) {
1068 status
= RRSetConfigFailed
;
1069 /* XXX recover from failure */
1074 if (!RRCrtcSet(crtc
, mode
, 0, 0, stuff
->rotation
, 1, &output
))
1075 status
= RRSetConfigFailed
;
1077 pScrPriv
->lastSetTime
= time
;
1078 status
= RRSetConfigSuccess
;
1082 * XXX Configure other crtcs to mirror as much as possible
1089 rep
= (xRRSetScreenConfigReply
) {
1092 .sequenceNumber
= client
->sequence
,
1095 .newTimestamp
= pScrPriv
->lastSetTime
.milliseconds
,
1096 .newConfigTimestamp
= pScrPriv
->lastConfigTime
.milliseconds
,
1097 .root
= pDraw
->pScreen
->root
->drawable
.id
,
1098 /* .subpixelOrder = ?? */
1101 if (client
->swapped
) {
1102 swaps(&rep
.sequenceNumber
);
1104 swapl(&rep
.newTimestamp
);
1105 swapl(&rep
.newConfigTimestamp
);
1108 WriteToClient(client
, sizeof(xRRSetScreenConfigReply
), &rep
);
1114 RR10CurrentSizeID(ScreenPtr pScreen
)
1116 CARD16 sizeID
= 0xffff;
1117 RROutputPtr output
= RRFirstOutput(pScreen
);
1120 RR10DataPtr data
= RR10GetData(pScreen
, output
);
1125 for (i
= 0; i
< data
->nsize
; i
++)
1126 if (data
->sizes
[i
].width
== pScreen
->width
&&
1127 data
->sizes
[i
].height
== pScreen
->height
) {
1128 sizeID
= (CARD16
) i
;