Added very slow software scaling to the X11 renderer
authorSam Lantinga <slouken@libsdl.org>
Wed, 03 Dec 2008 12:10:51 +0000
changeset 28287e5ff6cd05bf
parent 2827 aec4399c507a
child 2829 16fe3b867887
Added very slow software scaling to the X11 renderer
include/SDL_surface.h
src/video/SDL_stretch.c
src/video/SDL_stretch_c.h
src/video/SDL_yuv_sw.c
src/video/x11/SDL_x11render.c
     1.1 --- a/include/SDL_surface.h	Wed Dec 03 11:09:58 2008 +0000
     1.2 +++ b/include/SDL_surface.h	Wed Dec 03 12:10:51 2008 +0000
     1.3 @@ -462,16 +462,16 @@
     1.4       SDL_Surface * dst, SDL_Rect * dstrect);
     1.5  
     1.6  /**
     1.7 - * \fn int SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect)
     1.8 + * \fn int SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, const SDL_Rect * dstrect)
     1.9   *
    1.10   * \brief Perform a fast, low quality, stretch blit between two surfaces of the same pixel format.
    1.11   *
    1.12   * \note This function uses a static buffer, and is not thread-safe.
    1.13   */
    1.14  extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src,
    1.15 -                                            SDL_Rect * srcrect,
    1.16 +                                            const SDL_Rect * srcrect,
    1.17                                              SDL_Surface * dst,
    1.18 -                                            SDL_Rect * dstrect);
    1.19 +                                            const SDL_Rect * dstrect);
    1.20  
    1.21  /* Ends C function definitions when using C++ */
    1.22  #ifdef __cplusplus
     2.1 --- a/src/video/SDL_stretch.c	Wed Dec 03 11:09:58 2008 +0000
     2.2 +++ b/src/video/SDL_stretch.c	Wed Dec 03 12:10:51 2008 +0000
     2.3 @@ -173,8 +173,8 @@
     2.4     NOTE:  This function is not safe to call from multiple threads!
     2.5  */
     2.6  int
     2.7 -SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect,
     2.8 -                SDL_Surface * dst, SDL_Rect * dstrect)
     2.9 +SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect,
    2.10 +                SDL_Surface * dst, const SDL_Rect * dstrect)
    2.11  {
    2.12      int src_locked;
    2.13      int dst_locked;
     3.1 --- a/src/video/SDL_stretch_c.h	Wed Dec 03 11:09:58 2008 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,29 +0,0 @@
     3.4 -/*
     3.5 -    SDL - Simple DirectMedia Layer
     3.6 -    Copyright (C) 1997-2006 Sam Lantinga
     3.7 -
     3.8 -    This library is free software; you can redistribute it and/or
     3.9 -    modify it under the terms of the GNU Lesser General Public
    3.10 -    License as published by the Free Software Foundation; either
    3.11 -    version 2.1 of the License, or (at your option) any later version.
    3.12 -
    3.13 -    This library is distributed in the hope that it will be useful,
    3.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    3.16 -    Lesser General Public License for more details.
    3.17 -
    3.18 -    You should have received a copy of the GNU Lesser General Public
    3.19 -    License along with this library; if not, write to the Free Software
    3.20 -    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    3.21 -
    3.22 -    Sam Lantinga
    3.23 -    slouken@libsdl.org
    3.24 -*/
    3.25 -#include "SDL_config.h"
    3.26 -
    3.27 -/* Perform a stretch blit between two surfaces of the same format.
    3.28 -   NOTE:  This function is not safe to call from multiple threads!
    3.29 -*/
    3.30 -extern int SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect,
    3.31 -                           SDL_Surface * dst, SDL_Rect * dstrect);
    3.32 -/* vi: set ts=4 sw=4 expandtab: */
     4.1 --- a/src/video/SDL_yuv_sw.c	Wed Dec 03 11:09:58 2008 +0000
     4.2 +++ b/src/video/SDL_yuv_sw.c	Wed Dec 03 12:10:51 2008 +0000
     4.3 @@ -85,7 +85,6 @@
     4.4  
     4.5  #include "SDL_video.h"
     4.6  #include "SDL_cpuinfo.h"
     4.7 -#include "SDL_stretch_c.h"
     4.8  #include "SDL_yuv_sw_c.h"
     4.9  
    4.10  
     5.1 --- a/src/video/x11/SDL_x11render.c	Wed Dec 03 11:09:58 2008 +0000
     5.2 +++ b/src/video/x11/SDL_x11render.c	Wed Dec 03 12:10:51 2008 +0000
     5.3 @@ -97,6 +97,7 @@
     5.4      /* MIT shared memory extension information */
     5.5      XShmSegmentInfo shminfo;
     5.6  #endif
     5.7 +    XImage *scaling_image;
     5.8      void *pixels;
     5.9      int pitch;
    5.10  } X11_TextureData;
    5.11 @@ -131,6 +132,21 @@
    5.12                          texture->h, data->pixels, data->pitch);
    5.13  }
    5.14  
    5.15 +static int
    5.16 +X11_GetDepthFromPixelFormat(Uint32 format)
    5.17 +{
    5.18 +    int depth, order;
    5.19 +
    5.20 +    depth = SDL_BITSPERPIXEL(format);
    5.21 +    order = SDL_PIXELORDER(format);
    5.22 +    if (depth == 32
    5.23 +        && (order == SDL_PACKEDORDER_XRGB || order == SDL_PACKEDORDER_RGBX
    5.24 +            || SDL_PACKEDORDER_XBGR || order == SDL_PACKEDORDER_BGRX)) {
    5.25 +        depth = 24;
    5.26 +    }
    5.27 +    return depth;
    5.28 +}
    5.29 +
    5.30  static Uint32
    5.31  X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp)
    5.32  {
    5.33 @@ -385,7 +401,7 @@
    5.34      SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
    5.35      X11_TextureData *data;
    5.36      XWindowAttributes attributes;
    5.37 -    int depth, order;
    5.38 +    int depth;
    5.39  
    5.40      data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
    5.41      if (!data) {
    5.42 @@ -409,13 +425,7 @@
    5.43  
    5.44      XGetWindowAttributes(renderdata->display, renderdata->window,
    5.45                           &attributes);
    5.46 -    depth = SDL_BITSPERPIXEL(data->format);
    5.47 -    order = SDL_PIXELORDER(data->format);
    5.48 -    if (depth == 32
    5.49 -        && (order == SDL_PACKEDORDER_XRGB || order == SDL_PACKEDORDER_RGBX
    5.50 -            || SDL_PACKEDORDER_XBGR || order == SDL_PACKEDORDER_BGRX)) {
    5.51 -        depth = 24;
    5.52 -    }
    5.53 +    depth = X11_GetDepthFromPixelFormat(data->format);
    5.54  
    5.55      if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
    5.56  #ifndef NO_SHARED_MEMORY
    5.57 @@ -532,9 +542,17 @@
    5.58  static int
    5.59  X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
    5.60  {
    5.61 +    X11_TextureData *data = (X11_TextureData *) texture->driverdata;
    5.62 +
    5.63      switch (texture->scaleMode) {
    5.64      case SDL_TEXTURESCALEMODE_NONE:
    5.65          return 0;
    5.66 +    case SDL_TEXTURESCALEMODE_FAST:
    5.67 +        /* We can sort of fake it for streaming textures */
    5.68 +        if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
    5.69 +            return 0;
    5.70 +        }
    5.71 +        /* Fall through to unsupported case */
    5.72      default:
    5.73          SDL_Unsupported();
    5.74          texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
    5.75 @@ -646,17 +664,102 @@
    5.76      if (data->makedirty) {
    5.77          SDL_AddDirtyRect(&data->dirty, dstrect);
    5.78      }
    5.79 +    if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
    5.80  #ifndef NO_SHARED_MEMORY
    5.81 -    if (texturedata->shminfo.shmaddr) {
    5.82 -        XShmPutImage(data->display, data->drawable, data->gc,
    5.83 -                     texturedata->image, srcrect->x, srcrect->y, dstrect->x,
    5.84 -                     dstrect->y, srcrect->w, srcrect->h, False);
    5.85 -    } else
    5.86 +        if (texturedata->shminfo.shmaddr) {
    5.87 +            XShmPutImage(data->display, data->drawable, data->gc,
    5.88 +                         texturedata->image, srcrect->x, srcrect->y,
    5.89 +                         dstrect->x, dstrect->y, srcrect->w, srcrect->h,
    5.90 +                         False);
    5.91 +        } else
    5.92  #endif
    5.93 -    if (texturedata->pixels) {
    5.94 -        XPutImage(data->display, data->drawable, data->gc, texturedata->image,
    5.95 -                  srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w,
    5.96 -                  srcrect->h);
    5.97 +        if (texturedata->pixels) {
    5.98 +            XPutImage(data->display, data->drawable, data->gc,
    5.99 +                      texturedata->image, srcrect->x, srcrect->y, dstrect->x,
   5.100 +                      dstrect->y, srcrect->w, srcrect->h);
   5.101 +        } else {
   5.102 +            XCopyArea(data->display, texturedata->pixmap, data->drawable,
   5.103 +                      data->gc, srcrect->x, srcrect->y, dstrect->w,
   5.104 +                      dstrect->h, srcrect->x, srcrect->y);
   5.105 +        }
   5.106 +    } else if (texturedata->yuv
   5.107 +               || texture->access == SDL_TEXTUREACCESS_STREAMING) {
   5.108 +        SDL_Surface src, dst;
   5.109 +        SDL_PixelFormat fmt;
   5.110 +        SDL_Rect rect;
   5.111 +        XImage *image = texturedata->scaling_image;
   5.112 +
   5.113 +        if (!image) {
   5.114 +            XWindowAttributes attributes;
   5.115 +            int depth;
   5.116 +            void *pixels;
   5.117 +            int pitch;
   5.118 +
   5.119 +            XGetWindowAttributes(data->display, data->window, &attributes);
   5.120 +
   5.121 +            pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
   5.122 +            pixels = SDL_malloc(dstrect->h * pitch);
   5.123 +            if (!pixels) {
   5.124 +                SDL_OutOfMemory();
   5.125 +                return -1;
   5.126 +            }
   5.127 +
   5.128 +            depth = X11_GetDepthFromPixelFormat(texturedata->format);
   5.129 +            image =
   5.130 +                XCreateImage(data->display, attributes.visual, depth, ZPixmap,
   5.131 +                             0, pixels, dstrect->w, dstrect->h,
   5.132 +                             SDL_BYTESPERPIXEL(texturedata->format) * 8,
   5.133 +                             pitch);
   5.134 +            if (!image) {
   5.135 +                SDL_SetError("XCreateImage() failed");
   5.136 +                return -1;
   5.137 +            }
   5.138 +            texturedata->scaling_image = image;
   5.139 +
   5.140 +        } else if (image->width != dstrect->w || image->height != dstrect->h
   5.141 +                   || !image->data) {
   5.142 +            image->width = dstrect->w;
   5.143 +            image->height = dstrect->h;
   5.144 +            image->bytes_per_line =
   5.145 +                image->width * SDL_BYTESPERPIXEL(texturedata->format);
   5.146 +            image->data =
   5.147 +                (char *) SDL_realloc(image->data,
   5.148 +                                     image->height * image->bytes_per_line);
   5.149 +            if (!image->data) {
   5.150 +                SDL_OutOfMemory();
   5.151 +                return -1;
   5.152 +            }
   5.153 +        }
   5.154 +
   5.155 +        /* Set up fake surfaces for SDL_SoftStretch() */
   5.156 +        src.format = &fmt;
   5.157 +        src.w = texture->w;
   5.158 +        src.h = texture->h;
   5.159 +#ifndef NO_SHARED_MEMORY
   5.160 +        if (texturedata->shminfo.shmaddr) {
   5.161 +            src.pixels = texturedata->shminfo.shmaddr;
   5.162 +        } else
   5.163 +#endif
   5.164 +            src.pixels = texturedata->pixels;
   5.165 +        src.pitch = texturedata->pitch;
   5.166 +
   5.167 +        dst.format = &fmt;
   5.168 +        dst.w = image->width;
   5.169 +        dst.h = image->height;
   5.170 +        dst.pixels = image->data;
   5.171 +        dst.pitch = image->bytes_per_line;
   5.172 +
   5.173 +        fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
   5.174 +
   5.175 +        rect.x = 0;
   5.176 +        rect.y = 0;
   5.177 +        rect.w = dstrect->w;
   5.178 +        rect.h = dstrect->h;
   5.179 +        if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
   5.180 +            return -1;
   5.181 +        }
   5.182 +        XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
   5.183 +                  dstrect->x, dstrect->y, dstrect->w, dstrect->h);
   5.184      } else {
   5.185          XCopyArea(data->display, texturedata->pixmap, data->drawable,
   5.186                    data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
   5.187 @@ -720,6 +823,11 @@
   5.188          data->pixels = NULL;
   5.189      }
   5.190  #endif
   5.191 +    if (data->scaling_image) {
   5.192 +        SDL_free(data->scaling_image->data);
   5.193 +        data->scaling_image->data = NULL;
   5.194 +        XDestroyImage(data->scaling_image);
   5.195 +    }
   5.196      if (data->pixels) {
   5.197          SDL_free(data->pixels);
   5.198      }