upgrade for xorg-server 1.12.99.905 (for 1.13 RC)
[framework/uifw/xorg/server/xorg-server.git] / randr / randr.c
1 /*
2  * Copyright © 2000 Compaq Computer Corporation
3  * Copyright © 2002 Hewlett-Packard Company
4  * Copyright © 2006 Intel Corporation
5  *
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.
15  *
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
22  * OF THIS SOFTWARE.
23  *
24  * Author:  Jim Gettys, Hewlett-Packard Company, Inc.
25  *          Keith Packard, Intel Corporation
26  */
27
28 #ifdef HAVE_DIX_CONFIG_H
29 #include <dix-config.h>
30 #endif
31
32 #include "randrstr.h"
33 #include "extinit.h"
34
35 /* From render.h */
36 #ifndef SubPixelUnknown
37 #define SubPixelUnknown 0
38 #endif
39
40 #define RR_VALIDATE
41 static int RRNScreens;
42
43 #define wrap(priv,real,mem,func) {\
44     priv->mem = real->mem; \
45     real->mem = func; \
46 }
47
48 #define unwrap(priv,real,mem) {\
49     real->mem = priv->mem; \
50 }
51
52 static int ProcRRDispatch(ClientPtr pClient);
53 static int SProcRRDispatch(ClientPtr pClient);
54
55 int RREventBase;
56 int RRErrorBase;
57 RESTYPE RRClientType, RREventType;      /* resource types for event masks */
58 DevPrivateKeyRec RRClientPrivateKeyRec;
59
60 DevPrivateKeyRec rrPrivKeyRec;
61
62 static void
63 RRClientCallback(CallbackListPtr *list, pointer closure, pointer data)
64 {
65     NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
66     ClientPtr pClient = clientinfo->client;
67
68     rrClientPriv(pClient);
69     RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
70     int i;
71
72     pRRClient->major_version = 0;
73     pRRClient->minor_version = 0;
74     for (i = 0; i < screenInfo.numScreens; i++) {
75         ScreenPtr pScreen = screenInfo.screens[i];
76
77         rrScrPriv(pScreen);
78
79         if (pScrPriv) {
80             pTimes[i].setTime = pScrPriv->lastSetTime;
81             pTimes[i].configTime = pScrPriv->lastConfigTime;
82         }
83     }
84 }
85
86 static Bool
87 RRCloseScreen(ScreenPtr pScreen)
88 {
89     rrScrPriv(pScreen);
90     int j;
91
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]);
97
98     if (pScrPriv->provider)
99         RRProviderDestroy(pScrPriv->provider);
100
101     free(pScrPriv->crtcs);
102     free(pScrPriv->outputs);
103     free(pScrPriv);
104     RRNScreens -= 1;            /* ok, one fewer screen with RandR running */
105     return (*pScreen->CloseScreen) (pScreen);
106 }
107
108 static void
109 SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,
110                            xRRScreenChangeNotifyEvent * to)
111 {
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);
125 }
126
127 static void
128 SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,
129                          xRRCrtcChangeNotifyEvent * to)
130 {
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);
139     /* pad1 */
140     cpswaps(from->x, to->x);
141     cpswaps(from->y, to->y);
142     cpswaps(from->width, to->width);
143     cpswaps(from->height, to->height);
144 }
145
146 static void
147 SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,
148                            xRROutputChangeNotifyEvent * to)
149 {
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;
162 }
163
164 static void
165 SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
166                              xRROutputPropertyNotifyEvent * to)
167 {
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;
176     /* pad1 */
177     /* pad2 */
178     /* pad3 */
179     /* pad4 */
180 }
181
182 static void
183 SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,
184                          xRRProviderChangeNotifyEvent * to)
185 {
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);
192 }
193
194 static void
195 SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,
196                                xRRProviderPropertyNotifyEvent * to)
197 {
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;
206     /* pad1 */
207     /* pad2 */
208     /* pad3 */
209     /* pad4 */
210 }
211
212 static void
213 SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
214                              xRRResourceChangeNotifyEvent * to)
215 {
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);
221 }
222
223 static void
224 SRRNotifyEvent(xEvent *from, xEvent *to)
225 {
226     switch (from->u.u.detail) {
227     case RRNotify_CrtcChange:
228         SRRCrtcChangeNotifyEvent((xRRCrtcChangeNotifyEvent *) from,
229                                  (xRRCrtcChangeNotifyEvent *) to);
230         break;
231     case RRNotify_OutputChange:
232         SRROutputChangeNotifyEvent((xRROutputChangeNotifyEvent *) from,
233                                    (xRROutputChangeNotifyEvent *) to);
234         break;
235     case RRNotify_OutputProperty:
236         SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
237                                      (xRROutputPropertyNotifyEvent *) to);
238         break;
239     case RRNotify_ProviderChange:
240         SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from,
241                                    (xRRProviderChangeNotifyEvent *) to);
242         break;
243     case RRNotify_ProviderProperty:
244         SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from,
245                                        (xRRProviderPropertyNotifyEvent *) to);
246         break;
247     case RRNotify_ResourceChange:
248         SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
249                                    (xRRResourceChangeNotifyEvent *) to);
250     default:
251         break;
252     }
253 }
254
255 static int RRGeneration;
256
257 Bool
258 RRInit(void)
259 {
260     if (RRGeneration != serverGeneration) {
261         if (!RRModeInit())
262             return FALSE;
263         if (!RRCrtcInit())
264             return FALSE;
265         if (!RROutputInit())
266             return FALSE;
267         RRGeneration = serverGeneration;
268     }
269     if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
270         return FALSE;
271
272     return TRUE;
273 }
274
275 Bool
276 RRScreenInit(ScreenPtr pScreen)
277 {
278     rrScrPrivPtr pScrPriv;
279
280     if (!RRInit())
281         return FALSE;
282
283     pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
284     if (!pScrPriv)
285         return FALSE;
286
287     SetRRScreen(pScreen, pScrPriv);
288
289     /*
290      * Calling function best set these function vectors
291      */
292     pScrPriv->rrGetInfo = 0;
293     pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
294     pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
295
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;
304 #endif
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;
313     pScrPriv->rate = 0;
314     pScrPriv->size = 0;
315 #endif
316
317     /*
318      * This value doesn't really matter -- any client must call
319      * GetScreenInfo before reading it which will automatically update
320      * the time
321      */
322     pScrPriv->lastSetTime = currentTime;
323     pScrPriv->lastConfigTime = currentTime;
324
325     wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
326
327     pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
328     pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
329     pScrPriv->numOutputs = 0;
330     pScrPriv->outputs = NULL;
331     pScrPriv->numCrtcs = 0;
332     pScrPriv->crtcs = NULL;
333
334     RRNScreens += 1;            /* keep count of screens that implement randr */
335     return TRUE;
336 }
337
338  /*ARGSUSED*/ static int
339 RRFreeClient(pointer data, XID id)
340 {
341     RREventPtr pRREvent;
342     WindowPtr pWin;
343     RREventPtr *pHead, pCur, pPrev;
344
345     pRREvent = (RREventPtr) data;
346     pWin = pRREvent->window;
347     dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
348                             RREventType, serverClient, DixDestroyAccess);
349     if (pHead) {
350         pPrev = 0;
351         for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
352             pPrev = pCur;
353         if (pCur) {
354             if (pPrev)
355                 pPrev->next = pRREvent->next;
356             else
357                 *pHead = pRREvent->next;
358         }
359     }
360     free((pointer) pRREvent);
361     return 1;
362 }
363
364  /*ARGSUSED*/ static int
365 RRFreeEvents(pointer data, XID id)
366 {
367     RREventPtr *pHead, pCur, pNext;
368
369     pHead = (RREventPtr *) data;
370     for (pCur = *pHead; pCur; pCur = pNext) {
371         pNext = pCur->next;
372         FreeResource(pCur->clientResource, RRClientType);
373         free((pointer) pCur);
374     }
375     free((pointer) pHead);
376     return 1;
377 }
378
379 void
380 RRExtensionInit(void)
381 {
382     ExtensionEntry *extEntry;
383
384     if (RRNScreens == 0)
385         return;
386
387     if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
388                                sizeof(RRClientRec) +
389                                screenInfo.numScreens * sizeof(RRTimesRec)))
390         return;
391     if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
392         return;
393
394     RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
395     if (!RRClientType)
396         return;
397     RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
398     if (!RREventType)
399         return;
400     extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
401                             ProcRRDispatch, SProcRRDispatch,
402                             NULL, StandardMinorOpcode);
403     if (!extEntry)
404         return;
405     RRErrorBase = extEntry->errorBase;
406     RREventBase = extEntry->eventBase;
407     EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
408         SRRScreenChangeNotifyEvent;
409     EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
410         SRRNotifyEvent;
411
412     RRModeInitErrorValue();
413     RRCrtcInitErrorValue();
414     RROutputInitErrorValue();
415     RRProviderInitErrorValue();
416 #ifdef PANORAMIX
417     RRXineramaExtensionInit();
418 #endif
419 }
420
421 static int
422 TellChanged(WindowPtr pWin, pointer value)
423 {
424     RREventPtr *pHead, pRREvent;
425     ClientPtr client;
426     ScreenPtr pScreen = pWin->drawable.pScreen;
427
428     rrScrPriv(pScreen);
429     int i;
430
431     dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
432                             RREventType, serverClient, DixReadAccess);
433     if (!pHead)
434         return WT_WALKCHILDREN;
435
436     for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
437         client = pRREvent->client;
438         if (client == serverClient || client->clientGone)
439             continue;
440
441         if (pRREvent->mask & RRScreenChangeNotifyMask)
442             RRDeliverScreenEvent(client, pWin, pScreen);
443
444         if (pRREvent->mask & RRCrtcChangeNotifyMask) {
445             for (i = 0; i < pScrPriv->numCrtcs; i++) {
446                 RRCrtcPtr crtc = pScrPriv->crtcs[i];
447
448                 if (crtc->changed)
449                     RRDeliverCrtcEvent(client, pWin, crtc);
450             }
451         }
452
453         if (pRREvent->mask & RROutputChangeNotifyMask) {
454             for (i = 0; i < pScrPriv->numOutputs; i++) {
455                 RROutputPtr output = pScrPriv->outputs[i];
456
457                 if (output->changed)
458                     RRDeliverOutputEvent(client, pWin, output);
459             }
460         }
461     }
462     return WT_WALKCHILDREN;
463 }
464
465 /*
466  * Something changed; send events and adjust pointer position
467  */
468 void
469 RRTellChanged(ScreenPtr pScreen)
470 {
471     ScreenPtr master;
472     rrScrPriv(pScreen);
473     rrScrPrivPtr mastersp;
474     int i;
475
476     if (pScreen->isGPU) {
477         master = pScreen->current_master;
478         mastersp = rrGetScrPriv(master);
479     }
480     else {
481         master = pScreen;
482         mastersp = pScrPriv;
483     }
484
485     if (pScrPriv->changed) {
486         UpdateCurrentTimeIf();
487         if (mastersp->configChanged) {
488             mastersp->lastConfigTime = currentTime;
489             mastersp->configChanged = FALSE;
490         }
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);
502         }
503     }
504 }
505
506 /*
507  * Return the first output which is connected to an active CRTC
508  * Used in emulating 1.0 behaviour
509  */
510 RROutputPtr
511 RRFirstOutput(ScreenPtr pScreen)
512 {
513     rrScrPriv(pScreen);
514     RROutputPtr output;
515     int i, j;
516
517     if (!pScrPriv)
518         return NULL;
519
520     if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
521         return pScrPriv->primaryOutput;
522
523     for (i = 0; i < pScrPriv->numCrtcs; i++) {
524         RRCrtcPtr crtc = pScrPriv->crtcs[i];
525
526         for (j = 0; j < pScrPriv->numOutputs; j++) {
527             output = pScrPriv->outputs[j];
528             if (output->crtc == crtc)
529                 return output;
530         }
531     }
532     return NULL;
533 }
534
535 CARD16
536 RRVerticalRefresh(xRRModeInfo * mode)
537 {
538     CARD32 refresh;
539     CARD32 dots = mode->hTotal * mode->vTotal;
540
541     if (!dots)
542         return 0;
543     refresh = (mode->dotClock + dots / 2) / dots;
544     if (refresh > 0xffff)
545         refresh = 0xffff;
546     return (CARD16) refresh;
547 }
548
549 static int
550 ProcRRDispatch(ClientPtr client)
551 {
552     REQUEST(xReq);
553     if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
554         return BadRequest;
555     return (*ProcRandrVector[stuff->data]) (client);
556 }
557
558 static int
559 SProcRRDispatch(ClientPtr client)
560 {
561     REQUEST(xReq);
562     if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
563         return BadRequest;
564     return (*SProcRandrVector[stuff->data]) (client);
565 }