Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | } |