cgv
Loading...
Searching...
No Matches
display.cxx
1#include "display.h"
2
3#include <cgv/utils/convert.h>
4#include <iostream>
5
6#ifdef _MSC_VER
7#include <windows.h>
8#endif
9
10namespace cgv {
11 namespace os {
12
13std::string display::last_error;
14
15std::ostream& operator << (std::ostream& os, const display_mode& dm)
16{
17 return
18 os << dm.width << "x"
19 << dm.height << "x"
20 << dm.bit_depth<< "|"
21 << dm.refresh_rate << "Hz";
22}
23
24std::ostream& operator << (std::ostream& os, const display_position& dp)
25{
26 return os << dp.x << "," << dp.y;
27}
28
29std::ostream& operator << (std::ostream& os, const display_configuration& dc)
30{
31 return os << dc.mode << ":" << dc.position;
32}
33
34std::ostream& operator << (std::ostream& os, const display& disp)
35{
36 os << disp.get_name().c_str() << " ('" << disp.get_description().c_str()
37 << "' - " << disp.get_ID().c_str() << ")"
38 << (disp.is_primary()?" primary":"")
39 << (disp.is_active()?" attached":"")
40 << (disp.is_removable()?" removable":"")
41 << (disp.is_mirror()?" mirror":"") << "\n ";
42 if (disp.is_active())
43 os << disp.get_configuration() << " ";
44 os << "[" << disp.get_registered_mode() << "]";
45 return os;
46}
47
48#ifdef _MSC_VER
49class windows_display : public display
50{
51protected:
52 DISPLAY_DEVICE dd;
53 DEVMODE cdm, rdm;
54 unsigned int idx;
55public:
56 bool update_structures()
57 {
58 if (!EnumDisplayDevices(NULL,idx,&dd,0)) {
59 last_error = "could not enumerate device";
60 return false;
61 }
62 if (!EnumDisplaySettingsEx(dd.DeviceName, ENUM_REGISTRY_SETTINGS, &rdm, 0)) {
63 last_error = "could not query registry display settings";
64 return false;
65 }
66 if (is_active()) {
67 if (!EnumDisplaySettingsEx(dd.DeviceName, ENUM_CURRENT_SETTINGS, &cdm, 0)) {
68 last_error = "could not query current display settings";
69 return false;
70 }
71 }
72 return true;
73 }
74 static bool interpret_error(LONG result)
75 {
76 switch (result) {
77 case DISP_CHANGE_SUCCESSFUL:
78 break;
79 case DISP_CHANGE_BADFLAGS:
80 last_error = "An invalid set of flags was passed in.";
81 return false;
82 case DISP_CHANGE_BADMODE:
83 last_error = "The graphics mode is not supported.";
84 return false;
85 case DISP_CHANGE_BADPARAM:
86 last_error = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
87 return false;
88 case DISP_CHANGE_FAILED:
89 last_error = "The display driver failed the specified graphics mode.";
90 return false;
91 case DISP_CHANGE_NOTUPDATED:
92 last_error = "Windows NT/2000/XP: Unable to write settings to the registry.";
93 return false;
94 case DISP_CHANGE_RESTART:
95 last_error = "The computer must be restarted for the graphics mode to work.";
96 return false;
97 }
98 return true;
99 }
100 bool update_after_display_change(LONG result)
101 {
102 if (!interpret_error(result))
103 return false;
104 return update_structures();
105 }
107 void enumerate_display_modes(std::vector<display_mode>& display_modes, bool compatible_with_attached_monitor)
108 {
109 DEVMODE dm;
110 memset(&dm,0,sizeof(DEVMODE));
111 dm.dmSize = sizeof(DEVMODE);
112 dm.dmDriverExtra = 0;
113 unsigned int i = 0;
114 while (EnumDisplaySettingsEx(dd.DeviceName, i, &dm, compatible_with_attached_monitor?0:EDS_RAWMODE)) {
115 display_mode disp_mode;
116 disp_mode.width = dm.dmPelsWidth;
117 disp_mode.height = dm.dmPelsHeight;
118 disp_mode.bit_depth = dm.dmBitsPerPel;
119 disp_mode.refresh_rate = dm.dmDisplayFrequency;
120 display_modes.push_back(disp_mode);
121 ++i;
122 }
123 }
125 void show_display_modes(bool compatible_with_attached_monitor)
126 {
127 std::vector<display_mode> display_modes;
128 enumerate_display_modes(display_modes, compatible_with_attached_monitor);
129 for (unsigned int i = 0; i < display_modes.size(); ++i)
130 std::cout << "display mode " << i << ": " << display_modes[i] << std::endl;
131 }
132
133 windows_display()
134 {
135 memset(&dd,0,sizeof(DISPLAY_DEVICE));
136 dd.cb = sizeof(DISPLAY_DEVICE);
137 memset(&cdm,0,sizeof(DEVMODE));
138 cdm.dmSize = sizeof(DEVMODE);
139 memset(&rdm,0,sizeof(DEVMODE));
140 rdm.dmSize = sizeof(DEVMODE);
141 }
142 bool attach(unsigned int i)
143 {
144 idx = i;
145 return update_structures();
146 }
148 std::string get_name() const
149 {
150#ifdef UNICODE
151 return cgv::utils::wstr2str(dd.DeviceName);
152#else
153 return std::string(dd.DeviceName);
154#endif
155 }
157 std::string get_description() const
158 {
159#ifdef UNICODE
160 return cgv::utils::wstr2str(dd.DeviceString);
161#else
162 return std::string(dd.DeviceString);
163#endif
164 }
166 std::string get_ID() const
167 {
168#ifdef UNICODE
169 return cgv::utils::wstr2str(dd.DeviceID);
170#else
171 return std::string(dd.DeviceID);
172#endif
173 }
175 bool is_mirror() const
176 {
177 return (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) != 0;
178 }
180 bool is_removable() const
181 {
182 return (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE) != 0;
183 }
184
186 bool is_active() const
187 {
188 return (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0;
189 }
191 bool activate()
192 {
193 return update_after_display_change(ChangeDisplaySettingsEx(dd.DeviceName, NULL, NULL, 0, NULL));
194 }
196 bool check_activate() const
197 {
198 return interpret_error(ChangeDisplaySettingsEx(dd.DeviceName, NULL, NULL, CDS_TEST, NULL));
199 }
201 bool deactivate()
202 {
203 cdm.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT ;
204 cdm.dmPelsWidth = 0;
205 cdm.dmPelsHeight = 0;
206 return update_after_display_change(
207 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, CDS_UPDATEREGISTRY, NULL));
208 }
210 bool is_primary() const
211 {
212 return (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0;
213 }
215 bool make_primary()
216 {
217 return update_after_display_change(
218 ChangeDisplaySettingsEx(dd.DeviceName, NULL, NULL, CDS_UPDATEREGISTRY|CDS_SET_PRIMARY, NULL));
219 }
221 bool can_be_primary() const
222 {
223 return !is_removable();
224 }
225
227 display_configuration get_configuration() const
228 {
229 return display_configuration(get_mode(),get_position());
230 }
232 display_mode get_mode() const
233 {
234 return display_mode(get_width(),get_height(),get_bit_depth(),get_refresh_rate());
235 }
237 unsigned int get_width() const
238 {
239 return cdm.dmPelsWidth;
240 }
242 unsigned int get_height() const
243 {
244 return cdm.dmPelsHeight;
245 }
247 unsigned int get_bit_depth() const
248 {
249 return cdm.dmBitsPerPel;
250 }
252 unsigned int get_refresh_rate() const
253 {
254 return cdm.dmDisplayFrequency;
255 }
257 display_position get_position() const
258 {
259 return display_position(get_x(), get_y());
260 }
262 int get_x() const
263 {
264 return cdm.dmPosition.x;
265 }
267 int get_y() const
268 {
269 return cdm.dmPosition.y;
270 }
271
273 bool set_configuration(const display_configuration& dc)
274 {
275 cdm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_POSITION;
276 cdm.dmPelsWidth = dc.mode.width;
277 cdm.dmPelsHeight = dc.mode.height;
278 cdm.dmBitsPerPel = dc.mode.bit_depth;
279 cdm.dmDisplayFrequency = dc.mode.refresh_rate;
280 cdm.dmPosition.x = dc.position.x;
281 cdm.dmPosition.y = dc.position.y;
282 return update_after_display_change(
283 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, 0, NULL)); //CDS_UPDATEREGISTRY
284 }
286 bool set_mode(const display_mode& dm)
287 {
288 cdm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
289 cdm.dmPelsWidth = dm.width;
290 cdm.dmPelsHeight = dm.height;
291 cdm.dmBitsPerPel = dm.bit_depth;
292 cdm.dmDisplayFrequency = dm.refresh_rate;
293 return update_after_display_change(
294 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, 0, NULL));
295 }
297 bool set_resolution(unsigned int w, unsigned int h)
298 {
299 cdm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
300 cdm.dmPelsWidth = w;
301 cdm.dmPelsHeight = h;
302 return update_after_display_change(
303 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, 0, NULL));
304 }
306 bool set_bit_depth(unsigned int bits)
307 {
308 cdm.dmFields = DM_BITSPERPEL;
309 cdm.dmBitsPerPel = bits;
310 return update_after_display_change(
311 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, 0, NULL));
312 }
314 bool set_refresh_rate(unsigned int hz)
315 {
316 cdm.dmFields = DM_DISPLAYFREQUENCY;
317 cdm.dmDisplayFrequency = hz;
318 return update_after_display_change(
319 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, 0, NULL));
320 }
322 bool set_position(const display_position& dp)
323 {
324 return set_position(dp.x, dp.y);
325 }
327 bool set_position(unsigned int x, unsigned int y)
328 {
329 cdm.dmFields = DM_POSITION;
330 cdm.dmPosition.x = x;
331 cdm.dmPosition.y = y;
332 return update_after_display_change(
333 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, 0, NULL));
334 }
335
336
338 display_mode get_registered_mode() const
339 {
340 return display_mode(get_registered_width(), get_registered_height(), get_registered_bit_depth(), get_registered_refresh_rate());
341 }
343 unsigned int get_registered_width() const
344 {
345 return rdm.dmPelsWidth;
346 }
348 unsigned int get_registered_height() const
349 {
350 return rdm.dmPelsHeight;
351 }
353 unsigned int get_registered_bit_depth() const
354 {
355 return rdm.dmBitsPerPel;
356 }
358 unsigned int get_registered_refresh_rate() const
359 {
360 return rdm.dmDisplayFrequency;
361 }
362
364 bool register_configuration(const display_configuration& dc)
365 {
366 cdm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_POSITION;
367 cdm.dmPelsWidth = dc.mode.width;
368 cdm.dmPelsHeight = dc.mode.height;
369 cdm.dmBitsPerPel = dc.mode.bit_depth;
370 cdm.dmDisplayFrequency = dc.mode.refresh_rate;
371 cdm.dmPosition.x = dc.position.x;
372 cdm.dmPosition.y = dc.position.y;
373 return update_after_display_change(
374 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL));
375 }
377 bool register_mode(const display_mode& dm)
378 {
379 cdm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
380 cdm.dmPelsWidth = dm.width;
381 cdm.dmPelsHeight = dm.height;
382 cdm.dmBitsPerPel = dm.bit_depth;
383 cdm.dmDisplayFrequency = dm.refresh_rate;
384 return update_after_display_change(
385 ChangeDisplaySettingsEx(dd.DeviceName, &cdm, NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL));
386 }
388 bool register_resolution(unsigned int w, unsigned int h)
389 {
390 rdm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
391 rdm.dmPelsWidth = w;
392 rdm.dmPelsHeight = h;
393 return update_after_display_change(
394 ChangeDisplaySettingsEx(dd.DeviceName, &rdm, NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL));
395 }
397 bool register_bit_depth(unsigned int bits)
398 {
399 rdm.dmFields = DM_BITSPERPEL;
400 rdm.dmBitsPerPel = bits;
401 return update_after_display_change(
402 ChangeDisplaySettingsEx(dd.DeviceName, &rdm, NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL));
403 }
405 bool register_refresh_rate(unsigned int hz)
406 {
407 rdm.dmFields = DM_DISPLAYFREQUENCY;
408 rdm.dmDisplayFrequency = hz;
409 return update_after_display_change(
410 ChangeDisplaySettingsEx(dd.DeviceName, &rdm, NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL));
411 }
413 bool register_position(const display_position& dp)
414 {
415 return register_position(dp.x,dp.y);
416 }
418 bool register_position(unsigned int x, unsigned int y)
419 {
420 rdm.dmFields = DM_POSITION;
421 rdm.dmPosition.x = x;
422 rdm.dmPosition.y = y;
423 return update_after_display_change(
424 ChangeDisplaySettingsEx(dd.DeviceName, &rdm, NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL));
425 }
426
428 bool check_configuration(const display_configuration& dc) const
429 {
430 DEVMODE dm;
431 memset(&dm,0,sizeof(DEVMODE));
432 dm.dmSize = sizeof(DEVMODE);
433 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_POSITION;
434 dm.dmPelsWidth = dc.mode.width;
435 dm.dmPelsHeight = dc.mode.height;
436 dm.dmBitsPerPel = dc.mode.bit_depth;
437 dm.dmDisplayFrequency = dc.mode.refresh_rate;
438 dm.dmPosition.x = dc.position.x;
439 dm.dmPosition.y = dc.position.y;
440 return interpret_error(
441 ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL));
442 }
444 bool check_mode(const display_mode& d) const
445 {
446 DEVMODE dm;
447 memset(&dm,0,sizeof(DEVMODE));
448 dm.dmSize = sizeof(DEVMODE);
449 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
450 dm.dmPelsWidth = d.width;
451 dm.dmPelsHeight = d.height;
452 dm.dmBitsPerPel = d.bit_depth;
453 dm.dmDisplayFrequency = d.refresh_rate;
454 return interpret_error(
455 ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL));
456 }
458 bool check_resolution(unsigned int w, unsigned int h) const
459 {
460 DEVMODE dm;
461 memset(&dm,0,sizeof(DEVMODE));
462 dm.dmSize = sizeof(DEVMODE);
463 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
464 dm.dmPelsWidth = w;
465 dm.dmPelsHeight = h;
466 return interpret_error(
467 ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL));
468 }
470 bool check_bit_depth(unsigned int bits) const
471 {
472 DEVMODE dm;
473 memset(&dm,0,sizeof(DEVMODE));
474 dm.dmSize = sizeof(DEVMODE);
475 dm.dmFields = DM_BITSPERPEL;
476 dm.dmBitsPerPel = bits;
477 return interpret_error(
478 ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL));
479 }
481 bool check_refresh_rate(unsigned int hz) const
482 {
483 DEVMODE dm;
484 memset(&dm,0,sizeof(DEVMODE));
485 dm.dmSize = sizeof(DEVMODE);
486 dm.dmFields = DM_DISPLAYFREQUENCY;
487 dm.dmDisplayFrequency = hz;
488 return interpret_error(
489 ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL));
490 }
492 bool check_position(const display_position& dp) const
493 {
494 return check_position(dp.x,dp.y);
495 }
497 bool check_position(unsigned int x, unsigned int y) const
498 {
499 DEVMODE dm;
500 memset(&dm,0,sizeof(DEVMODE));
501 dm.dmSize = sizeof(DEVMODE);
502 dm.dmFields = DM_POSITION;
503 dm.dmPosition.x = x;
504 dm.dmPosition.y = y;
505 return interpret_error(
506 ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL));
507 }
508};
509#endif
510
511std::vector<display*>& ref_displays()
512{
513 static std::vector<display*> displays;
514 return displays;
515}
516
517const std::vector<display*>& display::get_displays()
518{
519 return ref_displays();
520}
521
524{
525 for (unsigned int i=0; i<ref_displays().size(); ++i)
526 delete ref_displays()[i];
527 ref_displays().clear();
528}
530void display::scan_displays(DisplayScanMode mode)
531{
533#ifdef _MSC_VER
534 windows_display* d = new windows_display;
535 int i = 0;
536 while (d->attach(i)) {
537 DisplayScanMode display_mode = DSM_ALL;
538 bool keep = true;
539 if (((mode & DSM_PHYSICAL) != 0) && d->is_mirror())
540 keep = false;
541 if (((mode & DSM_ACTIVE) != 0) && !d->is_active())
542 keep = false;
543 if (((mode & DSM_PASSIVE) != 0) && d->is_active())
544 keep = false;
545 if (!keep)
546 delete d;
547 else
548 ref_displays().push_back(d);
549 ++i;
550 d = new windows_display;
551 }
552 delete d;
553#else
554 std::cerr << "scan_displays in cgv/utils/display.cxx not implemented" << std::endl;
555#endif
556}
557
560{
561#ifdef _MSC_VER
562 LONG result = ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
563 bool ret = true;
564 for (unsigned int i=0; i<ref_displays().size(); ++i)
565 ret = static_cast<windows_display*>(ref_displays()[i])->update_after_display_change(result) && ret;
566 return ret;
567#else
568 std::cerr << "activate_all in cgv/utils/display.cxx not implemented" << std::endl;
569 return false;
570#endif
571}
572
575{
576#ifdef _MSC_VER
577 return windows_display::interpret_error(ChangeDisplaySettingsEx(NULL, NULL, NULL, CDS_TEST, NULL));
578#else
579 std::cerr << "check_activate_all in cgv/utils/display.cxx not implemented" << std::endl;
580 return false;
581#endif
582}
583
585void display::show_all_displays(DisplayScanMode scan_mode)
586{
587 scan_displays(scan_mode);
588 const std::vector<display*>& displays = get_displays();
589 for (unsigned int i=0; i<displays.size(); ++i)
590 std::cout << "display " << i << ": " << *displays[i] << std::endl;
591}
592 }
593}
static bool check_activate_all()
check if all displays can be activated according to the registered settings
Definition display.cxx:574
static std::string last_error
if one of the methods return false, this static member gives textual information about the reason
Definition display.h:79
static void show_all_displays(DisplayScanMode scan_mode=DSM_ALL)
show all available displays
Definition display.cxx:585
static void clear_displays()
clear the list of previously scanned devices and free all allocated memory
Definition display.cxx:523
static const std::vector< display * > & get_displays()
return the list of previously scanned display devices
Definition display.cxx:517
static void scan_displays(DisplayScanMode mode=DSM_ALL)
scan all available displays and ignore the mirrored displays that do not correspond to physical devic...
Definition display.cxx:530
static bool activate_all()
activate all displays according to the registered settings
Definition display.cxx:559
bool attach(base_ptr slot_object, base_ptr attachment_object, void *user_data)
function to attach an object to an object of type attach_slot.
std::string wstr2str(const std::wstring &ws)
convert a 16-bit string to a 8-bit string
Definition convert.cxx:26
the cgv namespace
Definition print.h:11
a display mode describes a valid setting of the display parameters
Definition display.h:13