21 #include "../include/tscope5/display.h"
22 #include "../include/tscope5/graphics.h"
23 #include "../include/tscope5/bitmaps.h"
24 #include "../include/tscope5/display_internal.h"
25 #include "../include/tscope5/system_internal.h"
26 #include "../include/tscope5/graphics_internal.h"
94 for (i = 0; i < _ts5_status.num_displays; i++) {
96 if (_ts5_status.display[i].adapter
98 ts5_fatal (
"%s: %s, %s (%d)\n",
"ts5_install_display",
99 "cannot open fullscreen display",
100 "adapter already in use by another display", i);
109 request.refreshrate = -1;
110 request.display_mode = TS5_FULLSCREEN_WINDOW;
113 #ifdef TS5_RASPBERRYPI
115 request.display_mode = TS5_FULLSCREEN;
129 for (i = 0; i < _ts5_status.num_displays; i++) {
131 if (_ts5_status.display[i].adapter
133 ts5_fatal (
"%s: %s, %s (%d)\n",
"ts5_install_display",
134 "cannot open fullscreen display",
135 " adapter already in use by another display", i);
141 ALLEGRO_DISPLAY_MODE *mode;
142 mode = (ALLEGRO_DISPLAY_MODE *)al_malloc(
sizeof(ALLEGRO_DISPLAY_MODE));
143 int nmodes = al_get_num_display_modes();
146 for (i=0; i<nmodes; i++) {
148 mode = al_get_display_mode(i, mode);
153 || mode->refresh_rate==0)) {
161 ts5_fatal (
"%s: %s (%d, %d) %s (%d) %s %d\n",
162 "ts5_install_display",
163 "the requested combination of size",
166 "is not supported by display adapter",
176 request.display_mode = TS5_FULLSCREEN;
186 for (i = 0; i < _ts5_status.num_displays; i++) {
188 if (_ts5_status.display[i].adapter
190 && (_ts5_status.display[i].display_mode
192 || _ts5_status.display[i].display_mode
193 == TS5_FULLSCREEN_WINDOW)) {
195 ts5_fatal (
"%s: %s, %s (%d)\n",
"ts5_install_display",
196 "cannot open display",
197 " adapter already in use by a fullscreen display",
206 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
207 "ts5_install_display",
"adjusting display width to",
211 > _ts5_status.display_adapter
216 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
217 "ts5_install_display",
"adjusting display width to",
228 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
229 "ts5_install_display",
"adjusting display height to",
233 > _ts5_status.display_adapter
236 request.h = _ts5_status.display_adapter
239 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
240 "ts5_install_display",
"adjusting display height to",
250 if (request.x == -1) {
252 if (_ts5_status.graphics.coordinate_system
253 == TS5_CARTESIAN_COORDINATES) {
255 request.x = (_ts5_status.display_adapter
256 [request.adapter].w - request.w)/2;
262 request.x += _ts5_status.display_adapter[request.adapter].x1;
265 if (request.y == -1) {
267 if (_ts5_status.graphics.coordinate_system
268 == TS5_CARTESIAN_COORDINATES) {
270 request.y = (_ts5_status.display_adapter
271 [request.adapter].h - request.h)/2;
277 request.y += _ts5_status.display_adapter[request.adapter].y1;
281 request.refreshrate = -1;
282 request.display_mode = TS5_WINDOWED;
288 al_set_new_display_adapter(request.adapter);
289 al_set_new_display_refresh_rate(request.refreshrate);
291 al_set_new_display_option(ALLEGRO_VSYNC, (
int)request.vsync_mode,
294 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_REQUIRE);
295 al_set_new_display_option(ALLEGRO_SAMPLES, 16, ALLEGRO_SUGGEST);
296 al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
298 if (request.display_mode == TS5_WINDOWED) {
299 al_set_new_window_position(request.x, request.y);
302 if (request.display_mode == TS5_FULLSCREEN_WINDOW) {
303 al_set_new_window_position(INT_MAX, INT_MAX);
306 al_set_new_display_flags(request.display_mode);
309 _ts5_status.num_displays++;
310 _ts5_status.active_display = _ts5_status.num_displays - 1;
313 ts5_log(TS5_LOGLEVEL_1,
"ts5_install_display: Opening display\n");
315 TS5_DISPLAY **display;
316 display = al_realloc(_ts5_data.display,
317 _ts5_status.num_displays *
sizeof(TS5_DISPLAY *));
319 if (display == NULL) {
320 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
321 "failed to allocate memory for display pointer");
324 _ts5_data.display = (TS5_DISPLAY **) display;
326 _ts5_data.display[_ts5_status.active_display] =
327 al_create_display(request.w, request.h);
329 if (!_ts5_data.display[_ts5_status.active_display]) {
330 ts5_fatal(
"ts5_install_display: could not open display\n");
334 request.w = _ts5_status.display_adapter[request.adapter].w;
335 request.h = _ts5_status.display_adapter[request.adapter].h;
339 TS5_BITMAP **display_buffer;
341 display_buffer = al_realloc(_ts5_data.display_buffer,
342 _ts5_status.num_displays *
sizeof(TS5_BITMAP *));
344 if (display_buffer == NULL) {
345 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
346 "failed to allocate memory for display buffer pointer");
349 _ts5_data.display_buffer = (TS5_BITMAP **) display_buffer;
351 _ts5_data.display_buffer[_ts5_status.active_display] =
352 al_create_bitmap(request.w, request.h);
354 if (!_ts5_data.display_buffer[_ts5_status.active_display]) {
355 ts5_fatal(
"ts5_install_display: could not open display buffer\n");
360 TS5_BITMAP **display_backup;
362 display_backup = al_realloc(_ts5_data.display_backup,
363 _ts5_status.num_displays *
sizeof(TS5_BITMAP *));
365 if (display_backup == NULL) {
366 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
367 "failed to allocate memory for display backup pointer");
370 _ts5_data.display_backup = (TS5_BITMAP **) display_backup;
372 _ts5_data.display_backup[_ts5_status.active_display] =
373 al_create_bitmap(request.w, request.h);
375 if (!_ts5_data.display_backup[_ts5_status.active_display]) {
376 ts5_fatal(
"ts5_install_display: could not open display backup\n");
381 TS5_DISPLAY_STATUS *display_status;
382 display_status = al_realloc(_ts5_status.display,
383 _ts5_status.num_displays *
sizeof(TS5_DISPLAY_STATUS));
385 if (display_status == NULL) {
386 ts5_fatal(
"%s: %s\n",
"ts5_install_display",
387 "failed to allocate memory for display settings");
390 _ts5_status.display = (TS5_DISPLAY_STATUS *) display_status;
392 _ts5_status.display[_ts5_status.active_display].adapter =
395 if (request.display_mode==TS5_WINDOWED) {
397 al_get_window_position(_ts5_data.display[_ts5_status.active_display],
398 &request.x, &request.y);
400 if (request.x + request.w
403 int oldw = request.w;
405 request.w = _ts5_status.display_adapter
408 al_resize_display(_ts5_data.display[_ts5_status.active_display],
409 request.w, request.h);
411 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
412 "ts5_install_display",
"adjusting display width to",
416 if (request.y + request.h > _ts5_status.display_adapter
419 int oldh = request.h;
421 request.h = _ts5_status.display_adapter
424 al_resize_display(_ts5_data.display[_ts5_status.active_display],
425 request.w, request.h);
427 al_set_window_position(_ts5_data.display
428 [_ts5_status.active_display],
429 request.x, request.y + (request.h-oldh));
431 ts5_log(TS5_LOGLEVEL_1,
"%s: %s %d (was %d)\n",
432 "ts5_install_display",
"adjusting display height to",
435 al_get_window_position(
436 _ts5_data.display[_ts5_status.active_display],
437 &request.x, &request.y);
440 request.x -= _ts5_status.display_adapter[request.adapter].x1;
441 request.y -= _ts5_status.display_adapter[request.adapter].y1;
443 if (_ts5_status.graphics.coordinate_system
444 == TS5_CARTESIAN_COORDINATES) {
448 - (_ts5_status.display_adapter[request.adapter].w
452 (_ts5_status.display_adapter[request.adapter].h
458 _ts5_status.display[_ts5_status.active_display].x = request.x;
459 _ts5_status.display[_ts5_status.active_display].y = request.y;
460 _ts5_status.display[_ts5_status.active_display].w = request.w;
461 _ts5_status.display[_ts5_status.active_display].h = request.h;
463 _ts5_status.display[_ts5_status.active_display].refreshrate =
466 _ts5_status.display[_ts5_status.active_display].display_mode =
467 request.display_mode;
469 _ts5_status.display[_ts5_status.active_display].vsync_mode =
474 [_ts5_status.active_display]);
475 al_clear_to_color(_ts5_status.graphics.background_color);
478 [_ts5_status.active_display]);
486 _ts5_status.display[_ts5_status.active_display].last_sync = al_get_time();
493 return _ts5_status.active_display;
508 ts5_log(TS5_LOGLEVEL_5,
"ts5_clear_display()\n");
510 if (_ts5_data.target == NULL) {
511 ts5_fatal(
"ts5_clear_display: target is a NULL pointer\n");
514 al_clear_to_color(_ts5_status.graphics.background_color);
532 ts5_log(TS5_LOGLEVEL_5,
"ts5_flip_display()\n");
538 if (al_get_time() - _ts5_status.display[_ts5_status.active_display].last_sync >
539 1.0 / _ts5_status.display[_ts5_status.active_display].refreshrate + 0.003) {
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) {
551 al_set_target_backbuffer(_ts5_data.display[_ts5_status.active_display]);
552 al_draw_bitmap(_ts5_data.display_backup[_ts5_status.active_display], 0.0, 0.0, 0);
556 al_set_target_bitmap(_ts5_data.display_backup[_ts5_status.active_display]);
557 al_clear_to_color(_ts5_status.graphics.background_color);
558 al_draw_bitmap(_ts5_data.display_buffer[_ts5_status.active_display], 0.0, 0.0, 0);
562 al_set_target_backbuffer(_ts5_data.display[_ts5_status.active_display]);
563 al_draw_bitmap(_ts5_data.display_buffer[_ts5_status.active_display], 0.0, 0.0, 0);
566 _ts5_status.display[_ts5_status.active_display].last_sync = al_get_time();
568 al_clear_to_color(_ts5_status.graphics.background_color);
570 al_set_target_bitmap(_ts5_data.display_buffer
571 [_ts5_status.active_display]);
573 return _ts5_status.display[_ts5_status.active_display].last_sync;
608 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_active_display(%d)\n", display);
610 int retval = _ts5_status.active_display + 1;
611 _ts5_status.active_display = display - 1;
612 _ts5_data.target = _ts5_data.display_buffer[_ts5_status.active_display];
613 al_set_target_bitmap(_ts5_data.target);
615 _ts5_status.graphics.target_width =
616 al_get_bitmap_width(_ts5_data.target);
618 _ts5_status.graphics.target_height =
619 al_get_bitmap_height(_ts5_data.target);
636 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_active_display()\n");
638 return _ts5_status.active_display + 1;
665 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_num_display_adapters()\n");
667 return _ts5_status.num_display_adapters;
687 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter_size(%d,%f,%f)\n",
693 ts5_fatal(
"ts5_get_display_adapter_size: adapter index not valid\n");
695 else if (adapter == 0) {
699 else if (adapter <= _ts5_status.num_display_adapters) {
700 ww = _ts5_status.display_adapter[adapter-1].w;
701 hh = _ts5_status.display_adapter[adapter-1].h;
704 ts5_fatal(
"ts5_get_display_adapter_size: adapter index not valid\n");
729 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter_width(%d)\n", adapter);
750 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter_height(%d)\n", adapter);
789 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_adapter(%d)\n", adapter);
793 if (adapter > 0 && adapter <= _ts5_status.num_display_adapters) {
795 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
796 "ts5_set_display_adapter",
797 "set display adapter for next display to",
801 ts5_fatal (
"ts5_set_display_adapter: adapter index not valid\n");
820 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_adapter(%d)\n", display);
828 retval = _ts5_status.display[display-1].adapter + 1;
846 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_size(%f,%f)\n", w, h);
851 if (_ts5_status.graphics.coordinate_scale
852 == TS5_RELATIVE_COORDINATES) {
860 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d x %d (was %d x %d)\n",
861 "ts5_set_display_size",
862 "set display size for next display to",
881 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_size(%d,%p,%p)\n", display, w, h);
890 ww = _ts5_status.display[display-1].w;
891 hh = _ts5_status.display[display-1].h;
916 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_width(%d)\n", display);
937 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_height(%d)\n", display);
963 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_position(%f,%f)\n", x, y);
968 if (_ts5_status.graphics.coordinate_scale
969 == TS5_RELATIVE_COORDINATES) {
971 if (_ts5_status.graphics.coordinate_system
972 == TS5_CARTESIAN_COORDINATES) {
986 if (_ts5_status.graphics.coordinate_system
987 == TS5_CARTESIAN_COORDINATES) {
1002 ts5_log(TS5_LOGLEVEL_4,
"%s: %s (%d,%d) (was (%d,%d))\n",
1003 "ts5_set_display_position",
1004 "set display position for next display to",
1026 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_position(%d,%p,%p)\n",
1030 double dw, dh, aw, ah;
1036 al_get_window_position(_ts5_data.display[display-1],
1037 &_ts5_status.display[display-1].x,
1038 &_ts5_status.display[display-1].y);
1040 xx = _ts5_status.display[display-1].x;
1041 yy = _ts5_status.display[display-1].y;
1043 xx -= _ts5_status.display_adapter[adapter-1].x1;
1044 yy -= _ts5_status.display_adapter[adapter-1].y1;
1046 dw = _ts5_status.display[display-1].w;
1047 dh = _ts5_status.display[display-1].h;
1049 aw = _ts5_status.display_adapter[adapter-1].w;
1050 ah = _ts5_status.display_adapter[adapter-1].h;
1065 if (xx!=-1 && yy!=-1) {
1069 if (_ts5_status.graphics.coordinate_system
1070 == TS5_CARTESIAN_COORDINATES) {
1071 xx = xx + dw/2.0 - aw/2.0;
1072 yy = ah/2.0 - yy - dh/2.0;
1076 if (_ts5_status.graphics.coordinate_scale
1077 == TS5_RELATIVE_COORDINATES) {
1079 if (_ts5_status.graphics.coordinate_system
1080 == TS5_CARTESIAN_COORDINATES) {
1114 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_x(%d)\n", display);
1134 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_y(%d)\n", display);
1161 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_refreshrate(%d)\n", rate);
1167 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_refreshrate",
1168 "set refreshrate for next display to",
1187 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_refreshrate(%d)\n", display);
1195 retval = _ts5_status.display[display-1].refreshrate;
1232 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_display_mode(%d)\n", mode);
1236 if (mode != TS5_WINDOWED
1237 && mode != TS5_FULLSCREEN
1238 && mode != TS5_FULLSCREEN_WINDOW) {
1239 ts5_fatal (
"%s: %s (%d)\n",
"ts5_set_display_mode",
1240 "requested display mode not available", mode);
1245 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_display_mode",
1246 "set display mode for next display to",
1265 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_display_mode(%d)\n", display);
1273 retval = _ts5_status.display[display-1].display_mode;
1293 ts5_log(TS5_LOGLEVEL_4,
"ts5_set_vsync_mode(%d)\n", mode);
1297 if (mode < TS5_VSYNC_WHATEVER || mode > TS5_VSYNC_OFF) {
1298 ts5_fatal(
"ts5_set_vsync_mode: mode should be 0, 1 or 2 (is %d)\n",
1304 ts5_log(TS5_LOGLEVEL_4,
"%s: %s %d (was %d)\n",
"ts5_set_vsync_mode",
1305 "set vsync mode for next display to",
1324 ts5_log(TS5_LOGLEVEL_4,
"ts5_get_vsync_mode(%d)\n", display);
1332 retval = _ts5_status.display[display-1].vsync_mode;
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.
int ts5_set_vsync_mode(const int mode)
Set the vsync mode for the next display.
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_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.