Commit c18a2c360e3100bbd71162cf922dcd8c429a8b71
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>
Showing
6 changed files
with
413 additions
and
19 deletions
Makefile
| ... | ... | @@ -165,7 +165,7 @@ OBJS+=$(addprefix audio/, $(AUDIO_OBJS)) |
| 165 | 165 | |
| 166 | 166 | OBJS+=keymaps.o |
| 167 | 167 | ifdef CONFIG_SDL |
| 168 | -OBJS+=sdl.o x_keymap.o | |
| 168 | +OBJS+=sdl.o sdl_zoom.o x_keymap.o | |
| 169 | 169 | endif |
| 170 | 170 | ifdef CONFIG_CURSES |
| 171 | 171 | OBJS+=curses.o |
| ... | ... | @@ -209,7 +209,9 @@ cocoa.o: cocoa.m |
| 209 | 209 | |
| 210 | 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 | 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 | 75 | |
| 76 | 76 | #define QEMU_BIG_ENDIAN_FLAG 0x01 |
| 77 | 77 | #define QEMU_ALLOCATED_FLAG 0x02 |
| 78 | +#define QEMU_REALPIXELS_FLAG 0x04 | |
| 78 | 79 | |
| 79 | 80 | struct PixelFormat { |
| 80 | 81 | uint8_t bits_per_pixel; |
| ... | ... | @@ -172,7 +173,8 @@ static inline int is_surface_bgr(DisplaySurface *surface) |
| 172 | 173 | |
| 173 | 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 | 180 | static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) | ... | ... |
sdl.c
| ... | ... | @@ -32,6 +32,7 @@ |
| 32 | 32 | #include "console.h" |
| 33 | 33 | #include "sysemu.h" |
| 34 | 34 | #include "x_keymap.h" |
| 35 | +#include "sdl_zoom.h" | |
| 35 | 36 | |
| 36 | 37 | static DisplayChangeListener *dcl; |
| 37 | 38 | static SDL_Surface *real_screen; |
| ... | ... | @@ -54,20 +55,29 @@ static int guest_cursor = 0; |
| 54 | 55 | static int guest_x, guest_y; |
| 55 | 56 | static SDL_Cursor *guest_sprite = 0; |
| 56 | 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 | 61 | static void sdl_update(DisplayState *ds, int x, int y, int w, int h) |
| 60 | 62 | { |
| 61 | 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 | 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 | 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 | 102 | |
| 93 | 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 | 106 | if (gui_fullscreen) |
| 97 | 107 | flags |= SDL_FULLSCREEN; |
| 98 | 108 | if (gui_noframe) |
| ... | ... | @@ -110,7 +120,10 @@ static void do_sdl_resize(int new_width, int new_height, int bpp) |
| 110 | 120 | static void sdl_resize(DisplayState *ds) |
| 111 | 121 | { |
| 112 | 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 | 127 | sdl_setdata(ds); |
| 115 | 128 | } else { |
| 116 | 129 | if (guest_screen != NULL) { |
| ... | ... | @@ -163,8 +176,26 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height) |
| 163 | 176 | |
| 164 | 177 | surface->width = width; |
| 165 | 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 | 199 | do_sdl_resize(width, height, 16); |
| 169 | 200 | else |
| 170 | 201 | do_sdl_resize(width, height, 32); |
| ... | ... | @@ -174,9 +205,9 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height) |
| 174 | 205 | surface->data = real_screen->pixels; |
| 175 | 206 | |
| 176 | 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 | 209 | #else |
| 179 | - surface->flags = QEMU_ALLOCATED_FLAG; | |
| 210 | + surface->flags = QEMU_REALPIXELS_FLAG; | |
| 180 | 211 | #endif |
| 181 | 212 | allocator = 1; |
| 182 | 213 | |
| ... | ... | @@ -188,6 +219,9 @@ static void sdl_free_displaysurface(DisplaySurface *surface) |
| 188 | 219 | allocator = 0; |
| 189 | 220 | if (surface == NULL) |
| 190 | 221 | return; |
| 222 | + | |
| 223 | + if (surface->flags & QEMU_ALLOCATED_FLAG) | |
| 224 | + qemu_free(surface->data); | |
| 191 | 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 | 516 | static void toggle_full_screen(DisplayState *ds) |
| 483 | 517 | { |
| 484 | 518 | gui_fullscreen = !gui_fullscreen; |
| 485 | - do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel); | |
| 486 | 519 | if (gui_fullscreen) { |
| 520 | + scaling_active = 0; | |
| 487 | 521 | gui_saved_grab = gui_grab; |
| 488 | 522 | sdl_grab_start(); |
| 489 | 523 | } else { |
| ... | ... | @@ -675,6 +709,18 @@ static void sdl_refresh(DisplayState *ds) |
| 675 | 709 | } |
| 676 | 710 | } |
| 677 | 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 | 724 | default: |
| 679 | 725 | break; |
| 680 | 726 | } |
| ... | ... | @@ -783,7 +829,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) |
| 783 | 829 | exit(1); |
| 784 | 830 | } |
| 785 | 831 | vi = SDL_GetVideoInfo(); |
| 786 | - hostbpp = vi->vfmt->BitsPerPixel; | |
| 832 | + host_format = *(vi->vfmt); | |
| 787 | 833 | |
| 788 | 834 | dcl = qemu_mallocz(sizeof(DisplayChangeListener)); |
| 789 | 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 | + | ... | ... |