home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / contrib / seejpeg / seejpeg-.4 / seejpeg- / seejpeg-1.4.3 / display.c < prev    next >
C/C++ Source or Header  |  1994-04-05  |  14KB  |  537 lines

  1.  
  2. /*
  3.  * display.c
  4.  *
  5.  * Copyright (C) 1993, 1994 Evan Harris
  6.  *
  7.  * Permission is granted to freely redistribute and modify this code,
  8.  * providing the author(s) get credit for having written it.
  9.  */
  10.  
  11. /*
  12.  * (Evan) PIX_ALIGN changes inspired by Michael Weller, who patched against
  13.  * version 1.1:
  14.  *
  15.  * Patched to not depend on illegal assumptions (xbytes==bytesperpixel*xdim),
  16.  *         to obey logical_width a multiple of 8 pixels (not bytes)
  17.  *         to let logical_width be an even higher multiple of a power of two
  18.  *         for spike free video signal on Mach32
  19.  * 16. 3. 94 Michael Weller (eowmob@exp-math.uni-essen.de or
  20.  * eowmob@pollux.exp-math.uni-essen.de or mat42b@vm.hrz.uni-essen.de or
  21.  * mat42b@de0hrz1a.bitnet) (svgalib, mach32-driver)
  22.  */
  23.  
  24. #include "seejpeg.h"
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <vga.h>
  28.  
  29.  
  30. /*
  31.  * Set PIX_ALIGN to be 64 because it seems to be a nice safe value.
  32.  * Some cards can handle values much lower (which is desirable).
  33.  * If your card can I would recommend trying values of 8, 16 or 32
  34.  * before 64 (in the Makefile).
  35.  * My CLGD5426 works correctly with a value of 8. 
  36.  */
  37. #ifndef PIX_ALIGN
  38. #define PIX_ALIGN 64
  39. #endif
  40.  
  41.  
  42. struct best_mode_struct {
  43.     int min_width;
  44.     int min_height;
  45.     int mode;
  46.     int mode_width;
  47.     int mode_height;
  48.     int mode_depth;
  49. };
  50.  
  51. static struct best_mode_struct best_mode_256[] = {
  52. { 1024, 768, G1280x1024x256, 1280, 1024, 256 },
  53. {  800, 600,  G1024x768x256, 1024,  768, 256 },
  54. {  640, 480,   G800x600x256,  800,  600, 256 },
  55. #if 0
  56. {  360, 480,   G640x480x256,  640,  480, 256 },
  57.     /* we currently can't cope with the planar video modes */
  58. {  320, 400,   G360x480x256,  360,  480, 256 },
  59. {  320, 240,   G320x400x256,  320,  400, 256 },
  60. {  320, 200,   G320x240x256,  320,  240, 256 },
  61. #else
  62. {  320, 200,   G640x480x256,  640,  480, 256 },
  63. #endif  
  64. {    0,   0,   G320x200x256,  320,  200, 256 },
  65. };
  66.  
  67. static struct best_mode_struct best_mode_32k16m[] = {
  68. { 1024, 768, G1280x1024x16M, 1280, 1024, 16777216 },
  69. { 1024, 768, G1280x1024x32K, 1280, 1024,    32768 },
  70. {  800, 600,  G1024x768x16M, 1024,  768, 16777216 },
  71. {  800, 600,  G1024x768x32K, 1024,  768,    32768 },
  72. {  640, 480,   G800x600x16M,  800,  600, 16777216 },
  73. {  640, 480,   G800x600x32K,  800,  600,    32768 },
  74. {  320, 200,   G640x480x16M,  640,  480, 16777216 },
  75. {  320, 200,   G640x480x32K,  640,  480,    32768 },
  76. {    1,   1,   G320x200x16M,  320,  200, 16777216 },
  77. {    0,   0,   G320x200x32K,  320,  200,    32768 },
  78. };
  79.  
  80. static int logical_width, logical_height;
  81. static int logical_byte_width, bytesperpixel;
  82. static int mode_width, mode_height, mode_depth, start_row, mode_linewidth;
  83.  
  84.  
  85. /*
  86.  * Select the best video mode for the current video card.
  87.  *
  88.  * components: 3 for RGB, 1 for grayscale or colourmapped
  89.  */
  90.  
  91. int
  92. best_mode(int width, int height, int components)
  93. {
  94.     int mode, i;
  95. #ifndef NO_32K_CASCADE
  96.     vga_modeinfo *vgainfo;
  97.     int bytesperpixel, logical_byte_width, logical_width, logical_height;
  98. #endif  
  99.  
  100.     if (opt_forcemode != TEXT) {
  101.     if (vga_hasmode(opt_forcemode)) {
  102.         if (components == 1) {
  103.         i = 0;
  104.         do {
  105.             if (best_mode_256[i].mode == opt_forcemode) {
  106.             mode_width = best_mode_256[i].mode_width;
  107.             mode_height = best_mode_256[i].mode_height;
  108.             mode_depth = best_mode_256[i].mode_depth;
  109.             return opt_forcemode;
  110.             }
  111.         } while (best_mode_256[i++].min_width > 0);
  112.         } else if (components == 3) {
  113.         i = 0;
  114.         do {
  115.             if (best_mode_32k16m[i].mode == opt_forcemode) {
  116.             mode_width = best_mode_32k16m[i].mode_width;
  117.             mode_height = best_mode_32k16m[i].mode_height;
  118.             mode_depth = best_mode_32k16m[i].mode_depth;
  119.             return opt_forcemode;
  120.             }
  121.         } while (best_mode_32k16m[i++].min_width > 0);
  122.         }
  123.  
  124.         error_exit("Selected mode not supported for this image type");
  125.     } else {
  126.         error_exit("Selected mode not supported by chipset");
  127.     }
  128.     }
  129.  
  130.     mode = TEXT;
  131.  
  132.     if (components == 1) {
  133.  
  134.     i = 0;
  135.     do {
  136.         if ((opt_fuzz * width > best_mode_256[i].min_width
  137.          || (opt_fuzz * height > best_mode_256[i].min_height
  138.              && !opt_widthonly))
  139.         && vga_hasmode(best_mode_256[i].mode)) {
  140.         mode = best_mode_256[i].mode;
  141.         mode_width = best_mode_256[i].mode_width;
  142.         mode_height = best_mode_256[i].mode_height;
  143.         mode_depth = best_mode_256[i].mode_depth;
  144.         }
  145.     } while (mode == TEXT && best_mode_256[i++].min_width > 0);
  146.     if (mode == TEXT) {
  147.         error_exit("Cannot find a 256 colour video mode");
  148.     }
  149.  
  150.     } else if (components == 3) {
  151.  
  152.     i = 0;
  153.     do {
  154.         if ((opt_fuzz * width > best_mode_32k16m[i].min_width
  155.          || (opt_fuzz * height > best_mode_32k16m[i].min_height
  156.              && !opt_widthonly))
  157.         && vga_hasmode(best_mode_32k16m[i].mode)) {
  158.         mode = best_mode_32k16m[i].mode;
  159.         mode_width = best_mode_32k16m[i].mode_width;
  160.         mode_height = best_mode_32k16m[i].mode_height;
  161.         mode_depth = best_mode_32k16m[i].mode_depth;
  162.  
  163. #ifndef NO_32K_CASCADE
  164.         vgainfo = vga_getmodeinfo(mode);
  165.     
  166.         bytesperpixel = vgainfo->bytesperpixel;
  167.         mode_linewidth = vgainfo->linewidth;
  168.         
  169.         logical_byte_width =
  170.             MAX(mode_linewidth, width * bytesperpixel);
  171.         if (logical_byte_width % PIX_ALIGN != 0) {
  172.             logical_byte_width +=
  173.             PIX_ALIGN - logical_byte_width % PIX_ALIGN;
  174.         }
  175.         if (logical_byte_width % (bytesperpixel * PIX_ALIGN) != 0) {
  176.             logical_byte_width += (bytesperpixel * PIX_ALIGN)
  177.             - logical_byte_width % (bytesperpixel * PIX_ALIGN);
  178.         }
  179.         logical_width = logical_byte_width / bytesperpixel;
  180.         logical_height = MIN(vgainfo->maxpixels * bytesperpixel / logical_byte_width, height);
  181.         if (height > logical_height && mode_depth == 16777216) {
  182.             mode = TEXT; /* assume a 32k mode will be available */
  183.         }
  184. #endif
  185.         }
  186.     } while (mode == TEXT && best_mode_32k16m[i++].min_width > 0);
  187.     if (mode == TEXT) {
  188.         error_exit("Cannot find a 32K/16M colour video mode");
  189.     }
  190.  
  191.     } else {
  192.     error_exit("Cannot cope with number of output components");
  193.     }
  194.  
  195.     return mode;
  196. }
  197.  
  198.  
  199. void
  200. clear_screen(int mode_width, int mode_height,
  201.          int logical_width, int logical_height)
  202. {
  203.   int line, lines;
  204.   
  205.   vga_screenoff();
  206.   
  207.   /* it's done by vga_setmode() but it can't hurt */
  208.   vga_clear();            
  209.  
  210.   vga_setpalette(0, 0, 0, 0);
  211.   vga_setcolor(0);
  212.   
  213.   logical_height = MAX(logical_height, mode_height);
  214.   
  215.   /* fillblit is much better, but it's not general */
  216.   if ((logical_width * logical_height + mode_width - 1) / mode_width
  217.       > mode_height) {
  218.     lines = ((logical_width * logical_height + mode_width - 1) / mode_width
  219.          - mode_height);
  220.     for (line = mode_height; line < mode_height + lines; line++) {
  221.       vga_drawline(0, line, mode_width, line);
  222.     }
  223.   }
  224.  
  225.   vga_screenon();
  226. }
  227.  
  228.  
  229. /* ----------------------------------------------------------------- */
  230.  
  231.  
  232. void
  233. display_init(int image_width, int image_height, int components)
  234. {
  235.     int mode;            /* our video mode */
  236.     int width, height;
  237.     vga_modeinfo *vgainfo;
  238.  
  239.     width = (opt_doublex ? 2 * image_width : image_width);
  240.     height = (opt_doubley ? 2 * image_height : image_height);
  241.  
  242.     mode = best_mode(width, height, components);
  243.  
  244.     vgainfo = vga_getmodeinfo(mode);
  245.  
  246.     bytesperpixel = vgainfo->bytesperpixel;
  247.     mode_linewidth = vgainfo->linewidth;
  248.   
  249.     logical_byte_width = MAX(mode_linewidth, width * bytesperpixel);
  250.     if (logical_byte_width % PIX_ALIGN != 0) {
  251.     logical_byte_width += PIX_ALIGN - logical_byte_width % PIX_ALIGN;
  252.     }
  253.  
  254.     /*
  255.      * I don't really understand why we need this.
  256.      * I wonder if it's documented somewhere...
  257.      * 
  258.      * (Michael, Mach32): well some cards want multiples of 8pixels in a row..
  259.      * it is that easy.. 
  260.      */
  261.     if (logical_byte_width % (bytesperpixel * PIX_ALIGN) != 0) {
  262.     logical_byte_width += (bytesperpixel * PIX_ALIGN)
  263.         - logical_byte_width % (bytesperpixel * PIX_ALIGN);
  264.     }
  265.  
  266.     while (logical_byte_width / bytesperpixel
  267.        > vgainfo->maxpixels / mode_height) {
  268.     logical_byte_width -= bytesperpixel * PIX_ALIGN;
  269.     }
  270.  
  271.     logical_width = logical_byte_width / bytesperpixel;
  272.     logical_height =
  273.     MIN(vgainfo->maxpixels * bytesperpixel / logical_byte_width, height);
  274.  
  275.     if (opt_verbose) {
  276.     printf("Image  : %dx%dx%d\n", image_width, image_height,
  277.            1 << (8 * components));
  278.     printf("Mode   : %dx%dx%d\n", mode_width, mode_height, mode_depth);
  279.     printf("Logical: %dx%d\n", logical_width, logical_height);
  280.     }
  281.  
  282. #ifdef BUG_WORKAROUND
  283.     vga_setmode(TEXT);
  284. #endif    
  285.     if (vga_getcurrentmode() != mode) {
  286.     vga_setmode(mode);
  287.     }
  288.     vga_setdisplaystart(0);
  289.     vga_setlogicalwidth(logical_byte_width);
  290.  
  291.     start_row = 0;
  292.  
  293.     clear_screen(mode_width, mode_height, logical_width, logical_height);
  294. }
  295.  
  296.  
  297. void
  298. display_set_palette(int num_colors, JSAMPARRAY colormap, int components)
  299. {
  300.   int i;
  301.  
  302.   for (i = 0; i < num_colors; i++) {
  303.     /* we should put these in an array so there's only one syscall */
  304.     if (components == 1) {
  305.       vga_setpalette(i, GETJSAMPLE(colormap[0][i]) >> 2,
  306.              GETJSAMPLE(colormap[0][i]) >> 2,
  307.              GETJSAMPLE(colormap[0][i]) >> 2);
  308.     } else if (components == 3) {
  309.       vga_setpalette(i, GETJSAMPLE(colormap[0][i]) >> 2,
  310.              GETJSAMPLE(colormap[1][i]) >> 2,
  311.              GETJSAMPLE(colormap[2][i]) >> 2);
  312.     } else {
  313.       error_exit("Cannot cope with number of colour components");
  314.     }
  315.   }
  316. }
  317.  
  318.  
  319. void
  320. display_set_greyscale_palette()
  321. {
  322.   int i;
  323.  
  324.   for (i = 0; i < 256; i++) {
  325.     vga_setpalette(i, i >> 2, i >> 2, i >> 2);
  326.   }
  327. }
  328.  
  329.  
  330. void
  331. display_rows(int num_rows, JSAMPIMAGE pixel_data, int image_width,
  332.          int components)
  333. {
  334.     JSAMPROW ptr0, ptr1, ptr2;
  335.     int row, col;
  336.     int width, height;
  337.     int mode_row, mode_col;
  338.  
  339.     if (opt_doublex) {
  340.     width = MIN(image_width, logical_width / 2);
  341.     } else {
  342.     width = MIN(image_width, logical_width);
  343.     }
  344.  
  345.     if (start_row < logical_height) {
  346.     if (logical_height < start_row + num_rows) {
  347.         height = logical_height - start_row;
  348.     } else {
  349.         height = num_rows;
  350.     }
  351.     } else {
  352.     start_row += num_rows;
  353.     return;
  354.     }
  355.   
  356.     if (components == 1) {
  357.     for (row = 0; row < height; row++) {
  358.         mode_row = (((start_row + row) * logical_byte_width)
  359.             / mode_linewidth);
  360.         mode_col = ((((start_row + row) * logical_byte_width)
  361.              % mode_linewidth) / bytesperpixel);
  362.         ptr0 = pixel_data[0][row];
  363.       
  364.         /*
  365.          * Duplicated code so we only do an unnecessary test per line
  366.          * rather than per pixel.
  367.          */
  368.         if (opt_doublex) {
  369.         for (col = 0; col < width; col++) {
  370.             vga_setcolor(GETJSAMPLE(*ptr0++));
  371.             vga_drawpixel(mode_col++, mode_row);
  372.             vga_drawpixel(mode_col++, mode_row);
  373.             if (mode_col == mode_width) {
  374.             mode_col = 0;
  375.             mode_row++;
  376.             }
  377.         }
  378.         } else {
  379.         for (col = 0; col < width; col++) {
  380.             vga_setcolor(GETJSAMPLE(*ptr0++));
  381.             vga_drawpixel(mode_col++, mode_row);
  382.             if (mode_col == mode_width) {
  383.             mode_col = 0;
  384.             mode_row++;
  385.             }
  386.         }
  387.         }
  388.     }
  389.     } else {
  390.     for (row = 0; row < height; row++) {
  391.         mode_row = (((start_row + row) * logical_byte_width)
  392.             / mode_linewidth);
  393.         mode_col = ((((start_row + row) * logical_byte_width)
  394.              % mode_linewidth) / bytesperpixel);
  395.         ptr0 = pixel_data[0][row];
  396.         ptr1 = pixel_data[1][row];
  397.         ptr2 = pixel_data[2][row];
  398.  
  399.         /*
  400.          * Duplicated code so we only do an unnecessary test per line
  401.          * rather than per pixel.
  402.          */
  403.         if (opt_doublex) {
  404.         for (col = 0; col < width; col++) {
  405.             /* the slowest known solution... */
  406.             if (mode_depth == 32768) {
  407.             vga_setcolor(((GETJSAMPLE(*ptr0++) & 0xf8) << 7)
  408.                      | ((GETJSAMPLE(*ptr1++) & 0xf8) << 2)
  409.                      | (GETJSAMPLE(*ptr2++) >> 3));
  410.             } else {
  411.             vga_setcolor((GETJSAMPLE(*ptr0++) << 16)
  412.                      | (GETJSAMPLE(*ptr1++) << 8)
  413.                      | GETJSAMPLE(*ptr2++));
  414.             }
  415.             vga_drawpixel(mode_col++, mode_row);
  416.             vga_drawpixel(mode_col++, mode_row);
  417.             if (mode_col == mode_width) {
  418.             mode_col = 0;
  419.             mode_row++;
  420.             }
  421.         }
  422.         } else {
  423.         for (col = 0; col < width; col++) {
  424.             /* the slowest known solution... */
  425.             if (mode_depth == 32768) {
  426.             vga_setcolor(((GETJSAMPLE(*ptr0++) & 0xf8) << 7)
  427.                      | ((GETJSAMPLE(*ptr1++) & 0xf8) << 2)
  428.                      | (GETJSAMPLE(*ptr2++) >> 3));
  429.             } else {
  430.             vga_setcolor((GETJSAMPLE(*ptr0++) << 16)
  431.                      | (GETJSAMPLE(*ptr1++) << 8)
  432.                      | GETJSAMPLE(*ptr2++));
  433.             }
  434.             vga_drawpixel(mode_col++, mode_row);
  435.             if (mode_col == mode_width) {
  436.             mode_col = 0;
  437.             mode_row++;
  438.             }
  439.         }
  440.         }
  441.     }
  442.     }
  443.     start_row += num_rows;
  444. }
  445.  
  446.  
  447. #define OFFSET_ROWS 8
  448. #define OFFSET_COLS PIX_ALIGN    /* a high PIX_ALIGN is a pain here */
  449.  
  450. void
  451. scroll_until_end()
  452. {
  453.     int c, done = 0, offset = 0;
  454.  
  455.     /*
  456.      * If this is a slideshow we don't allow scrolling, we just sleep
  457.      * for the given time.
  458.      */
  459.     if (opt_slideshow >= 0) {
  460.     if (opt_slideshow > 0) {
  461.         sleep(opt_slideshow);
  462.     }
  463.     done = 1;
  464.     }
  465.     
  466.     while (!done) {
  467.     c = vga_getch();
  468.     switch (c) {
  469.       case 'q':
  470.         opt_cycle = 0;
  471.         done = 1;
  472.         break;
  473.         
  474.       case 0x1b:        /* ESC */
  475.         c = vga_getch();
  476.         if (c == '[') {
  477.         c = vga_getch();
  478.         switch (c) {
  479.           case 'A':    /* up */
  480.             if (offset > 0) {
  481.             offset -= OFFSET_ROWS * logical_byte_width;
  482.             while (offset < 0) {
  483.                 offset += logical_byte_width;
  484.             }
  485.             vga_setdisplaystart(offset);
  486.             }
  487.             break;
  488.           case 'B':    /* down */
  489.             if (offset / logical_byte_width
  490.             < logical_height - mode_height) {
  491.             offset += MIN(OFFSET_ROWS,
  492.                       logical_height - mode_height
  493.                       - offset / logical_byte_width)
  494.                 * logical_byte_width;
  495.             vga_setdisplaystart(offset);
  496.             }
  497.             break;
  498.           case 'C':    /* right */
  499.             if ((offset % logical_byte_width) / bytesperpixel
  500.             + mode_width
  501.             < logical_width) {
  502.             offset += MIN(OFFSET_COLS * bytesperpixel,
  503.                       (logical_width - mode_width)
  504.                       * bytesperpixel
  505.                       - offset % logical_byte_width);
  506.             vga_setdisplaystart(offset);
  507.             }
  508.             break;
  509.           case 'D':    /* left */
  510.             if (offset % logical_byte_width > 0) {
  511.             offset -= MIN(OFFSET_COLS * bytesperpixel,
  512.                       offset % logical_byte_width);
  513.             vga_setdisplaystart(offset);
  514.             }
  515.             break;
  516.           default:
  517.             done = 1;
  518.         }
  519.         } else {
  520.         done = 1;
  521.         }
  522.         break;
  523.  
  524.       default:
  525.         done = 1;
  526.         break;
  527.     }
  528.     }
  529. }
  530.  
  531.  
  532. void
  533. display_shutdown()
  534. {
  535.     vga_setmode(TEXT);
  536. }
  537.