summaryrefslogtreecommitdiff
path: root/sdl_zoom_template.h
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_zoom_template.h
parent14899cdf3a6e1fc0d72097a43c1c53a1354fbfbf (diff)
downloadqemu-c18a2c360e3100bbd71162cf922dcd8c429a8b71.tar.gz
qemu-c18a2c360e3100bbd71162cf922dcd8c429a8b71.tar.bz2
qemu-c18a2c360e3100bbd71162cf922dcd8c429a8b71.zip
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_zoom_template.h')
-rw-r--r--sdl_zoom_template.h225
1 files changed, 225 insertions, 0 deletions
diff --git a/sdl_zoom_template.h b/sdl_zoom_template.h
new file mode 100644
index 0000000000..64bbca849b
--- /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
+