vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / accelerants / common / validate_display_mode.cpp
blobdf3a2cb1f36bf21b1fb44a8b925c1223c6d62fa6
1 /*
2 * Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <validate_display_mode.h>
9 #include <string.h>
12 //#define TRACE_VALIDATION
13 #ifdef TRACE_VALIDATION
14 #ifdef __cplusplus
15 extern "C"
16 #endif
17 void _sPrintf(const char *format, ...);
18 # define TRACE(x...) _sPrintf("accelerant common: " x)
19 #else
20 # define TRACE(x...) ;
21 #endif
23 #define ERROR(x...) _sPrintf("accelerant common: " x)
26 static uint16
27 round(uint16 value, uint16 resolution)
29 return value / resolution * resolution;
33 static void
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.
87 bool
88 sanitize_display_mode(display_mode& mode,
89 const display_constraints& constraints, const edid1_info* edid)
91 display_mode originalMode = mode;
93 // size
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;
115 // horizontal timing
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);
121 // vertical 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;
133 bool
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)
146 return false;
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)
157 return false;
159 // Check pixel clock
160 if (mode.timing.pixel_clock > high.timing.pixel_clock
161 || mode.timing.pixel_clock < low.timing.pixel_clock)
162 return false;
164 // Check horizontal size
165 if (mode.virtual_width > high.virtual_width
166 || mode.virtual_width < low.virtual_width)
167 return false;
169 // Check vertical size
170 if (mode.virtual_height > high.virtual_height
171 || mode.virtual_height < low.virtual_height)
172 return false;
174 return true;