Changeset 539 for libcaca/trunk/caca/driver_gl.c
- Timestamp:
- Mar 7, 2006, 12:01:59 AM (15 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/caca/driver_gl.c
r537 r539 20 20 #include "config.h" 21 21 22 #if defined(USE_SLANG)23 # if defined(HAVE_SLANG_SLANG_H)24 # include <slang/slang.h>25 # else26 # include <slang.h>27 # endif28 #endif29 #if defined(USE_NCURSES)30 # if defined(HAVE_NCURSES_H)31 # include <ncurses.h>32 # else33 # include <curses.h>34 # endif35 #endif36 #if defined(USE_CONIO)37 # include <conio.h>38 # if defined(SCREENUPDATE_IN_PC_H)39 # include <pc.h>40 # endif41 #endif42 #if defined(USE_X11)43 # include <X11/Xlib.h>44 # if defined(HAVE_X11_XKBLIB_H)45 # include <X11/XKBlib.h>46 # endif47 #endif48 #if defined(USE_WIN32)49 # include <windows.h>50 #endif51 #if defined(USE_GL)52 # include <GL/gl.h>53 # include <GL/glut.h>54 # include <GL/freeglut_ext.h>55 #endif56 22 #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME) 57 23 # include <inttypes.h> … … 60 26 typedef unsigned char uint8_t; 61 27 #endif 28 29 #if defined(USE_GL) 30 31 #include <GL/gl.h> 32 #include <GL/glut.h> 33 #include <GL/freeglut_ext.h> 62 34 63 35 #include <stdio.h> /* BUFSIZ */ … … 69 41 #include <stdarg.h> 70 42 71 #if defined(HAVE_SIGNAL_H)72 # include <signal.h>73 #endif74 #if defined(HAVE_SYS_IOCTL_H)75 # include <sys/ioctl.h>76 #endif77 78 43 #include "caca.h" 79 44 #include "caca_internals.h" … … 85 50 */ 86 51 87 #if defined(USE_SLANG)88 /* Tables generated by test/optipal.c */89 static int const slang_palette[2*16*16] =90 {91 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0,92 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 0, 8,93 8, 7, 7, 8, 15, 7, 7, 15, 15, 9, 9, 15, 1, 9, 9, 1,94 7, 9, 9, 7, 8, 1, 1, 8, 0, 1, 15, 10, 10, 15, 2, 10,95 10, 2, 7, 10, 10, 7, 8, 2, 2, 8, 0, 2, 15, 11, 11, 15,96 3, 11, 11, 3, 7, 11, 11, 7, 8, 3, 3, 8, 0, 3, 15, 12,97 12, 15, 4, 12, 12, 4, 7, 12, 12, 7, 8, 4, 4, 8, 0, 4,98 15, 13, 13, 15, 5, 13, 13, 5, 7, 13, 13, 7, 8, 5, 5, 8,99 0, 5, 15, 14, 14, 15, 6, 14, 14, 6, 7, 14, 14, 7, 8, 6,100 6, 8, 0, 6, 4, 6, 6, 4, 12, 14, 14, 12, 6, 2, 2, 6,101 14, 10, 10, 14, 2, 3, 3, 2, 10, 11, 11, 10, 3, 1, 1, 3,102 11, 9, 9, 11, 1, 5, 5, 1, 9, 13, 13, 9, 5, 4, 4, 5,103 13, 12, 12, 13, 4, 14, 6, 12, 12, 6, 14, 4, 6, 10, 2, 14,104 14, 2, 10, 6, 2, 11, 3, 10, 10, 3, 11, 2, 3, 9, 1, 11,105 11, 1, 9, 3, 1, 13, 5, 9, 9, 5, 13, 1, 5, 12, 4, 13,106 13, 4, 12, 5, 0, 7, 0, 15, 15, 8, 8, 15, 15, 1, 7, 1,107 1, 6, 2, 5, 3, 4, 4, 3, 5, 2, 6, 1, 0, 0, 1, 1,108 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 2, 2, 3, 3,109 4, 4, 5, 5, 6, 6, 7, 7, 14, 9, 1, 15, 8, 9, 8, 8,110 9, 9, 1, 7, 0, 9, 9, 8, 6, 9, 13, 10, 2, 15, 8, 10,111 7, 2, 15, 2, 2, 7, 0, 10, 10, 8, 5, 10, 12, 11, 3, 15,112 8, 11, 7, 3, 15, 3, 3, 7, 0, 11, 11, 8, 4, 11, 11, 12,113 4, 15, 8, 12, 7, 4, 15, 4, 4, 7, 0, 12, 12, 8, 3, 12,114 10, 13, 5, 15, 8, 13, 7, 5, 15, 5, 5, 7, 0, 13, 13, 8,115 2, 13, 9, 14, 6, 15, 8, 14, 7, 6, 15, 6, 6, 7, 0, 14,116 14, 8, 1, 14, 5, 6, 2, 4, 13, 14, 10, 12, 4, 2, 3, 6,117 12, 10, 11, 14, 6, 3, 1, 2, 14, 11, 9, 10, 2, 1, 5, 3,118 10, 9, 13, 11, 3, 5, 4, 1, 11, 13, 12, 9, 1, 4, 6, 5,119 9, 12, 14, 13, 5, 14, 2, 12, 13, 6, 10, 4, 4, 10, 3, 14,120 12, 2, 11, 6, 6, 11, 1, 10, 14, 3, 9, 2, 2, 9, 5, 11,121 10, 1, 13, 3, 3, 13, 4, 9, 11, 5, 12, 1, 1, 12, 6, 13,122 9, 4, 14, 5, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,123 };124 125 static int const slang_assoc[16*16] =126 {127 134, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,128 28, 135, 214, 86, 219, 91, 133, 127, 26, 23, 240, 112, 245, 117, 141, 126,129 37, 211, 142, 83, 206, 132, 78, 160, 35, 237, 32, 109, 232, 140, 104, 161,130 46, 87, 82, 143, 131, 215, 210, 169, 44, 113, 108, 41, 139, 241, 236, 170,131 55, 222, 203, 130, 144, 94, 75, 178, 53, 248, 229, 138, 50, 120, 101, 179,132 64, 90, 129, 218, 95, 145, 223, 187, 62, 116, 137, 244, 121, 59, 249, 188,133 73, 128, 79, 207, 74, 202, 146, 196, 71, 136, 105, 233, 100, 228, 68, 197,134 122, 153, 162, 171, 180, 189, 198, 147, 16, 25, 34, 43, 52, 61, 70, 18,135 15, 27, 36, 45, 54, 63, 72, 17, 151, 155, 164, 173, 182, 191, 200, 124,136 154, 22, 238, 110, 243, 115, 156, 24, 150, 152, 216, 88, 221, 93, 148, 20,137 163, 235, 31, 107, 230, 165, 102, 33, 159, 213, 250, 85, 208, 157, 80, 29,138 172, 111, 106, 40, 174, 239, 234, 42, 168, 89, 84, 251, 166, 217, 212, 38,139 181, 246, 227, 183, 49, 118, 99, 51, 177, 224, 205, 175, 252, 96, 77, 47,140 190, 114, 192, 242, 119, 58, 247, 60, 186, 92, 184, 220, 97, 253, 225, 56,141 199, 201, 103, 231, 98, 226, 67, 69, 195, 193, 81, 209, 76, 204, 254, 65,142 123, 149, 158, 167, 176, 185, 194, 19, 125, 21, 30, 39, 48, 57, 66, 255,143 };144 #endif145 146 #if defined(USE_WIN32)147 static int const win32_fg_palette[] =148 {149 0,150 FOREGROUND_BLUE,151 FOREGROUND_GREEN,152 FOREGROUND_GREEN | FOREGROUND_BLUE,153 FOREGROUND_RED,154 FOREGROUND_RED | FOREGROUND_BLUE,155 FOREGROUND_RED | FOREGROUND_GREEN,156 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,157 FOREGROUND_INTENSITY,158 FOREGROUND_INTENSITY | FOREGROUND_BLUE,159 FOREGROUND_INTENSITY | FOREGROUND_GREEN,160 FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,161 FOREGROUND_INTENSITY | FOREGROUND_RED,162 FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,163 FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,164 FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE165 };166 167 static int const win32_bg_palette[] =168 {169 0,170 BACKGROUND_BLUE,171 BACKGROUND_GREEN,172 BACKGROUND_GREEN | BACKGROUND_BLUE,173 BACKGROUND_RED,174 BACKGROUND_RED | BACKGROUND_BLUE,175 BACKGROUND_RED | BACKGROUND_GREEN,176 BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,177 BACKGROUND_INTENSITY,178 BACKGROUND_INTENSITY | BACKGROUND_BLUE,179 BACKGROUND_INTENSITY | BACKGROUND_GREEN,180 BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE,181 BACKGROUND_INTENSITY | BACKGROUND_RED,182 BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE,183 BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN,184 BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE185 };186 #endif187 188 #if defined(USE_GL)189 52 /* Ok, I just suck. */ 190 53 static GLbyte const gl_bgpal[][4] = … … 210 73 211 74 static caca_t *gl_kk; /* FIXME: we ought to get rid of this */ 212 #endif213 75 214 76 /* 215 77 * Local functions 216 78 */ 217 static void caca_handle_resize(caca_t *kk);218 219 #if defined(USE_SLANG)220 static void slang_init_palette(void);221 #endif222 223 #if defined(HAVE_SIGNAL) && (defined(USE_NCURSES) || defined(USE_SLANG))224 static RETSIGTYPE sigwinch_handler(int);225 static caca_t *sigwinch_kk; /* FIXME: we ought to get rid of this */226 #endif227 228 #if defined(USE_X11)229 static int x11_error_handler(Display *, XErrorEvent *);230 #endif231 232 #if defined(USE_GL)233 79 static void gl_handle_keyboard(unsigned char, int, int); 234 80 static void gl_handle_special_key(int, int, int); … … 236 82 static void gl_handle_mouse(int, int, int, int); 237 83 static void gl_handle_mouse_motion(int, int); 238 #endif 239 240 #if !defined(_DOXYGEN_SKIP_ME) 241 int _caca_init_graphics(caca_t *kk) 242 { 243 #if defined(HAVE_SIGNAL) && (defined(USE_NCURSES) || defined(USE_SLANG)) 244 sigwinch_kk = kk; 245 signal(SIGWINCH, sigwinch_handler); 246 #endif 247 248 #if defined(USE_SLANG) 249 if(kk->driver == CACA_DRIVER_SLANG) 250 { 251 slang_init_palette(); 252 253 /* Disable alt charset support so that we get a chance to have all 254 * 256 colour pairs */ 255 SLtt_Has_Alt_Charset = 0; 256 257 cucul_set_size(kk->qq, SLtt_Screen_Cols, SLtt_Screen_Rows); 258 } 259 else 260 #endif 261 #if defined(USE_NCURSES) 262 if(kk->driver == CACA_DRIVER_NCURSES) 263 { 264 static int curses_colors[] = 265 { 266 /* Standard curses colours */ 267 COLOR_BLACK, 268 COLOR_BLUE, 269 COLOR_GREEN, 270 COLOR_CYAN, 271 COLOR_RED, 272 COLOR_MAGENTA, 273 COLOR_YELLOW, 274 COLOR_WHITE, 275 /* Extra values for xterm-16color */ 276 COLOR_BLACK + 8, 277 COLOR_BLUE + 8, 278 COLOR_GREEN + 8, 279 COLOR_CYAN + 8, 280 COLOR_RED + 8, 281 COLOR_MAGENTA + 8, 282 COLOR_YELLOW + 8, 283 COLOR_WHITE + 8 284 }; 285 286 int fg, bg, max; 287 288 /* Activate colour */ 289 start_color(); 290 291 /* If COLORS == 16, it means the terminal supports full bright colours 292 * using setab and setaf (will use \e[90m \e[91m etc. for colours >= 8), 293 * we can build 16*16 colour pairs. 294 * If COLORS == 8, it means the terminal does not know about bright 295 * colours and we need to get them through A_BOLD and A_BLINK (\e[1m 296 * and \e[5m). We can only build 8*8 colour pairs. */ 297 max = COLORS >= 16 ? 16 : 8; 298 299 for(bg = 0; bg < max; bg++) 300 for(fg = 0; fg < max; fg++) 301 { 302 /* Use ((max + 7 - fg) % max) instead of fg so that colour 0 303 * is light gray on black. Some terminals don't like this 304 * colour pair to be redefined. */ 305 int col = ((max + 7 - fg) % max) + max * bg; 306 init_pair(col, curses_colors[fg], curses_colors[bg]); 307 kk->ncurses.attr[fg + 16 * bg] = COLOR_PAIR(col); 308 309 if(max == 8) 310 { 311 /* Bright fg on simple bg */ 312 kk->ncurses.attr[fg + 8 + 16 * bg] = A_BOLD | COLOR_PAIR(col); 313 /* Simple fg on bright bg */ 314 kk->ncurses.attr[fg + 16 * (bg + 8)] = A_BLINK 315 | COLOR_PAIR(col); 316 /* Bright fg on bright bg */ 317 kk->ncurses.attr[fg + 8 + 16 * (bg + 8)] = A_BLINK | A_BOLD 318 | COLOR_PAIR(col); 319 } 320 } 321 322 cucul_set_size(kk->qq, COLS, LINES); 323 } 324 else 325 #endif 326 #if defined(USE_CONIO) 327 if(kk->driver == CACA_DRIVER_CONIO) 328 { 329 gettextinfo(&kk->conio.ti); 330 kk->conio.screen = malloc(2 * kk->conio.ti.screenwidth 331 * kk->conio.ti.screenheight * sizeof(char)); 332 if(kk->conio.screen == NULL) 333 return -1; 334 # if defined(SCREENUPDATE_IN_PC_H) 335 ScreenRetrieve(kk->conio.screen); 336 # else 337 /* FIXME */ 338 # endif 339 cucul_set_size(kk->qq, kk->conio.ti.screenwidth, 340 kk->conio.ti.screenheight); 341 } 342 else 343 #endif 344 #if defined(USE_X11) 345 if(kk->driver == CACA_DRIVER_X11) 346 { 347 static int const x11_palette[] = 348 { 349 /* Standard curses colours */ 350 0x0, 0x0, 0x0, 351 0x0, 0x0, 0x8000, 352 0x0, 0x8000, 0x0, 353 0x0, 0x8000, 0x8000, 354 0x8000, 0x0, 0x0, 355 0x8000, 0x0, 0x8000, 356 0x8000, 0x8000, 0x0, 357 0x8000, 0x8000, 0x8000, 358 /* Extra values for xterm-16color */ 359 0x4000, 0x4000, 0x4000, 360 0x4000, 0x4000, 0xffff, 361 0x4000, 0xffff, 0x4000, 362 0x4000, 0xffff, 0xffff, 363 0xffff, 0x4000, 0x4000, 364 0xffff, 0x4000, 0xffff, 365 0xffff, 0xffff, 0x4000, 366 0xffff, 0xffff, 0xffff, 367 }; 368 369 Colormap colormap; 370 XSetWindowAttributes x11_winattr; 371 int (*old_error_handler)(Display *, XErrorEvent *); 372 char const *fonts[] = { NULL, "8x13bold", "fixed" }, **parser; 373 char const *geometry; 374 unsigned int width = 0, height = 0; 375 int i; 376 377 geometry = getenv("CACA_GEOMETRY"); 378 if(geometry && *(geometry)) 379 sscanf(geometry, "%ux%u", &width, &height); 380 381 if(width && height) 382 cucul_set_size(kk->qq, width, height); 383 384 kk->x11.dpy = XOpenDisplay(NULL); 385 if(kk->x11.dpy == NULL) 386 return -1; 387 388 fonts[0] = getenv("CACA_FONT"); 389 if(fonts[0] && *fonts[0]) 390 parser = fonts; 391 else 392 parser = fonts + 1; 393 394 /* Ignore font errors */ 395 old_error_handler = XSetErrorHandler(x11_error_handler); 396 397 /* Parse our font list */ 398 for( ; ; parser++) 399 { 400 if(!*parser) 401 { 402 XSetErrorHandler(old_error_handler); 403 XCloseDisplay(kk->x11.dpy); 404 return -1; 405 } 406 407 kk->x11.font = XLoadFont(kk->x11.dpy, *parser); 408 if(!kk->x11.font) 409 continue; 410 411 kk->x11.font_struct = XQueryFont(kk->x11.dpy, kk->x11.font); 412 if(!kk->x11.font_struct) 413 { 414 XUnloadFont(kk->x11.dpy, kk->x11.font); 415 continue; 416 } 417 418 break; 419 } 420 421 /* Reset the default X11 error handler */ 422 XSetErrorHandler(old_error_handler); 423 424 kk->x11.font_width = kk->x11.font_struct->max_bounds.width; 425 kk->x11.font_height = kk->x11.font_struct->max_bounds.ascent 426 + kk->x11.font_struct->max_bounds.descent; 427 kk->x11.font_offset = kk->x11.font_struct->max_bounds.descent; 428 429 colormap = DefaultColormap(kk->x11.dpy, DefaultScreen(kk->x11.dpy)); 430 for(i = 0; i < 16; i++) 431 { 432 XColor color; 433 color.red = x11_palette[i * 3]; 434 color.green = x11_palette[i * 3 + 1]; 435 color.blue = x11_palette[i * 3 + 2]; 436 XAllocColor(kk->x11.dpy, colormap, &color); 437 kk->x11.colors[i] = color.pixel; 438 } 439 440 x11_winattr.backing_store = Always; 441 x11_winattr.background_pixel = kk->x11.colors[0]; 442 x11_winattr.event_mask = ExposureMask | StructureNotifyMask; 443 444 kk->x11.window = 445 XCreateWindow(kk->x11.dpy, DefaultRootWindow(kk->x11.dpy), 0, 0, 446 kk->qq->width * kk->x11.font_width, 447 kk->qq->height * kk->x11.font_height, 448 0, 0, InputOutput, 0, 449 CWBackingStore | CWBackPixel | CWEventMask, 450 &x11_winattr); 451 452 XStoreName(kk->x11.dpy, kk->x11.window, "caca for X"); 453 454 XSelectInput(kk->x11.dpy, kk->x11.window, StructureNotifyMask); 455 XMapWindow(kk->x11.dpy, kk->x11.window); 456 457 kk->x11.gc = XCreateGC(kk->x11.dpy, kk->x11.window, 0, NULL); 458 XSetForeground(kk->x11.dpy, kk->x11.gc, kk->x11.colors[15]); 459 XSetFont(kk->x11.dpy, kk->x11.gc, kk->x11.font); 460 461 for(;;) 462 { 463 XEvent event; 464 XNextEvent(kk->x11.dpy, &event); 465 if (event.type == MapNotify) 466 break; 467 } 468 469 #if defined(HAVE_X11_XKBLIB_H) 470 /* Disable autorepeat */ 471 XkbSetDetectableAutoRepeat(kk->x11.dpy, True, &kk->x11.autorepeat); 472 if(!kk->x11.autorepeat) 473 XAutoRepeatOff(kk->x11.dpy); 474 #endif 475 476 XSelectInput(kk->x11.dpy, kk->x11.window, kk->x11.event_mask); 477 478 XSync(kk->x11.dpy, False); 479 480 kk->x11.pixmap = XCreatePixmap(kk->x11.dpy, kk->x11.window, 481 kk->qq->width * kk->x11.font_width, 482 kk->qq->height * kk->x11.font_height, 483 DefaultDepth(kk->x11.dpy, 484 DefaultScreen(kk->x11.dpy))); 485 486 kk->x11.new_width = kk->x11.new_height = 0; 487 } 488 else 489 #endif 490 #if defined(USE_WIN32) 491 if(kk->driver == CACA_DRIVER_WIN32) 492 { 493 CONSOLE_CURSOR_INFO cci; 494 CONSOLE_SCREEN_BUFFER_INFO csbi; 495 COORD size; 496 497 kk->win32.front = 498 CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 499 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); 500 if(!kk->win32.front || kk->win32.front == INVALID_HANDLE_VALUE) 501 return -1; 502 503 kk->win32.back = 504 CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 505 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); 506 if(!kk->win32.back || kk->win32.back == INVALID_HANDLE_VALUE) 507 return -1; 508 509 if(!GetConsoleScreenBufferInfo(kk->win32.hout, &csbi)) 510 return -1; 511 512 /* Sample code to get the biggest possible window */ 513 //size = GetLargestConsoleWindowSize(kk->win32.hout); 514 cucul_set_size(kk->qq, csbi.srWindow.Right - csbi.srWindow.Left + 1, 515 csbi.srWindow.Bottom - csbi.srWindow.Top + 1); 516 size.X = kk->qq->width; 517 size.Y = kk->qq->height; 518 SetConsoleScreenBufferSize(kk->win32.front, size); 519 SetConsoleScreenBufferSize(kk->win32.back, size); 520 521 SetConsoleMode(kk->win32.front, 0); 522 SetConsoleMode(kk->win32.back, 0); 523 524 GetConsoleCursorInfo(kk->win32.front, &cci); 525 cci.dwSize = 0; 526 cci.bVisible = FALSE; 527 SetConsoleCursorInfo(kk->win32.front, &cci); 528 SetConsoleCursorInfo(kk->win32.back, &cci); 529 530 SetConsoleActiveScreenBuffer(kk->win32.front); 531 532 kk->win32.buffer = malloc(kk->qq->width * kk->qq->height 533 * sizeof(CHAR_INFO)); 534 if(kk->win32.buffer == NULL) 535 return -1; 536 } 537 else 538 #endif 539 #if defined(USE_GL) 540 if(kk->driver == CACA_DRIVER_GL) 541 { 542 char *empty_texture; 543 char const *geometry; 544 char *argv[2] = { "", NULL }; 545 unsigned int width = 0, height = 0; 546 int argc = 1; 547 int i; 548 549 gl_kk = kk; 550 551 geometry = getenv("CACA_GEOMETRY"); 552 if(geometry && *(geometry)) 553 sscanf(geometry, "%ux%u", &width, &height); 554 555 if(width && height) 556 cucul_set_size(kk->qq, width, height); 557 558 kk->gl.font_width = 9; 559 kk->gl.font_height = 15; 560 561 kk->gl.width = kk->qq->width * kk->gl.font_width; 562 kk->gl.height = kk->qq->height * kk->gl.font_height; 563 564 kk->gl.resized = 0; 565 kk->gl.bit = 0; 566 567 kk->gl.mouse_changed = kk->gl.mouse_clicked = 0; 568 kk->gl.mouse_button = kk->gl.mouse_state = 0; 569 570 kk->gl.key = 0; 571 kk->gl.special_key = 0; 572 573 kk->gl.sw = 9.0f / 16.0f; 574 kk->gl.sh = 15.0f / 16.0f; 575 576 glutInit(&argc, argv); 577 578 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 579 glutInitWindowSize(kk->gl.width, kk->gl.height); 580 kk->gl.window = glutCreateWindow("caca for GL"); 581 582 gluOrtho2D(0, kk->gl.width, kk->gl.height, 0); 583 584 glDisable(GL_CULL_FACE); 585 glDisable(GL_DEPTH_TEST); 586 587 glutKeyboardFunc(gl_handle_keyboard); 588 glutSpecialFunc(gl_handle_special_key); 589 glutReshapeFunc(gl_handle_reshape); 590 591 glutMouseFunc(gl_handle_mouse); 592 glutMotionFunc(gl_handle_mouse_motion); 593 glutPassiveMotionFunc(gl_handle_mouse_motion); 594 595 glLoadIdentity(); 596 597 glMatrixMode(GL_PROJECTION); 598 glPushMatrix(); 599 glLoadIdentity(); 600 gluOrtho2D(0, kk->gl.width, kk->gl.height, 0); 601 602 glMatrixMode(GL_MODELVIEW); 603 84 85 int gl_init_graphics(caca_t *kk) 86 { 87 char *empty_texture; 88 char const *geometry; 89 char *argv[2] = { "", NULL }; 90 unsigned int width = 0, height = 0; 91 int argc = 1; 92 int i; 93 94 gl_kk = kk; 95 96 geometry = getenv("CACA_GEOMETRY"); 97 if(geometry && *(geometry)) 98 sscanf(geometry, "%ux%u", &width, &height); 99 100 if(width && height) 101 cucul_set_size(kk->qq, width, height); 102 103 kk->gl.font_width = 9; 104 kk->gl.font_height = 15; 105 106 kk->gl.width = kk->qq->width * kk->gl.font_width; 107 kk->gl.height = kk->qq->height * kk->gl.font_height; 108 109 kk->gl.resized = 0; 110 kk->gl.bit = 0; 111 112 kk->gl.mouse_changed = kk->gl.mouse_clicked = 0; 113 kk->gl.mouse_button = kk->gl.mouse_state = 0; 114 115 kk->gl.key = 0; 116 kk->gl.special_key = 0; 117 118 kk->gl.sw = 9.0f / 16.0f; 119 kk->gl.sh = 15.0f / 16.0f; 120 121 glutInit(&argc, argv); 122 123 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 124 glutInitWindowSize(kk->gl.width, kk->gl.height); 125 kk->gl.window = glutCreateWindow("caca for GL"); 126 127 gluOrtho2D(0, kk->gl.width, kk->gl.height, 0); 128 129 glDisable(GL_CULL_FACE); 130 glDisable(GL_DEPTH_TEST); 131 132 glutKeyboardFunc(gl_handle_keyboard); 133 glutSpecialFunc(gl_handle_special_key); 134 glutReshapeFunc(gl_handle_reshape); 135 136 glutMouseFunc(gl_handle_mouse); 137 glutMotionFunc(gl_handle_mouse_motion); 138 glutPassiveMotionFunc(gl_handle_mouse_motion); 139 140 glLoadIdentity(); 141 142 glMatrixMode(GL_PROJECTION); 143 glPushMatrix(); 144 glLoadIdentity(); 145 gluOrtho2D(0, kk->gl.width, kk->gl.height, 0); 146 147 glMatrixMode(GL_MODELVIEW); 148 149 glClear(GL_COLOR_BUFFER_BIT); 150 151 empty_texture = malloc(16 * 16 * 4); 152 if(empty_texture == NULL) 153 return -1; 154 155 memset(empty_texture, 0xff, 16 * 16 * 4); 156 glEnable(GL_TEXTURE_2D); 157 158 for(i = 0; i < 94; i++) 159 { 160 glGenTextures(1, (GLuint*)&kk->gl.id[i]); 161 glBindTexture(GL_TEXTURE_2D, kk->gl.id[i]); 162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 164 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 165 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture); 166 } 167 168 for(i = 0; i < 94; i++) 169 { 170 glDisable(GL_TEXTURE_2D); 604 171 glClear(GL_COLOR_BUFFER_BIT); 605 172 606 empty_texture = malloc(16 * 16 * 4); 607 if(empty_texture == NULL) 608 return -1; 609 610 memset(empty_texture, 0xff, 16 * 16 * 4); 173 glColor3f(1, 1, 1); 174 glRasterPos2f(0, 15); 175 glutBitmapCharacter(GLUT_BITMAP_9_BY_15, i + 32); 176 611 177 glEnable(GL_TEXTURE_2D); 612 613 for(i = 0; i < 94; i++) 614 { 615 glGenTextures(1, (GLuint*)&kk->gl.id[i]); 616 glBindTexture(GL_TEXTURE_2D, kk->gl.id[i]); 617 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 618 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 619 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 620 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture); 621 } 622 623 for(i = 0; i < 94; i++) 178 glBindTexture(GL_TEXTURE_2D, kk->gl.id[i]); 179 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 180 0, kk->gl.height - 16, 16, 16, 0); 181 182 glutMainLoopEvent(); 183 glutPostRedisplay(); 184 } 185 186 return 0; 187 } 188 189 int gl_end_graphics(caca_t *kk) 190 { 191 glutDestroyWindow(kk->gl.window); 192 return 0; 193 } 194 195 int gl_set_window_title(caca_t *kk, char const *title) 196 { 197 glutSetWindowTitle(title); 198 return 0; 199 } 200 201 unsigned int gl_get_window_width(caca_t *kk) 202 { 203 return kk->gl.width; 204 } 205 206 unsigned int gl_get_window_height(caca_t *kk) 207 { 208 return kk->gl.height; 209 } 210 211 void gl_display(caca_t *kk) 212 { 213 unsigned int x, y, line; 214 215 glClear(GL_COLOR_BUFFER_BIT); 216 217 line = 0; 218 for(y = 0; y < kk->gl.height; y += kk->gl.font_height) 219 { 220 uint8_t *attr = kk->qq->attr + line * kk->qq->width; 221 222 for(x = 0; x < kk->gl.width; x += kk->gl.font_width) 624 223 { 625 224 glDisable(GL_TEXTURE_2D); 626 glClear(GL_COLOR_BUFFER_BIT); 627 628 glColor3f(1, 1, 1); 629 glRasterPos2f(0, 15); 630 glutBitmapCharacter(GLUT_BITMAP_9_BY_15, i + 32); 631 632 glEnable(GL_TEXTURE_2D); 633 glBindTexture(GL_TEXTURE_2D, kk->gl.id[i]); 634 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 635 0, kk->gl.height - 16, 16, 16, 0); 636 637 glutMainLoopEvent(); 638 glutPostRedisplay(); 225 glColor4bv(gl_bgpal[attr[0] >> 4]); 226 glBegin(GL_QUADS); 227 glVertex2f(x, y); 228 glVertex2f(x + kk->gl.font_width, y); 229 glVertex2f(x + kk->gl.font_width, y + kk->gl.font_height); 230 glVertex2f(x, y + kk->gl.font_height); 231 glEnd(); 232 233 attr++; 639 234 } 640 } 641 else 642 #endif 643 { 644 /* Dummy */ 645 } 646 647 kk->delay = 0; 648 kk->rendertime = 0; 649 650 return 0; 651 } 652 653 int _caca_end_graphics(caca_t *kk) 654 { 655 #if defined(USE_SLANG) 656 /* Nothing to do */ 657 #endif 658 #if defined(USE_NCURSES) 659 /* Nothing to do */ 660 #endif 661 #if defined(USE_CONIO) 662 if(kk->driver == CACA_DRIVER_CONIO) 663 { 664 free(kk->conio.screen); 665 } 666 else 667 #endif 668 #if defined(USE_X11) 669 if(kk->driver == CACA_DRIVER_X11) 670 { 671 XSync(kk->x11.dpy, False); 672 #if defined(HAVE_X11_XKBLIB_H) 673 if(!kk->x11.autorepeat) 674 XAutoRepeatOn(kk->x11.dpy); 675 #endif 676 XFreePixmap(kk->x11.dpy, kk->x11.pixmap); 677 XFreeFont(kk->x11.dpy, kk->x11.font_struct); 678 XFreeGC(kk->x11.dpy, kk->x11.gc); 679 XUnmapWindow(kk->x11.dpy, kk->x11.window); 680 XDestroyWindow(kk->x11.dpy, kk->x11.window); 681 XCloseDisplay(kk->x11.dpy); 682 } 683 else 684 #endif 685 #if defined(USE_WIN32) 686 if(kk->driver == CACA_DRIVER_WIN32) 687 { 688 SetConsoleActiveScreenBuffer(kk->win32.hout); 689 CloseHandle(kk->win32.back); 690 CloseHandle(kk->win32.front); 691 } 692 else 693 #endif 694 #if defined(USE_GL) 695 if(kk->driver == CACA_DRIVER_GL) 696 { 697 glutDestroyWindow(kk->gl.window); 698 } 699 else 700 #endif 701 { 702 /* Dummy */ 703 } 704 705 return 0; 706 } 707 #endif /* _DOXYGEN_SKIP_ME */ 708 709 /** \brief Set the window title. 710 * 711 * If libcaca runs in a window, try to change its title. This works with 712 * the X11 and Win32 drivers. 713 * 714 * \param title The desired window title. 715 * \return 0 upon success, a non-zero value if an error occurs. 716 */ 717 int caca_set_window_title(caca_t *kk, char const *title) 718 { 719 #if defined(USE_X11) 720 if(kk->driver == CACA_DRIVER_X11) 721 { 722 XStoreName(kk->x11.dpy, kk->x11.window, title); 723 } 724 else 725 #endif 726 #if defined(USE_WIN32) 727 if(kk->driver == CACA_DRIVER_WIN32) 728 { 729 SetConsoleTitle(title); 730 } 731 else 732 #endif 733 #if defined(USE_GL) 734 if(kk->driver == CACA_DRIVER_GL) 735 { 736 glutSetWindowTitle(title); 737 } 738 else 739 #endif 740 { 741 /* Not supported */ 742 return -1; 743 } 744 745 return 0; 746 } 747 748 /** \brief Get the window width. 749 * 750 * If libcaca runs in a window, get the usable window width. This value can 751 * be used for aspect ratio calculation. If libcaca does not run in a window 752 * or if there is no way to know the font size, assume a 6x10 font is being 753 * used. Note that the units are not necessarily pixels. 754 * 755 * \return The window width. 756 */ 757 unsigned int caca_get_window_width(caca_t *kk) 758 { 759 #if defined(USE_X11) 760 if(kk->driver == CACA_DRIVER_X11) 761 { 762 return kk->qq->width * kk->x11.font_width; 763 } 764 else 765 #endif 766 #if defined(USE_WIN32) 767 if(kk->driver == CACA_DRIVER_WIN32) 768 { 769 /* FIXME */ 770 } 771 else 772 #endif 773 #if defined(USE_GL) 774 if(kk->driver == CACA_DRIVER_GL) 775 { 776 return kk->gl.width; 777 } 778 else 779 #endif 780 { 781 /* Dummy */ 782 } 783 784 /* Fallback to a 6x10 font */ 785 return kk->qq->width * 6; 786 } 787 788 /** \brief Get the window height. 789 * 790 * If libcaca runs in a window, get the usable window height. This value can 791 * be used for aspect ratio calculation. If libcaca does not run in a window 792 * or if there is no way to know the font size, assume a 6x10 font is being 793 * used. Note that the units are not necessarily pixels. 794 * 795 * \return The window height. 796 */ 797 unsigned int caca_get_window_height(caca_t *kk) 798 { 799 #if defined(USE_X11) 800 if(kk->driver == CACA_DRIVER_X11) 801 { 802 return kk->qq->height * kk->x11.font_height; 803 } 804 else 805 #endif 806 #if defined(USE_WIN32) 807 if(kk->driver == CACA_DRIVER_WIN32) 808 { 809 /* FIXME */ 810 } 811 else 812 #endif 813 #if defined(USE_GL) 814 if(kk->driver == CACA_DRIVER_GL) 815 { 816 return kk->gl.height; 817 } 818 else 819 #endif 820 { 821 /* Dummy */ 822 } 823 824 /* Fallback to a 6x10 font */ 825 return kk->qq->height * 10; 826 } 827 828 /** \brief Set the refresh delay. 829 * 830 * This function sets the refresh delay in microseconds. The refresh delay 831 * is used by caca_display() to achieve constant framerate. See the 832 * caca_display() documentation for more details. 833 * 834 * If the argument is zero, constant framerate is disabled. This is the 835 * default behaviour. 836 * 837 * \param usec The refresh delay in microseconds. 838 */ 839 void caca_set_delay(caca_t *kk, unsigned int usec) 840 { 841 kk->delay = usec; 842 } 843 844 /** \brief Get the average rendering time. 845 * 846 * This function returns the average rendering time, which is the average 847 * measured time between two caca_display() calls, in microseconds. If 848 * constant framerate was activated by calling caca_set_delay(), the average 849 * rendering time will not be considerably shorter than the requested delay 850 * even if the real rendering time was shorter. 851 * 852 * \return The render time in microseconds. 853 */ 854 unsigned int caca_get_rendertime(caca_t *kk) 855 { 856 return kk->rendertime; 857 } 858 859 /** \brief Flush pending changes and redraw the screen. 860 * 861 * This function flushes all graphical operations and prints them to the 862 * screen. Nothing will show on the screen until caca_display() is 863 * called. 864 * 865 * If caca_set_delay() was called with a non-zero value, caca_display() 866 * will use that value to achieve constant framerate: if two consecutive 867 * calls to caca_display() are within a time range shorter than the value 868 * set with caca_set_delay(), the second call will wait a bit before 869 * performing the screen refresh. 870 */ 871 void caca_display(caca_t *kk) 872 { 873 #if !defined(_DOXYGEN_SKIP_ME) 874 #define IDLE_USEC 10000 875 #endif 876 int ticks = kk->lastticks + _caca_getticks(&kk->timer); 877 878 #if defined(USE_SLANG) 879 if(kk->driver == CACA_DRIVER_SLANG) 880 { 881 int x, y; 882 uint8_t *attr = kk->qq->attr; 883 uint32_t *chars = kk->qq->chars; 884 for(y = 0; y < (int)kk->qq->height; y++) 235 236 line++; 237 } 238 239 /* 2nd pass, avoids changing render state too much */ 240 glEnable(GL_BLEND); 241 glEnable(GL_TEXTURE_2D); 242 glBlendFunc(GL_ONE, GL_ONE); 243 244 line = 0; 245 for(y = 0; y < kk->gl.height; y += kk->gl.font_height) 246 { 247 uint8_t *attr = kk->qq->attr + line * kk->qq->width; 248 uint32_t *chars = kk->qq->chars + line * kk->qq->width; 249 250 for(x = 0; x < kk->gl.width; x += kk->gl.font_width) 885 251 { 886 SLsmg_gotorc(y, 0); 887 for(x = kk->qq->width; x--; ) 252 if(*chars != (uint32_t)' ') 888 253 { 889 #if defined(OPTIMISE_SLANG_PALETTE) 890 /* If foreground == background, just don't use this colour 891 * pair, and print a space instead of the real character. */ 892 uint8_t fgcolor = *attr & 0xf; 893 uint8_t bgcolor = *attr >> 4; 894 if(fgcolor != bgcolor) 895 { 896 SLsmg_set_color(slang_assoc[*attr++]); 897 SLsmg_write_char(*chars++ & 0x7f); 898 } 899 else 900 { 901 if(fgcolor == CUCUL_COLOR_BLACK) 902 fgcolor = CUCUL_COLOR_WHITE; 903 else if(fgcolor == CUCUL_COLOR_WHITE 904 || fgcolor <= CUCUL_COLOR_LIGHTGRAY) 905 fgcolor = CUCUL_COLOR_BLACK; 906 else 907 fgcolor = CUCUL_COLOR_WHITE; 908 SLsmg_set_color(slang_assoc[fgcolor + 16 * bgcolor]); 909 SLsmg_write_char(' '); 910 chars++; 911 attr++; 912 } 913 #else 914 SLsmg_set_color(*attr++); 915 SLsmg_write_char(*chars++ & 0x7f); 916 #endif 917 } 918 } 919 SLsmg_refresh(); 920 } 921 else 922 #endif 923 #if defined(USE_NCURSES) 924 if(kk->driver == CACA_DRIVER_NCURSES) 925 { 926 int x, y; 927 uint8_t *attr = kk->qq->attr; 928 uint32_t *chars = kk->qq->chars; 929 for(y = 0; y < (int)kk->qq->height; y++) 930 { 931 move(y, 0); 932 for(x = kk->qq->width; x--; ) 933 { 934 attrset(kk->ncurses.attr[*attr++]); 935 addch(*chars++ & 0x7f); 936 } 937 } 938 refresh(); 939 } 940 else 941 #endif 942 #if defined(USE_CONIO) 943 if(kk->driver == CACA_DRIVER_CONIO) 944 { 945 int n; 946 char *screen = kk->conio.screen; 947 uint8_t *attr = kk->qq->attr; 948 uint32_t *chars = kk->qq->chars; 949 for(n = kk->qq->height * kk->qq->width; n--; ) 950 { 951 *screen++ = *chars++ & 0x7f; 952 *screen++ = *attr++; 953 } 954 # if defined(SCREENUPDATE_IN_PC_H) 955 ScreenUpdate(kk->conio.screen); 956 # else 957 /* FIXME */ 958 # endif 959 } 960 else 961 #endif 962 #if defined(USE_X11) 963 if(kk->driver == CACA_DRIVER_X11) 964 { 965 unsigned int x, y, len; 966 967 /* First draw the background colours. Splitting the process in two 968 * loops like this is actually slightly faster. */ 969 for(y = 0; y < kk->qq->height; y++) 970 { 971 for(x = 0; x < kk->qq->width; x += len) 972 { 973 uint8_t *attr = kk->qq->attr + x + y * kk->qq->width; 974 975 len = 1; 976 while(x + len < kk->qq->width 977 && (attr[len] >> 4) == (attr[0] >> 4)) 978 len++; 979 980 XSetForeground(kk->x11.dpy, kk->x11.gc, 981 kk->x11.colors[attr[0] >> 4]); 982 XFillRectangle(kk->x11.dpy, kk->x11.pixmap, kk->x11.gc, 983 x * kk->x11.font_width, y * kk->x11.font_height, 984 len * kk->x11.font_width, kk->x11.font_height); 985 } 986 } 987 988 /* Then print the foreground characters */ 989 for(y = 0; y < kk->qq->height; y++) 990 { 991 for(x = 0; x < kk->qq->width; x += len) 992 { 993 char buffer[BUFSIZ]; /* FIXME: use a smaller buffer */ 994 uint32_t *chars = kk->qq->chars + x + y * kk->qq->width; 995 uint8_t *attr = kk->qq->attr + x + y * kk->qq->width; 996 997 len = 1; 998 999 /* Skip spaces */ 1000 if(chars[0] == ' ') 1001 continue; 1002 1003 buffer[0] = chars[0] & 0x7f; 1004 1005 while(x + len < kk->qq->width 1006 && (attr[len] & 0xf) == (attr[0] & 0xf)) 1007 { 1008 buffer[len] = chars[len] & 0x7f; 1009 len++; 1010 } 1011 1012 XSetForeground(kk->x11.dpy, kk->x11.gc, kk->x11.colors[attr[0] & 0xf]); 1013 XDrawString(kk->x11.dpy, kk->x11.pixmap, kk->x11.gc, 1014 x * kk->x11.font_width, 1015 (y + 1) * kk->x11.font_height - kk->x11.font_offset, 1016 buffer, len); 1017 } 1018 } 1019 1020 XCopyArea(kk->x11.dpy, kk->x11.pixmap, kk->x11.window, kk->x11.gc, 0, 0, 1021 kk->qq->width * kk->x11.font_width, kk->qq->height * kk->x11.font_height, 1022 0, 0); 1023 XFlush(kk->x11.dpy); 1024 } 1025 else 1026 #endif 1027 #if defined(USE_WIN32) 1028 if(kk->driver == CACA_DRIVER_WIN32) 1029 { 1030 COORD size, pos; 1031 SMALL_RECT rect; 1032 unsigned int i; 1033 1034 /* Render everything to our back buffer */ 1035 for(i = 0; i < kk->qq->width * kk->qq->height; i++) 1036 { 1037 kk->win32.buffer[i].Char.AsciiChar = kk->qq->chars[i] & 0x7f; 1038 kk->win32.buffer[i].Attributes = 1039 win32_fg_palette[kk->qq->attr[i] & 0xf] 1040 | win32_bg_palette[kk->qq->attr[i] >> 4]; 1041 } 1042 1043 /* Blit the back buffer to the front buffer */ 1044 size.X = kk->qq->width; 1045 size.Y = kk->qq->height; 1046 pos.X = pos.Y = 0; 1047 rect.Left = rect.Top = 0; 1048 rect.Right = kk->qq->width - 1; 1049 rect.Bottom = kk->qq->height - 1; 1050 WriteConsoleOutput(kk->win32.front, kk->win32.buffer, size, pos, &rect); 1051 } 1052 else 1053 #endif 1054 #if defined(USE_GL) 1055 if(kk->driver == CACA_DRIVER_GL) 1056 { 1057 unsigned int x, y, line; 1058 1059 glClear(GL_COLOR_BUFFER_BIT); 1060 1061 line = 0; 1062 for(y = 0; y < kk->gl.height; y += kk->gl.font_height) 1063 { 1064 uint8_t *attr = kk->qq->attr + line * kk->qq->width; 1065 1066 for(x = 0; x < kk->gl.width; x += kk->gl.font_width) 1067 { 1068 glDisable(GL_TEXTURE_2D); 1069 glColor4bv(gl_bgpal[attr[0] >> 4]); 254 char ch = *chars & 0x7f; 255 256 /* FIXME: check ch bounds */ 257 glBindTexture(GL_TEXTURE_2D, kk->gl.id[ch - 32]); 258 glColor4bv(gl_bgpal[attr[0] & 0xf]); 1070 259 glBegin(GL_QUADS); 260 glTexCoord2f(0, kk->gl.sh); 1071 261 glVertex2f(x, y); 262 glTexCoord2f(kk->gl.sw, kk->gl.sh); 1072 263 glVertex2f(x + kk->gl.font_width, y); 264 glTexCoord2f(kk->gl.sw, 0); 1073 265 glVertex2f(x + kk->gl.font_width, y + kk->gl.font_height); 266 glTexCoord2f(0, 0); 1074 267 glVertex2f(x, y + kk->gl.font_height); 1075 268 glEnd(); 1076 1077 attr++;1078 269 } 1079 270 1080 line++; 271 attr++; 272 chars++; 1081 273 } 1082 1083 /* 2nd pass, avoids changing render state too much */ 1084 glEnable(GL_BLEND); 1085 glEnable(GL_TEXTURE_2D); 1086 glBlendFunc(GL_ONE, GL_ONE); 1087 1088 line = 0; 1089 for(y = 0; y < kk->gl.height; y += kk->gl.font_height) 1090 { 1091 uint8_t *attr = kk->qq->attr + line * kk->qq->width; 1092 uint32_t *chars = kk->qq->chars + line * kk->qq->width; 1093 1094 for(x = 0; x < kk->gl.width; x += kk->gl.font_width) 1095 { 1096 if(*chars != (uint32_t)' ') 1097 { 1098 char ch = *chars & 0x7f; 1099 1100 /* FIXME: check ch bounds */ 1101 glBindTexture(GL_TEXTURE_2D, kk->gl.id[ch - 32]); 1102 glColor4bv(gl_bgpal[attr[0] & 0xf]); 1103 glBegin(GL_QUADS); 1104 glTexCoord2f(0, kk->gl.sh); 1105 glVertex2f(x, y); 1106 glTexCoord2f(kk->gl.sw, kk->gl.sh); 1107 glVertex2f(x + kk->gl.font_width, y); 1108 glTexCoord2f(kk->gl.sw, 0); 1109 glVertex2f(x + kk->gl.font_width, y + kk->gl.font_height); 1110 glTexCoord2f(0, 0); 1111 glVertex2f(x, y + kk->gl.font_height); 1112 glEnd(); 1113 } 1114 1115 attr++; 1116 chars++; 1117 } 1118 line++; 1119 } 1120 glDisable(GL_BLEND); 1121 glDisable(GL_TEXTURE_2D); 1122 1123 glutMainLoopEvent(); 1124 glutSwapBuffers(); 1125 glutPostRedisplay(); 1126 } 1127 else 1128 #endif 1129 { 1130 /* Dummy */ 1131 } 1132 1133 /* FIXME handle this somewhere else */ 1134 if(kk->resize) 1135 { 1136 kk->resize = 0; 1137 caca_handle_resize(kk); 1138 } 1139 1140 /* Wait until kk->delay + time of last call */ 1141 ticks += _caca_getticks(&kk->timer); 1142 for(ticks += _caca_getticks(&kk->timer); 1143 ticks + IDLE_USEC < (int)kk->delay; 1144 ticks += _caca_getticks(&kk->timer)) 1145 { 1146 _caca_sleep(IDLE_USEC); 1147 } 1148 1149 /* Update the sliding mean of the render time */ 1150 kk->rendertime = (7 * kk->rendertime + ticks) / 8; 1151 1152 kk->lastticks = ticks - kk->delay; 1153 1154 /* If we drifted too much, it's bad, bad, bad. */ 1155 if(kk->lastticks > (int)kk->delay) 1156 kk->lastticks = 0; 1157 } 1158 1159 /* 1160 * XXX: following functions are local 1161 */ 1162 1163 static void caca_handle_resize(caca_t *kk) 274 line++; 275 } 276 glDisable(GL_BLEND); 277 glDisable(GL_TEXTURE_2D); 278 279 glutMainLoopEvent(); 280 glutSwapBuffers(); 281 glutPostRedisplay(); 282 } 283 284 void gl_handle_resize(caca_t *kk) 1164 285 { 1165 286 unsigned int new_width, new_height; … … 1168 289 new_height = kk->qq->height; 1169 290 1170 #if defined(USE_SLANG) 1171 if(kk->driver == CACA_DRIVER_SLANG) 1172 { 1173 SLtt_get_screen_size(); 1174 new_width = SLtt_Screen_Cols; 1175 new_height = SLtt_Screen_Rows; 1176 1177 if(new_width != kk->qq->width || new_height != kk->qq->height) 1178 SLsmg_reinit_smg(); 1179 } 1180 else 1181 #endif 1182 #if defined(USE_NCURSES) 1183 if(kk->driver == CACA_DRIVER_NCURSES) 1184 { 1185 struct winsize size; 1186 1187 if(ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) 1188 { 1189 new_width = size.ws_col; 1190 new_height = size.ws_row; 1191 #if defined(HAVE_RESIZE_TERM) 1192 resize_term(new_height, new_width); 1193 #else 1194 resizeterm(new_height, new_width); 1195 #endif 1196 wrefresh(curscr); 1197 } 1198 } 1199 else 1200 #endif 1201 #if defined(USE_CONIO) 1202 if(kk->driver == CACA_DRIVER_CONIO) 1203 { 1204 /* Nothing to do here. */ 1205 } 1206 else 1207 #endif 1208 #if defined(USE_X11) 1209 if(kk->driver == CACA_DRIVER_X11) 1210 { 1211 Pixmap new_pixmap; 1212 1213 new_width = kk->x11.new_width; 1214 new_height = kk->x11.new_height; 1215 1216 new_pixmap = XCreatePixmap(kk->x11.dpy, kk->x11.window, 1217 kk->qq->width * kk->x11.font_width, 1218 kk->qq->height * kk->x11.font_height, 1219 DefaultDepth(kk->x11.dpy, 1220 DefaultScreen(kk->x11.dpy))); 1221 XCopyArea(kk->x11.dpy, kk->x11.pixmap, new_pixmap, kk->x11.gc, 0, 0, 1222 kk->qq->width * kk->x11.font_width, 1223 kk->qq->height * kk->x11.font_height, 0, 0); 1224 XFreePixmap(kk->x11.dpy, kk->x11.pixmap); 1225 kk->x11.pixmap = new_pixmap; 1226 } 1227 else 1228 #endif 1229 #if defined(USE_WIN32) 1230 if(kk->driver == CACA_DRIVER_WIN32) 1231 { 1232 /* Nothing to do here. */ 1233 } 1234 else 1235 #endif 1236 #if defined(USE_GL) 1237 if(kk->driver == CACA_DRIVER_GL) 1238 { 1239 kk->gl.width = kk->gl.new_width; 1240 kk->gl.height = kk->gl.new_height; 1241 1242 new_width = kk->gl.width / kk->gl.font_width; 1243 new_height = (kk->gl.height / kk->gl.font_height) + 1; 1244 1245 glMatrixMode(GL_PROJECTION); 1246 glPushMatrix(); 1247 glLoadIdentity(); 1248 1249 glViewport(0, 0, kk->gl.width, kk->gl.height); 1250 gluOrtho2D(0, kk->gl.width, kk->gl.height, 0); 1251 glMatrixMode(GL_MODELVIEW); 1252 } 1253 else 1254 #endif 1255 { 1256 /* Dummy */ 1257 } 1258 1259 /* Tell libcucul we changed size */ 1260 if(new_width != kk->qq->width || new_height != kk->qq->height) 1261 cucul_set_size(kk->qq, new_width, new_height); 1262 } 1263 1264 #if defined(USE_SLANG) 1265 static void slang_init_palette(void) 1266 { 1267 /* See SLang ref., 5.4.4. */ 1268 static char *slang_colors[16] = 1269 { 1270 /* Standard colours */ 1271 "black", 1272 "blue", 1273 "green", 1274 "cyan", 1275 "red", 1276 "magenta", 1277 "brown", 1278 "lightgray", 1279 /* Bright colours */ 1280 "gray", 1281 "brightblue", 1282 "brightgreen", 1283 "brightcyan", 1284 "brightred", 1285 "brightmagenta", 1286 "yellow", 1287 "white", 1288 }; 1289 1290 #if defined(OPTIMISE_SLANG_PALETTE) 1291 int i; 1292 1293 for(i = 0; i < 16 * 16; i++) 1294 SLtt_set_color(i, NULL, slang_colors[slang_palette[i * 2]], 1295 slang_colors[slang_palette[i * 2 + 1]]); 1296 #else 1297 int fg, bg; 1298 1299 for(bg = 0; bg < 16; bg++) 1300 for(fg = 0; fg < 16; fg++) 1301 { 1302 int i = fg + 16 * bg; 1303 SLtt_set_color(i, NULL, slang_colors[fg], slang_colors[bg]); 1304 } 1305 #endif 1306 } 1307 #endif /* USE_SLANG */ 1308 1309 #if defined(USE_X11) 1310 static int x11_error_handler(Display *dpy, XErrorEvent *event) 1311 { 1312 /* Ignore the error */ 1313 return 0; 1314 } 1315 #endif 1316 1317 #if defined(HAVE_SIGNAL) && (defined(USE_NCURSES) || defined(USE_SLANG)) 1318 static RETSIGTYPE sigwinch_handler(int sig) 1319 { 1320 sigwinch_kk->resize_event = 1; 1321 1322 signal(SIGWINCH, sigwinch_handler);; 1323 } 1324 #endif 1325 1326 #if defined(USE_GL) 291 kk->gl.width = kk->gl.new_width; 292 kk->gl.height = kk->gl.new_height; 293 294 new_width = kk->gl.width / kk->gl.font_width; 295 new_height = (kk->gl.height / kk->gl.font_height) + 1; 296 297 glMatrixMode(GL_PROJECTION); 298 glPushMatrix(); 299 glLoadIdentity(); 300 301 glViewport(0, 0, kk->gl.width, kk->gl.height); 302 gluOrtho2D(0, kk->gl.width, kk->gl.height, 0); 303 glMatrixMode(GL_MODELVIEW); 304 } 305 306 /* 307 * XXX: following functions are local 308 */ 309 1327 310 static void gl_handle_keyboard(unsigned char key, int x, int y) 1328 311 { … … 1374 357 kk->gl.mouse_changed = 1; 1375 358 } 1376 #endif 1377 359 360 /* 361 * Driver initialisation 362 */ 363 364 void gl_init_driver(caca_t *kk) 365 { 366 kk->driver.driver = CACA_DRIVER_GL; 367 368 kk->driver.init_graphics = gl_init_graphics; 369 kk->driver.end_graphics = gl_end_graphics; 370 kk->driver.set_window_title = gl_set_window_title; 371 kk->driver.get_window_width = gl_get_window_width; 372 kk->driver.get_window_height = gl_get_window_height; 373 kk->driver.display = gl_display; 374 kk->driver.handle_resize = gl_handle_resize; 375 } 376 377 #endif /* USE_GL */ 378
Note: See TracChangeset
for help on using the changeset viewer.