Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * OpenTyrian: A modern cross-platform port of Tyrian
  3.  * Copyright (C) 2007-2010  The OpenTyrian Development Team
  4.  *
  5.  * Scale2x, Scale3x
  6.  * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License
  10.  * as published by the Free Software Foundation; either version 2
  11.  * of the License, or (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  21.  */
  22. #include "video_scale.h"
  23.  
  24. #include "palette.h"
  25. #include "video.h"
  26.  
  27. #include <assert.h>
  28.  
  29. static void no_scale( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  30. static void nn_32( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  31. static void nn_16( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  32.  
  33. static void scale2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  34. static void scale2x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  35. static void scale3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  36. static void scale3x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  37.  
  38. void hq2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  39. void hq3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  40. void hq4x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface );
  41.  
  42. uint scaler;
  43.  
  44. const struct Scalers scalers[] =
  45. {
  46. #if defined(TARGET_GP2X) || defined(TARGET_DINGUX)
  47.         { 320,           240,            no_scale, nn_16,      nn_32,      "None" },
  48. #else
  49.         { 1 * vga_width, 1 * vga_height, no_scale, nn_16,      nn_32,      "None" },
  50.         { 2 * vga_width, 2 * vga_height, NULL,     nn_16,      nn_32,      "2x" },
  51.         { 2 * vga_width, 2 * vga_height, NULL,     scale2x_16, scale2x_32, "Scale2x" },
  52.         { 2 * vga_width, 2 * vga_height, NULL,     NULL,       hq2x_32,    "hq2x" },
  53.         { 3 * vga_width, 3 * vga_height, NULL,     nn_16,      nn_32,      "3x" },
  54.         { 3 * vga_width, 3 * vga_height, NULL,     scale3x_16, scale3x_32, "Scale3x" },
  55.         { 3 * vga_width, 3 * vga_height, NULL,     NULL,       hq3x_32,    "hq3x" },
  56.         { 4 * vga_width, 4 * vga_height, NULL,     nn_16,      nn_32,      "4x" },
  57.         { 4 * vga_width, 4 * vga_height, NULL,     NULL,       hq4x_32,    "hq4x" },
  58. #endif
  59. };
  60. const uint scalers_count = COUNTOF(scalers);
  61.  
  62. void set_scaler_by_name( const char *name )
  63. {
  64.         for (uint i = 0; i < scalers_count; ++i)
  65.         {
  66.                 if (strcmp(name, scalers[i].name) == 0)
  67.                 {
  68.                         scaler = i;
  69.                         break;
  70.                 }
  71.         }
  72. }
  73.  
  74. #if defined(TARGET_GP2X) || defined(TARGET_DINGUX)
  75. #define VGA_CENTERED
  76. #endif
  77.  
  78. void no_scale( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  79. {
  80.         Uint8 *src = src_surface->pixels,
  81.               *dst = dst_surface->pixels;
  82.        
  83. #ifdef VGA_CENTERED
  84.         size_t blank = (dst_surface->h - src_surface->h) / 2 * dst_surface->pitch;
  85.         memset(dst, 0, blank);
  86.         dst += blank;
  87. #endif
  88.        
  89.         memcpy(dst, src, src_surface->pitch * src_surface->h);
  90.        
  91. #ifdef VGA_CENTERED
  92.         dst += src_surface->pitch * src_surface->h;
  93.         memset(dst, 0, blank);
  94. #endif
  95. }
  96.  
  97.  
  98. void nn_32( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  99. {
  100.         Uint8 *src = src_surface->pixels, *src_temp,
  101.               *dst = dst_surface->pixels, *dst_temp;
  102.         int src_pitch = src_surface->pitch,
  103.             dst_pitch = dst_surface->pitch;
  104.         const int dst_Bpp = 4;         // dst_surface->format->BytesPerPixel
  105.        
  106.         const int height = vga_height, // src_surface->h
  107.                   width = vga_width,   // src_surface->w
  108.                   scale = dst_surface->w / width;
  109.         assert(scale == dst_surface->h / height);
  110.        
  111. #ifdef VGA_CENTERED
  112.         size_t blank = (dst_surface->h - src_surface->h) / 2 * dst_surface->pitch;
  113.         memset(dst, 0, blank);
  114.         dst += blank;
  115. #endif
  116.        
  117.         for (int y = height; y > 0; y--)
  118.         {
  119.                 src_temp = src;
  120.                 dst_temp = dst;
  121.                
  122.                 for (int x = width; x > 0; x--)
  123.                 {
  124.                         for (int z = scale; z > 0; z--)
  125.                         {
  126.                                 *(Uint32 *)dst = rgb_palette[*src];
  127.                                 dst += dst_Bpp;
  128.                         }
  129.                         src++;
  130.                 }
  131.                
  132.                 src = src_temp + src_pitch;
  133.                 dst = dst_temp + dst_pitch;
  134.                
  135.                 for (int z = scale; z > 1; z--)
  136.                 {
  137.                         memcpy(dst, dst_temp, dst_pitch);
  138.                         dst += dst_pitch;
  139.                 }
  140.         }
  141.        
  142. #ifdef VGA_CENTERED
  143.         memset(dst, 0, blank);
  144. #endif
  145. }
  146.  
  147. void nn_16( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  148. {
  149.         Uint8 *src = src_surface->pixels, *src_temp,
  150.               *dst = dst_surface->pixels, *dst_temp;
  151.         int src_pitch = src_surface->pitch,
  152.             dst_pitch = dst_surface->pitch;
  153.         const int dst_Bpp = 2;         // dst_surface->format->BytesPerPixel
  154.        
  155.         const int height = vga_height, // src_surface->h
  156.                   width = vga_width,   // src_surface->w
  157.                   scale = dst_surface->w / width;
  158.         assert(scale == dst_surface->h / height);
  159.        
  160. #ifdef VGA_CENTERED
  161.         size_t blank = (dst_surface->h - src_surface->h) / 2 * dst_surface->pitch;
  162.         memset(dst, 0, blank);
  163.         dst += blank;
  164. #endif
  165.        
  166.         for (int y = height; y > 0; y--)
  167.         {
  168.                 src_temp = src;
  169.                 dst_temp = dst;
  170.                
  171.                 for (int x = width; x > 0; x--)
  172.                 {
  173.                         for (int z = scale; z > 0; z--)
  174.                         {
  175.                                 *(Uint16 *)dst = rgb_palette[*src];
  176.                                 dst += dst_Bpp;
  177.                         }
  178.                         src++;
  179.                 }
  180.                
  181.                 src = src_temp + src_pitch;
  182.                 dst = dst_temp + dst_pitch;
  183.                
  184.                 for (int z = scale; z > 1; z--)
  185.                 {
  186.                         memcpy(dst, dst_temp, dst_pitch);
  187.                         dst += dst_pitch;
  188.                 }
  189.         }
  190.        
  191. #ifdef VGA_CENTERED
  192.         memset(dst, 0, blank);
  193. #endif
  194. }
  195.  
  196.  
  197. void scale2x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  198. {
  199.         Uint8 *src = src_surface->pixels, *src_temp,
  200.               *dst = dst_surface->pixels, *dst_temp;
  201.         int src_pitch = src_surface->pitch,
  202.             dst_pitch = dst_surface->pitch;
  203.         const int dst_Bpp = 4;         // dst_surface->format->BytesPerPixel
  204.        
  205.         const int height = vga_height, // src_surface->h
  206.                   width = vga_width;   // src_surface->w
  207.        
  208.         int prevline, nextline;
  209.        
  210.         Uint32 E0, E1, E2, E3, B, D, E, F, H;
  211.         for (int y = 0; y < height; y++)
  212.         {
  213.                 src_temp = src;
  214.                 dst_temp = dst;
  215.                
  216.                 prevline = (y > 0) ? -src_pitch : 0;
  217.                 nextline = (y < height - 1) ? src_pitch : 0;
  218.                
  219.                 for (int x = 0; x < width; x++)
  220.                 {
  221.                         B = rgb_palette[*(src + prevline)];
  222.                         D = rgb_palette[*(x > 0 ? src - 1 : src)];
  223.                         E = rgb_palette[*src];
  224.                         F = rgb_palette[*(x < width - 1 ? src + 1 : src)];
  225.                         H = rgb_palette[*(src + nextline)];
  226.                        
  227.                         if (B != H && D != F) {
  228.                                 E0 = D == B ? D : E;
  229.                                 E1 = B == F ? F : E;
  230.                                 E2 = D == H ? D : E;
  231.                                 E3 = H == F ? F : E;
  232.                         } else {
  233.                                 E0 = E1 = E2 = E3 = E;
  234.                         }
  235.                        
  236.                         *(Uint32 *)dst = E0;
  237.                         *(Uint32 *)(dst + dst_Bpp) = E1;
  238.                         *(Uint32 *)(dst + dst_pitch) = E2;
  239.                         *(Uint32 *)(dst + dst_pitch + dst_Bpp) = E3;
  240.                        
  241.                         src++;
  242.                         dst += 2 * dst_Bpp;
  243.                 }
  244.                
  245.                 src = src_temp + src_pitch;
  246.                 dst = dst_temp + 2 * dst_pitch;
  247.         }
  248. }
  249.  
  250. void scale2x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  251. {
  252.         Uint8 *src = src_surface->pixels, *src_temp,
  253.               *dst = dst_surface->pixels, *dst_temp;
  254.         int src_pitch = src_surface->pitch,
  255.             dst_pitch = dst_surface->pitch;
  256.         const int dst_Bpp = 2;         // dst_surface->format->BytesPerPixel
  257.        
  258.         const int height = vga_height, // src_surface->h
  259.                   width = vga_width;   // src_surface->w
  260.        
  261.         int prevline, nextline;
  262.        
  263.         Uint16 E0, E1, E2, E3, B, D, E, F, H;
  264.         for (int y = 0; y < height; y++)
  265.         {
  266.                 src_temp = src;
  267.                 dst_temp = dst;
  268.                
  269.                 prevline = (y > 0) ? -src_pitch : 0;
  270.                 nextline = (y < height - 1) ? src_pitch : 0;
  271.                
  272.                 for (int x = 0; x < width; x++)
  273.                 {
  274.                         B = rgb_palette[*(src + prevline)];
  275.                         D = rgb_palette[*(x > 0 ? src - 1 : src)];
  276.                         E = rgb_palette[*src];
  277.                         F = rgb_palette[*(x < width - 1 ? src + 1 : src)];
  278.                         H = rgb_palette[*(src + nextline)];
  279.                        
  280.                         if (B != H && D != F) {
  281.                                 E0 = D == B ? D : E;
  282.                                 E1 = B == F ? F : E;
  283.                                 E2 = D == H ? D : E;
  284.                                 E3 = H == F ? F : E;
  285.                         } else {
  286.                                 E0 = E1 = E2 = E3 = E;
  287.                         }
  288.                        
  289.                         *(Uint16 *)dst = E0;
  290.                         *(Uint16 *)(dst + dst_Bpp) = E1;
  291.                         *(Uint16 *)(dst + dst_pitch) = E2;
  292.                         *(Uint16 *)(dst + dst_pitch + dst_Bpp) = E3;
  293.                        
  294.                         src++;
  295.                         dst += 2 * dst_Bpp;
  296.                 }
  297.                
  298.                 src = src_temp + src_pitch;
  299.                 dst = dst_temp + 2 * dst_pitch;
  300.         }
  301. }
  302.  
  303.  
  304. void scale3x_32( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  305. {
  306.         Uint8 *src = src_surface->pixels, *src_temp,
  307.               *dst = dst_surface->pixels, *dst_temp;
  308.         int src_pitch = src_surface->pitch,
  309.             dst_pitch = dst_surface->pitch;
  310.         const int dst_Bpp = 4;         // dst_surface->format->BytesPerPixel
  311.        
  312.         const int height = vga_height, // src_surface->h
  313.                   width = vga_width;   // src_surface->w
  314.        
  315.         int prevline, nextline;
  316.        
  317.         Uint32 E0, E1, E2, E3, E4, E5, E6, E7, E8, A, B, C, D, E, F, G, H, I;
  318.         for (int y = 0; y < height; y++)
  319.         {
  320.                 src_temp = src;
  321.                 dst_temp = dst;
  322.                
  323.                 prevline = (y > 0) ? -src_pitch : 0;
  324.                 nextline = (y < height - 1) ? src_pitch : 0;
  325.                
  326.                 for (int x = 0; x < width; x++)
  327.                 {
  328.                         A = rgb_palette[*(src + prevline - (x > 0 ? 1 : 0))];
  329.                         B = rgb_palette[*(src + prevline)];
  330.                         C = rgb_palette[*(src + prevline + (x < width - 1 ? 1 : 0))];
  331.                         D = rgb_palette[*(src - (x > 0 ? 1 : 0))];
  332.                         E = rgb_palette[*src];
  333.                         F = rgb_palette[*(src + (x < width - 1 ? 1 : 0))];
  334.                         G = rgb_palette[*(src + nextline - (x > 0 ? 1 : 0))];
  335.                         H = rgb_palette[*(src + nextline)];
  336.                         I = rgb_palette[*(src + nextline + (x < width - 1 ? 1 : 0))];
  337.                        
  338.                         if (B != H && D != F) {
  339.                                 E0 = D == B ? D : E;
  340.                                 E1 = (D == B && E != C) || (B == F && E != A) ? B : E;
  341.                                 E2 = B == F ? F : E;
  342.                                 E3 = (D == B && E != G) || (D == H && E != A) ? D : E;
  343.                                 E4 = E;
  344.                                 E5 = (B == F && E != I) || (H == F && E != C) ? F : E;
  345.                                 E6 = D == H ? D : E;
  346.                                 E7 = (D == H && E != I) || (H == F && E != G) ? H : E;
  347.                                 E8 = H == F ? F : E;
  348.                         } else {
  349.                                 E0 = E1 = E2 = E3 = E4 = E5 = E6 = E7 = E8 = E;
  350.                         }
  351.                        
  352.                         *(Uint32 *)dst = E0;
  353.                         *(Uint32 *)(dst + dst_Bpp) = E1;
  354.                         *(Uint32 *)(dst + 2 * dst_Bpp) = E2;
  355.                         *(Uint32 *)(dst + dst_pitch) = E3;
  356.                         *(Uint32 *)(dst + dst_pitch + dst_Bpp) = E4;
  357.                         *(Uint32 *)(dst + dst_pitch + 2 * dst_Bpp) = E5;
  358.                         *(Uint32 *)(dst + 2 * dst_pitch) = E6;
  359.                         *(Uint32 *)(dst + 2 * dst_pitch + dst_Bpp) = E7;
  360.                         *(Uint32 *)(dst + 2 * dst_pitch + 2 * dst_Bpp) = E8;
  361.                        
  362.                         src++;
  363.                         dst += 3 * dst_Bpp;
  364.                 }
  365.                
  366.                 src = src_temp + src_pitch;
  367.                 dst = dst_temp + 3 * dst_pitch;
  368.         }
  369. }
  370.  
  371. void scale3x_16( SDL_Surface *src_surface, SDL_Surface *dst_surface )
  372. {
  373.         Uint8 *src = src_surface->pixels, *src_temp,
  374.               *dst = dst_surface->pixels, *dst_temp;
  375.         int src_pitch = src_surface->pitch,
  376.             dst_pitch = dst_surface->pitch;
  377.         const int dst_Bpp = 2;         // dst_surface->format->BytesPerPixel
  378.        
  379.         const int height = vga_height, // src_surface->h
  380.                   width = vga_width;   // src_surface->w
  381.        
  382.         int prevline, nextline;
  383.        
  384.         Uint16 E0, E1, E2, E3, E4, E5, E6, E7, E8, A, B, C, D, E, F, G, H, I;
  385.         for (int y = 0; y < height; y++)
  386.         {
  387.                 src_temp = src;
  388.                 dst_temp = dst;
  389.                
  390.                 prevline = (y > 0) ? -src_pitch : 0;
  391.                 nextline = (y < height - 1) ? src_pitch : 0;
  392.                
  393.                 for (int x = 0; x < width; x++)
  394.                 {
  395.                         A = rgb_palette[*(src + prevline - (x > 0 ? 1 : 0))];
  396.                         B = rgb_palette[*(src + prevline)];
  397.                         C = rgb_palette[*(src + prevline + (x < width - 1 ? 1 : 0))];
  398.                         D = rgb_palette[*(src - (x > 0 ? 1 : 0))];
  399.                         E = rgb_palette[*src];
  400.                         F = rgb_palette[*(src + (x < width - 1 ? 1 : 0))];
  401.                         G = rgb_palette[*(src + nextline - (x > 0 ? 1 : 0))];
  402.                         H = rgb_palette[*(src + nextline)];
  403.                         I = rgb_palette[*(src + nextline + (x < width - 1 ? 1 : 0))];
  404.                        
  405.                         if (B != H && D != F) {
  406.                                 E0 = D == B ? D : E;
  407.                                 E1 = (D == B && E != C) || (B == F && E != A) ? B : E;
  408.                                 E2 = B == F ? F : E;
  409.                                 E3 = (D == B && E != G) || (D == H && E != A) ? D : E;
  410.                                 E4 = E;
  411.                                 E5 = (B == F && E != I) || (H == F && E != C) ? F : E;
  412.                                 E6 = D == H ? D : E;
  413.                                 E7 = (D == H && E != I) || (H == F && E != G) ? H : E;
  414.                                 E8 = H == F ? F : E;
  415.                         } else {
  416.                                 E0 = E1 = E2 = E3 = E4 = E5 = E6 = E7 = E8 = E;
  417.                         }
  418.                        
  419.                         *(Uint16 *)dst = E0;
  420.                         *(Uint16 *)(dst + dst_Bpp) = E1;
  421.                         *(Uint16 *)(dst + 2 * dst_Bpp) = E2;
  422.                         *(Uint16 *)(dst + dst_pitch) = E3;
  423.                         *(Uint16 *)(dst + dst_pitch + dst_Bpp) = E4;
  424.                         *(Uint16 *)(dst + dst_pitch + 2 * dst_Bpp) = E5;
  425.                         *(Uint16 *)(dst + 2 * dst_pitch) = E6;
  426.                         *(Uint16 *)(dst + 2 * dst_pitch + dst_Bpp) = E7;
  427.                         *(Uint16 *)(dst + 2 * dst_pitch + 2 * dst_Bpp) = E8;
  428.                        
  429.                         src++;
  430.                         dst += 3 * dst_Bpp;
  431.                 }
  432.                
  433.                 src = src_temp + src_pitch;
  434.                 dst = dst_temp + 3 * dst_pitch;
  435.         }
  436. }
  437.  
  438.