hw/xwin/glx: Use silent rules
[xserver/hramrach.git] / randr / randr.c
blob9f3df5fbe71e22521bd11618efb03897def33c8a
1 /*
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
22 * OF THIS SOFTWARE.
24 * Author: Jim Gettys, Hewlett-Packard Company, Inc.
25 * Keith Packard, Intel Corporation
28 #ifdef HAVE_DIX_CONFIG_H
29 #include <dix-config.h>
30 #endif
32 #include "randrstr.h"
34 /* From render.h */
35 #ifndef SubPixelUnknown
36 #define SubPixelUnknown 0
37 #endif
39 #define RR_VALIDATE
40 static int RRNScreens;
42 #define wrap(priv,real,mem,func) {\
43 priv->mem = real->mem; \
44 real->mem = func; \
47 #define unwrap(priv,real,mem) {\
48 real->mem = priv->mem; \
51 static int ProcRRDispatch(ClientPtr pClient);
52 static int SProcRRDispatch(ClientPtr pClient);
54 int RREventBase;
55 int RRErrorBase;
56 RESTYPE RRClientType, RREventType; /* resource types for event masks */
57 DevPrivateKeyRec RRClientPrivateKeyRec;
59 DevPrivateKeyRec rrPrivKeyRec;
61 static void
62 RRClientCallback(CallbackListPtr *list, pointer closure, pointer data)
64 NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
65 ClientPtr pClient = clientinfo->client;
67 rrClientPriv(pClient);
68 RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
69 int i;
71 pRRClient->major_version = 0;
72 pRRClient->minor_version = 0;
73 for (i = 0; i < screenInfo.numScreens; i++) {
74 ScreenPtr pScreen = screenInfo.screens[i];
76 rrScrPriv(pScreen);
78 if (pScrPriv) {
79 pTimes[i].setTime = pScrPriv->lastSetTime;
80 pTimes[i].configTime = pScrPriv->lastConfigTime;
85 static Bool
86 RRCloseScreen(int i, ScreenPtr pScreen)
88 rrScrPriv(pScreen);
89 int j;
91 unwrap(pScrPriv, pScreen, CloseScreen);
92 for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
93 RRCrtcDestroy(pScrPriv->crtcs[j]);
94 for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
95 RROutputDestroy(pScrPriv->outputs[j]);
97 free(pScrPriv->crtcs);
98 free(pScrPriv->outputs);
99 free(pScrPriv);
100 RRNScreens -= 1; /* ok, one fewer screen with RandR running */
101 return (*pScreen->CloseScreen) (i, pScreen);
104 static void
105 SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,
106 xRRScreenChangeNotifyEvent * to)
108 to->type = from->type;
109 to->rotation = from->rotation;
110 cpswaps(from->sequenceNumber, to->sequenceNumber);
111 cpswapl(from->timestamp, to->timestamp);
112 cpswapl(from->configTimestamp, to->configTimestamp);
113 cpswapl(from->root, to->root);
114 cpswapl(from->window, to->window);
115 cpswaps(from->sizeID, to->sizeID);
116 cpswaps(from->subpixelOrder, to->subpixelOrder);
117 cpswaps(from->widthInPixels, to->widthInPixels);
118 cpswaps(from->heightInPixels, to->heightInPixels);
119 cpswaps(from->widthInMillimeters, to->widthInMillimeters);
120 cpswaps(from->heightInMillimeters, to->heightInMillimeters);
123 static void
124 SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,
125 xRRCrtcChangeNotifyEvent * to)
127 to->type = from->type;
128 to->subCode = from->subCode;
129 cpswaps(from->sequenceNumber, to->sequenceNumber);
130 cpswapl(from->timestamp, to->timestamp);
131 cpswapl(from->window, to->window);
132 cpswapl(from->crtc, to->crtc);
133 cpswapl(from->mode, to->mode);
134 cpswaps(from->rotation, to->rotation);
135 /* pad1 */
136 cpswaps(from->x, to->x);
137 cpswaps(from->y, to->y);
138 cpswaps(from->width, to->width);
139 cpswaps(from->height, to->height);
142 static void
143 SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,
144 xRROutputChangeNotifyEvent * to)
146 to->type = from->type;
147 to->subCode = from->subCode;
148 cpswaps(from->sequenceNumber, to->sequenceNumber);
149 cpswapl(from->timestamp, to->timestamp);
150 cpswapl(from->configTimestamp, to->configTimestamp);
151 cpswapl(from->window, to->window);
152 cpswapl(from->output, to->output);
153 cpswapl(from->crtc, to->crtc);
154 cpswapl(from->mode, to->mode);
155 cpswaps(from->rotation, to->rotation);
156 to->connection = from->connection;
157 to->subpixelOrder = from->subpixelOrder;
160 static void
161 SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
162 xRROutputPropertyNotifyEvent * to)
164 to->type = from->type;
165 to->subCode = from->subCode;
166 cpswaps(from->sequenceNumber, to->sequenceNumber);
167 cpswapl(from->window, to->window);
168 cpswapl(from->output, to->output);
169 cpswapl(from->atom, to->atom);
170 cpswapl(from->timestamp, to->timestamp);
171 to->state = from->state;
172 /* pad1 */
173 /* pad2 */
174 /* pad3 */
175 /* pad4 */
178 static void
179 SRRNotifyEvent(xEvent *from, xEvent *to)
181 switch (from->u.u.detail) {
182 case RRNotify_CrtcChange:
183 SRRCrtcChangeNotifyEvent((xRRCrtcChangeNotifyEvent *) from,
184 (xRRCrtcChangeNotifyEvent *) to);
185 break;
186 case RRNotify_OutputChange:
187 SRROutputChangeNotifyEvent((xRROutputChangeNotifyEvent *) from,
188 (xRROutputChangeNotifyEvent *) to);
189 break;
190 case RRNotify_OutputProperty:
191 SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
192 (xRROutputPropertyNotifyEvent *) to);
193 break;
194 default:
195 break;
199 static int RRGeneration;
201 Bool
202 RRInit(void)
204 if (RRGeneration != serverGeneration) {
205 if (!RRModeInit())
206 return FALSE;
207 if (!RRCrtcInit())
208 return FALSE;
209 if (!RROutputInit())
210 return FALSE;
211 RRGeneration = serverGeneration;
213 if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
214 return FALSE;
216 return TRUE;
219 Bool
220 RRScreenInit(ScreenPtr pScreen)
222 rrScrPrivPtr pScrPriv;
224 if (!RRInit())
225 return FALSE;
227 pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
228 if (!pScrPriv)
229 return FALSE;
231 SetRRScreen(pScreen, pScrPriv);
234 * Calling function best set these function vectors
236 pScrPriv->rrGetInfo = 0;
237 pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
238 pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
240 pScrPriv->width = pScreen->width;
241 pScrPriv->height = pScreen->height;
242 pScrPriv->mmWidth = pScreen->mmWidth;
243 pScrPriv->mmHeight = pScreen->mmHeight;
244 #if RANDR_12_INTERFACE
245 pScrPriv->rrScreenSetSize = NULL;
246 pScrPriv->rrCrtcSet = NULL;
247 pScrPriv->rrCrtcSetGamma = NULL;
248 #endif
249 #if RANDR_10_INTERFACE
250 pScrPriv->rrSetConfig = 0;
251 pScrPriv->rotations = RR_Rotate_0;
252 pScrPriv->reqWidth = pScreen->width;
253 pScrPriv->reqHeight = pScreen->height;
254 pScrPriv->nSizes = 0;
255 pScrPriv->pSizes = NULL;
256 pScrPriv->rotation = RR_Rotate_0;
257 pScrPriv->rate = 0;
258 pScrPriv->size = 0;
259 #endif
262 * This value doesn't really matter -- any client must call
263 * GetScreenInfo before reading it which will automatically update
264 * the time
266 pScrPriv->lastSetTime = currentTime;
267 pScrPriv->lastConfigTime = currentTime;
269 wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
271 pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
273 pScrPriv->numOutputs = 0;
274 pScrPriv->outputs = NULL;
275 pScrPriv->numCrtcs = 0;
276 pScrPriv->crtcs = NULL;
278 RRNScreens += 1; /* keep count of screens that implement randr */
279 return TRUE;
282 /*ARGSUSED*/ static int
283 RRFreeClient(pointer data, XID id)
285 RREventPtr pRREvent;
286 WindowPtr pWin;
287 RREventPtr *pHead, pCur, pPrev;
289 pRREvent = (RREventPtr) data;
290 pWin = pRREvent->window;
291 dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
292 RREventType, serverClient, DixDestroyAccess);
293 if (pHead) {
294 pPrev = 0;
295 for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
296 pPrev = pCur;
297 if (pCur) {
298 if (pPrev)
299 pPrev->next = pRREvent->next;
300 else
301 *pHead = pRREvent->next;
304 free((pointer) pRREvent);
305 return 1;
308 /*ARGSUSED*/ static int
309 RRFreeEvents(pointer data, XID id)
311 RREventPtr *pHead, pCur, pNext;
313 pHead = (RREventPtr *) data;
314 for (pCur = *pHead; pCur; pCur = pNext) {
315 pNext = pCur->next;
316 FreeResource(pCur->clientResource, RRClientType);
317 free((pointer) pCur);
319 free((pointer) pHead);
320 return 1;
323 void
324 RRExtensionInit(void)
326 ExtensionEntry *extEntry;
328 if (RRNScreens == 0)
329 return;
331 if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
332 sizeof(RRClientRec) +
333 screenInfo.numScreens * sizeof(RRTimesRec)))
334 return;
335 if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
336 return;
338 RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
339 if (!RRClientType)
340 return;
341 RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
342 if (!RREventType)
343 return;
344 extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
345 ProcRRDispatch, SProcRRDispatch,
346 NULL, StandardMinorOpcode);
347 if (!extEntry)
348 return;
349 RRErrorBase = extEntry->errorBase;
350 RREventBase = extEntry->eventBase;
351 EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
352 SRRScreenChangeNotifyEvent;
353 EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
354 SRRNotifyEvent;
356 RRModeInitErrorValue();
357 RRCrtcInitErrorValue();
358 RROutputInitErrorValue();
360 #ifdef PANORAMIX
361 RRXineramaExtensionInit();
362 #endif
365 static int
366 TellChanged(WindowPtr pWin, pointer value)
368 RREventPtr *pHead, pRREvent;
369 ClientPtr client;
370 ScreenPtr pScreen = pWin->drawable.pScreen;
372 rrScrPriv(pScreen);
373 int i;
375 dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
376 RREventType, serverClient, DixReadAccess);
377 if (!pHead)
378 return WT_WALKCHILDREN;
380 for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
381 client = pRREvent->client;
382 if (client == serverClient || client->clientGone)
383 continue;
385 if (pRREvent->mask & RRScreenChangeNotifyMask)
386 RRDeliverScreenEvent(client, pWin, pScreen);
388 if (pRREvent->mask & RRCrtcChangeNotifyMask) {
389 for (i = 0; i < pScrPriv->numCrtcs; i++) {
390 RRCrtcPtr crtc = pScrPriv->crtcs[i];
392 if (crtc->changed)
393 RRDeliverCrtcEvent(client, pWin, crtc);
397 if (pRREvent->mask & RROutputChangeNotifyMask) {
398 for (i = 0; i < pScrPriv->numOutputs; i++) {
399 RROutputPtr output = pScrPriv->outputs[i];
401 if (output->changed)
402 RRDeliverOutputEvent(client, pWin, output);
406 return WT_WALKCHILDREN;
410 * Something changed; send events and adjust pointer position
412 void
413 RRTellChanged(ScreenPtr pScreen)
415 rrScrPriv(pScreen);
416 int i;
418 if (pScrPriv->changed) {
419 UpdateCurrentTime();
420 if (pScrPriv->configChanged) {
421 pScrPriv->lastConfigTime = currentTime;
422 pScrPriv->configChanged = FALSE;
424 pScrPriv->changed = FALSE;
425 WalkTree(pScreen, TellChanged, (pointer) pScreen);
426 for (i = 0; i < pScrPriv->numOutputs; i++)
427 pScrPriv->outputs[i]->changed = FALSE;
428 for (i = 0; i < pScrPriv->numCrtcs; i++)
429 pScrPriv->crtcs[i]->changed = FALSE;
430 if (pScrPriv->layoutChanged) {
431 pScrPriv->layoutChanged = FALSE;
432 RRPointerScreenConfigured(pScreen);
433 RRSendConfigNotify(pScreen);
439 * Return the first output which is connected to an active CRTC
440 * Used in emulating 1.0 behaviour
442 RROutputPtr
443 RRFirstOutput(ScreenPtr pScreen)
445 rrScrPriv(pScreen);
446 RROutputPtr output;
447 int i, j;
449 if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
450 return pScrPriv->primaryOutput;
452 for (i = 0; i < pScrPriv->numCrtcs; i++) {
453 RRCrtcPtr crtc = pScrPriv->crtcs[i];
455 for (j = 0; j < pScrPriv->numOutputs; j++) {
456 output = pScrPriv->outputs[j];
457 if (output->crtc == crtc)
458 return output;
461 return NULL;
464 CARD16
465 RRVerticalRefresh(xRRModeInfo * mode)
467 CARD32 refresh;
468 CARD32 dots = mode->hTotal * mode->vTotal;
470 if (!dots)
471 return 0;
472 refresh = (mode->dotClock + dots / 2) / dots;
473 if (refresh > 0xffff)
474 refresh = 0xffff;
475 return (CARD16) refresh;
478 static int
479 ProcRRDispatch(ClientPtr client)
481 REQUEST(xReq);
482 if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
483 return BadRequest;
484 return (*ProcRandrVector[stuff->data]) (client);
487 static int
488 SProcRRDispatch(ClientPtr client)
490 REQUEST(xReq);
491 if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
492 return BadRequest;
493 return (*SProcRandrVector[stuff->data]) (client);