qemu/ui/sdl_zoom_template.h
<<
>>
Prefs
   1/*
   2 * SDL_zoom_template - surface scaling
   3 * 
   4 * Copyright (c) 2009 Citrix Systems, Inc.
   5 *
   6 * Derived from: SDL_rotozoom,  LGPL (c) A. Schiffler from the SDL_gfx library.
   7 * Modifications by Stefano Stabellini.
   8 *
   9 * This work is licensed under the terms of the GNU GPL version 2.
  10 * See the COPYING file in the top-level directory.
  11 *
  12 */
  13
  14#if BPP == 16
  15#define SDL_TYPE Uint16
  16#elif BPP == 32
  17#define SDL_TYPE Uint32
  18#else
  19#error unsupport depth
  20#endif
  21
  22/*  
  23 *  Simple helper functions to make the code looks nicer
  24 *
  25 *  Assume spf = source SDL_PixelFormat
  26 *         dpf = dest SDL_PixelFormat
  27 *
  28 */
  29#define getRed(color)   (((color) & spf->Rmask) >> spf->Rshift)
  30#define getGreen(color) (((color) & spf->Gmask) >> spf->Gshift)
  31#define getBlue(color)  (((color) & spf->Bmask) >> spf->Bshift)
  32#define getAlpha(color) (((color) & spf->Amask) >> spf->Ashift)
  33
  34#define setRed(r, pcolor) do { \
  35    *pcolor = ((*pcolor) & (~(dpf->Rmask))) + \
  36              (((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \
  37} while (0);
  38
  39#define setGreen(g, pcolor) do { \
  40    *pcolor = ((*pcolor) & (~(dpf->Gmask))) + \
  41              (((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \
  42} while (0);
  43
  44#define setBlue(b, pcolor) do { \
  45    *pcolor = ((*pcolor) & (~(dpf->Bmask))) + \
  46              (((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \
  47} while (0);
  48
  49#define setAlpha(a, pcolor) do { \
  50    *pcolor = ((*pcolor) & (~(dpf->Amask))) + \
  51              (((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \
  52} while (0);
  53
  54static void glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth,
  55                                   SDL_Rect *dst_rect)
  56{
  57    int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, sstep_jump;
  58    SDL_TYPE *c00, *c01, *c10, *c11, *sp, *csp, *dp;
  59    int d_gap;
  60    SDL_PixelFormat *spf = src->format;
  61    SDL_PixelFormat *dpf = dst->format;
  62
  63    if (smooth) { 
  64        /* For interpolation: assume source dimension is one pixel.
  65         * Smaller here to avoid overflow on right and bottom edge.
  66         */
  67        sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
  68        sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
  69    } else {
  70        sx = (int) (65536.0 * (float) src->w / (float) dst->w);
  71        sy = (int) (65536.0 * (float) src->h / (float) dst->h);
  72    }
  73
  74    sax = g_new(int, dst->w + 1);
  75    say = g_new(int, dst->h + 1);
  76
  77    sp = csp = (SDL_TYPE *) src->pixels;
  78    dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
  79                       dst_rect->x * dst->format->BytesPerPixel);
  80
  81    csx = 0;
  82    csax = sax;
  83    for (x = 0; x <= dst->w; x++) {
  84        *csax = csx;
  85        csax++;
  86        csx &= 0xffff;
  87        csx += sx;
  88    }
  89    csy = 0;
  90    csay = say;
  91    for (y = 0; y <= dst->h; y++) {
  92        *csay = csy;
  93        csay++;
  94        csy &= 0xffff;
  95        csy += sy;
  96    }
  97
  98    d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
  99
 100    if (smooth) {
 101        csay = say;
 102        for (y = 0; y < dst_rect->y; y++) {
 103            csay++;
 104            sstep = (*csay >> 16) * src->pitch;
 105            csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 106        }
 107
 108        /* Calculate sstep_jump */
 109        csax = sax; 
 110        sstep_jump = 0;
 111        for (x = 0; x < dst_rect->x; x++) {
 112            csax++; 
 113            sstep = (*csax >> 16);
 114            sstep_jump += sstep;
 115        }
 116
 117        for (y = 0; y < dst_rect->h ; y++) {
 118            /* Setup colour source pointers */
 119            c00 = csp + sstep_jump;
 120            c01 = c00 + 1;
 121            c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
 122            c11 = c10 + 1;
 123            csax = sax + dst_rect->x; 
 124
 125            for (x = 0; x < dst_rect->w; x++) {
 126
 127                /* Interpolate colours */
 128                ex = (*csax & 0xffff);
 129                ey = (*csay & 0xffff);
 130                t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
 131                     getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
 132                t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
 133                     getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
 134                setRed((((t2 - t1) * ey) >> 16) + t1, dp);
 135                t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
 136                     getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
 137                t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
 138                     getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
 139                setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
 140                t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
 141                     getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
 142                t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
 143                     getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
 144                setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
 145                t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
 146                     getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
 147                t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
 148                     getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
 149                setAlpha((((t2 - t1) * ey) >> 16) + t1, dp); 
 150
 151                /* Advance source pointers */
 152                csax++; 
 153                sstep = (*csax >> 16);
 154                c00 += sstep;
 155                c01 += sstep;
 156                c10 += sstep;
 157                c11 += sstep;
 158                /* Advance destination pointer */
 159                dp++;
 160            }
 161            /* Advance source pointer */
 162            csay++;
 163            csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
 164            /* Advance destination pointers */
 165            dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
 166        }
 167
 168
 169    } else {
 170        csay = say;
 171
 172        for (y = 0; y < dst_rect->y; y++) {
 173            csay++;
 174            sstep = (*csay >> 16) * src->pitch;
 175            csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 176        }
 177
 178        /* Calculate sstep_jump */
 179        csax = sax; 
 180        sstep_jump = 0;
 181        for (x = 0; x < dst_rect->x; x++) {
 182            csax++; 
 183            sstep = (*csax >> 16);
 184            sstep_jump += sstep;
 185        }
 186
 187        for (y = 0 ; y < dst_rect->h ; y++) {
 188            sp = csp + sstep_jump;
 189            csax = sax + dst_rect->x;
 190
 191            for (x = 0; x < dst_rect->w; x++) {
 192
 193                /* Draw */
 194                *dp = *sp;
 195
 196                /* Advance source pointers */
 197                csax++;
 198                sstep = (*csax >> 16);
 199                sp += sstep;
 200
 201                /* Advance destination pointer */
 202                dp++;
 203            }
 204            /* Advance source pointers */
 205            csay++;
 206            sstep = (*csay >> 16) * src->pitch;
 207            csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
 208
 209            /* Advance destination pointer */
 210            dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
 211        }
 212    }
 213
 214    g_free(sax);
 215    g_free(say);
 216}
 217
 218#undef SDL_TYPE
 219
 220