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>
This commit is contained in:
parent
14899cdf3a
commit
c18a2c360e
6
Makefile
6
Makefile
@ -165,7 +165,7 @@ OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
|
|||||||
|
|
||||||
OBJS+=keymaps.o
|
OBJS+=keymaps.o
|
||||||
ifdef CONFIG_SDL
|
ifdef CONFIG_SDL
|
||||||
OBJS+=sdl.o x_keymap.o
|
OBJS+=sdl.o sdl_zoom.o x_keymap.o
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_CURSES
|
ifdef CONFIG_CURSES
|
||||||
OBJS+=curses.o
|
OBJS+=curses.o
|
||||||
@ -209,7 +209,9 @@ cocoa.o: cocoa.m
|
|||||||
|
|
||||||
keymaps.o: keymaps.c keymaps.h
|
keymaps.o: keymaps.c keymaps.h
|
||||||
|
|
||||||
sdl.o: sdl.c keymaps.h sdl_keysym.h
|
sdl_zoom.o: sdl_zoom.c sdl_zoom.h sdl_zoom_template.h
|
||||||
|
|
||||||
|
sdl.o: sdl.c keymaps.h sdl_keysym.h sdl_zoom.h
|
||||||
|
|
||||||
sdl.o audio/sdlaudio.o baum.o: CFLAGS += $(SDL_CFLAGS)
|
sdl.o audio/sdlaudio.o baum.o: CFLAGS += $(SDL_CFLAGS)
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ void kbd_put_keysym(int keysym);
|
|||||||
|
|
||||||
#define QEMU_BIG_ENDIAN_FLAG 0x01
|
#define QEMU_BIG_ENDIAN_FLAG 0x01
|
||||||
#define QEMU_ALLOCATED_FLAG 0x02
|
#define QEMU_ALLOCATED_FLAG 0x02
|
||||||
|
#define QEMU_REALPIXELS_FLAG 0x04
|
||||||
|
|
||||||
struct PixelFormat {
|
struct PixelFormat {
|
||||||
uint8_t bits_per_pixel;
|
uint8_t bits_per_pixel;
|
||||||
@ -172,7 +173,8 @@ static inline int is_surface_bgr(DisplaySurface *surface)
|
|||||||
|
|
||||||
static inline int is_buffer_shared(DisplaySurface *surface)
|
static inline int is_buffer_shared(DisplaySurface *surface)
|
||||||
{
|
{
|
||||||
return (!(surface->flags & QEMU_ALLOCATED_FLAG));
|
return (!(surface->flags & QEMU_ALLOCATED_FLAG) &&
|
||||||
|
!(surface->flags & QEMU_REALPIXELS_FLAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
|
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
|
||||||
|
78
sdl.c
78
sdl.c
@ -32,6 +32,7 @@
|
|||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "x_keymap.h"
|
#include "x_keymap.h"
|
||||||
|
#include "sdl_zoom.h"
|
||||||
|
|
||||||
static DisplayChangeListener *dcl;
|
static DisplayChangeListener *dcl;
|
||||||
static SDL_Surface *real_screen;
|
static SDL_Surface *real_screen;
|
||||||
@ -54,20 +55,29 @@ static int guest_cursor = 0;
|
|||||||
static int guest_x, guest_y;
|
static int guest_x, guest_y;
|
||||||
static SDL_Cursor *guest_sprite = 0;
|
static SDL_Cursor *guest_sprite = 0;
|
||||||
static uint8_t allocator;
|
static uint8_t allocator;
|
||||||
static uint8_t hostbpp;
|
static SDL_PixelFormat host_format;
|
||||||
|
static int scaling_active = 0;
|
||||||
|
|
||||||
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
|
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
|
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
|
||||||
|
SDL_Rect rec;
|
||||||
|
rec.x = x;
|
||||||
|
rec.y = y;
|
||||||
|
rec.w = w;
|
||||||
|
rec.h = h;
|
||||||
|
|
||||||
if (guest_screen) {
|
if (guest_screen) {
|
||||||
SDL_Rect rec;
|
if (!scaling_active) {
|
||||||
rec.x = x;
|
SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
|
||||||
rec.y = y;
|
} else {
|
||||||
rec.w = w;
|
if (sdl_zoom_blit(guest_screen, real_screen, SMOOTHING_ON, &rec) < 0) {
|
||||||
rec.h = h;
|
fprintf(stderr, "Zoom blit failed\n");
|
||||||
SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
|
exit(1);
|
||||||
}
|
}
|
||||||
SDL_UpdateRect(real_screen, x, y, w, h);
|
}
|
||||||
|
}
|
||||||
|
SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl_setdata(DisplayState *ds)
|
static void sdl_setdata(DisplayState *ds)
|
||||||
@ -92,7 +102,7 @@ static void do_sdl_resize(int new_width, int new_height, int bpp)
|
|||||||
|
|
||||||
// printf("resizing to %d %d\n", w, h);
|
// printf("resizing to %d %d\n", w, h);
|
||||||
|
|
||||||
flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
|
flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE;
|
||||||
if (gui_fullscreen)
|
if (gui_fullscreen)
|
||||||
flags |= SDL_FULLSCREEN;
|
flags |= SDL_FULLSCREEN;
|
||||||
if (gui_noframe)
|
if (gui_noframe)
|
||||||
@ -110,7 +120,10 @@ static void do_sdl_resize(int new_width, int new_height, int bpp)
|
|||||||
static void sdl_resize(DisplayState *ds)
|
static void sdl_resize(DisplayState *ds)
|
||||||
{
|
{
|
||||||
if (!allocator) {
|
if (!allocator) {
|
||||||
do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
|
if (!scaling_active)
|
||||||
|
do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
|
||||||
|
else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds))
|
||||||
|
do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds));
|
||||||
sdl_setdata(ds);
|
sdl_setdata(ds);
|
||||||
} else {
|
} else {
|
||||||
if (guest_screen != NULL) {
|
if (guest_screen != NULL) {
|
||||||
@ -163,8 +176,26 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
|
|||||||
|
|
||||||
surface->width = width;
|
surface->width = width;
|
||||||
surface->height = height;
|
surface->height = height;
|
||||||
|
|
||||||
|
if (scaling_active) {
|
||||||
|
if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
|
||||||
|
surface->linesize = width * 4;
|
||||||
|
surface->pf = qemu_default_pixelformat(32);
|
||||||
|
} else {
|
||||||
|
surface->linesize = width * host_format.BytesPerPixel;
|
||||||
|
surface->pf = sdl_to_qemu_pixelformat(&host_format);
|
||||||
|
}
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
|
||||||
|
#else
|
||||||
|
surface->flags = QEMU_ALLOCATED_FLAG;
|
||||||
|
#endif
|
||||||
|
surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
|
||||||
|
|
||||||
if (hostbpp == 16)
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host_format.BitsPerPixel == 16)
|
||||||
do_sdl_resize(width, height, 16);
|
do_sdl_resize(width, height, 16);
|
||||||
else
|
else
|
||||||
do_sdl_resize(width, height, 32);
|
do_sdl_resize(width, height, 32);
|
||||||
@ -174,9 +205,9 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
|
|||||||
surface->data = real_screen->pixels;
|
surface->data = real_screen->pixels;
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
|
surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
|
||||||
#else
|
#else
|
||||||
surface->flags = QEMU_ALLOCATED_FLAG;
|
surface->flags = QEMU_REALPIXELS_FLAG;
|
||||||
#endif
|
#endif
|
||||||
allocator = 1;
|
allocator = 1;
|
||||||
|
|
||||||
@ -188,6 +219,9 @@ static void sdl_free_displaysurface(DisplaySurface *surface)
|
|||||||
allocator = 0;
|
allocator = 0;
|
||||||
if (surface == NULL)
|
if (surface == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (surface->flags & QEMU_ALLOCATED_FLAG)
|
||||||
|
qemu_free(surface->data);
|
||||||
qemu_free(surface);
|
qemu_free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,8 +516,8 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
|
|||||||
static void toggle_full_screen(DisplayState *ds)
|
static void toggle_full_screen(DisplayState *ds)
|
||||||
{
|
{
|
||||||
gui_fullscreen = !gui_fullscreen;
|
gui_fullscreen = !gui_fullscreen;
|
||||||
do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
|
|
||||||
if (gui_fullscreen) {
|
if (gui_fullscreen) {
|
||||||
|
scaling_active = 0;
|
||||||
gui_saved_grab = gui_grab;
|
gui_saved_grab = gui_grab;
|
||||||
sdl_grab_start();
|
sdl_grab_start();
|
||||||
} else {
|
} else {
|
||||||
@ -675,6 +709,18 @@ static void sdl_refresh(DisplayState *ds)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SDL_VIDEORESIZE:
|
||||||
|
{
|
||||||
|
SDL_ResizeEvent *rev = &ev->resize;
|
||||||
|
int bpp = real_screen->format->BitsPerPixel;
|
||||||
|
if (bpp != 16 && bpp != 32)
|
||||||
|
bpp = 32;
|
||||||
|
do_sdl_resize(rev->w, rev->h, bpp);
|
||||||
|
scaling_active = 1;
|
||||||
|
vga_hw_invalidate();
|
||||||
|
vga_hw_update();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -783,7 +829,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
vi = SDL_GetVideoInfo();
|
vi = SDL_GetVideoInfo();
|
||||||
hostbpp = vi->vfmt->BitsPerPixel;
|
host_format = *(vi->vfmt);
|
||||||
|
|
||||||
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
|
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
|
||||||
dcl->dpy_update = sdl_update;
|
dcl->dpy_update = sdl_update;
|
||||||
|
94
sdl_zoom.c
Normal file
94
sdl_zoom.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* SDL_zoom - surface scaling
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Citrix Systems, Inc.
|
||||||
|
*
|
||||||
|
* Derived from: SDL_rotozoom, LGPL (c) A. Schiffler from the SDL_gfx library.
|
||||||
|
* Modifications by Stefano Stabellini.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sdl_zoom.h"
|
||||||
|
#include "osdep.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static int sdl_zoom_rgb16(SDL_Surface *src, SDL_Surface *dst, int smooth,
|
||||||
|
SDL_Rect *dst_rect);
|
||||||
|
static int sdl_zoom_rgb32(SDL_Surface *src, SDL_Surface *dst, int smooth,
|
||||||
|
SDL_Rect *dst_rect);
|
||||||
|
|
||||||
|
#define BPP 32
|
||||||
|
#include "sdl_zoom_template.h"
|
||||||
|
#undef BPP
|
||||||
|
#define BPP 16
|
||||||
|
#include "sdl_zoom_template.h"
|
||||||
|
#undef BPP
|
||||||
|
|
||||||
|
int sdl_zoom_blit(SDL_Surface *src_sfc, SDL_Surface *dst_sfc, int smooth,
|
||||||
|
SDL_Rect *in_rect)
|
||||||
|
{
|
||||||
|
SDL_Rect zoom, src_rect;
|
||||||
|
int extra;
|
||||||
|
|
||||||
|
/* Grow the size of the modified rectangle to avoid edge artefacts */
|
||||||
|
src_rect.x = (in_rect->x > 0) ? (in_rect->x - 1) : 0;
|
||||||
|
src_rect.y = (in_rect->y > 0) ? (in_rect->y - 1) : 0;
|
||||||
|
|
||||||
|
src_rect.w = in_rect->w + 1;
|
||||||
|
if (src_rect.x + src_rect.w > src_sfc->w)
|
||||||
|
src_rect.w = src_sfc->w - src_rect.x;
|
||||||
|
|
||||||
|
src_rect.h = in_rect->h + 1;
|
||||||
|
if (src_rect.y + src_rect.h > src_sfc->h)
|
||||||
|
src_rect.h = src_sfc->h - src_rect.y;
|
||||||
|
|
||||||
|
/* (x,y) : round down */
|
||||||
|
zoom.x = (int)(((float)(src_rect.x * dst_sfc->w)) / (float)(src_sfc->w));
|
||||||
|
zoom.y = (int)(((float)(src_rect.y * dst_sfc->h)) / (float)(src_sfc->h));
|
||||||
|
|
||||||
|
/* (w,h) : round up */
|
||||||
|
zoom.w = (int)( ((double)((src_rect.w * dst_sfc->w) + (src_sfc->w - 1))) /
|
||||||
|
(double)(src_sfc->w));
|
||||||
|
|
||||||
|
zoom.h = (int)( ((double)((src_rect.h * dst_sfc->h) + (src_sfc->h - 1))) /
|
||||||
|
(double)(src_sfc->h));
|
||||||
|
|
||||||
|
/* Account for any (x,y) rounding by adding one-source-pixel's worth
|
||||||
|
* of destination pixels and then edge checking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extra = ((dst_sfc->w-1) / src_sfc->w) + 1;
|
||||||
|
|
||||||
|
if ((zoom.x + zoom.w) < (dst_sfc->w - extra))
|
||||||
|
zoom.w += extra;
|
||||||
|
else
|
||||||
|
zoom.w = dst_sfc->w - zoom.x;
|
||||||
|
|
||||||
|
extra = ((dst_sfc->h-1) / src_sfc->h) + 1;
|
||||||
|
|
||||||
|
if ((zoom.y + zoom.h) < (dst_sfc->h - extra))
|
||||||
|
zoom.h += extra;
|
||||||
|
else
|
||||||
|
zoom.h = dst_sfc->h - zoom.y;
|
||||||
|
|
||||||
|
/* The rectangle (zoom.x, zoom.y, zoom.w, zoom.h) is the area on the
|
||||||
|
* destination surface that needs to be updated.
|
||||||
|
*/
|
||||||
|
if (src_sfc->format->BitsPerPixel == 32)
|
||||||
|
sdl_zoom_rgb32(src_sfc, dst_sfc, smooth, &zoom);
|
||||||
|
else if (src_sfc->format->BitsPerPixel == 16)
|
||||||
|
sdl_zoom_rgb16(src_sfc, dst_sfc, smooth, &zoom);
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "pixel format not supported\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the rectangle of the update to the caller */
|
||||||
|
*in_rect = zoom;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
25
sdl_zoom.h
Normal file
25
sdl_zoom.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* SDL_zoom - surface scaling
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Citrix Systems, Inc.
|
||||||
|
*
|
||||||
|
* Derived from: SDL_rotozoom, LGPL (c) A. Schiffler from the SDL_gfx library.
|
||||||
|
* Modifications by Stefano Stabellini.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SDL_zoom_h
|
||||||
|
#define _SDL_zoom_h
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
|
||||||
|
#define SMOOTHING_OFF 0
|
||||||
|
#define SMOOTHING_ON 1
|
||||||
|
|
||||||
|
int sdl_zoom_blit(SDL_Surface *src_sfc, SDL_Surface *dst_sfc,
|
||||||
|
int smooth, SDL_Rect *src_rect);
|
||||||
|
|
||||||
|
#endif /* _SDL_zoom_h */
|
225
sdl_zoom_template.h
Normal file
225
sdl_zoom_template.h
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* SDL_zoom_template - surface scaling
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Citrix Systems, Inc.
|
||||||
|
*
|
||||||
|
* Derived from: SDL_rotozoom, LGPL (c) A. Schiffler from the SDL_gfx library.
|
||||||
|
* Modifications by Stefano Stabellini.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if BPP == 16
|
||||||
|
#define SDL_TYPE Uint16
|
||||||
|
#elif BPP == 32
|
||||||
|
#define SDL_TYPE Uint32
|
||||||
|
#else
|
||||||
|
#error unsupport depth
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple helper functions to make the code looks nicer
|
||||||
|
*
|
||||||
|
* Assume spf = source SDL_PixelFormat
|
||||||
|
* dpf = dest SDL_PixelFormat
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define getRed(color) (((color) & spf->Rmask) >> spf->Rshift)
|
||||||
|
#define getGreen(color) (((color) & spf->Gmask) >> spf->Gshift)
|
||||||
|
#define getBlue(color) (((color) & spf->Bmask) >> spf->Bshift)
|
||||||
|
#define getAlpha(color) (((color) & spf->Amask) >> spf->Ashift)
|
||||||
|
|
||||||
|
#define setRed(r, pcolor) do { \
|
||||||
|
*pcolor = ((*pcolor) & (~(dpf->Rmask))) + \
|
||||||
|
(((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define setGreen(g, pcolor) do { \
|
||||||
|
*pcolor = ((*pcolor) & (~(dpf->Gmask))) + \
|
||||||
|
(((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define setBlue(b, pcolor) do { \
|
||||||
|
*pcolor = ((*pcolor) & (~(dpf->Bmask))) + \
|
||||||
|
(((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define setAlpha(a, pcolor) do { \
|
||||||
|
*pcolor = ((*pcolor) & (~(dpf->Amask))) + \
|
||||||
|
(((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
static int glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth,
|
||||||
|
SDL_Rect *dst_rect)
|
||||||
|
{
|
||||||
|
int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, sstep_jump;
|
||||||
|
SDL_TYPE *c00, *c01, *c10, *c11, *sp, *csp, *dp;
|
||||||
|
int d_gap;
|
||||||
|
SDL_PixelFormat *spf = src->format;
|
||||||
|
SDL_PixelFormat *dpf = dst->format;
|
||||||
|
|
||||||
|
if (smooth) {
|
||||||
|
/* For interpolation: assume source dimension is one pixel.
|
||||||
|
* Smaller here to avoid overflow on right and bottom edge.
|
||||||
|
*/
|
||||||
|
sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
|
||||||
|
sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
|
||||||
|
} else {
|
||||||
|
sx = (int) (65536.0 * (float) src->w / (float) dst->w);
|
||||||
|
sy = (int) (65536.0 * (float) src->h / (float) dst->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
|
||||||
|
free(sax);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = csp = (SDL_TYPE *) src->pixels;
|
||||||
|
dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
|
||||||
|
dst_rect->x * dst->format->BytesPerPixel);
|
||||||
|
|
||||||
|
csx = 0;
|
||||||
|
csax = sax;
|
||||||
|
for (x = 0; x <= dst->w; x++) {
|
||||||
|
*csax = csx;
|
||||||
|
csax++;
|
||||||
|
csx &= 0xffff;
|
||||||
|
csx += sx;
|
||||||
|
}
|
||||||
|
csy = 0;
|
||||||
|
csay = say;
|
||||||
|
for (y = 0; y <= dst->h; y++) {
|
||||||
|
*csay = csy;
|
||||||
|
csay++;
|
||||||
|
csy &= 0xffff;
|
||||||
|
csy += sy;
|
||||||
|
}
|
||||||
|
|
||||||
|
d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
|
||||||
|
|
||||||
|
if (smooth) {
|
||||||
|
csay = say;
|
||||||
|
for (y = 0; y < dst_rect->y; y++) {
|
||||||
|
csay++;
|
||||||
|
sstep = (*csay >> 16) * src->pitch;
|
||||||
|
csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate sstep_jump */
|
||||||
|
csax = sax;
|
||||||
|
sstep_jump = 0;
|
||||||
|
for (x = 0; x < dst_rect->x; x++) {
|
||||||
|
csax++;
|
||||||
|
sstep = (*csax >> 16);
|
||||||
|
sstep_jump += sstep;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y = 0; y < dst_rect->h ; y++) {
|
||||||
|
/* Setup colour source pointers */
|
||||||
|
c00 = csp + sstep_jump;
|
||||||
|
c01 = c00 + 1;
|
||||||
|
c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
|
||||||
|
c11 = c10 + 1;
|
||||||
|
csax = sax + dst_rect->x;
|
||||||
|
|
||||||
|
for (x = 0; x < dst_rect->w; x++) {
|
||||||
|
|
||||||
|
/* Interpolate colours */
|
||||||
|
ex = (*csax & 0xffff);
|
||||||
|
ey = (*csay & 0xffff);
|
||||||
|
t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
|
||||||
|
getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
|
||||||
|
t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
|
||||||
|
getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
|
||||||
|
setRed((((t2 - t1) * ey) >> 16) + t1, dp);
|
||||||
|
t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
|
||||||
|
getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
|
||||||
|
t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
|
||||||
|
getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
|
||||||
|
setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
|
||||||
|
t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
|
||||||
|
getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
|
||||||
|
t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
|
||||||
|
getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
|
||||||
|
setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
|
||||||
|
t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
|
||||||
|
getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
|
||||||
|
t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
|
||||||
|
getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
|
||||||
|
setAlpha((((t2 - t1) * ey) >> 16) + t1, dp);
|
||||||
|
|
||||||
|
/* Advance source pointers */
|
||||||
|
csax++;
|
||||||
|
sstep = (*csax >> 16);
|
||||||
|
c00 += sstep;
|
||||||
|
c01 += sstep;
|
||||||
|
c10 += sstep;
|
||||||
|
c11 += sstep;
|
||||||
|
/* Advance destination pointer */
|
||||||
|
dp++;
|
||||||
|
}
|
||||||
|
/* Advance source pointer */
|
||||||
|
csay++;
|
||||||
|
csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
|
||||||
|
/* Advance destination pointers */
|
||||||
|
dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
csay = say;
|
||||||
|
|
||||||
|
for (y = 0; y < dst_rect->y; y++) {
|
||||||
|
csay++;
|
||||||
|
sstep = (*csay >> 16) * src->pitch;
|
||||||
|
csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate sstep_jump */
|
||||||
|
csax = sax;
|
||||||
|
sstep_jump = 0;
|
||||||
|
for (x = 0; x < dst_rect->x; x++) {
|
||||||
|
csax++;
|
||||||
|
sstep = (*csax >> 16);
|
||||||
|
sstep_jump += sstep;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y = 0 ; y < dst_rect->h ; y++) {
|
||||||
|
sp = csp + sstep_jump;
|
||||||
|
csax = sax + dst_rect->x;
|
||||||
|
|
||||||
|
for (x = 0; x < dst_rect->w; x++) {
|
||||||
|
|
||||||
|
/* Draw */
|
||||||
|
*dp = *sp;
|
||||||
|
|
||||||
|
/* Advance source pointers */
|
||||||
|
csax++;
|
||||||
|
sstep = (*csax >> 16);
|
||||||
|
sp += sstep;
|
||||||
|
|
||||||
|
/* Advance destination pointer */
|
||||||
|
dp++;
|
||||||
|
}
|
||||||
|
/* Advance source pointers */
|
||||||
|
csay++;
|
||||||
|
sstep = (*csay >> 16) * src->pitch;
|
||||||
|
csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
|
||||||
|
|
||||||
|
/* Advance destination pointer */
|
||||||
|
dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sax);
|
||||||
|
free(say);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SDL_TYPE
|
||||||
|
|
Loading…
Reference in New Issue
Block a user