* [Qemu-devel] [PATCH] sdl zooming
@ 2009-06-24 10:58 Stefano Stabellini
2009-06-24 12:41 ` Anthony Liguori
2009-06-24 16:07 ` Blue Swirl
0 siblings, 2 replies; 8+ messages in thread
From: Stefano Stabellini @ 2009-06-24 10:58 UTC (permalink / raw)
To: qemu-devel@nongnu.org
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>
---
diff --git a/Makefile b/Makefile
index 781e7ed..58faff9 100644
--- a/Makefile
+++ b/Makefile
@@ -162,7 +162,7 @@ OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
OBJS+=keymaps.o
ifdef CONFIG_SDL
-OBJS+=sdl.o x_keymap.o
+OBJS+=sdl.o sdl_zoom.o x_keymap.o
endif
ifdef CONFIG_CURSES
OBJS+=curses.o
@@ -206,7 +206,9 @@ cocoa.o: cocoa.m
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: CFLAGS += $(SDL_CFLAGS)
diff --git a/console.h b/console.h
index 4172175..3518339 100644
--- a/console.h
+++ b/console.h
@@ -75,6 +75,7 @@ void kbd_put_keysym(int keysym);
#define QEMU_BIG_ENDIAN_FLAG 0x01
#define QEMU_ALLOCATED_FLAG 0x02
+#define QEMU_REALPIXELS_FLAG 0x04
struct PixelFormat {
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)
{
- 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)
diff --git a/sdl.c b/sdl.c
index 178b553..d81399e 100644
--- a/sdl.c
+++ b/sdl.c
@@ -32,6 +32,7 @@
#include "console.h"
#include "sysemu.h"
#include "x_keymap.h"
+#include "sdl_zoom.h"
static DisplayChangeListener *dcl;
static SDL_Surface *real_screen;
@@ -54,20 +55,29 @@ static int guest_cursor = 0;
static int guest_x, guest_y;
static SDL_Cursor *guest_sprite = 0;
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)
{
// 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) {
- SDL_Rect rec;
- rec.x = x;
- rec.y = y;
- rec.w = w;
- rec.h = h;
- SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
- }
- SDL_UpdateRect(real_screen, x, y, w, h);
+ if (!scaling_active) {
+ SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
+ } else {
+ if (sdl_zoom_blit(guest_screen, real_screen, SMOOTHING_ON, &rec) < 0) {
+ fprintf(stderr, "Zoom blit failed\n");
+ exit(1);
+ }
+ }
+ }
+ SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
}
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);
- flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE;
if (gui_fullscreen)
flags |= SDL_FULLSCREEN;
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)
{
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);
} else {
if (guest_screen != NULL) {
@@ -163,8 +176,26 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
surface->width = width;
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);
+
+ return surface;
+ }
- if (hostbpp == 16)
+ if (host_format.BitsPerPixel == 16)
do_sdl_resize(width, height, 16);
else
do_sdl_resize(width, height, 32);
@@ -174,9 +205,9 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
surface->data = real_screen->pixels;
#ifdef WORDS_BIGENDIAN
- surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+ surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
#else
- surface->flags = QEMU_ALLOCATED_FLAG;
+ surface->flags = QEMU_REALPIXELS_FLAG;
#endif
allocator = 1;
@@ -188,6 +219,9 @@ static void sdl_free_displaysurface(DisplaySurface *surface)
allocator = 0;
if (surface == NULL)
return;
+
+ if (surface->flags & QEMU_ALLOCATED_FLAG)
+ qemu_free(surface->data);
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)
{
gui_fullscreen = !gui_fullscreen;
- do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
if (gui_fullscreen) {
+ scaling_active = 0;
gui_saved_grab = gui_grab;
sdl_grab_start();
} else {
@@ -675,6 +709,18 @@ static void sdl_refresh(DisplayState *ds)
}
}
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:
break;
}
@@ -783,7 +829,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
exit(1);
}
vi = SDL_GetVideoInfo();
- hostbpp = vi->vfmt->BitsPerPixel;
+ host_format = *(vi->vfmt);
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
dcl->dpy_update = sdl_update;
diff --git a/sdl_zoom.c b/sdl_zoom.c
new file mode 100644
index 0000000..56d3604
--- /dev/null
+++ b/sdl_zoom.c
@@ -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;
+}
+
diff --git a/sdl_zoom.h b/sdl_zoom.h
new file mode 100644
index 0000000..33dc634
--- /dev/null
+++ b/sdl_zoom.h
@@ -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 */
diff --git a/sdl_zoom_template.h b/sdl_zoom_template.h
new file mode 100644
index 0000000..64bbca8
--- /dev/null
+++ b/sdl_zoom_template.h
@@ -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
+
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-06-24 10:58 [Qemu-devel] [PATCH] sdl zooming Stefano Stabellini
@ 2009-06-24 12:41 ` Anthony Liguori
2009-06-24 14:05 ` Stefano Stabellini
2009-06-24 16:07 ` Blue Swirl
1 sibling, 1 reply; 8+ messages in thread
From: Anthony Liguori @ 2009-06-24 12:41 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: qemu-devel@nongnu.org
Stefano Stabellini wrote:
> 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>
>
Hi Stefano,
First, really neat patch. I was looking at this recently myself. I
cannot tell quickly from looking at the code--perhaps not enough
caffeine yet this morning. Is this nearest neighbor with some sort of
smoothing mechanism on top?
In my experiences with scaling VM displays, bilinear interpolation seems
to fit the use case here well as it does best from 1.0-2.0x which is
more or less what you'll commonly see.
Bilinear interpolation can be implemented rather effectively on most
processors and is usually hardware supported too. That suggests that
using a library is the right approach to avoid maintaining
platform-specific code.
Cairo seems to be a good choice. It integrates well with SDL and is
portable to all of the platforms we care about. It's a very simple API
too for scaling. We use it in gtk-vnc and it has proven to be very good
for this task.
What do you think?
http://cairographics.org/SDL/
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-06-24 12:41 ` Anthony Liguori
@ 2009-06-24 14:05 ` Stefano Stabellini
0 siblings, 0 replies; 8+ messages in thread
From: Stefano Stabellini @ 2009-06-24 14:05 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel@nongnu.org
Anthony Liguori wrote:
> Hi Stefano,
>
> First, really neat patch.
Thank you, this time I spent a considerable amount of time in cleaning
the patch up and testing it so that it would be easier to merge.
> I was looking at this recently myself. I
> cannot tell quickly from looking at the code--perhaps not enough
> caffeine yet this morning. Is this nearest neighbor with some sort of
> smoothing mechanism on top?
The smooth==0 is a nearest neighbor algorithm, while the smooth==1 is a
bilinear interpolation.
>
> In my experiences with scaling VM displays, bilinear interpolation seems
> to fit the use case here well as it does best from 1.0-2.0x which is
> more or less what you'll commonly see.
>
> Bilinear interpolation can be implemented rather effectively on most
> processors and is usually hardware supported too. That suggests that
> using a library is the right approach to avoid maintaining
> platform-specific code.
>
> Cairo seems to be a good choice. It integrates well with SDL and is
> portable to all of the platforms we care about. It's a very simple API
> too for scaling. We use it in gtk-vnc and it has proven to be very good
> for this task.
>
> What do you think?
I think cairo is a good choice for a new qemu gtk-cairo frontend, but I
don't think that mixing cairo and sdl is a good idea.
Among other things they can have pixel format issues, and it seems to me
that cairo is only able to use 32bpp SDL_Surface.
If you really want a library than SDL_gfx should be used instead, but I
think is overkill.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-06-24 10:58 [Qemu-devel] [PATCH] sdl zooming Stefano Stabellini
2009-06-24 12:41 ` Anthony Liguori
@ 2009-06-24 16:07 ` Blue Swirl
2009-06-25 13:03 ` Stefano Stabellini
1 sibling, 1 reply; 8+ messages in thread
From: Blue Swirl @ 2009-06-24 16:07 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: qemu-devel@nongnu.org
On 6/24/09, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
> 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.
As you are already using the template system, for extra performance,
you could remove 'smooth' as parameter and instantiate separate
functions for both cases with something like:
static int glue(glue(sdl_zoom_rgb, BPP), _ ## SMOOTH)(SDL_Surface
*src, SDL_Surface *dst,
SDL_Rect *dst_rect)
Then s/smooth/SMOOTH/g in the function and adjust callers.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-06-24 16:07 ` Blue Swirl
@ 2009-06-25 13:03 ` Stefano Stabellini
2009-07-02 14:02 ` Stefano Stabellini
0 siblings, 1 reply; 8+ messages in thread
From: Stefano Stabellini @ 2009-06-25 13:03 UTC (permalink / raw)
To: Blue Swirl; +Cc: qemu-devel@nongnu.org
Blue Swirl wrote:
> On 6/24/09, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
>> 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.
>
> As you are already using the template system, for extra performance,
> you could remove 'smooth' as parameter and instantiate separate
> functions for both cases with something like:
>
> static int glue(glue(sdl_zoom_rgb, BPP), _ ## SMOOTH)(SDL_Surface
> *src, SDL_Surface *dst,
> SDL_Rect *dst_rect)
>
> Then s/smooth/SMOOTH/g in the function and adjust callers.
I am not sure if this change is going to increase the readability of the
code or the performances by much, but this is the new version of the
patch nonetheless.
At this point I would consider making SMOOTH a compile time only variable.
---
diff --git a/Makefile b/Makefile
index 781e7ed..58faff9 100644
--- a/Makefile
+++ b/Makefile
@@ -162,7 +162,7 @@ OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
OBJS+=keymaps.o
ifdef CONFIG_SDL
-OBJS+=sdl.o x_keymap.o
+OBJS+=sdl.o sdl_zoom.o x_keymap.o
endif
ifdef CONFIG_CURSES
OBJS+=curses.o
@@ -206,7 +206,9 @@ cocoa.o: cocoa.m
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: CFLAGS += $(SDL_CFLAGS)
diff --git a/console.h b/console.h
index 4172175..3518339 100644
--- a/console.h
+++ b/console.h
@@ -75,6 +75,7 @@ void kbd_put_keysym(int keysym);
#define QEMU_BIG_ENDIAN_FLAG 0x01
#define QEMU_ALLOCATED_FLAG 0x02
+#define QEMU_REALPIXELS_FLAG 0x04
struct PixelFormat {
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)
{
- 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)
diff --git a/sdl.c b/sdl.c
index 178b553..d81399e 100644
--- a/sdl.c
+++ b/sdl.c
@@ -32,6 +32,7 @@
#include "console.h"
#include "sysemu.h"
#include "x_keymap.h"
+#include "sdl_zoom.h"
static DisplayChangeListener *dcl;
static SDL_Surface *real_screen;
@@ -54,20 +55,29 @@ static int guest_cursor = 0;
static int guest_x, guest_y;
static SDL_Cursor *guest_sprite = 0;
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)
{
// 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) {
- SDL_Rect rec;
- rec.x = x;
- rec.y = y;
- rec.w = w;
- rec.h = h;
- SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
- }
- SDL_UpdateRect(real_screen, x, y, w, h);
+ if (!scaling_active) {
+ SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
+ } else {
+ if (sdl_zoom_blit(guest_screen, real_screen, SMOOTHING_ON, &rec) < 0) {
+ fprintf(stderr, "Zoom blit failed\n");
+ exit(1);
+ }
+ }
+ }
+ SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
}
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);
- flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE;
if (gui_fullscreen)
flags |= SDL_FULLSCREEN;
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)
{
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);
} else {
if (guest_screen != NULL) {
@@ -163,8 +176,26 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
surface->width = width;
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);
+
+ return surface;
+ }
- if (hostbpp == 16)
+ if (host_format.BitsPerPixel == 16)
do_sdl_resize(width, height, 16);
else
do_sdl_resize(width, height, 32);
@@ -174,9 +205,9 @@ static DisplaySurface* sdl_create_displaysurface(int width, int height)
surface->data = real_screen->pixels;
#ifdef WORDS_BIGENDIAN
- surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+ surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
#else
- surface->flags = QEMU_ALLOCATED_FLAG;
+ surface->flags = QEMU_REALPIXELS_FLAG;
#endif
allocator = 1;
@@ -188,6 +219,9 @@ static void sdl_free_displaysurface(DisplaySurface *surface)
allocator = 0;
if (surface == NULL)
return;
+
+ if (surface->flags & QEMU_ALLOCATED_FLAG)
+ qemu_free(surface->data);
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)
{
gui_fullscreen = !gui_fullscreen;
- do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
if (gui_fullscreen) {
+ scaling_active = 0;
gui_saved_grab = gui_grab;
sdl_grab_start();
} else {
@@ -675,6 +709,18 @@ static void sdl_refresh(DisplayState *ds)
}
}
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:
break;
}
@@ -783,7 +829,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
exit(1);
}
vi = SDL_GetVideoInfo();
- hostbpp = vi->vfmt->BitsPerPixel;
+ host_format = *(vi->vfmt);
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
dcl->dpy_update = sdl_update;
diff --git a/sdl_zoom.c b/sdl_zoom.c
new file mode 100644
index 0000000..a9e82a4
--- /dev/null
+++ b/sdl_zoom.c
@@ -0,0 +1,110 @@
+/*
+ * 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_smooth(SDL_Surface *src, SDL_Surface *dst, SDL_Rect *dst_rect);
+static int sdl_zoom_rgb32_smooth(SDL_Surface *src, SDL_Surface *dst, SDL_Rect *dst_rect);
+static int sdl_zoom_rgb16_fast(SDL_Surface *src, SDL_Surface *dst, SDL_Rect *dst_rect);
+static int sdl_zoom_rgb32_fast(SDL_Surface *src, SDL_Surface *dst, SDL_Rect *dst_rect);
+
+#define SMOOTH 1
+#define BPP 32
+#include "sdl_zoom_template.h"
+#undef BPP
+#define BPP 16
+#include "sdl_zoom_template.h"
+#undef BPP
+#undef SMOOTH
+#define SMOOTH 0
+#define BPP 32
+#include "sdl_zoom_template.h"
+#undef BPP
+#define BPP 16
+#include "sdl_zoom_template.h"
+#undef BPP
+#undef SMOOTH
+
+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) {
+ if (smooth)
+ sdl_zoom_rgb32_smooth(src_sfc, dst_sfc, &zoom);
+ else
+ sdl_zoom_rgb32_fast(src_sfc, dst_sfc, &zoom);
+ } else if (src_sfc->format->BitsPerPixel == 16) {
+ if (smooth)
+ sdl_zoom_rgb16_smooth(src_sfc, dst_sfc, &zoom);
+ else
+ sdl_zoom_rgb16_fast(src_sfc, dst_sfc, &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;
+}
+
diff --git a/sdl_zoom.h b/sdl_zoom.h
new file mode 100644
index 0000000..33dc634
--- /dev/null
+++ b/sdl_zoom.h
@@ -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 */
diff --git a/sdl_zoom_template.h b/sdl_zoom_template.h
new file mode 100644
index 0000000..bc440ad
--- /dev/null
+++ b/sdl_zoom_template.h
@@ -0,0 +1,233 @@
+/*
+ * 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
+
+#if SMOOTH == 1
+#define ALG _smooth
+#else
+#define ALG _fast
+#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(glue(sdl_zoom_rgb, BPP), ALG)(SDL_Surface *src,
+ SDL_Surface *dst,
+ SDL_Rect *dst_rect)
+{
+ int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, sstep, sstep_jump;
+ SDL_TYPE *sp, *csp, *dp;
+ int d_gap;
+
+#if SMOOTH == 1
+ int ex, ey, t1, t2;
+ SDL_TYPE *c00, *c01, *c10, *c11;
+ SDL_PixelFormat *spf = src->format;
+ SDL_PixelFormat *dpf = dst->format;
+
+ /* 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);
+#endif
+
+ 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 == 1
+ 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);
+ }
+#endif
+
+ free(sax);
+ free(say);
+ return (0);
+}
+
+#undef SDL_TYPE
+#undef ALG
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-06-25 13:03 ` Stefano Stabellini
@ 2009-07-02 14:02 ` Stefano Stabellini
2009-07-02 14:23 ` Filip Navara
0 siblings, 1 reply; 8+ messages in thread
From: Stefano Stabellini @ 2009-07-02 14:02 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: Blue Swirl, qemu-devel@nongnu.org
On Thu, 25 Jun 2009, Stefano Stabellini wrote:
> Blue Swirl wrote:
>
> > On 6/24/09, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
> >> 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.
> >
> > As you are already using the template system, for extra performance,
> > you could remove 'smooth' as parameter and instantiate separate
> > functions for both cases with something like:
> >
> > static int glue(glue(sdl_zoom_rgb, BPP), _ ## SMOOTH)(SDL_Surface
> > *src, SDL_Surface *dst,
> > SDL_Rect *dst_rect)
> >
> > Then s/smooth/SMOOTH/g in the function and adjust callers.
>
>
>
> I am not sure if this change is going to increase the readability of the
> code or the performances by much, but this is the new version of the
> patch nonetheless.
>
Any update on this?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-07-02 14:02 ` Stefano Stabellini
@ 2009-07-02 14:23 ` Filip Navara
2009-07-02 14:33 ` Stefano Stabellini
0 siblings, 1 reply; 8+ messages in thread
From: Filip Navara @ 2009-07-02 14:23 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: Blue Swirl, qemu-devel@nongnu.org
On Thu, Jul 2, 2009 at 4:02 PM, Stefano
Stabellini<stefano.stabellini@eu.citrix.com> wrote:
> On Thu, 25 Jun 2009, Stefano Stabellini wrote:
>> Blue Swirl wrote:
>>
>> > On 6/24/09, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
>> >> 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.
>> >
>> > As you are already using the template system, for extra performance,
>> > you could remove 'smooth' as parameter and instantiate separate
>> > functions for both cases with something like:
>> >
>> > static int glue(glue(sdl_zoom_rgb, BPP), _ ## SMOOTH)(SDL_Surface
>> > *src, SDL_Surface *dst,
>> > SDL_Rect *dst_rect)
>> >
>> > Then s/smooth/SMOOTH/g in the function and adjust callers.
>>
>>
>>
>> I am not sure if this change is going to increase the readability of the
>> code or the performances by much, but this is the new version of the
>> patch nonetheless.
>>
>
> Any update on this?
It was commited to git...
F.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] sdl zooming
2009-07-02 14:23 ` Filip Navara
@ 2009-07-02 14:33 ` Stefano Stabellini
0 siblings, 0 replies; 8+ messages in thread
From: Stefano Stabellini @ 2009-07-02 14:33 UTC (permalink / raw)
To: Filip Navara; +Cc: Blue Swirl, qemu-devel@nongnu.org, Stefano Stabellini
On Thu, 2 Jul 2009, Filip Navara wrote:
> >
> > Any update on this?
>
> It was commited to git...
>
Oops, I really should fix the url of the git repo I am pulling from :)
Thanks,
Stefano
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-07-02 14:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-24 10:58 [Qemu-devel] [PATCH] sdl zooming Stefano Stabellini
2009-06-24 12:41 ` Anthony Liguori
2009-06-24 14:05 ` Stefano Stabellini
2009-06-24 16:07 ` Blue Swirl
2009-06-25 13:03 ` Stefano Stabellini
2009-07-02 14:02 ` Stefano Stabellini
2009-07-02 14:23 ` Filip Navara
2009-07-02 14:33 ` Stefano Stabellini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).