First import
[xorg_rtime.git] / xorg-server-1.4 / randr / rroutput.c
bloba67e4931a174853286ae9ead0cdc4c88ec433173
1 /*
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
20 * OF THIS SOFTWARE.
23 #include "randrstr.h"
25 RESTYPE RROutputType;
28 * Notify the output of some change
30 void
31 RROutputChanged (RROutputPtr output, Bool configChanged)
33 ScreenPtr pScreen = output->pScreen;
35 output->changed = TRUE;
36 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,
52 int nameLength,
53 void *devPrivate)
55 RROutputPtr output;
56 RROutputPtr *outputs;
57 rrScrPrivPtr pScrPriv;
59 if (!RRInit())
60 return NULL;
62 pScrPriv = rrGetScrPriv(pScreen);
64 if (pScrPriv->numOutputs)
65 outputs = xrealloc (pScrPriv->outputs,
66 (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
67 else
68 outputs = xalloc (sizeof (RROutputPtr));
69 if (!outputs)
70 return FALSE;
72 pScrPriv->outputs = outputs;
74 output = xalloc (sizeof (RROutputRec) + nameLength + 1);
75 if (!output)
76 return NULL;
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;
85 output->mmWidth = 0;
86 output->mmHeight = 0;
87 output->crtc = NULL;
88 output->numCrtcs = 0;
89 output->crtcs = NULL;
90 output->numClones = 0;
91 output->clones = NULL;
92 output->numModes = 0;
93 output->numPreferred = 0;
94 output->modes = NULL;
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))
102 return NULL;
104 pScrPriv->outputs[pScrPriv->numOutputs++] = output;
105 return output;
109 * Notify extension that output parameters have been changed
111 Bool
112 RROutputSetClones (RROutputPtr output,
113 RROutputPtr *clones,
114 int numClones)
116 RROutputPtr *newClones;
117 int i;
119 if (numClones == output->numClones)
121 for (i = 0; i < numClones; i++)
122 if (output->clones[i] != clones[i])
123 break;
124 if (i == numClones)
125 return TRUE;
127 if (numClones)
129 newClones = xalloc (numClones * sizeof (RROutputPtr));
130 if (!newClones)
131 return FALSE;
133 else
134 newClones = NULL;
135 if (output->clones)
136 xfree (output->clones);
137 memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
138 output->clones = newClones;
139 output->numClones = numClones;
140 RROutputChanged (output, TRUE);
141 return TRUE;
144 Bool
145 RROutputSetModes (RROutputPtr output,
146 RRModePtr *modes,
147 int numModes,
148 int numPreferred)
150 RRModePtr *newModes;
151 int i;
153 if (numModes == output->numModes && numPreferred == output->numPreferred)
155 for (i = 0; i < numModes; i++)
156 if (output->modes[i] != modes[i])
157 break;
158 if (i == numModes)
160 for (i = 0; i < numModes; i++)
161 RRModeDestroy (modes[i]);
162 return TRUE;
166 if (numModes)
168 newModes = xalloc (numModes * sizeof (RRModePtr));
169 if (!newModes)
170 return FALSE;
172 else
173 newModes = NULL;
174 if (output->modes)
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);
185 return TRUE;
189 RROutputAddUserMode (RROutputPtr output,
190 RRModePtr mode)
192 int m;
193 ScreenPtr pScreen = output->pScreen;
194 rrScrPriv(pScreen);
195 RRModePtr *newModes;
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 ?
201 output->modes[m] :
202 output->userModes[m - output->numModes]);
203 if (mode == e)
204 return Success;
207 /* Check with the DDX to see if this mode is OK */
208 if (pScrPriv->rrOutputValidateMode)
209 if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode))
210 return BadMatch;
212 if (output->userModes)
213 newModes = xrealloc (output->userModes,
214 (output->numUserModes + 1) * sizeof (RRModePtr));
215 else
216 newModes = xalloc (sizeof (RRModePtr));
217 if (!newModes)
218 return BadAlloc;
220 output->userModes = newModes;
221 output->userModes[output->numUserModes++] = mode;
222 ++mode->refcnt;
223 RROutputChanged (output, TRUE);
224 RRTellChanged (pScreen);
225 return Success;
229 RROutputDeleteUserMode (RROutputPtr output,
230 RRModePtr mode)
232 int m;
234 /* Find this mode in the user mode list */
235 for (m = 0; m < output->numUserModes; m++)
237 RRModePtr e = output->userModes[m];
239 if (mode == e)
240 break;
242 /* Not there, access error */
243 if (m == output->numUserModes)
244 return BadAccess;
246 /* make sure the mode isn't active for this output */
247 if (output->crtc && output->crtc->mode == mode)
248 return BadMatch;
250 memmove (output->userModes + m, output->userModes + m + 1,
251 (output->numUserModes - m - 1) * sizeof (RRModePtr));
252 output->numUserModes--;
253 RRModeDestroy (mode);
254 return Success;
257 Bool
258 RROutputSetCrtcs (RROutputPtr output,
259 RRCrtcPtr *crtcs,
260 int numCrtcs)
262 RRCrtcPtr *newCrtcs;
263 int i;
265 if (numCrtcs == output->numCrtcs)
267 for (i = 0; i < numCrtcs; i++)
268 if (output->crtcs[i] != crtcs[i])
269 break;
270 if (i == numCrtcs)
271 return TRUE;
273 if (numCrtcs)
275 newCrtcs = xalloc (numCrtcs * sizeof (RRCrtcPtr));
276 if (!newCrtcs)
277 return FALSE;
279 else
280 newCrtcs = NULL;
281 if (output->crtcs)
282 xfree (output->crtcs);
283 memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
284 output->crtcs = newCrtcs;
285 output->numCrtcs = numCrtcs;
286 RROutputChanged (output, TRUE);
287 return TRUE;
290 Bool
291 RROutputSetConnection (RROutputPtr output,
292 CARD8 connection)
294 if (output->connection == connection)
295 return TRUE;
296 output->connection = connection;
297 RROutputChanged (output, TRUE);
298 return TRUE;
301 Bool
302 RROutputSetSubpixelOrder (RROutputPtr output,
303 int subpixelOrder)
305 if (output->subpixelOrder == subpixelOrder)
306 return TRUE;
308 output->subpixelOrder = subpixelOrder;
309 RROutputChanged (output, FALSE);
310 return TRUE;
313 Bool
314 RROutputSetPhysicalSize (RROutputPtr output,
315 int mmWidth,
316 int mmHeight)
318 if (output->mmWidth == mmWidth && output->mmHeight == mmHeight)
319 return TRUE;
320 output->mmWidth = mmWidth;
321 output->mmHeight = mmHeight;
322 RROutputChanged (output, FALSE);
323 return TRUE;
327 void
328 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
330 ScreenPtr pScreen = pWin->drawable.pScreen;
331 rrScrPriv (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;
343 if (crtc)
345 oe.crtc = crtc->id;
346 oe.mode = mode ? mode->mode.id : None;
347 oe.rotation = crtc->rotation;
349 else
351 oe.crtc = None;
352 oe.mode = None;
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
363 void
364 RROutputDestroy (RROutputPtr output)
366 FreeResource (output->id, 0);
369 static int
370 RROutputDestroyResource (pointer value, XID pid)
372 RROutputPtr output = (RROutputPtr) value;
373 ScreenPtr pScreen = output->pScreen;
374 int m;
376 if (pScreen)
378 rrScrPriv(pScreen);
379 int i;
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;
388 break;
392 if (output->modes)
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);
404 if (output->crtcs)
405 xfree (output->crtcs);
406 if (output->clones)
407 xfree (output->clones);
408 RRDeleteAllOutputProperties (output);
409 xfree (output);
410 return 1;
414 * Initialize output type
416 Bool
417 RROutputInit (void)
419 RROutputType = CreateNewResourceType (RROutputDestroyResource);
420 if (!RROutputType)
421 return FALSE;
422 #ifdef XResExtension
423 RegisterResourceName (RROutputType, "OUTPUT");
424 #endif
425 return TRUE;
428 #define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32)
431 ProcRRGetOutputInfo (ClientPtr client)
433 REQUEST(xRRGetOutputInfoReq);
434 xRRGetOutputInfoReply rep;
435 RROutputPtr output;
436 CARD8 *extra;
437 unsigned long extraLen;
438 ScreenPtr pScreen;
439 rrScrPrivPtr pScrPriv;
440 RRCrtc *crtcs;
441 RRMode *modes;
442 RROutput *clones;
443 char *name;
444 int i, n;
446 REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
447 output = LookupOutput(client, stuff->output, DixReadAccess);
449 if (!output)
451 client->errorValue = stuff->output;
452 return RRErrorBase + BadRROutput;
455 pScreen = output->pScreen;
456 pScrPriv = rrGetScrPriv(pScreen);
458 rep.type = X_Reply;
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 +
475 output->numClones +
476 ((rep.nameLength + 3) >> 2)) << 2);
478 if (extraLen)
480 rep.length += extraLen >> 2;
481 extra = xalloc (extraLen);
482 if (!extra)
483 return BadAlloc;
485 else
486 extra = NULL;
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;
496 if (client->swapped)
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;
503 else
504 modes[i] = output->userModes[i - output->numModes]->mode.id;
505 if (client->swapped)
506 swapl (&modes[i], n);
508 for (i = 0; i < output->numClones; i++)
510 clones[i] = output->clones[i]->id;
511 if (client->swapped)
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);
519 swapl(&rep.crtc, 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);
528 if (extraLen)
530 WriteToClient (client, extraLen, (char *) extra);
531 xfree (extra);
534 return client->noClientException;