2 * Copyright © 2000 Compaq Computer Corporation
3 * Copyright © 2002 Hewlett-Packard Company
4 * Copyright © 2006 Intel Corporation
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that copyright
9 * notice and this permission notice appear in supporting documentation, and
10 * that the name of the copyright holders not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. The copyright holders make no representations
13 * about the suitability of this software for any purpose. It is provided "as
14 * is" without express or implied warranty.
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * Author: Jim Gettys, Hewlett-Packard Company, Inc.
25 * Keith Packard, Intel Corporation
28 #ifdef HAVE_DIX_CONFIG_H
29 #include <dix-config.h>
36 #ifndef SubPixelUnknown
37 #define SubPixelUnknown 0
41 static int RRNScreens;
43 #define wrap(priv,real,mem,func) {\
44 priv->mem = real->mem; \
48 #define unwrap(priv,real,mem) {\
49 real->mem = priv->mem; \
52 static int ProcRRDispatch(ClientPtr pClient);
53 static int SProcRRDispatch(ClientPtr pClient);
57 RESTYPE RRClientType, RREventType; /* resource types for event masks */
58 DevPrivateKeyRec RRClientPrivateKeyRec;
60 DevPrivateKeyRec rrPrivKeyRec;
63 RRClientCallback(CallbackListPtr *list, pointer closure, pointer data)
65 NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
66 ClientPtr pClient = clientinfo->client;
68 rrClientPriv(pClient);
69 RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
72 pRRClient->major_version = 0;
73 pRRClient->minor_version = 0;
74 for (i = 0; i < screenInfo.numScreens; i++) {
75 ScreenPtr pScreen = screenInfo.screens[i];
80 pTimes[i].setTime = pScrPriv->lastSetTime;
81 pTimes[i].configTime = pScrPriv->lastConfigTime;
87 RRCloseScreen(ScreenPtr pScreen)
92 unwrap(pScrPriv, pScreen, CloseScreen);
93 for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
94 RRCrtcDestroy(pScrPriv->crtcs[j]);
95 for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
96 RROutputDestroy(pScrPriv->outputs[j]);
98 if (pScrPriv->provider)
99 RRProviderDestroy(pScrPriv->provider);
101 free(pScrPriv->crtcs);
102 free(pScrPriv->outputs);
104 RRNScreens -= 1; /* ok, one fewer screen with RandR running */
105 return (*pScreen->CloseScreen) (pScreen);
109 SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,
110 xRRScreenChangeNotifyEvent * to)
112 to->type = from->type;
113 to->rotation = from->rotation;
114 cpswaps(from->sequenceNumber, to->sequenceNumber);
115 cpswapl(from->timestamp, to->timestamp);
116 cpswapl(from->configTimestamp, to->configTimestamp);
117 cpswapl(from->root, to->root);
118 cpswapl(from->window, to->window);
119 cpswaps(from->sizeID, to->sizeID);
120 cpswaps(from->subpixelOrder, to->subpixelOrder);
121 cpswaps(from->widthInPixels, to->widthInPixels);
122 cpswaps(from->heightInPixels, to->heightInPixels);
123 cpswaps(from->widthInMillimeters, to->widthInMillimeters);
124 cpswaps(from->heightInMillimeters, to->heightInMillimeters);
128 SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,
129 xRRCrtcChangeNotifyEvent * to)
131 to->type = from->type;
132 to->subCode = from->subCode;
133 cpswaps(from->sequenceNumber, to->sequenceNumber);
134 cpswapl(from->timestamp, to->timestamp);
135 cpswapl(from->window, to->window);
136 cpswapl(from->crtc, to->crtc);
137 cpswapl(from->mode, to->mode);
138 cpswaps(from->rotation, to->rotation);
140 cpswaps(from->x, to->x);
141 cpswaps(from->y, to->y);
142 cpswaps(from->width, to->width);
143 cpswaps(from->height, to->height);
147 SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,
148 xRROutputChangeNotifyEvent * to)
150 to->type = from->type;
151 to->subCode = from->subCode;
152 cpswaps(from->sequenceNumber, to->sequenceNumber);
153 cpswapl(from->timestamp, to->timestamp);
154 cpswapl(from->configTimestamp, to->configTimestamp);
155 cpswapl(from->window, to->window);
156 cpswapl(from->output, to->output);
157 cpswapl(from->crtc, to->crtc);
158 cpswapl(from->mode, to->mode);
159 cpswaps(from->rotation, to->rotation);
160 to->connection = from->connection;
161 to->subpixelOrder = from->subpixelOrder;
165 SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
166 xRROutputPropertyNotifyEvent * to)
168 to->type = from->type;
169 to->subCode = from->subCode;
170 cpswaps(from->sequenceNumber, to->sequenceNumber);
171 cpswapl(from->window, to->window);
172 cpswapl(from->output, to->output);
173 cpswapl(from->atom, to->atom);
174 cpswapl(from->timestamp, to->timestamp);
175 to->state = from->state;
183 SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,
184 xRRProviderChangeNotifyEvent * to)
186 to->type = from->type;
187 to->subCode = from->subCode;
188 cpswaps(from->sequenceNumber, to->sequenceNumber);
189 cpswapl(from->timestamp, to->timestamp);
190 cpswapl(from->window, to->window);
191 cpswapl(from->provider, to->provider);
195 SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,
196 xRRProviderPropertyNotifyEvent * to)
198 to->type = from->type;
199 to->subCode = from->subCode;
200 cpswaps(from->sequenceNumber, to->sequenceNumber);
201 cpswapl(from->window, to->window);
202 cpswapl(from->provider, to->provider);
203 cpswapl(from->atom, to->atom);
204 cpswapl(from->timestamp, to->timestamp);
205 to->state = from->state;
213 SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
214 xRRResourceChangeNotifyEvent * to)
216 to->type = from->type;
217 to->subCode = from->subCode;
218 cpswaps(from->sequenceNumber, to->sequenceNumber);
219 cpswapl(from->timestamp, to->timestamp);
220 cpswapl(from->window, to->window);
224 SRRNotifyEvent(xEvent *from, xEvent *to)
226 switch (from->u.u.detail) {
227 case RRNotify_CrtcChange:
228 SRRCrtcChangeNotifyEvent((xRRCrtcChangeNotifyEvent *) from,
229 (xRRCrtcChangeNotifyEvent *) to);
231 case RRNotify_OutputChange:
232 SRROutputChangeNotifyEvent((xRROutputChangeNotifyEvent *) from,
233 (xRROutputChangeNotifyEvent *) to);
235 case RRNotify_OutputProperty:
236 SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
237 (xRROutputPropertyNotifyEvent *) to);
239 case RRNotify_ProviderChange:
240 SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from,
241 (xRRProviderChangeNotifyEvent *) to);
243 case RRNotify_ProviderProperty:
244 SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from,
245 (xRRProviderPropertyNotifyEvent *) to);
247 case RRNotify_ResourceChange:
248 SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
249 (xRRResourceChangeNotifyEvent *) to);
255 static int RRGeneration;
260 if (RRGeneration != serverGeneration) {
267 RRGeneration = serverGeneration;
269 if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
276 RRScreenInit(ScreenPtr pScreen)
278 rrScrPrivPtr pScrPriv;
283 pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
287 SetRRScreen(pScreen, pScrPriv);
290 * Calling function best set these function vectors
292 pScrPriv->rrGetInfo = 0;
293 pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
294 pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
296 pScrPriv->width = pScreen->width;
297 pScrPriv->height = pScreen->height;
298 pScrPriv->mmWidth = pScreen->mmWidth;
299 pScrPriv->mmHeight = pScreen->mmHeight;
300 #if RANDR_12_INTERFACE
301 pScrPriv->rrScreenSetSize = NULL;
302 pScrPriv->rrCrtcSet = NULL;
303 pScrPriv->rrCrtcSetGamma = NULL;
305 #if RANDR_10_INTERFACE
306 pScrPriv->rrSetConfig = 0;
307 pScrPriv->rotations = RR_Rotate_0;
308 pScrPriv->reqWidth = pScreen->width;
309 pScrPriv->reqHeight = pScreen->height;
310 pScrPriv->nSizes = 0;
311 pScrPriv->pSizes = NULL;
312 pScrPriv->rotation = RR_Rotate_0;
318 * This value doesn't really matter -- any client must call
319 * GetScreenInfo before reading it which will automatically update
322 pScrPriv->lastSetTime = currentTime;
323 pScrPriv->lastConfigTime = currentTime;
325 wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
327 pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
328 pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
329 pScrPriv->numOutputs = 0;
330 pScrPriv->outputs = NULL;
331 pScrPriv->numCrtcs = 0;
332 pScrPriv->crtcs = NULL;
334 RRNScreens += 1; /* keep count of screens that implement randr */
338 /*ARGSUSED*/ static int
339 RRFreeClient(pointer data, XID id)
343 RREventPtr *pHead, pCur, pPrev;
345 pRREvent = (RREventPtr) data;
346 pWin = pRREvent->window;
347 dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
348 RREventType, serverClient, DixDestroyAccess);
351 for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
355 pPrev->next = pRREvent->next;
357 *pHead = pRREvent->next;
360 free((pointer) pRREvent);
364 /*ARGSUSED*/ static int
365 RRFreeEvents(pointer data, XID id)
367 RREventPtr *pHead, pCur, pNext;
369 pHead = (RREventPtr *) data;
370 for (pCur = *pHead; pCur; pCur = pNext) {
372 FreeResource(pCur->clientResource, RRClientType);
373 free((pointer) pCur);
375 free((pointer) pHead);
380 RRExtensionInit(void)
382 ExtensionEntry *extEntry;
387 if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
388 sizeof(RRClientRec) +
389 screenInfo.numScreens * sizeof(RRTimesRec)))
391 if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
394 RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
397 RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
400 extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
401 ProcRRDispatch, SProcRRDispatch,
402 NULL, StandardMinorOpcode);
405 RRErrorBase = extEntry->errorBase;
406 RREventBase = extEntry->eventBase;
407 EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
408 SRRScreenChangeNotifyEvent;
409 EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
412 RRModeInitErrorValue();
413 RRCrtcInitErrorValue();
414 RROutputInitErrorValue();
415 RRProviderInitErrorValue();
417 RRXineramaExtensionInit();
422 TellChanged(WindowPtr pWin, pointer value)
424 RREventPtr *pHead, pRREvent;
426 ScreenPtr pScreen = pWin->drawable.pScreen;
431 dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
432 RREventType, serverClient, DixReadAccess);
434 return WT_WALKCHILDREN;
436 for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
437 client = pRREvent->client;
438 if (client == serverClient || client->clientGone)
441 if (pRREvent->mask & RRScreenChangeNotifyMask)
442 RRDeliverScreenEvent(client, pWin, pScreen);
444 if (pRREvent->mask & RRCrtcChangeNotifyMask) {
445 for (i = 0; i < pScrPriv->numCrtcs; i++) {
446 RRCrtcPtr crtc = pScrPriv->crtcs[i];
449 RRDeliverCrtcEvent(client, pWin, crtc);
453 if (pRREvent->mask & RROutputChangeNotifyMask) {
454 for (i = 0; i < pScrPriv->numOutputs; i++) {
455 RROutputPtr output = pScrPriv->outputs[i];
458 RRDeliverOutputEvent(client, pWin, output);
462 return WT_WALKCHILDREN;
466 * Something changed; send events and adjust pointer position
469 RRTellChanged(ScreenPtr pScreen)
473 rrScrPrivPtr mastersp;
476 if (pScreen->isGPU) {
477 master = pScreen->current_master;
478 mastersp = rrGetScrPriv(master);
485 if (pScrPriv->changed) {
486 UpdateCurrentTimeIf();
487 if (mastersp->configChanged) {
488 mastersp->lastConfigTime = currentTime;
489 mastersp->configChanged = FALSE;
491 pScrPriv->changed = FALSE;
492 mastersp->changed = FALSE;
493 WalkTree(master, TellChanged, (pointer) master);
494 for (i = 0; i < pScrPriv->numOutputs; i++)
495 pScrPriv->outputs[i]->changed = FALSE;
496 for (i = 0; i < pScrPriv->numCrtcs; i++)
497 pScrPriv->crtcs[i]->changed = FALSE;
498 if (mastersp->layoutChanged) {
499 pScrPriv->layoutChanged = FALSE;
500 RRPointerScreenConfigured(master);
501 RRSendConfigNotify(master);
507 * Return the first output which is connected to an active CRTC
508 * Used in emulating 1.0 behaviour
511 RRFirstOutput(ScreenPtr pScreen)
520 if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
521 return pScrPriv->primaryOutput;
523 for (i = 0; i < pScrPriv->numCrtcs; i++) {
524 RRCrtcPtr crtc = pScrPriv->crtcs[i];
526 for (j = 0; j < pScrPriv->numOutputs; j++) {
527 output = pScrPriv->outputs[j];
528 if (output->crtc == crtc)
536 RRVerticalRefresh(xRRModeInfo * mode)
539 CARD32 dots = mode->hTotal * mode->vTotal;
543 refresh = (mode->dotClock + dots / 2) / dots;
544 if (refresh > 0xffff)
546 return (CARD16) refresh;
550 ProcRRDispatch(ClientPtr client)
553 if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
555 return (*ProcRandrVector[stuff->data]) (client);
559 SProcRRDispatch(ClientPtr client)
562 if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
564 return (*SProcRandrVector[stuff->data]) (client);