Add patch that contain Mali fixes.
[deb_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 if (!RRProviderInit())
268 return FALSE;
269 RRGeneration = serverGeneration;
270 }
271 if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
272 return FALSE;
273
274 return TRUE;
275 }
276
277 Bool
278 RRScreenInit(ScreenPtr pScreen)
279 {
280 rrScrPrivPtr pScrPriv;
281
282 if (!RRInit())
283 return FALSE;
284
285 pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
286 if (!pScrPriv)
287 return FALSE;
288
289 SetRRScreen(pScreen, pScrPriv);
290
291 /*
292 * Calling function best set these function vectors
293 */
294 pScrPriv->rrGetInfo = 0;
295 pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
296 pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
297
298 pScrPriv->width = pScreen->width;
299 pScrPriv->height = pScreen->height;
300 pScrPriv->mmWidth = pScreen->mmWidth;
301 pScrPriv->mmHeight = pScreen->mmHeight;
302 #if RANDR_12_INTERFACE
303 pScrPriv->rrScreenSetSize = NULL;
304 pScrPriv->rrCrtcSet = NULL;
305 pScrPriv->rrCrtcSetGamma = NULL;
306 #endif
307 #if RANDR_10_INTERFACE
308 pScrPriv->rrSetConfig = 0;
309 pScrPriv->rotations = RR_Rotate_0;
310 pScrPriv->reqWidth = pScreen->width;
311 pScrPriv->reqHeight = pScreen->height;
312 pScrPriv->nSizes = 0;
313 pScrPriv->pSizes = NULL;
314 pScrPriv->rotation = RR_Rotate_0;
315 pScrPriv->rate = 0;
316 pScrPriv->size = 0;
317 #endif
318
319 /*
320 * This value doesn't really matter -- any client must call
321 * GetScreenInfo before reading it which will automatically update
322 * the time
323 */
324 pScrPriv->lastSetTime = currentTime;
325 pScrPriv->lastConfigTime = currentTime;
326
327 wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
328
329 pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
330 pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
331 pScrPriv->numOutputs = 0;
332 pScrPriv->outputs = NULL;
333 pScrPriv->numCrtcs = 0;
334 pScrPriv->crtcs = NULL;
335
336 RRNScreens += 1; /* keep count of screens that implement randr */
337 return TRUE;
338 }
339
340 /*ARGSUSED*/ static int
341 RRFreeClient(pointer data, XID id)
342 {
343 RREventPtr pRREvent;
344 WindowPtr pWin;
345 RREventPtr *pHead, pCur, pPrev;
346
347 pRREvent = (RREventPtr) data;
348 pWin = pRREvent->window;
349 dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
350 RREventType, serverClient, DixDestroyAccess);
351 if (pHead) {
352 pPrev = 0;
353 for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
354 pPrev = pCur;
355 if (pCur) {
356 if (pPrev)
357 pPrev->next = pRREvent->next;
358 else
359 *pHead = pRREvent->next;
360 }
361 }
362 free((pointer) pRREvent);
363 return 1;
364 }
365
366 /*ARGSUSED*/ static int
367 RRFreeEvents(pointer data, XID id)
368 {
369 RREventPtr *pHead, pCur, pNext;
370
371 pHead = (RREventPtr *) data;
372 for (pCur = *pHead; pCur; pCur = pNext) {
373 pNext = pCur->next;
374 FreeResource(pCur->clientResource, RRClientType);
375 free((pointer) pCur);
376 }
377 free((pointer) pHead);
378 return 1;
379 }
380
381 void
382 RRExtensionInit(void)
383 {
384 ExtensionEntry *extEntry;
385
386 if (RRNScreens == 0)
387 return;
388
389 if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
390 sizeof(RRClientRec) +
391 screenInfo.numScreens * sizeof(RRTimesRec)))
392 return;
393 if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
394 return;
395
396 RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
397 if (!RRClientType)
398 return;
399 RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
400 if (!RREventType)
401 return;
402 extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
403 ProcRRDispatch, SProcRRDispatch,
404 NULL, StandardMinorOpcode);
405 if (!extEntry)
406 return;
407 RRErrorBase = extEntry->errorBase;
408 RREventBase = extEntry->eventBase;
409 EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
410 SRRScreenChangeNotifyEvent;
411 EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
412 SRRNotifyEvent;
413
414 RRModeInitErrorValue();
415 RRCrtcInitErrorValue();
416 RROutputInitErrorValue();
417 RRProviderInitErrorValue();
418 #ifdef PANORAMIX
419 RRXineramaExtensionInit();
420 #endif
421 }
422
423 void
424 RRResourcesChanged(ScreenPtr pScreen)
425 {
426 rrScrPriv(pScreen);
427 pScrPriv->resourcesChanged = TRUE;
428
429 RRSetChanged(pScreen);
430 }
431
432 static void
433 RRDeliverResourceEvent(ClientPtr client, WindowPtr pWin)
434 {
435 ScreenPtr pScreen = pWin->drawable.pScreen;
436
437 rrScrPriv(pScreen);
438
439 xRRResourceChangeNotifyEvent re = {
440 .type = RRNotify + RREventBase,
441 .subCode = RRNotify_ResourceChange,
442 .timestamp = pScrPriv->lastSetTime.milliseconds,
443 .window = pWin->drawable.id
444 };
445
446 WriteEventsToClient(client, 1, (xEvent *) &re);
447 }
448
449 static int
450 TellChanged(WindowPtr pWin, pointer value)
451 {
452 RREventPtr *pHead, pRREvent;
453 ClientPtr client;
454 ScreenPtr pScreen = pWin->drawable.pScreen;
455 ScreenPtr iter;
456 rrScrPrivPtr pSlaveScrPriv;
457
458 rrScrPriv(pScreen);
459 int i;
460
461 dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
462 RREventType, serverClient, DixReadAccess);
463 if (!pHead)
464 return WT_WALKCHILDREN;
465
466 for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
467 client = pRREvent->client;
468 if (client == serverClient || client->clientGone)
469 continue;
470
471 if (pRREvent->mask & RRScreenChangeNotifyMask)
472 RRDeliverScreenEvent(client, pWin, pScreen);
473
474 if (pRREvent->mask & RRCrtcChangeNotifyMask) {
475 for (i = 0; i < pScrPriv->numCrtcs; i++) {
476 RRCrtcPtr crtc = pScrPriv->crtcs[i];
477
478 if (crtc->changed)
479 RRDeliverCrtcEvent(client, pWin, crtc);
480 }
481
482 xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
483 pSlaveScrPriv = rrGetScrPriv(iter);
484 for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) {
485 RRCrtcPtr crtc = pSlaveScrPriv->crtcs[i];
486
487 if (crtc->changed)
488 RRDeliverCrtcEvent(client, pWin, crtc);
489 }
490 }
491 }
492
493 if (pRREvent->mask & RROutputChangeNotifyMask) {
494 for (i = 0; i < pScrPriv->numOutputs; i++) {
495 RROutputPtr output = pScrPriv->outputs[i];
496
497 if (output->changed)
498 RRDeliverOutputEvent(client, pWin, output);
499 }
500
501 xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
502 pSlaveScrPriv = rrGetScrPriv(iter);
503 for (i = 0; i < pSlaveScrPriv->numOutputs; i++) {
504 RROutputPtr output = pSlaveScrPriv->outputs[i];
505
506 if (output->changed)
507 RRDeliverOutputEvent(client, pWin, output);
508 }
509 }
510 }
511
512 if (pRREvent->mask & RRProviderChangeNotifyMask) {
513 xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
514 pSlaveScrPriv = rrGetScrPriv(iter);
515 if (pSlaveScrPriv->provider->changed)
516 RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
517 }
518 xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
519 pSlaveScrPriv = rrGetScrPriv(iter);
520 if (pSlaveScrPriv->provider->changed)
521 RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
522 }
523 xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
524 pSlaveScrPriv = rrGetScrPriv(iter);
525 if (pSlaveScrPriv->provider->changed)
526 RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
527 }
528 }
529
530 if (pRREvent->mask & RRResourceChangeNotifyMask) {
531 if (pScrPriv->resourcesChanged) {
532 RRDeliverResourceEvent(client, pWin);
533 }
534 }
535 }
536 return WT_WALKCHILDREN;
537 }
538
539 void
540 RRSetChanged(ScreenPtr pScreen)
541 {
542 /* set changed bits on the master screen only */
543 ScreenPtr master;
544 rrScrPriv(pScreen);
545 rrScrPrivPtr mastersp;
546
547 if (pScreen->isGPU) {
548 master = pScreen->current_master;
549 if (!master)
550 return;
551 mastersp = rrGetScrPriv(master);
552 }
553 else {
554 master = pScreen;
555 mastersp = pScrPriv;
556 }
557
558 mastersp->changed = TRUE;
559 }
560
561 /*
562 * Something changed; send events and adjust pointer position
563 */
564 void
565 RRTellChanged(ScreenPtr pScreen)
566 {
567 ScreenPtr master;
568 rrScrPriv(pScreen);
569 rrScrPrivPtr mastersp;
570 int i;
571 ScreenPtr iter;
572 rrScrPrivPtr pSlaveScrPriv;
573
574 if (pScreen->isGPU) {
575 master = pScreen->current_master;
576 mastersp = rrGetScrPriv(master);
577 }
578 else {
579 master = pScreen;
580 mastersp = pScrPriv;
581 }
582
583 if (mastersp->changed) {
584 UpdateCurrentTimeIf();
585 if (mastersp->configChanged) {
586 mastersp->lastConfigTime = currentTime;
587 mastersp->configChanged = FALSE;
588 }
589 pScrPriv->changed = FALSE;
590 mastersp->changed = FALSE;
591
592 WalkTree(master, TellChanged, (pointer) master);
593
594 mastersp->resourcesChanged = FALSE;
595
596 for (i = 0; i < pScrPriv->numOutputs; i++)
597 pScrPriv->outputs[i]->changed = FALSE;
598 for (i = 0; i < pScrPriv->numCrtcs; i++)
599 pScrPriv->crtcs[i]->changed = FALSE;
600
601 xorg_list_for_each_entry(iter, &master->output_slave_list, output_head) {
602 pSlaveScrPriv = rrGetScrPriv(iter);
603 pSlaveScrPriv->provider->changed = FALSE;
604 for (i = 0; i < pSlaveScrPriv->numOutputs; i++)
605 pSlaveScrPriv->outputs[i]->changed = FALSE;
606 for (i = 0; i < pSlaveScrPriv->numCrtcs; i++)
607 pSlaveScrPriv->crtcs[i]->changed = FALSE;
608 }
609 xorg_list_for_each_entry(iter, &master->offload_slave_list, offload_head) {
610 pSlaveScrPriv = rrGetScrPriv(iter);
611 pSlaveScrPriv->provider->changed = FALSE;
612 }
613 xorg_list_for_each_entry(iter, &master->unattached_list, unattached_head) {
614 pSlaveScrPriv = rrGetScrPriv(iter);
615 pSlaveScrPriv->provider->changed = FALSE;
616 }
617
618 if (mastersp->layoutChanged) {
619 pScrPriv->layoutChanged = FALSE;
620 RRPointerScreenConfigured(master);
621 RRSendConfigNotify(master);
622 }
623 }
624 }
625
626 /*
627 * Return the first output which is connected to an active CRTC
628 * Used in emulating 1.0 behaviour
629 */
630 RROutputPtr
631 RRFirstOutput(ScreenPtr pScreen)
632 {
633 rrScrPriv(pScreen);
634 RROutputPtr output;
635 int i, j;
636
637 if (!pScrPriv)
638 return NULL;
639
640 if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
641 return pScrPriv->primaryOutput;
642
643 for (i = 0; i < pScrPriv->numCrtcs; i++) {
644 RRCrtcPtr crtc = pScrPriv->crtcs[i];
645
646 for (j = 0; j < pScrPriv->numOutputs; j++) {
647 output = pScrPriv->outputs[j];
648 if (output->crtc == crtc)
649 return output;
650 }
651 }
652 return NULL;
653 }
654
655 CARD16
656 RRVerticalRefresh(xRRModeInfo * mode)
657 {
658 CARD32 refresh;
659 CARD32 dots = mode->hTotal * mode->vTotal;
660
661 if (!dots)
662 return 0;
663 refresh = (mode->dotClock + dots / 2) / dots;
664 if (refresh > 0xffff)
665 refresh = 0xffff;
666 return (CARD16) refresh;
667 }
668
669 static int
670 ProcRRDispatch(ClientPtr client)
671 {
672 REQUEST(xReq);
673 if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
674 return BadRequest;
675 return (*ProcRandrVector[stuff->data]) (client);
676 }
677
678 static int
679 SProcRRDispatch(ClientPtr client)
680 {
681 REQUEST(xReq);
682 if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
683 return BadRequest;
684 return (*SProcRandrVector[stuff->data]) (client);
685 }