hw/xwin/glx: Use silent rules
[xserver/hramrach.git] / randr / rroutput.c
blob0890c55b58d68c6e0838dc0b6d480b844983ac73
1 /*
2 * Copyright © 2006 Keith Packard
3 * Copyright © 2008 Red Hat, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 * OF THIS SOFTWARE.
24 #include "randrstr.h"
26 RESTYPE RROutputType;
29 * Notify the output of some change
31 void
32 RROutputChanged(RROutputPtr output, Bool configChanged)
34 ScreenPtr pScreen = output->pScreen;
36 output->changed = TRUE;
37 if (pScreen) {
38 rrScrPriv(pScreen);
39 pScrPriv->changed = TRUE;
40 if (configChanged)
41 pScrPriv->configChanged = TRUE;
46 * Create an output
49 RROutputPtr
50 RROutputCreate(ScreenPtr pScreen,
51 const char *name, int nameLength, void *devPrivate)
53 RROutputPtr output;
54 RROutputPtr *outputs;
55 rrScrPrivPtr pScrPriv;
57 if (!RRInit())
58 return NULL;
60 pScrPriv = rrGetScrPriv(pScreen);
62 if (pScrPriv->numOutputs)
63 outputs = realloc(pScrPriv->outputs,
64 (pScrPriv->numOutputs + 1) * sizeof(RROutputPtr));
65 else
66 outputs = malloc(sizeof(RROutputPtr));
67 if (!outputs)
68 return FALSE;
70 pScrPriv->outputs = outputs;
72 output = malloc(sizeof(RROutputRec) + nameLength + 1);
73 if (!output)
74 return NULL;
75 output->id = FakeClientID(0);
76 output->pScreen = pScreen;
77 output->name = (char *) (output + 1);
78 output->nameLength = nameLength;
79 memcpy(output->name, name, nameLength);
80 output->name[nameLength] = '\0';
81 output->connection = RR_UnknownConnection;
82 output->subpixelOrder = SubPixelUnknown;
83 output->mmWidth = 0;
84 output->mmHeight = 0;
85 output->crtc = NULL;
86 output->numCrtcs = 0;
87 output->crtcs = NULL;
88 output->numClones = 0;
89 output->clones = NULL;
90 output->numModes = 0;
91 output->numPreferred = 0;
92 output->modes = NULL;
93 output->numUserModes = 0;
94 output->userModes = NULL;
95 output->properties = NULL;
96 output->pendingProperties = FALSE;
97 output->changed = FALSE;
98 output->devPrivate = devPrivate;
100 if (!AddResource(output->id, RROutputType, (pointer) output))
101 return NULL;
103 pScrPriv->outputs[pScrPriv->numOutputs++] = output;
104 return output;
108 * Notify extension that output parameters have been changed
110 Bool
111 RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones)
113 RROutputPtr *newClones;
114 int i;
116 if (numClones == output->numClones) {
117 for (i = 0; i < numClones; i++)
118 if (output->clones[i] != clones[i])
119 break;
120 if (i == numClones)
121 return TRUE;
123 if (numClones) {
124 newClones = malloc(numClones * sizeof(RROutputPtr));
125 if (!newClones)
126 return FALSE;
128 else
129 newClones = NULL;
130 free(output->clones);
131 memcpy(newClones, clones, numClones * sizeof(RROutputPtr));
132 output->clones = newClones;
133 output->numClones = numClones;
134 RROutputChanged(output, TRUE);
135 return TRUE;
138 Bool
139 RROutputSetModes(RROutputPtr output,
140 RRModePtr * modes, int numModes, int numPreferred)
142 RRModePtr *newModes;
143 int i;
145 if (numModes == output->numModes && numPreferred == output->numPreferred) {
146 for (i = 0; i < numModes; i++)
147 if (output->modes[i] != modes[i])
148 break;
149 if (i == numModes) {
150 for (i = 0; i < numModes; i++)
151 RRModeDestroy(modes[i]);
152 return TRUE;
156 if (numModes) {
157 newModes = malloc(numModes * sizeof(RRModePtr));
158 if (!newModes)
159 return FALSE;
161 else
162 newModes = NULL;
163 if (output->modes) {
164 for (i = 0; i < output->numModes; i++)
165 RRModeDestroy(output->modes[i]);
166 free(output->modes);
168 memcpy(newModes, modes, numModes * sizeof(RRModePtr));
169 output->modes = newModes;
170 output->numModes = numModes;
171 output->numPreferred = numPreferred;
172 RROutputChanged(output, TRUE);
173 return TRUE;
177 RROutputAddUserMode(RROutputPtr output, RRModePtr mode)
179 int m;
180 ScreenPtr pScreen = output->pScreen;
182 rrScrPriv(pScreen);
183 RRModePtr *newModes;
185 /* Check to see if this mode is already listed for this output */
186 for (m = 0; m < output->numModes + output->numUserModes; m++) {
187 RRModePtr e = (m < output->numModes ?
188 output->modes[m] :
189 output->userModes[m - output->numModes]);
190 if (mode == e)
191 return Success;
194 /* Check with the DDX to see if this mode is OK */
195 if (pScrPriv->rrOutputValidateMode)
196 if (!pScrPriv->rrOutputValidateMode(pScreen, output, mode))
197 return BadMatch;
199 if (output->userModes)
200 newModes = realloc(output->userModes,
201 (output->numUserModes + 1) * sizeof(RRModePtr));
202 else
203 newModes = malloc(sizeof(RRModePtr));
204 if (!newModes)
205 return BadAlloc;
207 output->userModes = newModes;
208 output->userModes[output->numUserModes++] = mode;
209 ++mode->refcnt;
210 RROutputChanged(output, TRUE);
211 RRTellChanged(pScreen);
212 return Success;
216 RROutputDeleteUserMode(RROutputPtr output, RRModePtr mode)
218 int m;
220 /* Find this mode in the user mode list */
221 for (m = 0; m < output->numUserModes; m++) {
222 RRModePtr e = output->userModes[m];
224 if (mode == e)
225 break;
227 /* Not there, access error */
228 if (m == output->numUserModes)
229 return BadAccess;
231 /* make sure the mode isn't active for this output */
232 if (output->crtc && output->crtc->mode == mode)
233 return BadMatch;
235 memmove(output->userModes + m, output->userModes + m + 1,
236 (output->numUserModes - m - 1) * sizeof(RRModePtr));
237 output->numUserModes--;
238 RRModeDestroy(mode);
239 return Success;
242 Bool
243 RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs)
245 RRCrtcPtr *newCrtcs;
246 int i;
248 if (numCrtcs == output->numCrtcs) {
249 for (i = 0; i < numCrtcs; i++)
250 if (output->crtcs[i] != crtcs[i])
251 break;
252 if (i == numCrtcs)
253 return TRUE;
255 if (numCrtcs) {
256 newCrtcs = malloc(numCrtcs * sizeof(RRCrtcPtr));
257 if (!newCrtcs)
258 return FALSE;
260 else
261 newCrtcs = NULL;
262 free(output->crtcs);
263 memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr));
264 output->crtcs = newCrtcs;
265 output->numCrtcs = numCrtcs;
266 RROutputChanged(output, TRUE);
267 return TRUE;
270 Bool
271 RROutputSetConnection(RROutputPtr output, CARD8 connection)
273 if (output->connection == connection)
274 return TRUE;
275 output->connection = connection;
276 RROutputChanged(output, TRUE);
277 return TRUE;
280 Bool
281 RROutputSetSubpixelOrder(RROutputPtr output, int subpixelOrder)
283 if (output->subpixelOrder == subpixelOrder)
284 return TRUE;
286 output->subpixelOrder = subpixelOrder;
287 RROutputChanged(output, FALSE);
288 return TRUE;
291 Bool
292 RROutputSetPhysicalSize(RROutputPtr output, int mmWidth, int mmHeight)
294 if (output->mmWidth == mmWidth && output->mmHeight == mmHeight)
295 return TRUE;
296 output->mmWidth = mmWidth;
297 output->mmHeight = mmHeight;
298 RROutputChanged(output, FALSE);
299 return TRUE;
302 void
303 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
305 ScreenPtr pScreen = pWin->drawable.pScreen;
307 rrScrPriv(pScreen);
308 xRROutputChangeNotifyEvent oe;
309 RRCrtcPtr crtc = output->crtc;
310 RRModePtr mode = crtc ? crtc->mode : 0;
312 oe.type = RRNotify + RREventBase;
313 oe.subCode = RRNotify_OutputChange;
314 oe.timestamp = pScrPriv->lastSetTime.milliseconds;
315 oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
316 oe.window = pWin->drawable.id;
317 oe.output = output->id;
318 if (crtc) {
319 oe.crtc = crtc->id;
320 oe.mode = mode ? mode->mode.id : None;
321 oe.rotation = crtc->rotation;
323 else {
324 oe.crtc = None;
325 oe.mode = None;
326 oe.rotation = RR_Rotate_0;
328 oe.connection = output->connection;
329 oe.subpixelOrder = output->subpixelOrder;
330 WriteEventsToClient(client, 1, (xEvent *) &oe);
334 * Destroy a Output at shutdown
336 void
337 RROutputDestroy(RROutputPtr output)
339 FreeResource(output->id, 0);
342 static int
343 RROutputDestroyResource(pointer value, XID pid)
345 RROutputPtr output = (RROutputPtr) value;
346 ScreenPtr pScreen = output->pScreen;
347 int m;
349 if (pScreen) {
350 rrScrPriv(pScreen);
351 int i;
353 if (pScrPriv->primaryOutput == output)
354 pScrPriv->primaryOutput = NULL;
356 for (i = 0; i < pScrPriv->numOutputs; i++) {
357 if (pScrPriv->outputs[i] == output) {
358 memmove(pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
359 (pScrPriv->numOutputs - (i + 1)) * sizeof(RROutputPtr));
360 --pScrPriv->numOutputs;
361 break;
365 if (output->modes) {
366 for (m = 0; m < output->numModes; m++)
367 RRModeDestroy(output->modes[m]);
368 free(output->modes);
371 for (m = 0; m < output->numUserModes; m++)
372 RRModeDestroy(output->userModes[m]);
373 free(output->userModes);
375 free(output->crtcs);
376 free(output->clones);
377 RRDeleteAllOutputProperties(output);
378 free(output);
379 return 1;
383 * Initialize output type
385 Bool
386 RROutputInit(void)
388 RROutputType = CreateNewResourceType(RROutputDestroyResource, "OUTPUT");
389 if (!RROutputType)
390 return FALSE;
392 return TRUE;
396 * Initialize output type error value
398 void
399 RROutputInitErrorValue(void)
401 SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput);
404 #define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32)
407 ProcRRGetOutputInfo(ClientPtr client)
409 REQUEST(xRRGetOutputInfoReq);
410 xRRGetOutputInfoReply rep;
411 RROutputPtr output;
412 CARD8 *extra;
413 unsigned long extraLen;
414 ScreenPtr pScreen;
415 rrScrPrivPtr pScrPriv;
416 RRCrtc *crtcs;
417 RRMode *modes;
418 RROutput *clones;
419 char *name;
420 int i;
422 REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
423 VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
425 pScreen = output->pScreen;
426 pScrPriv = rrGetScrPriv(pScreen);
428 rep.type = X_Reply;
429 rep.sequenceNumber = client->sequence;
430 rep.length = bytes_to_int32(OutputInfoExtra);
431 rep.timestamp = pScrPriv->lastSetTime.milliseconds;
432 rep.crtc = output->crtc ? output->crtc->id : None;
433 rep.mmWidth = output->mmWidth;
434 rep.mmHeight = output->mmHeight;
435 rep.connection = output->connection;
436 rep.subpixelOrder = output->subpixelOrder;
437 rep.nCrtcs = output->numCrtcs;
438 rep.nModes = output->numModes + output->numUserModes;
439 rep.nPreferred = output->numPreferred;
440 rep.nClones = output->numClones;
441 rep.nameLength = output->nameLength;
443 extraLen = ((output->numCrtcs +
444 output->numModes + output->numUserModes +
445 output->numClones + bytes_to_int32(rep.nameLength)) << 2);
447 if (extraLen) {
448 rep.length += bytes_to_int32(extraLen);
449 extra = malloc(extraLen);
450 if (!extra)
451 return BadAlloc;
453 else
454 extra = NULL;
456 crtcs = (RRCrtc *) extra;
457 modes = (RRMode *) (crtcs + output->numCrtcs);
458 clones = (RROutput *) (modes + output->numModes + output->numUserModes);
459 name = (char *) (clones + output->numClones);
461 for (i = 0; i < output->numCrtcs; i++) {
462 crtcs[i] = output->crtcs[i]->id;
463 if (client->swapped)
464 swapl(&crtcs[i]);
466 for (i = 0; i < output->numModes + output->numUserModes; i++) {
467 if (i < output->numModes)
468 modes[i] = output->modes[i]->mode.id;
469 else
470 modes[i] = output->userModes[i - output->numModes]->mode.id;
471 if (client->swapped)
472 swapl(&modes[i]);
474 for (i = 0; i < output->numClones; i++) {
475 clones[i] = output->clones[i]->id;
476 if (client->swapped)
477 swapl(&clones[i]);
479 memcpy(name, output->name, output->nameLength);
480 if (client->swapped) {
481 swaps(&rep.sequenceNumber);
482 swapl(&rep.length);
483 swapl(&rep.timestamp);
484 swapl(&rep.crtc);
485 swapl(&rep.mmWidth);
486 swapl(&rep.mmHeight);
487 swaps(&rep.nCrtcs);
488 swaps(&rep.nModes);
489 swaps(&rep.nClones);
490 swaps(&rep.nameLength);
492 WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *) &rep);
493 if (extraLen) {
494 WriteToClient(client, extraLen, (char *) extra);
495 free(extra);
498 return Success;
501 static void
502 RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, RROutputPtr output)
504 if (pScrPriv->primaryOutput == output)
505 return;
507 /* clear the old primary */
508 if (pScrPriv->primaryOutput) {
509 RROutputChanged(pScrPriv->primaryOutput, 0);
510 pScrPriv->primaryOutput = NULL;
513 /* set the new primary */
514 if (output) {
515 pScrPriv->primaryOutput = output;
516 RROutputChanged(output, 0);
519 pScrPriv->layoutChanged = TRUE;
521 RRTellChanged(pScreen);
525 ProcRRSetOutputPrimary(ClientPtr client)
527 REQUEST(xRRSetOutputPrimaryReq);
528 RROutputPtr output = NULL;
529 WindowPtr pWin;
530 rrScrPrivPtr pScrPriv;
531 int rc;
533 REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
535 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
536 if (rc != Success)
537 return rc;
539 if (stuff->output) {
540 VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
542 if (output->pScreen != pWin->drawable.pScreen) {
543 client->errorValue = stuff->window;
544 return BadMatch;
548 pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
549 RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
551 return Success;
555 ProcRRGetOutputPrimary(ClientPtr client)
557 REQUEST(xRRGetOutputPrimaryReq);
558 WindowPtr pWin;
559 rrScrPrivPtr pScrPriv;
560 xRRGetOutputPrimaryReply rep;
561 RROutputPtr primary = NULL;
562 int rc;
564 REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
566 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
567 if (rc != Success)
568 return rc;
570 pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
571 if (pScrPriv)
572 primary = pScrPriv->primaryOutput;
574 memset(&rep, 0, sizeof(rep));
575 rep.type = X_Reply;
576 rep.sequenceNumber = client->sequence;
577 rep.output = primary ? primary->id : None;
579 if (client->swapped) {
580 swaps(&rep.sequenceNumber);
581 swapl(&rep.output);
584 WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep);
586 return Success;