22 #include "../include/tscope5/display.h"
23 #include "../include/tscope5/graphics.h"
24 #include "../include/tscope5/bitmaps.h"
25 #include "../include/tscope5/display_internal.h"
26 #include "../include/tscope5/system_internal.h"
27 #include "../include/tscope5/graphics_internal.h"
95 for (i = 0; i < _ts5_status.num_displays; i++) {
97 if (_ts5_status.display[i].adapter
99 ts5_fatal (
"%s: %s, %s (%d)\n",
"ts5_install_display",
100 "cannot open fullscreen display",
101 "adapter already in use by another display", i);
110 request.refreshrate = -1;
111 request.display_mode = TS5_FULLSCREEN_WINDOW;
116 #ifdef TS5_RASPBERRYPI
118 request.display_mode = TS5_FULLSCREEN;
132 for (i = 0; i < _ts5_status.num_displays; i++) {
134 if (_ts5_status.display[i].adapter
136 ts5_fatal (
"%s: %s, %s (%d)\n",
"ts5_install_display",
137 "cannot open fullscreen display",
138 " adapter already in use by another display", i);
144 ALLEGRO_DISPLAY_MODE *mode;
145 mode = (ALLEGRO_DISPLAY_MODE *)al_malloc(
sizeof(ALLEGRO_DISPLAY_MODE));
146 int nmodes = al_get_num_display_modes();
149 for (i=0; i<nmodes; i++) {
151 mode = al_get_display_mode(i, mode);
156 || mode->refresh_rate==0)) {
164 ts5_fatal (
"%s: %s (%d, %d) %s (%d) %s %d\n",
165 "ts5_install_display",
166 "the requested combination of size",
169 "is not supported by display adapter",
179 request.display_mode = TS5_FULLSCREEN;
191 for (i = 0; i < _ts5_status.num_displays; i++) {
193 if (_ts5_status.display[i].adapter
195 && (_ts5_status.display[i].display_mode
197 || _ts5_status.display[i].display_mode
198 == TS5_FULLSCREEN_WINDOW)) {
200 ts5_fatal (
"%s: %s, %s (%d)\n",
"ts5_install_display",
201 "cannot open display",
202 " adapter already in use by a fullscreen display",
211 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
212 "ts5_install_display",
"adjusting display width to",
216 > _ts5_status.display_adapter
221 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
222 "ts5_install_display",
"adjusting display width to",
233 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
234 "ts5_install_display",
"adjusting display height to",
238 > _ts5_status.display_adapter
241 request.h = _ts5_status.display_adapter
244 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
245 "ts5_install_display",
"adjusting display height to",
255 if (request.x == -1) {
257 if (_ts5_status.graphics.coordinate_system
258 == TS5_CARTESIAN_COORDINATES) {
260 request.x = (_ts5_status.display_adapter
261 [request.adapter].w - request.w)/2;
267 request.x += _ts5_status.display_adapter[request.adapter].x1;
270 if (request.y == -1) {
272 if (_ts5_status.graphics.coordinate_system
273 == TS5_CARTESIAN_COORDINATES) {
275 request.y = (_ts5_status.display_adapter
276 [request.adapter].h - request.h)/2;
282 request.y += _ts5_status.display_adapter[request.adapter].y1;
286 request.refreshrate = -1;
287 request.display_mode = TS5_WINDOWED;
295 al_set_new_display_adapter(request.adapter);
296 al_set_new_display_refresh_rate(request.refreshrate);
298 al_set_new_display_option(ALLEGRO_VSYNC, (
int)request.vsync_mode,
302 if (request.display_mode == TS5_WINDOWED) {
303 al_set_new_window_position(request.x, request.y);
306 if (request.display_mode == TS5_FULLSCREEN_WINDOW) {
307 al_set_new_window_position(INT_MAX, INT_MAX);
310 al_set_new_display_flags(request.display_mode);
313 _ts5_status.num_displays++;
314 _ts5_status.active_display = _ts5_status.num_displays - 1;
317 ts5_log(TS5_LOGLEVEL_1,
"ts5_install_display: Opening display\n");
319 TS5_DISPLAY **display;
320 display = al_realloc(_ts5_data.display,
321 _ts5_status.num_displays *
sizeof(TS5_DISPLAY *));
323 if (display == NULL) {
324 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
325 "failed to allocate memory for display pointer");
328 _ts5_data.display = (TS5_DISPLAY **) display;
330 _ts5_data.display[_ts5_status.active_display] =
331 al_create_display(request.w, request.h);
333 if (!_ts5_data.display[_ts5_status.active_display]) {
334 ts5_fatal(
"ts5_install_display: could not open display\n");
338 request.w = _ts5_status.display_adapter[request.adapter].w;
339 request.h = _ts5_status.display_adapter[request.adapter].h;
343 TS5_BITMAP **display_buffer;
345 display_buffer = al_realloc(_ts5_data.display_buffer,
346 _ts5_status.num_displays *
sizeof(TS5_BITMAP *));
348 if (display_buffer == NULL) {
349 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
350 "failed to allocate memory for display buffer pointer");
353 _ts5_data.display_buffer = (TS5_BITMAP **) display_buffer;
355 _ts5_data.display_buffer[_ts5_status.active_display] =
356 al_create_bitmap(request.w * request.sampling_factor, request.h * request.sampling_factor);
358 if (!_ts5_data.display_buffer[_ts5_status.active_display]) {
359 ts5_fatal(
"ts5_install_display: could not open display buffer\n");
364 TS5_BITMAP **display_backup;
366 display_backup = al_realloc(_ts5_data.display_backup,
367 _ts5_status.num_displays *
sizeof(TS5_BITMAP *));
369 if (display_backup == NULL) {
370 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
371 "failed to allocate memory for display backup pointer");
374 _ts5_data.display_backup = (TS5_BITMAP **) display_backup;
376 _ts5_data.display_backup[_ts5_status.active_display] =
377 al_create_bitmap(request.w * request.sampling_factor, request.h * request.sampling_factor);
379 if (!_ts5_data.display_backup[_ts5_status.active_display]) {
380 ts5_fatal(
"ts5_install_display: could not open display backup\n");
385 TS5_DISPLAY_STATUS *display_status;
386 display_status = al_realloc(_ts5_status.display,
387 _ts5_status.num_displays *
sizeof(TS5_DISPLAY_STATUS));
389 if (display_status == NULL) {
390 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
391 "failed to allocate memory for display settings");
394 _ts5_status.display = (TS5_DISPLAY_STATUS *) display_status;
396 _ts5_status.display[_ts5_status.active_display].adapter =
399 if (request.display_mode==TS5_WINDOWED) {
401 al_get_window_position(_ts5_data.display[_ts5_status.active_display],
402 &request.x, &request.y);
404 if (request.x + request.w
407 int oldw = request.w;
409 request.w = _ts5_status.display_adapter
412 al_resize_display(_ts5_data.display[_ts5_status.active_display],
413 request.w, request.h);
415 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
416 "ts5_install_display",
"adjusting display width to",
420 if (request.y + request.h > _ts5_status.display_adapter
423 int oldh = request.h;
425 request.h = _ts5_status.display_adapter
428 al_resize_display(_ts5_data.display[_ts5_status.active_display],
429 request.w, request.h);
431 al_set_window_position(_ts5_data.display
432 [_ts5_status.active_display],
433 request.x, request.y + (request.h-oldh));
435 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
436 "ts5_install_display",
"adjusting display height to",
439 al_get_window_position(
440 _ts5_data.display[_ts5_status.active_display],
441 &request.x, &request.y);
444 request.x -= _ts5_status.display_adapter[request.adapter].x1;
445 request.y -= _ts5_status.display_adapter[request.adapter].y1;
447 if (_ts5_status.graphics.coordinate_system
448 == TS5_CARTESIAN_COORDINATES) {
452 - (_ts5_status.display_adapter[request.adapter].w
456 (_ts5_status.display_adapter[request.adapter].h
462 _ts5_status.display[_ts5_status.active_display].x = request.x;
463 _ts5_status.display[_ts5_status.active_display].y = request.y;
464 _ts5_status.display[_ts5_status.active_display].w = request.w;
465 _ts5_status.display[_ts5_status.active_display].h = request.h;
467 _ts5_status.display[_ts5_status.active_display].refreshrate =
470 _ts5_status.display[_ts5_status.active_display].display_mode =
471 request.display_mode;
473 _ts5_status.display[_ts5_status.active_display].vsync_mode =
476 _ts5_status.display[_ts5_status.active_display].multisampling =
477 request.multisampling;
479 _ts5_status.display[_ts5_status.active_display].sampling_factor =
480 request.sampling_factor;
484 [_ts5_status.active_display]);
485 al_clear_to_color(_ts5_status.graphics.background_color);
488 [_ts5_status.active_display]);
496 _ts5_status.display[_ts5_status.active_display].last_sync = al_get_time();
503 return _ts5_status.active_display;
518 ts5_log(TS5_LOGLEVEL_5,
"ts5_clear_display()\n");
520 if (_ts5_data.target == NULL) {
521 ts5_fatal(
"ts5_clear_display: target is a NULL pointer\n");
524 al_clear_to_color(_ts5_status.graphics.background_color);
542 ts5_log(TS5_LOGLEVEL_5,
"ts5_flip_display()\n");
548 if (al_get_time() - _ts5_status.display[_ts5_status.active_display].last_sync >
549 1.0 / _ts5_status.display[_ts5_status.active_display].refreshrate + 0.003) {
556 double w = _ts5_status.display[_ts5_status.active_display].w;
557 double h = _ts5_status.display[_ts5_status.active_display].h;
558 double factor = (double)_ts5_status.display[_ts5_status.active_display].sampling_factor;
564 if (al_get_time() - _ts5_status.display[_ts5_status.active_display].last_sync >
565 1.0 / _ts5_status.display[_ts5_status.active_display].refreshrate + 0.003) {
567 al_set_target_backbuffer(_ts5_data.display[_ts5_status.active_display]);
568 if (_ts5_status.display[_ts5_status.active_display].multisampling) {
569 al_draw_scaled_bitmap(_ts5_data.display_backup[_ts5_status.active_display],
570 0.0, 0.0, w*factor, h*factor,
575 al_draw_bitmap(_ts5_data.display_backup[_ts5_status.active_display], 0.0, 0.0, 0);
580 al_set_target_bitmap(_ts5_data.display_backup[_ts5_status.active_display]);
581 al_clear_to_color(_ts5_status.graphics.background_color);
582 al_draw_bitmap(_ts5_data.display_buffer[_ts5_status.active_display], 0.0, 0.0, 0);
586 al_set_target_backbuffer(_ts5_data.display[_ts5_status.active_display]);
587 if (_ts5_status.display[_ts5_status.active_display].multisampling) {
588 al_draw_scaled_bitmap(_ts5_data.display_buffer[_ts5_status.active_display],
589 0.0, 0.0, w*factor, h*factor,
594 al_draw_bitmap(_ts5_data.display_buffer[_ts5_status.active_display], 0.0, 0.0, 0);
598 _ts5_status.display[_ts5_status.active_display].last_sync = al_get_time();
600 al_clear_to_color(_ts5_status.graphics.background_color);
602 al_set_target_bitmap(_ts5_data.display_buffer
603 [_ts5_status.active_display]);
605 return _ts5_status.display[_ts5_status.active_display].last_sync;
640 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_active_display(%d)\n", display);
642 int retval = _ts5_status.active_display + 1;
643 _ts5_status.active_display = display - 1;
644 _ts5_data.target = _ts5_data.display_buffer[_ts5_status.active_display];
645 al_set_target_bitmap(_ts5_data.target);
647 _ts5_status.graphics.target_width =
650 _ts5_status.graphics.target_height =
668 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_active_display()\n");
670 return _ts5_status.active_display + 1;
697 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_num_display_adapters()\n");
699 return _ts5_status.num_display_adapters;
719 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter_size(%d,%f,%f)\n",
725 ts5_fatal(
"ts5_get_display_adapter_size: adapter index not valid\n");
727 else if (adapter == 0) {
731 else if (adapter <= _ts5_status.num_display_adapters) {
732 ww = _ts5_status.display_adapter[adapter-1].w;
733 hh = _ts5_status.display_adapter[adapter-1].h;
736 ts5_fatal(
"ts5_get_display_adapter_size: adapter index not valid\n");
761 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter_width(%d)\n", adapter);
782 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter_height(%d)\n", adapter);
821 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_adapter(%d)\n", adapter);
825 if (adapter > 0 && adapter <= _ts5_status.num_display_adapters) {
827 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
828 "ts5_set_display_adapter",
829 "set display adapter for next display to",
833 ts5_fatal (
"ts5_set_display_adapter: adapter index not valid\n");
852 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter(%d)\n", display);
860 retval = _ts5_status.display[display-1].adapter + 1;
878 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_size(%f,%f)\n", w, h);
883 if (_ts5_status.graphics.coordinate_scale
884 == TS5_RELATIVE_COORDINATES) {
892 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d x %d (was %d x %d)\n",
893 "ts5_set_display_size",
894 "set display size for next display to",
913 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_size(%d,%p,%p)\n", display, w, h);
922 ww = _ts5_status.display[display-1].w;
923 hh = _ts5_status.display[display-1].h;
948 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_width(%d)\n", display);
969 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_height(%d)\n", display);
995 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_position(%f,%f)\n", x, y);
1000 if (_ts5_status.graphics.coordinate_scale
1001 == TS5_RELATIVE_COORDINATES) {
1003 if (_ts5_status.graphics.coordinate_system
1004 == TS5_CARTESIAN_COORDINATES) {
1018 if (_ts5_status.graphics.coordinate_system
1019 == TS5_CARTESIAN_COORDINATES) {
1034 ts5_log(TS5_LOGLEVEL_4,
"%s: %s (%d,%d) (was (%d,%d))\n",
1035 "ts5_set_display_position",
1036 "set display position for next display to",
1058 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_position(%d,%p,%p)\n",
1062 double dw, dh, aw, ah;
1068 al_get_window_position(_ts5_data.display[display-1],
1069 &_ts5_status.display[display-1].x,
1070 &_ts5_status.display[display-1].y);
1072 xx = _ts5_status.display[display-1].x;
1073 yy = _ts5_status.display[display-1].y;
1075 xx -= _ts5_status.display_adapter[adapter-1].x1;
1076 yy -= _ts5_status.display_adapter[adapter-1].y1;
1078 dw = _ts5_status.display[display-1].w;
1079 dh = _ts5_status.display[display-1].h;
1081 aw = _ts5_status.display_adapter[adapter-1].w;
1082 ah = _ts5_status.display_adapter[adapter-1].h;
1097 if (xx!=-1 && yy!=-1) {
1101 if (_ts5_status.graphics.coordinate_system
1102 == TS5_CARTESIAN_COORDINATES) {
1103 xx = xx + dw/2.0 - aw/2.0;
1104 yy = ah/2.0 - yy - dh/2.0;
1108 if (_ts5_status.graphics.coordinate_scale
1109 == TS5_RELATIVE_COORDINATES) {
1111 if (_ts5_status.graphics.coordinate_system
1112 == TS5_CARTESIAN_COORDINATES) {
1146 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_x(%d)\n", display);
1166 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_y(%d)\n", display);
1193 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_refreshrate(%d)\n", rate);
1199 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_refreshrate",
1200 "set refreshrate for next display to",
1219 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_refreshrate(%d)\n", display);
1227 retval = _ts5_status.display[display-1].refreshrate;
1264 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_mode(%d)\n", mode);
1268 if (mode != TS5_WINDOWED
1269 && mode != TS5_FULLSCREEN
1270 && mode != TS5_FULLSCREEN_WINDOW) {
1271 ts5_fatal (
"%s: %s (%d)\n",
"ts5_set_display_mode",
1272 "requested display mode not available", mode);
1277 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_display_mode",
1278 "set display mode for next display to",
1297 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_mode(%d)\n", display);
1305 retval = _ts5_status.display[display-1].display_mode;
1325 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_vsync_mode(%d)\n", mode);
1329 if (mode < TS5_VSYNC_WHATEVER || mode > TS5_VSYNC_OFF) {
1330 ts5_fatal(
"ts5_set_vsync_mode: mode should be 0, 1 or 2 (is %d)\n",
1336 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_vsync_mode",
1337 "set vsync mode for next display to",
1356 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_vsync_mode(%d)\n", display);
1364 retval = _ts5_status.display[display-1].vsync_mode;
1388 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_multisampling(%d)\n", multisampling);
1392 if (multisampling != TS5_MULTISAMPLING_OFF && multisampling != TS5_MULTISAMPLING_ON) {
1393 ts5_fatal(
"%s: %s (is %d)\n",
"ts5_set_multisampling: ",
1394 "multisampling should be either TS5_MULTISAMPLING_OFF or TS5_MULTISAMPLING_ON ",
1401 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_multisampling",
1402 "set multisampling level for next display to",
1422 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_multisampling(%d)\n", display);
1430 retval = _ts5_status.display[display-1].multisampling;
double ts5_get_display_adapter_width(const int adapter)
Get the width of the monitor attached to a display adapter.
int ts5_get_vsync_mode(const int display)
Get the vsync mode of a display.
void ts5_check_display(char *calling_function)
Do some checks at the start of each display function.
int ts5_set_display_mode(const int mode)
Set the display mode for the next display.
TS5_DISPLAY_STATUS ts5_nextdisplay
Settings for the next display that will be opened.
void ts5_check_display2(char *calling_function, const int display)
Do some checks at the start of each display function.
int ts5_get_num_display_adapters()
Get the number of display adapters that are connected to the system.
double ts5_flip_display()
Make what has been drawn visible on the screen.
int ts5_set_active_display(const int display)
Set the active display.
double ts5_get_bitmap_width(TS5_BITMAP *map)
Get the width of a bitmap in pixels.
int ts5_set_multisampling(const int multisampling)
Set the multisampling mode for the next display.
int ts5_set_vsync_mode(const int mode)
Set the vsync mode for the next display.
double ts5_get_bitmap_height(TS5_BITMAP *map)
Get the height of a bitmap in pixels.
void ts5_get_display_adapter_size(const int adapter, double *w, double *h)
Get the size of the monitor attached to a display adapter.
TS5_BITMAP * ts5_set_drawing_target(TS5_BITMAP *target)
Set the active drawing target.
void ts5_get_display_position(const int display, double *x, double *y)
Get the position of a display.
int ts5_get_display_mode(const int display)
Get the display mode of a display.
int ts5_install_display()
Open a new display.
void ts5_uninstall_displays()
Close all open displays.
double ts5_get_display_x(const int display)
Get the horizontal position of a display.
void ts5_set_display_size(double w, double h)
Set the size of the next display.
int ts5_get_active_display()
Get the active display.
double ts5_get_display_adapter_height(const int adapter)
Get the heigth of the monitor attached to a display adapter.
void ts5_log(const unsigned int level, const char *format,...)
Send info to a logging window.
int ts5_get_refreshrate(const int display)
Get the refreshrate of a display.
void ts5_clear_display()
Clear the current drawing target.
double ts5_get_display_width(const int display)
Get the width of a display.
void ts5_set_display_position(double x, double y)
Set the position of the next display.
int ts5_set_refreshrate(const int rate)
Set the requested refreshrate for the next display.
double ts5_get_display_height(const int display)
Get the height of a display.
void ts5_fatal(const char *format,...)
Exit safely with an error message.
void ts5_get_display_size(const int display, double *w, double *h)
Get the size of a display.
double ts5_get_display_y(const int display)
Get the vertical position of a display.
int ts5_get_multisampling(const int display)
Get the multisampling mode of a display.
int ts5_set_display_adapter(const int adapter)
Set the display adapter for the next display that will be opened.
int ts5_get_display_adapter(const int display)
Get the index of the display adapter of a display.