home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Emulatoren / UAE061.LZH / uae-0.6.1 / gfxutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  9.4 KB  |  444 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Common code needed by all the various graphics systems.
  5.   * 
  6.   * (c) 1996 Bernd Schmidt, Ed Hanway, Samuel Devulder
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include "config.h"
  13. #include "options.h"
  14. #include "memory.h"
  15. #include "custom.h"
  16. #include "newcpu.h"
  17. #include "keyboard.h"
  18. #include "xwin.h"
  19. #include "keybuf.h"
  20.  
  21. #define    RED     0
  22. #define    GRN    1
  23. #define    BLU    2
  24.  
  25. /*
  26.  * dither matrix
  27.  */
  28. static UBYTE dither[4][4] =
  29. {
  30.   {0,8,2,10},
  31.   {12,4,14,6},
  32.   {3,11,1,9},
  33.   {14 /* 15 */,7,13,5}
  34. };
  35.  
  36. unsigned long doMask(int p, int bits, int shift)
  37. {
  38.     /* p is a value from 0 to 15 (Amiga color value)
  39.      * scale to 0..255, shift to align msb with mask, and apply mask */
  40.  
  41.     unsigned long val = p * 0x11111111UL;
  42.     val >>= (32 - bits);
  43.     val <<= shift;
  44.  
  45.     return val;
  46. }
  47.  
  48. void alloc_colors64k(int rw, int gw, int bw, int rs, int gs, int bs)
  49. {
  50.     int i;
  51.     for(i=0; i<4096; i++) {
  52.     int r = i >> 8;
  53.     int g = (i >> 4) & 0xF;
  54.     int b = i & 0xF;
  55.     xcolors[i] = doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs);
  56.     }
  57. }
  58.  
  59. static int allocated[4096];
  60. static int newmaxcol;
  61.  
  62. void setup_maxcol(int max)
  63. {
  64.     newmaxcol = max;
  65. }
  66.  
  67. void alloc_colors256(allocfunc_type allocfunc)
  68. {
  69.     int nb_cols[3]; /* r,g,b */
  70.     int maxcol = newmaxcol?:256;
  71.     int i,j,k,l,t;
  72.     int diff[4096];
  73.  
  74.     xcolnr *map;
  75.  
  76.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  77.     
  78.     /*
  79.      * compute #cols per components
  80.      */
  81.     for(i = 1; i*i*i <= maxcol; ++i)
  82.     ;
  83.     --i;
  84.  
  85.     nb_cols[RED] = i;
  86.     nb_cols[GRN] = i;
  87.     nb_cols[BLU] = i;
  88.     
  89.     if(i==1) {printf("maxcol=%d\n",maxcol);exit(0);}
  90.  
  91.     /*
  92.      * set the colormap
  93.      */
  94.     l=0;
  95.     for(i = 0; i < nb_cols[RED]; ++i) {
  96.     int r = (i * 15 + (nb_cols[RED] - 1)/2) / (nb_cols[RED] - 1);
  97.     for(j = 0; j < nb_cols[GRN]; ++j) {
  98.         int g = (j * 15 + (nb_cols[GRN] - 1)/2) / (nb_cols[GRN] - 1);
  99.         for(k = 0; k < nb_cols[BLU]; ++k) { 
  100.         int b = (k * 15 + (nb_cols[BLU] - 1)/2) / (nb_cols[BLU] - 1);
  101.         int result,j;
  102.         result = allocfunc(r, g, b, map + l);
  103. #ifdef AMIGA
  104.         if(!result) {free(map);return;}
  105. #endif
  106.         l++;
  107.         }
  108.     }
  109.     }
  110. /*printf("%d color(s) lost\n",maxcol - l);*/
  111.  
  112.     /*
  113.      * for each component compute the mapping
  114.      */
  115.     {
  116.     int diffr, diffg, diffb, maxdiff = 0, won = 0, lost;
  117.     int r, d = 8;
  118.     for(r=0; r<16; ++r) {
  119.         int cr, g, q;
  120.       
  121.         k  = nb_cols[RED]-1;
  122.         cr = (r * k) / 15;
  123.         q  = (r * k) % 15;
  124.         if(q > d && cr < k) ++cr;
  125.         diffr = abs(cr*k-r);
  126.         for(g=0; g<16; ++g) {
  127.         int cg, b;
  128.           
  129.         k  = nb_cols[GRN]-1;
  130.         cg = (g * k) / 15;
  131.         q  = (g * k) % 15;
  132.         if(q > d && cg < k) ++cg;
  133.         diffg = abs(cg*k-g);
  134.         for(b=0; b<16; ++b) {
  135.             int cb, rgb = (r<<8) | (g<<4) | b;
  136.  
  137.             k  = nb_cols[BLU]-1;
  138.             cb = (b * k) / 15;
  139.             q  = (b * k) % 15;
  140.             if(q > d && cb < k) ++cb;
  141.             diffb = abs(cb*k-b);
  142.             xcolors[rgb] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
  143.             diff[rgb] = diffr+diffg+diffb;
  144.             if (diff[rgb] > maxdiff)
  145.             maxdiff = diff[rgb];
  146.         }
  147.         }
  148.     }
  149.     while (maxdiff > 0 && l < maxcol) {
  150.         int newmaxdiff = 0;
  151.         lost = 0; won++;
  152.         for(r = 15; r >= 0; r--) {
  153.         int cr, g, q;
  154.       
  155.         for(g = 15; g >= 0; g--) {
  156.             int cg, b;
  157.           
  158.             for(b = 15; b >= 0; b--) {
  159.             int cb, rgb = (r<<8) | (g<<4) | b;
  160.  
  161.             if (diff[rgb] == maxdiff) {
  162.                 int result;
  163.             
  164.                 if (l >= maxcol)
  165.                 lost++;
  166.                 else {
  167.                 result = allocfunc(r, g, b, xcolors + rgb);
  168.                 l++;
  169.                 }
  170.                 diff[rgb] = 0;
  171.             } else if (diff[rgb] > newmaxdiff)
  172.                 newmaxdiff = diff[rgb];
  173.             
  174.             }
  175.         }
  176.         }
  177.         maxdiff = newmaxdiff;
  178.     }
  179.     finished:    
  180. /*    printf("%d color(s) lost, %d stages won\n",lost, won);*/
  181.     }
  182.     free (map);
  183. }
  184.  
  185. /*
  186.  * This dithering process works by letting UAE run internaly in 12bit
  187.  * mode and doing the dithering on the fly when rendering to the display.
  188.  * The dithering algorithm is quite fast but uses lot of memory (4*8*2^12 =
  189.  * 128Kb). I don't think that is a trouble right now, but when UAE will 
  190.  * emulate AGA and work internaly in 24bit mode, that dithering algorithm
  191.  * will need 4*8*2^24 = 512Mb. Obviously that fast algorithm will not be
  192.  * tractable. However, we could then use an other algorithm, slower, but 
  193.  * far more reasonable (I am thinking about the one that is used in DJPEG).
  194.  */
  195.  
  196. UBYTE cidx[4][8*4096]; /* fast, but memory hungry =:-( */
  197.  
  198. /*
  199.  * Compute dithering structures
  200.  */
  201. void setup_greydither_maxcol(int maxcol, allocfunc_type allocfunc)
  202. {
  203.     int i,j,k,l,t;
  204.     xcolnr *map;
  205.     
  206.     for (i = 0; i < 4096; i++)
  207.     xcolors[i] = i;
  208.     
  209.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  210.  
  211.     /*
  212.      * set the colormap
  213.      */
  214.     for(i = 0; i < maxcol; ++i) {
  215.     int c, result;
  216.     c = (15 * i + (maxcol-1)/2) / (maxcol - 1);
  217.         result = allocfunc(c, c, c, map + i);
  218.     /* @@@ check for errors */
  219.         if(!result) {free(map);return;}
  220.     }
  221.  
  222.     /*
  223.      * for each componant compute the mapping
  224.      */
  225.     for(i=0;i<4;++i) {
  226.     for(j=0;j<4;++j) {
  227.         int r, d = dither[i][j]*17;
  228.         for(r=0; r<16; ++r) {
  229.         int g;
  230.         for(g=0; g<16; ++g) {
  231.             int  b;
  232.             for(b=0; b<16; ++b) {
  233.             int rgb = (r<<8) | (g<<4) | b;
  234.             int c,p,q;
  235.             
  236.             c = (77  * r + 
  237.                  151 * g + 
  238.                  28  * b) / 15; /* c in 0..256 */
  239.             
  240.             k = maxcol-1;  
  241.             p = (c * k) / 256;
  242.             q = (c * k) % 256;
  243.             if(q / k > d / k && p < k) ++p;
  244.             cidx[i][rgb + (j+4)*4096] = 
  245.                 cidx[i][rgb + j*4096] = map[p];
  246.             }
  247.         }
  248.         }
  249.     }
  250.     }
  251.     free (map);
  252. }
  253.  
  254. void setup_greydither(int bits, allocfunc_type allocfunc)
  255. {
  256.     return setup_greydither_maxcol(1<<bits, allocfunc);
  257. }
  258.  
  259. void setup_dither(int bits, allocfunc_type allocfunc)
  260. {
  261.     int nb_cols[3]; /* r,g,b */
  262.     int maxcol = 1 << bits;
  263.     int i,j,k,l,t;
  264.  
  265.     xcolnr *map;
  266.     int *redvals, *grnvals, *bluvals;
  267.     
  268.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  269.  
  270.     for (i = 0; i < 4096; i++)
  271.     xcolors[i] = i;
  272.     
  273.     /*
  274.      * compute #cols per components
  275.      */
  276.     for(i = 1; i*i*i <= maxcol; ++i)
  277.     ;
  278.     --i;
  279.  
  280.     nb_cols[RED] = i;
  281.     nb_cols[GRN] = i;
  282.     nb_cols[BLU] = i;
  283.  
  284.     if(nb_cols[RED]*(++i)*nb_cols[BLU] <= maxcol) {
  285.     nb_cols[GRN] = i;
  286.     if((i)*nb_cols[GRN]*nb_cols[BLU] <= maxcol) nb_cols[RED] = i;
  287.     }
  288.  
  289.     redvals = (int *)malloc(sizeof(int) * maxcol);
  290.     grnvals = redvals + nb_cols[RED];
  291.     bluvals = grnvals + nb_cols[BLU];
  292.     /*
  293.      * set the colormap
  294.      */
  295.     l=0;
  296.     for(i = 0; i < nb_cols[RED]; ++i) {
  297.     int r = (i * 15 + (nb_cols[RED] - 1)/2) / (nb_cols[RED] - 1);
  298.     redvals[i] = r;
  299.     for(j = 0; j < nb_cols[GRN]; ++j) {
  300.         int g = (j * 15 + (nb_cols[GRN] - 1)/2) / (nb_cols[GRN] - 1);
  301.         grnvals[j] = g;
  302.         for(k = 0; k < nb_cols[BLU]; ++k) { 
  303.         int b = (k * 15 + (nb_cols[BLU] - 1)/2) / (nb_cols[BLU] - 1);
  304.         int result;
  305.         bluvals[k] = b;
  306.         result = allocfunc(r, g, b, map + l);
  307.             if(!result) {free(map);return;}
  308.         l++;
  309.         }
  310.     }
  311.     }
  312. /*  printf("%d color(s) lost\n",maxcol - l); */
  313.  
  314.     /*
  315.      * for each component compute the mapping
  316.      */
  317.     {
  318.     int r;
  319.     for(r=0; r<16; ++r) {
  320.         int g;
  321.         for(g=0; g<16; ++g) {
  322.         int b;
  323.         for(b=0; b<16; ++b) {
  324.             int rederr = 0, grnerr = 0, bluerr = 0;
  325.             int rgb = (r<<8) | (g<<4) | b;
  326.  
  327.             for(i=0;i<4;++i) for(j=0;j<4;++j) {
  328.             int d = dither[i][j];
  329.             int cr, cg, cb, k, q;
  330. #if 0 /* Slightly different algorithm. Needs some tuning. */
  331.             k  = nb_cols[RED]-1;
  332.             cr = r * k / 15;
  333.             q  = r * k - 15*cr;
  334.             if (cr < 0) cr = 0;
  335.             else
  336.                 if(q / k > d / k && rederr <= 0) ++cr;
  337.             if (cr > k) cr = k;
  338.             rederr += redvals[cr]-r;
  339.           
  340.             k  = nb_cols[GRN]-1;
  341.             cg = g * k / 15;
  342.             q  = g * k - 15*cg;
  343.             if (cg < 0) cg = 0;
  344.             else
  345.                 if (q / k > d / k && grnerr <= 0) ++cg;
  346.             if (cg > k) cg = k;
  347.             grnerr += grnvals[cg]-g;
  348.  
  349.             k  = nb_cols[BLU]-1;
  350.             cb = b * k / 15;
  351.             q  = b * k - 15*cb;
  352.             if (cb < 0) cb = 0;
  353.             else
  354.                 if (q / k > d / k && bluerr <= 0) ++cb;
  355.             if (cb > k) cb = k;
  356.             bluerr += bluvals[cb]-b;
  357. #else
  358.             k  = nb_cols[RED]-1;
  359.             cr = r * k / 15;
  360.             q  = r * k - 15*cr;
  361.             if (cr < 0) cr = 0;
  362.             else
  363.                 if(q / k > d / k) ++cr;
  364.             if (cr > k) cr = k;
  365.           
  366.             k  = nb_cols[GRN]-1;
  367.             cg = g * k / 15;
  368.             q  = g * k - 15*cg;
  369.             if (cg < 0) cg = 0;
  370.             else
  371.                 if (q / k > d / k) ++cg;
  372.             if (cg > k) cg = k;
  373.  
  374.             k  = nb_cols[BLU]-1;
  375.             cb = b * k / 15;
  376.             q  = b * k - 15*cb;
  377.             if (cb < 0) cb = 0;
  378.             else
  379.                 if (q / k > d / k) ++cb;
  380.             if (cb > k) cb = k;
  381. #endif
  382.             cidx[i][rgb + (j+4)*4096] = cidx[i][rgb + j*4096] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
  383.             }
  384.         }
  385.         }
  386.     }
  387.     }
  388.     free (map);
  389. }
  390.  
  391. #ifndef X86_ASSEMBLY
  392. /*
  393.  * Dither the line.
  394.  * Make sure you call this only with (len & 3) == 0, or you'll just make
  395.  * yourself unhappy.
  396.  */
  397.  
  398. void DitherLine(UBYTE *l, UWORD *r4g4b4, int x, int y, WORD len, int bits)
  399. {
  400.     UBYTE *dith = cidx[y&3]+(x&3)*4096;
  401.     UBYTE d = 0;
  402.     int bitsleft = 8;
  403.    
  404.     if(bits == 8) {
  405.         while(len>0) {
  406.             *l++ = dith[0*4096 + *r4g4b4++];
  407.             *l++ = dith[1*4096 + *r4g4b4++];
  408.             *l++ = dith[2*4096 + *r4g4b4++];
  409.             *l++ = dith[3*4096 + *r4g4b4++];
  410.             len -= 4;
  411.         }
  412.         return;
  413.     }
  414.  
  415.     while(len) {
  416.     int v;
  417.     v = dith[0*4096 + *r4g4b4++];
  418.     bitsleft -= bits;
  419.     d |= (v << bitsleft);
  420.     if (!bitsleft)
  421.         *l++ = d, bitsleft = 8, d = 0;
  422.     
  423.     v = dith[1*4096 + *r4g4b4++];
  424.     bitsleft -= bits;
  425.     d |= (v << bitsleft);
  426.     if (!bitsleft)
  427.         *l++ = d, bitsleft = 8, d = 0;
  428.     
  429.     v = dith[2*4096 + *r4g4b4++];
  430.     bitsleft -= bits;
  431.     d |= (v << bitsleft);
  432.     if (!bitsleft)
  433.         *l++ = d, bitsleft = 8, d = 0;
  434.     
  435.     v = dith[3*4096 + *r4g4b4++];
  436.     bitsleft -= bits;
  437.     d |= (v << bitsleft);
  438.     if (!bitsleft)
  439.         *l++ = d, bitsleft = 8, d = 0;
  440.     len -= 4;
  441.     }
  442. }
  443. #endif
  444.