summaryrefslogtreecommitdiff
path: root/sdl.c
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2009-06-24 11:58:25 +0100
committerAnthony Liguori <aliguori@us.ibm.com>2009-06-29 08:52:44 -0500
commitc18a2c360e3100bbd71162cf922dcd8c429a8b71 (patch)
treedea997d9de9b100224a2f2adf25dead03d47df34 /sdl.c
parent14899cdf3a6e1fc0d72097a43c1c53a1354fbfbf (diff)
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>
Diffstat (limited to 'sdl.c')
-rw-r--r--sdl.c78
1 files changed, 62 insertions, 16 deletions
diff --git a/sdl.c b/sdl.c
index 178b5532b8..d81399e512 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;