Scale2X 4 Sdl


sebt3

homebrew player (P. & C.)
Joined
Sep 9, 2008
Messages
4,886
Age
43
Location
France
Website
sebt3.openpandora.org
Hi there,

Some of us discussed scale2x on irc today. I found the SDL implementation (in the contrib directory) not compeling enough, so I've done my own :

Code:
 #define B sp[i - b]
 #define D sp[i - (i>0?1:0)]
 #define F sp[i + (i<wd?1:0)]
 #define H sp[i + h]
 #define E  sp[i]
 #define E0 tp[i*2] 
 #define E1 tp[i*2 + 1]
 #define E2 tp[i*2 + tpitch]
 #define E3 tp[i*2 + 1 + tpitch]
 
 void scale2x(SDL_Surface* surface, SDL_Surface* dest)
  {
    register int i, j;
    int b, h;
    int bpp = surface->format->BytesPerPixel;
    if (SDL_MUSTLOCK(dest) != 0)
    {
      if (SDL_LockSurface(dest) < 0)
      {
        fprintf(stderr, "dest locking failedn");
        return;
      }
    }
  
    const int wd = ((dest->w / 2) < (surface->w)) ? (dest->w / 2) : (surface->w);
    const int hg = ((dest->h) < (surface->h*2)) ? (dest->h / 2) : (surface->h);
 
    switch (bpp)
    {
      case 2:
      {
        int tpitch = dest->pitch / 2;
        int spitch = surface->pitch / 2;
        Uint16* tp = (Uint16*) dest->pixels;
        Uint16* sp = (Uint16*) surface->pixels;
  
        for (j = 0; j < hg; ++j)
        {
 	 b = j>0?spitch:0;
 	 h = j<hg?spitch:0;
          for (i = 0; i < wd; ++i)
          {
 		if (B != H && D != F) {
 			E0 = D == B ? D : E;
 			E1 = B == F ? F : E;
 			E2 = D == H ? D : E;
 			E3 = H == F ? F : E;
 		} else {
 			E0 = E;
 			E1 = E;
 			E2 = E;
 			E3 = E;
 		}
          }
          tp += 2*tpitch;
          sp += spitch;
        }
  
        break;
      }
      case 4:
      {
        int tpitch = dest->pitch / 4;
        int spitch = surface->pitch / 4;
        Uint32* tp = (Uint32*) dest->pixels;
        Uint32* sp = (Uint32*) surface->pixels;
  
        for (j = 0; j < hg; ++j)
        {
 	 b = j>0?spitch:0;
 	 h = j<hg?spitch:0;
          for (i = 0; i < wd; ++i)
          {
 		if (B != H && D != F) {
 			E0 = D == B ? D : E;
 			E1 = B == F ? F : E;
 			E2 = D == H ? D : E;
 			E3 = H == F ? F : E;
 		} else {
 			E0 = E;
 			E1 = E;
 			E2 = E;
 			E3 = E;
 		}
          }
          tp += 2*tpitch;
          sp += spitch;
        }
  
        break;
      }
      default:
        fprintf(stderr, "Unsupported bitdepth.n");
        break;
    }
  
  
    if (SDL_MUSTLOCK(dest) != 0)
    {
      SDL_UnlockSurface(dest);
    }
  }

The result is as fast as the initial (stupid) 2x scaler I wrote for the zelda's games. But I'm not a performance genius. Is there something that could drive up the performance a little more here ?


EDIT : this is completely obsolete : http://www.gp32x.de/board/index.php?/topic/57506-improved-sdl/
 
Last edited by a moderator:
As codeaholic point me on IRC, if I want to get feed back, I have to say why I have done this.
First, the complete and original implementation of it is generic. And I don't have a good track record of integrating video code to SDL.
The tarball contain a contrib directory, which contain sdl/scale2x.c. At first this file looked to be exactly what I was looking for.
Then I saw that this file doesn't even take care of the optimisation explained here.

So I wrote the above by merging my simple2x I used in the zelda's games with this one. (BTW, you can see my version don't support 24bpp).

My performance concerns are :
- I'm using #define for readability, but the one in contrib/sdl is using variables. So I'm switching some "stor" to a shift and an increment. Not sure which is faster
- The original implementation take first and last column apart, I'm using (i>0?1:0) in my #define. So this test is done for every pixels. Does is worth lower the readability to remove that test every pixel ?
- I'm using "register" for the 2 loop counter, but I dont even know how much are available on this soc.Is it worth doing the research to find the variable that should be set as a register or gcc is doing a good enough job ?

I'm not going to unroll the loops : that what "-funroll-loop" is for.
I dont want to optimize this to death (anyway if you realy need performances use the complete implementation. I know Pickle have done this). I'm seeing this as a good base to talk about performance in the code and share our experience. (mine is limited so I intend to learn from your answer :p)
 
Back
Top