home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / gl / scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-28  |  6.1 KB  |  268 lines

  1. /* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */
  2. /* scale.c    Scaling routine */
  3.  
  4.  
  5. #include <stdlib.h>
  6. #include <vga.h>
  7. #include "inlstring.h"        /* include inline string operations */
  8.  
  9. #include "vgagl.h"
  10. #include "def.h"
  11.  
  12.  
  13. /* #define USE_ASM */
  14.  
  15.  
  16. /* We use the 32-bit to 64-bit multiply and 64-bit to 32-bit divide of the */
  17. /* 386 (which gcc doesn't know well enough) to efficiently perform integer */
  18. /* scaling without having to worry about overflows. */
  19.  
  20. static inline int muldiv64( int m1, int m2, int d ) {
  21. /* int32 * int32 -> int64 / int32 -> int32 */
  22.     int result;
  23.     __asm__(
  24.         "imull %%edx\n\t"
  25.         "idivl %3\n\t"
  26.         : "=a" (result)            /* out */
  27.         : "a" (m1), "d" (m2), "g" (d)    /* in */
  28.         : "ax", "dx"            /* mod */
  29.     );
  30.     return result;
  31. }
  32.  
  33.  
  34. /* This is a DDA-based algorithm. */
  35. /* Iteration over target bitmap. */
  36.  
  37. void gl_scalebox( int w1, int h1, void *_dp1, int w2, int h2, void *_dp2 ) {
  38.     uchar *dp1 = _dp1;
  39.     uchar *dp2 = _dp2;
  40.     int xfactor;
  41.     int yfactor;
  42.  
  43.     if (w2 == 0 || h2 == 0)
  44.         return;
  45.  
  46.     xfactor = muldiv64(w1, 65536, w2);    /* scaled by 65536 */
  47.     yfactor = muldiv64(h1, 65536, h2);    /* scaled by 65536 */
  48.  
  49.     switch (BYTESPERPIXEL) {
  50.     case 1 :
  51.         {
  52.             int y, sy;
  53.             sy = 0;
  54.             for (y = 0; y < h2;) {
  55.                 int sx = 0;
  56.                     uchar *dp2old = dp2; 
  57.                     int x;
  58.                     x = 0;
  59.                     while (x < w2 - 8) {
  60. #ifdef USE_ASM
  61.  
  62.                 /* This saves just a couple of cycles per */
  63.                 /* pixel on a 486, but I couldn't resist. */
  64.                 __asm__ __volatile__("
  65.                     movl %4,%%eax
  66.                     shrl $16,%%eax
  67.                     addl %5,%4
  68.                     movb (%3,%%eax),%%al
  69.                     movb %%al,(%1,%2)
  70.                     movl %4,%%eax
  71.                     shrl $16,%%eax
  72.                     addl %5,%4
  73.                     movb (%3,%%eax),%%al
  74.                     movb %%al,1(%1,%2)
  75.                     movl %4,%%eax
  76.                     shrl $16,%%eax
  77.                     addl %5,%4
  78.                     movb (%3,%%eax),%%al
  79.                     movb %%al,2(%1,%2)
  80.                     movl %4,%%eax
  81.                     shrl $16,%%eax
  82.                     addl %5,%4
  83.                     movb (%3,%%eax),%%al
  84.                     movb %%al,3(%1,%2)
  85.                     movl %4,%%eax
  86.                     shrl $16,%%eax
  87.                     addl %5,%4
  88.                     movb (%3,%%eax),%%al
  89.                     movb %%al,4(%1,%2)
  90.                     movl %4,%%eax
  91.                     shrl $16,%%eax
  92.                     addl %5,%4
  93.                     movb (%3,%%eax),%%al
  94.                     movb %%al,5(%1,%2)
  95.                     movl %4,%%eax
  96.                     shrl $16,%%eax
  97.                     addl %5,%4
  98.                     movb (%3,%%eax),%%al
  99.                     movb %%al,6(%1,%2)
  100.                     movl %4,%%eax
  101.                     shrl $16,%%eax
  102.                     addl %5,%4
  103.                     movb (%3,%%eax),%%al
  104.                     movb %%al,7(%1,%2)
  105.                     \n\t"
  106.                 : /* output */
  107.                 : /* input */
  108.                   "ax" (0), "r" (dp2), "r" (x), "r" (dp1),
  109.                   "r" (sx), "r" (xfactor)
  110.                 : "ax", "4"
  111.                 );
  112. #else
  113.                 *(dp2 + x) = *(dp1 + (sx >> 16));
  114.                 sx += xfactor;
  115.                 *(dp2 + x + 1) = *(dp1 + (sx >> 16));
  116.                 sx += xfactor;
  117.                 *(dp2 + x + 2) = *(dp1 + (sx >> 16));
  118.                 sx += xfactor;
  119.                 *(dp2 + x + 3) = *(dp1 + (sx >> 16));
  120.                 sx += xfactor;
  121.                 *(dp2 + x + 4) = *(dp1 + (sx >> 16));
  122.                 sx += xfactor;
  123.                 *(dp2 + x + 5) = *(dp1 + (sx >> 16));
  124.                 sx += xfactor;
  125.                 *(dp2 + x + 6) = *(dp1 + (sx >> 16));
  126.                 sx += xfactor;
  127.                 *(dp2 + x + 7) = *(dp1 + (sx >> 16));
  128.                 sx += xfactor;
  129. #endif
  130.                 x += 8;
  131.             }
  132.                     while (x < w2) {
  133.                 *(dp2 + x) = *(dp1 + (sx >> 16));
  134.                 sx += xfactor;
  135.                 x++;
  136.             }
  137.             dp2 += w2;
  138.             y++;
  139.             while (y < h2) {
  140.                 int l;
  141.                 int syint = sy >> 16;
  142.                 sy += yfactor;
  143.                 if ((sy >> 16) != syint)
  144.                     break;
  145.                 /* Copy identical lines. */
  146.                         l = dp2 - dp2old;
  147.                         __memcpy(dp2, dp2old, l);
  148.                         dp2old = dp2;
  149.                         dp2 += l;
  150.                         y++;
  151.                     }
  152.                     dp1 = _dp1 + (sy >> 16) * w1;
  153.             }
  154.             }
  155.             break;
  156.     case 2 :
  157.         {
  158.             int y, sy;
  159.             sy = 0;
  160.             for (y = 0; y < h2;) {
  161.                 int sx = 0;
  162.                     uchar *dp2old = dp2; 
  163.                     int x;
  164.                     x = 0;
  165.                     /* This can be greatly optimized with loop */
  166.                     /* unrolling; omitted to save space. */
  167.                     while (x < w2) {
  168.                 *(unsigned short *)(dp2 + x * 2) =
  169.                 *(unsigned short *)(dp1 + (sx >> 16) * 2);
  170.                 sx += xfactor;
  171.                 x++;
  172.             }
  173.             dp2 += w2 * 2;
  174.             y++;
  175.             while (y < h2) {
  176.                 int l;
  177.                 int syint = sy >> 16;
  178.                 sy += yfactor;
  179.                 if ((sy >> 16) != syint)
  180.                     break;
  181.                 /* Copy identical lines. */
  182.                         l = dp2 - dp2old;
  183.                         __memcpy(dp2, dp2old, l);
  184.                         dp2old = dp2;
  185.                         dp2 += l;
  186.                         y++;
  187.                     }
  188.                     dp1 = _dp1 + (sy >> 16) * w1 * 2;
  189.             }
  190.             }
  191.             break;
  192.     case 3 :
  193.         {
  194.             int y, sy;
  195.             sy = 0;
  196.             for (y = 0; y < h2;) {
  197.                 int sx = 0;
  198.                     uchar *dp2old = dp2; 
  199.                     int x;
  200.                     x = 0;
  201.                     /* This can be greatly optimized with loop */
  202.                     /* unrolling; omitted to save space. */
  203.                     while (x < w2) {
  204.                 *(unsigned short *)(dp2 + x * 3) =
  205.                 *(unsigned short *)(dp1 + (sx >> 16) * 3);
  206.                 *(unsigned char *)(dp2 + x * 3 + 2) =
  207.                 *(unsigned char *)(dp1 + (sx >> 16) * 3 + 2);
  208.                 sx += xfactor;
  209.                 x++;
  210.             }
  211.             dp2 += w2 * 3;
  212.             y++;
  213.             while (y < h2) {
  214.                 int l;
  215.                 int syint = sy >> 16;
  216.                 sy += yfactor;
  217.                 if ((sy >> 16) != syint)
  218.                     break;
  219.                 /* Copy identical lines. */
  220.                         l = dp2 - dp2old;
  221.                         __memcpy(dp2, dp2old, l);
  222.                         dp2old = dp2;
  223.                         dp2 += l;
  224.                         y++;
  225.                     }
  226.                     dp1 = _dp1 + (sy >> 16) * w1 * 3;
  227.             }
  228.             }
  229.             break;
  230.     case 4 :
  231.         {
  232.             int y, sy;
  233.             sy = 0;
  234.             for (y = 0; y < h2;) {
  235.                 int sx = 0;
  236.                     uchar *dp2old = dp2; 
  237.                     int x;
  238.                     x = 0;
  239.                     /* This can be greatly optimized with loop */
  240.                     /* unrolling; omitted to save space. */
  241.                     while (x < w2) {
  242.                 *(unsigned *)(dp2 + x * 4) =
  243.                 *(unsigned *)(dp1 + (sx >> 16) * 4);
  244.                 sx += xfactor;
  245.                 x++;
  246.             }
  247.             dp2 += w2 * 4;
  248.             y++;
  249.             while (y < h2) {
  250.                 int l;
  251.                 int syint = sy >> 16;
  252.                 sy += yfactor;
  253.                 if ((sy >> 16) != syint)
  254.                     break;
  255.                 /* Copy identical lines. */
  256.                         l = dp2 - dp2old;
  257.                         __memcpy(dp2, dp2old, l);
  258.                         dp2old = dp2;
  259.                         dp2 += l;
  260.                         y++;
  261.                     }
  262.                     dp1 = _dp1 + (sy >> 16) * w1 * 4;
  263.             }
  264.             }
  265.             break;
  266.         }
  267. }
  268.