Commit c18a2c360e3100bbd71162cf922dcd8c429a8b71

Authored by Stefano Stabellini
Committed by Anthony Liguori
1 parent 14899cdf

sdl zooming

Hi all,
this patch implements zooming capabilities for the sdl interface.
A new sdl_zoom_blit function is added that is able to scale and blit a
portion of a surface into another.
This way we can enable SDL_RESIZABLE and have a real_screen surface with
a different size than the guest surface and let sdl_zoom_blit take care
of the problem.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Makefile
@@ -165,7 +165,7 @@ OBJS+=$(addprefix audio/, $(AUDIO_OBJS)) @@ -165,7 +165,7 @@ OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
165 165
166 OBJS+=keymaps.o 166 OBJS+=keymaps.o
167 ifdef CONFIG_SDL 167 ifdef CONFIG_SDL
168 -OBJS+=sdl.o x_keymap.o 168 +OBJS+=sdl.o sdl_zoom.o x_keymap.o
169 endif 169 endif
170 ifdef CONFIG_CURSES 170 ifdef CONFIG_CURSES
171 OBJS+=curses.o 171 OBJS+=curses.o
@@ -209,7 +209,9 @@ cocoa.o: cocoa.m @@ -209,7 +209,9 @@ cocoa.o: cocoa.m
209 209
210 keymaps.o: keymaps.c keymaps.h 210 keymaps.o: keymaps.c keymaps.h
211 211
212 -sdl.o: sdl.c keymaps.h sdl_keysym.h 212 +sdl_zoom.o: sdl_zoom.c sdl_zoom.h sdl_zoom_template.h
  213 +
  214 +sdl.o: sdl.c keymaps.h sdl_keysym.h sdl_zoom.h
213 215
214 sdl.o audio/sdlaudio.o baum.o: CFLAGS += $(SDL_CFLAGS) 216 sdl.o audio/sdlaudio.o baum.o: CFLAGS += $(SDL_CFLAGS)
215 217
console.h
@@ -75,6 +75,7 @@ void kbd_put_keysym(int keysym); @@ -75,6 +75,7 @@ void kbd_put_keysym(int keysym);
75 75
76 #define QEMU_BIG_ENDIAN_FLAG 0x01 76 #define QEMU_BIG_ENDIAN_FLAG 0x01
77 #define QEMU_ALLOCATED_FLAG 0x02 77 #define QEMU_ALLOCATED_FLAG 0x02
  78 +#define QEMU_REALPIXELS_FLAG 0x04
78 79
79 struct PixelFormat { 80 struct PixelFormat {
80 uint8_t bits_per_pixel; 81 uint8_t bits_per_pixel;
@@ -172,7 +173,8 @@ static inline int is_surface_bgr(DisplaySurface *surface) @@ -172,7 +173,8 @@ static inline int is_surface_bgr(DisplaySurface *surface)
172 173
173 static inline int is_buffer_shared(DisplaySurface *surface) 174 static inline int is_buffer_shared(DisplaySurface *surface)
174 { 175 {
175 - return (!(surface->flags & QEMU_ALLOCATED_FLAG)); 176 + return (!(surface->flags & QEMU_ALLOCATED_FLAG) &&
  177 + !(surface->flags & QEMU_REALPIXELS_FLAG));
176 } 178 }
177 179
178 static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) 180 static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
@@ -32,6 +32,7 @@ @@ -32,6 +32,7 @@
32 #include "console.h" 32 #include "console.h"
33 #include "sysemu.h" 33 #include "sysemu.h"
34 #include "x_keymap.h" 34 #include "x_keymap.h"
  35 +#include "sdl_zoom.h"
35 36
36 static DisplayChangeListener *dcl; 37 static DisplayChangeListener *dcl;
37 static SDL_Surface *real_screen; 38 static SDL_Surface *real_screen;
@@ -54,20 +55,29 @@ static int guest_cursor = 0; @@ -54,20 +55,29 @@ static int guest_cursor = 0;
54 static int guest_x, guest_y; 55 static int guest_x, guest_y;
55 static SDL_Cursor *guest_sprite = 0; 56 static SDL_Cursor *guest_sprite = 0;
56 static uint8_t allocator; 57 static uint8_t allocator;
57 -static uint8_t hostbpp; 58 +static SDL_PixelFormat host_format;
  59 +static int scaling_active = 0;
58 60
59 static void sdl_update(DisplayState *ds, int x, int y, int w, int h) 61 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
60 { 62 {
61 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); 63 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
  64 + SDL_Rect rec;
  65 + rec.x = x;
  66 + rec.y = y;
  67 + rec.w = w;
  68 + rec.h = h;
  69 +
62 if (guest_screen) { 70 if (guest_screen) {
63 - SDL_Rect rec;  
64 - rec.x = x;  
65 - rec.y = y;  
66 - rec.w = w;  
67 - rec.h = h;  
68 - SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);  
69 - }  
70 - SDL_UpdateRect(real_screen, x, y, w, h); 71 + if (!scaling_active) {
  72 + SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
  73 + } else {
  74 + if (sdl_zoom_blit(guest_screen, real_screen, SMOOTHING_ON, &rec) < 0) {
  75 + fprintf(stderr, "Zoom blit failed\n");
  76 + exit(1);
  77 + }
  78 + }
  79 + }
  80 + SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
71 } 81 }
72 82
73 static void sdl_setdata(DisplayState *ds) 83 static void sdl_setdata(DisplayState *ds)
@@ -92,7 +102,7 @@ static void do_sdl_resize(int new_width, int new_height, int bpp) @@ -92,7 +102,7 @@ static void do_sdl_resize(int new_width, int new_height, int bpp)
92 102
93 // printf("resizing to %d %d\n", w, h); 103 // printf("resizing to %d %d\n", w, h);
94 104
95 - flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; 105 + flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE;
96 if (gui_fullscreen) 106 if (gui_fullscreen)
97 flags |= SDL_FULLSCREEN; 107 flags |= SDL_FULLSCREEN;
98 if (gui_noframe) 108 if (gui_noframe)
@@ -110,7 +120,10 @@ static void do_sdl_resize(int new_width, int new_height, int bpp) @@ -110,7 +120,10 @@ static void do_sdl_resize(int new_width, int new_height, int bpp)
110 static void sdl_resize(DisplayState *ds) 120 static void sdl_resize(DisplayState *ds)
111 { 121 {
112 if (!allocator) { 122 if (!allocator) {
113 - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); 123 + if (!scaling_active)
  124 + do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
  125 + else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds))
  126 + do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds));
114 sdl_setdata(ds); 127 sdl_setdata(ds);
115 } else { 128 } else {
116 if (guest_screen != NULL) { 129 if (guest_screen != NULL) {
@@ -163,8 +176,26 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height) @@ -163,8 +176,26 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
163 176
164 surface->width = width; 177 surface->width = width;
165 surface->height = height; 178 surface->height = height;
  179 +
  180 + if (scaling_active) {
  181 + if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
  182 + surface->linesize = width * 4;
  183 + surface->pf = qemu_default_pixelformat(32);
  184 + } else {
  185 + surface->linesize = width * host_format.BytesPerPixel;
  186 + surface->pf = sdl_to_qemu_pixelformat(&host_format);
  187 + }
  188 +#ifdef WORDS_BIGENDIAN
  189 + surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
  190 +#else
  191 + surface->flags = QEMU_ALLOCATED_FLAG;
  192 +#endif
  193 + surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
  194 +
  195 + return surface;
  196 + }
166 197
167 - if (hostbpp == 16) 198 + if (host_format.BitsPerPixel == 16)
168 do_sdl_resize(width, height, 16); 199 do_sdl_resize(width, height, 16);
169 else 200 else
170 do_sdl_resize(width, height, 32); 201 do_sdl_resize(width, height, 32);
@@ -174,9 +205,9 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height) @@ -174,9 +205,9 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
174 surface->data = real_screen->pixels; 205 surface->data = real_screen->pixels;
175 206
176 #ifdef WORDS_BIGENDIAN 207 #ifdef WORDS_BIGENDIAN
177 - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; 208 + surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
178 #else 209 #else
179 - surface->flags = QEMU_ALLOCATED_FLAG; 210 + surface->flags = QEMU_REALPIXELS_FLAG;
180 #endif 211 #endif
181 allocator = 1; 212 allocator = 1;
182 213
@@ -188,6 +219,9 @@ static void sdl_free_displaysurface(DisplaySurface *surface) @@ -188,6 +219,9 @@ static void sdl_free_displaysurface(DisplaySurface *surface)
188 allocator = 0; 219 allocator = 0;
189 if (surface == NULL) 220 if (surface == NULL)
190 return; 221 return;
  222 +
  223 + if (surface->flags & QEMU_ALLOCATED_FLAG)
  224 + qemu_free(surface->data);
191 qemu_free(surface); 225 qemu_free(surface);
192 } 226 }
193 227
@@ -482,8 +516,8 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state @@ -482,8 +516,8 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
482 static void toggle_full_screen(DisplayState *ds) 516 static void toggle_full_screen(DisplayState *ds)
483 { 517 {
484 gui_fullscreen = !gui_fullscreen; 518 gui_fullscreen = !gui_fullscreen;
485 - do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);  
486 if (gui_fullscreen) { 519 if (gui_fullscreen) {
  520 + scaling_active = 0;
487 gui_saved_grab = gui_grab; 521 gui_saved_grab = gui_grab;
488 sdl_grab_start(); 522 sdl_grab_start();
489 } else { 523 } else {
@@ -675,6 +709,18 @@ static void sdl_refresh(DisplayState *ds) @@ -675,6 +709,18 @@ static void sdl_refresh(DisplayState *ds)
675 } 709 }
676 } 710 }
677 break; 711 break;
  712 + case SDL_VIDEORESIZE:
  713 + {
  714 + SDL_ResizeEvent *rev = &ev->resize;
  715 + int bpp = real_screen->format->BitsPerPixel;
  716 + if (bpp != 16 && bpp != 32)
  717 + bpp = 32;
  718 + do_sdl_resize(rev->w, rev->h, bpp);
  719 + scaling_active = 1;
  720 + vga_hw_invalidate();
  721 + vga_hw_update();
  722 + break;
  723 + }
678 default: 724 default:
679 break; 725 break;
680 } 726 }
@@ -783,7 +829,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) @@ -783,7 +829,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
783 exit(1); 829 exit(1);
784 } 830 }
785 vi = SDL_GetVideoInfo(); 831 vi = SDL_GetVideoInfo();
786 - hostbpp = vi->vfmt->BitsPerPixel; 832 + host_format = *(vi->vfmt);
787 833
788 dcl = qemu_mallocz(sizeof(DisplayChangeListener)); 834 dcl = qemu_mallocz(sizeof(DisplayChangeListener));
789 dcl->dpy_update = sdl_update; 835 dcl->dpy_update = sdl_update;
sdl_zoom.c 0 โ†’ 100644
  1 +/*
  2 + * SDL_zoom - 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 +#include "sdl_zoom.h"
  15 +#include "osdep.h"
  16 +#include <stdint.h>
  17 +
  18 +static int sdl_zoom_rgb16(SDL_Surface *src, SDL_Surface *dst, int smooth,
  19 + SDL_Rect *dst_rect);
  20 +static int sdl_zoom_rgb32(SDL_Surface *src, SDL_Surface *dst, int smooth,
  21 + SDL_Rect *dst_rect);
  22 +
  23 +#define BPP 32
  24 +#include "sdl_zoom_template.h"
  25 +#undef BPP
  26 +#define BPP 16
  27 +#include "sdl_zoom_template.h"
  28 +#undef BPP
  29 +
  30 +int sdl_zoom_blit(SDL_Surface *src_sfc, SDL_Surface *dst_sfc, int smooth,
  31 + SDL_Rect *in_rect)
  32 +{
  33 + SDL_Rect zoom, src_rect;
  34 + int extra;
  35 +
  36 + /* Grow the size of the modified rectangle to avoid edge artefacts */
  37 + src_rect.x = (in_rect->x > 0) ? (in_rect->x - 1) : 0;
  38 + src_rect.y = (in_rect->y > 0) ? (in_rect->y - 1) : 0;
  39 +
  40 + src_rect.w = in_rect->w + 1;
  41 + if (src_rect.x + src_rect.w > src_sfc->w)
  42 + src_rect.w = src_sfc->w - src_rect.x;
  43 +
  44 + src_rect.h = in_rect->h + 1;
  45 + if (src_rect.y + src_rect.h > src_sfc->h)
  46 + src_rect.h = src_sfc->h - src_rect.y;
  47 +
  48 + /* (x,y) : round down */
  49 + zoom.x = (int)(((float)(src_rect.x * dst_sfc->w)) / (float)(src_sfc->w));
  50 + zoom.y = (int)(((float)(src_rect.y * dst_sfc->h)) / (float)(src_sfc->h));
  51 +
  52 + /* (w,h) : round up */
  53 + zoom.w = (int)( ((double)((src_rect.w * dst_sfc->w) + (src_sfc->w - 1))) /
  54 + (double)(src_sfc->w));
  55 +
  56 + zoom.h = (int)( ((double)((src_rect.h * dst_sfc->h) + (src_sfc->h - 1))) /
  57 + (double)(src_sfc->h));
  58 +
  59 + /* Account for any (x,y) rounding by adding one-source-pixel's worth
  60 + * of destination pixels and then edge checking.
  61 + */
  62 +
  63 + extra = ((dst_sfc->w-1) / src_sfc->w) + 1;
  64 +
  65 + if ((zoom.x + zoom.w) < (dst_sfc->w - extra))
  66 + zoom.w += extra;
  67 + else
  68 + zoom.w = dst_sfc->w - zoom.x;
  69 +
  70 + extra = ((dst_sfc->h-1) / src_sfc->h) + 1;
  71 +
  72 + if ((zoom.y + zoom.h) < (dst_sfc->h - extra))
  73 + zoom.h += extra;
  74 + else
  75 + zoom.h = dst_sfc->h - zoom.y;
  76 +
  77 + /* The rectangle (zoom.x, zoom.y, zoom.w, zoom.h) is the area on the
  78 + * destination surface that needs to be updated.
  79 + */
  80 + if (src_sfc->format->BitsPerPixel == 32)
  81 + sdl_zoom_rgb32(src_sfc, dst_sfc, smooth, &zoom);
  82 + else if (src_sfc->format->BitsPerPixel == 16)
  83 + sdl_zoom_rgb16(src_sfc, dst_sfc, smooth, &zoom);
  84 + else {
  85 + fprintf(stderr, "pixel format not supported\n");
  86 + return -1;
  87 + }
  88 +
  89 + /* Return the rectangle of the update to the caller */
  90 + *in_rect = zoom;
  91 +
  92 + return 0;
  93 +}
  94 +
sdl_zoom.h 0 โ†’ 100644
  1 +/*
  2 + * SDL_zoom - 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 +#ifndef _SDL_zoom_h
  15 +#define _SDL_zoom_h
  16 +
  17 +#include <SDL/SDL.h>
  18 +
  19 +#define SMOOTHING_OFF 0
  20 +#define SMOOTHING_ON 1
  21 +
  22 +int sdl_zoom_blit(SDL_Surface *src_sfc, SDL_Surface *dst_sfc,
  23 + int smooth, SDL_Rect *src_rect);
  24 +
  25 +#endif /* _SDL_zoom_h */
sdl_zoom_template.h 0 โ†’ 100644
  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 +
  54 +static int 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 + if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
  75 + return (-1);
  76 + }
  77 + if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
  78 + free(sax);
  79 + return (-1);
  80 + }
  81 +
  82 + sp = csp = (SDL_TYPE *) src->pixels;
  83 + dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
  84 + dst_rect->x * dst->format->BytesPerPixel);
  85 +
  86 + csx = 0;
  87 + csax = sax;
  88 + for (x = 0; x <= dst->w; x++) {
  89 + *csax = csx;
  90 + csax++;
  91 + csx &= 0xffff;
  92 + csx += sx;
  93 + }
  94 + csy = 0;
  95 + csay = say;
  96 + for (y = 0; y <= dst->h; y++) {
  97 + *csay = csy;
  98 + csay++;
  99 + csy &= 0xffff;
  100 + csy += sy;
  101 + }
  102 +
  103 + d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
  104 +
  105 + if (smooth) {
  106 + csay = say;
  107 + for (y = 0; y < dst_rect->y; y++) {
  108 + csay++;
  109 + sstep = (*csay >> 16) * src->pitch;
  110 + csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  111 + }
  112 +
  113 + /* Calculate sstep_jump */
  114 + csax = sax;
  115 + sstep_jump = 0;
  116 + for (x = 0; x < dst_rect->x; x++) {
  117 + csax++;
  118 + sstep = (*csax >> 16);
  119 + sstep_jump += sstep;
  120 + }
  121 +
  122 + for (y = 0; y < dst_rect->h ; y++) {
  123 + /* Setup colour source pointers */
  124 + c00 = csp + sstep_jump;
  125 + c01 = c00 + 1;
  126 + c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
  127 + c11 = c10 + 1;
  128 + csax = sax + dst_rect->x;
  129 +
  130 + for (x = 0; x < dst_rect->w; x++) {
  131 +
  132 + /* Interpolate colours */
  133 + ex = (*csax & 0xffff);
  134 + ey = (*csay & 0xffff);
  135 + t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
  136 + getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
  137 + t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
  138 + getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
  139 + setRed((((t2 - t1) * ey) >> 16) + t1, dp);
  140 + t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
  141 + getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
  142 + t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
  143 + getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
  144 + setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
  145 + t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
  146 + getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
  147 + t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
  148 + getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
  149 + setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
  150 + t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
  151 + getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
  152 + t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
  153 + getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
  154 + setAlpha((((t2 - t1) * ey) >> 16) + t1, dp);
  155 +
  156 + /* Advance source pointers */
  157 + csax++;
  158 + sstep = (*csax >> 16);
  159 + c00 += sstep;
  160 + c01 += sstep;
  161 + c10 += sstep;
  162 + c11 += sstep;
  163 + /* Advance destination pointer */
  164 + dp++;
  165 + }
  166 + /* Advance source pointer */
  167 + csay++;
  168 + csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
  169 + /* Advance destination pointers */
  170 + dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
  171 + }
  172 +
  173 +
  174 + } else {
  175 + csay = say;
  176 +
  177 + for (y = 0; y < dst_rect->y; y++) {
  178 + csay++;
  179 + sstep = (*csay >> 16) * src->pitch;
  180 + csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  181 + }
  182 +
  183 + /* Calculate sstep_jump */
  184 + csax = sax;
  185 + sstep_jump = 0;
  186 + for (x = 0; x < dst_rect->x; x++) {
  187 + csax++;
  188 + sstep = (*csax >> 16);
  189 + sstep_jump += sstep;
  190 + }
  191 +
  192 + for (y = 0 ; y < dst_rect->h ; y++) {
  193 + sp = csp + sstep_jump;
  194 + csax = sax + dst_rect->x;
  195 +
  196 + for (x = 0; x < dst_rect->w; x++) {
  197 +
  198 + /* Draw */
  199 + *dp = *sp;
  200 +
  201 + /* Advance source pointers */
  202 + csax++;
  203 + sstep = (*csax >> 16);
  204 + sp += sstep;
  205 +
  206 + /* Advance destination pointer */
  207 + dp++;
  208 + }
  209 + /* Advance source pointers */
  210 + csay++;
  211 + sstep = (*csay >> 16) * src->pitch;
  212 + csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  213 +
  214 + /* Advance destination pointer */
  215 + dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
  216 + }
  217 + }
  218 +
  219 + free(sax);
  220 + free(say);
  221 + return (0);
  222 +}
  223 +
  224 +#undef SDL_TYPE
  225 +