From 54e97e3bcaf04f64c30bec65b50691321ff4d474 Mon Sep 17 00:00:00 2001 From: gewlitys Date: Wed, 5 Feb 2003 01:18:34 +0000 Subject: [PATCH] Biadapt and biadv scaling now works in OpenGL mode too; separated scaling code from pure.c to 2xscalers.c git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@674 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/src/msvc++/UrQuanMasters.dsp | 8 + sc2/src/sc2code/libs/graphics/sdl/2xscalers.c | 2616 +++++++++++++++++ sc2/src/sc2code/libs/graphics/sdl/2xscalers.h | 27 + sc2/src/sc2code/libs/graphics/sdl/Makeinfo | 2 +- sc2/src/sc2code/libs/graphics/sdl/opengl.c | 130 +- sc2/src/sc2code/libs/graphics/sdl/pure.c | 2598 +--------------- 7 files changed, 2749 insertions(+), 2633 deletions(-) create mode 100644 sc2/src/sc2code/libs/graphics/sdl/2xscalers.c create mode 100644 sc2/src/sc2code/libs/graphics/sdl/2xscalers.h diff --git a/sc2/ChangeLog b/sc2/ChangeLog index a47070b75..15a5ec5e1 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.2: +- Biadapt and biadv scalers now work in OpenGL mode too -Mika - Fixed lockup when fastforwarding through orz comm -PBlue - A new windows installer is now in builds/win32_install -PBlue - Added '-a' switch to go between OpenAL and MixSDL at runtime -PBlue diff --git a/sc2/src/msvc++/UrQuanMasters.dsp b/sc2/src/msvc++/UrQuanMasters.dsp index 5c4805717..f90af92e5 100644 --- a/sc2/src/msvc++/UrQuanMasters.dsp +++ b/sc2/src/msvc++/UrQuanMasters.dsp @@ -152,6 +152,14 @@ SOURCE=..\sc2code\libs\file\temp.c # PROP Default_Filter "" # Begin Source File +SOURCE=..\sc2code\libs\graphics\sdl\2xscalers.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\sdl\2xscalers.h +# End Source File +# Begin Source File + SOURCE=..\sc2code\libs\graphics\sdl\3do_blt.c # End Source File # Begin Source File diff --git a/sc2/src/sc2code/libs/graphics/sdl/2xscalers.c b/sc2/src/sc2code/libs/graphics/sdl/2xscalers.c new file mode 100644 index 000000000..df056044f --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/sdl/2xscalers.c @@ -0,0 +1,2616 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef GFXMODULE_SDL + +#include "libs/graphics/sdl/sdl_common.h" +#include "2xscalers.h" + +static const Uint32 bilinear_table[4][4] = +{ + { 9, 3, 3, 1 }, + { 3, 1, 9, 3 }, + { 3, 9, 1, 3 }, + { 1, 3, 3, 9 } +}; + +typedef union +{ + struct + { + Uint8 c1, c2, c3; + } bchan; + Uint8 channels[3]; +} PIXEL_24BIT; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +// big endian cpu +// We avoid potential pagefaults based on the assumption +// that all buffers are allocated on *at least* 32bit boundary +// So if the pointer (p) is 32bit-aligned, we can read at +// least 32 bits at once; or if it is not aligned then we +// are not at the beginning of the buffer and can read 1 byte +// before (p) +// +// WARNING!! Do not call these macros like so: +// SET_PIX_24BIT (dst_p++, pixel) +// The pre-increment or post-increment will be done +// several times +// +# define GET_PIX_24BIT(p) \ + ( ((Uint32)(p)) & 3 ? \ + (*(Uint32 *)((Uint8 *)(p) - 1) & 0x00ffffff) : \ + (*(Uint32 *)(p) >> 8) \ + ) + +# define SET_PIX_24BIT(p, c) \ + ( ((Uint32)(p)) & 3 ? \ + ( *(Uint32 *)((Uint8 *)(p) - 1) = \ + (*(Uint32 *)((Uint8 *)(p) - 1) & 0xff000000) | \ + ((c) & 0x00ffffff) \ + ) : \ + ( *(Uint32 *)(p) = \ + (*(Uint32 *)(p) & 0x000000ff) | \ + ((c) << 8) \ + ) \ + ) +#else +// little endian cpu +// Same page-safety assumption applies as for big-endian +// +# define GET_PIX_24BIT(p) \ + ( ((Uint32)(p)) & 3 ? \ + (*(Uint32 *)((Uint8 *)(p) - 1) >> 8) : \ + (*(Uint32 *)(p) & 0x00ffffff) \ + ) + +# define SET_PIX_24BIT(p, c) \ + ( ((Uint32)(p)) & 3 ? \ + ( *(Uint32 *)((Uint8 *)(p) - 1) = \ + (*(Uint32 *)((Uint8 *)(p) - 1) & 0x000000ff) | \ + ((c) << 8) \ + ) : \ + ( *(Uint32 *)(p) = \ + (*(Uint32 *)(p) & 0xff000000) | \ + ((c) & 0x00ffffff) \ + ) \ + ) +#endif + +// RGB -> YUV transformation +// the RGB vector is multiplied by the transformation matrix +// to get the YUV vector +static const double YUV_matrix[3][3] = +{ + /* Y U V */ + /* R */ {0.2989, -0.1687, 0.5000}, + /* G */ {0.5867, -0.3312, -0.4183}, + /* B */ {0.1144, 0.5000, -0.0816} +}; + +typedef enum +{ + YUV_XFORM_R = 0, + YUV_XFORM_G = 1, + YUV_XFORM_B = 2, + YUV_XFORM_Y = 0, + YUV_XFORM_U = 1, + YUV_XFORM_V = 2 +} RGB_YUV_INDEX; + +// pre-computed transformations for 8 bits per channel +static int RGB_to_YUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 256]; +// double to int rounding error correction +#define YUV_ERR_CORR 0.4999 + +// pre-compute the RGB->YUV transformations +void +Scale_PrepYUV() +{ + int i1; + + for (i1 = 0; i1 < 3; i1++) // enum R,G,B + { + int i2; + for (i2 = 0; i2 < 3; i2++) // enum Y,U,V + { + int i3; + for (i3 = 0; i3 < 256; i3++) // enum possible channel vals + RGB_to_YUV[i1][i2][i3] = (int) + (YUV_matrix[i1][i2] * i3 + YUV_ERR_CORR); + } + } +} + +// expands the given rectangle in all directions by 'expansion' +// guarded by 'limits' +void +Scale_ExpandRect (SDL_Rect* rect, int expansion, SDL_Rect* limits) +{ + if (rect->x - expansion >= limits->x) + { + rect->w += expansion; + rect->x -= expansion; + } + else + { + rect->w += rect->x - limits->x; + rect->x = limits->x; + } + + if (rect->y - expansion >= limits->y) + { + rect->h += expansion; + rect->y -= expansion; + } + else + { + rect->h += rect->y - limits->y; + rect->y = limits->y; + } + + if (rect->x + rect->w + expansion <= limits->w) + rect->w += expansion; + else + rect->w = limits->w - rect->x; + + if (rect->y + rect->h + expansion <= limits->h) + rect->h += expansion; + else + rect->h = limits->h - rect->y; +} + +// blends two pixels with ratio 50% - 50% +__inline__ Uint32 +Scale_BlendPixels (SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) +{ + return ((((pix1 & fmt->Rmask) + + (pix2 & fmt->Rmask) + ) >> 1) & fmt->Rmask) | + ((((pix1 & fmt->Gmask) + + (pix2 & fmt->Gmask) + ) >> 1) & fmt->Gmask) | + ((((pix1 & fmt->Bmask) + + (pix2 & fmt->Bmask) + ) >> 1) & fmt->Bmask); +} + +// compare pixels by their RGB +__inline__ int +Scale_GetRGBDelta (SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) +{ + Uint32 c; + int delta; + + c = (((pix1 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss) + - (((pix2 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss); + delta = c * c; + + c = (((pix1 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss) + - (((pix2 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss); + delta += c * c; + + c = (((pix1 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss) + - (((pix2 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss); + delta += c * c; + + return delta; +} + +// compare pixels by their YUVs +__inline__ int +Scale_GetYUVDelta (SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) +{ + Uint32 r1, g1, b1, r2, g2, b2; + int compd, delta; + + r1 = ((pix1 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss; + g1 = ((pix1 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss; + b1 = ((pix1 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss; + r2 = ((pix2 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss; + g2 = ((pix2 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss; + b2 = ((pix2 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss; + + // compare Ys + compd = RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r1] + + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g1] + + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b1] + - RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r2] + - RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g2] + - RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b2]; + if (compd < 0) + compd = -compd; + // Y is 2-4 times more important than U or V + delta = compd << 1; + + // compare Us + compd = RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_U][r1] + + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_U][g1] + + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_U][b1] + - RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_U][r2] + - RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_U][g2] + - RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_U][b2]; + if (compd < 0) + compd = -compd; + delta += compd; + + // compare Vs + compd = RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_V][r1] + + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_V][g1] + + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_V][b1] + - RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_V][r2] + - RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_V][g2] + - RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_V][b2]; + if (compd < 0) + compd = -compd; + delta += compd; + + return delta; +} + +// retrieve the Y (intensity) component of pixel's YUV +__inline__ int +Scale_GetPixY (SDL_PixelFormat* fmt, Uint32 pix) +{ + Uint32 r, g, b; + + r = ((pix & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss; + g = ((pix & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss; + b = ((pix & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss; + + // compare Ys + return RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r] + + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g] + + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b]; +} + +// biadapt scaling to 2x +void +Scale_BiAdaptFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) +{ + int x, y; + const int w = src->w, h = src->h, dw = dst->w; + int xend, yend; + int dsrc, ddst; + SDL_Rect region = *r; + SDL_Rect limits; + SDL_PixelFormat *fmt = dst->format; + + // expand updated region if necessary + // pixels neighbooring the updated region may + // change as a result of updates + limits.x = 0; + limits.y = 0; + limits.w = src->w; + limits.h = src->h; + Scale_ExpandRect (®ion, 2, &limits); + + xend = region.x + region.w; + yend = region.y + region.h; + dsrc = w - region.w; + ddst = (dw - region.w) * 2; + + switch (fmt->BytesPerPixel) + { + case 2: // 16bpp scaling + #define BIADAPT_GETPIX(p) ( *(Uint16 *)(p) ) + #define BIADAPT_SETPIX(p, c) ( *(Uint16 *)(p) = (c) ) + #define BIADAPT_BUF Uint16 + { + BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; + BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; + Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; + + // move ptrs to the first updated pixel + src_p += w * region.y + region.x; + dst_p += (dw * region.y + region.x) * 2; + + for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) + { + for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) + { + pixval_tl = BIADAPT_GETPIX (src_p); + + BIADAPT_SETPIX (dst_p, pixval_tl); + + if (y + 1 < h) + { + // check pixel below the current one + pixval_bl = BIADAPT_GETPIX (src_p + w); + + if (pixval_tl == pixval_bl) + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + else + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, pixval_tl, pixval_bl) + ); + } + else + { + // last pixel in column - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + } + dst_p++; + + + if (x + 1 >= w) + { + // last pixel in row - propagate + BIADAPT_SETPIX (dst_p, pixval_tl); + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // check pixel to the right from the current one + pixval_tr = BIADAPT_GETPIX (src_p + 1); + + if (pixval_tl == pixval_tr) + BIADAPT_SETPIX (dst_p, pixval_tr); + else + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, pixval_tl, pixval_tr) + ); + + if (y + 1 >= h) + { + // last pixel in column - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // check pixel to the bottom-right + pixval_br = BIADAPT_GETPIX (src_p + 1 + w); + + if (pixval_tl == pixval_br && pixval_tr == pixval_bl) + { + int cl, cr; + Uint32 clr; + + if (pixval_tl == pixval_tr) + { + // all 4 are equal - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // both pairs are equal, have to resolve the pixel + // race; we try detecting which color is + // the background by looking for a line or an edge + // examine 8 pixels surrounding the current quad + + cl = cr = 1; + + if (x > 0) + { + clr = BIADAPT_GETPIX (src_p - 1); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p - 1 + w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (y > 0) + { + clr = BIADAPT_GETPIX (src_p - w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 1 - w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (x + 2 < w) + { + clr = BIADAPT_GETPIX (src_p + 2); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 2 + w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (y + 2 < h) + { + clr = BIADAPT_GETPIX (src_p + 2 * w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 1 + 2 * w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + // least count wins + if (cl > cr) + BIADAPT_SETPIX (dst_p + dw, pixval_tr); + else if (cr > cl) + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + else + BIADAPT_SETPIX (dst_p + dw, + Scale_BlendPixels (fmt, pixval_tl, + pixval_tr)); + } + else if (pixval_tl == pixval_br) + { + // main diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + } + else if (pixval_tr == pixval_bl) + { + // 2nd diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, pixval_tr); + } + else + { + // blend all 4 + BIADAPT_SETPIX (dst_p + dw, + ((((pixval_tl & fmt->Rmask) + + (pixval_bl & fmt->Rmask) + + (pixval_tr & fmt->Rmask) + + (pixval_br & fmt->Rmask) + ) >> 2) & fmt->Rmask) | + ((((pixval_tl & fmt->Gmask) + + (pixval_bl & fmt->Gmask) + + (pixval_tr & fmt->Gmask) + + (pixval_br & fmt->Gmask) + ) >> 2) & fmt->Gmask) | + ((((pixval_tl & fmt->Bmask) + + (pixval_bl & fmt->Bmask) + + (pixval_tr & fmt->Bmask) + + (pixval_br & fmt->Bmask) + ) >> 2) & fmt->Bmask)); + } + } + } + break; + } + #undef BIADAPT_GETPIX + #undef BIADAPT_SETPIX + #undef BIADAPT_BUF + + case 3: // 24bpp scaling + #define BIADAPT_GETPIX(p) GET_PIX_24BIT(p) + #define BIADAPT_SETPIX(p, c) SET_PIX_24BIT(p, c) + #define BIADAPT_BUF PIXEL_24BIT + { + BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; + BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; + Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; + + // move ptrs to the first updated pixel + src_p += w * region.y + region.x; + dst_p += (dw * region.y + region.x) * 2; + + for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) + { + for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) + { + pixval_tl = BIADAPT_GETPIX (src_p); + + BIADAPT_SETPIX (dst_p, pixval_tl); + + if (y + 1 < h) + { + // check pixel below the current one + pixval_bl = BIADAPT_GETPIX (src_p + w); + + if (pixval_tl == pixval_bl) + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + else + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, pixval_tl, pixval_bl) + ); + } + else + { + // last pixel in column - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + } + dst_p++; + + + if (x + 1 >= w) + { + // last pixel in row - propagate + BIADAPT_SETPIX (dst_p, pixval_tl); + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // check pixel to the right from the current one + pixval_tr = BIADAPT_GETPIX (src_p + 1); + + if (pixval_tl == pixval_tr) + BIADAPT_SETPIX (dst_p, pixval_tr); + else + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, pixval_tl, pixval_tr) + ); + + if (y + 1 >= h) + { + // last pixel in column - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // check pixel to the bottom-right + pixval_br = BIADAPT_GETPIX (src_p + 1 + w); + + if (pixval_tl == pixval_br && pixval_tr == pixval_bl) + { + int cl, cr; + Uint32 clr; + + if (pixval_tl == pixval_tr) + { + // all 4 are equal - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // both pairs are equal, have to resolve the pixel + // race; we try detecting which color is + // the background by looking for a line or an edge + // examine 8 pixels surrounding the current quad + + cl = cr = 1; + + if (x > 0) + { + clr = BIADAPT_GETPIX (src_p - 1); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p - 1 + w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (y > 0) + { + clr = BIADAPT_GETPIX (src_p - w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 1 - w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (x + 2 < w) + { + clr = BIADAPT_GETPIX (src_p + 2); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 2 + w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (y + 2 < h) + { + clr = BIADAPT_GETPIX (src_p + 2 * w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 1 + 2 * w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + // least count wins + if (cl > cr) + BIADAPT_SETPIX (dst_p + dw, pixval_tr); + else if (cr > cl) + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + else + BIADAPT_SETPIX (dst_p + dw, + Scale_BlendPixels (fmt, pixval_tl, + pixval_tr)); + } + else if (pixval_tl == pixval_br) + { + // main diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + } + else if (pixval_tr == pixval_bl) + { + // 2nd diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, pixval_tr); + } + else + { + // blend all 4 + BIADAPT_SETPIX (dst_p + dw, + ((((pixval_tl & fmt->Rmask) + + (pixval_bl & fmt->Rmask) + + (pixval_tr & fmt->Rmask) + + (pixval_br & fmt->Rmask) + ) >> 2) & fmt->Rmask) | + ((((pixval_tl & fmt->Gmask) + + (pixval_bl & fmt->Gmask) + + (pixval_tr & fmt->Gmask) + + (pixval_br & fmt->Gmask) + ) >> 2) & fmt->Gmask) | + ((((pixval_tl & fmt->Bmask) + + (pixval_bl & fmt->Bmask) + + (pixval_tr & fmt->Bmask) + + (pixval_br & fmt->Bmask) + ) >> 2) & fmt->Bmask)); + } + } + } + break; + } + #undef BIADAPT_GETPIX + #undef BIADAPT_SETPIX + #undef BIADAPT_BUF + + case 4: // 32bpp scaling + #define BIADAPT_GETPIX(p) ( *(Uint32 *)(p) ) + #define BIADAPT_SETPIX(p, c) ( *(Uint32 *)(p) = (c) ) + #define BIADAPT_BUF Uint32 + { + BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; + BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; + Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; + + // move ptrs to the first updated pixel + src_p += w * region.y + region.x; + dst_p += (dw * region.y + region.x) * 2; + + for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) + { + for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) + { + pixval_tl = BIADAPT_GETPIX (src_p); + + BIADAPT_SETPIX (dst_p, pixval_tl); + + if (y + 1 < h) + { + // check pixel below the current one + pixval_bl = BIADAPT_GETPIX (src_p + w); + + if (pixval_tl == pixval_bl) + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + else + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, pixval_tl, pixval_bl) + ); + } + else + { + // last pixel in column - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + } + dst_p++; + + + if (x + 1 >= w) + { + // last pixel in row - propagate + BIADAPT_SETPIX (dst_p, pixval_tl); + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // check pixel to the right from the current one + pixval_tr = BIADAPT_GETPIX (src_p + 1); + + if (pixval_tl == pixval_tr) + BIADAPT_SETPIX (dst_p, pixval_tr); + else + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, pixval_tl, pixval_tr) + ); + + if (y + 1 >= h) + { + // last pixel in column - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // check pixel to the bottom-right + pixval_br = BIADAPT_GETPIX (src_p + 1 + w); + + if (pixval_tl == pixval_br && pixval_tr == pixval_bl) + { + int cl, cr; + Uint32 clr; + + if (pixval_tl == pixval_tr) + { + // all 4 are equal - propagate + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + continue; + } + + // both pairs are equal, have to resolve the pixel + // race; we try detecting which color is + // the background by looking for a line or an edge + // examine 8 pixels surrounding the current quad + + cl = cr = 1; + + if (x > 0) + { + clr = BIADAPT_GETPIX (src_p - 1); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p - 1 + w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (y > 0) + { + clr = BIADAPT_GETPIX (src_p - w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 1 - w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (x + 2 < w) + { + clr = BIADAPT_GETPIX (src_p + 2); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 2 + w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + if (y + 2 < h) + { + clr = BIADAPT_GETPIX (src_p + 2 * w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + + clr = BIADAPT_GETPIX (src_p + 1 + 2 * w); + if (clr == pixval_tl) + cl++; + else if (clr == pixval_tr) + cr++; + } + + // least count wins + if (cl > cr) + BIADAPT_SETPIX (dst_p + dw, pixval_tr); + else if (cr > cl) + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + else + BIADAPT_SETPIX (dst_p + dw, + Scale_BlendPixels (fmt, pixval_tl, + pixval_tr)); + } + else if (pixval_tl == pixval_br) + { + // main diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, pixval_tl); + } + else if (pixval_tr == pixval_bl) + { + // 2nd diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, pixval_tr); + } + else + { + // blend all 4 + BIADAPT_SETPIX (dst_p + dw, + ((((pixval_tl & fmt->Rmask) + + (pixval_bl & fmt->Rmask) + + (pixval_tr & fmt->Rmask) + + (pixval_br & fmt->Rmask) + ) >> 2) & fmt->Rmask) | + ((((pixval_tl & fmt->Gmask) + + (pixval_bl & fmt->Gmask) + + (pixval_tr & fmt->Gmask) + + (pixval_br & fmt->Gmask) + ) >> 2) & fmt->Gmask) | + ((((pixval_tl & fmt->Bmask) + + (pixval_bl & fmt->Bmask) + + (pixval_tr & fmt->Bmask) + + (pixval_br & fmt->Bmask) + ) >> 2) & fmt->Bmask)); + } + } + } + break; + } + #undef BIADAPT_GETPIX + #undef BIADAPT_SETPIX + #undef BIADAPT_BUF + #undef BIADAPT_CLR + + } +} + +// advanced biadapt scaling to 2x +void +Scale_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) +{ + int x, y; + const int w = src->w, h = src->h, dw = dst->w; + int xend, yend; + int dsrc, ddst; + SDL_Rect region = *r; + SDL_Rect limits; + SDL_PixelFormat *fmt = dst->format; + // for clarity purposes, the 'pixels' array here is transposed + Uint32 pixels[4][4]; + static int resolve_coord[][2] = + { + {0, -1}, {1, -1}, { 2, 0}, { 2, 1}, + {1, 2}, {0, 2}, {-1, 1}, {-1, 0}, + {100, 100} // term + }; + + // these macros are for clarity; they make the current pixel (0,0) + // and allow to access pixels in all directions + #define PIX(x, y) (pixels[1 + (x)][1 + (y)]) + #define SRC(x, y) (src_p + (x) + ((y) * w)) + // commonly used operations, for clarity also + // others are defined at their respective bpp levels + #define BIADAPT_RGBHIGH 8000 + #define BIADAPT_YUVLOW 30 + #define BIADAPT_YUVMED 70 + #define BIADAPT_YUVHIGH 130 + + #define BIADAPT_CMPRGB(p1, p2) \ + Scale_GetRGBDelta (fmt, p1, p2) + // high tolerance pixel comparison + #define BIADAPT_CMPRGB_HIGH(p1, p2) \ + (p1 == p2 || BIADAPT_CMPRGB (p1, p2) <= BIADAPT_RGBHIGH) + + #define BIADAPT_CMPYUV(p1, p2) \ + Scale_GetYUVDelta (fmt, p1, p2) + // low tolerance pixel comparison + #define BIADAPT_CMPYUV_LOW(p1, p2) \ + (p1 == p2 || BIADAPT_CMPYUV (p1, p2) <= BIADAPT_YUVLOW) + // medium tolerance pixel comparison + #define BIADAPT_CMPYUV_MED(p1, p2) \ + (p1 == p2 || BIADAPT_CMPYUV (p1, p2) <= BIADAPT_YUVMED) + // high tolerance pixel comparison + #define BIADAPT_CMPYUV_HIGH(p1, p2) \ + (p1 == p2 || BIADAPT_CMPYUV (p1, p2) <= BIADAPT_YUVHIGH) + + // expand updated region if necessary + // pixels neighbooring the updated region may + // change as a result of updates + limits.x = 0; + limits.y = 0; + limits.w = src->w; + limits.h = src->h; + Scale_ExpandRect (®ion, 2, &limits); + + xend = region.x + region.w; + yend = region.y + region.h; + dsrc = w - region.w; + ddst = (dw - region.w) * 2; + + switch (fmt->BytesPerPixel) + { + case 2: // 16bpp scaling + #define BIADAPT_GETPIX(p) ( *(Uint16 *)(p) ) + #define BIADAPT_SETPIX(p, c) ( *(Uint16 *)(p) = (c) ) + #define BIADAPT_BUF Uint16 + { + BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; + BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; + + src_p += w * region.y + region.x; + dst_p += (dw * region.y + region.x) * 2; + + for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) + { + for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) + { + // pixel eqaulity counter + int cmatch; + + // most pixels will fall into 'all 4 equal' + // pattern, so we check it first + cmatch = 0; + + PIX (0, 0) = BIADAPT_GETPIX (SRC (0, 0)); + + BIADAPT_SETPIX (dst_p, PIX (0, 0)); + + if (y + 1 < h) + { + // check pixel below the current one + PIX (0, 1) = BIADAPT_GETPIX (SRC (0, 1)); + + if (PIX (0, 0) == PIX (0, 1)) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + cmatch |= 1; + } + } + else + { + // last pixel in column - propagate + PIX (0, 1) = PIX (0, 0); + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + cmatch |= 1; + + } + + if (x + 1 < w) + { + // check pixel to the right from the current one + PIX (1, 0) = BIADAPT_GETPIX (SRC (1, 0)); + + if (PIX (0, 0) == PIX (1, 0)) + { + BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); + cmatch |= 2; + } + } + else + { + // last pixel in row - propagate + PIX (1, 0) = PIX (0, 0); + BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); + cmatch |= 2; + } + + if (cmatch == 3) + { + if (y + 1 < h || x + 1 < w) + { + // last pixel in row/column and nearest + // neighboor is identical + dst_p++; + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + continue; + } + + // check pixel to the bottom-right + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + + if (PIX (0, 0) == PIX (1, 1)) + { + // all 4 are equal - propagate + dst_p++; + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + continue; + } + } + + // some neighnoors are different, lets check them + + if (x > 0) + PIX (-1, 0) = BIADAPT_GETPIX (SRC (-1, 0)); + else + PIX (-1, 0) = PIX (0, 0); + + if (x + 2 < w) + PIX (2, 0) = BIADAPT_GETPIX (SRC (2, 0)); + else + PIX (2, 0) = PIX (1, 0); + + if (y + 1 < h) + { + if (x > 0) + PIX (-1, 1) = BIADAPT_GETPIX (SRC (-1, 1)); + else + PIX (-1, 1) = PIX (0, 1); + + if (x + 2 < w) + { + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + PIX (2, 1) = BIADAPT_GETPIX (SRC (2, 1)); + } + else if (x + 1 < w) + { + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + PIX (2, 1) = PIX (1, 1); + } + else + { + PIX (1, 1) = PIX (0, 1); + PIX (2, 1) = PIX (0, 1); + } + } + else + { + // last pixel in column + PIX (-1, 1) = PIX (-1, 0); + PIX (1, 1) = PIX (1, 0); + PIX (2, 1) = PIX (2, 0); + } + + if (y + 2 < h) + { + PIX (0, 2) = BIADAPT_GETPIX (SRC (0, 2)); + + if (x > 0) + PIX (-1, 2) = BIADAPT_GETPIX (SRC (-1, 2)); + else + PIX (-1, 2) = PIX (0, 2); + + if (x + 2 < w) + { + PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); + PIX (2, 2) = BIADAPT_GETPIX (SRC (2, 2)); + } + else if (x + 1 < w) + { + PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); + PIX (2, 2) = PIX (1, 2); + } + else + { + PIX (1, 2) = PIX (0, 2); + PIX (2, 2) = PIX (0, 2); + } + } + else + { + // last pixel in column + PIX (-1, 2) = PIX (-1, 1); + PIX (0, 2) = PIX (0, 1); + PIX (1, 2) = PIX (1, 1); + PIX (2, 2) = PIX (2, 1); + } + + if (y > 0) + { + PIX (0, -1) = BIADAPT_GETPIX (SRC (0, -1)); + + if (x > 0) + PIX (-1, -1) = BIADAPT_GETPIX (SRC (-1, -1)); + else + PIX (-1, -1) = PIX (0, -1); + + if (x + 2 < w) + { + PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); + PIX (2, -1) = BIADAPT_GETPIX (SRC (2, -1)); + } + else if (x + 1 < w) + { + PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); + PIX (2, -1) = PIX (1, -1); + } + else + { + PIX (1, -1) = PIX (0, -1); + PIX (2, -1) = PIX (0, -1); + } + } + else + { + PIX (-1, -1) = PIX (-1, 0); + PIX (0, -1) = PIX (0, 0); + PIX (1, -1) = PIX (1, 0); + PIX (2, -1) = PIX (2, 0); + } + + // check pixel below the current one + if (!(cmatch & 1)) + { + if (BIADAPT_CMPYUV (PIX (0, 0), PIX (0, 1)) <= BIADAPT_YUVLOW) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (0, 1)) + ); + cmatch |= 1; + } + // detect a 2:1 line going across the current pixel + else if ( (PIX (0, 0) == PIX (-1, 0) + && PIX (0, 0) == PIX (1, 1) + && PIX (0, 0) == PIX (2, 1) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || + + (PIX (0, 0) == PIX (1, 0) + && PIX (0, 0) == PIX (-1, 1) + && PIX (0, 0) == PIX (2, -1) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + } + // detect a 2:1 line going across the pixel below current + else if ( (PIX (0, 1) == PIX (-1, 0) + && PIX (0, 1) == PIX (1, 1) + && PIX (0, 1) == PIX (2, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || + + (PIX (0, 1) == PIX (1, 0) + && PIX (0, 1) == PIX (-1, 1) + && PIX (0, 1) == PIX (2, 0) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 1)); + } + else + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (0, 1)) + ); + } + + dst_p++; + + // check pixel to the right from the current one + if (!(cmatch & 2)) + { + if (BIADAPT_CMPYUV (PIX (0, 0), PIX (1, 0)) <= BIADAPT_YUVLOW) + { + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 0)) + ); + cmatch |= 2; + } + // detect a 1:2 line going across the current pixel + else if ( (PIX (0, 0) == PIX (1, -1) + && PIX (0, 0) == PIX (0, 1) + && PIX (0, 0) == PIX (-1, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || + + (PIX (0, 0) == PIX (0, -1) + && PIX (0, 0) == PIX (1, 1) + && PIX (0, 0) == PIX (1, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) + + { + BIADAPT_SETPIX (dst_p, PIX (0, 0)); + } + // detect a 1:2 line going across the pixel to the right + else if ( (PIX (1, 0) == PIX (1, -1) + && PIX (1, 0) == PIX (0, 1) + && PIX (1, 0) == PIX (0, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || + + (PIX (1, 0) == PIX (0, -1) + && PIX (1, 0) == PIX (1, 1) + && PIX (1, 0) == PIX (2, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) + { + BIADAPT_SETPIX (dst_p, PIX (1, 0)); + } + else + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 0)) + ); + } + + if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) + { + // diagonals are equal + int *coord; + int cl, cr; + Uint32 clr; + + // both pairs are equal, have to resolve the pixel + // race; we try detecting which color is + // the background by looking for a line or an edge + // examine 8 pixels surrounding the current quad + + cl = cr = 2; + for (coord = resolve_coord[0]; *coord < 100; coord += 2) + { + clr = PIX (coord[0], coord[1]); + + if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) + cl++; + else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) + cr++; + } + + // least count wins + if (cl > cr) + clr = PIX (1, 0); + else if (cr > cl) + clr = PIX (0, 0); + else + clr = Scale_BlendPixels (fmt, + PIX (0, 0), PIX (1, 0)); + + BIADAPT_SETPIX (dst_p + dw, clr); + continue; + } + + if (cmatch == 3 + || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) + && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 1), PIX (1, 0)) + ); + continue; + } + else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + continue; + } + + // check pixel to the bottom-right + if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) + && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) + { + if (Scale_GetPixY (fmt, PIX (0, 0)) + > Scale_GetPixY (fmt, PIX (1, 0))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + } + else + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (1, 0), PIX (0, 1)) + ); + } + } + else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) + { + // main diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + } + else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) + { + // 2nd diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (1, 0), PIX (0, 1)) + ); + } + else + { + // blend all 4 + BIADAPT_SETPIX (dst_p + dw, + ((((PIX (0, 0) & fmt->Rmask) + + (PIX (0, 1) & fmt->Rmask) + + (PIX (1, 0) & fmt->Rmask) + + (PIX (1, 1) & fmt->Rmask) + ) >> 2) & fmt->Rmask) | + ((((PIX (0, 0) & fmt->Gmask) + + (PIX (0, 1) & fmt->Gmask) + + (PIX (1, 0) & fmt->Gmask) + + (PIX (1, 1) & fmt->Gmask) + ) >> 2) & fmt->Gmask) | + ((((PIX (0, 0) & fmt->Bmask) + + (PIX (0, 1) & fmt->Bmask) + + (PIX (1, 0) & fmt->Bmask) + + (PIX (1, 1) & fmt->Bmask) + ) >> 2) & fmt->Bmask)); + } + } + } + break; + } + #undef BIADAPT_GETPIX + #undef BIADAPT_SETPIX + #undef BIADAPT_BUF + + case 3: // 24bpp scaling + #define BIADAPT_GETPIX(p) GET_PIX_24BIT(p) + #define BIADAPT_SETPIX(p, c) SET_PIX_24BIT(p, c) + #define BIADAPT_BUF PIXEL_24BIT + { + BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; + BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; + + src_p += w * region.y + region.x; + dst_p += (dw * region.y + region.x) * 2; + + for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) + { + for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) + { + // pixel eqaulity counter + int cmatch; + + // most pixels will fall into 'all 4 equal' + // pattern, so we check it first + cmatch = 0; + + PIX (0, 0) = BIADAPT_GETPIX (SRC (0, 0)); + + BIADAPT_SETPIX (dst_p, PIX (0, 0)); + + if (y + 1 < h) + { + // check pixel below the current one + PIX (0, 1) = BIADAPT_GETPIX (SRC (0, 1)); + + if (PIX (0, 0) == PIX (0, 1)) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + cmatch |= 1; + } + } + else + { + // last pixel in column - propagate + PIX (0, 1) = PIX (0, 0); + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + cmatch |= 1; + + } + + if (x + 1 < w) + { + // check pixel to the right from the current one + PIX (1, 0) = BIADAPT_GETPIX (SRC (1, 0)); + + if (PIX (0, 0) == PIX (1, 0)) + { + BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); + cmatch |= 2; + } + } + else + { + // last pixel in row - propagate + PIX (1, 0) = PIX (0, 0); + BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); + cmatch |= 2; + } + + if (cmatch == 3) + { + if (y + 1 < h || x + 1 < w) + { + // last pixel in row/column and nearest + // neighboor is identical + dst_p++; + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + continue; + } + + // check pixel to the bottom-right + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + + if (PIX (0, 0) == PIX (1, 1)) + { + // all 4 are equal - propagate + dst_p++; + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + continue; + } + } + + // some neighnoors are different, lets check them + + if (x > 0) + PIX (-1, 0) = BIADAPT_GETPIX (SRC (-1, 0)); + else + PIX (-1, 0) = PIX (0, 0); + + if (x + 2 < w) + PIX (2, 0) = BIADAPT_GETPIX (SRC (2, 0)); + else + PIX (2, 0) = PIX (1, 0); + + if (y + 1 < h) + { + if (x > 0) + PIX (-1, 1) = BIADAPT_GETPIX (SRC (-1, 1)); + else + PIX (-1, 1) = PIX (0, 1); + + if (x + 2 < w) + { + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + PIX (2, 1) = BIADAPT_GETPIX (SRC (2, 1)); + } + else if (x + 1 < w) + { + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + PIX (2, 1) = PIX (1, 1); + } + else + { + PIX (1, 1) = PIX (0, 1); + PIX (2, 1) = PIX (0, 1); + } + } + else + { + // last pixel in column + PIX (-1, 1) = PIX (-1, 0); + PIX (1, 1) = PIX (1, 0); + PIX (2, 1) = PIX (2, 0); + } + + if (y + 2 < h) + { + PIX (0, 2) = BIADAPT_GETPIX (SRC (0, 2)); + + if (x > 0) + PIX (-1, 2) = BIADAPT_GETPIX (SRC (-1, 2)); + else + PIX (-1, 2) = PIX (0, 2); + + if (x + 2 < w) + { + PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); + PIX (2, 2) = BIADAPT_GETPIX (SRC (2, 2)); + } + else if (x + 1 < w) + { + PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); + PIX (2, 2) = PIX (1, 2); + } + else + { + PIX (1, 2) = PIX (0, 2); + PIX (2, 2) = PIX (0, 2); + } + } + else + { + // last pixel in column + PIX (-1, 2) = PIX (-1, 1); + PIX (0, 2) = PIX (0, 1); + PIX (1, 2) = PIX (1, 1); + PIX (2, 2) = PIX (2, 1); + } + + if (y > 0) + { + PIX (0, -1) = BIADAPT_GETPIX (SRC (0, -1)); + + if (x > 0) + PIX (-1, -1) = BIADAPT_GETPIX (SRC (-1, -1)); + else + PIX (-1, -1) = PIX (0, -1); + + if (x + 2 < w) + { + PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); + PIX (2, -1) = BIADAPT_GETPIX (SRC (2, -1)); + } + else if (x + 1 < w) + { + PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); + PIX (2, -1) = PIX (1, -1); + } + else + { + PIX (1, -1) = PIX (0, -1); + PIX (2, -1) = PIX (0, -1); + } + } + else + { + PIX (-1, -1) = PIX (-1, 0); + PIX (0, -1) = PIX (0, 0); + PIX (1, -1) = PIX (1, 0); + PIX (2, -1) = PIX (2, 0); + } + + // check pixel below the current one + if (!(cmatch & 1)) + { + if (BIADAPT_CMPYUV (PIX (0, 0), PIX (0, 1)) <= BIADAPT_YUVLOW) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (0, 1)) + ); + cmatch |= 1; + } + // detect a 2:1 line going across the current pixel + else if ( (PIX (0, 0) == PIX (-1, 0) + && PIX (0, 0) == PIX (1, 1) + && PIX (0, 0) == PIX (2, 1) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || + + (PIX (0, 0) == PIX (1, 0) + && PIX (0, 0) == PIX (-1, 1) + && PIX (0, 0) == PIX (2, -1) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + } + // detect a 2:1 line going across the pixel below current + else if ( (PIX (0, 1) == PIX (-1, 0) + && PIX (0, 1) == PIX (1, 1) + && PIX (0, 1) == PIX (2, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || + + (PIX (0, 1) == PIX (1, 0) + && PIX (0, 1) == PIX (-1, 1) + && PIX (0, 1) == PIX (2, 0) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 1)); + } + else + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (0, 1)) + ); + } + + dst_p++; + + // check pixel to the right from the current one + if (!(cmatch & 2)) + { + if (BIADAPT_CMPYUV (PIX (0, 0), PIX (1, 0)) <= BIADAPT_YUVLOW) + { + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 0)) + ); + cmatch |= 2; + } + // detect a 1:2 line going across the current pixel + else if ( (PIX (0, 0) == PIX (1, -1) + && PIX (0, 0) == PIX (0, 1) + && PIX (0, 0) == PIX (-1, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || + + (PIX (0, 0) == PIX (0, -1) + && PIX (0, 0) == PIX (1, 1) + && PIX (0, 0) == PIX (1, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) + + { + BIADAPT_SETPIX (dst_p, PIX (0, 0)); + } + // detect a 1:2 line going across the pixel to the right + else if ( (PIX (1, 0) == PIX (1, -1) + && PIX (1, 0) == PIX (0, 1) + && PIX (1, 0) == PIX (0, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || + + (PIX (1, 0) == PIX (0, -1) + && PIX (1, 0) == PIX (1, 1) + && PIX (1, 0) == PIX (2, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) + { + BIADAPT_SETPIX (dst_p, PIX (1, 0)); + } + else + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 0)) + ); + } + + if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) + { + // diagonals are equal + int *coord; + int cl, cr; + Uint32 clr; + + // both pairs are equal, have to resolve the pixel + // race; we try detecting which color is + // the background by looking for a line or an edge + // examine 8 pixels surrounding the current quad + + cl = cr = 2; + for (coord = resolve_coord[0]; *coord < 100; coord += 2) + { + clr = PIX (coord[0], coord[1]); + + if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) + cl++; + else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) + cr++; + } + + // least count wins + if (cl > cr) + clr = PIX (1, 0); + else if (cr > cl) + clr = PIX (0, 0); + else + clr = Scale_BlendPixels (fmt, + PIX (0, 0), PIX (1, 0)); + + BIADAPT_SETPIX (dst_p + dw, clr); + continue; + } + + if (cmatch == 3 + || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) + && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 1), PIX (1, 0)) + ); + continue; + } + else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + continue; + } + + // check pixel to the bottom-right + if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) + && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) + { + if (Scale_GetPixY (fmt, PIX (0, 0)) + > Scale_GetPixY (fmt, PIX (1, 0))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + } + else + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (1, 0), PIX (0, 1)) + ); + } + } + else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) + { + // main diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + } + else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) + { + // 2nd diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (1, 0), PIX (0, 1)) + ); + } + else + { + // blend all 4 + BIADAPT_SETPIX (dst_p + dw, + ((((PIX (0, 0) & fmt->Rmask) + + (PIX (0, 1) & fmt->Rmask) + + (PIX (1, 0) & fmt->Rmask) + + (PIX (1, 1) & fmt->Rmask) + ) >> 2) & fmt->Rmask) | + ((((PIX (0, 0) & fmt->Gmask) + + (PIX (0, 1) & fmt->Gmask) + + (PIX (1, 0) & fmt->Gmask) + + (PIX (1, 1) & fmt->Gmask) + ) >> 2) & fmt->Gmask) | + ((((PIX (0, 0) & fmt->Bmask) + + (PIX (0, 1) & fmt->Bmask) + + (PIX (1, 0) & fmt->Bmask) + + (PIX (1, 1) & fmt->Bmask) + ) >> 2) & fmt->Bmask)); + } + } + } + break; + } + #undef BIADAPT_GETPIX + #undef BIADAPT_SETPIX + #undef BIADAPT_BUF + + case 4: // 32bpp scaling + #define BIADAPT_GETPIX(p) ( *(Uint32 *)(p) ) + #define BIADAPT_SETPIX(p, c) ( *(Uint32 *)(p) = (c) ) + #define BIADAPT_BUF Uint32 + { + BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; + BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; + + src_p += w * region.y + region.x; + dst_p += (dw * region.y + region.x) * 2; + + for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) + { + for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) + { + // pixel eqaulity counter + int cmatch; + + // most pixels will fall into 'all 4 equal' + // pattern, so we check it first + cmatch = 0; + + PIX (0, 0) = BIADAPT_GETPIX (SRC (0, 0)); + + BIADAPT_SETPIX (dst_p, PIX (0, 0)); + + if (y + 1 < h) + { + // check pixel below the current one + PIX (0, 1) = BIADAPT_GETPIX (SRC (0, 1)); + + if (PIX (0, 0) == PIX (0, 1)) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + cmatch |= 1; + } + } + else + { + // last pixel in column - propagate + PIX (0, 1) = PIX (0, 0); + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + cmatch |= 1; + + } + + if (x + 1 < w) + { + // check pixel to the right from the current one + PIX (1, 0) = BIADAPT_GETPIX (SRC (1, 0)); + + if (PIX (0, 0) == PIX (1, 0)) + { + BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); + cmatch |= 2; + } + } + else + { + // last pixel in row - propagate + PIX (1, 0) = PIX (0, 0); + BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); + cmatch |= 2; + } + + if (cmatch == 3) + { + if (y + 1 < h || x + 1 < w) + { + // last pixel in row/column and nearest + // neighboor is identical + dst_p++; + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + continue; + } + + // check pixel to the bottom-right + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + + if (PIX (0, 0) == PIX (1, 1)) + { + // all 4 are equal - propagate + dst_p++; + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + continue; + } + } + + // some neighnoors are different, lets check them + + if (x > 0) + PIX (-1, 0) = BIADAPT_GETPIX (SRC (-1, 0)); + else + PIX (-1, 0) = PIX (0, 0); + + if (x + 2 < w) + PIX (2, 0) = BIADAPT_GETPIX (SRC (2, 0)); + else + PIX (2, 0) = PIX (1, 0); + + if (y + 1 < h) + { + if (x > 0) + PIX (-1, 1) = BIADAPT_GETPIX (SRC (-1, 1)); + else + PIX (-1, 1) = PIX (0, 1); + + if (x + 2 < w) + { + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + PIX (2, 1) = BIADAPT_GETPIX (SRC (2, 1)); + } + else if (x + 1 < w) + { + PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); + PIX (2, 1) = PIX (1, 1); + } + else + { + PIX (1, 1) = PIX (0, 1); + PIX (2, 1) = PIX (0, 1); + } + } + else + { + // last pixel in column + PIX (-1, 1) = PIX (-1, 0); + PIX (1, 1) = PIX (1, 0); + PIX (2, 1) = PIX (2, 0); + } + + if (y + 2 < h) + { + PIX (0, 2) = BIADAPT_GETPIX (SRC (0, 2)); + + if (x > 0) + PIX (-1, 2) = BIADAPT_GETPIX (SRC (-1, 2)); + else + PIX (-1, 2) = PIX (0, 2); + + if (x + 2 < w) + { + PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); + PIX (2, 2) = BIADAPT_GETPIX (SRC (2, 2)); + } + else if (x + 1 < w) + { + PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); + PIX (2, 2) = PIX (1, 2); + } + else + { + PIX (1, 2) = PIX (0, 2); + PIX (2, 2) = PIX (0, 2); + } + } + else + { + // last pixel in column + PIX (-1, 2) = PIX (-1, 1); + PIX (0, 2) = PIX (0, 1); + PIX (1, 2) = PIX (1, 1); + PIX (2, 2) = PIX (2, 1); + } + + if (y > 0) + { + PIX (0, -1) = BIADAPT_GETPIX (SRC (0, -1)); + + if (x > 0) + PIX (-1, -1) = BIADAPT_GETPIX (SRC (-1, -1)); + else + PIX (-1, -1) = PIX (0, -1); + + if (x + 2 < w) + { + PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); + PIX (2, -1) = BIADAPT_GETPIX (SRC (2, -1)); + } + else if (x + 1 < w) + { + PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); + PIX (2, -1) = PIX (1, -1); + } + else + { + PIX (1, -1) = PIX (0, -1); + PIX (2, -1) = PIX (0, -1); + } + } + else + { + PIX (-1, -1) = PIX (-1, 0); + PIX (0, -1) = PIX (0, 0); + PIX (1, -1) = PIX (1, 0); + PIX (2, -1) = PIX (2, 0); + } + + // check pixel below the current one + if (!(cmatch & 1)) + { + if (BIADAPT_CMPYUV (PIX (0, 0), PIX (0, 1)) <= BIADAPT_YUVLOW) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (0, 1)) + ); + cmatch |= 1; + } + // detect a 2:1 line going across the current pixel + else if ( (PIX (0, 0) == PIX (-1, 0) + && PIX (0, 0) == PIX (1, 1) + && PIX (0, 0) == PIX (2, 1) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || + + (PIX (0, 0) == PIX (1, 0) + && PIX (0, 0) == PIX (-1, 1) + && PIX (0, 0) == PIX (2, -1) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); + } + // detect a 2:1 line going across the pixel below current + else if ( (PIX (0, 1) == PIX (-1, 0) + && PIX (0, 1) == PIX (1, 1) + && PIX (0, 1) == PIX (2, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || + + (PIX (0, 1) == PIX (1, 0) + && PIX (0, 1) == PIX (-1, 1) + && PIX (0, 1) == PIX (2, 0) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) + { + BIADAPT_SETPIX (dst_p + dw, PIX (0, 1)); + } + else + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (0, 1)) + ); + } + + dst_p++; + + // check pixel to the right from the current one + if (!(cmatch & 2)) + { + if (BIADAPT_CMPYUV (PIX (0, 0), PIX (1, 0)) <= BIADAPT_YUVLOW) + { + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 0)) + ); + cmatch |= 2; + } + // detect a 1:2 line going across the current pixel + else if ( (PIX (0, 0) == PIX (1, -1) + && PIX (0, 0) == PIX (0, 1) + && PIX (0, 0) == PIX (-1, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || + + (PIX (0, 0) == PIX (0, -1) + && PIX (0, 0) == PIX (1, 1) + && PIX (0, 0) == PIX (1, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) + + { + BIADAPT_SETPIX (dst_p, PIX (0, 0)); + } + // detect a 1:2 line going across the pixel to the right + else if ( (PIX (1, 0) == PIX (1, -1) + && PIX (1, 0) == PIX (0, 1) + && PIX (1, 0) == PIX (0, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || + + (PIX (1, 0) == PIX (0, -1) + && PIX (1, 0) == PIX (1, 1) + && PIX (1, 0) == PIX (2, 2) && + + ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || + (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) + && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) + { + BIADAPT_SETPIX (dst_p, PIX (1, 0)); + } + else + BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 0)) + ); + } + + if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) + { + // diagonals are equal + int *coord; + int cl, cr; + Uint32 clr; + + // both pairs are equal, have to resolve the pixel + // race; we try detecting which color is + // the background by looking for a line or an edge + // examine 8 pixels surrounding the current quad + + cl = cr = 2; + for (coord = resolve_coord[0]; *coord < 100; coord += 2) + { + clr = PIX (coord[0], coord[1]); + + if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) + cl++; + else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) + cr++; + } + + // least count wins + if (cl > cr) + clr = PIX (1, 0); + else if (cr > cl) + clr = PIX (0, 0); + else + clr = Scale_BlendPixels (fmt, + PIX (0, 0), PIX (1, 0)); + + BIADAPT_SETPIX (dst_p + dw, clr); + continue; + } + + if (cmatch == 3 + || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) + && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 1), PIX (1, 0)) + ); + continue; + } + else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + continue; + } + + // check pixel to the bottom-right + if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) + && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) + { + if (Scale_GetPixY (fmt, PIX (0, 0)) + > Scale_GetPixY (fmt, PIX (1, 0))) + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + } + else + { + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (1, 0), PIX (0, 1)) + ); + } + } + else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) + { + // main diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (0, 0), PIX (1, 1)) + ); + } + else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) + { + // 2nd diagonal is same color + // use its value + BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( + fmt, PIX (1, 0), PIX (0, 1)) + ); + } + else + { + // blend all 4 + BIADAPT_SETPIX (dst_p + dw, + ((((PIX (0, 0) & fmt->Rmask) + + (PIX (0, 1) & fmt->Rmask) + + (PIX (1, 0) & fmt->Rmask) + + (PIX (1, 1) & fmt->Rmask) + ) >> 2) & fmt->Rmask) | + ((((PIX (0, 0) & fmt->Gmask) + + (PIX (0, 1) & fmt->Gmask) + + (PIX (1, 0) & fmt->Gmask) + + (PIX (1, 1) & fmt->Gmask) + ) >> 2) & fmt->Gmask) | + ((((PIX (0, 0) & fmt->Bmask) + + (PIX (0, 1) & fmt->Bmask) + + (PIX (1, 0) & fmt->Bmask) + + (PIX (1, 1) & fmt->Bmask) + ) >> 2) & fmt->Bmask)); + } + } + } + break; + } + #undef BIADAPT_GETPIX + #undef BIADAPT_SETPIX + #undef BIADAPT_BUF + } + + #undef BIADAPT_CMPRGB + #undef BIADAPT_CMPRGB_HIGH + #undef BIADAPT_CMPYUV + #undef BIADAPT_CMPYUV_LOW + #undef BIADAPT_CMPYUV_MED + #undef BIADAPT_CMPYUV_HIGH + + #undef PIX + #undef SRC +} + + +// nearest neighbor scaling to 2x +void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) +{ + int x, y; + const int w = src->w, dw = dst->w; + const int x0 = r->x, y0 = r->y, rw = r->w, rh = r->h; + const int ds = w-rw, dd = (dw-rw) * 2; + + switch (dst->format->BytesPerPixel) + { + case 2: + { + Uint16 *src_p = (Uint16 *)src->pixels, *dst_p = (Uint16 *)dst->pixels; + Uint16 pixval_16; + src_p += w*y0 + x0; + dst_p += (dw*y0 + x0) * 2; + for (y = 0; y < rh; ++y) + { + for (x = 0; x < rw; ++x) + { + pixval_16 = *src_p++; + dst_p[dw] = pixval_16; + *dst_p++ = pixval_16; + dst_p[dw] = pixval_16; + *dst_p++ = pixval_16; + } + dst_p += dd; + src_p += ds; + } + break; + } + case 3: + { + PIXEL_24BIT *src_p = (PIXEL_24BIT *)src->pixels; + PIXEL_24BIT *dst_p = (PIXEL_24BIT *)dst->pixels; + PIXEL_24BIT *src_p2; + const int dd = dw - rw * 2; // override + Uint32 pixval_32; + src_p += w*y0 + x0; + dst_p += (dw*y0 + x0) * 2; + for (y = 0; y < rh; ++y) + { + src_p2 = src_p; + for (x = 0; x < rw; ++x, ++src_p) + { + pixval_32 = GET_PIX_24BIT (src_p); + SET_PIX_24BIT (dst_p, pixval_32); + dst_p++; + SET_PIX_24BIT (dst_p, pixval_32); + dst_p++; + } + dst_p += dd; + src_p = src_p2; + for (x = 0; x < rw; ++x, ++src_p) + { + pixval_32 = GET_PIX_24BIT (src_p); + SET_PIX_24BIT (dst_p, pixval_32); + dst_p++; + SET_PIX_24BIT (dst_p, pixval_32); + dst_p++; + } + dst_p += dd; + src_p += ds; + } + break; + } + case 4: + { + Uint32 *src_p = (Uint32 *)src->pixels, *dst_p = (Uint32 *)dst->pixels; + Uint32 pixval_32; + src_p += w*y0 + x0; + dst_p += (dw*y0 + x0) * 2; + for (y = 0; y < rh; ++y) + { + for (x = 0; x < rw; ++x) + { + pixval_32 = *src_p++; + dst_p[dw] = pixval_32; + *dst_p++ = pixval_32; + dst_p[dw] = pixval_32; + *dst_p++ = pixval_32; + } + dst_p += dd; + src_p += ds; + } + break; + } + } +} + +// bilinear scaling to 2x +void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) +{ + int x, y, i = 0, j, fa, fb, fc, fd; + const int w = dst->w, h = dst->h; + SDL_PixelFormat *fmt = dst->format; + + switch (dst->format->BytesPerPixel) + { + case 2: + { + Uint16 *src_p = (Uint16 *) src->pixels, *src_p2; + Uint16 *dst_p = (Uint16 *) dst->pixels; + Uint32 p[4]; + + for (y = 0; y < h; ++y) + { + src_p2 = src_p; + j = i; + + p[0] = src_p[0]; + if (y < h - 2) + p[2] = src_p[src->w]; + else + p[2] = 0; + + for (x = 0; x < w; ++x) + { + if (j == i) + { + if (y < h - 2) + { + if (x < w - 2) + { + p[1] = src_p[1]; + p[3] = src_p[src->w + 1]; + } + else + { + p[1] = 0; + p[3] = 0; + } + } + else + { + if (x < w - 2) + p[1] = src_p[1]; + else + p[1] = 0; + p[3] = 0; + } + } + + fa = bilinear_table[j][0]; + fb = bilinear_table[j][1]; + fc = bilinear_table[j][2]; + fd = bilinear_table[j][3]; + + *dst_p++ = + (((((p[0] & fmt->Rmask) * fa) + + ((p[1] & fmt->Rmask) * fb) + + ((p[2] & fmt->Rmask) * fc) + + ((p[3] & fmt->Rmask) * fd)) >> 4) & fmt->Rmask) | + (((((p[0] & fmt->Gmask) * fa) + + ((p[1] & fmt->Gmask) * fb) + + ((p[2] & fmt->Gmask) * fc) + + ((p[3] & fmt->Gmask) * fd)) >> 4) & fmt->Gmask) | + (((((p[0] & fmt->Bmask) * fa) + + ((p[1] & fmt->Bmask) * fb) + + ((p[2] & fmt->Bmask) * fc) + + ((p[3] & fmt->Bmask) * fd)) >> 4) & fmt->Bmask); + + if (j & 2) + { + j = i; + src_p++; + p[0] = p[1]; + p[2] = p[3]; + } + else + { + j = i | 2; + } + } + + if (!i) + src_p = src_p2; + i = !i; + } + + break; + } + case 3: + { + // 24bpp mode bilinear scaling isn't implemented currently + // it would probably be too slow to be useful anyway + Scale_Nearest (src, dst, r); + break; + } + case 4: + { + Uint32 *src_p = (Uint32 *) src->pixels, *src_p2; + Uint32 *dst_p = (Uint32 *) dst->pixels; + Uint32 p[4]; + + for (y = 0; y < h; ++y) + { + src_p2 = src_p; + j = i; + + p[0] = src_p[0]; + if (y < h - 2) + p[2] = src_p[src->w]; + else + p[2] = 0; + + for (x = 0; x < w; ++x) + { + if (j == i) + { + if (y < h - 2) + { + if (x < w - 2) + { + p[1] = src_p[1]; + p[3] = src_p[src->w + 1]; + } + else + { + p[1] = 0; + p[3] = 0; + } + } + else + { + if (x < w - 2) + p[1] = src_p[1]; + else + p[1] = 0; + p[3] = 0; + } + } + + fa = bilinear_table[j][0]; + fb = bilinear_table[j][1]; + fc = bilinear_table[j][2]; + fd = bilinear_table[j][3]; + + *dst_p++ = + (((((p[0] & fmt->Rmask) * fa) + + ((p[1] & fmt->Rmask) * fb) + + ((p[2] & fmt->Rmask) * fc) + + ((p[3] & fmt->Rmask) * fd)) >> 4) & fmt->Rmask) | + (((((p[0] & fmt->Gmask) * fa) + + ((p[1] & fmt->Gmask) * fb) + + ((p[2] & fmt->Gmask) * fc) + + ((p[3] & fmt->Gmask) * fd)) >> 4) & fmt->Gmask) | + (((((p[0] & fmt->Bmask) * fa) + + ((p[1] & fmt->Bmask) * fb) + + ((p[2] & fmt->Bmask) * fc) + + ((p[3] & fmt->Bmask) * fd)) >> 4) & fmt->Bmask); + + if (j & 2) + { + j = i; + src_p++; + p[0] = p[1]; + p[2] = p[3]; + } + else + { + j = i | 2; + } + } + + if (!i) + src_p = src_p2; + i = !i; + } + + break; + } + } +} + +#endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/2xscalers.h b/sc2/src/sc2code/libs/graphics/sdl/2xscalers.h new file mode 100644 index 000000000..903a75bd1 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/sdl/2xscalers.h @@ -0,0 +1,27 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _2XSCALERS_H_ +#define _2XSCALERS_H_ + +void Scale_PrepYUV (void); +void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); +void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); +void Scale_BiAdaptFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); +void Scale_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); + +#endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/Makeinfo b/sc2/src/sc2code/libs/graphics/sdl/Makeinfo index 9814ebd90..30d7dcb4d 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/Makeinfo +++ b/sc2/src/sc2code/libs/graphics/sdl/Makeinfo @@ -1,3 +1,3 @@ uqm_CFILES="3do_blt.c 3do_funcs.c 3do_getbody.c dcqueue.c opengl.c primitives.c pure.c rndzoom.c rotozoom.c sdl_common.c oscilloscope.c - canvas.c bbox.c" + canvas.c bbox.c 2xscalers.c" diff --git a/sc2/src/sc2code/libs/graphics/sdl/opengl.c b/sc2/src/sc2code/libs/graphics/sdl/opengl.c index cbfda8657..edf9fefbc 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/opengl.c +++ b/sc2/src/sc2code/libs/graphics/sdl/opengl.c @@ -19,8 +19,12 @@ #if defined (GFXMODULE_SDL) && defined (HAVE_OPENGL) #include "libs/graphics/sdl/opengl.h" +#include "bbox.h" +#include "2xscalers.h" static SDL_Surface *format_conv_surf; +static SDL_Surface *scaled_display; +static SDL_Surface *scaled_transition; static int ScreenFilterMode; static unsigned int DisplayTexture; @@ -40,18 +44,17 @@ static BOOLEAN upload_transitiontexture = FALSE; #define A_MASK 0xff000000 #endif + static SDL_Surface * Create_Screen () { SDL_Surface *result = SDL_CreateRGBSurface(SDL_SWSURFACE, ScreenWidth, ScreenHeight, 32, R_MASK, G_MASK, B_MASK, 0x00000000); - if (result == NULL) { fprintf (stderr, "Couldn't create screen buffer: %s\n", SDL_GetError()); exit (-1); } - return result; } @@ -59,13 +62,11 @@ int TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) { char VideoName[256]; - int videomode_flags; - int i; + int i, videomode_flags, texture_width, texture_height; GraphicsDriver = driver; fprintf (stderr, "Initializing SDL (OpenGL).\n"); - if ((SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) == -1)) { fprintf (stderr, "Could not initialize SDL: %s.\n", SDL_GetError()); @@ -74,7 +75,6 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) SDL_VideoDriverName (VideoName, sizeof (VideoName)); fprintf (stderr, "SDL driver used: %s\n", VideoName); - fprintf (stderr, "SDL initialized.\n"); fprintf (stderr, "Initializing Screen.\n"); @@ -84,10 +84,6 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) ScreenHeightActual = height; switch (bpp) { - case 8: - fprintf (stderr, "bpp of 8 not supported under OpenGL\n"); - exit(-1); - case 15: SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5); @@ -111,6 +107,8 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); break; + default: + break; } SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, bpp); @@ -122,7 +120,6 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) SDL_Video = SDL_SetVideoMode (ScreenWidthActual, ScreenHeightActual, bpp, videomode_flags); - if (SDL_Video == NULL) { fprintf (stderr, "Couldn't set OpenGL %ix%ix%i video mode: %s\n", @@ -150,14 +147,44 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) format_conv_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, 32, R_MASK, G_MASK, B_MASK, A_MASK); - if (format_conv_surf == NULL) { fprintf (stderr, "Couldn't create format_conv_surf: %s\n", SDL_GetError()); exit(-1); } - if (GfxFlags & TFB_GFXFLAGS_SCALE_BILINEAR || GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT || + if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT || + GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) + { + scaled_display = SDL_CreateRGBSurface(SDL_SWSURFACE, ScreenWidth * 2, + ScreenHeight * 2, 32, R_MASK, G_MASK, B_MASK, 0x00000000); + if (scaled_display == NULL) + { + fprintf (stderr, "Couldn't create scaled_display: %s\n", SDL_GetError()); + exit(-1); + } + scaled_transition = SDL_CreateRGBSurface(SDL_SWSURFACE, ScreenWidth * 2, + ScreenHeight * 2, 32, R_MASK, G_MASK, B_MASK, 0x00000000); + if (scaled_transition == NULL) + { + fprintf (stderr, "Couldn't create scaled_transition: %s\n", SDL_GetError()); + exit(-1); + } + + texture_width = 1024; + texture_height = 512; + } + else + { + texture_width = 512; + texture_height = 256; + } + + // pre-compute the RGB->YUV transformations + Scale_PrepYUV(); + + if (GfxFlags & TFB_GFXFLAGS_SCALE_BILINEAR || + GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT || GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) ScreenFilterMode = GL_LINEAR; else @@ -181,21 +208,21 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp) glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glGenTextures (1, &TransitionTexture); glBindTexture (GL_TEXTURE_2D, TransitionTexture); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); return 0; } void TFB_GL_UploadTransitionScreen (void) { - upload_transitiontexture = TRUE; + upload_transitiontexture = TRUE; } void @@ -207,7 +234,6 @@ TFB_GL_ScanLines (void) glEnable (GL_BLEND); glBlendFunc (GL_DST_COLOR, GL_ZERO); glColor3f (0.85f, 0.85f, 0.85f); - for (y = 0; y < ScreenHeightActual; y += 2) { glBegin (GL_LINES); @@ -218,7 +244,6 @@ TFB_GL_ScanLines (void) glBlendFunc (GL_DST_COLOR, GL_ONE); glColor3f (0.2f, 0.2f, 0.2f); - for (y = 1; y < ScreenHeightActual; y += 2) { glBegin (GL_LINES); @@ -232,19 +257,14 @@ void TFB_GL_DrawQuad (void) { glBegin (GL_TRIANGLE_FAN); - glTexCoord2f (0, 0); glVertex2i (0, 0); - glTexCoord2f (ScreenWidth / 512.0f, 0); - glVertex2i (ScreenWidthActual, 0); - + glVertex2i (ScreenWidthActual, 0); glTexCoord2f (ScreenWidth / 512.0f, ScreenHeight / 256.0f); glVertex2i (ScreenWidthActual, ScreenHeightActual); - glTexCoord2f (0, ScreenHeight / 256.0f); glVertex2i (0, ScreenHeightActual); - glEnd (); } @@ -257,7 +277,6 @@ TFB_GL_SwapBuffers (void) glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0,ScreenWidthActual,ScreenHeightActual, 0, -1, 1); - glMatrixMode (GL_MODELVIEW); glLoadIdentity (); @@ -265,15 +284,36 @@ TFB_GL_SwapBuffers (void) glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode); - glEnable (GL_TEXTURE_2D); glDisable (GL_BLEND); glColor4f (1, 1, 1, 1); + + if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT || + GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) + { + SDL_Rect updated; + updated.x = TFB_BBox.region.corner.x; + updated.y = TFB_BBox.region.corner.y; + updated.w = TFB_BBox.region.extent.width; + updated.h = TFB_BBox.region.extent.height; - SDL_LockSurface (SDL_Screen); - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth, ScreenHeight, - GL_RGBA, GL_UNSIGNED_BYTE, SDL_Screen->pixels); - SDL_UnlockSurface (SDL_Screen); + if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT) + Scale_BiAdaptFilter (SDL_Screen, scaled_display, &updated); + else if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) + Scale_BiAdaptAdvFilter (SDL_Screen, scaled_display, &updated); + + SDL_LockSurface (scaled_display); + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth * 2, ScreenHeight * 2, + GL_RGBA, GL_UNSIGNED_BYTE, scaled_display->pixels); + SDL_UnlockSurface (scaled_display); + } + else + { + SDL_LockSurface (SDL_Screen); + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth, ScreenHeight, + GL_RGBA, GL_UNSIGNED_BYTE, SDL_Screen->pixels); + SDL_UnlockSurface (SDL_Screen); + } TFB_GL_DrawQuad (); @@ -287,10 +327,30 @@ TFB_GL_SwapBuffers (void) if (upload_transitiontexture) { - SDL_LockSurface (TransitionScreen); - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth, ScreenHeight, - GL_RGBA, GL_UNSIGNED_BYTE, TransitionScreen->pixels); - SDL_UnlockSurface (TransitionScreen); + if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT || + GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) + { + SDL_Rect updated; + updated.x = updated.y = 0; + updated.w = ScreenWidth; + updated.h = ScreenHeight; + if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT) + Scale_BiAdaptFilter (TransitionScreen, scaled_transition, &updated); + else if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) + Scale_BiAdaptAdvFilter (TransitionScreen, scaled_transition, &updated); + + SDL_LockSurface (scaled_transition); + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth * 2, ScreenHeight * 2, + GL_RGBA, GL_UNSIGNED_BYTE, scaled_transition->pixels); + SDL_UnlockSurface (scaled_transition); + } + else + { + SDL_LockSurface (TransitionScreen); + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth, ScreenHeight, + GL_RGBA, GL_UNSIGNED_BYTE, TransitionScreen->pixels); + SDL_UnlockSurface (TransitionScreen); + } upload_transitiontexture = FALSE; } @@ -337,7 +397,7 @@ TFB_GL_SwapBuffers (void) TFB_GL_DrawQuad (); } - if (scanlines) + if (GfxFlags & TFB_GFXFLAGS_SCANLINES) TFB_GL_ScanLines (); SDL_GL_SwapBuffers (); diff --git a/sc2/src/sc2code/libs/graphics/sdl/pure.c b/sc2/src/sc2code/libs/graphics/sdl/pure.c index 1d491c2f4..1e3b5ac80 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/pure.c +++ b/sc2/src/sc2code/libs/graphics/sdl/pure.c @@ -18,114 +18,14 @@ #ifdef GFXMODULE_SDL #include "pure.h" -#include "primitives.h" #include "bbox.h" +#include "2xscalers.h" static SDL_Surface *fade_black; static SDL_Surface *fade_white; static SDL_Surface *fade_temp; static int gfx_flags; -static const Uint32 bilinear_table[4][4] = -{ - { 9, 3, 3, 1 }, - { 3, 1, 9, 3 }, - { 3, 9, 1, 3 }, - { 1, 3, 3, 9 } -}; - -typedef union -{ - struct - { - Uint8 c1, c2, c3; - } bchan; - Uint8 channels[3]; -} PIXEL_24BIT; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN -// big endian cpu -// We avoid potential pagefaults based on the assumption -// that all buffers are allocated on *at least* 32bit boundary -// So if the pointer (p) is 32bit-aligned, we can read at -// least 32 bits at once; or if it is not aligned then we -// are not at the beginning of the buffer and can read 1 byte -// before (p) -// -// WARNING!! Do not call these macros like so: -// SET_PIX_24BIT (dst_p++, pixel) -// The pre-increment or post-increment will be done -// several times -// -# define GET_PIX_24BIT(p) \ - ( ((Uint32)(p)) & 3 ? \ - (*(Uint32 *)((Uint8 *)(p) - 1) & 0x00ffffff) : \ - (*(Uint32 *)(p) >> 8) \ - ) - -# define SET_PIX_24BIT(p, c) \ - ( ((Uint32)(p)) & 3 ? \ - ( *(Uint32 *)((Uint8 *)(p) - 1) = \ - (*(Uint32 *)((Uint8 *)(p) - 1) & 0xff000000) | \ - ((c) & 0x00ffffff) \ - ) : \ - ( *(Uint32 *)(p) = \ - (*(Uint32 *)(p) & 0x000000ff) | \ - ((c) << 8) \ - ) \ - ) -#else -// little endian cpu -// Same page-safety assumption applies as for big-endian -// -# define GET_PIX_24BIT(p) \ - ( ((Uint32)(p)) & 3 ? \ - (*(Uint32 *)((Uint8 *)(p) - 1) >> 8) : \ - (*(Uint32 *)(p) & 0x00ffffff) \ - ) - -# define SET_PIX_24BIT(p, c) \ - ( ((Uint32)(p)) & 3 ? \ - ( *(Uint32 *)((Uint8 *)(p) - 1) = \ - (*(Uint32 *)((Uint8 *)(p) - 1) & 0x000000ff) | \ - ((c) << 8) \ - ) : \ - ( *(Uint32 *)(p) = \ - (*(Uint32 *)(p) & 0xff000000) | \ - ((c) & 0x00ffffff) \ - ) \ - ) -#endif - -// RGB -> YUV transformation -// the RGB vector is multiplied by the transformation matrix -// to get the YUV vector -static const double YUV_matrix[3][3] = -{ - /* Y U V */ - /* R */ {0.2989, -0.1687, 0.5000}, - /* G */ {0.5867, -0.3312, -0.4183}, - /* B */ {0.1144, 0.5000, -0.0816} -}; - -typedef enum -{ - YUV_XFORM_R = 0, - YUV_XFORM_G = 1, - YUV_XFORM_B = 2, - YUV_XFORM_Y = 0, - YUV_XFORM_U = 1, - YUV_XFORM_V = 2 -} RGB_YUV_INDEX; - -// pre-computed transformations for 8 bits per channel -static int RGB_to_YUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 256]; -// double to int rounding error correction -#define YUV_ERR_CORR 0.4999 - -static void Scale_PrepYUV(); - - static SDL_Surface * Create_Screen (SDL_Surface *template) { @@ -246,2502 +146,6 @@ TFB_Pure_InitGraphics (int driver, int flags, int width, int height, int bpp) return 0; } -// pre-compute the RGB->YUV transformations -static void -Scale_PrepYUV() -{ - int i1; - - for (i1 = 0; i1 < 3; i1++) // enum R,G,B - { - int i2; - for (i2 = 0; i2 < 3; i2++) // enum Y,U,V - { - int i3; - for (i3 = 0; i3 < 256; i3++) // enum possible channel vals - RGB_to_YUV[i1][i2][i3] = (int) - (YUV_matrix[i1][i2] * i3 + YUV_ERR_CORR); - } - } -} - -// expands the given rectangle in all directions by 'expansion' -// guarded by 'limits' -void -Scale_ExpandRect (SDL_Rect* rect, int expansion, SDL_Rect* limits) -{ - if (rect->x - expansion >= limits->x) - { - rect->w += expansion; - rect->x -= expansion; - } - else - { - rect->w += rect->x - limits->x; - rect->x = limits->x; - } - - if (rect->y - expansion >= limits->y) - { - rect->h += expansion; - rect->y -= expansion; - } - else - { - rect->h += rect->y - limits->y; - rect->y = limits->y; - } - - if (rect->x + rect->w + expansion <= limits->w) - rect->w += expansion; - else - rect->w = limits->w - rect->x; - - if (rect->y + rect->h + expansion <= limits->h) - rect->h += expansion; - else - rect->h = limits->h - rect->y; -} - -// blends two pixels with ratio 50% - 50% -__inline__ Uint32 -Scale_BlendPixels (SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) -{ - return ((((pix1 & fmt->Rmask) + - (pix2 & fmt->Rmask) - ) >> 1) & fmt->Rmask) | - ((((pix1 & fmt->Gmask) + - (pix2 & fmt->Gmask) - ) >> 1) & fmt->Gmask) | - ((((pix1 & fmt->Bmask) + - (pix2 & fmt->Bmask) - ) >> 1) & fmt->Bmask); -} - -// compare pixels by their RGB -__inline__ int -Scale_GetRGBDelta (SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) -{ - Uint32 c; - int delta; - - c = (((pix1 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss) - - (((pix2 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss); - delta = c * c; - - c = (((pix1 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss) - - (((pix2 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss); - delta += c * c; - - c = (((pix1 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss) - - (((pix2 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss); - delta += c * c; - - return delta; -} - -// compare pixels by their YUVs -__inline__ int -Scale_GetYUVDelta (SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) -{ - Uint32 r1, g1, b1, r2, g2, b2; - int compd, delta; - - r1 = ((pix1 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss; - g1 = ((pix1 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss; - b1 = ((pix1 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss; - r2 = ((pix2 & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss; - g2 = ((pix2 & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss; - b2 = ((pix2 & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss; - - // compare Ys - compd = RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r1] - + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g1] - + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b1] - - RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r2] - - RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g2] - - RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b2]; - if (compd < 0) - compd = -compd; - // Y is 2-4 times more important than U or V - delta = compd << 1; - - // compare Us - compd = RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_U][r1] - + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_U][g1] - + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_U][b1] - - RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_U][r2] - - RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_U][g2] - - RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_U][b2]; - if (compd < 0) - compd = -compd; - delta += compd; - - // compare Vs - compd = RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_V][r1] - + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_V][g1] - + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_V][b1] - - RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_V][r2] - - RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_V][g2] - - RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_V][b2]; - if (compd < 0) - compd = -compd; - delta += compd; - - return delta; -} - -// retrieve the Y (intensity) component of pixel's YUV -__inline__ int -Scale_GetPixY (SDL_PixelFormat* fmt, Uint32 pix) -{ - Uint32 r, g, b; - - r = ((pix & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss; - g = ((pix & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss; - b = ((pix & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss; - - // compare Ys - return RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r] - + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g] - + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b]; -} - -// biadapt scaling to 2x -static void -Scale_BiAdaptFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) -{ - int x, y; - const int w = src->w, h = src->h, dw = dst->w; - int xend, yend; - int dsrc, ddst; - SDL_Rect region = *r; - SDL_Rect limits; - SDL_PixelFormat *fmt = dst->format; - - // expand updated region if necessary - // pixels neighbooring the updated region may - // change as a result of updates - limits.x = 0; - limits.y = 0; - limits.w = src->w; - limits.h = src->h; - Scale_ExpandRect (®ion, 2, &limits); - - xend = region.x + region.w; - yend = region.y + region.h; - dsrc = w - region.w; - ddst = (dw - region.w) * 2; - - switch (fmt->BytesPerPixel) - { - case 2: // 16bpp scaling - #define BIADAPT_GETPIX(p) ( *(Uint16 *)(p) ) - #define BIADAPT_SETPIX(p, c) ( *(Uint16 *)(p) = (c) ) - #define BIADAPT_BUF Uint16 - { - BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; - BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; - Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; - - // move ptrs to the first updated pixel - src_p += w * region.y + region.x; - dst_p += (dw * region.y + region.x) * 2; - - for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) - { - for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) - { - pixval_tl = BIADAPT_GETPIX (src_p); - - BIADAPT_SETPIX (dst_p, pixval_tl); - - if (y + 1 < h) - { - // check pixel below the current one - pixval_bl = BIADAPT_GETPIX (src_p + w); - - if (pixval_tl == pixval_bl) - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - else - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, pixval_tl, pixval_bl) - ); - } - else - { - // last pixel in column - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - } - dst_p++; - - - if (x + 1 >= w) - { - // last pixel in row - propagate - BIADAPT_SETPIX (dst_p, pixval_tl); - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // check pixel to the right from the current one - pixval_tr = BIADAPT_GETPIX (src_p + 1); - - if (pixval_tl == pixval_tr) - BIADAPT_SETPIX (dst_p, pixval_tr); - else - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, pixval_tl, pixval_tr) - ); - - if (y + 1 >= h) - { - // last pixel in column - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // check pixel to the bottom-right - pixval_br = BIADAPT_GETPIX (src_p + 1 + w); - - if (pixval_tl == pixval_br && pixval_tr == pixval_bl) - { - int cl, cr; - Uint32 clr; - - if (pixval_tl == pixval_tr) - { - // all 4 are equal - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // both pairs are equal, have to resolve the pixel - // race; we try detecting which color is - // the background by looking for a line or an edge - // examine 8 pixels surrounding the current quad - - cl = cr = 1; - - if (x > 0) - { - clr = BIADAPT_GETPIX (src_p - 1); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p - 1 + w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (y > 0) - { - clr = BIADAPT_GETPIX (src_p - w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 1 - w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (x + 2 < w) - { - clr = BIADAPT_GETPIX (src_p + 2); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 2 + w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (y + 2 < h) - { - clr = BIADAPT_GETPIX (src_p + 2 * w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 1 + 2 * w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - // least count wins - if (cl > cr) - BIADAPT_SETPIX (dst_p + dw, pixval_tr); - else if (cr > cl) - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - else - BIADAPT_SETPIX (dst_p + dw, - Scale_BlendPixels (fmt, pixval_tl, - pixval_tr)); - } - else if (pixval_tl == pixval_br) - { - // main diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - } - else if (pixval_tr == pixval_bl) - { - // 2nd diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, pixval_tr); - } - else - { - // blend all 4 - BIADAPT_SETPIX (dst_p + dw, - ((((pixval_tl & fmt->Rmask) + - (pixval_bl & fmt->Rmask) + - (pixval_tr & fmt->Rmask) + - (pixval_br & fmt->Rmask) - ) >> 2) & fmt->Rmask) | - ((((pixval_tl & fmt->Gmask) + - (pixval_bl & fmt->Gmask) + - (pixval_tr & fmt->Gmask) + - (pixval_br & fmt->Gmask) - ) >> 2) & fmt->Gmask) | - ((((pixval_tl & fmt->Bmask) + - (pixval_bl & fmt->Bmask) + - (pixval_tr & fmt->Bmask) + - (pixval_br & fmt->Bmask) - ) >> 2) & fmt->Bmask)); - } - } - } - break; - } - #undef BIADAPT_GETPIX - #undef BIADAPT_SETPIX - #undef BIADAPT_BUF - - case 3: // 24bpp scaling - #define BIADAPT_GETPIX(p) GET_PIX_24BIT(p) - #define BIADAPT_SETPIX(p, c) SET_PIX_24BIT(p, c) - #define BIADAPT_BUF PIXEL_24BIT - { - BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; - BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; - Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; - - // move ptrs to the first updated pixel - src_p += w * region.y + region.x; - dst_p += (dw * region.y + region.x) * 2; - - for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) - { - for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) - { - pixval_tl = BIADAPT_GETPIX (src_p); - - BIADAPT_SETPIX (dst_p, pixval_tl); - - if (y + 1 < h) - { - // check pixel below the current one - pixval_bl = BIADAPT_GETPIX (src_p + w); - - if (pixval_tl == pixval_bl) - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - else - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, pixval_tl, pixval_bl) - ); - } - else - { - // last pixel in column - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - } - dst_p++; - - - if (x + 1 >= w) - { - // last pixel in row - propagate - BIADAPT_SETPIX (dst_p, pixval_tl); - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // check pixel to the right from the current one - pixval_tr = BIADAPT_GETPIX (src_p + 1); - - if (pixval_tl == pixval_tr) - BIADAPT_SETPIX (dst_p, pixval_tr); - else - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, pixval_tl, pixval_tr) - ); - - if (y + 1 >= h) - { - // last pixel in column - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // check pixel to the bottom-right - pixval_br = BIADAPT_GETPIX (src_p + 1 + w); - - if (pixval_tl == pixval_br && pixval_tr == pixval_bl) - { - int cl, cr; - Uint32 clr; - - if (pixval_tl == pixval_tr) - { - // all 4 are equal - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // both pairs are equal, have to resolve the pixel - // race; we try detecting which color is - // the background by looking for a line or an edge - // examine 8 pixels surrounding the current quad - - cl = cr = 1; - - if (x > 0) - { - clr = BIADAPT_GETPIX (src_p - 1); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p - 1 + w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (y > 0) - { - clr = BIADAPT_GETPIX (src_p - w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 1 - w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (x + 2 < w) - { - clr = BIADAPT_GETPIX (src_p + 2); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 2 + w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (y + 2 < h) - { - clr = BIADAPT_GETPIX (src_p + 2 * w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 1 + 2 * w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - // least count wins - if (cl > cr) - BIADAPT_SETPIX (dst_p + dw, pixval_tr); - else if (cr > cl) - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - else - BIADAPT_SETPIX (dst_p + dw, - Scale_BlendPixels (fmt, pixval_tl, - pixval_tr)); - } - else if (pixval_tl == pixval_br) - { - // main diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - } - else if (pixval_tr == pixval_bl) - { - // 2nd diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, pixval_tr); - } - else - { - // blend all 4 - BIADAPT_SETPIX (dst_p + dw, - ((((pixval_tl & fmt->Rmask) + - (pixval_bl & fmt->Rmask) + - (pixval_tr & fmt->Rmask) + - (pixval_br & fmt->Rmask) - ) >> 2) & fmt->Rmask) | - ((((pixval_tl & fmt->Gmask) + - (pixval_bl & fmt->Gmask) + - (pixval_tr & fmt->Gmask) + - (pixval_br & fmt->Gmask) - ) >> 2) & fmt->Gmask) | - ((((pixval_tl & fmt->Bmask) + - (pixval_bl & fmt->Bmask) + - (pixval_tr & fmt->Bmask) + - (pixval_br & fmt->Bmask) - ) >> 2) & fmt->Bmask)); - } - } - } - break; - } - #undef BIADAPT_GETPIX - #undef BIADAPT_SETPIX - #undef BIADAPT_BUF - - case 4: // 32bpp scaling - #define BIADAPT_GETPIX(p) ( *(Uint32 *)(p) ) - #define BIADAPT_SETPIX(p, c) ( *(Uint32 *)(p) = (c) ) - #define BIADAPT_BUF Uint32 - { - BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; - BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; - Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; - - // move ptrs to the first updated pixel - src_p += w * region.y + region.x; - dst_p += (dw * region.y + region.x) * 2; - - for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) - { - for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) - { - pixval_tl = BIADAPT_GETPIX (src_p); - - BIADAPT_SETPIX (dst_p, pixval_tl); - - if (y + 1 < h) - { - // check pixel below the current one - pixval_bl = BIADAPT_GETPIX (src_p + w); - - if (pixval_tl == pixval_bl) - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - else - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, pixval_tl, pixval_bl) - ); - } - else - { - // last pixel in column - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - } - dst_p++; - - - if (x + 1 >= w) - { - // last pixel in row - propagate - BIADAPT_SETPIX (dst_p, pixval_tl); - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // check pixel to the right from the current one - pixval_tr = BIADAPT_GETPIX (src_p + 1); - - if (pixval_tl == pixval_tr) - BIADAPT_SETPIX (dst_p, pixval_tr); - else - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, pixval_tl, pixval_tr) - ); - - if (y + 1 >= h) - { - // last pixel in column - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // check pixel to the bottom-right - pixval_br = BIADAPT_GETPIX (src_p + 1 + w); - - if (pixval_tl == pixval_br && pixval_tr == pixval_bl) - { - int cl, cr; - Uint32 clr; - - if (pixval_tl == pixval_tr) - { - // all 4 are equal - propagate - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - continue; - } - - // both pairs are equal, have to resolve the pixel - // race; we try detecting which color is - // the background by looking for a line or an edge - // examine 8 pixels surrounding the current quad - - cl = cr = 1; - - if (x > 0) - { - clr = BIADAPT_GETPIX (src_p - 1); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p - 1 + w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (y > 0) - { - clr = BIADAPT_GETPIX (src_p - w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 1 - w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (x + 2 < w) - { - clr = BIADAPT_GETPIX (src_p + 2); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 2 + w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - if (y + 2 < h) - { - clr = BIADAPT_GETPIX (src_p + 2 * w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - - clr = BIADAPT_GETPIX (src_p + 1 + 2 * w); - if (clr == pixval_tl) - cl++; - else if (clr == pixval_tr) - cr++; - } - - // least count wins - if (cl > cr) - BIADAPT_SETPIX (dst_p + dw, pixval_tr); - else if (cr > cl) - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - else - BIADAPT_SETPIX (dst_p + dw, - Scale_BlendPixels (fmt, pixval_tl, - pixval_tr)); - } - else if (pixval_tl == pixval_br) - { - // main diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, pixval_tl); - } - else if (pixval_tr == pixval_bl) - { - // 2nd diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, pixval_tr); - } - else - { - // blend all 4 - BIADAPT_SETPIX (dst_p + dw, - ((((pixval_tl & fmt->Rmask) + - (pixval_bl & fmt->Rmask) + - (pixval_tr & fmt->Rmask) + - (pixval_br & fmt->Rmask) - ) >> 2) & fmt->Rmask) | - ((((pixval_tl & fmt->Gmask) + - (pixval_bl & fmt->Gmask) + - (pixval_tr & fmt->Gmask) + - (pixval_br & fmt->Gmask) - ) >> 2) & fmt->Gmask) | - ((((pixval_tl & fmt->Bmask) + - (pixval_bl & fmt->Bmask) + - (pixval_tr & fmt->Bmask) + - (pixval_br & fmt->Bmask) - ) >> 2) & fmt->Bmask)); - } - } - } - break; - } - #undef BIADAPT_GETPIX - #undef BIADAPT_SETPIX - #undef BIADAPT_BUF - #undef BIADAPT_CLR - - } -} - -// advanced biadapt scaling to 2x -static void -Scale_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) -{ - int x, y; - const int w = src->w, h = src->h, dw = dst->w; - int xend, yend; - int dsrc, ddst; - SDL_Rect region = *r; - SDL_Rect limits; - SDL_PixelFormat *fmt = dst->format; - // for clarity purposes, the 'pixels' array here is transposed - Uint32 pixels[4][4]; - static int resolve_coord[][2] = - { - {0, -1}, {1, -1}, { 2, 0}, { 2, 1}, - {1, 2}, {0, 2}, {-1, 1}, {-1, 0}, - {100, 100} // term - }; - - // these macros are for clarity; they make the current pixel (0,0) - // and allow to access pixels in all directions - #define PIX(x, y) (pixels[1 + (x)][1 + (y)]) - #define SRC(x, y) (src_p + (x) + ((y) * w)) - // commonly used operations, for clarity also - // others are defined at their respective bpp levels - #define BIADAPT_RGBHIGH 8000 - #define BIADAPT_YUVLOW 30 - #define BIADAPT_YUVMED 70 - #define BIADAPT_YUVHIGH 130 - - #define BIADAPT_CMPRGB(p1, p2) \ - Scale_GetRGBDelta (fmt, p1, p2) - // high tolerance pixel comparison - #define BIADAPT_CMPRGB_HIGH(p1, p2) \ - (p1 == p2 || BIADAPT_CMPRGB (p1, p2) <= BIADAPT_RGBHIGH) - - #define BIADAPT_CMPYUV(p1, p2) \ - Scale_GetYUVDelta (fmt, p1, p2) - // low tolerance pixel comparison - #define BIADAPT_CMPYUV_LOW(p1, p2) \ - (p1 == p2 || BIADAPT_CMPYUV (p1, p2) <= BIADAPT_YUVLOW) - // medium tolerance pixel comparison - #define BIADAPT_CMPYUV_MED(p1, p2) \ - (p1 == p2 || BIADAPT_CMPYUV (p1, p2) <= BIADAPT_YUVMED) - // high tolerance pixel comparison - #define BIADAPT_CMPYUV_HIGH(p1, p2) \ - (p1 == p2 || BIADAPT_CMPYUV (p1, p2) <= BIADAPT_YUVHIGH) - - // expand updated region if necessary - // pixels neighbooring the updated region may - // change as a result of updates - limits.x = 0; - limits.y = 0; - limits.w = src->w; - limits.h = src->h; - Scale_ExpandRect (®ion, 2, &limits); - - xend = region.x + region.w; - yend = region.y + region.h; - dsrc = w - region.w; - ddst = (dw - region.w) * 2; - - switch (fmt->BytesPerPixel) - { - case 2: // 16bpp scaling - #define BIADAPT_GETPIX(p) ( *(Uint16 *)(p) ) - #define BIADAPT_SETPIX(p, c) ( *(Uint16 *)(p) = (c) ) - #define BIADAPT_BUF Uint16 - { - BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; - BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; - - src_p += w * region.y + region.x; - dst_p += (dw * region.y + region.x) * 2; - - for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) - { - for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) - { - // pixel eqaulity counter - int cmatch; - - // most pixels will fall into 'all 4 equal' - // pattern, so we check it first - cmatch = 0; - - PIX (0, 0) = BIADAPT_GETPIX (SRC (0, 0)); - - BIADAPT_SETPIX (dst_p, PIX (0, 0)); - - if (y + 1 < h) - { - // check pixel below the current one - PIX (0, 1) = BIADAPT_GETPIX (SRC (0, 1)); - - if (PIX (0, 0) == PIX (0, 1)) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - cmatch |= 1; - } - } - else - { - // last pixel in column - propagate - PIX (0, 1) = PIX (0, 0); - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - cmatch |= 1; - - } - - if (x + 1 < w) - { - // check pixel to the right from the current one - PIX (1, 0) = BIADAPT_GETPIX (SRC (1, 0)); - - if (PIX (0, 0) == PIX (1, 0)) - { - BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); - cmatch |= 2; - } - } - else - { - // last pixel in row - propagate - PIX (1, 0) = PIX (0, 0); - BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); - cmatch |= 2; - } - - if (cmatch == 3) - { - if (y + 1 < h || x + 1 < w) - { - // last pixel in row/column and nearest - // neighboor is identical - dst_p++; - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - continue; - } - - // check pixel to the bottom-right - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - - if (PIX (0, 0) == PIX (1, 1)) - { - // all 4 are equal - propagate - dst_p++; - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - continue; - } - } - - // some neighnoors are different, lets check them - - if (x > 0) - PIX (-1, 0) = BIADAPT_GETPIX (SRC (-1, 0)); - else - PIX (-1, 0) = PIX (0, 0); - - if (x + 2 < w) - PIX (2, 0) = BIADAPT_GETPIX (SRC (2, 0)); - else - PIX (2, 0) = PIX (1, 0); - - if (y + 1 < h) - { - if (x > 0) - PIX (-1, 1) = BIADAPT_GETPIX (SRC (-1, 1)); - else - PIX (-1, 1) = PIX (0, 1); - - if (x + 2 < w) - { - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - PIX (2, 1) = BIADAPT_GETPIX (SRC (2, 1)); - } - else if (x + 1 < w) - { - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - PIX (2, 1) = PIX (1, 1); - } - else - { - PIX (1, 1) = PIX (0, 1); - PIX (2, 1) = PIX (0, 1); - } - } - else - { - // last pixel in column - PIX (-1, 1) = PIX (-1, 0); - PIX (1, 1) = PIX (1, 0); - PIX (2, 1) = PIX (2, 0); - } - - if (y + 2 < h) - { - PIX (0, 2) = BIADAPT_GETPIX (SRC (0, 2)); - - if (x > 0) - PIX (-1, 2) = BIADAPT_GETPIX (SRC (-1, 2)); - else - PIX (-1, 2) = PIX (0, 2); - - if (x + 2 < w) - { - PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); - PIX (2, 2) = BIADAPT_GETPIX (SRC (2, 2)); - } - else if (x + 1 < w) - { - PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); - PIX (2, 2) = PIX (1, 2); - } - else - { - PIX (1, 2) = PIX (0, 2); - PIX (2, 2) = PIX (0, 2); - } - } - else - { - // last pixel in column - PIX (-1, 2) = PIX (-1, 1); - PIX (0, 2) = PIX (0, 1); - PIX (1, 2) = PIX (1, 1); - PIX (2, 2) = PIX (2, 1); - } - - if (y > 0) - { - PIX (0, -1) = BIADAPT_GETPIX (SRC (0, -1)); - - if (x > 0) - PIX (-1, -1) = BIADAPT_GETPIX (SRC (-1, -1)); - else - PIX (-1, -1) = PIX (0, -1); - - if (x + 2 < w) - { - PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); - PIX (2, -1) = BIADAPT_GETPIX (SRC (2, -1)); - } - else if (x + 1 < w) - { - PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); - PIX (2, -1) = PIX (1, -1); - } - else - { - PIX (1, -1) = PIX (0, -1); - PIX (2, -1) = PIX (0, -1); - } - } - else - { - PIX (-1, -1) = PIX (-1, 0); - PIX (0, -1) = PIX (0, 0); - PIX (1, -1) = PIX (1, 0); - PIX (2, -1) = PIX (2, 0); - } - - // check pixel below the current one - if (!(cmatch & 1)) - { - if (BIADAPT_CMPYUV (PIX (0, 0), PIX (0, 1)) <= BIADAPT_YUVLOW) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (0, 1)) - ); - cmatch |= 1; - } - // detect a 2:1 line going across the current pixel - else if ( (PIX (0, 0) == PIX (-1, 0) - && PIX (0, 0) == PIX (1, 1) - && PIX (0, 0) == PIX (2, 1) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || - - (PIX (0, 0) == PIX (1, 0) - && PIX (0, 0) == PIX (-1, 1) - && PIX (0, 0) == PIX (2, -1) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - } - // detect a 2:1 line going across the pixel below current - else if ( (PIX (0, 1) == PIX (-1, 0) - && PIX (0, 1) == PIX (1, 1) - && PIX (0, 1) == PIX (2, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || - - (PIX (0, 1) == PIX (1, 0) - && PIX (0, 1) == PIX (-1, 1) - && PIX (0, 1) == PIX (2, 0) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 1)); - } - else - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (0, 1)) - ); - } - - dst_p++; - - // check pixel to the right from the current one - if (!(cmatch & 2)) - { - if (BIADAPT_CMPYUV (PIX (0, 0), PIX (1, 0)) <= BIADAPT_YUVLOW) - { - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 0)) - ); - cmatch |= 2; - } - // detect a 1:2 line going across the current pixel - else if ( (PIX (0, 0) == PIX (1, -1) - && PIX (0, 0) == PIX (0, 1) - && PIX (0, 0) == PIX (-1, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || - - (PIX (0, 0) == PIX (0, -1) - && PIX (0, 0) == PIX (1, 1) - && PIX (0, 0) == PIX (1, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) - - { - BIADAPT_SETPIX (dst_p, PIX (0, 0)); - } - // detect a 1:2 line going across the pixel to the right - else if ( (PIX (1, 0) == PIX (1, -1) - && PIX (1, 0) == PIX (0, 1) - && PIX (1, 0) == PIX (0, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || - - (PIX (1, 0) == PIX (0, -1) - && PIX (1, 0) == PIX (1, 1) - && PIX (1, 0) == PIX (2, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) - { - BIADAPT_SETPIX (dst_p, PIX (1, 0)); - } - else - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 0)) - ); - } - - if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) - { - // diagonals are equal - int *coord; - int cl, cr; - Uint32 clr; - - // both pairs are equal, have to resolve the pixel - // race; we try detecting which color is - // the background by looking for a line or an edge - // examine 8 pixels surrounding the current quad - - cl = cr = 2; - for (coord = resolve_coord[0]; *coord < 100; coord += 2) - { - clr = PIX (coord[0], coord[1]); - - if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) - cl++; - else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) - cr++; - } - - // least count wins - if (cl > cr) - clr = PIX (1, 0); - else if (cr > cl) - clr = PIX (0, 0); - else - clr = Scale_BlendPixels (fmt, - PIX (0, 0), PIX (1, 0)); - - BIADAPT_SETPIX (dst_p + dw, clr); - continue; - } - - if (cmatch == 3 - || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) - && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 1), PIX (1, 0)) - ); - continue; - } - else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - continue; - } - - // check pixel to the bottom-right - if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) - && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) - { - if (Scale_GetPixY (fmt, PIX (0, 0)) - > Scale_GetPixY (fmt, PIX (1, 0))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - } - else - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (1, 0), PIX (0, 1)) - ); - } - } - else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) - { - // main diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - } - else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) - { - // 2nd diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (1, 0), PIX (0, 1)) - ); - } - else - { - // blend all 4 - BIADAPT_SETPIX (dst_p + dw, - ((((PIX (0, 0) & fmt->Rmask) + - (PIX (0, 1) & fmt->Rmask) + - (PIX (1, 0) & fmt->Rmask) + - (PIX (1, 1) & fmt->Rmask) - ) >> 2) & fmt->Rmask) | - ((((PIX (0, 0) & fmt->Gmask) + - (PIX (0, 1) & fmt->Gmask) + - (PIX (1, 0) & fmt->Gmask) + - (PIX (1, 1) & fmt->Gmask) - ) >> 2) & fmt->Gmask) | - ((((PIX (0, 0) & fmt->Bmask) + - (PIX (0, 1) & fmt->Bmask) + - (PIX (1, 0) & fmt->Bmask) + - (PIX (1, 1) & fmt->Bmask) - ) >> 2) & fmt->Bmask)); - } - } - } - break; - } - #undef BIADAPT_GETPIX - #undef BIADAPT_SETPIX - #undef BIADAPT_BUF - - case 3: // 24bpp scaling - #define BIADAPT_GETPIX(p) GET_PIX_24BIT(p) - #define BIADAPT_SETPIX(p, c) SET_PIX_24BIT(p, c) - #define BIADAPT_BUF PIXEL_24BIT - { - BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; - BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; - - src_p += w * region.y + region.x; - dst_p += (dw * region.y + region.x) * 2; - - for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) - { - for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) - { - // pixel eqaulity counter - int cmatch; - - // most pixels will fall into 'all 4 equal' - // pattern, so we check it first - cmatch = 0; - - PIX (0, 0) = BIADAPT_GETPIX (SRC (0, 0)); - - BIADAPT_SETPIX (dst_p, PIX (0, 0)); - - if (y + 1 < h) - { - // check pixel below the current one - PIX (0, 1) = BIADAPT_GETPIX (SRC (0, 1)); - - if (PIX (0, 0) == PIX (0, 1)) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - cmatch |= 1; - } - } - else - { - // last pixel in column - propagate - PIX (0, 1) = PIX (0, 0); - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - cmatch |= 1; - - } - - if (x + 1 < w) - { - // check pixel to the right from the current one - PIX (1, 0) = BIADAPT_GETPIX (SRC (1, 0)); - - if (PIX (0, 0) == PIX (1, 0)) - { - BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); - cmatch |= 2; - } - } - else - { - // last pixel in row - propagate - PIX (1, 0) = PIX (0, 0); - BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); - cmatch |= 2; - } - - if (cmatch == 3) - { - if (y + 1 < h || x + 1 < w) - { - // last pixel in row/column and nearest - // neighboor is identical - dst_p++; - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - continue; - } - - // check pixel to the bottom-right - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - - if (PIX (0, 0) == PIX (1, 1)) - { - // all 4 are equal - propagate - dst_p++; - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - continue; - } - } - - // some neighnoors are different, lets check them - - if (x > 0) - PIX (-1, 0) = BIADAPT_GETPIX (SRC (-1, 0)); - else - PIX (-1, 0) = PIX (0, 0); - - if (x + 2 < w) - PIX (2, 0) = BIADAPT_GETPIX (SRC (2, 0)); - else - PIX (2, 0) = PIX (1, 0); - - if (y + 1 < h) - { - if (x > 0) - PIX (-1, 1) = BIADAPT_GETPIX (SRC (-1, 1)); - else - PIX (-1, 1) = PIX (0, 1); - - if (x + 2 < w) - { - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - PIX (2, 1) = BIADAPT_GETPIX (SRC (2, 1)); - } - else if (x + 1 < w) - { - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - PIX (2, 1) = PIX (1, 1); - } - else - { - PIX (1, 1) = PIX (0, 1); - PIX (2, 1) = PIX (0, 1); - } - } - else - { - // last pixel in column - PIX (-1, 1) = PIX (-1, 0); - PIX (1, 1) = PIX (1, 0); - PIX (2, 1) = PIX (2, 0); - } - - if (y + 2 < h) - { - PIX (0, 2) = BIADAPT_GETPIX (SRC (0, 2)); - - if (x > 0) - PIX (-1, 2) = BIADAPT_GETPIX (SRC (-1, 2)); - else - PIX (-1, 2) = PIX (0, 2); - - if (x + 2 < w) - { - PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); - PIX (2, 2) = BIADAPT_GETPIX (SRC (2, 2)); - } - else if (x + 1 < w) - { - PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); - PIX (2, 2) = PIX (1, 2); - } - else - { - PIX (1, 2) = PIX (0, 2); - PIX (2, 2) = PIX (0, 2); - } - } - else - { - // last pixel in column - PIX (-1, 2) = PIX (-1, 1); - PIX (0, 2) = PIX (0, 1); - PIX (1, 2) = PIX (1, 1); - PIX (2, 2) = PIX (2, 1); - } - - if (y > 0) - { - PIX (0, -1) = BIADAPT_GETPIX (SRC (0, -1)); - - if (x > 0) - PIX (-1, -1) = BIADAPT_GETPIX (SRC (-1, -1)); - else - PIX (-1, -1) = PIX (0, -1); - - if (x + 2 < w) - { - PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); - PIX (2, -1) = BIADAPT_GETPIX (SRC (2, -1)); - } - else if (x + 1 < w) - { - PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); - PIX (2, -1) = PIX (1, -1); - } - else - { - PIX (1, -1) = PIX (0, -1); - PIX (2, -1) = PIX (0, -1); - } - } - else - { - PIX (-1, -1) = PIX (-1, 0); - PIX (0, -1) = PIX (0, 0); - PIX (1, -1) = PIX (1, 0); - PIX (2, -1) = PIX (2, 0); - } - - // check pixel below the current one - if (!(cmatch & 1)) - { - if (BIADAPT_CMPYUV (PIX (0, 0), PIX (0, 1)) <= BIADAPT_YUVLOW) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (0, 1)) - ); - cmatch |= 1; - } - // detect a 2:1 line going across the current pixel - else if ( (PIX (0, 0) == PIX (-1, 0) - && PIX (0, 0) == PIX (1, 1) - && PIX (0, 0) == PIX (2, 1) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || - - (PIX (0, 0) == PIX (1, 0) - && PIX (0, 0) == PIX (-1, 1) - && PIX (0, 0) == PIX (2, -1) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - } - // detect a 2:1 line going across the pixel below current - else if ( (PIX (0, 1) == PIX (-1, 0) - && PIX (0, 1) == PIX (1, 1) - && PIX (0, 1) == PIX (2, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || - - (PIX (0, 1) == PIX (1, 0) - && PIX (0, 1) == PIX (-1, 1) - && PIX (0, 1) == PIX (2, 0) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 1)); - } - else - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (0, 1)) - ); - } - - dst_p++; - - // check pixel to the right from the current one - if (!(cmatch & 2)) - { - if (BIADAPT_CMPYUV (PIX (0, 0), PIX (1, 0)) <= BIADAPT_YUVLOW) - { - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 0)) - ); - cmatch |= 2; - } - // detect a 1:2 line going across the current pixel - else if ( (PIX (0, 0) == PIX (1, -1) - && PIX (0, 0) == PIX (0, 1) - && PIX (0, 0) == PIX (-1, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || - - (PIX (0, 0) == PIX (0, -1) - && PIX (0, 0) == PIX (1, 1) - && PIX (0, 0) == PIX (1, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) - - { - BIADAPT_SETPIX (dst_p, PIX (0, 0)); - } - // detect a 1:2 line going across the pixel to the right - else if ( (PIX (1, 0) == PIX (1, -1) - && PIX (1, 0) == PIX (0, 1) - && PIX (1, 0) == PIX (0, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || - - (PIX (1, 0) == PIX (0, -1) - && PIX (1, 0) == PIX (1, 1) - && PIX (1, 0) == PIX (2, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) - { - BIADAPT_SETPIX (dst_p, PIX (1, 0)); - } - else - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 0)) - ); - } - - if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) - { - // diagonals are equal - int *coord; - int cl, cr; - Uint32 clr; - - // both pairs are equal, have to resolve the pixel - // race; we try detecting which color is - // the background by looking for a line or an edge - // examine 8 pixels surrounding the current quad - - cl = cr = 2; - for (coord = resolve_coord[0]; *coord < 100; coord += 2) - { - clr = PIX (coord[0], coord[1]); - - if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) - cl++; - else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) - cr++; - } - - // least count wins - if (cl > cr) - clr = PIX (1, 0); - else if (cr > cl) - clr = PIX (0, 0); - else - clr = Scale_BlendPixels (fmt, - PIX (0, 0), PIX (1, 0)); - - BIADAPT_SETPIX (dst_p + dw, clr); - continue; - } - - if (cmatch == 3 - || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) - && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 1), PIX (1, 0)) - ); - continue; - } - else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - continue; - } - - // check pixel to the bottom-right - if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) - && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) - { - if (Scale_GetPixY (fmt, PIX (0, 0)) - > Scale_GetPixY (fmt, PIX (1, 0))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - } - else - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (1, 0), PIX (0, 1)) - ); - } - } - else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) - { - // main diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - } - else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) - { - // 2nd diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (1, 0), PIX (0, 1)) - ); - } - else - { - // blend all 4 - BIADAPT_SETPIX (dst_p + dw, - ((((PIX (0, 0) & fmt->Rmask) + - (PIX (0, 1) & fmt->Rmask) + - (PIX (1, 0) & fmt->Rmask) + - (PIX (1, 1) & fmt->Rmask) - ) >> 2) & fmt->Rmask) | - ((((PIX (0, 0) & fmt->Gmask) + - (PIX (0, 1) & fmt->Gmask) + - (PIX (1, 0) & fmt->Gmask) + - (PIX (1, 1) & fmt->Gmask) - ) >> 2) & fmt->Gmask) | - ((((PIX (0, 0) & fmt->Bmask) + - (PIX (0, 1) & fmt->Bmask) + - (PIX (1, 0) & fmt->Bmask) + - (PIX (1, 1) & fmt->Bmask) - ) >> 2) & fmt->Bmask)); - } - } - } - break; - } - #undef BIADAPT_GETPIX - #undef BIADAPT_SETPIX - #undef BIADAPT_BUF - - case 4: // 32bpp scaling - #define BIADAPT_GETPIX(p) ( *(Uint32 *)(p) ) - #define BIADAPT_SETPIX(p, c) ( *(Uint32 *)(p) = (c) ) - #define BIADAPT_BUF Uint32 - { - BIADAPT_BUF *src_p = (BIADAPT_BUF *)src->pixels; - BIADAPT_BUF *dst_p = (BIADAPT_BUF *)dst->pixels; - - src_p += w * region.y + region.x; - dst_p += (dw * region.y + region.x) * 2; - - for (y = region.y; y < yend; ++y, dst_p += ddst, src_p += dsrc) - { - for (x = region.x; x < xend; ++x, ++src_p, ++dst_p) - { - // pixel eqaulity counter - int cmatch; - - // most pixels will fall into 'all 4 equal' - // pattern, so we check it first - cmatch = 0; - - PIX (0, 0) = BIADAPT_GETPIX (SRC (0, 0)); - - BIADAPT_SETPIX (dst_p, PIX (0, 0)); - - if (y + 1 < h) - { - // check pixel below the current one - PIX (0, 1) = BIADAPT_GETPIX (SRC (0, 1)); - - if (PIX (0, 0) == PIX (0, 1)) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - cmatch |= 1; - } - } - else - { - // last pixel in column - propagate - PIX (0, 1) = PIX (0, 0); - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - cmatch |= 1; - - } - - if (x + 1 < w) - { - // check pixel to the right from the current one - PIX (1, 0) = BIADAPT_GETPIX (SRC (1, 0)); - - if (PIX (0, 0) == PIX (1, 0)) - { - BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); - cmatch |= 2; - } - } - else - { - // last pixel in row - propagate - PIX (1, 0) = PIX (0, 0); - BIADAPT_SETPIX (dst_p + 1, PIX (0, 0)); - cmatch |= 2; - } - - if (cmatch == 3) - { - if (y + 1 < h || x + 1 < w) - { - // last pixel in row/column and nearest - // neighboor is identical - dst_p++; - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - continue; - } - - // check pixel to the bottom-right - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - - if (PIX (0, 0) == PIX (1, 1)) - { - // all 4 are equal - propagate - dst_p++; - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - continue; - } - } - - // some neighnoors are different, lets check them - - if (x > 0) - PIX (-1, 0) = BIADAPT_GETPIX (SRC (-1, 0)); - else - PIX (-1, 0) = PIX (0, 0); - - if (x + 2 < w) - PIX (2, 0) = BIADAPT_GETPIX (SRC (2, 0)); - else - PIX (2, 0) = PIX (1, 0); - - if (y + 1 < h) - { - if (x > 0) - PIX (-1, 1) = BIADAPT_GETPIX (SRC (-1, 1)); - else - PIX (-1, 1) = PIX (0, 1); - - if (x + 2 < w) - { - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - PIX (2, 1) = BIADAPT_GETPIX (SRC (2, 1)); - } - else if (x + 1 < w) - { - PIX (1, 1) = BIADAPT_GETPIX (SRC (1, 1)); - PIX (2, 1) = PIX (1, 1); - } - else - { - PIX (1, 1) = PIX (0, 1); - PIX (2, 1) = PIX (0, 1); - } - } - else - { - // last pixel in column - PIX (-1, 1) = PIX (-1, 0); - PIX (1, 1) = PIX (1, 0); - PIX (2, 1) = PIX (2, 0); - } - - if (y + 2 < h) - { - PIX (0, 2) = BIADAPT_GETPIX (SRC (0, 2)); - - if (x > 0) - PIX (-1, 2) = BIADAPT_GETPIX (SRC (-1, 2)); - else - PIX (-1, 2) = PIX (0, 2); - - if (x + 2 < w) - { - PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); - PIX (2, 2) = BIADAPT_GETPIX (SRC (2, 2)); - } - else if (x + 1 < w) - { - PIX (1, 2) = BIADAPT_GETPIX (SRC (1, 2)); - PIX (2, 2) = PIX (1, 2); - } - else - { - PIX (1, 2) = PIX (0, 2); - PIX (2, 2) = PIX (0, 2); - } - } - else - { - // last pixel in column - PIX (-1, 2) = PIX (-1, 1); - PIX (0, 2) = PIX (0, 1); - PIX (1, 2) = PIX (1, 1); - PIX (2, 2) = PIX (2, 1); - } - - if (y > 0) - { - PIX (0, -1) = BIADAPT_GETPIX (SRC (0, -1)); - - if (x > 0) - PIX (-1, -1) = BIADAPT_GETPIX (SRC (-1, -1)); - else - PIX (-1, -1) = PIX (0, -1); - - if (x + 2 < w) - { - PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); - PIX (2, -1) = BIADAPT_GETPIX (SRC (2, -1)); - } - else if (x + 1 < w) - { - PIX (1, -1) = BIADAPT_GETPIX (SRC (1, -1)); - PIX (2, -1) = PIX (1, -1); - } - else - { - PIX (1, -1) = PIX (0, -1); - PIX (2, -1) = PIX (0, -1); - } - } - else - { - PIX (-1, -1) = PIX (-1, 0); - PIX (0, -1) = PIX (0, 0); - PIX (1, -1) = PIX (1, 0); - PIX (2, -1) = PIX (2, 0); - } - - // check pixel below the current one - if (!(cmatch & 1)) - { - if (BIADAPT_CMPYUV (PIX (0, 0), PIX (0, 1)) <= BIADAPT_YUVLOW) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (0, 1)) - ); - cmatch |= 1; - } - // detect a 2:1 line going across the current pixel - else if ( (PIX (0, 0) == PIX (-1, 0) - && PIX (0, 0) == PIX (1, 1) - && PIX (0, 0) == PIX (2, 1) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || - - (PIX (0, 0) == PIX (1, 0) - && PIX (0, 0) == PIX (-1, 1) - && PIX (0, 0) == PIX (2, -1) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 0)); - } - // detect a 2:1 line going across the pixel below current - else if ( (PIX (0, 1) == PIX (-1, 0) - && PIX (0, 1) == PIX (1, 1) - && PIX (0, 1) == PIX (2, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || - - (PIX (0, 1) == PIX (1, 0) - && PIX (0, 1) == PIX (-1, 1) - && PIX (0, 1) == PIX (2, 0) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) - { - BIADAPT_SETPIX (dst_p + dw, PIX (0, 1)); - } - else - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (0, 1)) - ); - } - - dst_p++; - - // check pixel to the right from the current one - if (!(cmatch & 2)) - { - if (BIADAPT_CMPYUV (PIX (0, 0), PIX (1, 0)) <= BIADAPT_YUVLOW) - { - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 0)) - ); - cmatch |= 2; - } - // detect a 1:2 line going across the current pixel - else if ( (PIX (0, 0) == PIX (1, -1) - && PIX (0, 0) == PIX (0, 1) - && PIX (0, 0) == PIX (-1, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || - - (PIX (0, 0) == PIX (0, -1) - && PIX (0, 0) == PIX (1, 1) - && PIX (0, 0) == PIX (1, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) - - { - BIADAPT_SETPIX (dst_p, PIX (0, 0)); - } - // detect a 1:2 line going across the pixel to the right - else if ( (PIX (1, 0) == PIX (1, -1) - && PIX (1, 0) == PIX (0, 1) - && PIX (1, 0) == PIX (0, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || - - (PIX (1, 0) == PIX (0, -1) - && PIX (1, 0) == PIX (1, 1) - && PIX (1, 0) == PIX (2, 2) && - - ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || - (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) - && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) - { - BIADAPT_SETPIX (dst_p, PIX (1, 0)); - } - else - BIADAPT_SETPIX (dst_p, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 0)) - ); - } - - if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) - { - // diagonals are equal - int *coord; - int cl, cr; - Uint32 clr; - - // both pairs are equal, have to resolve the pixel - // race; we try detecting which color is - // the background by looking for a line or an edge - // examine 8 pixels surrounding the current quad - - cl = cr = 2; - for (coord = resolve_coord[0]; *coord < 100; coord += 2) - { - clr = PIX (coord[0], coord[1]); - - if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) - cl++; - else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) - cr++; - } - - // least count wins - if (cl > cr) - clr = PIX (1, 0); - else if (cr > cl) - clr = PIX (0, 0); - else - clr = Scale_BlendPixels (fmt, - PIX (0, 0), PIX (1, 0)); - - BIADAPT_SETPIX (dst_p + dw, clr); - continue; - } - - if (cmatch == 3 - || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) - && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 1), PIX (1, 0)) - ); - continue; - } - else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - continue; - } - - // check pixel to the bottom-right - if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) - && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) - { - if (Scale_GetPixY (fmt, PIX (0, 0)) - > Scale_GetPixY (fmt, PIX (1, 0))) - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - } - else - { - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (1, 0), PIX (0, 1)) - ); - } - } - else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) - { - // main diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (0, 0), PIX (1, 1)) - ); - } - else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) - { - // 2nd diagonal is same color - // use its value - BIADAPT_SETPIX (dst_p + dw, Scale_BlendPixels ( - fmt, PIX (1, 0), PIX (0, 1)) - ); - } - else - { - // blend all 4 - BIADAPT_SETPIX (dst_p + dw, - ((((PIX (0, 0) & fmt->Rmask) + - (PIX (0, 1) & fmt->Rmask) + - (PIX (1, 0) & fmt->Rmask) + - (PIX (1, 1) & fmt->Rmask) - ) >> 2) & fmt->Rmask) | - ((((PIX (0, 0) & fmt->Gmask) + - (PIX (0, 1) & fmt->Gmask) + - (PIX (1, 0) & fmt->Gmask) + - (PIX (1, 1) & fmt->Gmask) - ) >> 2) & fmt->Gmask) | - ((((PIX (0, 0) & fmt->Bmask) + - (PIX (0, 1) & fmt->Bmask) + - (PIX (1, 0) & fmt->Bmask) + - (PIX (1, 1) & fmt->Bmask) - ) >> 2) & fmt->Bmask)); - } - } - } - break; - } - #undef BIADAPT_GETPIX - #undef BIADAPT_SETPIX - #undef BIADAPT_BUF - } - - #undef BIADAPT_CMPRGB - #undef BIADAPT_CMPRGB_HIGH - #undef BIADAPT_CMPYUV - #undef BIADAPT_CMPYUV_LOW - #undef BIADAPT_CMPYUV_MED - #undef BIADAPT_CMPYUV_HIGH - - #undef PIX - #undef SRC -} - - -// nearest neighbor scaling to 2x -static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) -{ - int x, y; - const int w = src->w, dw = dst->w; - const int x0 = r->x, y0 = r->y, rw = r->w, rh = r->h; - const int ds = w-rw, dd = (dw-rw) * 2; - - switch (dst->format->BytesPerPixel) - { - case 2: - { - Uint16 *src_p = (Uint16 *)src->pixels, *dst_p = (Uint16 *)dst->pixels; - Uint16 pixval_16; - src_p += w*y0 + x0; - dst_p += (dw*y0 + x0) * 2; - for (y = 0; y < rh; ++y) - { - for (x = 0; x < rw; ++x) - { - pixval_16 = *src_p++; - dst_p[dw] = pixval_16; - *dst_p++ = pixval_16; - dst_p[dw] = pixval_16; - *dst_p++ = pixval_16; - } - dst_p += dd; - src_p += ds; - } - break; - } - case 3: - { - PIXEL_24BIT *src_p = (PIXEL_24BIT *)src->pixels; - PIXEL_24BIT *dst_p = (PIXEL_24BIT *)dst->pixels; - PIXEL_24BIT *src_p2; - const int dd = dw - rw * 2; // override - Uint32 pixval_32; - src_p += w*y0 + x0; - dst_p += (dw*y0 + x0) * 2; - for (y = 0; y < rh; ++y) - { - src_p2 = src_p; - for (x = 0; x < rw; ++x, ++src_p) - { - pixval_32 = GET_PIX_24BIT (src_p); - SET_PIX_24BIT (dst_p, pixval_32); - dst_p++; - SET_PIX_24BIT (dst_p, pixval_32); - dst_p++; - } - dst_p += dd; - src_p = src_p2; - for (x = 0; x < rw; ++x, ++src_p) - { - pixval_32 = GET_PIX_24BIT (src_p); - SET_PIX_24BIT (dst_p, pixval_32); - dst_p++; - SET_PIX_24BIT (dst_p, pixval_32); - dst_p++; - } - dst_p += dd; - src_p += ds; - } - break; - } - case 4: - { - Uint32 *src_p = (Uint32 *)src->pixels, *dst_p = (Uint32 *)dst->pixels; - Uint32 pixval_32; - src_p += w*y0 + x0; - dst_p += (dw*y0 + x0) * 2; - for (y = 0; y < rh; ++y) - { - for (x = 0; x < rw; ++x) - { - pixval_32 = *src_p++; - dst_p[dw] = pixval_32; - *dst_p++ = pixval_32; - dst_p[dw] = pixval_32; - *dst_p++ = pixval_32; - } - dst_p += dd; - src_p += ds; - } - break; - } - } -} - -// bilinear scaling to 2x -static void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) -{ - int x, y, i = 0, j, fa, fb, fc, fd; - const int w = dst->w, h = dst->h; - SDL_PixelFormat *fmt = dst->format; - - switch (dst->format->BytesPerPixel) - { - case 2: - { - Uint16 *src_p = (Uint16 *) src->pixels, *src_p2; - Uint16 *dst_p = (Uint16 *) dst->pixels; - Uint32 p[4]; - - for (y = 0; y < h; ++y) - { - src_p2 = src_p; - j = i; - - p[0] = src_p[0]; - if (y < h - 2) - p[2] = src_p[src->w]; - else - p[2] = 0; - - for (x = 0; x < w; ++x) - { - if (j == i) - { - if (y < h - 2) - { - if (x < w - 2) - { - p[1] = src_p[1]; - p[3] = src_p[src->w + 1]; - } - else - { - p[1] = 0; - p[3] = 0; - } - } - else - { - if (x < w - 2) - p[1] = src_p[1]; - else - p[1] = 0; - p[3] = 0; - } - } - - fa = bilinear_table[j][0]; - fb = bilinear_table[j][1]; - fc = bilinear_table[j][2]; - fd = bilinear_table[j][3]; - - *dst_p++ = - (((((p[0] & fmt->Rmask) * fa) + - ((p[1] & fmt->Rmask) * fb) + - ((p[2] & fmt->Rmask) * fc) + - ((p[3] & fmt->Rmask) * fd)) >> 4) & fmt->Rmask) | - (((((p[0] & fmt->Gmask) * fa) + - ((p[1] & fmt->Gmask) * fb) + - ((p[2] & fmt->Gmask) * fc) + - ((p[3] & fmt->Gmask) * fd)) >> 4) & fmt->Gmask) | - (((((p[0] & fmt->Bmask) * fa) + - ((p[1] & fmt->Bmask) * fb) + - ((p[2] & fmt->Bmask) * fc) + - ((p[3] & fmt->Bmask) * fd)) >> 4) & fmt->Bmask); - - if (j & 2) - { - j = i; - src_p++; - p[0] = p[1]; - p[2] = p[3]; - } - else - { - j = i | 2; - } - } - - if (!i) - src_p = src_p2; - i = !i; - } - - break; - } - case 3: - { - // 24bpp mode bilinear scaling isn't implemented currently - // it would probably be too slow to be useful anyway - Scale_Nearest (src, dst, r); - break; - } - case 4: - { - Uint32 *src_p = (Uint32 *) src->pixels, *src_p2; - Uint32 *dst_p = (Uint32 *) dst->pixels; - Uint32 p[4]; - - for (y = 0; y < h; ++y) - { - src_p2 = src_p; - j = i; - - p[0] = src_p[0]; - if (y < h - 2) - p[2] = src_p[src->w]; - else - p[2] = 0; - - for (x = 0; x < w; ++x) - { - if (j == i) - { - if (y < h - 2) - { - if (x < w - 2) - { - p[1] = src_p[1]; - p[3] = src_p[src->w + 1]; - } - else - { - p[1] = 0; - p[3] = 0; - } - } - else - { - if (x < w - 2) - p[1] = src_p[1]; - else - p[1] = 0; - p[3] = 0; - } - } - - fa = bilinear_table[j][0]; - fb = bilinear_table[j][1]; - fc = bilinear_table[j][2]; - fd = bilinear_table[j][3]; - - *dst_p++ = - (((((p[0] & fmt->Rmask) * fa) + - ((p[1] & fmt->Rmask) * fb) + - ((p[2] & fmt->Rmask) * fc) + - ((p[3] & fmt->Rmask) * fd)) >> 4) & fmt->Rmask) | - (((((p[0] & fmt->Gmask) * fa) + - ((p[1] & fmt->Gmask) * fb) + - ((p[2] & fmt->Gmask) * fc) + - ((p[3] & fmt->Gmask) * fd)) >> 4) & fmt->Gmask) | - (((((p[0] & fmt->Bmask) * fa) + - ((p[1] & fmt->Bmask) * fb) + - ((p[2] & fmt->Bmask) * fc) + - ((p[3] & fmt->Bmask) * fd)) >> 4) & fmt->Bmask); - - if (j & 2) - { - j = i; - src_p++; - p[0] = p[1]; - p[2] = p[3]; - } - else - { - j = i | 2; - } - } - - if (!i) - src_p = src_p2; - i = !i; - } - - break; - } - } -} - static void ScanLines (SDL_Surface *dst) { Uint8 *pixels = (Uint8 *) dst->pixels;