2 * Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
7 #include <validate_display_mode.h>
12 //#define TRACE_VALIDATION
13 #ifdef TRACE_VALIDATION
17 void _sPrintf(const char *format
, ...);
18 # define TRACE(x...) _sPrintf("accelerant common: " x)
20 # define TRACE(x...) ;
23 #define ERROR(x...) _sPrintf("accelerant common: " x)
27 round(uint16 value
, uint16 resolution
)
29 return value
/ resolution
* resolution
;
34 sanitize_timing(uint16
& display
, uint16
& syncStart
, uint16
& syncEnd
,
35 uint16
& total
, const timing_constraints
& constraints
)
37 if (syncStart
< display
+ constraints
.min_before_sync
) {
38 TRACE("%s: syncStart(%" B_PRIu16
") < display(%" B_PRIu16
")"
39 " + min_before_sync(%" B_PRIu16
")\n", __func__
, syncStart
,
40 display
, constraints
.min_before_sync
);
41 syncStart
= display
+ constraints
.min_before_sync
;
42 } else if (syncStart
> constraints
.max_sync_start
) {
43 TRACE("%s: syncStart(%" B_PRIu16
") > max_sync_start(%" B_PRIu16
")\n",
44 __func__
, syncStart
, constraints
.max_sync_start
);
45 syncStart
= constraints
.max_sync_start
;
48 uint32 syncLength
= syncEnd
- syncStart
;
49 if (syncLength
< constraints
.min_sync_length
) {
50 TRACE("%s: syncLength(%" B_PRIu16
")"
51 " < min_sync_length(%" B_PRIu16
")\n",
52 __func__
, syncLength
, constraints
.min_sync_length
);
53 syncLength
= constraints
.min_sync_length
;
54 } else if (syncLength
> constraints
.max_sync_length
) {
55 TRACE("%s: syncLength(%" B_PRIu16
")"
56 " > max_sync_length(%" B_PRIu16
")\n",
57 __func__
, syncLength
, constraints
.max_sync_length
);
58 syncLength
= constraints
.max_sync_length
;
61 if (total
< syncStart
+ syncLength
+ constraints
.min_after_sync
) {
62 TRACE("%s: total(%" B_PRIu16
")"
63 " < syncStart(%" B_PRIu16
")"
64 " + syncLength(%" B_PRIu16
")"
65 " + min_after_sync(%" B_PRIu16
")\n",
66 __func__
, total
, syncStart
, syncLength
, constraints
.min_after_sync
);
67 total
= syncStart
+ syncLength
+ constraints
.min_after_sync
;
70 if (total
> constraints
.max_total
) {
71 TRACE("%s: total(%" B_PRIu16
") > max_total(%" B_PRIu16
")\n",
72 __func__
, total
, constraints
.max_total
);
73 total
= constraints
.max_total
;
74 syncLength
= min_c(syncLength
, uint16(total
- syncStart
));
77 syncEnd
= round(syncStart
+ syncLength
, constraints
.resolution
);
78 syncStart
= round(syncStart
, constraints
.resolution
);
79 display
= round(display
, constraints
.resolution
);
80 total
= round(total
, constraints
.resolution
);
84 /*! Makes sure the passed in \a mode fulfills the specified \a constraints.
85 Returns whether or not the mode had to be changed.
88 sanitize_display_mode(display_mode
& mode
,
89 const display_constraints
& constraints
, const edid1_info
* edid
)
91 display_mode originalMode
= mode
;
95 if (mode
.timing
.h_display
< constraints
.min_h_display
) {
96 TRACE("%s: h_display(%" B_PRIu16
") < min_h_display(%" B_PRIu16
")\n",
97 __func__
, mode
.timing
.h_display
, constraints
.min_h_display
);
98 mode
.timing
.h_display
= constraints
.min_h_display
;
99 } else if (mode
.timing
.h_display
> constraints
.max_h_display
) {
100 TRACE("%s: h_display(%" B_PRIu16
") > max_h_display(%" B_PRIu16
")\n",
101 __func__
, mode
.timing
.h_display
, constraints
.max_h_display
);
102 mode
.timing
.h_display
= constraints
.max_h_display
;
105 if (mode
.timing
.v_display
< constraints
.min_v_display
) {
106 TRACE("%s: v_display(%" B_PRIu16
") < min_v_display(%" B_PRIu16
")\n",
107 __func__
, mode
.timing
.v_display
, constraints
.min_v_display
);
108 mode
.timing
.v_display
= constraints
.min_v_display
;
109 } else if (mode
.timing
.v_display
> constraints
.max_v_display
) {
110 TRACE("%s: v_display(%" B_PRIu16
") > max_v_display(%" B_PRIu16
")\n",
111 __func__
, mode
.timing
.v_display
, constraints
.max_v_display
);
112 mode
.timing
.v_display
= constraints
.max_v_display
;
117 sanitize_timing(mode
.timing
.h_display
, mode
.timing
.h_sync_start
,
118 mode
.timing
.h_sync_end
, mode
.timing
.h_total
,
119 constraints
.horizontal_timing
);
123 sanitize_timing(mode
.timing
.v_display
, mode
.timing
.v_sync_start
,
124 mode
.timing
.v_sync_end
, mode
.timing
.v_total
,
125 constraints
.vertical_timing
);
127 // TODO: take EDID and pixel clock into account!
129 return memcmp(&mode
, &originalMode
, sizeof(display_mode
)) != 0;
134 is_display_mode_within_bounds(display_mode
& mode
, const display_mode
& low
,
135 const display_mode
& high
)
137 // Check horizontal timing
138 if (mode
.timing
.h_display
< low
.timing
.h_display
139 || mode
.timing
.h_display
> high
.timing
.h_display
140 || mode
.timing
.h_sync_start
< low
.timing
.h_sync_start
141 || mode
.timing
.h_sync_start
> high
.timing
.h_sync_start
142 || mode
.timing
.h_sync_end
< low
.timing
.h_sync_end
143 || mode
.timing
.h_sync_end
> high
.timing
.h_sync_end
144 || mode
.timing
.h_total
< low
.timing
.h_total
145 || mode
.timing
.h_total
> high
.timing
.h_total
)
148 // Check vertical timing
149 if (mode
.timing
.h_display
< low
.timing
.h_display
150 || mode
.timing
.h_display
> high
.timing
.h_display
151 || mode
.timing
.h_sync_start
< low
.timing
.h_sync_start
152 || mode
.timing
.h_sync_start
> high
.timing
.h_sync_start
153 || mode
.timing
.h_sync_end
< low
.timing
.h_sync_end
154 || mode
.timing
.h_sync_end
> high
.timing
.h_sync_end
155 || mode
.timing
.h_total
< low
.timing
.h_total
156 || mode
.timing
.h_total
> high
.timing
.h_total
)
160 if (mode
.timing
.pixel_clock
> high
.timing
.pixel_clock
161 || mode
.timing
.pixel_clock
< low
.timing
.pixel_clock
)
164 // Check horizontal size
165 if (mode
.virtual_width
> high
.virtual_width
166 || mode
.virtual_width
< low
.virtual_width
)
169 // Check vertical size
170 if (mode
.virtual_height
> high
.virtual_height
171 || mode
.virtual_height
< low
.virtual_height
)