Ignore:
Timestamp:
Mar 7, 2006, 12:01:59 AM (14 years ago)
Author:
Sam Hocevar
Message:
  • Split caca/graphics.c into driver-specific files. Resize is currently broken, and event handling is not yet in the driver-specific files, but I will of course fix that later.
File:
1 copied

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/caca/driver_gl.c

    r537 r539  
    2020#include "config.h"
    2121
    22 #if defined(USE_SLANG)
    23 #   if defined(HAVE_SLANG_SLANG_H)
    24 #       include <slang/slang.h>
    25 #   else
    26 #       include <slang.h>
    27 #   endif
    28 #endif
    29 #if defined(USE_NCURSES)
    30 #   if defined(HAVE_NCURSES_H)
    31 #       include <ncurses.h>
    32 #   else
    33 #       include <curses.h>
    34 #   endif
    35 #endif
    36 #if defined(USE_CONIO)
    37 #   include <conio.h>
    38 #   if defined(SCREENUPDATE_IN_PC_H)
    39 #       include <pc.h>
    40 #   endif
    41 #endif
    42 #if defined(USE_X11)
    43 #   include <X11/Xlib.h>
    44 #   if defined(HAVE_X11_XKBLIB_H)
    45 #       include <X11/XKBlib.h>
    46 #   endif
    47 #endif
    48 #if defined(USE_WIN32)
    49 #   include <windows.h>
    50 #endif
    51 #if defined(USE_GL)
    52 #   include <GL/gl.h>
    53 #   include <GL/glut.h>
    54 #   include <GL/freeglut_ext.h>
    55 #endif
    5622#if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
    5723#   include <inttypes.h>
     
    6026typedef unsigned char uint8_t;
    6127#endif
     28
     29#if defined(USE_GL)
     30
     31#include <GL/gl.h>
     32#include <GL/glut.h>
     33#include <GL/freeglut_ext.h>
    6234
    6335#include <stdio.h> /* BUFSIZ */
     
    6941#include <stdarg.h>
    7042
    71 #if defined(HAVE_SIGNAL_H)
    72 #   include <signal.h>
    73 #endif
    74 #if defined(HAVE_SYS_IOCTL_H)
    75 #   include <sys/ioctl.h>
    76 #endif
    77 
    7843#include "caca.h"
    7944#include "caca_internals.h"
     
    8550 */
    8651
    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 #endif
    145 
    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_BLUE
    165 };
    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_BLUE
    185 };
    186 #endif
    187 
    188 #if defined(USE_GL)
    18952/* Ok, I just suck. */
    19053static GLbyte const gl_bgpal[][4] =
     
    21073
    21174static caca_t *gl_kk; /* FIXME: we ought to get rid of this */
    212 #endif
    21375
    21476/*
    21577 * Local functions
    21678 */
    217 static void caca_handle_resize(caca_t *kk);
    218 
    219 #if defined(USE_SLANG)
    220 static void slang_init_palette(void);
    221 #endif
    222 
    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 #endif
    227 
    228 #if defined(USE_X11)
    229 static int x11_error_handler(Display *, XErrorEvent *);
    230 #endif
    231 
    232 #if defined(USE_GL)
    23379static void gl_handle_keyboard(unsigned char, int, int);
    23480static void gl_handle_special_key(int, int, int);
     
    23682static void gl_handle_mouse(int, int, int, int);
    23783static 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
     85int 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);
    604171        glClear(GL_COLOR_BUFFER_BIT);
    605172
    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
    611177        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
     189int gl_end_graphics(caca_t *kk)
     190{
     191    glutDestroyWindow(kk->gl.window);
     192    return 0;
     193}
     194
     195int gl_set_window_title(caca_t *kk, char const *title)
     196{
     197    glutSetWindowTitle(title);
     198    return 0;
     199}
     200
     201unsigned int gl_get_window_width(caca_t *kk)
     202{
     203    return kk->gl.width;
     204}
     205
     206unsigned int gl_get_window_height(caca_t *kk)
     207{
     208    return kk->gl.height;
     209}
     210
     211void 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)
    624223        {
    625224            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++;
    639234        }
    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)
    885251        {
    886             SLsmg_gotorc(y, 0);
    887             for(x = kk->qq->width; x--; )
     252            if(*chars != (uint32_t)' ')
    888253            {
    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]);
    1070259                glBegin(GL_QUADS);
     260                    glTexCoord2f(0, kk->gl.sh);
    1071261                    glVertex2f(x, y);
     262                    glTexCoord2f(kk->gl.sw, kk->gl.sh);
    1072263                    glVertex2f(x + kk->gl.font_width, y);
     264                    glTexCoord2f(kk->gl.sw, 0);
    1073265                    glVertex2f(x + kk->gl.font_width, y + kk->gl.font_height);
     266                    glTexCoord2f(0, 0);
    1074267                    glVertex2f(x, y + kk->gl.font_height);
    1075268                glEnd();
    1076 
    1077                 attr++;
    1078269            }
    1079270
    1080             line++;
     271            attr++;
     272            chars++;
    1081273        }
    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
     284void gl_handle_resize(caca_t *kk)
    1164285{
    1165286    unsigned int new_width, new_height;
     
    1168289    new_height = kk->qq->height;
    1169290
    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
    1327310static void gl_handle_keyboard(unsigned char key, int x, int y)
    1328311{
     
    1374357    kk->gl.mouse_changed = 1;
    1375358}
    1376 #endif
    1377 
     359
     360/*
     361 * Driver initialisation
     362 */
     363
     364void 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.