]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/xserver.git/blob - randr/rroutput.c
Applied all debian/patches from glsdk-6_00_00_07 release
[glsdk/xserver.git] / randr / rroutput.c
1 /*
2  * Copyright © 2006 Keith Packard
3  * Copyright © 2008 Red Hat, Inc.
4  *
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.
14  *
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.
22  */
24 #include "randrstr.h"
26 RESTYPE RROutputType;
28 /*
29  * Notify the output of some change
30  */
31 void
32 RROutputChanged (RROutputPtr output, Bool configChanged)
33 {
34     ScreenPtr   pScreen = output->pScreen;
35     
36     output->changed = TRUE;
37     if (pScreen)
38     {
39         rrScrPriv (pScreen);
40         pScrPriv->changed = TRUE;
41         if (configChanged)
42             pScrPriv->configChanged = TRUE;
43     }
44 }
46 /*
47  * Create an output
48  */
50 RROutputPtr
51 RROutputCreate (ScreenPtr   pScreen,
52                 const char  *name,
53                 int         nameLength,
54                 void        *devPrivate)
55 {
56     RROutputPtr     output;
57     RROutputPtr     *outputs;
58     rrScrPrivPtr    pScrPriv;
60     if (!RRInit())
61         return NULL;
62     
63     pScrPriv = rrGetScrPriv(pScreen);
65     if (pScrPriv->numOutputs)
66         outputs = realloc(pScrPriv->outputs,
67                             (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
68     else
69         outputs = malloc(sizeof (RROutputPtr));
70     if (!outputs)
71         return FALSE;
73     pScrPriv->outputs = outputs;
74     
75     output = malloc(sizeof (RROutputRec) + nameLength + 1);
76     if (!output)
77         return NULL;
78     output->id = FakeClientID (0);
79     output->pScreen = pScreen;
80     output->name = (char *) (output + 1);
81     output->nameLength = nameLength;
82     memcpy (output->name, name, nameLength);
83     output->name[nameLength] = '\0';
84     output->connection = RR_UnknownConnection;
85     output->subpixelOrder = SubPixelUnknown;
86     output->mmWidth = 0;
87     output->mmHeight = 0;
88     output->crtc = NULL;
89     output->numCrtcs = 0;
90     output->crtcs = NULL;
91     output->numClones = 0;
92     output->clones = NULL;
93     output->numModes = 0;
94     output->numPreferred = 0;
95     output->modes = NULL;
96     output->numUserModes = 0;
97     output->userModes = NULL;
98     output->properties = NULL;
99     output->pendingProperties = FALSE;
100     output->changed = FALSE;
101     output->devPrivate = devPrivate;
102     
103     if (!AddResource (output->id, RROutputType, (pointer) output))
104         return NULL;
106     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
107     return output;
110 /*
111  * Notify extension that output parameters have been changed
112  */
113 Bool
114 RROutputSetClones (RROutputPtr  output,
115                    RROutputPtr  *clones,
116                    int          numClones)
118     RROutputPtr *newClones;
119     int         i;
121     if (numClones == output->numClones)
122     {
123         for (i = 0; i < numClones; i++)
124             if (output->clones[i] != clones[i])
125                 break;
126         if (i == numClones)
127             return TRUE;
128     }
129     if (numClones)
130     {
131         newClones = malloc(numClones * sizeof (RROutputPtr));
132         if (!newClones)
133             return FALSE;
134     }
135     else
136         newClones = NULL;
137     free(output->clones);
138     memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
139     output->clones = newClones;
140     output->numClones = numClones;
141     RROutputChanged (output, TRUE);
142     return TRUE;
145 Bool
146 RROutputSetModes (RROutputPtr   output,
147                   RRModePtr     *modes,
148                   int           numModes,
149                   int           numPreferred)
151     RRModePtr   *newModes;
152     int         i;
154     if (numModes == output->numModes && numPreferred == output->numPreferred)
155     {
156         for (i = 0; i < numModes; i++)
157             if (output->modes[i] != modes[i])
158                 break;
159         if (i == numModes)
160         {
161             for (i = 0; i < numModes; i++)
162                 RRModeDestroy (modes[i]);
163             return TRUE;
164         }
165     }
167     if (numModes)
168     {
169         newModes = malloc(numModes * sizeof (RRModePtr));
170         if (!newModes)
171             return FALSE;
172     }
173     else
174         newModes = NULL;
175     if (output->modes)
176     {
177         for (i = 0; i < output->numModes; i++)
178             RRModeDestroy (output->modes[i]);
179         free(output->modes);
180     }
181     memcpy (newModes, modes, numModes * sizeof (RRModePtr));
182     output->modes = newModes;
183     output->numModes = numModes;
184     output->numPreferred = numPreferred;
185     RROutputChanged (output, TRUE);
186     return TRUE;
189 int
190 RROutputAddUserMode (RROutputPtr    output,
191                      RRModePtr      mode)
193     int         m;
194     ScreenPtr   pScreen = output->pScreen;
195     rrScrPriv(pScreen);
196     RRModePtr   *newModes;
198     /* Check to see if this mode is already listed for this output */
199     for (m = 0; m < output->numModes + output->numUserModes; m++)
200     {
201         RRModePtr   e = (m < output->numModes ?
202                          output->modes[m] :
203                          output->userModes[m - output->numModes]);
204         if (mode == e)
205             return Success;
206     }
208     /* Check with the DDX to see if this mode is OK */
209     if (pScrPriv->rrOutputValidateMode)
210         if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode))
211             return BadMatch;
213     if (output->userModes)
214         newModes = realloc(output->userModes,
215                              (output->numUserModes + 1) * sizeof (RRModePtr));
216     else
217         newModes = malloc(sizeof (RRModePtr));
218     if (!newModes)
219         return BadAlloc;
221     output->userModes = newModes;
222     output->userModes[output->numUserModes++] = mode;
223     ++mode->refcnt;
224     RROutputChanged (output, TRUE);
225     RRTellChanged (pScreen);
226     return Success;
229 int
230 RROutputDeleteUserMode (RROutputPtr output,
231                         RRModePtr   mode)
233     int         m;
234     
235     /* Find this mode in the user mode list */
236     for (m = 0; m < output->numUserModes; m++)
237     {
238         RRModePtr   e = output->userModes[m];
240         if (mode == e)
241             break;
242     }
243     /* Not there, access error */
244     if (m == output->numUserModes)
245         return BadAccess;
247     /* make sure the mode isn't active for this output */
248     if (output->crtc && output->crtc->mode == mode)
249         return BadMatch;
251     memmove (output->userModes + m, output->userModes + m + 1,
252              (output->numUserModes - m - 1) * sizeof (RRModePtr));
253     output->numUserModes--;
254     RRModeDestroy (mode);
255     return Success;
258 Bool
259 RROutputSetCrtcs (RROutputPtr   output,
260                   RRCrtcPtr     *crtcs,
261                   int           numCrtcs)
263     RRCrtcPtr   *newCrtcs;
264     int         i;
266     if (numCrtcs == output->numCrtcs)
267     {
268         for (i = 0; i < numCrtcs; i++)
269             if (output->crtcs[i] != crtcs[i])
270                 break;
271         if (i == numCrtcs)
272             return TRUE;
273     }
274     if (numCrtcs)
275     {
276         newCrtcs = malloc(numCrtcs * sizeof (RRCrtcPtr));
277         if (!newCrtcs)
278             return FALSE;
279     }
280     else
281         newCrtcs = NULL;
282     free(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;
335     
336     oe.type = RRNotify + RREventBase;
337     oe.subCode = RRNotify_OutputChange;
338     oe.timestamp = pScrPriv->lastSetTime.milliseconds;
339     oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
340     oe.window = pWin->drawable.id;
341     oe.output = output->id;
342     if (crtc)
343     {
344         oe.crtc = crtc->id;
345         oe.mode = mode ? mode->mode.id : None;
346         oe.rotation = crtc->rotation;
347     }
348     else
349     {
350         oe.crtc = None;
351         oe.mode = None;
352         oe.rotation = RR_Rotate_0;
353     }
354     oe.connection = output->connection;
355     oe.subpixelOrder = output->subpixelOrder;
356     WriteEventsToClient (client, 1, (xEvent *) &oe);
359 /*
360  * Destroy a Output at shutdown
361  */
362 void
363 RROutputDestroy (RROutputPtr output)
365     FreeResource (output->id, 0);
368 static int
369 RROutputDestroyResource (pointer value, XID pid)
371     RROutputPtr output = (RROutputPtr) value;
372     ScreenPtr   pScreen = output->pScreen;
373     int         m;
375     if (pScreen)
376     {
377         rrScrPriv(pScreen);
378         int             i;
380         if (pScrPriv->primaryOutput == output)
381             pScrPriv->primaryOutput = NULL;
382     
383         for (i = 0; i < pScrPriv->numOutputs; i++)
384         {
385             if (pScrPriv->outputs[i] == output)
386             {
387                 memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
388                          (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr));
389                 --pScrPriv->numOutputs;
390                 break;
391             }
392         }
393     }
394     if (output->modes)
395     {
396         for (m = 0; m < output->numModes; m++)
397             RRModeDestroy (output->modes[m]);
398         free(output->modes);
399     }
400     
401     for (m = 0; m < output->numUserModes; m++)
402         RRModeDestroy (output->userModes[m]);
403     free(output->userModes);
405     free(output->crtcs);
406     free(output->clones);
407     RRDeleteAllOutputProperties (output);
408     free(output);
409     return 1;
412 /*
413  * Initialize output type
414  */
415 Bool
416 RROutputInit (void)
418     RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT");
419     if (!RROutputType)
420         return FALSE;
422     return TRUE;
425 /*
426  * Initialize output type error value
427  */
428 void
429 RROutputInitErrorValue(void)
431     SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput);
434 #define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32)
436 int
437 ProcRRGetOutputInfo (ClientPtr client)
439     REQUEST(xRRGetOutputInfoReq);
440     xRRGetOutputInfoReply       rep;
441     RROutputPtr                 output;
442     CARD8                       *extra;
443     unsigned long               extraLen;
444     ScreenPtr                   pScreen;
445     rrScrPrivPtr                pScrPriv;
446     RRCrtc                      *crtcs;
447     RRMode                      *modes;
448     RROutput                    *clones;
449     char                        *name;
450     int                         i, n;
451     
452     REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
453     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
455     pScreen = output->pScreen;
456     pScrPriv = rrGetScrPriv(pScreen);
458     rep.type = X_Reply;
459     rep.sequenceNumber = client->sequence;
460     rep.length = bytes_to_int32(OutputInfoExtra);
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;
472     
473     extraLen = ((output->numCrtcs +
474                  output->numModes + output->numUserModes +
475                  output->numClones +
476                  bytes_to_int32(rep.nameLength)) << 2);
478     if (extraLen)
479     {
480         rep.length += bytes_to_int32(extraLen);
481         extra = malloc(extraLen);
482         if (!extra)
483             return BadAlloc;
484     }
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);
492     
493     for (i = 0; i < output->numCrtcs; i++)
494     {
495         crtcs[i] = output->crtcs[i]->id;
496         if (client->swapped)
497             swapl (&crtcs[i], n);
498     }
499     for (i = 0; i < output->numModes + output->numUserModes; i++)
500     {
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);
507     }
508     for (i = 0; i < output->numClones; i++)
509     {
510         clones[i] = output->clones[i]->id;
511         if (client->swapped)
512             swapl (&clones[i], n);
513     }
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);
526     }
527     WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep);
528     if (extraLen)
529     {
530         WriteToClient (client, extraLen, (char *) extra);
531         free(extra);
532     }
533     
534     return Success;
537 static void
538 RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv,
539                    RROutputPtr output)
541     if (pScrPriv->primaryOutput == output)
542         return;
544     /* clear the old primary */
545     if (pScrPriv->primaryOutput) {
546         RROutputChanged(pScrPriv->primaryOutput, 0);
547         pScrPriv->primaryOutput = NULL;
548     }
550     /* set the new primary */
551     if (output) {
552         pScrPriv->primaryOutput = output;
553         RROutputChanged(output, 0);
554     }
556     pScrPriv->layoutChanged = TRUE;
558     RRTellChanged(pScreen);
561 int
562 ProcRRSetOutputPrimary(ClientPtr client)
564     REQUEST(xRRSetOutputPrimaryReq);
565     RROutputPtr output = NULL;
566     WindowPtr pWin;
567     rrScrPrivPtr pScrPriv;
568     int rc;
570     REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
572     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
573     if (rc != Success)
574         return rc;
576     if (stuff->output) {
577         VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
579         if (output->pScreen != pWin->drawable.pScreen) {
580             client->errorValue = stuff->window;
581             return BadMatch;
582         }
583     }
585     pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
586     if (pScrPriv)
587         RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
589     return Success;
592 int
593 ProcRRGetOutputPrimary(ClientPtr client)
595     REQUEST(xRRGetOutputPrimaryReq);
596     WindowPtr pWin;
597     rrScrPrivPtr pScrPriv;
598     xRRGetOutputPrimaryReply rep;
599     RROutputPtr primary = NULL;
600     int rc;
602     REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
604     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
605     if (rc != Success)
606         return rc;
608     pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
609     if (pScrPriv)
610         primary = pScrPriv->primaryOutput;
612     memset(&rep, 0, sizeof(rep));
613     rep.type = X_Reply;
614     rep.sequenceNumber = client->sequence;
615     rep.output = primary ? primary->id : None;
617     if (client->swapped) {
618         int n;
619         swaps(&rep.sequenceNumber, n);
620         swapl(&rep.output, n);
621     }
623     WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep);
625     return Success;