home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / bilinear.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  12.9 KB  |  421 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. /**     Code adapted from Exult source code by Forgotten
  20.  **    Scale.cc - Trying to scale with bilinear interpolation.
  21.  **
  22.  **    Written: 6/14/00 - JSF
  23.  **/
  24.  
  25. #include "System.h"
  26.  
  27. static u8 row_cur[3*322];
  28. static u8 row_next[3*322];
  29.  
  30. static u8 *rgb_row_cur = row_cur;
  31. static u8 *rgb_row_next = row_next;
  32.  
  33. #define RGB(r,g,b) ((r)>>3) << systemRedShift |\
  34.   ((g) >> 3) << systemGreenShift |\
  35.   ((b) >> 3) << systemBlueShift\
  36.  
  37. static void fill_rgb_row_16(u16 *from, int src_width, u8 *row, int width)
  38. {
  39.   u8 *copy_start = row + src_width*3;
  40.   u8 *all_stop = row + width*3;
  41.   while (row < copy_start) {
  42.     u16 color = *from++;
  43.     *row++ = ((color >> systemRedShift) & 0x1f) << 3;
  44.     *row++ = ((color >> systemGreenShift) & 0x1f) << 3;
  45.     *row++ = ((color >> systemBlueShift) & 0x1f) << 3;
  46.   }
  47.   // any remaining elements to be written to 'row' are a replica of the
  48.   // preceding pixel
  49.   u8 *p = row-3;
  50.   while (row < all_stop) {
  51.     // we're guaranteed three elements per pixel; could unroll the loop
  52.     // further, especially with a Duff's Device, but the gains would be
  53.     // probably limited (judging by profiler output)
  54.     *row++ = *p++;
  55.     *row++ = *p++;
  56.     *row++ = *p++;
  57.   }
  58. }
  59.  
  60. static void fill_rgb_row_32(u32 *from, int src_width, u8 *row, int width)
  61. {
  62.   u8 *copy_start = row + src_width*3;
  63.   u8 *all_stop = row + width*3;
  64.   while (row < copy_start) {
  65.     u32 color = *from++;
  66.     *row++ = ((color >> systemRedShift) & 0x1f) << 3;
  67.     *row++ = ((color >> systemGreenShift) & 0x1f) << 3;
  68.     *row++ = ((color >> systemBlueShift) & 0x1f) << 3;
  69.   }
  70.   // any remaining elements to be written to 'row' are a replica of the
  71.   // preceding pixel
  72.   u8 *p = row-3;
  73.   while (row < all_stop) {
  74.     // we're guaranteed three elements per pixel; could unroll the loop
  75.     // further, especially with a Duff's Device, but the gains would be
  76.     // probably limited (judging by profiler output)
  77.     *row++ = *p++;
  78.     *row++ = *p++;
  79.     *row++ = *p++;
  80.   }
  81. }
  82.  
  83. void Bilinear(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
  84.               u8 *dstPtr, u32 dstPitch, int width, int height)
  85. {
  86.   u16 *to = (u16 *)dstPtr;
  87.   u16 *to_odd = (u16 *)(dstPtr + dstPitch);
  88.  
  89.   int from_width = width;
  90.   u16 *from = (u16 *)srcPtr;
  91.   fill_rgb_row_16(from, from_width, rgb_row_cur, width+1);
  92.  
  93.   for(int y = 0; y < height; y++) {
  94.     u16 *from_orig = from;
  95.     u16 *to_orig = to;
  96.     
  97.     if (y+1 < height)
  98.       fill_rgb_row_16(from+width+2, from_width, rgb_row_next, 
  99.                    width+1);
  100.     else
  101.       fill_rgb_row_16(from, from_width, rgb_row_next, width+1);
  102.     
  103.     // every pixel in the src region, is extended to 4 pixels in the
  104.     // destination, arranged in a square 'quad'; if the current src
  105.     // pixel is 'a', then in what follows 'b' is the src pixel to the
  106.     // right, 'c' is the src pixel below, and 'd' is the src pixel to
  107.     // the right and down
  108.     u8 *cur_row  = rgb_row_cur;
  109.     u8 *next_row = rgb_row_next;
  110.     u8 *ar = cur_row++;
  111.     u8 *ag = cur_row++;
  112.     u8 *ab = cur_row++;
  113.     u8 *cr = next_row++;
  114.     u8 *cg = next_row++;
  115.     u8 *cb = next_row++;
  116.     for(int x=0; x < width; x++) {
  117.       u8 *br = cur_row++;
  118.       u8 *bg = cur_row++;
  119.       u8 *bb = cur_row++;
  120.       u8 *dr = next_row++;
  121.       u8 *dg = next_row++;
  122.       u8 *db = next_row++;
  123.  
  124.       // upper left pixel in quad: just copy it in
  125.       *to++ = RGB(*ar, *ag, *ab);
  126.       
  127.       // upper right
  128.       *to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
  129.       
  130.       // lower left
  131.       *to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
  132.       
  133.       // lower right
  134.       *to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
  135.                       (*ag+*bg+*cg+*dg)>>2,
  136.                       (*ab+*bb+*cb+*db)>>2);
  137.       
  138.       // 'b' becomes 'a', 'd' becomes 'c'
  139.       ar = br;
  140.       ag = bg;
  141.       ab = bb;
  142.       cr = dr;
  143.       cg = dg;
  144.       cb = db;
  145.     }
  146.     
  147.     // the "next" rgb row becomes the current; the old current rgb row is
  148.     // recycled and serves as the new "next" row
  149.     u8 *temp;
  150.     temp = rgb_row_cur;
  151.     rgb_row_cur = rgb_row_next;
  152.     rgb_row_next = temp;
  153.     
  154.     // update the pointers for start of next pair of lines
  155.     from = (u16 *)((u8 *)from_orig + srcPitch);
  156.     to = (u16 *)((u8 *)to_orig + (dstPitch << 1));
  157.     to_odd = (u16 *)((u8 *)to + dstPitch);
  158.   }
  159. }
  160.  
  161. void BilinearPlus(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
  162.                   u8 *dstPtr, u32 dstPitch, int width, int height)
  163. {
  164.   u16 *to = (u16 *)dstPtr;
  165.   u16 *to_odd = (u16 *)(dstPtr + dstPitch);
  166.  
  167.   int from_width = width;
  168.   u16 *from = (u16 *)srcPtr;
  169.   fill_rgb_row_16(from, from_width, rgb_row_cur, width+1);
  170.  
  171.   for(int y = 0; y < height; y++) {
  172.     u16 *from_orig = from;
  173.     u16 *to_orig = to;
  174.     
  175.     if (y+1 < height)
  176.       fill_rgb_row_16(from+width+2, from_width, rgb_row_next, 
  177.                    width+1);
  178.     else
  179.       fill_rgb_row_16(from, from_width, rgb_row_next, width+1);
  180.     
  181.     // every pixel in the src region, is extended to 4 pixels in the
  182.     // destination, arranged in a square 'quad'; if the current src
  183.     // pixel is 'a', then in what follows 'b' is the src pixel to the
  184.     // right, 'c' is the src pixel below, and 'd' is the src pixel to
  185.     // the right and down
  186.     u8 *cur_row  = rgb_row_cur;
  187.     u8 *next_row = rgb_row_next;
  188.     u8 *ar = cur_row++;
  189.     u8 *ag = cur_row++;
  190.     u8 *ab = cur_row++;
  191.     u8 *cr = next_row++;
  192.     u8 *cg = next_row++;
  193.     u8 *cb = next_row++;
  194.     for(int x=0; x < width; x++) {
  195.       u8 *br = cur_row++;
  196.       u8 *bg = cur_row++;
  197.       u8 *bb = cur_row++;
  198.       u8 *dr = next_row++;
  199.       u8 *dg = next_row++;
  200.       u8 *db = next_row++;
  201.       
  202.       // upper left pixel in quad: just copy it in
  203.       //*to++ = manip.rgb(*ar, *ag, *ab);
  204. #ifdef USE_ORIGINAL_BILINEAR_PLUS
  205.       *to++ = RGB(
  206.                   (((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3,
  207.                   (((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3,
  208.                   (((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3);
  209. #else
  210.       *to++ = RGB(
  211.                   (((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4,
  212.                   (((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4,
  213.                   (((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4);
  214. #endif
  215.       
  216.       // upper right
  217.       *to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
  218.       
  219.       // lower left
  220.       *to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
  221.       
  222.       // lower right
  223.       *to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
  224.                       (*ag+*bg+*cg+*dg)>>2,
  225.                       (*ab+*bb+*cb+*db)>>2);
  226.       
  227.       // 'b' becomes 'a', 'd' becomes 'c'
  228.       ar = br;
  229.       ag = bg;
  230.       ab = bb;
  231.       cr = dr;
  232.       cg = dg;
  233.       cb = db;
  234.     }
  235.     
  236.     // the "next" rgb row becomes the current; the old current rgb row is
  237.     // recycled and serves as the new "next" row
  238.     u8 *temp;
  239.     temp = rgb_row_cur;
  240.     rgb_row_cur = rgb_row_next;
  241.     rgb_row_next = temp;
  242.     
  243.     // update the pointers for start of next pair of lines
  244.     from = (u16 *)((u8 *)from_orig + srcPitch);
  245.     to = (u16 *)((u8 *)to_orig + (dstPitch << 1));
  246.     to_odd = (u16 *)((u8 *)to + dstPitch);
  247.   }
  248. }
  249.  
  250. void Bilinear32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
  251.                 u8 *dstPtr, u32 dstPitch, int width, int height)
  252. {
  253.   u32 *to = (u32 *)dstPtr;
  254.   u32 *to_odd = (u32 *)(dstPtr + dstPitch);
  255.  
  256.   int from_width = width;
  257.   if(width+1 < from_width)
  258.     from_width = width+1;
  259.   u32 *from = (u32 *)srcPtr;
  260.   fill_rgb_row_32(from, from_width, rgb_row_cur, width+1);
  261.  
  262.   for(int y = 0; y < height; y++) {
  263.     u32 *from_orig = from;
  264.     u32 *to_orig = to;
  265.     
  266.     if (y+1 < height)
  267.       fill_rgb_row_32(from+width+1, from_width, rgb_row_next, 
  268.                    width+1);
  269.     else
  270.       fill_rgb_row_32(from, from_width, rgb_row_next, width+1);
  271.     
  272.     // every pixel in the src region, is extended to 4 pixels in the
  273.     // destination, arranged in a square 'quad'; if the current src
  274.     // pixel is 'a', then in what follows 'b' is the src pixel to the
  275.     // right, 'c' is the src pixel below, and 'd' is the src pixel to
  276.     // the right and down
  277.     u8 *cur_row  = rgb_row_cur;
  278.     u8 *next_row = rgb_row_next;
  279.     u8 *ar = cur_row++;
  280.     u8 *ag = cur_row++;
  281.     u8 *ab = cur_row++;
  282.     u8 *cr = next_row++;
  283.     u8 *cg = next_row++;
  284.     u8 *cb = next_row++;
  285.     for(int x=0; x < width; x++) {
  286.       u8 *br = cur_row++;
  287.       u8 *bg = cur_row++;
  288.       u8 *bb = cur_row++;
  289.       u8 *dr = next_row++;
  290.       u8 *dg = next_row++;
  291.       u8 *db = next_row++;
  292.  
  293.       // upper left pixel in quad: just copy it in
  294.       *to++ = RGB(*ar, *ag, *ab);
  295.       
  296.       // upper right
  297.       *to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
  298.       
  299.       // lower left
  300.       *to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
  301.       
  302.       // lower right
  303.       *to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
  304.                       (*ag+*bg+*cg+*dg)>>2,
  305.                       (*ab+*bb+*cb+*db)>>2);
  306.       
  307.       // 'b' becomes 'a', 'd' becomes 'c'
  308.       ar = br;
  309.       ag = bg;
  310.       ab = bb;
  311.       cr = dr;
  312.       cg = dg;
  313.       cb = db;
  314.     }
  315.     
  316.     // the "next" rgb row becomes the current; the old current rgb row is
  317.     // recycled and serves as the new "next" row
  318.     u8 *temp;
  319.     temp = rgb_row_cur;
  320.     rgb_row_cur = rgb_row_next;
  321.     rgb_row_next = temp;
  322.     
  323.     // update the pointers for start of next pair of lines
  324.     from = (u32 *)((u8 *)from_orig + srcPitch);
  325.     to = (u32 *)((u8 *)to_orig + (dstPitch << 1));
  326.     to_odd = (u32 *)((u8 *)to + dstPitch);
  327.   }
  328. }
  329.  
  330. void BilinearPlus32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
  331.                     u8 *dstPtr, u32 dstPitch, int width, int height)
  332. {
  333.   u32 *to = (u32 *)dstPtr;
  334.   u32 *to_odd = (u32 *)(dstPtr + dstPitch);
  335.  
  336.   int from_width = width;
  337.   if(width+1 < from_width)
  338.     from_width = width+1;
  339.   u32 *from = (u32 *)srcPtr;
  340.   fill_rgb_row_32(from, from_width, rgb_row_cur, width+1);
  341.  
  342.   for(int y = 0; y < height; y++) {
  343.     u32 *from_orig = from;
  344.     u32 *to_orig = to;
  345.     
  346.     if (y+1 < height)
  347.       fill_rgb_row_32(from+width+1, from_width, rgb_row_next, 
  348.                    width+1);
  349.     else
  350.       fill_rgb_row_32(from, from_width, rgb_row_next, width+1);
  351.     
  352.     // every pixel in the src region, is extended to 4 pixels in the
  353.     // destination, arranged in a square 'quad'; if the current src
  354.     // pixel is 'a', then in what follows 'b' is the src pixel to the
  355.     // right, 'c' is the src pixel below, and 'd' is the src pixel to
  356.     // the right and down
  357.     u8 *cur_row  = rgb_row_cur;
  358.     u8 *next_row = rgb_row_next;
  359.     u8 *ar = cur_row++;
  360.     u8 *ag = cur_row++;
  361.     u8 *ab = cur_row++;
  362.     u8 *cr = next_row++;
  363.     u8 *cg = next_row++;
  364.     u8 *cb = next_row++;
  365.     for(int x=0; x < width; x++) {
  366.       u8 *br = cur_row++;
  367.       u8 *bg = cur_row++;
  368.       u8 *bb = cur_row++;
  369.       u8 *dr = next_row++;
  370.       u8 *dg = next_row++;
  371.       u8 *db = next_row++;
  372.       
  373.       // upper left pixel in quad: just copy it in
  374.       //*to++ = manip.rgb(*ar, *ag, *ab);
  375. #ifdef USE_ORIGINAL_BILINEAR_PLUS
  376.       *to++ = RGB(
  377.                   (((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3,
  378.                   (((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3,
  379.                   (((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3);
  380. #else
  381.       *to++ = RGB(
  382.                   (((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4,
  383.                   (((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4,
  384.                   (((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4);
  385. #endif
  386.       
  387.       // upper right
  388.       *to++ = RGB((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1);
  389.       
  390.       // lower left
  391.       *to_odd++ = RGB((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1);
  392.       
  393.       // lower right
  394.       *to_odd++ = RGB((*ar+*br+*cr+*dr)>>2,
  395.                       (*ag+*bg+*cg+*dg)>>2,
  396.                       (*ab+*bb+*cb+*db)>>2);
  397.       
  398.       // 'b' becomes 'a', 'd' becomes 'c'
  399.       ar = br;
  400.       ag = bg;
  401.       ab = bb;
  402.       cr = dr;
  403.       cg = dg;
  404.       cb = db;
  405.     }
  406.     
  407.     // the "next" rgb row becomes the current; the old current rgb row is
  408.     // recycled and serves as the new "next" row
  409.     u8 *temp;
  410.     temp = rgb_row_cur;
  411.     rgb_row_cur = rgb_row_next;
  412.     rgb_row_next = temp;
  413.     
  414.     // update the pointers for start of next pair of lines
  415.     from = (u32 *)((u8 *)from_orig + srcPitch);
  416.     to = (u32 *)((u8 *)to_orig + (dstPitch << 1));
  417.     to_odd = (u32 *)((u8 *)to + dstPitch);
  418.   }
  419. }
  420.  
  421.