Mercurial > sdl-ios-xcode
changeset 2828:7e5ff6cd05bf
Added very slow software scaling to the X11 renderer
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 03 Dec 2008 12:10:51 +0000 |
parents | aec4399c507a |
children | 16fe3b867887 |
files | 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 |
diffstat | 5 files changed, 130 insertions(+), 52 deletions(-) [+] |
line wrap: on
line diff
--- a/include/SDL_surface.h Wed Dec 03 11:09:58 2008 +0000 +++ b/include/SDL_surface.h Wed Dec 03 12:10:51 2008 +0000 @@ -462,16 +462,16 @@ SDL_Surface * dst, SDL_Rect * dstrect); /** - * \fn int SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) + * \fn int SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, const SDL_Rect * dstrect) * * \brief Perform a fast, low quality, stretch blit between two surfaces of the same pixel format. * * \note This function uses a static buffer, and is not thread-safe. */ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src, - SDL_Rect * srcrect, + const SDL_Rect * srcrect, SDL_Surface * dst, - SDL_Rect * dstrect); + const SDL_Rect * dstrect); /* Ends C function definitions when using C++ */ #ifdef __cplusplus
--- a/src/video/SDL_stretch.c Wed Dec 03 11:09:58 2008 +0000 +++ b/src/video/SDL_stretch.c Wed Dec 03 12:10:51 2008 +0000 @@ -173,8 +173,8 @@ NOTE: This function is not safe to call from multiple threads! */ int -SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect, - SDL_Surface * dst, SDL_Rect * dstrect) +SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect, + SDL_Surface * dst, const SDL_Rect * dstrect) { int src_locked; int dst_locked;
--- a/src/video/SDL_stretch_c.h Wed Dec 03 11:09:58 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Sam Lantinga - slouken@libsdl.org -*/ -#include "SDL_config.h" - -/* Perform a stretch blit between two surfaces of the same format. - NOTE: This function is not safe to call from multiple threads! -*/ -extern int SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect, - SDL_Surface * dst, SDL_Rect * dstrect); -/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_yuv_sw.c Wed Dec 03 11:09:58 2008 +0000 +++ b/src/video/SDL_yuv_sw.c Wed Dec 03 12:10:51 2008 +0000 @@ -85,7 +85,6 @@ #include "SDL_video.h" #include "SDL_cpuinfo.h" -#include "SDL_stretch_c.h" #include "SDL_yuv_sw_c.h"
--- a/src/video/x11/SDL_x11render.c Wed Dec 03 11:09:58 2008 +0000 +++ b/src/video/x11/SDL_x11render.c Wed Dec 03 12:10:51 2008 +0000 @@ -97,6 +97,7 @@ /* MIT shared memory extension information */ XShmSegmentInfo shminfo; #endif + XImage *scaling_image; void *pixels; int pitch; } X11_TextureData; @@ -131,6 +132,21 @@ texture->h, data->pixels, data->pitch); } +static int +X11_GetDepthFromPixelFormat(Uint32 format) +{ + int depth, order; + + depth = SDL_BITSPERPIXEL(format); + order = SDL_PIXELORDER(format); + if (depth == 32 + && (order == SDL_PACKEDORDER_XRGB || order == SDL_PACKEDORDER_RGBX + || SDL_PACKEDORDER_XBGR || order == SDL_PACKEDORDER_BGRX)) { + depth = 24; + } + return depth; +} + static Uint32 X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp) { @@ -385,7 +401,7 @@ SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); X11_TextureData *data; XWindowAttributes attributes; - int depth, order; + int depth; data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { @@ -409,13 +425,7 @@ XGetWindowAttributes(renderdata->display, renderdata->window, &attributes); - depth = SDL_BITSPERPIXEL(data->format); - order = SDL_PIXELORDER(data->format); - if (depth == 32 - && (order == SDL_PACKEDORDER_XRGB || order == SDL_PACKEDORDER_RGBX - || SDL_PACKEDORDER_XBGR || order == SDL_PACKEDORDER_BGRX)) { - depth = 24; - } + depth = X11_GetDepthFromPixelFormat(data->format); if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { #ifndef NO_SHARED_MEMORY @@ -532,9 +542,17 @@ static int X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) { + X11_TextureData *data = (X11_TextureData *) texture->driverdata; + switch (texture->scaleMode) { case SDL_TEXTURESCALEMODE_NONE: return 0; + case SDL_TEXTURESCALEMODE_FAST: + /* We can sort of fake it for streaming textures */ + if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { + return 0; + } + /* Fall through to unsupported case */ default: SDL_Unsupported(); texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; @@ -646,17 +664,102 @@ if (data->makedirty) { SDL_AddDirtyRect(&data->dirty, dstrect); } + if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { #ifndef NO_SHARED_MEMORY - if (texturedata->shminfo.shmaddr) { - XShmPutImage(data->display, data->drawable, data->gc, - texturedata->image, srcrect->x, srcrect->y, dstrect->x, - dstrect->y, srcrect->w, srcrect->h, False); - } else + if (texturedata->shminfo.shmaddr) { + XShmPutImage(data->display, data->drawable, data->gc, + texturedata->image, srcrect->x, srcrect->y, + dstrect->x, dstrect->y, srcrect->w, srcrect->h, + False); + } else #endif - if (texturedata->pixels) { - XPutImage(data->display, data->drawable, data->gc, texturedata->image, - srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w, - srcrect->h); + if (texturedata->pixels) { + XPutImage(data->display, data->drawable, data->gc, + texturedata->image, srcrect->x, srcrect->y, dstrect->x, + dstrect->y, srcrect->w, srcrect->h); + } else { + XCopyArea(data->display, texturedata->pixmap, data->drawable, + data->gc, srcrect->x, srcrect->y, dstrect->w, + dstrect->h, srcrect->x, srcrect->y); + } + } else if (texturedata->yuv + || texture->access == SDL_TEXTUREACCESS_STREAMING) { + SDL_Surface src, dst; + SDL_PixelFormat fmt; + SDL_Rect rect; + XImage *image = texturedata->scaling_image; + + if (!image) { + XWindowAttributes attributes; + int depth; + void *pixels; + int pitch; + + XGetWindowAttributes(data->display, data->window, &attributes); + + pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format); + pixels = SDL_malloc(dstrect->h * pitch); + if (!pixels) { + SDL_OutOfMemory(); + return -1; + } + + depth = X11_GetDepthFromPixelFormat(texturedata->format); + image = + XCreateImage(data->display, attributes.visual, depth, ZPixmap, + 0, pixels, dstrect->w, dstrect->h, + SDL_BYTESPERPIXEL(texturedata->format) * 8, + pitch); + if (!image) { + SDL_SetError("XCreateImage() failed"); + return -1; + } + texturedata->scaling_image = image; + + } else if (image->width != dstrect->w || image->height != dstrect->h + || !image->data) { + image->width = dstrect->w; + image->height = dstrect->h; + image->bytes_per_line = + image->width * SDL_BYTESPERPIXEL(texturedata->format); + image->data = + (char *) SDL_realloc(image->data, + image->height * image->bytes_per_line); + if (!image->data) { + SDL_OutOfMemory(); + return -1; + } + } + + /* Set up fake surfaces for SDL_SoftStretch() */ + src.format = &fmt; + src.w = texture->w; + src.h = texture->h; +#ifndef NO_SHARED_MEMORY + if (texturedata->shminfo.shmaddr) { + src.pixels = texturedata->shminfo.shmaddr; + } else +#endif + src.pixels = texturedata->pixels; + src.pitch = texturedata->pitch; + + dst.format = &fmt; + dst.w = image->width; + dst.h = image->height; + dst.pixels = image->data; + dst.pitch = image->bytes_per_line; + + fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format); + + rect.x = 0; + rect.y = 0; + rect.w = dstrect->w; + rect.h = dstrect->h; + if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) { + return -1; + } + XPutImage(data->display, data->drawable, data->gc, image, 0, 0, + dstrect->x, dstrect->y, dstrect->w, dstrect->h); } else { XCopyArea(data->display, texturedata->pixmap, data->drawable, data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, @@ -720,6 +823,11 @@ data->pixels = NULL; } #endif + if (data->scaling_image) { + SDL_free(data->scaling_image->data); + data->scaling_image->data = NULL; + XDestroyImage(data->scaling_image); + } if (data->pixels) { SDL_free(data->pixels); }