2 * Copyright © 2006 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
28 * Notify the output of some change
31 RROutputChanged (RROutputPtr output
, Bool configChanged
)
33 ScreenPtr pScreen
= output
->pScreen
;
35 output
->changed
= TRUE
;
39 pScrPriv
->changed
= TRUE
;
41 pScrPriv
->configChanged
= TRUE
;
50 RROutputCreate (ScreenPtr pScreen
,
57 rrScrPrivPtr pScrPriv
;
62 pScrPriv
= rrGetScrPriv(pScreen
);
64 if (pScrPriv
->numOutputs
)
65 outputs
= xrealloc (pScrPriv
->outputs
,
66 (pScrPriv
->numOutputs
+ 1) * sizeof (RROutputPtr
));
68 outputs
= xalloc (sizeof (RROutputPtr
));
72 pScrPriv
->outputs
= outputs
;
74 output
= xalloc (sizeof (RROutputRec
) + nameLength
+ 1);
77 output
->id
= FakeClientID (0);
78 output
->pScreen
= pScreen
;
79 output
->name
= (char *) (output
+ 1);
80 output
->nameLength
= nameLength
;
81 memcpy (output
->name
, name
, nameLength
);
82 output
->name
[nameLength
] = '\0';
83 output
->connection
= RR_UnknownConnection
;
84 output
->subpixelOrder
= SubPixelUnknown
;
90 output
->numClones
= 0;
91 output
->clones
= NULL
;
93 output
->numPreferred
= 0;
95 output
->numUserModes
= 0;
96 output
->userModes
= NULL
;
97 output
->properties
= NULL
;
98 output
->changed
= FALSE
;
99 output
->devPrivate
= devPrivate
;
101 if (!AddResource (output
->id
, RROutputType
, (pointer
) output
))
104 pScrPriv
->outputs
[pScrPriv
->numOutputs
++] = output
;
109 * Notify extension that output parameters have been changed
112 RROutputSetClones (RROutputPtr output
,
116 RROutputPtr
*newClones
;
119 if (numClones
== output
->numClones
)
121 for (i
= 0; i
< numClones
; i
++)
122 if (output
->clones
[i
] != clones
[i
])
129 newClones
= xalloc (numClones
* sizeof (RROutputPtr
));
136 xfree (output
->clones
);
137 memcpy (newClones
, clones
, numClones
* sizeof (RROutputPtr
));
138 output
->clones
= newClones
;
139 output
->numClones
= numClones
;
140 RROutputChanged (output
, TRUE
);
145 RROutputSetModes (RROutputPtr output
,
153 if (numModes
== output
->numModes
&& numPreferred
== output
->numPreferred
)
155 for (i
= 0; i
< numModes
; i
++)
156 if (output
->modes
[i
] != modes
[i
])
160 for (i
= 0; i
< numModes
; i
++)
161 RRModeDestroy (modes
[i
]);
168 newModes
= xalloc (numModes
* sizeof (RRModePtr
));
176 for (i
= 0; i
< output
->numModes
; i
++)
177 RRModeDestroy (output
->modes
[i
]);
178 xfree (output
->modes
);
180 memcpy (newModes
, modes
, numModes
* sizeof (RRModePtr
));
181 output
->modes
= newModes
;
182 output
->numModes
= numModes
;
183 output
->numPreferred
= numPreferred
;
184 RROutputChanged (output
, TRUE
);
189 RROutputAddUserMode (RROutputPtr output
,
193 ScreenPtr pScreen
= output
->pScreen
;
197 /* Check to see if this mode is already listed for this output */
198 for (m
= 0; m
< output
->numModes
+ output
->numUserModes
; m
++)
200 RRModePtr e
= (m
< output
->numModes
?
202 output
->userModes
[m
- output
->numModes
]);
207 /* Check with the DDX to see if this mode is OK */
208 if (pScrPriv
->rrOutputValidateMode
)
209 if (!pScrPriv
->rrOutputValidateMode (pScreen
, output
, mode
))
212 if (output
->userModes
)
213 newModes
= xrealloc (output
->userModes
,
214 (output
->numUserModes
+ 1) * sizeof (RRModePtr
));
216 newModes
= xalloc (sizeof (RRModePtr
));
220 output
->userModes
= newModes
;
221 output
->userModes
[output
->numUserModes
++] = mode
;
223 RROutputChanged (output
, TRUE
);
224 RRTellChanged (pScreen
);
229 RROutputDeleteUserMode (RROutputPtr output
,
234 /* Find this mode in the user mode list */
235 for (m
= 0; m
< output
->numUserModes
; m
++)
237 RRModePtr e
= output
->userModes
[m
];
242 /* Not there, access error */
243 if (m
== output
->numUserModes
)
246 /* make sure the mode isn't active for this output */
247 if (output
->crtc
&& output
->crtc
->mode
== mode
)
250 memmove (output
->userModes
+ m
, output
->userModes
+ m
+ 1,
251 (output
->numUserModes
- m
- 1) * sizeof (RRModePtr
));
252 output
->numUserModes
--;
253 RRModeDestroy (mode
);
258 RROutputSetCrtcs (RROutputPtr output
,
265 if (numCrtcs
== output
->numCrtcs
)
267 for (i
= 0; i
< numCrtcs
; i
++)
268 if (output
->crtcs
[i
] != crtcs
[i
])
275 newCrtcs
= xalloc (numCrtcs
* sizeof (RRCrtcPtr
));
282 xfree (output
->crtcs
);
283 memcpy (newCrtcs
, crtcs
, numCrtcs
* sizeof (RRCrtcPtr
));
284 output
->crtcs
= newCrtcs
;
285 output
->numCrtcs
= numCrtcs
;
286 RROutputChanged (output
, TRUE
);
291 RROutputSetConnection (RROutputPtr output
,
294 if (output
->connection
== connection
)
296 output
->connection
= connection
;
297 RROutputChanged (output
, TRUE
);
302 RROutputSetSubpixelOrder (RROutputPtr output
,
305 if (output
->subpixelOrder
== subpixelOrder
)
308 output
->subpixelOrder
= subpixelOrder
;
309 RROutputChanged (output
, FALSE
);
314 RROutputSetPhysicalSize (RROutputPtr output
,
318 if (output
->mmWidth
== mmWidth
&& output
->mmHeight
== mmHeight
)
320 output
->mmWidth
= mmWidth
;
321 output
->mmHeight
= mmHeight
;
322 RROutputChanged (output
, FALSE
);
328 RRDeliverOutputEvent(ClientPtr client
, WindowPtr pWin
, RROutputPtr output
)
330 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
332 xRROutputChangeNotifyEvent oe
;
333 RRCrtcPtr crtc
= output
->crtc
;
334 RRModePtr mode
= crtc
? crtc
->mode
: 0;
336 oe
.type
= RRNotify
+ RREventBase
;
337 oe
.subCode
= RRNotify_OutputChange
;
338 oe
.sequenceNumber
= client
->sequence
;
339 oe
.timestamp
= pScrPriv
->lastSetTime
.milliseconds
;
340 oe
.configTimestamp
= pScrPriv
->lastConfigTime
.milliseconds
;
341 oe
.window
= pWin
->drawable
.id
;
342 oe
.output
= output
->id
;
346 oe
.mode
= mode
? mode
->mode
.id
: None
;
347 oe
.rotation
= crtc
->rotation
;
353 oe
.rotation
= RR_Rotate_0
;
355 oe
.connection
= output
->connection
;
356 oe
.subpixelOrder
= output
->subpixelOrder
;
357 WriteEventsToClient (client
, 1, (xEvent
*) &oe
);
361 * Destroy a Output at shutdown
364 RROutputDestroy (RROutputPtr output
)
366 FreeResource (output
->id
, 0);
370 RROutputDestroyResource (pointer value
, XID pid
)
372 RROutputPtr output
= (RROutputPtr
) value
;
373 ScreenPtr pScreen
= output
->pScreen
;
381 for (i
= 0; i
< pScrPriv
->numOutputs
; i
++)
383 if (pScrPriv
->outputs
[i
] == output
)
385 memmove (pScrPriv
->outputs
+ i
, pScrPriv
->outputs
+ i
+ 1,
386 (pScrPriv
->numOutputs
- (i
+ 1)) * sizeof (RROutputPtr
));
387 --pScrPriv
->numOutputs
;
394 for (m
= 0; m
< output
->numModes
; m
++)
395 RRModeDestroy (output
->modes
[m
]);
396 xfree (output
->modes
);
399 for (m
= 0; m
< output
->numUserModes
; m
++)
400 RRModeDestroy (output
->userModes
[m
]);
401 if (output
->userModes
)
402 xfree (output
->userModes
);
405 xfree (output
->crtcs
);
407 xfree (output
->clones
);
408 RRDeleteAllOutputProperties (output
);
414 * Initialize output type
419 RROutputType
= CreateNewResourceType (RROutputDestroyResource
);
423 RegisterResourceName (RROutputType
, "OUTPUT");
428 #define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32)
431 ProcRRGetOutputInfo (ClientPtr client
)
433 REQUEST(xRRGetOutputInfoReq
);
434 xRRGetOutputInfoReply rep
;
437 unsigned long extraLen
;
439 rrScrPrivPtr pScrPriv
;
446 REQUEST_SIZE_MATCH(xRRGetOutputInfoReq
);
447 output
= LookupOutput(client
, stuff
->output
, DixReadAccess
);
451 client
->errorValue
= stuff
->output
;
452 return RRErrorBase
+ BadRROutput
;
455 pScreen
= output
->pScreen
;
456 pScrPriv
= rrGetScrPriv(pScreen
);
459 rep
.sequenceNumber
= client
->sequence
;
460 rep
.length
= OutputInfoExtra
>> 2;
461 rep
.timestamp
= pScrPriv
->lastSetTime
.milliseconds
;
462 rep
.crtc
= output
->crtc
? output
->crtc
->id
: None
;
463 rep
.mmWidth
= output
->mmWidth
;
464 rep
.mmHeight
= output
->mmHeight
;
465 rep
.connection
= output
->connection
;
466 rep
.subpixelOrder
= output
->subpixelOrder
;
467 rep
.nCrtcs
= output
->numCrtcs
;
468 rep
.nModes
= output
->numModes
+ output
->numUserModes
;
469 rep
.nPreferred
= output
->numPreferred
;
470 rep
.nClones
= output
->numClones
;
471 rep
.nameLength
= output
->nameLength
;
473 extraLen
= ((output
->numCrtcs
+
474 output
->numModes
+ output
->numUserModes
+
476 ((rep
.nameLength
+ 3) >> 2)) << 2);
480 rep
.length
+= extraLen
>> 2;
481 extra
= xalloc (extraLen
);
488 crtcs
= (RRCrtc
*) extra
;
489 modes
= (RRMode
*) (crtcs
+ output
->numCrtcs
);
490 clones
= (RROutput
*) (modes
+ output
->numModes
+ output
->numUserModes
);
491 name
= (char *) (clones
+ output
->numClones
);
493 for (i
= 0; i
< output
->numCrtcs
; i
++)
495 crtcs
[i
] = output
->crtcs
[i
]->id
;
497 swapl (&crtcs
[i
], n
);
499 for (i
= 0; i
< output
->numModes
+ output
->numUserModes
; i
++)
501 if (i
< output
->numModes
)
502 modes
[i
] = output
->modes
[i
]->mode
.id
;
504 modes
[i
] = output
->userModes
[i
- output
->numModes
]->mode
.id
;
506 swapl (&modes
[i
], n
);
508 for (i
= 0; i
< output
->numClones
; i
++)
510 clones
[i
] = output
->clones
[i
]->id
;
512 swapl (&clones
[i
], n
);
514 memcpy (name
, output
->name
, output
->nameLength
);
515 if (client
->swapped
) {
516 swaps(&rep
.sequenceNumber
, n
);
517 swapl(&rep
.length
, n
);
518 swapl(&rep
.timestamp
, n
);
520 swapl(&rep
.mmWidth
, n
);
521 swapl(&rep
.mmHeight
, n
);
522 swaps(&rep
.nCrtcs
, n
);
523 swaps(&rep
.nModes
, n
);
524 swaps(&rep
.nClones
, n
);
525 swaps(&rep
.nameLength
, n
);
527 WriteToClient(client
, sizeof(xRRGetOutputInfoReply
), (char *)&rep
);
530 WriteToClient (client
, extraLen
, (char *) extra
);
534 return client
->noClientException
;