Bug Summary

File:randr/rrcrtc.c
Location:line 367, column 24
Description:Access to field 'current_master' results in a dereference of a null pointer (loaded from field 'pScreen')

Annotated Source Code

1/*
2 * Copyright © 2006 Keith Packard
3 * Copyright 2010 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 */
23
24#include "randrstr.h"
25#include "swaprep.h"
26#include "mipointer.h"
27
28RESTYPE RRCrtcType;
29
30/*
31 * Notify the CRTC of some change
32 */
33void
34RRCrtcChanged(RRCrtcPtr crtc, Bool layoutChanged)
35{
36 ScreenPtr pScreen = crtc->pScreen;
37
38 crtc->changed = TRUE1;
39 if (pScreen) {
40 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
41
42 RRSetChanged(pScreen);
43 /*
44 * Send ConfigureNotify on any layout change
45 */
46 if (layoutChanged)
47 pScrPriv->layoutChanged = TRUE1;
48 }
49}
50
51/*
52 * Create a CRTC
53 */
54RRCrtcPtr
55RRCrtcCreate(ScreenPtr pScreen, void *devPrivate)
56{
57 RRCrtcPtr crtc;
58 RRCrtcPtr *crtcs;
59 rrScrPrivPtr pScrPriv;
60
61 if (!RRInit())
62 return NULL((void*)0);
63
64 pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&rrPrivKeyRec)))
;
65
66 /* make space for the crtc pointer */
67 if (pScrPriv->numCrtcs)
68 crtcs = realloc(pScrPriv->crtcs,
69 (pScrPriv->numCrtcs + 1) * sizeof(RRCrtcPtr));
70 else
71 crtcs = malloc(sizeof(RRCrtcPtr));
72 if (!crtcs)
73 return FALSE0;
74 pScrPriv->crtcs = crtcs;
75
76 crtc = calloc(1, sizeof(RRCrtcRec));
77 if (!crtc)
78 return NULL((void*)0);
79 crtc->id = FakeClientID(0);
80 crtc->pScreen = pScreen;
81 crtc->mode = NULL((void*)0);
82 crtc->x = 0;
83 crtc->y = 0;
84 crtc->rotation = RR_Rotate_01;
85 crtc->rotations = RR_Rotate_01;
86 crtc->outputs = NULL((void*)0);
87 crtc->numOutputs = 0;
88 crtc->gammaSize = 0;
89 crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL((void*)0);
90 crtc->changed = FALSE0;
91 crtc->devPrivate = devPrivate;
92 RRTransformInit(&crtc->client_pending_transform);
93 RRTransformInit(&crtc->client_current_transform);
94 pixman_transform_init_identity(&crtc->transform);
95 pixman_f_transform_init_identity(&crtc->f_transform);
96 pixman_f_transform_init_identity(&crtc->f_inverse);
97
98 if (!AddResourceDarwin_X_AddResource(crtc->id, RRCrtcType, (void *) crtc))
99 return NULL((void*)0);
100
101 /* attach the screen and crtc together */
102 crtc->pScreen = pScreen;
103 pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
104
105 RRResourcesChanged(pScreen);
106
107 return crtc;
108}
109
110/*
111 * Set the allowed rotations on a CRTC
112 */
113void
114RRCrtcSetRotations(RRCrtcPtr crtc, Rotation rotations)
115{
116 crtc->rotations = rotations;
117}
118
119/*
120 * Set whether transforms are allowed on a CRTC
121 */
122void
123RRCrtcSetTransformSupport(RRCrtcPtr crtc, Bool transforms)
124{
125 crtc->transforms = transforms;
126}
127
128/*
129 * Notify the extension that the Crtc has been reconfigured,
130 * the driver calls this whenever it has updated the mode
131 */
132Bool
133RRCrtcNotify(RRCrtcPtr crtc,
134 RRModePtr mode,
135 int x,
136 int y,
137 Rotation rotation,
138 RRTransformPtr transform, int numOutputs, RROutputPtr * outputs)
139{
140 int i, j;
141
142 /*
143 * Check to see if any of the new outputs were
144 * not in the old list and mark them as changed
145 */
146 for (i = 0; i < numOutputs; i++) {
147 for (j = 0; j < crtc->numOutputs; j++)
148 if (outputs[i] == crtc->outputs[j])
149 break;
150 if (j == crtc->numOutputs) {
151 outputs[i]->crtc = crtc;
152 RROutputChanged(outputs[i], FALSE0);
153 RRCrtcChanged(crtc, FALSE0);
154 }
155 }
156 /*
157 * Check to see if any of the old outputs are
158 * not in the new list and mark them as changed
159 */
160 for (j = 0; j < crtc->numOutputs; j++) {
161 for (i = 0; i < numOutputs; i++)
162 if (outputs[i] == crtc->outputs[j])
163 break;
164 if (i == numOutputs) {
165 if (crtc->outputs[j]->crtc == crtc)
166 crtc->outputs[j]->crtc = NULL((void*)0);
167 RROutputChanged(crtc->outputs[j], FALSE0);
168 RRCrtcChanged(crtc, FALSE0);
169 }
170 }
171 /*
172 * Reallocate the crtc output array if necessary
173 */
174 if (numOutputs != crtc->numOutputs) {
175 RROutputPtr *newoutputs;
176
177 if (numOutputs) {
178 if (crtc->numOutputs)
179 newoutputs = realloc(crtc->outputs,
180 numOutputs * sizeof(RROutputPtr));
181 else
182 newoutputs = malloc(numOutputs * sizeof(RROutputPtr));
183 if (!newoutputs)
184 return FALSE0;
185 }
186 else {
187 free(crtc->outputs);
188 newoutputs = NULL((void*)0);
189 }
190 crtc->outputs = newoutputs;
191 crtc->numOutputs = numOutputs;
192 }
193 /*
194 * Copy the new list of outputs into the crtc
195 */
196 memcpy(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr))__builtin___memcpy_chk (crtc->outputs, outputs, numOutputs
* sizeof(RROutputPtr), __builtin_object_size (crtc->outputs
, 0))
;
197 /*
198 * Update remaining crtc fields
199 */
200 if (mode != crtc->mode) {
201 if (crtc->mode)
202 RRModeDestroy(crtc->mode);
203 crtc->mode = mode;
204 if (mode != NULL((void*)0))
205 mode->refcnt++;
206 RRCrtcChanged(crtc, TRUE1);
207 }
208 if (x != crtc->x) {
209 crtc->x = x;
210 RRCrtcChanged(crtc, TRUE1);
211 }
212 if (y != crtc->y) {
213 crtc->y = y;
214 RRCrtcChanged(crtc, TRUE1);
215 }
216 if (rotation != crtc->rotation) {
217 crtc->rotation = rotation;
218 RRCrtcChanged(crtc, TRUE1);
219 }
220 if (!RRTransformEqual(transform, &crtc->client_current_transform)) {
221 RRTransformCopy(&crtc->client_current_transform, transform);
222 RRCrtcChanged(crtc, TRUE1);
223 }
224 if (crtc->changed && mode) {
225 RRTransformCompute(x, y,
226 mode->mode.width, mode->mode.height,
227 rotation,
228 &crtc->client_current_transform,
229 &crtc->transform, &crtc->f_transform,
230 &crtc->f_inverse);
231 }
232 return TRUE1;
233}
234
235void
236RRDeliverCrtcEvent(ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
237{
238 ScreenPtr pScreen = pWin->drawable.pScreen;
239
240 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
241 RRModePtr mode = crtc->mode;
242
243 xRRCrtcChangeNotifyEvent ce = {
244 .type = RRNotify1 + RREventBase,
245 .subCode = RRNotify_CrtcChange0,
246 .timestamp = pScrPriv->lastSetTime.milliseconds,
247 .window = pWin->drawable.id,
248 .crtc = crtc->id,
249 .mode = mode ? mode->mode.id : None0L,
250 .rotation = crtc->rotation,
251 .x = mode ? crtc->x : 0,
252 .y = mode ? crtc->y : 0,
253 .width = mode ? mode->mode.width : 0,
254 .height = mode ? mode->mode.height : 0
255 };
256 WriteEventsToClient(client, 1, (xEvent *) &ce);
257}
258
259static Bool
260RRCrtcPendingProperties(RRCrtcPtr crtc)
261{
262 ScreenPtr pScreen = crtc->pScreen;
263
264 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
265 int o;
266
267 for (o = 0; o < pScrPriv->numOutputs; o++) {
268 RROutputPtr output = pScrPriv->outputs[o];
269
270 if (output->crtc == crtc && output->pendingProperties)
271 return TRUE1;
272 }
273 return FALSE0;
274}
275
276static void
277crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
278{
279 *left = crtc->x;
280 *top = crtc->y;
281
282 switch (crtc->rotation) {
283 case RR_Rotate_01:
284 case RR_Rotate_1804:
285 default:
286 *right = crtc->x + crtc->mode->mode.width;
287 *bottom = crtc->y + crtc->mode->mode.height;
288 return;
289 case RR_Rotate_902:
290 case RR_Rotate_2708:
291 *right = crtc->x + crtc->mode->mode.height;
292 *bottom = crtc->y + crtc->mode->mode.width;
293 return;
294 }
295}
296
297/* overlapping counts as adjacent */
298static Bool
299crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
300{
301 /* left, right, top, bottom... */
302 int al, ar, at, ab;
303 int bl, br, bt, bb;
304 int cl, cr, ct, cb; /* the overlap, if any */
305
306 crtc_bounds(a, &al, &ar, &at, &ab);
307 crtc_bounds(b, &bl, &br, &bt, &bb);
308
309 cl = max(al, bl)(((al) > (bl)) ? (al) : (bl));
310 cr = min(ar, br)(((ar) < (br)) ? (ar) : (br));
311 ct = max(at, bt)(((at) > (bt)) ? (at) : (bt));
312 cb = min(ab, bb)(((ab) < (bb)) ? (ab) : (bb));
313
314 return (cl <= cr) && (ct <= cb);
315}
316
317/* Depth-first search and mark all CRTCs reachable from cur */
318static void
319mark_crtcs(rrScrPrivPtr pScrPriv, int *reachable, int cur)
320{
321 int i;
322
323 reachable[cur] = TRUE1;
324 for (i = 0; i < pScrPriv->numCrtcs; ++i) {
325 if (reachable[i] || !pScrPriv->crtcs[i]->mode)
326 continue;
327 if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
328 mark_crtcs(pScrPriv, reachable, i);
329 }
330}
331
332static void
333RRComputeContiguity(ScreenPtr pScreen)
334{
335 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
336 Bool discontiguous = TRUE1;
337 int i, n = pScrPriv->numCrtcs;
338
339 int *reachable = calloc(n, sizeof(int));
340
341 if (!reachable)
342 goto out;
343
344 /* Find first enabled CRTC and start search for reachable CRTCs from it */
345 for (i = 0; i < n; ++i) {
346 if (pScrPriv->crtcs[i]->mode) {
347 mark_crtcs(pScrPriv, reachable, i);
348 break;
349 }
350 }
351
352 /* Check that all enabled CRTCs were marked as reachable */
353 for (i = 0; i < n; ++i)
354 if (pScrPriv->crtcs[i]->mode && !reachable[i])
355 goto out;
356
357 discontiguous = FALSE0;
358
359 out:
360 free(reachable);
361 pScrPriv->discontiguous = discontiguous;
362}
363
364void
365RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
366{
367 ScreenPtr master = crtc->pScreen->current_master;
5
Access to field 'current_master' results in a dereference of a null pointer (loaded from field 'pScreen')
368 PixmapPtr mscreenpix;
369 rrScrPriv(crtc->pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(crtc->pScreen)->devPrivates, (&rrPrivKeyRec)))
;
370
371 mscreenpix = master->GetScreenPixmap(master);
372
373 pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL((void*)0));
374 if (crtc->scanout_pixmap) {
375 master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap);
376 /*
377 * Unref the pixmap twice: once for the original reference, and once
378 * for the reference implicitly added by PixmapShareToSlave.
379 */
380 master->DestroyPixmap(crtc->scanout_pixmap->master_pixmap);
381 master->DestroyPixmap(crtc->scanout_pixmap->master_pixmap);
382 crtc->pScreen->DestroyPixmap(crtc->scanout_pixmap);
383 }
384 crtc->scanout_pixmap = NULL((void*)0);
385 RRCrtcChanged(crtc, TRUE1);
386}
387
388static Bool
389rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
390 int x, int y)
391{
392 PixmapPtr mpix, spix;
393 ScreenPtr master = crtc->pScreen->current_master;
394 Bool ret;
395 int depth;
396 PixmapPtr mscreenpix;
397 PixmapPtr protopix = crtc->pScreen->current_master->GetScreenPixmap(crtc->pScreen->current_master);
398 rrScrPriv(crtc->pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(crtc->pScreen)->devPrivates, (&rrPrivKeyRec)))
;
399
400 /* create a pixmap on the master screen,
401 then get a shared handle for it
402 create a shared pixmap on the slave screen using the handle
403 set the master screen to do dirty updates to the shared pixmap
404 from the screen pixmap.
405 set slave screen to scanout shared linear pixmap
406 */
407
408 mscreenpix = master->GetScreenPixmap(master);
409 depth = protopix->drawable.depth;
410
411 if (crtc->scanout_pixmap)
412 RRCrtcDetachScanoutPixmap(crtc);
413
414 if (width == 0 && height == 0) {
415 return TRUE1;
416 }
417
418 mpix = master->CreatePixmap(master, width, height, depth,
419 CREATE_PIXMAP_USAGE_SHARED4);
420 if (!mpix)
421 return FALSE0;
422
423 spix = PixmapShareToSlave(mpix, crtc->pScreen);
424 if (spix == NULL((void*)0)) {
425 master->DestroyPixmap(mpix);
426 return FALSE0;
427 }
428
429 ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix);
430 if (ret == FALSE0) {
431 ErrorF("randr: failed to set shadow slave pixmap\n");
432 return FALSE0;
433 }
434
435 crtc->scanout_pixmap = spix;
436
437 master->StartPixmapTracking(mscreenpix, spix, x, y);
438 return TRUE1;
439}
440
441static Bool
442rrCheckPixmapBounding(ScreenPtr pScreen,
443 RRCrtcPtr rr_crtc, int x, int y, int w, int h)
444{
445 RegionRec root_pixmap_region, total_region, new_crtc_region;
446 int c;
447 BoxRec newbox;
448 BoxPtr newsize;
449 ScreenPtr slave;
450 int new_width, new_height;
451 PixmapPtr screen_pixmap = pScreen->GetScreenPixmap(pScreen);
452 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
453
454 PixmapRegionInit(&root_pixmap_region, screen_pixmap);
455 RegionInit(&total_region, NULL((void*)0), 0);
456
457 /* have to iterate all the crtcs of the attached gpu masters
458 and all their output slaves */
459 for (c = 0; c < pScrPriv->numCrtcs; c++) {
460 if (pScrPriv->crtcs[c] == rr_crtc) {
461 newbox.x1 = x;
462 newbox.x2 = x + w;
463 newbox.y1 = y;
464 newbox.y2 = y + h;
465 } else {
466 if (!pScrPriv->crtcs[c]->mode)
467 continue;
468 newbox.x1 = pScrPriv->crtcs[c]->x;
469 newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
470 newbox.y1 = pScrPriv->crtcs[c]->y;
471 newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
472 }
473 RegionInit(&new_crtc_region, &newbox, 1);
474 RegionUnion(&total_region, &total_region, &new_crtc_region);
475 }
476
477 xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head)for (slave = (typeof(*slave) *)((char *)((&pScreen->output_slave_list
)->next) - __builtin_offsetof(typeof(*slave), output_head)
); &slave->output_head != (&pScreen->output_slave_list
); slave = (typeof(*slave) *)((char *)(slave->output_head.
next) - __builtin_offsetof(typeof(*slave), output_head)))
{
478 rrScrPrivPtr slave_priv = rrGetScrPriv(slave)((rrScrPrivPtr)dixLookupPrivate(&(slave)->devPrivates,
(&rrPrivKeyRec)))
;
479 for (c = 0; c < slave_priv->numCrtcs; c++) {
480 if (slave_priv->crtcs[c] == rr_crtc) {
481 newbox.x1 = x;
482 newbox.x2 = x + w;
483 newbox.y1 = y;
484 newbox.y2 = y + h;
485 }
486 else {
487 if (!slave_priv->crtcs[c]->mode)
488 continue;
489 newbox.x1 = slave_priv->crtcs[c]->x;
490 newbox.x2 = slave_priv->crtcs[c]->x + slave_priv->crtcs[c]->mode->mode.width;
491 newbox.y1 = slave_priv->crtcs[c]->y;
492 newbox.y2 = slave_priv->crtcs[c]->y + slave_priv->crtcs[c]->mode->mode.height;
493 }
494 RegionInit(&new_crtc_region, &newbox, 1);
495 RegionUnion(&total_region, &total_region, &new_crtc_region);
496 }
497 }
498
499 newsize = RegionExtents(&total_region);
500 new_width = newsize->x2 - newsize->x1;
501 new_height = newsize->y2 - newsize->y1;
502
503 if (new_width == screen_pixmap->drawable.width &&
504 new_height == screen_pixmap->drawable.height) {
505 } else {
506 pScrPriv->rrScreenSetSize(pScreen, new_width, new_height, 0, 0);
507 }
508
509 /* set shatters TODO */
510 return TRUE1;
511}
512
513/*
514 * Request that the Crtc be reconfigured
515 */
516Bool
517RRCrtcSet(RRCrtcPtr crtc,
518 RRModePtr mode,
519 int x,
520 int y, Rotation rotation, int numOutputs, RROutputPtr * outputs)
521{
522 ScreenPtr pScreen = crtc->pScreen;
523 Bool ret = FALSE0;
524 Bool recompute = TRUE1;
525 Bool crtcChanged;
526 int o;
527
528 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
529
530 crtcChanged = FALSE0;
531 for (o = 0; o < numOutputs; o++) {
532 if (outputs[o] && outputs[o]->crtc != crtc) {
533 crtcChanged = TRUE1;
534 break;
535 }
536 }
537
538 /* See if nothing changed */
539 if (crtc->mode == mode &&
540 crtc->x == x &&
541 crtc->y == y &&
542 crtc->rotation == rotation &&
543 crtc->numOutputs == numOutputs &&
544 !memcmp(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr)) &&
545 !RRCrtcPendingProperties(crtc) && !RRCrtcPendingTransform(crtc) &&
546 !crtcChanged) {
547 recompute = FALSE0;
548 ret = TRUE1;
549 }
550 else {
551 if (pScreen->isGPU) {
552 ScreenPtr master = pScreen->current_master;
553 int width = 0, height = 0;
554
555 if (mode) {
556 width = mode->mode.width;
557 height = mode->mode.height;
558 }
559 ret = rrCheckPixmapBounding(master, crtc,
560 x, y, width, height);
561 if (!ret)
562 return FALSE0;
563
564 if (pScreen->current_master) {
565 ret = rrCreateSharedPixmap(crtc, width, height, x, y);
566 }
567 }
568#if RANDR_12_INTERFACE1
569 if (pScrPriv->rrCrtcSet) {
570 ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
571 rotation, numOutputs, outputs);
572 }
573 else
574#endif
575 {
576#if RANDR_10_INTERFACE1
577 if (pScrPriv->rrSetConfig) {
578 RRScreenSize size;
579 RRScreenRate rate;
580
581 if (!mode) {
582 RRCrtcNotify(crtc, NULL((void*)0), x, y, rotation, NULL((void*)0), 0, NULL((void*)0));
583 ret = TRUE1;
584 }
585 else {
586 size.width = mode->mode.width;
587 size.height = mode->mode.height;
588 if (outputs[0]->mmWidth && outputs[0]->mmHeight) {
589 size.mmWidth = outputs[0]->mmWidth;
590 size.mmHeight = outputs[0]->mmHeight;
591 }
592 else {
593 size.mmWidth = pScreen->mmWidth;
594 size.mmHeight = pScreen->mmHeight;
595 }
596 size.nRates = 1;
597 rate.rate = RRVerticalRefresh(&mode->mode);
598 size.pRates = &rate;
599 ret =
600 (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate,
601 &size);
602 /*
603 * Old 1.0 interface tied screen size to mode size
604 */
605 if (ret) {
606 RRCrtcNotify(crtc, mode, x, y, rotation, NULL((void*)0), 1,
607 outputs);
608 RRScreenSizeNotify(pScreen);
609 }
610 }
611 }
612#endif
613 }
614 if (ret) {
615
616 RRTellChanged(pScreen);
617
618 for (o = 0; o < numOutputs; o++)
619 RRPostPendingProperties(outputs[o]);
620 }
621 }
622
623 if (recompute)
624 RRComputeContiguity(pScreen);
625
626 return ret;
627}
628
629/*
630 * Return crtc transform
631 */
632RRTransformPtr
633RRCrtcGetTransform(RRCrtcPtr crtc)
634{
635 RRTransformPtr transform = &crtc->client_pending_transform;
636
637 if (pixman_transform_is_identity(&transform->transform))
638 return NULL((void*)0);
639 return transform;
640}
641
642/*
643 * Check whether the pending and current transforms are the same
644 */
645Bool
646RRCrtcPendingTransform(RRCrtcPtr crtc)
647{
648 return memcmp(&crtc->client_current_transform.transform,
649 &crtc->client_pending_transform.transform,
650 sizeof(PictTransform)) != 0;
651}
652
653/*
654 * Destroy a Crtc at shutdown
655 */
656void
657RRCrtcDestroy(RRCrtcPtr crtc)
658{
659 FreeResource(crtc->id, 0);
660}
661
662static int
663RRCrtcDestroyResource(void *value, XID pid)
664{
665 RRCrtcPtr crtc = (RRCrtcPtr) value;
666 ScreenPtr pScreen = crtc->pScreen;
667
668 if (pScreen) {
1
Assuming 'pScreen' is null
2
Taking false branch
669 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
670 int i;
671
672 for (i = 0; i < pScrPriv->numCrtcs; i++) {
673 if (pScrPriv->crtcs[i] == crtc) {
674 memmove(pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,__builtin___memmove_chk (pScrPriv->crtcs + i, pScrPriv->
crtcs + i + 1, (pScrPriv->numCrtcs - (i + 1)) * sizeof(RRCrtcPtr
), __builtin_object_size (pScrPriv->crtcs + i, 0))
675 (pScrPriv->numCrtcs - (i + 1)) * sizeof(RRCrtcPtr))__builtin___memmove_chk (pScrPriv->crtcs + i, pScrPriv->
crtcs + i + 1, (pScrPriv->numCrtcs - (i + 1)) * sizeof(RRCrtcPtr
), __builtin_object_size (pScrPriv->crtcs + i, 0))
;
676 --pScrPriv->numCrtcs;
677 break;
678 }
679 }
680
681 RRResourcesChanged(pScreen);
682 }
683
684 if (crtc->scanout_pixmap)
3
Taking true branch
685 RRCrtcDetachScanoutPixmap(crtc);
4
Calling 'RRCrtcDetachScanoutPixmap'
686 free(crtc->gammaRed);
687 if (crtc->mode)
688 RRModeDestroy(crtc->mode);
689 free(crtc);
690 return 1;
691}
692
693/*
694 * Request that the Crtc gamma be changed
695 */
696
697Bool
698RRCrtcGammaSet(RRCrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue)
699{
700 Bool ret = TRUE1;
701
702#if RANDR_12_INTERFACE1
703 ScreenPtr pScreen = crtc->pScreen;
704#endif
705
706 memcpy(crtc->gammaRed, red, crtc->gammaSize * sizeof(CARD16))__builtin___memcpy_chk (crtc->gammaRed, red, crtc->gammaSize
* sizeof(CARD16), __builtin_object_size (crtc->gammaRed, 0
))
;
707 memcpy(crtc->gammaGreen, green, crtc->gammaSize * sizeof(CARD16))__builtin___memcpy_chk (crtc->gammaGreen, green, crtc->
gammaSize * sizeof(CARD16), __builtin_object_size (crtc->gammaGreen
, 0))
;
708 memcpy(crtc->gammaBlue, blue, crtc->gammaSize * sizeof(CARD16))__builtin___memcpy_chk (crtc->gammaBlue, blue, crtc->gammaSize
* sizeof(CARD16), __builtin_object_size (crtc->gammaBlue,
0))
;
709#if RANDR_12_INTERFACE1
710 if (pScreen) {
711 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
712 if (pScrPriv->rrCrtcSetGamma)
713 ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
714 }
715#endif
716 return ret;
717}
718
719/*
720 * Request current gamma back from the DDX (if possible).
721 * This includes gamma size.
722 */
723Bool
724RRCrtcGammaGet(RRCrtcPtr crtc)
725{
726 Bool ret = TRUE1;
727
728#if RANDR_12_INTERFACE1
729 ScreenPtr pScreen = crtc->pScreen;
730#endif
731
732#if RANDR_12_INTERFACE1
733 if (pScreen) {
734 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
735 if (pScrPriv->rrCrtcGetGamma)
736 ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc);
737 }
738#endif
739 return ret;
740}
741
742/*
743 * Notify the extension that the Crtc gamma has been changed
744 * The driver calls this whenever it has changed the gamma values
745 * in the RRCrtcRec
746 */
747
748Bool
749RRCrtcGammaNotify(RRCrtcPtr crtc)
750{
751 return TRUE1; /* not much going on here */
752}
753
754static void
755RRModeGetScanoutSize(RRModePtr mode, PictTransformPtr transform,
756 int *width, int *height)
757{
758 BoxRec box;
759
760 if (mode == NULL((void*)0)) {
761 *width = 0;
762 *height = 0;
763 return;
764 }
765
766 box.x1 = 0;
767 box.y1 = 0;
768 box.x2 = mode->mode.width;
769 box.y2 = mode->mode.height;
770
771 pixman_transform_bounds(transform, &box);
772 *width = box.x2 - box.x1;
773 *height = box.y2 - box.y1;
774}
775
776/**
777 * Returns the width/height that the crtc scans out from the framebuffer
778 */
779void
780RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
781{
782 RRModeGetScanoutSize(crtc->mode, &crtc->transform, width, height);
783}
784
785/*
786 * Set the size of the gamma table at server startup time
787 */
788
789Bool
790RRCrtcGammaSetSize(RRCrtcPtr crtc, int size)
791{
792 CARD16 *gamma;
793
794 if (size == crtc->gammaSize)
795 return TRUE1;
796 if (size) {
797 gamma = malloc(size * 3 * sizeof(CARD16));
798 if (!gamma)
799 return FALSE0;
800 }
801 else
802 gamma = NULL((void*)0);
803 free(crtc->gammaRed);
804 crtc->gammaRed = gamma;
805 crtc->gammaGreen = gamma + size;
806 crtc->gammaBlue = gamma + size * 2;
807 crtc->gammaSize = size;
808 return TRUE1;
809}
810
811/*
812 * Set the pending CRTC transformation
813 */
814
815int
816RRCrtcTransformSet(RRCrtcPtr crtc,
817 PictTransformPtr transform,
818 struct pixman_f_transform *f_transform,
819 struct pixman_f_transform *f_inverse,
820 char *filter_name,
821 int filter_len, xFixed * params, int nparams)
822{
823 PictFilterPtr filter = NULL((void*)0);
824 int width = 0, height = 0;
825
826 if (!crtc->transforms)
827 return BadValue2;
828
829 if (filter_len) {
830 filter = PictureFindFilter(crtc->pScreen, filter_name, filter_len);
831 if (!filter)
832 return BadName15;
833 if (filter->ValidateParams) {
834 if (!filter->ValidateParams(crtc->pScreen, filter->id,
835 params, nparams, &width, &height))
836 return BadMatch8;
837 }
838 else {
839 width = filter->width;
840 height = filter->height;
841 }
842 }
843 else {
844 if (nparams)
845 return BadMatch8;
846 }
847 if (!RRTransformSetFilter(&crtc->client_pending_transform,
848 filter, params, nparams, width, height))
849 return BadAlloc11;
850
851 crtc->client_pending_transform.transform = *transform;
852 crtc->client_pending_transform.f_transform = *f_transform;
853 crtc->client_pending_transform.f_inverse = *f_inverse;
854 return Success0;
855}
856
857/*
858 * Initialize crtc type
859 */
860Bool
861RRCrtcInit(void)
862{
863 RRCrtcType = CreateNewResourceType(RRCrtcDestroyResource, "CRTC");
864 if (!RRCrtcType)
865 return FALSE0;
866
867 return TRUE1;
868}
869
870/*
871 * Initialize crtc type error value
872 */
873void
874RRCrtcInitErrorValue(void)
875{
876 SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc1);
877}
878
879int
880ProcRRGetCrtcInfo(ClientPtr client)
881{
882 REQUEST(xRRGetCrtcInfoReq)xRRGetCrtcInfoReq *stuff = (xRRGetCrtcInfoReq *)client->requestBuffer;
883 xRRGetCrtcInfoReply rep;
884 RRCrtcPtr crtc;
885 CARD8 *extra;
886 unsigned long extraLen;
887 ScreenPtr pScreen;
888 rrScrPrivPtr pScrPriv;
889 RRModePtr mode;
890 RROutput *outputs;
891 RROutput *possible;
892 int i, j, k;
893 int width, height;
894 BoxRec panned_area;
895
896 REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq)if ((sizeof(xRRGetCrtcInfoReq) >> 2) != client->req_len
) return(16)
;
897 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
898
899 /* All crtcs must be associated with screens before client
900 * requests are processed
901 */
902 pScreen = crtc->pScreen;
903 pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&rrPrivKeyRec)))
;
904
905 mode = crtc->mode;
906
907 rep = (xRRGetCrtcInfoReply) {
908 .type = X_Reply1,
909 .status = RRSetConfigSuccess0,
910 .sequenceNumber = client->sequence,
911 .length = 0,
912 .timestamp = pScrPriv->lastSetTime.milliseconds
913 };
914 if (pScrPriv->rrGetPanning &&
915 pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL((void*)0), NULL((void*)0)) &&
916 (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
917 {
918 rep.x = panned_area.x1;
919 rep.y = panned_area.y1;
920 rep.width = panned_area.x2 - panned_area.x1;
921 rep.height = panned_area.y2 - panned_area.y1;
922 }
923 else {
924 RRCrtcGetScanoutSize(crtc, &width, &height);
925 rep.x = crtc->x;
926 rep.y = crtc->y;
927 rep.width = width;
928 rep.height = height;
929 }
930 rep.mode = mode ? mode->mode.id : 0;
931 rep.rotation = crtc->rotation;
932 rep.rotations = crtc->rotations;
933 rep.nOutput = crtc->numOutputs;
934 k = 0;
935 for (i = 0; i < pScrPriv->numOutputs; i++)
936 for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
937 if (pScrPriv->outputs[i]->crtcs[j] == crtc)
938 k++;
939 rep.nPossibleOutput = k;
940
941 rep.length = rep.nOutput + rep.nPossibleOutput;
942
943 extraLen = rep.length << 2;
944 if (extraLen) {
945 extra = malloc(extraLen);
946 if (!extra)
947 return BadAlloc11;
948 }
949 else
950 extra = NULL((void*)0);
951
952 outputs = (RROutput *) extra;
953 possible = (RROutput *) (outputs + rep.nOutput);
954
955 for (i = 0; i < crtc->numOutputs; i++) {
956 outputs[i] = crtc->outputs[i]->id;
957 if (client->swapped)
958 swapl(&outputs[i])do { if (sizeof(*(&outputs[i])) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&outputs[i]) & 3) && ((uintptr_t
)(&outputs[i]) & 3) == 0) *(&outputs[i]) = lswapl
(*(&outputs[i])); else swap_uint32((uint32_t *)(&outputs
[i])); } while (0)
;
959 }
960 k = 0;
961 for (i = 0; i < pScrPriv->numOutputs; i++)
962 for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
963 if (pScrPriv->outputs[i]->crtcs[j] == crtc) {
964 possible[k] = pScrPriv->outputs[i]->id;
965 if (client->swapped)
966 swapl(&possible[k])do { if (sizeof(*(&possible[k])) != 4) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&possible[k]) & 3) &&
((uintptr_t)(&possible[k]) & 3) == 0) *(&possible
[k]) = lswapl(*(&possible[k])); else swap_uint32((uint32_t
*)(&possible[k])); } while (0)
;
967 k++;
968 }
969
970 if (client->swapped) {
971 swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber
) & 1) && ((uintptr_t)(&rep.sequenceNumber) &
1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber
)); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); }
while (0)
;
972 swapl(&rep.length)do { if (sizeof(*(&rep.length)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.length) & 3) && ((uintptr_t
)(&rep.length) & 3) == 0) *(&rep.length) = lswapl
(*(&rep.length)); else swap_uint32((uint32_t *)(&rep.
length)); } while (0)
;
973 swapl(&rep.timestamp)do { if (sizeof(*(&rep.timestamp)) != 4) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.timestamp) & 3
) && ((uintptr_t)(&rep.timestamp) & 3) == 0) *
(&rep.timestamp) = lswapl(*(&rep.timestamp)); else swap_uint32
((uint32_t *)(&rep.timestamp)); } while (0)
;
974 swaps(&rep.x)do { if (sizeof(*(&rep.x)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.x) & 1) && ((uintptr_t)(&
rep.x) & 1) == 0) *(&rep.x) = lswaps(*(&rep.x)); else
swap_uint16((uint16_t *)(&rep.x)); } while (0)
;
975 swaps(&rep.y)do { if (sizeof(*(&rep.y)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.y) & 1) && ((uintptr_t)(&
rep.y) & 1) == 0) *(&rep.y) = lswaps(*(&rep.y)); else
swap_uint16((uint16_t *)(&rep.y)); } while (0)
;
976 swaps(&rep.width)do { if (sizeof(*(&rep.width)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.width) & 1) && ((uintptr_t)
(&rep.width) & 1) == 0) *(&rep.width) = lswaps(*(
&rep.width)); else swap_uint16((uint16_t *)(&rep.width
)); } while (0)
;
977 swaps(&rep.height)do { if (sizeof(*(&rep.height)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.height) & 1) && ((uintptr_t
)(&rep.height) & 1) == 0) *(&rep.height) = lswaps
(*(&rep.height)); else swap_uint16((uint16_t *)(&rep.
height)); } while (0)
;
978 swapl(&rep.mode)do { if (sizeof(*(&rep.mode)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.mode) & 3) && ((uintptr_t)(
&rep.mode) & 3) == 0) *(&rep.mode) = lswapl(*(&
rep.mode)); else swap_uint32((uint32_t *)(&rep.mode)); } while
(0)
;
979 swaps(&rep.rotation)do { if (sizeof(*(&rep.rotation)) != 2) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&rep.rotation) & 1) &&
((uintptr_t)(&rep.rotation) & 1) == 0) *(&rep.rotation
) = lswaps(*(&rep.rotation)); else swap_uint16((uint16_t *
)(&rep.rotation)); } while (0)
;
980 swaps(&rep.rotations)do { if (sizeof(*(&rep.rotations)) != 2) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.rotations) & 1
) && ((uintptr_t)(&rep.rotations) & 1) == 0) *
(&rep.rotations) = lswaps(*(&rep.rotations)); else swap_uint16
((uint16_t *)(&rep.rotations)); } while (0)
;
981 swaps(&rep.nOutput)do { if (sizeof(*(&rep.nOutput)) != 2) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&rep.nOutput) & 1) &&
((uintptr_t)(&rep.nOutput) & 1) == 0) *(&rep.nOutput
) = lswaps(*(&rep.nOutput)); else swap_uint16((uint16_t *
)(&rep.nOutput)); } while (0)
;
982 swaps(&rep.nPossibleOutput)do { if (sizeof(*(&rep.nPossibleOutput)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&rep.nPossibleOutput
) & 1) && ((uintptr_t)(&rep.nPossibleOutput) &
1) == 0) *(&rep.nPossibleOutput) = lswaps(*(&rep.nPossibleOutput
)); else swap_uint16((uint16_t *)(&rep.nPossibleOutput));
} while (0)
;
983 }
984 WriteToClient(client, sizeof(xRRGetCrtcInfoReply), &rep);
985 if (extraLen) {
986 WriteToClient(client, extraLen, extra);
987 free(extra);
988 }
989
990 return Success0;
991}
992
993int
994ProcRRSetCrtcConfig(ClientPtr client)
995{
996 REQUEST(xRRSetCrtcConfigReq)xRRSetCrtcConfigReq *stuff = (xRRSetCrtcConfigReq *)client->
requestBuffer
;
997 xRRSetCrtcConfigReply rep;
998 ScreenPtr pScreen;
999 rrScrPrivPtr pScrPriv;
1000 RRCrtcPtr crtc;
1001 RRModePtr mode;
1002 int numOutputs;
1003 RROutputPtr *outputs = NULL((void*)0);
1004 RROutput *outputIds;
1005 TimeStamp time;
1006 Rotation rotation;
1007 int ret, i, j;
1008 CARD8 status;
1009
1010 REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq)if ((sizeof(xRRSetCrtcConfigReq) >> 2) > client->
req_len ) return(16)
;
1011 numOutputs = (stuff->length - bytes_to_int32(SIZEOF(xRRSetCrtcConfigReq)28));
1012
1013 VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<5)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1014
1015 if (stuff->mode == None0L) {
1016 mode = NULL((void*)0);
1017 if (numOutputs > 0)
1018 return BadMatch8;
1019 }
1020 else {
1021 VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess){ int rc = dixLookupResourceByType((void **)&(mode), stuff
->mode, RRModeType, client, (1<<5)); if (rc != 0) { client
->errorValue = stuff->mode; return rc; } }
;
1022 if (numOutputs == 0)
1023 return BadMatch8;
1024 }
1025 if (numOutputs) {
1026 outputs = malloc(numOutputs * sizeof(RROutputPtr));
1027 if (!outputs)
1028 return BadAlloc11;
1029 }
1030 else
1031 outputs = NULL((void*)0);
1032
1033 outputIds = (RROutput *) (stuff + 1);
1034 for (i = 0; i < numOutputs; i++) {
1035 ret = dixLookupResourceByType((void **) (outputs + i), outputIds[i],
1036 RROutputType, client, DixSetAttrAccess(1<<5));
1037 if (ret != Success0) {
1038 free(outputs);
1039 return ret;
1040 }
1041 /* validate crtc for this output */
1042 for (j = 0; j < outputs[i]->numCrtcs; j++)
1043 if (outputs[i]->crtcs[j] == crtc)
1044 break;
1045 if (j == outputs[i]->numCrtcs) {
1046 free(outputs);
1047 return BadMatch8;
1048 }
1049 /* validate mode for this output */
1050 for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) {
1051 RRModePtr m = (j < outputs[i]->numModes ?
1052 outputs[i]->modes[j] :
1053 outputs[i]->userModes[j - outputs[i]->numModes]);
1054 if (m == mode)
1055 break;
1056 }
1057 if (j == outputs[i]->numModes + outputs[i]->numUserModes) {
1058 free(outputs);
1059 return BadMatch8;
1060 }
1061 }
1062 /* validate clones */
1063 for (i = 0; i < numOutputs; i++) {
1064 for (j = 0; j < numOutputs; j++) {
1065 int k;
1066
1067 if (i == j)
1068 continue;
1069 for (k = 0; k < outputs[i]->numClones; k++) {
1070 if (outputs[i]->clones[k] == outputs[j])
1071 break;
1072 }
1073 if (k == outputs[i]->numClones) {
1074 free(outputs);
1075 return BadMatch8;
1076 }
1077 }
1078 }
1079
1080 pScreen = crtc->pScreen;
1081 pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&rrPrivKeyRec)))
;
1082
1083 time = ClientTimeToServerTime(stuff->timestamp);
1084
1085 if (!pScrPriv) {
1086 time = currentTime;
1087 status = RRSetConfigFailed3;
1088 goto sendReply;
1089 }
1090
1091 /*
1092 * Validate requested rotation
1093 */
1094 rotation = (Rotation) stuff->rotation;
1095
1096 /* test the rotation bits only! */
1097 switch (rotation & 0xf) {
1098 case RR_Rotate_01:
1099 case RR_Rotate_902:
1100 case RR_Rotate_1804:
1101 case RR_Rotate_2708:
1102 break;
1103 default:
1104 /*
1105 * Invalid rotation
1106 */
1107 client->errorValue = stuff->rotation;
1108 free(outputs);
1109 return BadValue2;
1110 }
1111
1112 if (mode) {
1113 if ((~crtc->rotations) & rotation) {
1114 /*
1115 * requested rotation or reflection not supported by screen
1116 */
1117 client->errorValue = stuff->rotation;
1118 free(outputs);
1119 return BadMatch8;
1120 }
1121
1122#ifdef RANDR_12_INTERFACE1
1123 /*
1124 * Check screen size bounds if the DDX provides a 1.2 interface
1125 * for setting screen size. Else, assume the CrtcSet sets
1126 * the size along with the mode. If the driver supports transforms,
1127 * then it must allow crtcs to display a subset of the screen, so
1128 * only do this check for drivers without transform support.
1129 */
1130 if (pScrPriv->rrScreenSetSize && !crtc->transforms) {
1131 int source_width;
1132 int source_height;
1133 PictTransform transform;
1134 struct pixman_f_transform f_transform, f_inverse;
1135 int width, height;
1136
1137 if (pScreen->isGPU) {
1138 width = pScreen->current_master->width;
1139 height = pScreen->current_master->height;
1140 }
1141 else {
1142 width = pScreen->width;
1143 height = pScreen->height;
1144 }
1145
1146 RRTransformCompute(stuff->x, stuff->y,
1147 mode->mode.width, mode->mode.height,
1148 rotation,
1149 &crtc->client_pending_transform,
1150 &transform, &f_transform, &f_inverse);
1151
1152 RRModeGetScanoutSize(mode, &transform, &source_width,
1153 &source_height);
1154 if (stuff->x + source_width > width) {
1155 client->errorValue = stuff->x;
1156 free(outputs);
1157 return BadValue2;
1158 }
1159
1160 if (stuff->y + source_height > height) {
1161 client->errorValue = stuff->y;
1162 free(outputs);
1163 return BadValue2;
1164 }
1165 }
1166#endif
1167 }
1168
1169 if (!RRCrtcSet(crtc, mode, stuff->x, stuff->y,
1170 rotation, numOutputs, outputs)) {
1171 status = RRSetConfigFailed3;
1172 goto sendReply;
1173 }
1174 status = RRSetConfigSuccess0;
1175 pScrPriv->lastSetTime = time;
1176
1177 sendReply:
1178 free(outputs);
1179
1180 rep = (xRRSetCrtcConfigReply) {
1181 .type = X_Reply1,
1182 .status = status,
1183 .sequenceNumber = client->sequence,
1184 .length = 0,
1185 .newTimestamp = pScrPriv->lastSetTime.milliseconds
1186 };
1187
1188 if (client->swapped) {
1189 swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber
) & 1) && ((uintptr_t)(&rep.sequenceNumber) &
1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber
)); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); }
while (0)
;
1190 swapl(&rep.length)do { if (sizeof(*(&rep.length)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.length) & 3) && ((uintptr_t
)(&rep.length) & 3) == 0) *(&rep.length) = lswapl
(*(&rep.length)); else swap_uint32((uint32_t *)(&rep.
length)); } while (0)
;
1191 swapl(&rep.newTimestamp)do { if (sizeof(*(&rep.newTimestamp)) != 4) wrong_size();
if (__builtin_constant_p((uintptr_t)(&rep.newTimestamp) &
3) && ((uintptr_t)(&rep.newTimestamp) & 3) ==
0) *(&rep.newTimestamp) = lswapl(*(&rep.newTimestamp
)); else swap_uint32((uint32_t *)(&rep.newTimestamp)); } while
(0)
;
1192 }
1193 WriteToClient(client, sizeof(xRRSetCrtcConfigReply), &rep);
1194
1195 return Success0;
1196}
1197
1198int
1199ProcRRGetPanning(ClientPtr client)
1200{
1201 REQUEST(xRRGetPanningReq)xRRGetPanningReq *stuff = (xRRGetPanningReq *)client->requestBuffer;
1202 xRRGetPanningReply rep;
1203 RRCrtcPtr crtc;
1204 ScreenPtr pScreen;
1205 rrScrPrivPtr pScrPriv;
1206 BoxRec total;
1207 BoxRec tracking;
1208 INT16 border[4];
1209
1210 REQUEST_SIZE_MATCH(xRRGetPanningReq)if ((sizeof(xRRGetPanningReq) >> 2) != client->req_len
) return(16)
;
1211 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1212
1213 /* All crtcs must be associated with screens before client
1214 * requests are processed
1215 */
1216 pScreen = crtc->pScreen;
1217 pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&rrPrivKeyRec)))
;
1218
1219 if (!pScrPriv)
1220 return RRErrorBase + BadRRCrtc1;
1221
1222 rep = (xRRGetPanningReply) {
1223 .type = X_Reply1,
1224 .status = RRSetConfigSuccess0,
1225 .sequenceNumber = client->sequence,
1226 .length = 1,
1227 .timestamp = pScrPriv->lastSetTime.milliseconds
1228 };
1229
1230 if (pScrPriv->rrGetPanning &&
1231 pScrPriv->rrGetPanning(pScreen, crtc, &total, &tracking, border)) {
1232 rep.left = total.x1;
1233 rep.top = total.y1;
1234 rep.width = total.x2 - total.x1;
1235 rep.height = total.y2 - total.y1;
1236 rep.track_left = tracking.x1;
1237 rep.track_top = tracking.y1;
1238 rep.track_width = tracking.x2 - tracking.x1;
1239 rep.track_height = tracking.y2 - tracking.y1;
1240 rep.border_left = border[0];
1241 rep.border_top = border[1];
1242 rep.border_right = border[2];
1243 rep.border_bottom = border[3];
1244 }
1245
1246 if (client->swapped) {
1247 swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber
) & 1) && ((uintptr_t)(&rep.sequenceNumber) &
1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber
)); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); }
while (0)
;
1248 swapl(&rep.length)do { if (sizeof(*(&rep.length)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.length) & 3) && ((uintptr_t
)(&rep.length) & 3) == 0) *(&rep.length) = lswapl
(*(&rep.length)); else swap_uint32((uint32_t *)(&rep.
length)); } while (0)
;
1249 swapl(&rep.timestamp)do { if (sizeof(*(&rep.timestamp)) != 4) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.timestamp) & 3
) && ((uintptr_t)(&rep.timestamp) & 3) == 0) *
(&rep.timestamp) = lswapl(*(&rep.timestamp)); else swap_uint32
((uint32_t *)(&rep.timestamp)); } while (0)
;
1250 swaps(&rep.left)do { if (sizeof(*(&rep.left)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.left) & 1) && ((uintptr_t)(
&rep.left) & 1) == 0) *(&rep.left) = lswaps(*(&
rep.left)); else swap_uint16((uint16_t *)(&rep.left)); } while
(0)
;
1251 swaps(&rep.top)do { if (sizeof(*(&rep.top)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.top) & 1) && ((uintptr_t)(&
rep.top) & 1) == 0) *(&rep.top) = lswaps(*(&rep.top
)); else swap_uint16((uint16_t *)(&rep.top)); } while (0)
;
1252 swaps(&rep.width)do { if (sizeof(*(&rep.width)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.width) & 1) && ((uintptr_t)
(&rep.width) & 1) == 0) *(&rep.width) = lswaps(*(
&rep.width)); else swap_uint16((uint16_t *)(&rep.width
)); } while (0)
;
1253 swaps(&rep.height)do { if (sizeof(*(&rep.height)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.height) & 1) && ((uintptr_t
)(&rep.height) & 1) == 0) *(&rep.height) = lswaps
(*(&rep.height)); else swap_uint16((uint16_t *)(&rep.
height)); } while (0)
;
1254 swaps(&rep.track_left)do { if (sizeof(*(&rep.track_left)) != 2) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.track_left) &
1) && ((uintptr_t)(&rep.track_left) & 1) == 0
) *(&rep.track_left) = lswaps(*(&rep.track_left)); else
swap_uint16((uint16_t *)(&rep.track_left)); } while (0)
;
1255 swaps(&rep.track_top)do { if (sizeof(*(&rep.track_top)) != 2) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.track_top) & 1
) && ((uintptr_t)(&rep.track_top) & 1) == 0) *
(&rep.track_top) = lswaps(*(&rep.track_top)); else swap_uint16
((uint16_t *)(&rep.track_top)); } while (0)
;
1256 swaps(&rep.track_width)do { if (sizeof(*(&rep.track_width)) != 2) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.track_width) &
1) && ((uintptr_t)(&rep.track_width) & 1) ==
0) *(&rep.track_width) = lswaps(*(&rep.track_width))
; else swap_uint16((uint16_t *)(&rep.track_width)); } while
(0)
;
1257 swaps(&rep.track_height)do { if (sizeof(*(&rep.track_height)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&rep.track_height) &
1) && ((uintptr_t)(&rep.track_height) & 1) ==
0) *(&rep.track_height) = lswaps(*(&rep.track_height
)); else swap_uint16((uint16_t *)(&rep.track_height)); } while
(0)
;
1258 swaps(&rep.border_left)do { if (sizeof(*(&rep.border_left)) != 2) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.border_left) &
1) && ((uintptr_t)(&rep.border_left) & 1) ==
0) *(&rep.border_left) = lswaps(*(&rep.border_left))
; else swap_uint16((uint16_t *)(&rep.border_left)); } while
(0)
;
1259 swaps(&rep.border_top)do { if (sizeof(*(&rep.border_top)) != 2) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&rep.border_top) &
1) && ((uintptr_t)(&rep.border_top) & 1) == 0
) *(&rep.border_top) = lswaps(*(&rep.border_top)); else
swap_uint16((uint16_t *)(&rep.border_top)); } while (0)
;
1260 swaps(&rep.border_right)do { if (sizeof(*(&rep.border_right)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&rep.border_right) &
1) && ((uintptr_t)(&rep.border_right) & 1) ==
0) *(&rep.border_right) = lswaps(*(&rep.border_right
)); else swap_uint16((uint16_t *)(&rep.border_right)); } while
(0)
;
1261 swaps(&rep.border_bottom)do { if (sizeof(*(&rep.border_bottom)) != 2) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&rep.border_bottom
) & 1) && ((uintptr_t)(&rep.border_bottom) &
1) == 0) *(&rep.border_bottom) = lswaps(*(&rep.border_bottom
)); else swap_uint16((uint16_t *)(&rep.border_bottom)); }
while (0)
;
1262 }
1263 WriteToClient(client, sizeof(xRRGetPanningReply), &rep);
1264 return Success0;
1265}
1266
1267int
1268ProcRRSetPanning(ClientPtr client)
1269{
1270 REQUEST(xRRSetPanningReq)xRRSetPanningReq *stuff = (xRRSetPanningReq *)client->requestBuffer;
1271 xRRSetPanningReply rep;
1272 RRCrtcPtr crtc;
1273 ScreenPtr pScreen;
1274 rrScrPrivPtr pScrPriv;
1275 TimeStamp time;
1276 BoxRec total;
1277 BoxRec tracking;
1278 INT16 border[4];
1279 CARD8 status;
1280
1281 REQUEST_SIZE_MATCH(xRRSetPanningReq)if ((sizeof(xRRSetPanningReq) >> 2) != client->req_len
) return(16)
;
1282 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1283
1284 /* All crtcs must be associated with screens before client
1285 * requests are processed
1286 */
1287 pScreen = crtc->pScreen;
1288 pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&rrPrivKeyRec)))
;
1289
1290 if (!pScrPriv) {
1291 time = currentTime;
1292 status = RRSetConfigFailed3;
1293 goto sendReply;
1294 }
1295
1296 time = ClientTimeToServerTime(stuff->timestamp);
1297
1298 if (!pScrPriv->rrGetPanning)
1299 return RRErrorBase + BadRRCrtc1;
1300
1301 total.x1 = stuff->left;
1302 total.y1 = stuff->top;
1303 total.x2 = total.x1 + stuff->width;
1304 total.y2 = total.y1 + stuff->height;
1305 tracking.x1 = stuff->track_left;
1306 tracking.y1 = stuff->track_top;
1307 tracking.x2 = tracking.x1 + stuff->track_width;
1308 tracking.y2 = tracking.y1 + stuff->track_height;
1309 border[0] = stuff->border_left;
1310 border[1] = stuff->border_top;
1311 border[2] = stuff->border_right;
1312 border[3] = stuff->border_bottom;
1313
1314 if (!pScrPriv->rrSetPanning(pScreen, crtc, &total, &tracking, border))
1315 return BadMatch8;
1316
1317 pScrPriv->lastSetTime = time;
1318
1319 status = RRSetConfigSuccess0;
1320
1321 sendReply:
1322 rep = (xRRSetPanningReply) {
1323 .type = X_Reply1,
1324 .status = status,
1325 .sequenceNumber = client->sequence,
1326 .length = 0,
1327 .newTimestamp = pScrPriv->lastSetTime.milliseconds
1328 };
1329
1330 if (client->swapped) {
1331 swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber
) & 1) && ((uintptr_t)(&rep.sequenceNumber) &
1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber
)); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); }
while (0)
;
1332 swapl(&rep.length)do { if (sizeof(*(&rep.length)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.length) & 3) && ((uintptr_t
)(&rep.length) & 3) == 0) *(&rep.length) = lswapl
(*(&rep.length)); else swap_uint32((uint32_t *)(&rep.
length)); } while (0)
;
1333 swapl(&rep.newTimestamp)do { if (sizeof(*(&rep.newTimestamp)) != 4) wrong_size();
if (__builtin_constant_p((uintptr_t)(&rep.newTimestamp) &
3) && ((uintptr_t)(&rep.newTimestamp) & 3) ==
0) *(&rep.newTimestamp) = lswapl(*(&rep.newTimestamp
)); else swap_uint32((uint32_t *)(&rep.newTimestamp)); } while
(0)
;
1334 }
1335 WriteToClient(client, sizeof(xRRSetPanningReply), &rep);
1336 return Success0;
1337}
1338
1339int
1340ProcRRGetCrtcGammaSize(ClientPtr client)
1341{
1342 REQUEST(xRRGetCrtcGammaSizeReq)xRRGetCrtcGammaSizeReq *stuff = (xRRGetCrtcGammaSizeReq *)client
->requestBuffer
;
1343 xRRGetCrtcGammaSizeReply reply;
1344 RRCrtcPtr crtc;
1345
1346 REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq)if ((sizeof(xRRGetCrtcGammaSizeReq) >> 2) != client->
req_len) return(16)
;
1347 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1348
1349 /* Gamma retrieval failed, any better error? */
1350 if (!RRCrtcGammaGet(crtc))
1351 return RRErrorBase + BadRRCrtc1;
1352
1353 reply = (xRRGetCrtcGammaSizeReply) {
1354 .type = X_Reply1,
1355 .sequenceNumber = client->sequence,
1356 .length = 0,
1357 .size = crtc->gammaSize
1358 };
1359 if (client->swapped) {
1360 swaps(&reply.sequenceNumber)do { if (sizeof(*(&reply.sequenceNumber)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&reply.sequenceNumber
) & 1) && ((uintptr_t)(&reply.sequenceNumber)
& 1) == 0) *(&reply.sequenceNumber) = lswaps(*(&
reply.sequenceNumber)); else swap_uint16((uint16_t *)(&reply
.sequenceNumber)); } while (0)
;
1361 swapl(&reply.length)do { if (sizeof(*(&reply.length)) != 4) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&reply.length) & 3) &&
((uintptr_t)(&reply.length) & 3) == 0) *(&reply.
length) = lswapl(*(&reply.length)); else swap_uint32((uint32_t
*)(&reply.length)); } while (0)
;
1362 swaps(&reply.size)do { if (sizeof(*(&reply.size)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&reply.size) & 1) && ((uintptr_t
)(&reply.size) & 1) == 0) *(&reply.size) = lswaps
(*(&reply.size)); else swap_uint16((uint16_t *)(&reply
.size)); } while (0)
;
1363 }
1364 WriteToClient(client, sizeof(xRRGetCrtcGammaSizeReply), &reply);
1365 return Success0;
1366}
1367
1368int
1369ProcRRGetCrtcGamma(ClientPtr client)
1370{
1371 REQUEST(xRRGetCrtcGammaReq)xRRGetCrtcGammaReq *stuff = (xRRGetCrtcGammaReq *)client->
requestBuffer
;
1372 xRRGetCrtcGammaReply reply;
1373 RRCrtcPtr crtc;
1374 unsigned long len;
1375 char *extra = NULL((void*)0);
1376
1377 REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq)if ((sizeof(xRRGetCrtcGammaReq) >> 2) != client->req_len
) return(16)
;
1378 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1379
1380 /* Gamma retrieval failed, any better error? */
1381 if (!RRCrtcGammaGet(crtc))
1382 return RRErrorBase + BadRRCrtc1;
1383
1384 len = crtc->gammaSize * 3 * 2;
1385
1386 if (crtc->gammaSize) {
1387 extra = malloc(len);
1388 if (!extra)
1389 return BadAlloc11;
1390 }
1391
1392 reply = (xRRGetCrtcGammaReply) {
1393 .type = X_Reply1,
1394 .sequenceNumber = client->sequence,
1395 .length = bytes_to_int32(len),
1396 .size = crtc->gammaSize
1397 };
1398 if (client->swapped) {
1399 swaps(&reply.sequenceNumber)do { if (sizeof(*(&reply.sequenceNumber)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&reply.sequenceNumber
) & 1) && ((uintptr_t)(&reply.sequenceNumber)
& 1) == 0) *(&reply.sequenceNumber) = lswaps(*(&
reply.sequenceNumber)); else swap_uint16((uint16_t *)(&reply
.sequenceNumber)); } while (0)
;
1400 swapl(&reply.length)do { if (sizeof(*(&reply.length)) != 4) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&reply.length) & 3) &&
((uintptr_t)(&reply.length) & 3) == 0) *(&reply.
length) = lswapl(*(&reply.length)); else swap_uint32((uint32_t
*)(&reply.length)); } while (0)
;
1401 swaps(&reply.size)do { if (sizeof(*(&reply.size)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&reply.size) & 1) && ((uintptr_t
)(&reply.size) & 1) == 0) *(&reply.size) = lswaps
(*(&reply.size)); else swap_uint16((uint16_t *)(&reply
.size)); } while (0)
;
1402 }
1403 WriteToClient(client, sizeof(xRRGetCrtcGammaReply), &reply);
1404 if (crtc->gammaSize) {
1405 memcpy(extra, crtc->gammaRed, len)__builtin___memcpy_chk (extra, crtc->gammaRed, len, __builtin_object_size
(extra, 0))
;
1406 client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
1407 WriteSwappedDataToClient(client, len, extra)if ((client)->swapped) (*(client)->pSwapReplyFunc)(client
, (int)(len), extra); else WriteToClient(client, (int)(len), (
extra));
;
1408 free(extra);
1409 }
1410 return Success0;
1411}
1412
1413int
1414ProcRRSetCrtcGamma(ClientPtr client)
1415{
1416 REQUEST(xRRSetCrtcGammaReq)xRRSetCrtcGammaReq *stuff = (xRRSetCrtcGammaReq *)client->
requestBuffer
;
1417 RRCrtcPtr crtc;
1418 unsigned long len;
1419 CARD16 *red, *green, *blue;
1420
1421 REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq)if ((sizeof(xRRSetCrtcGammaReq) >> 2) > client->req_len
) return(16)
;
1422 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1423
1424 len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcGammaReq));
1425 if (len < (stuff->size * 3 + 1) >> 1)
1426 return BadLength16;
1427
1428 if (stuff->size != crtc->gammaSize)
1429 return BadMatch8;
1430
1431 red = (CARD16 *) (stuff + 1);
1432 green = red + crtc->gammaSize;
1433 blue = green + crtc->gammaSize;
1434
1435 RRCrtcGammaSet(crtc, red, green, blue);
1436
1437 return Success0;
1438}
1439
1440/* Version 1.3 additions */
1441
1442int
1443ProcRRSetCrtcTransform(ClientPtr client)
1444{
1445 REQUEST(xRRSetCrtcTransformReq)xRRSetCrtcTransformReq *stuff = (xRRSetCrtcTransformReq *)client
->requestBuffer
;
1446 RRCrtcPtr crtc;
1447 PictTransform transform;
1448 struct pixman_f_transform f_transform, f_inverse;
1449 char *filter;
1450 int nbytes;
1451 xFixed *params;
1452 int nparams;
1453
1454 REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq)if ((sizeof(xRRSetCrtcTransformReq) >> 2) > client->
req_len ) return(16)
;
1455 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1456
1457 PictTransform_from_xRenderTransform(&transform, &stuff->transform);
1458 pixman_f_transform_from_pixman_transform(&f_transform, &transform);
1459 if (!pixman_f_transform_invert(&f_inverse, &f_transform))
1460 return BadMatch8;
1461
1462 filter = (char *) (stuff + 1);
1463 nbytes = stuff->nbytesFilter;
1464 params = (xFixed *) (filter + pad_to_int32(nbytes));
1465 nparams = ((xFixed *) stuff + client->req_len) - params;
1466 if (nparams < 0)
1467 return BadLength16;
1468
1469 return RRCrtcTransformSet(crtc, &transform, &f_transform, &f_inverse,
1470 filter, nbytes, params, nparams);
1471}
1472
1473#define CrtcTransformExtra(96 - 32) (SIZEOF(xRRGetCrtcTransformReply)96 - 32)
1474
1475static int
1476transform_filter_length(RRTransformPtr transform)
1477{
1478 int nbytes, nparams;
1479
1480 if (transform->filter == NULL((void*)0))
1481 return 0;
1482 nbytes = strlen(transform->filter->name);
1483 nparams = transform->nparams;
1484 return pad_to_int32(nbytes) + (nparams * sizeof(xFixed));
1485}
1486
1487static int
1488transform_filter_encode(ClientPtr client, char *output,
1489 CARD16 *nbytesFilter,
1490 CARD16 *nparamsFilter, RRTransformPtr transform)
1491{
1492 int nbytes, nparams;
1493
1494 if (transform->filter == NULL((void*)0)) {
1495 *nbytesFilter = 0;
1496 *nparamsFilter = 0;
1497 return 0;
1498 }
1499 nbytes = strlen(transform->filter->name);
1500 nparams = transform->nparams;
1501 *nbytesFilter = nbytes;
1502 *nparamsFilter = nparams;
1503 memcpy(output, transform->filter->name, nbytes)__builtin___memcpy_chk (output, transform->filter->name
, nbytes, __builtin_object_size (output, 0))
;
1504 while ((nbytes & 3) != 0)
1505 output[nbytes++] = 0;
1506 memcpy(output + nbytes, transform->params, nparams * sizeof(xFixed))__builtin___memcpy_chk (output + nbytes, transform->params
, nparams * sizeof(xFixed), __builtin_object_size (output + nbytes
, 0))
;
1507 if (client->swapped) {
1508 swaps(nbytesFilter)do { if (sizeof(*(nbytesFilter)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(nbytesFilter) & 1) && ((uintptr_t)(nbytesFilter
) & 1) == 0) *(nbytesFilter) = lswaps(*(nbytesFilter)); else
swap_uint16((uint16_t *)(nbytesFilter)); } while (0)
;
1509 swaps(nparamsFilter)do { if (sizeof(*(nparamsFilter)) != 2) wrong_size(); if (__builtin_constant_p
((uintptr_t)(nparamsFilter) & 1) && ((uintptr_t)(
nparamsFilter) & 1) == 0) *(nparamsFilter) = lswaps(*(nparamsFilter
)); else swap_uint16((uint16_t *)(nparamsFilter)); } while (0
)
;
1510 SwapLongs((CARD32 *) (output + nbytes), nparams);
1511 }
1512 nbytes += nparams * sizeof(xFixed);
1513 return nbytes;
1514}
1515
1516static void
1517transform_encode(ClientPtr client, xRenderTransform * wire,
1518 PictTransform * pict)
1519{
1520 xRenderTransform_from_PictTransform(wire, pict);
1521 if (client->swapped)
1522 SwapLongs((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform)));
1523}
1524
1525int
1526ProcRRGetCrtcTransform(ClientPtr client)
1527{
1528 REQUEST(xRRGetCrtcTransformReq)xRRGetCrtcTransformReq *stuff = (xRRGetCrtcTransformReq *)client
->requestBuffer
;
1529 xRRGetCrtcTransformReply *reply;
1530 RRCrtcPtr crtc;
1531 int nextra;
1532 RRTransformPtr current, pending;
1533 char *extra;
1534
1535 REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq)if ((sizeof(xRRGetCrtcTransformReq) >> 2) != client->
req_len) return(16)
;
1536 VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(crtc), stuff
->crtc, RRCrtcType, client, (1<<0)); if (rc != 0) { client
->errorValue = stuff->crtc; return rc; } }
;
1537
1538 pending = &crtc->client_pending_transform;
1539 current = &crtc->client_current_transform;
1540
1541 nextra = (transform_filter_length(pending) +
1542 transform_filter_length(current));
1543
1544 reply = calloc(1, sizeof(xRRGetCrtcTransformReply) + nextra);
1545 if (!reply)
1546 return BadAlloc11;
1547
1548 extra = (char *) (reply + 1);
1549 reply->type = X_Reply1;
1550 reply->sequenceNumber = client->sequence;
1551 reply->length = bytes_to_int32(CrtcTransformExtra(96 - 32) + nextra);
1552
1553 reply->hasTransforms = crtc->transforms;
1554
1555 transform_encode(client, &reply->pendingTransform, &pending->transform);
1556 extra += transform_filter_encode(client, extra,
1557 &reply->pendingNbytesFilter,
1558 &reply->pendingNparamsFilter, pending);
1559
1560 transform_encode(client, &reply->currentTransform, &current->transform);
1561 extra += transform_filter_encode(client, extra,
1562 &reply->currentNbytesFilter,
1563 &reply->currentNparamsFilter, current);
1564
1565 if (client->swapped) {
1566 swaps(&reply->sequenceNumber)do { if (sizeof(*(&reply->sequenceNumber)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&reply->sequenceNumber
) & 1) && ((uintptr_t)(&reply->sequenceNumber
) & 1) == 0) *(&reply->sequenceNumber) = lswaps(*(
&reply->sequenceNumber)); else swap_uint16((uint16_t *
)(&reply->sequenceNumber)); } while (0)
;
1567 swapl(&reply->length)do { if (sizeof(*(&reply->length)) != 4) wrong_size();
if (__builtin_constant_p((uintptr_t)(&reply->length) &
3) && ((uintptr_t)(&reply->length) & 3) ==
0) *(&reply->length) = lswapl(*(&reply->length
)); else swap_uint32((uint32_t *)(&reply->length)); } while
(0)
;
1568 }
1569 WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra, reply);
1570 free(reply);
1571 return Success0;
1572}
1573
1574static Bool check_all_screen_crtcs(ScreenPtr pScreen, int *x, int *y)
1575{
1576 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
1577 int i;
1578 for (i = 0; i < pScrPriv->numCrtcs; i++) {
1579 RRCrtcPtr crtc = pScrPriv->crtcs[i];
1580
1581 int left, right, top, bottom;
1582
1583 if (!crtc->mode)
1584 continue;
1585
1586 crtc_bounds(crtc, &left, &right, &top, &bottom);
1587
1588 if ((*x >= left) && (*x < right) && (*y >= top) && (*y < bottom))
1589 return TRUE1;
1590 }
1591 return FALSE0;
1592}
1593
1594static Bool constrain_all_screen_crtcs(DeviceIntPtr pDev, ScreenPtr pScreen, int *x, int *y)
1595{
1596 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
1597 int i;
1598
1599 /* if we're trying to escape, clamp to the CRTC we're coming from */
1600 for (i = 0; i < pScrPriv->numCrtcs; i++) {
1601 RRCrtcPtr crtc = pScrPriv->crtcs[i];
1602 int nx, ny;
1603 int left, right, top, bottom;
1604
1605 if (!crtc->mode)
1606 continue;
1607
1608 crtc_bounds(crtc, &left, &right, &top, &bottom);
1609 miPointerGetPosition(pDev, &nx, &ny);
1610
1611 if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom)) {
1612 if (*x < left)
1613 *x = left;
1614 if (*x >= right)
1615 *x = right - 1;
1616 if (*y < top)
1617 *y = top;
1618 if (*y >= bottom)
1619 *y = bottom - 1;
1620
1621 return TRUE1;
1622 }
1623 }
1624 return FALSE0;
1625}
1626
1627void
1628RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
1629 int *y)
1630{
1631 rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pScreen)->devPrivates, (&rrPrivKeyRec)))
;
1632 Bool ret;
1633 ScreenPtr slave;
1634
1635 /* intentional dead space -> let it float */
1636 if (pScrPriv->discontiguous)
1637 return;
1638
1639 /* if we're moving inside a crtc, we're fine */
1640 ret = check_all_screen_crtcs(pScreen, x, y);
1641 if (ret == TRUE1)
1642 return;
1643
1644 xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head)for (slave = (typeof(*slave) *)((char *)((&pScreen->output_slave_list
)->next) - __builtin_offsetof(typeof(*slave), output_head)
); &slave->output_head != (&pScreen->output_slave_list
); slave = (typeof(*slave) *)((char *)(slave->output_head.
next) - __builtin_offsetof(typeof(*slave), output_head)))
{
1645 ret = check_all_screen_crtcs(slave, x, y);
1646 if (ret == TRUE1)
1647 return;
1648 }
1649
1650 /* if we're trying to escape, clamp to the CRTC we're coming from */
1651 ret = constrain_all_screen_crtcs(pDev, pScreen, x, y);
1652 if (ret == TRUE1)
1653 return;
1654
1655 xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head)for (slave = (typeof(*slave) *)((char *)((&pScreen->output_slave_list
)->next) - __builtin_offsetof(typeof(*slave), output_head)
); &slave->output_head != (&pScreen->output_slave_list
); slave = (typeof(*slave) *)((char *)(slave->output_head.
next) - __builtin_offsetof(typeof(*slave), output_head)))
{
1656 ret = constrain_all_screen_crtcs(pDev, slave, x, y);
1657 if (ret == TRUE1)
1658 return;
1659 }
1660}
1661
1662Bool
1663RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
1664{
1665 rrScrPriv(pDrawable->pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(&
(pDrawable->pScreen)->devPrivates, (&rrPrivKeyRec))
)
;
1666 Bool ret = TRUE1;
1667 PixmapPtr *saved_scanout_pixmap;
1668 int i;
1669
1670 saved_scanout_pixmap = malloc(sizeof(PixmapPtr)*pScrPriv->numCrtcs);
1671 if (saved_scanout_pixmap == NULL((void*)0))
1672 return FALSE0;
1673
1674 for (i = 0; i < pScrPriv->numCrtcs; i++) {
1675 RRCrtcPtr crtc = pScrPriv->crtcs[i];
1676 Bool size_fits;
1677
1678 saved_scanout_pixmap[i] = crtc->scanout_pixmap;
1679
1680 if (!crtc->mode && enable)
1681 continue;
1682 if (!crtc->scanout_pixmap && !enable)
1683 continue;
1684
1685 size_fits = (crtc->mode &&
1686 crtc->x == pDrawable->x &&
1687 crtc->y == pDrawable->y &&
1688 crtc->mode->mode.width == pDrawable->width &&
1689 crtc->mode->mode.height == pDrawable->height);
1690
1691 /* is the pixmap already set? */
1692 if (crtc->scanout_pixmap == pPixmap) {
1693 /* if its a disable then don't care about size */
1694 if (enable == FALSE0) {
1695 /* set scanout to NULL */
1696 crtc->scanout_pixmap = NULL((void*)0);
1697 }
1698 else if (!size_fits) {
1699 /* if the size no longer fits then drop off */
1700 crtc->scanout_pixmap = NULL((void*)0);
1701 pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
1702
1703 (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
1704 crtc->rotation, crtc->numOutputs, crtc->outputs);
1705 saved_scanout_pixmap[i] = crtc->scanout_pixmap;
1706 ret = FALSE0;
1707 }
1708 else {
1709 /* if the size fits then we are already setup */
1710 }
1711 }
1712 else {
1713 if (!size_fits)
1714 ret = FALSE0;
1715 else if (enable)
1716 crtc->scanout_pixmap = pPixmap;
1717 else
1718 /* reject an attempt to disable someone else's scanout_pixmap */
1719 ret = FALSE0;
1720 }
1721 }
1722
1723 for (i = 0; i < pScrPriv->numCrtcs; i++) {
1724 RRCrtcPtr crtc = pScrPriv->crtcs[i];
1725
1726 if (crtc->scanout_pixmap == saved_scanout_pixmap[i])
1727 continue;
1728
1729 if (ret) {
1730 pScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
1731
1732 (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
1733 crtc->rotation, crtc->numOutputs, crtc->outputs);
1734 }
1735 else
1736 crtc->scanout_pixmap = saved_scanout_pixmap[i];
1737 }
1738 free(saved_scanout_pixmap);
1739
1740 return ret;
1741}