From da1bc169a15ed590427088e34b6007777103d504 Mon Sep 17 00:00:00 2001 From: p989 Date: Thu, 16 Jul 2009 04:08:18 +0000 Subject: [PATCH] win32: bilinear filter --- desmume/src/windows/DeSmuME_2005.vcproj | 4 + desmume/src/windows/DeSmuME_2008.vcproj | 4 + desmume/src/windows/filter/bilinear.cpp | 236 ++++++++++++++++++++++++ desmume/src/windows/filter/filter.h | 3 +- desmume/src/windows/main.cpp | 5 + desmume/src/windows/resource.h | 1 + desmume/src/windows/resources.rc | Bin 685838 -> 685952 bytes desmume/src/windows/video.h | 6 +- 8 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 desmume/src/windows/filter/bilinear.cpp diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 01235a6d2..ba397a083 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -601,6 +601,10 @@ RelativePath=".\filter\2xsai.cpp" > + + diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index 2937f209b..28534acbf 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -717,6 +717,10 @@ RelativePath=".\aviout.cpp" > + + diff --git a/desmume/src/windows/filter/bilinear.cpp b/desmume/src/windows/filter/bilinear.cpp new file mode 100644 index 000000000..fc477f7c7 --- /dev/null +++ b/desmume/src/windows/filter/bilinear.cpp @@ -0,0 +1,236 @@ +/** Code adapted from Exult source code by Forgotten + ** Scale.cc - Trying to scale with bilinear interpolation. + ** + ** Written: 6/14/00 - JSF + **/ + +#include "types.h" + +int systemRedShift = 10; +int systemGreenShift = 0; +int systemBlueShift = 5; + +#define RGB1(r,g,b) ((r)>>3) << systemRedShift |\ + ((g) >> 3) << systemGreenShift |\ + ((b) >> 3) << systemBlueShift\ + +static void fill_rgb_row_16(u16 *from, int src_width, u8 *row, int width) +{ + u8 *copy_start = row + src_width*3; + u8 *all_stop = row + width*3; + while (row < copy_start) { + u16 color = *from++; + *row++ = ((color >> systemRedShift) & 0x1f) << 3; + *row++ = ((color >> systemGreenShift) & 0x1f) << 3; + *row++ = ((color >> systemBlueShift) & 0x1f) << 3; + } + // any remaining elements to be written to 'row' are a replica of the + // preceding pixel + u8 *p = row-3; + while (row < all_stop) { + // we're guaranteed three elements per pixel; could unroll the loop + // further, especially with a Duff's Device, but the gains would be + // probably limited (judging by profiler output) + *row++ = *p++; + *row++ = *p++; + *row++ = *p++; + } +} + +void Bilinear(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 row_cur[3*322]; + u8 row_next[3*322]; + u8 *rgb_row_cur = row_cur; + u8 *rgb_row_next = row_next; + + u16 *to = (u16 *)dstPtr; + u16 *to_odd = (u16 *)(dstPtr + dstPitch); + + int from_width = width; + u16 *from = (u16 *)srcPtr; + fill_rgb_row_16(from, from_width, rgb_row_cur, width+1); + + for(int y = 0; y < height; y++) { + u16 *from_orig = from; + u16 *to_orig = to; + + if (y+1 < height) + fill_rgb_row_16(from+width, from_width, rgb_row_next, + width+1); + else + fill_rgb_row_16(from, from_width, rgb_row_next, width+1); + + // every pixel in the src region, is extended to 4 pixels in the + // destination, arranged in a square 'quad'; if the current src + // pixel is 'a', then in what follows 'b' is the src pixel to the + // right, 'c' is the src pixel below, and 'd' is the src pixel to + // the right and down + u8 *cur_row = rgb_row_cur; + u8 *next_row = rgb_row_next; + u8 *ar = cur_row++; + u8 *ag = cur_row++; + u8 *ab = cur_row++; + u8 *cr = next_row++; + u8 *cg = next_row++; + u8 *cb = next_row++; + for(int x=0; x < width; x++) { + u8 *br = cur_row++; + u8 *bg = cur_row++; + u8 *bb = cur_row++; + u8 *dr = next_row++; + u8 *dg = next_row++; + u8 *db = next_row++; + + // upper left pixel in quad: just copy it in + *to++ = RGB1(*ar, *ag, *ab); + + // upper right + *to++ = RGB1((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); + + // lower left + *to_odd++ = RGB1((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); + + // lower right + *to_odd++ = RGB1((*ar+*br+*cr+*dr)>>2, + (*ag+*bg+*cg+*dg)>>2, + (*ab+*bb+*cb+*db)>>2); + + // 'b' becomes 'a', 'd' becomes 'c' + ar = br; + ag = bg; + ab = bb; + cr = dr; + cg = dg; + cb = db; + } + + // the "next" rgb row becomes the current; the old current rgb row is + // recycled and serves as the new "next" row + u8 *temp; + temp = rgb_row_cur; + rgb_row_cur = rgb_row_next; + rgb_row_next = temp; + + // update the pointers for start of next pair of lines + from = (u16 *)((u8 *)from_orig + srcPitch); + to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); + to_odd = (u16 *)((u8 *)to + dstPitch); + } +} + +struct SSurface { + unsigned char *Surface; + + unsigned int Pitch; + unsigned int Width, Height; +}; + +void BilinearPlus(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 row_cur[3*322]; + u8 row_next[3*322]; + u8 *rgb_row_cur = row_cur; + u8 *rgb_row_next = row_next; + + u16 *to = (u16 *)dstPtr; + u16 *to_odd = (u16 *)(dstPtr + dstPitch); + + int from_width = width; + u16 *from = (u16 *)srcPtr; + fill_rgb_row_16(from, from_width, rgb_row_cur, width+1); + + for(int y = 0; y < height; y++) { + u16 *from_orig = from; + u16 *to_orig = to; + + if (y+1 < height) + fill_rgb_row_16(from+width, from_width, rgb_row_next, + width+1); + else + fill_rgb_row_16(from, from_width, rgb_row_next, width+1); + + // every pixel in the src region, is extended to 4 pixels in the + // destination, arranged in a square 'quad'; if the current src + // pixel is 'a', then in what follows 'b' is the src pixel to the + // right, 'c' is the src pixel below, and 'd' is the src pixel to + // the right and down + u8 *cur_row = rgb_row_cur; + u8 *next_row = rgb_row_next; + u8 *ar = cur_row++; + u8 *ag = cur_row++; + u8 *ab = cur_row++; + u8 *cr = next_row++; + u8 *cg = next_row++; + u8 *cb = next_row++; + for(int x=0; x < width; x++) { + u8 *br = cur_row++; + u8 *bg = cur_row++; + u8 *bb = cur_row++; + u8 *dr = next_row++; + u8 *dg = next_row++; + u8 *db = next_row++; + + // upper left pixel in quad: just copy it in + //*to++ = manip.rgb(*ar, *ag, *ab); +#ifdef USE_ORIGINAL_BILINEAR_PLUS + *to++ = RGB( + (((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3, + (((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3, + (((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3); +#else + *to++ = RGB1( + (((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4, + (((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4, + (((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4); +#endif + + // upper right + *to++ = RGB1((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); + + // lower left + *to_odd++ = RGB1((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); + + // lower right + *to_odd++ = RGB1((*ar+*br+*cr+*dr)>>2, + (*ag+*bg+*cg+*dg)>>2, + (*ab+*bb+*cb+*db)>>2); + + // 'b' becomes 'a', 'd' becomes 'c' + ar = br; + ag = bg; + ab = bb; + cr = dr; + cg = dg; + cb = db; + } + + // the "next" rgb row becomes the current; the old current rgb row is + // recycled and serves as the new "next" row + u8 *temp; + temp = rgb_row_cur; + rgb_row_cur = rgb_row_next; + rgb_row_next = temp; + + // update the pointers for start of next pair of lines + from = (u16 *)((u8 *)from_orig + srcPitch); + to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); + to_odd = (u16 *)((u8 *)to + dstPitch); + } +} + +void RenderBilinear (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + Bilinear (lpSrc, Src.Pitch, + lpSrc, + lpDst, Dst.Pitch, Src.Width, Src.Height); + +} \ No newline at end of file diff --git a/desmume/src/windows/filter/filter.h b/desmume/src/windows/filter/filter.h index 2334a81ad..3dbc99d9a 100644 --- a/desmume/src/windows/filter/filter.h +++ b/desmume/src/windows/filter/filter.h @@ -9,4 +9,5 @@ void RenderHQ2X (SSurface Src, SSurface Dst); void Render2xSaI (SSurface Src, SSurface Dst); void RenderSuper2xSaI (SSurface Src, SSurface Dst); void RenderSuperEagle (SSurface Src, SSurface Dst); -void RenderScanline( SSurface Src, SSurface Dst); \ No newline at end of file +void RenderScanline( SSurface Src, SSurface Dst); +void RenderBilinear( SSurface Src, SSurface Dst); \ No newline at end of file diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 1746400b7..66b13fd9f 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -2491,6 +2491,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM MainWindow->checkMenu(IDM_RENDER_SUPER2XSAI, MF_BYCOMMAND | video.currentfilter == video.SUPER2XSAI ? MF_CHECKED:MF_UNCHECKED); MainWindow->checkMenu(IDM_RENDER_SUPEREAGLE, MF_BYCOMMAND | video.currentfilter == video.SUPEREAGLE ? MF_CHECKED:MF_UNCHECKED); MainWindow->checkMenu(IDM_RENDER_SCANLINE, MF_BYCOMMAND | video.currentfilter == video.SCANLINE ? MF_CHECKED:MF_UNCHECKED); + MainWindow->checkMenu(IDM_RENDER_BILINEAR, MF_BYCOMMAND | video.currentfilter == video.BILINEAR ? MF_CHECKED:MF_UNCHECKED); //Language selection @@ -2843,6 +2844,10 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM video.setfilter(video.SCANLINE); FilterUpdate(hwnd); break; + case IDM_RENDER_BILINEAR: + video.setfilter(video.BILINEAR); + FilterUpdate(hwnd); + break; case IDM_STATE_LOAD: { OPENFILENAME ofn; diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index 5a2bf4caf..c07db3a3f 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -168,6 +168,7 @@ #define IDM_RENDER_SUPER2XSAI 554 #define IDM_RENDER_SUPEREAGLE 555 #define IDM_RENDER_SCANLINE 556 +#define IDM_RENDER_BILINEAR 557 #define IDD_IO_REG 601 #define IDM_RECORD_MOVIE 602 #define IDM_PLAY_MOVIE 603 diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index fcae0ab8d263e585ea99aa7567f5a5fe18891f3b..33e8afc4b3c503ae544b55734ac840af9c930191 100644 GIT binary patch delta 99 zcmeBsr`hmcv!R8tg{g(Pg=GutAJ*wztgK@EP7Ik0IY6ApkjjwAP&D12h1FEtiNTY> u2Z;R`Tp1i0f*5!ixEMGYI43W((QnscV+CS1AZ7<*4j|^-uEoanqyPXId>2dr delta 49 zcmZp8ui5ubv!R8tg{g(Pg=GutAJ)l>Z1mdau(1L$8xXStF$WNHZlA-(^`rm**H97I diff --git a/desmume/src/windows/video.h b/desmume/src/windows/video.h index 13fe8325d..4f2f6e52b 100644 --- a/desmume/src/windows/video.h +++ b/desmume/src/windows/video.h @@ -20,7 +20,8 @@ public: _2XSAI, SUPER2XSAI, SUPEREAGLE, - SCANLINE + SCANLINE, + BILINEAR }; @@ -82,6 +83,9 @@ public: case SCANLINE: RenderScanline(src, dst); break; + case BILINEAR: + RenderBilinear(src, dst); + break; } }