Bug Summary

File:hw/xfree86/modes/xf86Crtc.c
Location:line 2366, column 9
Description:Value stored to 'output' is never read

Annotated Source Code

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 */
23
24#ifdef HAVE_XORG_CONFIG_H1
25#include <xorg-config.h>
26#else
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30#endif
31
32#include <stddef.h>
33#include <string.h>
34#include <stdio.h>
35
36#include "xf86.h"
37#include "xf86DDC.h"
38#include "xf86Crtc.h"
39#include "xf86Modes.h"
40#include "xf86Priv.h"
41#include "xf86RandR12.h"
42#include "X11/extensions/render.h"
43#include "X11/extensions/dpmsconst.h"
44#include "X11/Xatom.h"
45#include "picturestr.h"
46
47#ifdef XV1
48#include "xf86xv.h"
49#endif
50
51#define NO_OUTPUT_DEFAULT_WIDTH1024 1024
52#define NO_OUTPUT_DEFAULT_HEIGHT768 768
53/*
54 * Initialize xf86CrtcConfig structure
55 */
56
57int xf86CrtcConfigPrivateIndex = -1;
58
59void
60xf86CrtcConfigInit(ScrnInfoPtr scrn, const xf86CrtcConfigFuncsRec * funcs)
61{
62 xf86CrtcConfigPtr config;
63
64 if (xf86CrtcConfigPrivateIndex == -1)
65 xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
66 config = xnfcalloc(1, sizeof(xf86CrtcConfigRec))XNFcallocarray((1), (sizeof(xf86CrtcConfigRec)));
67
68 config->funcs = funcs;
69 config->compat_output = -1;
70
71 scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
72}
73
74void
75xf86CrtcSetSizeRange(ScrnInfoPtr scrn,
76 int minWidth, int minHeight, int maxWidth, int maxHeight)
77{
78 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
79
80 config->minWidth = minWidth;
81 config->minHeight = minHeight;
82 config->maxWidth = maxWidth;
83 config->maxHeight = maxHeight;
84}
85
86/*
87 * Crtc functions
88 */
89xf86CrtcPtr
90xf86CrtcCreate(ScrnInfoPtr scrn, const xf86CrtcFuncsRec * funcs)
91{
92 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
93 xf86CrtcPtr crtc, *crtcs;
94
95 crtc = calloc(sizeof(xf86CrtcRec), 1);
96 if (!crtc)
97 return NULL((void*)0);
98 crtc->version = XF86_CRTC_VERSION6;
99 crtc->scrn = scrn;
100 crtc->funcs = funcs;
101#ifdef RANDR_12_INTERFACE1
102 crtc->randr_crtc = NULL((void*)0);
103#endif
104 crtc->rotation = RR_Rotate_01;
105 crtc->desiredRotation = RR_Rotate_01;
106 pixman_transform_init_identity(&crtc->crtc_to_framebuffer);
107 pixman_f_transform_init_identity(&crtc->f_crtc_to_framebuffer);
108 pixman_f_transform_init_identity(&crtc->f_framebuffer_to_crtc);
109 crtc->filter = NULL((void*)0);
110 crtc->params = NULL((void*)0);
111 crtc->nparams = 0;
112 crtc->filter_width = 0;
113 crtc->filter_height = 0;
114 crtc->transform_in_use = FALSE0;
115 crtc->transformPresent = FALSE0;
116 crtc->desiredTransformPresent = FALSE0;
117 memset(&crtc->bounds, '\0', sizeof(crtc->bounds))__builtin___memset_chk (&crtc->bounds, '\0', sizeof(crtc
->bounds), __builtin_object_size (&crtc->bounds, 0)
)
;
118
119 /* Preallocate gamma at a sensible size. */
120 crtc->gamma_size = 256;
121 crtc->gamma_red = xallocarray(crtc->gamma_size, 3 * sizeof(CARD16))xreallocarray(((void*)0), (crtc->gamma_size), (3 * sizeof(
CARD16)))
;
122 if (!crtc->gamma_red) {
123 free(crtc);
124 return NULL((void*)0);
125 }
126 crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
127 crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
128
129 if (xf86_config->crtc)
130 crtcs = reallocarrayxreallocarray(xf86_config->crtc,
131 xf86_config->num_crtc + 1, sizeof(xf86CrtcPtr));
132 else
133 crtcs = xallocarray(xf86_config->num_crtc + 1, sizeof(xf86CrtcPtr))xreallocarray(((void*)0), (xf86_config->num_crtc + 1), (sizeof
(xf86CrtcPtr)))
;
134 if (!crtcs) {
135 free(crtc->gamma_red);
136 free(crtc);
137 return NULL((void*)0);
138 }
139 xf86_config->crtc = crtcs;
140 xf86_config->crtc[xf86_config->num_crtc++] = crtc;
141 return crtc;
142}
143
144void
145xf86CrtcDestroy(xf86CrtcPtr crtc)
146{
147 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn)((xf86CrtcConfigPtr) ((crtc->scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
148 int c;
149
150 (*crtc->funcs->destroy) (crtc);
151 for (c = 0; c < xf86_config->num_crtc; c++)
152 if (xf86_config->crtc[c] == crtc) {
153 memmove(&xf86_config->crtc[c],__builtin___memmove_chk (&xf86_config->crtc[c], &xf86_config
->crtc[c + 1], ((xf86_config->num_crtc - (c + 1)) * sizeof
(void *)), __builtin_object_size (&xf86_config->crtc[c
], 0))
154 &xf86_config->crtc[c + 1],__builtin___memmove_chk (&xf86_config->crtc[c], &xf86_config
->crtc[c + 1], ((xf86_config->num_crtc - (c + 1)) * sizeof
(void *)), __builtin_object_size (&xf86_config->crtc[c
], 0))
155 ((xf86_config->num_crtc - (c + 1)) * sizeof(void *)))__builtin___memmove_chk (&xf86_config->crtc[c], &xf86_config
->crtc[c + 1], ((xf86_config->num_crtc - (c + 1)) * sizeof
(void *)), __builtin_object_size (&xf86_config->crtc[c
], 0))
;
156 xf86_config->num_crtc--;
157 break;
158 }
159 free(crtc->params);
160 free(crtc->gamma_red);
161 free(crtc);
162}
163
164/**
165 * Return whether any outputs are connected to the specified pipe
166 */
167
168Bool
169xf86CrtcInUse(xf86CrtcPtr crtc)
170{
171 ScrnInfoPtr pScrn = crtc->scrn;
172 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
173 int o;
174
175 for (o = 0; o < xf86_config->num_output; o++)
176 if (xf86_config->output[o]->crtc == crtc)
177 return TRUE1;
178 return FALSE0;
179}
180
181void
182xf86CrtcSetScreenSubpixelOrder(ScreenPtr pScreen)
183{
184 int subpixel_order = SubPixelUnknown0;
185 Bool has_none = FALSE0;
186 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
187 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
188 int icrtc, o;
189
190 for (icrtc = 0; icrtc < xf86_config->num_crtc; icrtc++) {
191 xf86CrtcPtr crtc = xf86_config->crtc[icrtc];
192
193 for (o = 0; o < xf86_config->num_output; o++) {
194 xf86OutputPtr output = xf86_config->output[o];
195
196 if (output->crtc == crtc) {
197 switch (output->subpixel_order) {
198 case SubPixelNone5:
199 has_none = TRUE1;
200 break;
201 case SubPixelUnknown0:
202 break;
203 default:
204 subpixel_order = output->subpixel_order;
205 break;
206 }
207 }
208 if (subpixel_order != SubPixelUnknown0)
209 break;
210 }
211 if (subpixel_order != SubPixelUnknown0) {
212 static const int circle[4] = {
213 SubPixelHorizontalRGB1,
214 SubPixelVerticalRGB3,
215 SubPixelHorizontalBGR2,
216 SubPixelVerticalBGR4,
217 };
218 int rotate;
219 int sc;
220
221 for (rotate = 0; rotate < 4; rotate++)
222 if (crtc->rotation & (1 << rotate))
223 break;
224 for (sc = 0; sc < 4; sc++)
225 if (circle[sc] == subpixel_order)
226 break;
227 sc = (sc + rotate) & 0x3;
228 if ((crtc->rotation & RR_Reflect_X16) && !(sc & 1))
229 sc ^= 2;
230 if ((crtc->rotation & RR_Reflect_Y32) && (sc & 1))
231 sc ^= 2;
232 subpixel_order = circle[sc];
233 break;
234 }
235 }
236 if (subpixel_order == SubPixelUnknown0 && has_none)
237 subpixel_order = SubPixelNone5;
238 PictureSetSubpixelOrder(pScreen, subpixel_order);
239}
240
241/**
242 * Sets the given video mode on the given crtc
243 */
244Bool
245xf86CrtcSetModeTransform(xf86CrtcPtr crtc, DisplayModePtr mode,
246 Rotation rotation, RRTransformPtr transform, int x,
247 int y)
248{
249 ScrnInfoPtr scrn = crtc->scrn;
250 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
251 int i;
252 Bool ret = FALSE0;
253 Bool didLock = FALSE0;
254 DisplayModePtr adjusted_mode;
255 DisplayModeRec saved_mode;
256 int saved_x, saved_y;
257 Rotation saved_rotation;
258 RRTransformRec saved_transform;
259 Bool saved_transform_present;
260
261 crtc->enabled = xf86CrtcInUse(crtc);
262
263 /* We only hit this if someone explicitly sends a "disabled" modeset. */
264 if (!crtc->enabled) {
265 /* Check everything for stuff that should be off. */
266 xf86DisableUnusedFunctions(scrn);
267 return TRUE1;
268 }
269
270 adjusted_mode = xf86DuplicateMode(mode);
271
272 saved_mode = crtc->mode;
273 saved_x = crtc->x;
274 saved_y = crtc->y;
275 saved_rotation = crtc->rotation;
276 if (crtc->transformPresent) {
277 RRTransformInit(&saved_transform);
278 RRTransformCopy(&saved_transform, &crtc->transform);
279 }
280 saved_transform_present = crtc->transformPresent;
281
282 /* Update crtc values up front so the driver can rely on them for mode
283 * setting.
284 */
285 crtc->mode = *mode;
286 crtc->x = x;
287 crtc->y = y;
288 crtc->rotation = rotation;
289 if (transform) {
290 RRTransformCopy(&crtc->transform, transform);
291 crtc->transformPresent = TRUE1;
292 }
293 else
294 crtc->transformPresent = FALSE0;
295
296 if (crtc->funcs->set_mode_major) {
297 ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
298 goto done;
299 }
300
301 didLock = crtc->funcs->lock(crtc);
302 /* Pass our mode to the outputs and the CRTC to give them a chance to
303 * adjust it according to limitations or output properties, and also
304 * a chance to reject the mode entirely.
305 */
306 for (i = 0; i < xf86_config->num_output; i++) {
307 xf86OutputPtr output = xf86_config->output[i];
308
309 if (output->crtc != crtc)
310 continue;
311
312 if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
313 goto done;
314 }
315 }
316
317 if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
318 goto done;
319 }
320
321 if (!xf86CrtcRotate(crtc))
322 goto done;
323
324 /* Prepare the outputs and CRTCs before setting the mode. */
325 for (i = 0; i < xf86_config->num_output; i++) {
326 xf86OutputPtr output = xf86_config->output[i];
327
328 if (output->crtc != crtc)
329 continue;
330
331 /* Disable the output as the first thing we do. */
332 output->funcs->prepare(output);
333 }
334
335 crtc->funcs->prepare(crtc);
336
337 /* Set up the DPLL and any output state that needs to adjust or depend
338 * on the DPLL.
339 */
340 crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y);
341 for (i = 0; i < xf86_config->num_output; i++) {
342 xf86OutputPtr output = xf86_config->output[i];
343
344 if (output->crtc == crtc)
345 output->funcs->mode_set(output, mode, adjusted_mode);
346 }
347
348 /* Only upload when needed, to avoid unneeded delays. */
349 if (!crtc->active && crtc->funcs->gamma_set)
350 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
351 crtc->gamma_blue, crtc->gamma_size);
352
353 /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
354 crtc->funcs->commit(crtc);
355 for (i = 0; i < xf86_config->num_output; i++) {
356 xf86OutputPtr output = xf86_config->output[i];
357
358 if (output->crtc == crtc)
359 output->funcs->commit(output);
360 }
361
362 ret = TRUE1;
363
364 done:
365 if (ret) {
366 crtc->active = TRUE1;
367 if (scrn->pScreen)
368 xf86CrtcSetScreenSubpixelOrder(scrn->pScreen);
369 if (scrn->ModeSet)
370 scrn->ModeSet(scrn);
371
372 /* Make sure the HW cursor is hidden if it's supposed to be, in case
373 * it was hidden while the CRTC was disabled
374 */
375 if (!xf86_config->cursor_on)
376 xf86_hide_cursors(scrn);
377 }
378 else {
379 crtc->x = saved_x;
380 crtc->y = saved_y;
381 crtc->rotation = saved_rotation;
382 crtc->mode = saved_mode;
383 if (saved_transform_present)
384 RRTransformCopy(&crtc->transform, &saved_transform);
385 crtc->transformPresent = saved_transform_present;
386 }
387
388 free((void *) adjusted_mode->name);
389 free(adjusted_mode);
390
391 if (didLock)
392 crtc->funcs->unlock(crtc);
393
394 return ret;
395}
396
397/**
398 * Sets the given video mode on the given crtc, but without providing
399 * a transform
400 */
401Bool
402xf86CrtcSetMode(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
403 int x, int y)
404{
405 return xf86CrtcSetModeTransform(crtc, mode, rotation, NULL((void*)0), x, y);
406}
407
408/**
409 * Pans the screen, does not change the mode
410 */
411void
412xf86CrtcSetOrigin(xf86CrtcPtr crtc, int x, int y)
413{
414 ScrnInfoPtr scrn = crtc->scrn;
415
416 crtc->x = x;
417 crtc->y = y;
418 if (crtc->funcs->set_origin) {
419 if (!xf86CrtcRotate(crtc))
420 return;
421 crtc->funcs->set_origin(crtc, x, y);
422 if (scrn->ModeSet)
423 scrn->ModeSet(scrn);
424 }
425 else
426 xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, x, y);
427}
428
429/*
430 * Output functions
431 */
432
433extern XF86ConfigPtr xf86configptr;
434
435typedef enum {
436 OPTION_PREFERRED_MODE,
437 OPTION_ZOOM_MODES,
438 OPTION_POSITION,
439 OPTION_BELOW,
440 OPTION_RIGHT_OF,
441 OPTION_ABOVE,
442 OPTION_LEFT_OF,
443 OPTION_ENABLE,
444 OPTION_DISABLE,
445 OPTION_MIN_CLOCK,
446 OPTION_MAX_CLOCK,
447 OPTION_IGNORE,
448 OPTION_ROTATE,
449 OPTION_PANNING,
450 OPTION_PRIMARY,
451 OPTION_DEFAULT_MODES,
452} OutputOpts;
453
454static OptionInfoRec xf86OutputOptions[] = {
455 {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE0},
456 {OPTION_ZOOM_MODES, "ZoomModes", OPTV_STRING, {0}, FALSE0 },
457 {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE0},
458 {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE0},
459 {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE0},
460 {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE0},
461 {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE0},
462 {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE0},
463 {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE0},
464 {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE0},
465 {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE0},
466 {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE0},
467 {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE0},
468 {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE0},
469 {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE0},
470 {OPTION_DEFAULT_MODES, "DefaultModes", OPTV_BOOLEAN, {0}, FALSE0},
471 {-1, NULL((void*)0), OPTV_NONE, {0}, FALSE0},
472};
473
474enum {
475 OPTION_MODEDEBUG,
476};
477
478static OptionInfoRec xf86DeviceOptions[] = {
479 {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE0},
480 {-1, NULL((void*)0), OPTV_NONE, {0}, FALSE0},
481};
482
483static void
484xf86OutputSetMonitor(xf86OutputPtr output)
485{
486 char *option_name;
487 const char *monitor;
488
489 if (!output->name)
490 return;
491
492 free(output->options);
493
494 output->options = xnfalloc(sizeof(xf86OutputOptions))XNFalloc((unsigned long)(sizeof(xf86OutputOptions)));
495 memcpy(output->options, xf86OutputOptions, sizeof(xf86OutputOptions))__builtin___memcpy_chk (output->options, xf86OutputOptions
, sizeof(xf86OutputOptions), __builtin_object_size (output->
options, 0))
;
496
497 XNFasprintf(&option_name, "monitor-%s", output->name);
498 monitor = xf86findOptionValue(output->scrn->options, option_name);
499 if (!monitor)
500 monitor = output->name;
501 else
502 xf86MarkOptionUsedByName(output->scrn->options, option_name);
503 free(option_name);
504 output->conf_monitor = xf86findMonitor(monitor,
505 xf86configptr->conf_monitor_lst);
506 /*
507 * Find the monitor section of the screen and use that
508 */
509 if (!output->conf_monitor && output->use_screen_monitor)
510 output->conf_monitor = xf86findMonitor(output->scrn->monitor->id,
511 xf86configptr->conf_monitor_lst);
512 if (output->conf_monitor) {
513 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
514 "Output %s using monitor section %s\n",
515 output->name, output->conf_monitor->mon_identifier);
516 xf86ProcessOptions(output->scrn->scrnIndex,
517 output->conf_monitor->mon_option_lst,
518 output->options);
519 }
520 else
521 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
522 "Output %s has no monitor section\n", output->name);
523}
524
525static Bool
526xf86OutputEnabled(xf86OutputPtr output, Bool strict)
527{
528 Bool enable, disable;
529
530 /* check to see if this output was enabled in the config file */
531 if (xf86GetOptValBool(output->options, OPTION_ENABLE, &enable) && enable) {
532 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
533 "Output %s enabled by config file\n", output->name);
534 return TRUE1;
535 }
536 /* or if this output was disabled in the config file */
537 if (xf86GetOptValBool(output->options, OPTION_DISABLE, &disable) && disable) {
538 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
539 "Output %s disabled by config file\n", output->name);
540 return FALSE0;
541 }
542
543 /* If not, try to only light up the ones we know are connected */
544 if (strict) {
545 enable = output->status == XF86OutputStatusConnected;
546 }
547 /* But if that fails, try to light up even outputs we're unsure of */
548 else {
549 enable = output->status != XF86OutputStatusDisconnected;
550 }
551
552 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
553 "Output %s %sconnected\n", output->name, enable ? "" : "dis");
554 return enable;
555}
556
557static Bool
558xf86OutputIgnored(xf86OutputPtr output)
559{
560 return xf86ReturnOptValBool(output->options, OPTION_IGNORE, FALSE0);
561}
562
563static const char *direction[4] = {
564 "normal",
565 "left",
566 "inverted",
567 "right"
568};
569
570static Rotation
571xf86OutputInitialRotation(xf86OutputPtr output)
572{
573 const char *rotate_name = xf86GetOptValString(output->options,
574 OPTION_ROTATE);
575 int i;
576
577 if (!rotate_name) {
578 if (output->initial_rotation)
579 return output->initial_rotation;
580 return RR_Rotate_01;
581 }
582
583 for (i = 0; i < 4; i++)
584 if (xf86nameCompare(direction[i], rotate_name) == 0)
585 return 1 << i;
586 return RR_Rotate_01;
587}
588
589xf86OutputPtr
590xf86OutputCreate(ScrnInfoPtr scrn,
591 const xf86OutputFuncsRec * funcs, const char *name)
592{
593 xf86OutputPtr output, *outputs;
594 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
595 int len;
596 Bool primary;
597
598 if (name)
599 len = strlen(name) + 1;
600 else
601 len = 0;
602
603 output = calloc(sizeof(xf86OutputRec) + len, 1);
604 if (!output)
605 return NULL((void*)0);
606 output->scrn = scrn;
607 output->funcs = funcs;
608 if (name) {
609 output->name = (char *) (output + 1);
610 strcpy(output->name, name)__builtin___strcpy_chk (output->name, name, __builtin_object_size
(output->name, 2 > 1 ? 1 : 0))
;
611 }
612 output->subpixel_order = SubPixelUnknown0;
613 /*
614 * Use the old per-screen monitor section for the first output
615 */
616 output->use_screen_monitor = (xf86_config->num_output == 0);
617#ifdef RANDR_12_INTERFACE1
618 output->randr_output = NULL((void*)0);
619#endif
620 if (name) {
621 xf86OutputSetMonitor(output);
622 if (xf86OutputIgnored(output)) {
623 free(output);
624 return FALSE0;
625 }
626 }
627
628 if (xf86_config->output)
629 outputs = reallocarrayxreallocarray(xf86_config->output,
630 xf86_config->num_output + 1,
631 sizeof(xf86OutputPtr));
632 else
633 outputs = xallocarray(xf86_config->num_output + 1,xreallocarray(((void*)0), (xf86_config->num_output + 1), (
sizeof(xf86OutputPtr)))
634 sizeof(xf86OutputPtr))xreallocarray(((void*)0), (xf86_config->num_output + 1), (
sizeof(xf86OutputPtr)))
;
635 if (!outputs) {
636 free(output);
637 return NULL((void*)0);
638 }
639
640 xf86_config->output = outputs;
641
642 if (xf86GetOptValBool(output->options, OPTION_PRIMARY, &primary) && primary) {
643 memmove(xf86_config->output + 1, xf86_config->output,__builtin___memmove_chk (xf86_config->output + 1, xf86_config
->output, xf86_config->num_output * sizeof(xf86OutputPtr
), __builtin_object_size (xf86_config->output + 1, 0))
644 xf86_config->num_output * sizeof(xf86OutputPtr))__builtin___memmove_chk (xf86_config->output + 1, xf86_config
->output, xf86_config->num_output * sizeof(xf86OutputPtr
), __builtin_object_size (xf86_config->output + 1, 0))
;
645 xf86_config->output[0] = output;
646 }
647 else {
648 xf86_config->output[xf86_config->num_output] = output;
649 }
650
651 xf86_config->num_output++;
652
653 return output;
654}
655
656Bool
657xf86OutputRename(xf86OutputPtr output, const char *name)
658{
659 char *newname = strdup(name);
660
661 if (!newname)
662 return FALSE0; /* so sorry... */
663
664 if (output->name && output->name != (char *) (output + 1))
665 free(output->name);
666 output->name = newname;
667 xf86OutputSetMonitor(output);
668 if (xf86OutputIgnored(output))
669 return FALSE0;
670 return TRUE1;
671}
672
673void
674xf86OutputUseScreenMonitor(xf86OutputPtr output, Bool use_screen_monitor)
675{
676 if (use_screen_monitor != output->use_screen_monitor) {
677 output->use_screen_monitor = use_screen_monitor;
678 xf86OutputSetMonitor(output);
679 }
680}
681
682void
683xf86OutputDestroy(xf86OutputPtr output)
684{
685 ScrnInfoPtr scrn = output->scrn;
686 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
687 int o;
688
689 (*output->funcs->destroy) (output);
690 while (output->probed_modes)
691 xf86DeleteMode(&output->probed_modes, output->probed_modes);
692 for (o = 0; o < xf86_config->num_output; o++)
693 if (xf86_config->output[o] == output) {
694 memmove(&xf86_config->output[o],__builtin___memmove_chk (&xf86_config->output[o], &
xf86_config->output[o + 1], ((xf86_config->num_output -
(o + 1)) * sizeof(void *)), __builtin_object_size (&xf86_config
->output[o], 0))
695 &xf86_config->output[o + 1],__builtin___memmove_chk (&xf86_config->output[o], &
xf86_config->output[o + 1], ((xf86_config->num_output -
(o + 1)) * sizeof(void *)), __builtin_object_size (&xf86_config
->output[o], 0))
696 ((xf86_config->num_output - (o + 1)) * sizeof(void *)))__builtin___memmove_chk (&xf86_config->output[o], &
xf86_config->output[o + 1], ((xf86_config->num_output -
(o + 1)) * sizeof(void *)), __builtin_object_size (&xf86_config
->output[o], 0))
;
697 xf86_config->num_output--;
698 break;
699 }
700 if (output->name && output->name != (char *) (output + 1))
701 free(output->name);
702 free(output);
703}
704
705/*
706 * Called during CreateScreenResources to hook up RandR
707 */
708static Bool
709xf86CrtcCreateScreenResources(ScreenPtr screen)
710{
711 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
712 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
713
714 screen->CreateScreenResources = config->CreateScreenResources;
715
716 if (!(*screen->CreateScreenResources) (screen))
717 return FALSE0;
718
719 if (!xf86RandR12CreateScreenResources(screen))
720 return FALSE0;
721
722 return TRUE1;
723}
724
725/*
726 * Clean up config on server reset
727 */
728static Bool
729xf86CrtcCloseScreen(ScreenPtr screen)
730{
731 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
732 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
733 int o, c;
734
735 screen->CloseScreen = config->CloseScreen;
736
737 xf86RotateCloseScreen(screen);
738
739 xf86RandR12CloseScreen(screen);
740
741 screen->CloseScreen(screen);
742
743 for (o = 0; o < config->num_output; o++) {
744 xf86OutputPtr output = config->output[o];
745
746 output->randr_output = NULL((void*)0);
747 }
748 for (c = 0; c < config->num_crtc; c++) {
749 xf86CrtcPtr crtc = config->crtc[c];
750
751 crtc->randr_crtc = NULL((void*)0);
752 }
753 /* detach any providers */
754 if (config->randr_provider) {
755 RRProviderDestroy(config->randr_provider);
756 config->randr_provider = NULL((void*)0);
757 }
758 return TRUE1;
759}
760
761/*
762 * Called at ScreenInit time to set up
763 */
764#ifdef RANDR_13_INTERFACE1
765int
766#else
767Bool
768#endif
769xf86CrtcScreenInit(ScreenPtr screen)
770{
771 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
772 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
773 int c;
774
775 /* Rotation */
776 xf86DrvMsg(scrn->scrnIndex, X_INFO,
777 "RandR 1.2 enabled, ignore the following RandR disabled message.\n");
778 xf86DisableRandR(); /* Disable old RandR extension support */
779 xf86RandR12Init(screen);
780
781 /* support all rotations if every crtc has the shadow alloc funcs */
782 for (c = 0; c < config->num_crtc; c++) {
783 xf86CrtcPtr crtc = config->crtc[c];
784
785 if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create)
786 break;
787 }
788 if (c == config->num_crtc) {
789 xf86RandR12SetRotations(screen, RR_Rotate_01 | RR_Rotate_902 |
790 RR_Rotate_1804 | RR_Rotate_2708 |
791 RR_Reflect_X16 | RR_Reflect_Y32);
792 xf86RandR12SetTransformSupport(screen, TRUE1);
793 }
794 else {
795 xf86RandR12SetRotations(screen, RR_Rotate_01);
796 xf86RandR12SetTransformSupport(screen, FALSE0);
797 }
798
799 /* Wrap CreateScreenResources so we can initialize the RandR code */
800 config->CreateScreenResources = screen->CreateScreenResources;
801 screen->CreateScreenResources = xf86CrtcCreateScreenResources;
802
803 config->CloseScreen = screen->CloseScreen;
804 screen->CloseScreen = xf86CrtcCloseScreen;
805
806 /* This might still be marked wrapped from a previous generation */
807 config->BlockHandler = NULL((void*)0);
808
809#ifdef XFreeXDGA1
810 _xf86_di_dga_init_internal(screen);
811#endif
812#ifdef RANDR_13_INTERFACE1
813 return RANDR_INTERFACE_VERSION0x0104;
814#else
815 return TRUE1;
816#endif
817}
818
819static DisplayModePtr
820xf86DefaultMode(xf86OutputPtr output, int width, int height)
821{
822 DisplayModePtr target_mode = NULL((void*)0);
823 DisplayModePtr mode;
824 int target_diff = 0;
825 int target_preferred = 0;
826 int mm_height;
827
828 mm_height = output->mm_height;
829 if (!mm_height)
830 mm_height = (768 * 25.4) / DEFAULT_DPI96;
831 /*
832 * Pick a mode closest to DEFAULT_DPI
833 */
834 for (mode = output->probed_modes; mode; mode = mode->next) {
835 int dpi;
836 int preferred = (((mode->type & M_T_PREFERRED0x08) != 0) +
837 ((mode->type & M_T_USERPREF0x80) != 0));
838 int diff;
839
840 if (xf86ModeWidth(mode, output->initial_rotation) > width ||
841 xf86ModeHeight(mode, output->initial_rotation) > height)
842 continue;
843
844 /* yes, use VDisplay here, not xf86ModeHeight */
845 dpi = (mode->VDisplay * 254) / (mm_height * 10);
846 diff = dpi - DEFAULT_DPI96;
847 diff = diff < 0 ? -diff : diff;
848 if (target_mode == NULL((void*)0) || (preferred > target_preferred) ||
849 (preferred == target_preferred && diff < target_diff)) {
850 target_mode = mode;
851 target_diff = diff;
852 target_preferred = preferred;
853 }
854 }
855 return target_mode;
856}
857
858static DisplayModePtr
859xf86ClosestMode(xf86OutputPtr output,
860 DisplayModePtr match, Rotation match_rotation,
861 int width, int height)
862{
863 DisplayModePtr target_mode = NULL((void*)0);
864 DisplayModePtr mode;
865 int target_diff = 0;
866
867 /*
868 * Pick a mode closest to the specified mode
869 */
870 for (mode = output->probed_modes; mode; mode = mode->next) {
871 int dx, dy;
872 int diff;
873
874 if (xf86ModeWidth(mode, output->initial_rotation) > width ||
875 xf86ModeHeight(mode, output->initial_rotation) > height)
876 continue;
877
878 /* exact matches are preferred */
879 if (output->initial_rotation == match_rotation &&
880 xf86ModesEqual(mode, match))
881 return mode;
882
883 dx = xf86ModeWidth(match, match_rotation) - xf86ModeWidth(mode,
884 output->
885 initial_rotation);
886 dy = xf86ModeHeight(match, match_rotation) - xf86ModeHeight(mode,
887 output->
888 initial_rotation);
889 diff = dx * dx + dy * dy;
890 if (target_mode == NULL((void*)0) || diff < target_diff) {
891 target_mode = mode;
892 target_diff = diff;
893 }
894 }
895 return target_mode;
896}
897
898static DisplayModePtr
899xf86OutputHasPreferredMode(xf86OutputPtr output, int width, int height)
900{
901 DisplayModePtr mode;
902
903 for (mode = output->probed_modes; mode; mode = mode->next) {
904 if (xf86ModeWidth(mode, output->initial_rotation) > width ||
905 xf86ModeHeight(mode, output->initial_rotation) > height)
906 continue;
907
908 if (mode->type & M_T_PREFERRED0x08)
909 return mode;
910 }
911 return NULL((void*)0);
912}
913
914static DisplayModePtr
915xf86OutputHasUserPreferredMode(xf86OutputPtr output)
916{
917 DisplayModePtr mode, first = output->probed_modes;
918
919 for (mode = first; mode && mode->next != first; mode = mode->next)
920 if (mode->type & M_T_USERPREF0x80)
921 return mode;
922
923 return NULL((void*)0);
924}
925
926static int
927xf86PickCrtcs(ScrnInfoPtr scrn,
928 xf86CrtcPtr * best_crtcs,
929 DisplayModePtr * modes, int n, int width, int height)
930{
931 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
932 int c, o;
933 xf86OutputPtr output;
934 xf86CrtcPtr crtc;
935 xf86CrtcPtr *crtcs;
936 int best_score;
937 int score;
938 int my_score;
939
940 if (n == config->num_output)
941 return 0;
942 output = config->output[n];
943
944 /*
945 * Compute score with this output disabled
946 */
947 best_crtcs[n] = NULL((void*)0);
948 best_score = xf86PickCrtcs(scrn, best_crtcs, modes, n + 1, width, height);
949 if (modes[n] == NULL((void*)0))
950 return best_score;
951
952 crtcs = xallocarray(config->num_output, sizeof(xf86CrtcPtr))xreallocarray(((void*)0), (config->num_output), (sizeof(xf86CrtcPtr
)))
;
953 if (!crtcs)
954 return best_score;
955
956 my_score = 1;
957 /* Score outputs that are known to be connected higher */
958 if (output->status == XF86OutputStatusConnected)
959 my_score++;
960 /* Score outputs with preferred modes higher */
961 if (xf86OutputHasPreferredMode(output, width, height))
962 my_score++;
963 /*
964 * Select a crtc for this output and
965 * then attempt to configure the remaining
966 * outputs
967 */
968 for (c = 0; c < config->num_crtc; c++) {
969 if ((output->possible_crtcs & (1 << c)) == 0)
970 continue;
971
972 crtc = config->crtc[c];
973 /*
974 * Check to see if some other output is
975 * using this crtc
976 */
977 for (o = 0; o < n; o++)
978 if (best_crtcs[o] == crtc)
979 break;
980 if (o < n) {
981 /*
982 * If the two outputs desire the same mode,
983 * see if they can be cloned
984 */
985 if (xf86ModesEqual(modes[o], modes[n]) &&
986 config->output[o]->initial_rotation ==
987 config->output[n]->initial_rotation &&
988 config->output[o]->initial_x == config->output[n]->initial_x &&
989 config->output[o]->initial_y == config->output[n]->initial_y) {
990 if ((output->possible_clones & (1 << o)) == 0)
991 continue; /* nope, try next CRTC */
992 }
993 else
994 continue; /* different modes, can't clone */
995 }
996 crtcs[n] = crtc;
997 memcpy(crtcs, best_crtcs, n * sizeof(xf86CrtcPtr))__builtin___memcpy_chk (crtcs, best_crtcs, n * sizeof(xf86CrtcPtr
), __builtin_object_size (crtcs, 0))
;
998 score =
999 my_score + xf86PickCrtcs(scrn, crtcs, modes, n + 1, width, height);
1000 if (score > best_score) {
1001 best_score = score;
1002 memcpy(best_crtcs, crtcs, config->num_output * sizeof(xf86CrtcPtr))__builtin___memcpy_chk (best_crtcs, crtcs, config->num_output
* sizeof(xf86CrtcPtr), __builtin_object_size (best_crtcs, 0)
)
;
1003 }
1004 }
1005 free(crtcs);
1006 return best_score;
1007}
1008
1009/*
1010 * Compute the virtual size necessary to place all of the available
1011 * crtcs in the specified configuration.
1012 *
1013 * canGrow indicates that the driver can make the screen larger than its initial
1014 * configuration. If FALSE, this function will enlarge the screen to include
1015 * the largest available mode.
1016 */
1017
1018static void
1019xf86DefaultScreenLimits(ScrnInfoPtr scrn, int *widthp, int *heightp,
1020 Bool canGrow)
1021{
1022 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
1023 int width = 0, height = 0;
1024 int o;
1025 int c;
1026 int s;
1027
1028 for (c = 0; c < config->num_crtc; c++) {
1029 int crtc_width = 0, crtc_height = 0;
1030 xf86CrtcPtr crtc = config->crtc[c];
1031
1032 if (crtc->enabled) {
1033 crtc_width =
1034 crtc->desiredX + xf86ModeWidth(&crtc->desiredMode,
1035 crtc->desiredRotation);
1036 crtc_height =
1037 crtc->desiredY + xf86ModeHeight(&crtc->desiredMode,
1038 crtc->desiredRotation);
1039 }
1040 if (!canGrow) {
1041 for (o = 0; o < config->num_output; o++) {
1042 xf86OutputPtr output = config->output[o];
1043
1044 for (s = 0; s < config->num_crtc; s++)
1045 if (output->possible_crtcs & (1 << s)) {
1046 DisplayModePtr mode;
1047
1048 for (mode = output->probed_modes; mode;
1049 mode = mode->next) {
1050 if (mode->HDisplay > crtc_width)
1051 crtc_width = mode->HDisplay;
1052 if (mode->VDisplay > crtc_width)
1053 crtc_width = mode->VDisplay;
1054 if (mode->VDisplay > crtc_height)
1055 crtc_height = mode->VDisplay;
1056 if (mode->HDisplay > crtc_height)
1057 crtc_height = mode->HDisplay;
1058 }
1059 }
1060 }
1061 }
1062 if (crtc_width > width)
1063 width = crtc_width;
1064 if (crtc_height > height)
1065 height = crtc_height;
1066 }
1067 if (config->maxWidth && width > config->maxWidth)
1068 width = config->maxWidth;
1069 if (config->maxHeight && height > config->maxHeight)
1070 height = config->maxHeight;
1071 if (config->minWidth && width < config->minWidth)
1072 width = config->minWidth;
1073 if (config->minHeight && height < config->minHeight)
1074 height = config->minHeight;
1075 *widthp = width;
1076 *heightp = height;
1077}
1078
1079#define POSITION_UNSET-100000 -100000
1080
1081/*
1082 * check if the user configured any outputs at all
1083 * with either a position or a relative setting or a mode.
1084 */
1085static Bool
1086xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr * modes)
1087{
1088 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
1089 int o;
1090 Bool user_conf = FALSE0;
1091
1092 for (o = 0; o < config->num_output; o++) {
1093 xf86OutputPtr output = config->output[o];
1094 const char *position;
1095 const char *relative_name;
1096 OutputOpts relation;
1097 int r;
1098
1099 static const OutputOpts relations[] = {
1100 OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
1101 };
1102
1103 position = xf86GetOptValString(output->options, OPTION_POSITION);
1104 if (position)
1105 user_conf = TRUE1;
1106
1107 relation = 0;
1108 relative_name = NULL((void*)0);
1109 for (r = 0; r < 4; r++) {
1110 relation = relations[r];
1111 relative_name = xf86GetOptValString(output->options, relation);
1112 if (relative_name)
1113 break;
1114 }
1115 if (relative_name)
1116 user_conf = TRUE1;
1117
1118 modes[o] = xf86OutputHasUserPreferredMode(output);
1119 if (modes[o])
1120 user_conf = TRUE1;
1121 }
1122
1123 return user_conf;
1124}
1125
1126static Bool
1127xf86InitialOutputPositions(ScrnInfoPtr scrn, DisplayModePtr * modes)
1128{
1129 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
1130 int o;
1131 int min_x, min_y;
1132
1133 /* check for initial right-of heuristic */
1134 for (o = 0; o < config->num_output; o++)
1135 {
1136 xf86OutputPtr output = config->output[o];
1137
1138 if (output->initial_x || output->initial_y)
1139 return TRUE1;
1140 }
1141
1142 for (o = 0; o < config->num_output; o++) {
1143 xf86OutputPtr output = config->output[o];
1144
1145 output->initial_x = output->initial_y = POSITION_UNSET-100000;
1146 }
1147
1148 /*
1149 * Loop until all outputs are set
1150 */
1151 for (;;) {
1152 Bool any_set = FALSE0;
1153 Bool keep_going = FALSE0;
1154
1155 for (o = 0; o < config->num_output; o++) {
1156 static const OutputOpts relations[] = {
1157 OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
1158 };
1159 xf86OutputPtr output = config->output[o];
1160 xf86OutputPtr relative;
1161 const char *relative_name;
1162 const char *position;
1163 OutputOpts relation;
1164 int r;
1165
1166 if (output->initial_x != POSITION_UNSET-100000)
1167 continue;
1168 position = xf86GetOptValString(output->options, OPTION_POSITION);
1169 /*
1170 * Absolute position wins
1171 */
1172 if (position) {
1173 int x, y;
1174
1175 if (sscanf(position, "%d %d", &x, &y) == 2) {
1176 output->initial_x = x;
1177 output->initial_y = y;
1178 }
1179 else {
1180 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1181 "Output %s position not of form \"x y\"\n",
1182 output->name);
1183 output->initial_x = output->initial_y = 0;
1184 }
1185 any_set = TRUE1;
1186 continue;
1187 }
1188 /*
1189 * Next comes relative positions
1190 */
1191 relation = 0;
1192 relative_name = NULL((void*)0);
1193 for (r = 0; r < 4; r++) {
1194 relation = relations[r];
1195 relative_name = xf86GetOptValString(output->options, relation);
1196 if (relative_name)
1197 break;
1198 }
1199 if (relative_name) {
1200 int or;
1201
1202 relative = NULL((void*)0);
1203 for (or = 0; or < config->num_output; or++) {
1204 xf86OutputPtr out_rel = config->output[or];
1205 XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
1206
1207 if (rel_mon) {
1208 if (xf86nameCompare(rel_mon->mon_identifier,
1209 relative_name) == 0) {
1210 relative = config->output[or];
1211 break;
1212 }
1213 }
1214 if (strcmp(out_rel->name, relative_name) == 0) {
1215 relative = config->output[or];
1216 break;
1217 }
1218 }
1219 if (!relative) {
1220 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1221 "Cannot position output %s relative to unknown output %s\n",
1222 output->name, relative_name);
1223 output->initial_x = 0;
1224 output->initial_y = 0;
1225 any_set = TRUE1;
1226 continue;
1227 }
1228 if (!modes[or]) {
1229 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1230 "Cannot position output %s relative to output %s without modes\n",
1231 output->name, relative_name);
1232 output->initial_x = 0;
1233 output->initial_y = 0;
1234 any_set = TRUE1;
1235 continue;
1236 }
1237 if (relative->initial_x == POSITION_UNSET-100000) {
1238 keep_going = TRUE1;
1239 continue;
1240 }
1241 output->initial_x = relative->initial_x;
1242 output->initial_y = relative->initial_y;
1243 switch (relation) {
1244 case OPTION_BELOW:
1245 output->initial_y +=
1246 xf86ModeHeight(modes[or], relative->initial_rotation);
1247 break;
1248 case OPTION_RIGHT_OF:
1249 output->initial_x +=
1250 xf86ModeWidth(modes[or], relative->initial_rotation);
1251 break;
1252 case OPTION_ABOVE:
1253 if (modes[o])
1254 output->initial_y -=
1255 xf86ModeHeight(modes[o], output->initial_rotation);
1256 break;
1257 case OPTION_LEFT_OF:
1258 if (modes[o])
1259 output->initial_x -=
1260 xf86ModeWidth(modes[o], output->initial_rotation);
1261 break;
1262 default:
1263 break;
1264 }
1265 any_set = TRUE1;
1266 continue;
1267 }
1268
1269 /* Nothing set, just stick them at 0,0 */
1270 output->initial_x = 0;
1271 output->initial_y = 0;
1272 any_set = TRUE1;
1273 }
1274 if (!keep_going)
1275 break;
1276 if (!any_set) {
1277 for (o = 0; o < config->num_output; o++) {
1278 xf86OutputPtr output = config->output[o];
1279
1280 if (output->initial_x == POSITION_UNSET-100000) {
1281 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1282 "Output position loop. Moving %s to 0,0\n",
1283 output->name);
1284 output->initial_x = output->initial_y = 0;
1285 break;
1286 }
1287 }
1288 }
1289 }
1290
1291 /*
1292 * normalize positions
1293 */
1294 min_x = 1000000;
1295 min_y = 1000000;
1296 for (o = 0; o < config->num_output; o++) {
1297 xf86OutputPtr output = config->output[o];
1298
1299 if (output->initial_x < min_x)
1300 min_x = output->initial_x;
1301 if (output->initial_y < min_y)
1302 min_y = output->initial_y;
1303 }
1304
1305 for (o = 0; o < config->num_output; o++) {
1306 xf86OutputPtr output = config->output[o];
1307
1308 output->initial_x -= min_x;
1309 output->initial_y -= min_y;
1310 }
1311 return TRUE1;
1312}
1313
1314static void
1315xf86InitialPanning(ScrnInfoPtr scrn)
1316{
1317 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
1318 int o;
1319
1320 for (o = 0; o < config->num_output; o++) {
1321 xf86OutputPtr output = config->output[o];
1322 const char *panning = xf86GetOptValString(output->options, OPTION_PANNING);
1323 int width, height, left, top;
1324 int track_width, track_height, track_left, track_top;
1325 int brdr[4];
1326
1327 memset(&output->initialTotalArea, 0, sizeof(BoxRec))__builtin___memset_chk (&output->initialTotalArea, 0, sizeof
(BoxRec), __builtin_object_size (&output->initialTotalArea
, 0))
;
1328 memset(&output->initialTrackingArea, 0, sizeof(BoxRec))__builtin___memset_chk (&output->initialTrackingArea, 0
, sizeof(BoxRec), __builtin_object_size (&output->initialTrackingArea
, 0))
;
1329 memset(output->initialBorder, 0, 4 * sizeof(INT16))__builtin___memset_chk (output->initialBorder, 0, 4 * sizeof
(INT16), __builtin_object_size (output->initialBorder, 0))
;
1330
1331 if (!panning)
1332 continue;
1333
1334 switch (sscanf(panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
1335 &width, &height, &left, &top,
1336 &track_width, &track_height, &track_left, &track_top,
1337 &brdr[0], &brdr[1], &brdr[2], &brdr[3])) {
1338 case 12:
1339 output->initialBorder[0] = brdr[0];
1340 output->initialBorder[1] = brdr[1];
1341 output->initialBorder[2] = brdr[2];
1342 output->initialBorder[3] = brdr[3];
1343 /* fall through */
1344 case 8:
1345 output->initialTrackingArea.x1 = track_left;
1346 output->initialTrackingArea.y1 = track_top;
1347 output->initialTrackingArea.x2 = track_left + track_width;
1348 output->initialTrackingArea.y2 = track_top + track_height;
1349 /* fall through */
1350 case 4:
1351 output->initialTotalArea.x1 = left;
1352 output->initialTotalArea.y1 = top;
1353 /* fall through */
1354 case 2:
1355 output->initialTotalArea.x2 = output->initialTotalArea.x1 + width;
1356 output->initialTotalArea.y2 = output->initialTotalArea.y1 + height;
1357 break;
1358 default:
1359 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1360 "Broken panning specification '%s' for output %s in config file\n",
1361 panning, output->name);
1362 }
1363 }
1364}
1365
1366/** Return - 0 + if a should be earlier, same or later than b in list
1367 */
1368static int
1369xf86ModeCompare(DisplayModePtr a, DisplayModePtr b)
1370{
1371 int diff;
1372
1373 diff = ((b->type & M_T_PREFERRED0x08) != 0) - ((a->type & M_T_PREFERRED0x08) != 0);
1374 if (diff)
1375 return diff;
1376 diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
1377 if (diff)
1378 return diff;
1379 diff = b->Clock - a->Clock;
1380 return diff;
1381}
1382
1383/**
1384 * Insertion sort input in-place and return the resulting head
1385 */
1386static DisplayModePtr
1387xf86SortModes(DisplayModePtr input)
1388{
1389 DisplayModePtr output = NULL((void*)0), i, o, n, *op, prev;
1390
1391 /* sort by preferred status and pixel area */
1392 while (input) {
1393 i = input;
1394 input = input->next;
1395 for (op = &output; (o = *op); op = &o->next)
1396 if (xf86ModeCompare(o, i) > 0)
1397 break;
1398 i->next = *op;
1399 *op = i;
1400 }
1401 /* prune identical modes */
1402 for (o = output; o && (n = o->next); o = n) {
1403 if (!strcmp(o->name, n->name) && xf86ModesEqual(o, n)) {
1404 o->next = n->next;
1405 free((void *) n->name);
1406 free(n);
1407 n = o;
1408 }
1409 }
1410 /* hook up backward links */
1411 prev = NULL((void*)0);
1412 for (o = output; o; o = o->next) {
1413 o->prev = prev;
1414 prev = o;
1415 }
1416 return output;
1417}
1418
1419static const char *
1420preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output)
1421{
1422 const char *preferred_mode = NULL((void*)0);
1423
1424 /* Check for a configured preference for a particular mode */
1425 preferred_mode = xf86GetOptValString(output->options,
1426 OPTION_PREFERRED_MODE);
1427 if (preferred_mode)
1428 return preferred_mode;
1429
1430 if (pScrn->display->modes && *pScrn->display->modes)
1431 preferred_mode = *pScrn->display->modes;
1432
1433 return preferred_mode;
1434}
1435
1436/** identify a token
1437 * args
1438 * *src a string with zero or more tokens, e.g. "tok0 tok1",
1439 * **token stores a pointer to the first token character,
1440 * *len stores the token length.
1441 * return
1442 * a pointer into src[] at the token terminating character, or
1443 * NULL if no token is found.
1444 */
1445static const char *
1446gettoken(const char *src, const char **token, int *len)
1447{
1448 const char *delim = " \t";
1449 int skip;
1450
1451 if (!src)
1452 return NULL((void*)0);
1453
1454 skip = strspn(src, delim);
1455 *token = &src[skip];
1456
1457 *len = strcspn(*token, delim);
1458 /* Support for backslash escaped delimiters could be implemented
1459 * here.
1460 */
1461
1462 /* (*token)[0] != '\0' <==> *len > 0 */
1463 if (*len > 0)
1464 return &(*token)[*len];
1465 else
1466 return NULL((void*)0);
1467}
1468
1469/** Check for a user configured zoom mode list, Option "ZoomModes":
1470 *
1471 * Section "Monitor"
1472 * Identifier "a21inch"
1473 * Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480"
1474 * EndSection
1475 *
1476 * Each user mode name is searched for independently so the list
1477 * specification order is free. An output mode is matched at most
1478 * once, a mode with an already set M_T_USERDEF type bit is skipped.
1479 * Thus a repeat mode name specification matches the next output mode
1480 * with the same name.
1481 *
1482 * Ctrl+Alt+Keypad-{Plus,Minus} zooms {in,out} by selecting the
1483 * {next,previous} M_T_USERDEF mode in the screen modes list, itself
1484 * sorted toward lower dot area or lower dot clock frequency, see
1485 * modes/xf86Crtc.c: xf86SortModes() xf86SetScrnInfoModes(), and
1486 * common/xf86Cursor.c: xf86ZoomViewport().
1487 */
1488static int
1489processZoomModes(xf86OutputPtr output)
1490{
1491 const char *zoom_modes;
1492 int count = 0;
1493
1494 zoom_modes = xf86GetOptValString(output->options, OPTION_ZOOM_MODES);
1495
1496 if (zoom_modes) {
1497 const char *token, *next;
1498 int len;
1499
1500 next = gettoken(zoom_modes, &token, &len);
1501 while (next) {
1502 DisplayModePtr mode;
1503
1504 for (mode = output->probed_modes; mode; mode = mode->next)
1505 if (!strncmp(token, mode->name, len) /* prefix match */
1506 && mode->name[len] == '\0' /* equal length */
1507 && !(mode->type & M_T_USERDEF0x20)) { /* no rematch */
1508 mode->type |= M_T_USERDEF0x20;
1509 break;
1510 }
1511
1512 count++;
1513 next = gettoken(next, &token, &len);
1514 }
1515 }
1516
1517 return count;
1518}
1519
1520static void
1521GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
1522{
1523 if (!mon || !mode)
1524 return;
1525
1526 mon->nHsync = 1;
1527 mon->hsync[0].lo = 1024.0;
1528 mon->hsync[0].hi = 0.0;
1529
1530 mon->nVrefresh = 1;
1531 mon->vrefresh[0].lo = 1024.0;
1532 mon->vrefresh[0].hi = 0.0;
1533
1534 while (mode) {
1535 if (!mode->HSync)
1536 mode->HSync = ((float) mode->Clock) / ((float) mode->HTotal);
1537
1538 if (!mode->VRefresh)
1539 mode->VRefresh = (1000.0 * ((float) mode->Clock)) /
1540 ((float) (mode->HTotal * mode->VTotal));
1541
1542 if (mode->HSync < mon->hsync[0].lo)
1543 mon->hsync[0].lo = mode->HSync;
1544
1545 if (mode->HSync > mon->hsync[0].hi)
1546 mon->hsync[0].hi = mode->HSync;
1547
1548 if (mode->VRefresh < mon->vrefresh[0].lo)
1549 mon->vrefresh[0].lo = mode->VRefresh;
1550
1551 if (mode->VRefresh > mon->vrefresh[0].hi)
1552 mon->vrefresh[0].hi = mode->VRefresh;
1553
1554 mode = mode->next;
1555 }
1556
1557 /* stretch out the bottom to fit 640x480@60 */
1558 if (mon->hsync[0].lo > 31.0)
1559 mon->hsync[0].lo = 31.0;
1560 if (mon->vrefresh[0].lo > 58.0)
1561 mon->vrefresh[0].lo = 58.0;
1562}
1563
1564enum det_monrec_source {
1565 sync_config, sync_edid, sync_default
1566};
1567
1568struct det_monrec_parameter {
1569 MonRec *mon_rec;
1570 int *max_clock;
1571 Bool set_hsync;
1572 Bool set_vrefresh;
1573 enum det_monrec_source *sync_source;
1574};
1575
1576static void
1577handle_detailed_monrec(struct detailed_monitor_section *det_mon, void *data)
1578{
1579 struct det_monrec_parameter *p;
1580
1581 p = (struct det_monrec_parameter *) data;
1582
1583 if (det_mon->type == DS_RANGES0xFD) {
1584 struct monitor_ranges *ranges = &det_mon->section.ranges;
1585
1586 if (p->set_hsync && ranges->max_h) {
1587 p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h;
1588 p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h;
1589 p->mon_rec->nHsync++;
1590 if (*p->sync_source == sync_default)
1591 *p->sync_source = sync_edid;
1592 }
1593 if (p->set_vrefresh && ranges->max_v) {
1594 p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v;
1595 p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v;
1596 p->mon_rec->nVrefresh++;
1597 if (*p->sync_source == sync_default)
1598 *p->sync_source = sync_edid;
1599 }
1600 if (ranges->max_clock * 1000 > *p->max_clock)
1601 *p->max_clock = ranges->max_clock * 1000;
1602 }
1603}
1604
1605void
1606xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY)
1607{
1608 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
1609 int o;
1610
1611 /* When canGrow was TRUE in the initial configuration we have to
1612 * compare against the maximum values so that we don't drop modes.
1613 * When canGrow was FALSE, the maximum values would have been clamped
1614 * anyway.
1615 */
1616 if (maxX == 0 || maxY == 0) {
1617 maxX = config->maxWidth;
1618 maxY = config->maxHeight;
1619 }
1620
1621 /* Probe the list of modes for each output. */
1622 for (o = 0; o < config->num_output; o++) {
1623 xf86OutputPtr output = config->output[o];
1624 DisplayModePtr mode;
1625 DisplayModePtr config_modes = NULL((void*)0), output_modes, default_modes = NULL((void*)0);
1626 const char *preferred_mode;
1627 xf86MonPtr edid_monitor;
1628 XF86ConfMonitorPtr conf_monitor;
1629 MonRec mon_rec;
1630 int min_clock = 0;
1631 int max_clock = 0;
1632 double clock;
1633 Bool add_default_modes;
1634 Bool debug_modes = config->debug_modes || xf86Initialising;
1635 enum det_monrec_source sync_source = sync_default;
1636
1637 while (output->probed_modes != NULL((void*)0))
1638 xf86DeleteMode(&output->probed_modes, output->probed_modes);
1639
1640 /*
1641 * Check connection status
1642 */
1643 output->status = (*output->funcs->detect) (output);
1644
1645 if (output->status == XF86OutputStatusDisconnected &&
1646 !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE0)) {
1647 xf86OutputSetEDID(output, NULL((void*)0));
1648 continue;
1649 }
1650
1651 memset(&mon_rec, '\0', sizeof(mon_rec))__builtin___memset_chk (&mon_rec, '\0', sizeof(mon_rec), __builtin_object_size
(&mon_rec, 0))
;
1652
1653 conf_monitor = output->conf_monitor;
1654
1655 if (conf_monitor) {
1656 int i;
1657
1658 for (i = 0; i < conf_monitor->mon_n_hsync; i++) {
1659 mon_rec.hsync[mon_rec.nHsync].lo =
1660 conf_monitor->mon_hsync[i].lo;
1661 mon_rec.hsync[mon_rec.nHsync].hi =
1662 conf_monitor->mon_hsync[i].hi;
1663 mon_rec.nHsync++;
1664 sync_source = sync_config;
1665 }
1666 for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) {
1667 mon_rec.vrefresh[mon_rec.nVrefresh].lo =
1668 conf_monitor->mon_vrefresh[i].lo;
1669 mon_rec.vrefresh[mon_rec.nVrefresh].hi =
1670 conf_monitor->mon_vrefresh[i].hi;
1671 mon_rec.nVrefresh++;
1672 sync_source = sync_config;
1673 }
1674 config_modes = xf86GetMonitorModes(scrn, conf_monitor);
1675 }
1676
1677 output_modes = (*output->funcs->get_modes) (output);
1678
1679 /*
1680 * If the user has a preference, respect it.
1681 * Otherwise, don't second-guess the driver.
1682 */
1683 if (!xf86GetOptValBool(output->options, OPTION_DEFAULT_MODES,
1684 &add_default_modes))
1685 add_default_modes = (output_modes == NULL((void*)0));
1686
1687 edid_monitor = output->MonInfo;
1688
1689 if (edid_monitor) {
1690 struct det_monrec_parameter p;
1691 struct disp_features *features = &edid_monitor->features;
1692 struct cea_data_block *hdmi_db;
1693
1694 /* if display is not continuous-frequency, don't add default modes */
1695 if (!GTF_SUPPORTED(features->msc)(features->msc & 0x1))
1696 add_default_modes = FALSE0;
1697
1698 p.mon_rec = &mon_rec;
1699 p.max_clock = &max_clock;
1700 p.set_hsync = mon_rec.nHsync == 0;
1701 p.set_vrefresh = mon_rec.nVrefresh == 0;
1702 p.sync_source = &sync_source;
1703
1704 xf86ForEachDetailedBlock(edid_monitor, handle_detailed_monrec, &p);
1705
1706 /* Look at the CEA HDMI vendor block for the max TMDS freq */
1707 hdmi_db = xf86MonitorFindHDMIBlock(edid_monitor);
1708 if (hdmi_db && hdmi_db->len >= 7) {
1709 int tmds_freq = hdmi_db->u.vendor.hdmi.max_tmds_clock * 5000;
1710 xf86DrvMsg(scrn->scrnIndex, X_PROBED,
1711 "HDMI max TMDS frequency %dKHz\n", tmds_freq);
1712 if (tmds_freq > max_clock)
1713 max_clock = tmds_freq;
1714 }
1715 }
1716
1717 if (xf86GetOptValFreq(output->options, OPTION_MIN_CLOCK,
1718 OPTUNITS_KHZ, &clock))
1719 min_clock = (int) clock;
1720 if (xf86GetOptValFreq(output->options, OPTION_MAX_CLOCK,
1721 OPTUNITS_KHZ, &clock))
1722 max_clock = (int) clock;
1723
1724 /* If we still don't have a sync range, guess wildly */
1725 if (!mon_rec.nHsync || !mon_rec.nVrefresh)
1726 GuessRangeFromModes(&mon_rec, output_modes);
1727
1728 /*
1729 * These limits will end up setting a 1024x768@60Hz mode by default,
1730 * which seems like a fairly good mode to use when nothing else is
1731 * specified
1732 */
1733 if (mon_rec.nHsync == 0) {
1734 mon_rec.hsync[0].lo = 31.0;
1735 mon_rec.hsync[0].hi = 55.0;
1736 mon_rec.nHsync = 1;
1737 }
1738 if (mon_rec.nVrefresh == 0) {
1739 mon_rec.vrefresh[0].lo = 58.0;
1740 mon_rec.vrefresh[0].hi = 62.0;
1741 mon_rec.nVrefresh = 1;
1742 }
1743
1744 if (add_default_modes)
1745 default_modes = xf86GetDefaultModes();
1746
1747 /*
1748 * If this is not an RB monitor, remove RB modes from the default
1749 * pool. RB modes from the config or the monitor itself are fine.
1750 */
1751 if (!mon_rec.reducedblanking)
1752 xf86ValidateModesReducedBlanking(scrn, default_modes);
1753
1754 if (sync_source == sync_config) {
1755 /*
1756 * Check output and config modes against sync range from config file
1757 */
1758 xf86ValidateModesSync(scrn, output_modes, &mon_rec);
1759 xf86ValidateModesSync(scrn, config_modes, &mon_rec);
1760 }
1761 /*
1762 * Check default modes against sync range
1763 */
1764 xf86ValidateModesSync(scrn, default_modes, &mon_rec);
1765 /*
1766 * Check default modes against monitor max clock
1767 */
1768 if (max_clock) {
1769 xf86ValidateModesClocks(scrn, default_modes,
1770 &min_clock, &max_clock, 1);
1771 xf86ValidateModesClocks(scrn, output_modes,
1772 &min_clock, &max_clock, 1);
1773 }
1774
1775 output->probed_modes = NULL((void*)0);
1776 output->probed_modes = xf86ModesAdd(output->probed_modes, config_modes);
1777 output->probed_modes = xf86ModesAdd(output->probed_modes, output_modes);
1778 output->probed_modes =
1779 xf86ModesAdd(output->probed_modes, default_modes);
1780
1781 /*
1782 * Check all modes against max size, interlace, and doublescan
1783 */
1784 if (maxX && maxY)
1785 xf86ValidateModesSize(scrn, output->probed_modes, maxX, maxY, 0);
1786
1787 {
1788 int flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
1789 (output->doubleScanAllowed ? V_DBLSCAN : 0);
1790 xf86ValidateModesFlags(scrn, output->probed_modes, flags);
1791 }
1792
1793 /*
1794 * Check all modes against output
1795 */
1796 for (mode = output->probed_modes; mode != NULL((void*)0); mode = mode->next)
1797 if (mode->status == MODE_OK)
1798 mode->status = (*output->funcs->mode_valid) (output, mode);
1799
1800 xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes);
1801
1802 output->probed_modes = xf86SortModes(output->probed_modes);
1803
1804 /* Check for a configured preference for a particular mode */
1805 preferred_mode = preferredMode(scrn, output);
1806
1807 if (preferred_mode) {
1808 for (mode = output->probed_modes; mode; mode = mode->next) {
1809 if (!strcmp(preferred_mode, mode->name)) {
1810 if (mode != output->probed_modes) {
1811 if (mode->prev)
1812 mode->prev->next = mode->next;
1813 if (mode->next)
1814 mode->next->prev = mode->prev;
1815 mode->next = output->probed_modes;
1816 output->probed_modes->prev = mode;
1817 mode->prev = NULL((void*)0);
1818 output->probed_modes = mode;
1819 }
1820 mode->type |= (M_T_PREFERRED0x08 | M_T_USERPREF0x80);
1821 break;
1822 }
1823 }
1824 }
1825
1826 /* Ctrl+Alt+Keypad-{Plus,Minus} zoom mode: M_T_USERDEF mode type */
1827 processZoomModes(output);
1828
1829 output->initial_rotation = xf86OutputInitialRotation(output);
1830
1831 if (debug_modes) {
1832 if (output->probed_modes != NULL((void*)0)) {
1833 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1834 "Printing probed modes for output %s\n",
1835 output->name);
1836 }
1837 else {
1838 xf86DrvMsg(scrn->scrnIndex, X_INFO,
1839 "No remaining probed modes for output %s\n",
1840 output->name);
1841 }
1842 }
1843 for (mode = output->probed_modes; mode != NULL((void*)0); mode = mode->next) {
1844 /* The code to choose the best mode per pipe later on will require
1845 * VRefresh to be set.
1846 */
1847 mode->VRefresh = xf86ModeVRefresh(mode);
1848 xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
1849
1850 if (debug_modes)
1851 xf86PrintModeline(scrn->scrnIndex, mode);
1852 }
1853 }
1854}
1855
1856/**
1857 * Copy one of the output mode lists to the ScrnInfo record
1858 */
1859
1860static DisplayModePtr
1861biggestMode(DisplayModePtr a, DisplayModePtr b)
1862{
1863 int A, B;
1864
1865 if (!a)
1866 return b;
1867 if (!b)
1868 return a;
1869
1870 A = a->HDisplay * a->VDisplay;
1871 B = b->HDisplay * b->VDisplay;
1872
1873 if (A > B)
1874 return a;
1875
1876 return b;
1877}
1878
1879static xf86OutputPtr
1880SetCompatOutput(xf86CrtcConfigPtr config)
1881{
1882 xf86OutputPtr output = NULL((void*)0), test = NULL((void*)0);
1883 DisplayModePtr maxmode = NULL((void*)0), testmode, mode;
1884 int o, compat = -1, count, mincount = 0;
1885
1886 if (config->num_output == 0)
1887 return NULL((void*)0);
1888
1889 /* Look for one that's definitely connected */
1890 for (o = 0; o < config->num_output; o++) {
1891 test = config->output[o];
1892 if (!test->crtc)
1893 continue;
1894 if (test->status != XF86OutputStatusConnected)
1895 continue;
1896 if (!test->probed_modes)
1897 continue;
1898
1899 testmode = mode = test->probed_modes;
1900 for (count = 0; mode; mode = mode->next, count++)
1901 testmode = biggestMode(testmode, mode);
1902
1903 if (!output) {
1904 output = test;
1905 compat = o;
1906 maxmode = testmode;
1907 mincount = count;
1908 }
1909 else if (maxmode == biggestMode(maxmode, testmode)) {
1910 output = test;
1911 compat = o;
1912 maxmode = testmode;
1913 mincount = count;
1914 }
1915 else if ((maxmode->HDisplay == testmode->HDisplay) &&
1916 (maxmode->VDisplay == testmode->VDisplay) &&
1917 count <= mincount) {
1918 output = test;
1919 compat = o;
1920 maxmode = testmode;
1921 mincount = count;
1922 }
1923 }
1924
1925 /* If we didn't find one, take anything we can get */
1926 if (!output) {
1927 for (o = 0; o < config->num_output; o++) {
1928 test = config->output[o];
1929 if (!test->crtc)
1930 continue;
1931 if (!test->probed_modes)
1932 continue;
1933
1934 if (!output) {
1935 output = test;
1936 compat = o;
1937 }
1938 else if (test->probed_modes->HDisplay <
1939 output->probed_modes->HDisplay) {
1940 output = test;
1941 compat = o;
1942 }
1943 }
1944 }
1945
1946 if (compat >= 0) {
1947 config->compat_output = compat;
1948 }
1949 else if (config->compat_output >= 0 && config->compat_output < config->num_output) {
1950 /* Don't change the compat output when no valid outputs found */
1951 output = config->output[config->compat_output];
1952 }
1953
1954 /* All outputs are disconnected, select one to fake */
1955 if (!output && config->num_output) {
1956 config->compat_output = 0;
1957 output = config->output[config->compat_output];
1958 }
1959
1960 return output;
1961}
1962
1963void
1964xf86SetScrnInfoModes(ScrnInfoPtr scrn)
1965{
1966 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
1967 xf86OutputPtr output;
1968 xf86CrtcPtr crtc;
1969 DisplayModePtr last, mode = NULL((void*)0);
1970
1971 output = SetCompatOutput(config);
1972
1973 if (!output)
1974 return; /* punt */
1975
1976 crtc = output->crtc;
1977
1978 /* Clear any existing modes from scrn->modes */
1979 while (scrn->modes != NULL((void*)0))
1980 xf86DeleteMode(&scrn->modes, scrn->modes);
1981
1982 /* Set scrn->modes to the mode list for the 'compat' output */
1983 scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
1984
1985 if (crtc) {
1986 for (mode = scrn->modes; mode; mode = mode->next)
1987 if (xf86ModesEqual(mode, &crtc->desiredMode))
1988 break;
1989 }
1990
1991 if (!scrn->modes) {
1992 scrn->modes = xf86ModesAdd(scrn->modes,
1993 xf86CVTMode(scrn->display->virtualX,
1994 scrn->display->virtualY,
1995 60, 0, 0));
1996 }
1997
1998 /* For some reason, scrn->modes is circular, unlike the other mode
1999 * lists. How great is that?
2000 */
2001 for (last = scrn->modes; last && last->next; last = last->next);
2002 last->next = scrn->modes;
2003 scrn->modes->prev = last;
2004 if (mode) {
2005 while (scrn->modes != mode)
2006 scrn->modes = scrn->modes->next;
2007 }
2008
2009 scrn->currentMode = scrn->modes;
2010#ifdef XFreeXDGA1
2011 if (scrn->pScreen)
2012 _xf86_di_dga_reinit_internal(scrn->pScreen);
2013#endif
2014}
2015
2016static Bool
2017xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
2018 Bool *enabled)
2019{
2020 Bool any_enabled = FALSE0;
2021 int o;
2022
2023 /*
2024 * Don't bother enabling outputs on GPU screens: a client needs to attach
2025 * it to a source provider before setting a mode that scans out a shared
2026 * pixmap.
2027 */
2028 if (scrn->is_gpu)
2029 return FALSE0;
2030
2031 for (o = 0; o < config->num_output; o++)
2032 any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE1);
2033
2034 if (!any_enabled) {
2035 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2036 "No outputs definitely connected, trying again...\n");
2037
2038 for (o = 0; o < config->num_output; o++)
2039 any_enabled |= enabled[o] =
2040 xf86OutputEnabled(config->output[o], FALSE0);
2041 }
2042
2043 return any_enabled;
2044}
2045
2046static Bool
2047nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
2048{
2049 int o = *index;
2050
2051 for (o++; o < config->num_output; o++) {
2052 if (enabled[o]) {
2053 *index = o;
2054 return TRUE1;
2055 }
2056 }
2057
2058 return FALSE0;
2059}
2060
2061static Bool
2062aspectMatch(float a, float b)
2063{
2064 return fabs(1 - (a / b)) < 0.05;
2065}
2066
2067static DisplayModePtr
2068nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
2069{
2070 DisplayModePtr m = NULL((void*)0);
2071
2072 if (!o)
2073 return NULL((void*)0);
2074
2075 if (!last)
2076 m = o->probed_modes;
2077 else
2078 m = last->next;
2079
2080 for (; m; m = m->next)
2081 if (aspectMatch(aspect, (float) m->HDisplay / (float) m->VDisplay))
2082 return m;
2083
2084 return NULL((void*)0);
2085}
2086
2087static DisplayModePtr
2088bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
2089{
2090 int o = -1, p;
2091 DisplayModePtr mode = NULL((void*)0), test = NULL((void*)0), match = NULL((void*)0);
2092
2093 if (!nextEnabledOutput(config, enabled, &o))
2094 return NULL((void*)0);
2095 while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
2096 test = mode;
2097 for (p = o; nextEnabledOutput(config, enabled, &p);) {
2098 test = xf86OutputFindClosestMode(config->output[p], mode);
2099 if (!test)
2100 break;
2101 if (test->HDisplay != mode->HDisplay ||
2102 test->VDisplay != mode->VDisplay) {
2103 test = NULL((void*)0);
2104 break;
2105 }
2106 }
2107
2108 /* if we didn't match it on all outputs, try the next one */
2109 if (!test)
2110 continue;
2111
2112 /* if it's bigger than the last one, save it */
2113 if (!match || (test->HDisplay > match->HDisplay))
2114 match = test;
2115 }
2116
2117 /* return the biggest one found */
2118 return match;
2119}
2120
2121static int
2122numEnabledOutputs(xf86CrtcConfigPtr config, Bool *enabled)
2123{
2124 int i = 0, p;
2125
2126 for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
2127
2128 return i;
2129}
2130
2131static Bool
2132xf86TargetRightOf(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
2133 DisplayModePtr *modes, Bool *enabled,
2134 int width, int height)
2135{
2136 int o;
2137 int w = 0;
2138 Bool has_tile = FALSE0;
2139 uint32_t configured_outputs;
2140
2141 if (scrn->preferClone)
2142 return FALSE0;
2143
2144 if (numEnabledOutputs(config, enabled) < 2)
2145 return FALSE0;
2146
2147 for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
2148 DisplayModePtr mode =
2149 xf86OutputHasPreferredMode(config->output[o], width, height);
2150
2151 if (!mode)
2152 return FALSE0;
2153
2154 w += mode->HDisplay;
2155 }
2156
2157 if (w > width)
2158 return FALSE0;
2159
2160 w = 0;
2161 configured_outputs = 0;
2162
2163 for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
2164 DisplayModePtr mode =
2165 xf86OutputHasPreferredMode(config->output[o], width, height);
2166
2167 if (configured_outputs & (1 << o))
2168 continue;
2169
2170 if (config->output[o]->tile_info.group_id) {
2171 has_tile = TRUE1;
2172 continue;
2173 }
2174
2175 config->output[o]->initial_x = w;
2176 w += mode->HDisplay;
2177
2178 configured_outputs |= (1 << o);
2179 modes[o] = mode;
2180 }
2181
2182 if (has_tile) {
2183 for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
2184 int ht, vt, ot;
2185 int add_x, cur_x = w;
2186 struct xf86CrtcTileInfo *tile_info = &config->output[o]->tile_info, *this_tile;
2187 if (configured_outputs & (1 << o))
2188 continue;
2189 if (!tile_info->group_id)
2190 continue;
2191
2192 if (tile_info->tile_h_loc != 0 && tile_info->tile_v_loc != 0)
2193 continue;
2194
2195 for (ht = 0; ht < tile_info->num_h_tile; ht++) {
2196 int cur_y = 0;
2197 add_x = 0;
2198 for (vt = 0; vt < tile_info->num_v_tile; vt++) {
2199
2200 for (ot = -1; nextEnabledOutput(config, enabled, &ot); ) {
2201
2202 DisplayModePtr mode =
2203 xf86OutputHasPreferredMode(config->output[ot], width, height);
2204 if (!config->output[ot]->tile_info.group_id)
2205 continue;
2206
2207 this_tile = &config->output[ot]->tile_info;
2208 if (this_tile->group_id != tile_info->group_id)
2209 continue;
2210
2211 if (this_tile->tile_h_loc != ht ||
2212 this_tile->tile_v_loc != vt)
2213 continue;
2214
2215 config->output[ot]->initial_x = cur_x;
2216 config->output[ot]->initial_y = cur_y;
2217
2218 if (vt == 0)
2219 add_x = this_tile->tile_h_size;
2220 cur_y += this_tile->tile_v_size;
2221 configured_outputs |= (1 << ot);
2222 modes[ot] = mode;
2223 }
2224 }
2225 cur_x += add_x;
2226 }
2227 w = cur_x;
2228 }
2229 }
2230 return TRUE1;
2231}
2232
2233static Bool
2234xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
2235 DisplayModePtr * modes, Bool *enabled,
2236 int width, int height)
2237{
2238 int o, p;
2239 int max_pref_width = 0, max_pref_height = 0;
2240 DisplayModePtr *preferred, *preferred_match;
2241 Bool ret = FALSE0;
2242
2243 preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr))XNFcallocarray((config->num_output), (sizeof(DisplayModePtr
)))
;
2244 preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr))XNFcallocarray((config->num_output), (sizeof(DisplayModePtr
)))
;
2245
2246 /* Check if the preferred mode is available on all outputs */
2247 for (p = -1; nextEnabledOutput(config, enabled, &p);) {
2248 Rotation r = config->output[p]->initial_rotation;
2249 DisplayModePtr mode;
2250
2251 if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p],
2252 width, height))) {
2253 int pref_width = xf86ModeWidth(preferred[p], r);
2254 int pref_height = xf86ModeHeight(preferred[p], r);
2255 Bool all_match = TRUE1;
2256
2257 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2258 Bool match = FALSE0;
2259 xf86OutputPtr output = config->output[o];
2260
2261 if (o == p)
2262 continue;
2263
2264 /*
2265 * First see if the preferred mode matches on the next
2266 * output as well. This catches the common case of identical
2267 * monitors and makes sure they all have the same timings
2268 * and refresh. If that fails, we fall back to trying to
2269 * match just width & height.
2270 */
2271 mode = xf86OutputHasPreferredMode(output, pref_width,
2272 pref_height);
2273 if (mode && xf86ModesEqual(mode, preferred[p])) {
2274 preferred[o] = mode;
2275 match = TRUE1;
2276 }
2277 else {
2278 for (mode = output->probed_modes; mode; mode = mode->next) {
2279 Rotation ir = output->initial_rotation;
2280
2281 if (xf86ModeWidth(mode, ir) == pref_width &&
2282 xf86ModeHeight(mode, ir) == pref_height) {
2283 preferred[o] = mode;
2284 match = TRUE1;
2285 }
2286 }
2287 }
2288
2289 all_match &= match;
2290 }
2291
2292 if (all_match &&
2293 (pref_width * pref_height > max_pref_width * max_pref_height)) {
2294 for (o = -1; nextEnabledOutput(config, enabled, &o);)
2295 preferred_match[o] = preferred[o];
2296 max_pref_width = pref_width;
2297 max_pref_height = pref_height;
2298 ret = TRUE1;
2299 }
2300 }
2301 }
2302
2303 /*
2304 * If there's no preferred mode, but only one monitor, pick the
2305 * biggest mode for its aspect ratio or 4:3, assuming one exists.
2306 */
2307 if (!ret)
2308 do {
2309 float aspect = 0.0;
2310 DisplayModePtr a = NULL((void*)0), b = NULL((void*)0);
2311
2312 if (numEnabledOutputs(config, enabled) != 1)
2313 break;
2314
2315 p = -1;
2316 nextEnabledOutput(config, enabled, &p);
2317 if (config->output[p]->mm_height)
2318 aspect = (float) config->output[p]->mm_width /
2319 (float) config->output[p]->mm_height;
2320
2321 a = bestModeForAspect(config, enabled, 4.0/3.0);
2322 if (aspect)
2323 b = bestModeForAspect(config, enabled, aspect);
2324
2325 preferred_match[p] = biggestMode(a, b);
2326
2327 if (preferred_match[p])
2328 ret = TRUE1;
2329
2330 } while (0);
2331
2332 if (ret) {
2333 /* oh good, there is a match. stash the selected modes and return. */
2334 memcpy(modes, preferred_match,__builtin___memcpy_chk (modes, preferred_match, config->num_output
* sizeof(DisplayModePtr), __builtin_object_size (modes, 0))
2335 config->num_output * sizeof(DisplayModePtr))__builtin___memcpy_chk (modes, preferred_match, config->num_output
* sizeof(DisplayModePtr), __builtin_object_size (modes, 0))
;
2336 }
2337
2338 free(preferred);
2339 free(preferred_match);
2340 return ret;
2341}
2342
2343static Bool
2344xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
2345 DisplayModePtr * modes, Bool *enabled, int width, int height)
2346{
2347 int o;
2348 float aspect = 0.0, *aspects;
2349 xf86OutputPtr output;
2350 Bool ret = FALSE0;
2351 DisplayModePtr guess = NULL((void*)0), aspect_guess = NULL((void*)0), base_guess = NULL((void*)0);
2352
2353 aspects = xnfcalloc(config->num_output, sizeof(float))XNFcallocarray((config->num_output), (sizeof(float)));
2354
2355 /* collect the aspect ratios */
2356 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2357 output = config->output[o];
2358 if (output->mm_height)
2359 aspects[o] = (float) output->mm_width / (float) output->mm_height;
2360 else
2361 aspects[o] = 4.0 / 3.0;
2362 }
2363
2364 /* check that they're all the same */
2365 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2366 output = config->output[o];
Value stored to 'output' is never read
2367 if (!aspect) {
2368 aspect = aspects[o];
2369 }
2370 else if (!aspectMatch(aspect, aspects[o])) {
2371 goto no_aspect_match;
2372 }
2373 }
2374
2375 /* if they're all 4:3, just skip ahead and save effort */
2376 if (!aspectMatch(aspect, 4.0 / 3.0))
2377 aspect_guess = bestModeForAspect(config, enabled, aspect);
2378
2379 no_aspect_match:
2380 base_guess = bestModeForAspect(config, enabled, 4.0 / 3.0);
2381
2382 guess = biggestMode(base_guess, aspect_guess);
2383
2384 if (!guess)
2385 goto out;
2386
2387 /* found a mode that works everywhere, now apply it */
2388 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2389 modes[o] = xf86OutputFindClosestMode(config->output[o], guess);
2390 }
2391 ret = TRUE1;
2392
2393 out:
2394 free(aspects);
2395 return ret;
2396}
2397
2398static Bool
2399xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
2400 DisplayModePtr * modes, Bool *enabled, int width, int height)
2401{
2402 DisplayModePtr target_mode = NULL((void*)0);
2403 Rotation target_rotation = RR_Rotate_01;
2404 DisplayModePtr default_mode;
2405 int default_preferred, target_preferred = 0, o;
2406
2407 /* User preferred > preferred > other modes */
2408 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2409 default_mode = xf86DefaultMode(config->output[o], width, height);
2410 if (!default_mode)
2411 continue;
2412
2413 default_preferred = (((default_mode->type & M_T_PREFERRED0x08) != 0) +
2414 ((default_mode->type & M_T_USERPREF0x80) != 0));
2415
2416 if (default_preferred > target_preferred || !target_mode) {
2417 target_mode = default_mode;
2418 target_preferred = default_preferred;
2419 target_rotation = config->output[o]->initial_rotation;
2420 config->compat_output = o;
2421 }
2422 }
2423
2424 if (target_mode)
2425 modes[config->compat_output] = target_mode;
2426
2427 /* Fill in other output modes */
2428 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2429 if (!modes[o])
2430 modes[o] = xf86ClosestMode(config->output[o], target_mode,
2431 target_rotation, width, height);
2432 }
2433
2434 return target_mode != NULL((void*)0);
2435}
2436
2437static Bool
2438xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
2439 DisplayModePtr * modes, Bool *enabled, int width, int height)
2440{
2441 int o;
2442
2443 if (xf86UserConfiguredOutputs(scrn, modes))
2444 return xf86TargetFallback(scrn, config, modes, enabled, width, height);
2445
2446 for (o = -1; nextEnabledOutput(config, enabled, &o);)
2447 if (xf86OutputHasUserPreferredMode(config->output[o]))
2448 return
2449 xf86TargetFallback(scrn, config, modes, enabled, width, height);
2450
2451 return FALSE0;
2452}
2453
2454static Bool
2455xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green,
2456 float gamma_blue)
2457{
2458 int i, size = 256;
2459 CARD16 *red, *green, *blue;
2460
2461 red = xallocarray(size, 3 * sizeof(CARD16))xreallocarray(((void*)0), (size), (3 * sizeof(CARD16)));
2462 green = red + size;
2463 blue = green + size;
2464
2465 /* Only cause warning if user wanted gamma to be set. */
2466 if (!crtc->funcs->gamma_set &&
2467 (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) {
2468 free(red);
2469 return FALSE0;
2470 }
2471 else if (!crtc->funcs->gamma_set) {
2472 free(red);
2473 return TRUE1;
2474 }
2475
2476 /* At this early stage none of the randr-interface stuff is up.
2477 * So take the default gamma size for lack of something better.
2478 */
2479 for (i = 0; i < size; i++) {
2480 if (gamma_red == 1.0)
2481 red[i] = i << 8;
2482 else
2483 red[i] = (CARD16) (pow((double) i / (double) (size - 1),
2484 1. / (double) gamma_red) * (double) (size -
2485 1) *
2486 256);
2487
2488 if (gamma_green == 1.0)
2489 green[i] = i << 8;
2490 else
2491 green[i] = (CARD16) (pow((double) i / (double) (size - 1),
2492 1. / (double) gamma_green) *
2493 (double) (size - 1) * 256);
2494
2495 if (gamma_blue == 1.0)
2496 blue[i] = i << 8;
2497 else
2498 blue[i] = (CARD16) (pow((double) i / (double) (size - 1),
2499 1. / (double) gamma_blue) * (double) (size -
2500 1) *
2501 256);
2502 }
2503
2504 /* Default size is 256, so anything else is failure. */
2505 if (size != crtc->gamma_size) {
2506 free(red);
2507 return FALSE0;
2508 }
2509
2510 crtc->gamma_size = size;
2511 memcpy(crtc->gamma_red, red, crtc->gamma_size * sizeof(CARD16))__builtin___memcpy_chk (crtc->gamma_red, red, crtc->gamma_size
* sizeof(CARD16), __builtin_object_size (crtc->gamma_red,
0))
;
2512 memcpy(crtc->gamma_green, green, crtc->gamma_size * sizeof(CARD16))__builtin___memcpy_chk (crtc->gamma_green, green, crtc->
gamma_size * sizeof(CARD16), __builtin_object_size (crtc->
gamma_green, 0))
;
2513 memcpy(crtc->gamma_blue, blue, crtc->gamma_size * sizeof(CARD16))__builtin___memcpy_chk (crtc->gamma_blue, blue, crtc->gamma_size
* sizeof(CARD16), __builtin_object_size (crtc->gamma_blue
, 0))
;
2514
2515 /* Do not set gamma now, delay until the crtc is activated. */
2516
2517 free(red);
2518
2519 return TRUE1;
2520}
2521
2522static Bool
2523xf86OutputSetInitialGamma(xf86OutputPtr output)
2524{
2525 XF86ConfMonitorPtr mon = output->conf_monitor;
2526 float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0;
2527
2528 if (!mon)
2529 return TRUE1;
2530
2531 if (!output->crtc)
2532 return FALSE0;
2533
2534 /* Get configured values, where they exist. */
2535 if (mon->mon_gamma_red >= GAMMA_MIN(1.0 / 10.0) && mon->mon_gamma_red <= GAMMA_MAX10.0)
2536 gamma_red = mon->mon_gamma_red;
2537
2538 if (mon->mon_gamma_green >= GAMMA_MIN(1.0 / 10.0) && mon->mon_gamma_green <= GAMMA_MAX10.0)
2539 gamma_green = mon->mon_gamma_green;
2540
2541 if (mon->mon_gamma_blue >= GAMMA_MIN(1.0 / 10.0) && mon->mon_gamma_blue <= GAMMA_MAX10.0)
2542 gamma_blue = mon->mon_gamma_blue;
2543
2544 /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */
2545 if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) {
2546 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
2547 "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n",
2548 output->name, gamma_red, gamma_green, gamma_blue);
2549 return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green,
2550 gamma_blue);
2551 }
2552 else
2553 return TRUE1;
2554}
2555
2556/**
2557 * Construct default screen configuration
2558 *
2559 * Given auto-detected (and, eventually, configured) values,
2560 * construct a usable configuration for the system
2561 *
2562 * canGrow indicates that the driver can resize the screen to larger than its
2563 * initially configured size via the config->funcs->resize hook. If TRUE, this
2564 * function will set virtualX and virtualY to match the initial configuration
2565 * and leave config->max{Width,Height} alone. If FALSE, it will bloat
2566 * virtual[XY] to include the largest modes and set config->max{Width,Height}
2567 * accordingly.
2568 */
2569
2570Bool
2571xf86InitialConfiguration(ScrnInfoPtr scrn, Bool canGrow)
2572{
2573 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
2574 int o, c;
2575 xf86CrtcPtr *crtcs;
2576 DisplayModePtr *modes;
2577 Bool *enabled;
2578 int width, height;
2579 int i = scrn->scrnIndex;
2580 Bool have_outputs = TRUE1;
2581 Bool ret;
2582 Bool success = FALSE0;
2583
2584 /* Set up the device options */
2585 config->options = xnfalloc(sizeof(xf86DeviceOptions))XNFalloc((unsigned long)(sizeof(xf86DeviceOptions)));
2586 memcpy(config->options, xf86DeviceOptions, sizeof(xf86DeviceOptions))__builtin___memcpy_chk (config->options, xf86DeviceOptions
, sizeof(xf86DeviceOptions), __builtin_object_size (config->
options, 0))
;
2587 xf86ProcessOptions(scrn->scrnIndex, scrn->options, config->options);
2588 config->debug_modes = xf86ReturnOptValBool(config->options,
2589 OPTION_MODEDEBUG, FALSE0);
2590
2591 if (scrn->display->virtualX && !scrn->is_gpu)
2592 width = scrn->display->virtualX;
2593 else
2594 width = config->maxWidth;
2595 if (scrn->display->virtualY && !scrn->is_gpu)
2596 height = scrn->display->virtualY;
2597 else
2598 height = config->maxHeight;
2599
2600 xf86ProbeOutputModes(scrn, width, height);
2601
2602 crtcs = xnfcalloc(config->num_output, sizeof(xf86CrtcPtr))XNFcallocarray((config->num_output), (sizeof(xf86CrtcPtr))
)
;
2603 modes = xnfcalloc(config->num_output, sizeof(DisplayModePtr))XNFcallocarray((config->num_output), (sizeof(DisplayModePtr
)))
;
2604 enabled = xnfcalloc(config->num_output, sizeof(Bool))XNFcallocarray((config->num_output), (sizeof(Bool)));
2605
2606 ret = xf86CollectEnabledOutputs(scrn, config, enabled);
2607 if (ret == FALSE0 && canGrow) {
2608 if (!scrn->is_gpu)
2609 xf86DrvMsg(i, X_WARNING,
2610 "Unable to find connected outputs - setting %dx%d "
2611 "initial framebuffer\n",
2612 NO_OUTPUT_DEFAULT_WIDTH1024, NO_OUTPUT_DEFAULT_HEIGHT768);
2613 have_outputs = FALSE0;
2614 }
2615 else {
2616 if (xf86TargetUserpref(scrn, config, modes, enabled, width, height))
2617 xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n");
2618 else if (xf86TargetRightOf(scrn, config, modes, enabled, width, height))
2619 xf86DrvMsg(i, X_INFO, "Using spanning desktop for initial modes\n");
2620 else if (xf86TargetPreferred
2621 (scrn, config, modes, enabled, width, height))
2622 xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n");
2623 else if (xf86TargetAspect(scrn, config, modes, enabled, width, height))
2624 xf86DrvMsg(i, X_INFO,
2625 "Using fuzzy aspect match for initial modes\n");
2626 else if (xf86TargetFallback
2627 (scrn, config, modes, enabled, width, height))
2628 xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n");
2629 else
2630 xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n");
2631 }
2632
2633 for (o = -1; nextEnabledOutput(config, enabled, &o);) {
2634 if (!modes[o])
2635 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2636 "Output %s enabled but has no modes\n",
2637 config->output[o]->name);
2638 else
2639 xf86DrvMsg (scrn->scrnIndex, X_INFO,
2640 "Output %s using initial mode %s +%d+%d\n",
2641 config->output[o]->name, modes[o]->name,
2642 config->output[o]->initial_x,
2643 config->output[o]->initial_y);
2644 }
2645
2646 /*
2647 * Set the position of each output
2648 */
2649 if (!xf86InitialOutputPositions(scrn, modes))
2650 goto bailout;
2651
2652 /*
2653 * Set initial panning of each output
2654 */
2655 xf86InitialPanning(scrn);
2656
2657 /*
2658 * Assign CRTCs to fit output configuration
2659 */
2660 if (have_outputs && !xf86PickCrtcs(scrn, crtcs, modes, 0, width, height))
2661 goto bailout;
2662
2663 /* XXX override xf86 common frame computation code */
2664
2665 if (!scrn->is_gpu) {
2666 scrn->display->frameX0 = 0;
2667 scrn->display->frameY0 = 0;
2668 }
2669
2670 for (c = 0; c < config->num_crtc; c++) {
2671 xf86CrtcPtr crtc = config->crtc[c];
2672
2673 crtc->enabled = FALSE0;
2674 memset(&crtc->desiredMode, '\0', sizeof(crtc->desiredMode))__builtin___memset_chk (&crtc->desiredMode, '\0', sizeof
(crtc->desiredMode), __builtin_object_size (&crtc->
desiredMode, 0))
;
2675 /* Set default gamma for all crtc's. */
2676 /* This is done to avoid problems later on with cloned outputs. */
2677 xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0);
2678 }
2679
2680 if (xf86_crtc_supports_gamma(scrn))
2681 xf86DrvMsg(scrn->scrnIndex, X_INFO,
2682 "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n");
2683
2684 /*
2685 * Set initial configuration
2686 */
2687 for (o = 0; o < config->num_output; o++) {
2688 xf86OutputPtr output = config->output[o];
2689 DisplayModePtr mode = modes[o];
2690 xf86CrtcPtr crtc = crtcs[o];
2691
2692 if (mode && crtc) {
2693 xf86SaveModeContents(&crtc->desiredMode, mode);
2694 crtc->desiredRotation = output->initial_rotation;
2695 crtc->desiredX = output->initial_x;
2696 crtc->desiredY = output->initial_y;
2697 crtc->desiredTransformPresent = FALSE0;
2698 crtc->enabled = TRUE1;
2699 memcpy(&crtc->panningTotalArea, &output->initialTotalArea,__builtin___memcpy_chk (&crtc->panningTotalArea, &
output->initialTotalArea, sizeof(BoxRec), __builtin_object_size
(&crtc->panningTotalArea, 0))
2700 sizeof(BoxRec))__builtin___memcpy_chk (&crtc->panningTotalArea, &
output->initialTotalArea, sizeof(BoxRec), __builtin_object_size
(&crtc->panningTotalArea, 0))
;
2701 memcpy(&crtc->panningTrackingArea, &output->initialTrackingArea,__builtin___memcpy_chk (&crtc->panningTrackingArea, &
output->initialTrackingArea, sizeof(BoxRec), __builtin_object_size
(&crtc->panningTrackingArea, 0))
2702 sizeof(BoxRec))__builtin___memcpy_chk (&crtc->panningTrackingArea, &
output->initialTrackingArea, sizeof(BoxRec), __builtin_object_size
(&crtc->panningTrackingArea, 0))
;
2703 memcpy(crtc->panningBorder, output->initialBorder,__builtin___memcpy_chk (crtc->panningBorder, output->initialBorder
, 4 * sizeof(INT16), __builtin_object_size (crtc->panningBorder
, 0))
2704 4 * sizeof(INT16))__builtin___memcpy_chk (crtc->panningBorder, output->initialBorder
, 4 * sizeof(INT16), __builtin_object_size (crtc->panningBorder
, 0))
;
2705 output->crtc = crtc;
2706 if (!xf86OutputSetInitialGamma(output))
2707 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2708 "Initial gamma correction for output %s: failed.\n",
2709 output->name);
2710 }
2711 else {
2712 output->crtc = NULL((void*)0);
2713 }
2714 }
2715
2716 if (scrn->display->virtualX == 0 || scrn->is_gpu) {
2717 /*
2718 * Expand virtual size to cover the current config and potential mode
2719 * switches, if the driver can't enlarge the screen later.
2720 */
2721 xf86DefaultScreenLimits(scrn, &width, &height, canGrow);
2722
2723 if (have_outputs == FALSE0) {
2724 if (width < NO_OUTPUT_DEFAULT_WIDTH1024 &&
2725 height < NO_OUTPUT_DEFAULT_HEIGHT768) {
2726 width = NO_OUTPUT_DEFAULT_WIDTH1024;
2727 height = NO_OUTPUT_DEFAULT_HEIGHT768;
2728 }
2729 }
2730
2731 if (!scrn->is_gpu) {
2732 scrn->display->virtualX = width;
2733 scrn->display->virtualY = height;
2734 }
2735 }
2736
2737 if (width > scrn->virtualX)
2738 scrn->virtualX = width;
2739 if (height > scrn->virtualY)
2740 scrn->virtualY = height;
2741
2742 /*
2743 * Make sure the configuration isn't too small.
2744 */
2745 if (width < config->minWidth || height < config->minHeight)
2746 goto bailout;
2747
2748 /*
2749 * Limit the crtc config to virtual[XY] if the driver can't grow the
2750 * desktop.
2751 */
2752 if (!canGrow) {
2753 xf86CrtcSetSizeRange(scrn, config->minWidth, config->minHeight,
2754 width, height);
2755 }
2756
2757 xf86SetScrnInfoModes(scrn);
2758
2759 success = TRUE1;
2760 bailout:
2761 free(crtcs);
2762 free(modes);
2763 free(enabled);
2764 return success;
2765}
2766
2767/*
2768 * Check the CRTC we're going to map each output to vs. it's current
2769 * CRTC. If they don't match, we have to disable the output and the CRTC
2770 * since the driver will have to re-route things.
2771 */
2772static void
2773xf86PrepareOutputs(ScrnInfoPtr scrn)
2774{
2775 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
2776 int o;
2777
2778 for (o = 0; o < config->num_output; o++) {
2779 xf86OutputPtr output = config->output[o];
2780
2781#if RANDR_GET_CRTC_INTERFACE1
2782 /* Disable outputs that are unused or will be re-routed */
2783 if (!output->funcs->get_crtc ||
2784 output->crtc != (*output->funcs->get_crtc) (output) ||
2785 output->crtc == NULL((void*)0))
2786#endif
2787 (*output->funcs->dpms) (output, DPMSModeOff3);
2788 }
2789}
2790
2791static void
2792xf86PrepareCrtcs(ScrnInfoPtr scrn)
2793{
2794 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
2795 int c;
2796
2797 for (c = 0; c < config->num_crtc; c++) {
2798#if RANDR_GET_CRTC_INTERFACE1
2799 xf86CrtcPtr crtc = config->crtc[c];
2800 xf86OutputPtr output = NULL((void*)0);
2801 uint32_t desired_outputs = 0, current_outputs = 0;
2802 int o;
2803
2804 for (o = 0; o < config->num_output; o++) {
2805 output = config->output[o];
2806 if (output->crtc == crtc)
2807 desired_outputs |= (1 << o);
2808 /* If we can't tell where it's mapped, force it off */
2809 if (!output->funcs->get_crtc) {
2810 desired_outputs = 0;
2811 break;
2812 }
2813 if ((*output->funcs->get_crtc) (output) == crtc)
2814 current_outputs |= (1 << o);
2815 }
2816
2817 /*
2818 * If mappings are different or the CRTC is unused,
2819 * we need to disable it
2820 */
2821 if (desired_outputs != current_outputs || !desired_outputs)
2822 (*crtc->funcs->dpms) (crtc, DPMSModeOff3);
2823#else
2824 (*crtc->funcs->dpms) (crtc, DPMSModeOff3);
2825#endif
2826 }
2827}
2828
2829/*
2830 * Using the desired mode information in each crtc, set
2831 * modes (used in EnterVT functions, or at server startup)
2832 */
2833
2834Bool
2835xf86SetDesiredModes(ScrnInfoPtr scrn)
2836{
2837 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
2838 xf86CrtcPtr crtc = config->crtc[0];
2839 int enabled = 0, failed = 0;
2840 int c;
2841
2842 /* A driver with this hook will take care of this */
2843 if (!crtc->funcs->set_mode_major) {
2844 xf86PrepareOutputs(scrn);
2845 xf86PrepareCrtcs(scrn);
2846 }
2847
2848 for (c = 0; c < config->num_crtc; c++) {
2849 xf86OutputPtr output = NULL((void*)0);
2850 int o;
2851 RRTransformPtr transform;
2852
2853 crtc = config->crtc[c];
2854
2855 /* Skip disabled CRTCs */
2856 if (!crtc->enabled)
2857 continue;
2858
2859 if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc)
2860 output = xf86CompatOutput(scrn);
2861 else {
2862 for (o = 0; o < config->num_output; o++)
2863 if (config->output[o]->crtc == crtc) {
2864 output = config->output[o];
2865 break;
2866 }
2867 }
2868 /* paranoia */
2869 if (!output)
2870 continue;
2871
2872 /* Mark that we'll need to re-set the mode for sure */
2873 memset(&crtc->mode, 0, sizeof(crtc->mode))__builtin___memset_chk (&crtc->mode, 0, sizeof(crtc->
mode), __builtin_object_size (&crtc->mode, 0))
;
2874 if (!crtc->desiredMode.CrtcHDisplay) {
2875 DisplayModePtr mode =
2876 xf86OutputFindClosestMode(output, scrn->currentMode);
2877
2878 if (!mode)
2879 return FALSE0;
2880 xf86SaveModeContents(&crtc->desiredMode, mode);
2881 crtc->desiredRotation = RR_Rotate_01;
2882 crtc->desiredTransformPresent = FALSE0;
2883 crtc->desiredX = 0;
2884 crtc->desiredY = 0;
2885 }
2886
2887 if (crtc->desiredTransformPresent)
2888 transform = &crtc->desiredTransform;
2889 else
2890 transform = NULL((void*)0);
2891 if (xf86CrtcSetModeTransform
2892 (crtc, &crtc->desiredMode, crtc->desiredRotation, transform,
2893 crtc->desiredX, crtc->desiredY)) {
2894 ++enabled;
2895 } else {
2896 for (o = 0; o < config->num_output; o++)
2897 if (config->output[o]->crtc == crtc)
2898 config->output[o]->crtc = NULL((void*)0);
2899 crtc->enabled = FALSE0;
2900 ++failed;
2901 }
2902 }
2903
2904 xf86DisableUnusedFunctions(scrn);
2905 return enabled != 0 || failed == 0;
2906}
2907
2908/**
2909 * In the current world order, there are lists of modes per output, which may
2910 * or may not include the mode that was asked to be set by XFree86's mode
2911 * selection. Find the closest one, in the following preference order:
2912 *
2913 * - Equality
2914 * - Closer in size to the requested mode, but no larger
2915 * - Closer in refresh rate to the requested mode.
2916 */
2917
2918DisplayModePtr
2919xf86OutputFindClosestMode(xf86OutputPtr output, DisplayModePtr desired)
2920{
2921 DisplayModePtr best = NULL((void*)0), scan = NULL((void*)0);
2922
2923 for (scan = output->probed_modes; scan != NULL((void*)0); scan = scan->next) {
2924 /* If there's an exact match, we're done. */
2925 if (xf86ModesEqual(scan, desired)) {
2926 best = desired;
2927 break;
2928 }
2929
2930 /* Reject if it's larger than the desired mode. */
2931 if (scan->HDisplay > desired->HDisplay ||
2932 scan->VDisplay > desired->VDisplay) {
2933 continue;
2934 }
2935
2936 /*
2937 * If we haven't picked a best mode yet, use the first
2938 * one in the size range
2939 */
2940 if (best == NULL((void*)0)) {
2941 best = scan;
2942 continue;
2943 }
2944
2945 /* Find if it's closer to the right size than the current best
2946 * option.
2947 */
2948 if ((scan->HDisplay > best->HDisplay &&
2949 scan->VDisplay >= best->VDisplay) ||
2950 (scan->HDisplay >= best->HDisplay &&
2951 scan->VDisplay > best->VDisplay)) {
2952 best = scan;
2953 continue;
2954 }
2955
2956 /* Find if it's still closer to the right refresh than the current
2957 * best resolution.
2958 */
2959 if (scan->HDisplay == best->HDisplay &&
2960 scan->VDisplay == best->VDisplay &&
2961 (fabs(scan->VRefresh - desired->VRefresh) <
2962 fabs(best->VRefresh - desired->VRefresh))) {
2963 best = scan;
2964 }
2965 }
2966 return best;
2967}
2968
2969/**
2970 * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
2971 * take the specified mode and apply it to the crtc connected to the compat
2972 * output. Then, find similar modes for the other outputs, as with the
2973 * InitialConfiguration code above. The goal is to clone the desired
2974 * mode across all outputs that are currently active.
2975 */
2976
2977Bool
2978xf86SetSingleMode(ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
2979{
2980 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
2981 Bool ok = TRUE1;
2982 xf86OutputPtr compat_output;
2983 DisplayModePtr compat_mode = NULL((void*)0);
2984 int c;
2985
2986 /*
2987 * Let the compat output drive the final mode selection
2988 */
2989 compat_output = xf86CompatOutput(pScrn);
2990 if (compat_output)
2991 compat_mode = xf86OutputFindClosestMode(compat_output, desired);
2992 if (compat_mode)
2993 desired = compat_mode;
2994
2995 for (c = 0; c < config->num_crtc; c++) {
2996 xf86CrtcPtr crtc = config->crtc[c];
2997 DisplayModePtr crtc_mode = NULL((void*)0);
2998 int o;
2999
3000 if (!crtc->enabled)
3001 continue;
3002
3003 for (o = 0; o < config->num_output; o++) {
3004 xf86OutputPtr output = config->output[o];
3005 DisplayModePtr output_mode;
3006
3007 /* skip outputs not on this crtc */
3008 if (output->crtc != crtc)
3009 continue;
3010
3011 if (crtc_mode) {
3012 output_mode = xf86OutputFindClosestMode(output, crtc_mode);
3013 if (output_mode != crtc_mode)
3014 output->crtc = NULL((void*)0);
3015 }
3016 else
3017 crtc_mode = xf86OutputFindClosestMode(output, desired);
3018 }
3019 if (!crtc_mode) {
3020 crtc->enabled = FALSE0;
3021 continue;
3022 }
3023 if (!xf86CrtcSetModeTransform(crtc, crtc_mode, rotation, NULL((void*)0), 0, 0))
3024 ok = FALSE0;
3025 else {
3026 xf86SaveModeContents(&crtc->desiredMode, crtc_mode);
3027 crtc->desiredRotation = rotation;
3028 crtc->desiredTransformPresent = FALSE0;
3029 crtc->desiredX = 0;
3030 crtc->desiredY = 0;
3031 }
3032 }
3033 xf86DisableUnusedFunctions(pScrn);
3034#ifdef RANDR_12_INTERFACE1
3035 xf86RandR12TellChanged(pScrn->pScreen);
3036#endif
3037 return ok;
3038}
3039
3040/**
3041 * Set the DPMS power mode of all outputs and CRTCs.
3042 *
3043 * If the new mode is off, it will turn off outputs and then CRTCs.
3044 * Otherwise, it will affect CRTCs before outputs.
3045 */
3046void
3047xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
3048{
3049 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3050 int i;
3051
3052 if (!scrn->vtSema)
3053 return;
3054
3055 if (mode == DPMSModeOff3) {
3056 for (i = 0; i < config->num_output; i++) {
3057 xf86OutputPtr output = config->output[i];
3058
3059 if (output->crtc != NULL((void*)0))
3060 (*output->funcs->dpms) (output, mode);
3061 }
3062 }
3063
3064 for (i = 0; i < config->num_crtc; i++) {
3065 xf86CrtcPtr crtc = config->crtc[i];
3066
3067 if (crtc->enabled)
3068 (*crtc->funcs->dpms) (crtc, mode);
3069 }
3070
3071 if (mode != DPMSModeOff3) {
3072 for (i = 0; i < config->num_output; i++) {
3073 xf86OutputPtr output = config->output[i];
3074
3075 if (output->crtc != NULL((void*)0))
3076 (*output->funcs->dpms) (output, mode);
3077 }
3078 }
3079}
3080
3081/**
3082 * Implement the screensaver by just calling down into the driver DPMS hooks.
3083 *
3084 * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
3085 * the outputs will still get disabled (blanked).
3086 */
3087Bool
3088xf86SaveScreen(ScreenPtr pScreen, int mode)
3089{
3090 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3091
3092 if (xf86IsUnblank(mode))
3093 xf86DPMSSet(pScrn, DPMSModeOn0, 0);
3094 else
3095 xf86DPMSSet(pScrn, DPMSModeOff3, 0);
3096
3097 return TRUE1;
3098}
3099
3100/**
3101 * Disable all inactive crtcs and outputs
3102 */
3103void
3104xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
3105{
3106 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3107 int o, c;
3108
3109 for (o = 0; o < xf86_config->num_output; o++) {
3110 xf86OutputPtr output = xf86_config->output[o];
3111
3112 if (!output->crtc)
3113 (*output->funcs->dpms) (output, DPMSModeOff3);
3114 }
3115
3116 for (c = 0; c < xf86_config->num_crtc; c++) {
3117 xf86CrtcPtr crtc = xf86_config->crtc[c];
3118
3119 if (!crtc->enabled) {
3120 crtc->funcs->dpms(crtc, DPMSModeOff3);
3121 memset(&crtc->mode, 0, sizeof(crtc->mode))__builtin___memset_chk (&crtc->mode, 0, sizeof(crtc->
mode), __builtin_object_size (&crtc->mode, 0))
;
3122 xf86RotateDestroy(crtc);
3123 crtc->active = FALSE0;
3124 }
3125 }
3126 if (pScrn->pScreen)
3127 xf86_crtc_notify(pScrn->pScreen);
3128 if (pScrn->ModeSet)
3129 pScrn->ModeSet(pScrn);
3130 if (pScrn->pScreen) {
3131 if (pScrn->pScreen->isGPU)
3132 xf86CursorResetCursor(pScrn->pScreen->current_master);
3133 else
3134 xf86CursorResetCursor(pScrn->pScreen);
3135 }
3136}
3137
3138#ifdef RANDR_12_INTERFACE1
3139
3140#define EDID_ATOM_NAME"EDID" "EDID"
3141
3142/**
3143 * Set the RandR EDID property
3144 */
3145static void
3146xf86OutputSetEDIDProperty(xf86OutputPtr output, void *data, int data_len)
3147{
3148 Atom edid_atom = MakeAtom(EDID_ATOM_NAME"EDID", sizeof(EDID_ATOM_NAME"EDID") - 1, TRUE1);
3149
3150 /* This may get called before the RandR resources have been created */
3151 if (output->randr_output == NULL((void*)0))
3152 return;
3153
3154 if (data_len != 0) {
3155 RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER((Atom) 19), 8,
3156 PropModeReplace0, data_len, data, FALSE0, TRUE1);
3157 }
3158 else {
3159 RRDeleteOutputProperty(output->randr_output, edid_atom);
3160 }
3161}
3162
3163#define TILE_ATOM_NAME"TILE" "TILE"
3164/* changing this in the future could be tricky as people may hardcode 8 */
3165#define TILE_PROP_NUM_ITEMS8 8
3166static void
3167xf86OutputSetTileProperty(xf86OutputPtr output)
3168{
3169 Atom tile_atom = MakeAtom(TILE_ATOM_NAME"TILE", sizeof(TILE_ATOM_NAME"TILE") - 1, TRUE1);
3170
3171 /* This may get called before the RandR resources have been created */
3172 if (output->randr_output == NULL((void*)0))
3173 return;
3174
3175 if (output->tile_info.group_id != 0) {
3176 RRChangeOutputProperty(output->randr_output, tile_atom, XA_INTEGER((Atom) 19), 32,
3177 PropModeReplace0, TILE_PROP_NUM_ITEMS8, (uint32_t *)&output->tile_info, FALSE0, TRUE1);
3178 }
3179 else {
3180 RRDeleteOutputProperty(output->randr_output, tile_atom);
3181 }
3182}
3183
3184#endif
3185
3186/* Pull out a phyiscal size from a detailed timing if available. */
3187struct det_phySize_parameter {
3188 xf86OutputPtr output;
3189 ddc_quirk_t quirks;
3190 Bool ret;
3191};
3192
3193static void
3194handle_detailed_physical_size(struct detailed_monitor_section
3195 *det_mon, void *data)
3196{
3197 struct det_phySize_parameter *p;
3198
3199 p = (struct det_phySize_parameter *) data;
3200
3201 if (p->ret == TRUE1)
3202 return;
3203
3204 xf86DetTimingApplyQuirks(det_mon, p->quirks,
3205 p->output->MonInfo->features.hsize,
3206 p->output->MonInfo->features.vsize);
3207 if (det_mon->type == DT0 &&
3208 det_mon->section.d_timings.h_size != 0 &&
3209 det_mon->section.d_timings.v_size != 0) {
3210 /* some sanity checking for aspect ratio:
3211 assume any h / v (or v / h) > 2.4 to be bogus.
3212 This would even include cinemascope */
3213 if (((det_mon->section.d_timings.h_size * 5) <
3214 (det_mon->section.d_timings.v_size * 12)) &&
3215 ((det_mon->section.d_timings.v_size * 5) <
3216 (det_mon->section.d_timings.h_size * 12))) {
3217 p->output->mm_width = det_mon->section.d_timings.h_size;
3218 p->output->mm_height = det_mon->section.d_timings.v_size;
3219 p->ret = TRUE1;
3220 } else
3221 xf86DrvMsg(p->output->scrn->scrnIndex, X_WARNING,
3222 "Output %s: Strange aspect ratio (%i/%i), "
3223 "consider adding a quirk\n", p->output->name,
3224 det_mon->section.d_timings.h_size,
3225 det_mon->section.d_timings.v_size);
3226 }
3227}
3228
3229Bool
3230xf86OutputParseKMSTile(const char *tile_data, int tile_length,
3231 struct xf86CrtcTileInfo *tile_info)
3232{
3233 int ret;
3234
3235 ret = sscanf(tile_data, "%d:%d:%d:%d:%d:%d:%d:%d",
3236 &tile_info->group_id,
3237 &tile_info->flags,
3238 &tile_info->num_h_tile,
3239 &tile_info->num_v_tile,
3240 &tile_info->tile_h_loc,
3241 &tile_info->tile_v_loc,
3242 &tile_info->tile_h_size,
3243 &tile_info->tile_v_size);
3244 if (ret != 8)
3245 return FALSE0;
3246 return TRUE1;
3247}
3248
3249void
3250xf86OutputSetTile(xf86OutputPtr output, struct xf86CrtcTileInfo *tile_info)
3251{
3252 if (tile_info)
3253 output->tile_info = *tile_info;
3254 else
3255 memset(&output->tile_info, 0, sizeof(output->tile_info))__builtin___memset_chk (&output->tile_info, 0, sizeof(
output->tile_info), __builtin_object_size (&output->
tile_info, 0))
;
3256#ifdef RANDR_12_INTERFACE1
3257 xf86OutputSetTileProperty(output);
3258#endif
3259}
3260
3261/**
3262 * Set the EDID information for the specified output
3263 */
3264void
3265xf86OutputSetEDID(xf86OutputPtr output, xf86MonPtr edid_mon)
3266{
3267 ScrnInfoPtr scrn = output->scrn;
3268 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3269 Bool debug_modes = config->debug_modes || xf86Initialising;
3270
3271#ifdef RANDR_12_INTERFACE1
3272 int size;
3273#endif
3274
3275 free(output->MonInfo);
3276
3277 output->MonInfo = edid_mon;
3278 output->mm_width = 0;
3279 output->mm_height = 0;
3280
3281 if (debug_modes) {
3282 xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n",
3283 output->name);
3284 xf86PrintEDID(edid_mon);
3285 }
3286
3287 /* Set the DDC properties for the 'compat' output */
3288 if (output == xf86CompatOutput(scrn))
3289 xf86SetDDCproperties(scrn, edid_mon);
3290
3291#ifdef RANDR_12_INTERFACE1
3292 /* Set the RandR output properties */
3293 size = 0;
3294 if (edid_mon) {
3295 if (edid_mon->ver.version == 1) {
3296 size = 128;
3297 if (edid_mon->flags & EDID_COMPLETE_RAWDATA0x01)
3298 size += edid_mon->no_sections * 128;
3299 }
3300 else if (edid_mon->ver.version == 2)
3301 size = 256;
3302 }
3303 xf86OutputSetEDIDProperty(output, edid_mon ? edid_mon->rawData : NULL((void*)0),
3304 size);
3305#endif
3306
3307 if (edid_mon) {
3308
3309 struct det_phySize_parameter p;
3310
3311 p.output = output;
3312 p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex, edid_mon, FALSE0);
3313 p.ret = FALSE0;
3314 xf86ForEachDetailedBlock(edid_mon, handle_detailed_physical_size, &p);
3315
3316 /* if no mm size is available from a detailed timing, check the max size field */
3317 if ((!output->mm_width || !output->mm_height) &&
3318 (edid_mon->features.hsize && edid_mon->features.vsize)) {
3319 output->mm_width = edid_mon->features.hsize * 10;
3320 output->mm_height = edid_mon->features.vsize * 10;
3321 }
3322 }
3323}
3324
3325/**
3326 * Return the list of modes supported by the EDID information
3327 * stored in 'output'
3328 */
3329DisplayModePtr
3330xf86OutputGetEDIDModes(xf86OutputPtr output)
3331{
3332 ScrnInfoPtr scrn = output->scrn;
3333 xf86MonPtr edid_mon = output->MonInfo;
3334
3335 if (!edid_mon)
3336 return NULL((void*)0);
3337 return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
3338}
3339
3340/* maybe we should care about DDC1? meh. */
3341xf86MonPtr
3342xf86OutputGetEDID(xf86OutputPtr output, I2CBusPtr pDDCBus)
3343{
3344 ScrnInfoPtr scrn = output->scrn;
3345 xf86MonPtr mon;
3346
3347 mon = xf86DoEEDID(scrn, pDDCBus, TRUE1);
3348 if (mon)
3349 xf86DDCApplyQuirks(scrn->scrnIndex, mon);
3350
3351 return mon;
3352}
3353
3354static const char *_xf86ConnectorNames[] = {
3355 "None", "VGA", "DVI-I", "DVI-D",
3356 "DVI-A", "Composite", "S-Video",
3357 "Component", "LFP", "Proprietary",
3358 "HDMI", "DisplayPort",
3359};
3360
3361const char *
3362xf86ConnectorGetName(xf86ConnectorType connector)
3363{
3364 return _xf86ConnectorNames[connector];
3365}
3366
3367static void
3368x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
3369{
3370 dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
3371 dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
3372 dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
3373 dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
3374
3375 if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
3376 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
3377}
3378
3379static void
3380x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
3381{
3382 if (crtc->enabled) {
3383 crtc_box->x1 = crtc->x;
3384 crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
3385 crtc_box->y1 = crtc->y;
3386 crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
3387 }
3388 else
3389 crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
3390}
3391
3392static int
3393xf86_crtc_box_area(BoxPtr box)
3394{
3395 return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
3396}
3397
3398#ifdef XV1
3399/*
3400 * Return the crtc covering 'box'. If two crtcs cover a portion of
3401 * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
3402 * with greater coverage
3403 */
3404
3405static xf86CrtcPtr
3406xf86_covering_crtc(ScrnInfoPtr pScrn,
3407 BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret)
3408{
3409 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3410 xf86CrtcPtr crtc, best_crtc;
3411 int coverage, best_coverage;
3412 int c;
3413 BoxRec crtc_box, cover_box;
3414
3415 best_crtc = NULL((void*)0);
3416 best_coverage = 0;
3417 crtc_box_ret->x1 = 0;
3418 crtc_box_ret->x2 = 0;
3419 crtc_box_ret->y1 = 0;
3420 crtc_box_ret->y2 = 0;
3421 for (c = 0; c < xf86_config->num_crtc; c++) {
3422 crtc = xf86_config->crtc[c];
3423 x86_crtc_box(crtc, &crtc_box);
3424 x86_crtc_box_intersect(&cover_box, &crtc_box, box);
3425 coverage = xf86_crtc_box_area(&cover_box);
3426 if (coverage && crtc == desired) {
3427 *crtc_box_ret = crtc_box;
3428 return crtc;
3429 }
3430 else if (coverage > best_coverage) {
3431 *crtc_box_ret = crtc_box;
3432 best_crtc = crtc;
3433 best_coverage = coverage;
3434 }
3435 }
3436 return best_crtc;
3437}
3438
3439/*
3440 * For overlay video, compute the relevant CRTC and
3441 * clip video to that.
3442 *
3443 * returning FALSE means there was a memory failure of some kind,
3444 * not that the video shouldn't be displayed
3445 */
3446
3447Bool
3448xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
3449 xf86CrtcPtr * crtc_ret,
3450 xf86CrtcPtr desired_crtc,
3451 BoxPtr dst,
3452 INT32 *xa,
3453 INT32 *xb,
3454 INT32 *ya,
3455 INT32 *yb, RegionPtr reg, INT32 width, INT32 height)
3456{
3457 Bool ret;
3458 RegionRec crtc_region_local;
3459 RegionPtr crtc_region = reg;
3460
3461 if (crtc_ret) {
3462 BoxRec crtc_box;
3463 xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst,
3464 desired_crtc,
3465 &crtc_box);
3466
3467 if (crtc) {
3468 RegionInit(&crtc_region_local, &crtc_box, 1);
3469 crtc_region = &crtc_region_local;
3470 RegionIntersect(crtc_region, crtc_region, reg);
3471 }
3472 *crtc_ret = crtc;
3473 }
3474
3475 ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb,
3476 crtc_region, width, height);
3477
3478 if (crtc_region != reg)
3479 RegionUninit(&crtc_region_local);
3480
3481 return ret;
3482}
3483#endif
3484
3485xf86_crtc_notify_proc_ptr
3486xf86_wrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr new)
3487{
3488 if (xf86CrtcConfigPrivateIndex != -1) {
3489 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
3490 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3491 xf86_crtc_notify_proc_ptr old;
3492
3493 old = config->xf86_crtc_notify;
3494 config->xf86_crtc_notify = new;
3495 return old;
3496 }
3497 return NULL((void*)0);
3498}
3499
3500void
3501xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old)
3502{
3503 if (xf86CrtcConfigPrivateIndex != -1) {
3504 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
3505 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3506
3507 config->xf86_crtc_notify = old;
3508 }
3509}
3510
3511void
3512xf86_crtc_notify(ScreenPtr screen)
3513{
3514 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
3515 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3516
3517 if (config->xf86_crtc_notify)
3518 config->xf86_crtc_notify(screen);
3519}
3520
3521Bool
3522xf86_crtc_supports_gamma(ScrnInfoPtr pScrn)
3523{
3524 if (xf86CrtcConfigPrivateIndex != -1) {
3525 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn)((xf86CrtcConfigPtr) ((pScrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3526 xf86CrtcPtr crtc;
3527
3528 /* for multiple drivers loaded we need this */
3529 if (!xf86_config)
3530 return FALSE0;
3531 if (xf86_config->num_crtc == 0)
3532 return FALSE0;
3533 crtc = xf86_config->crtc[0];
3534
3535 return crtc->funcs->gamma_set != NULL((void*)0);
3536 }
3537
3538 return FALSE0;
3539}
3540
3541void
3542xf86ProviderSetup(ScrnInfoPtr scrn,
3543 const xf86ProviderFuncsRec *funcs, const char *name)
3544{
3545 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3546
3547 assert(!xf86_config->name)(__builtin_expect(!(!xf86_config->name), 0) ? __assert_rtn
(__func__, "xf86Crtc.c", 3547, "!xf86_config->name") : (void
)0)
;
3548 assert(name)(__builtin_expect(!(name), 0) ? __assert_rtn(__func__, "xf86Crtc.c"
, 3548, "name") : (void)0)
;
3549
3550 xf86_config->name = strdup(name);
3551 xf86_config->provider_funcs = funcs;
3552#ifdef RANDR_12_INTERFACE1
3553 xf86_config->randr_provider = NULL((void*)0);
3554#endif
3555}
3556
3557void
3558xf86DetachAllCrtc(ScrnInfoPtr scrn)
3559{
3560 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn)((xf86CrtcConfigPtr) ((scrn)->privates[xf86CrtcConfigPrivateIndex
].ptr))
;
3561 int i;
3562
3563 for (i = 0; i < xf86_config->num_crtc; i++) {
3564 xf86CrtcPtr crtc = xf86_config->crtc[i];
3565
3566 if (crtc->randr_crtc)
3567 RRCrtcDetachScanoutPixmap(crtc->randr_crtc);
3568
3569 /* dpms off */
3570 (*crtc->funcs->dpms) (crtc, DPMSModeOff3);
3571 /* force a reset the next time its used */
3572 crtc->randr_crtc->mode = NULL((void*)0);
3573 crtc->mode.HDisplay = 0;
3574 crtc->x = crtc->y = 0;
3575 }
3576}