Commit 4a86bb6e authored by Sam Lantinga's avatar Sam Lantinga

Added very slow software scaling to the X11 renderer

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403289
parent a403d948
...@@ -462,16 +462,16 @@ extern DECLSPEC int SDLCALL SDL_LowerBlit ...@@ -462,16 +462,16 @@ extern DECLSPEC int SDLCALL SDL_LowerBlit
SDL_Surface * dst, SDL_Rect * dstrect); 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. * \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. * \note This function uses a static buffer, and is not thread-safe.
*/ */
extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src, extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src,
SDL_Rect * srcrect, const SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Surface * dst,
SDL_Rect * dstrect); const SDL_Rect * dstrect);
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -173,8 +173,8 @@ copy_row3(Uint8 * src, int src_w, Uint8 * dst, int dst_w) ...@@ -173,8 +173,8 @@ copy_row3(Uint8 * src, int src_w, Uint8 * dst, int dst_w)
NOTE: This function is not safe to call from multiple threads! NOTE: This function is not safe to call from multiple threads!
*/ */
int int
SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect, SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect) SDL_Surface * dst, const SDL_Rect * dstrect)
{ {
int src_locked; int src_locked;
int dst_locked; int dst_locked;
......
/*
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: */
...@@ -85,7 +85,6 @@ ...@@ -85,7 +85,6 @@
#include "SDL_video.h" #include "SDL_video.h"
#include "SDL_cpuinfo.h" #include "SDL_cpuinfo.h"
#include "SDL_stretch_c.h"
#include "SDL_yuv_sw_c.h" #include "SDL_yuv_sw_c.h"
......
...@@ -97,6 +97,7 @@ typedef struct ...@@ -97,6 +97,7 @@ typedef struct
/* MIT shared memory extension information */ /* MIT shared memory extension information */
XShmSegmentInfo shminfo; XShmSegmentInfo shminfo;
#endif #endif
XImage *scaling_image;
void *pixels; void *pixels;
int pitch; int pitch;
} X11_TextureData; } X11_TextureData;
...@@ -131,6 +132,21 @@ UpdateYUVTextureData(SDL_Texture * texture) ...@@ -131,6 +132,21 @@ UpdateYUVTextureData(SDL_Texture * texture)
texture->h, data->pixels, data->pitch); 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 static Uint32
X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp) X11_GetPixelFormatFromDepth(Display * display, int screen, int depth, int bpp)
{ {
...@@ -385,7 +401,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -385,7 +401,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
X11_TextureData *data; X11_TextureData *data;
XWindowAttributes attributes; XWindowAttributes attributes;
int depth, order; int depth;
data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
...@@ -409,13 +425,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -409,13 +425,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
XGetWindowAttributes(renderdata->display, renderdata->window, XGetWindowAttributes(renderdata->display, renderdata->window,
&attributes); &attributes);
depth = SDL_BITSPERPIXEL(data->format); depth = X11_GetDepthFromPixelFormat(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;
}
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY
...@@ -532,9 +542,17 @@ X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -532,9 +542,17 @@ X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
static int static int
X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{ {
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
switch (texture->scaleMode) { switch (texture->scaleMode) {
case SDL_TEXTURESCALEMODE_NONE: case SDL_TEXTURESCALEMODE_NONE:
return 0; 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: default:
SDL_Unsupported(); SDL_Unsupported();
texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
...@@ -646,17 +664,102 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -646,17 +664,102 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
if (data->makedirty) { if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, dstrect); SDL_AddDirtyRect(&data->dirty, dstrect);
} }
if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY
if (texturedata->shminfo.shmaddr) { if (texturedata->shminfo.shmaddr) {
XShmPutImage(data->display, data->drawable, data->gc, XShmPutImage(data->display, data->drawable, data->gc,
texturedata->image, srcrect->x, srcrect->y, dstrect->x, texturedata->image, srcrect->x, srcrect->y,
dstrect->y, srcrect->w, srcrect->h, False); dstrect->x, dstrect->y, srcrect->w, srcrect->h,
} else False);
} else
#endif #endif
if (texturedata->pixels) { if (texturedata->pixels) {
XPutImage(data->display, data->drawable, data->gc, texturedata->image, XPutImage(data->display, data->drawable, data->gc,
srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w, texturedata->image, srcrect->x, srcrect->y, dstrect->x,
srcrect->h); 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 { } else {
XCopyArea(data->display, texturedata->pixmap, data->drawable, XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
...@@ -720,6 +823,11 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -720,6 +823,11 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
data->pixels = NULL; data->pixels = NULL;
} }
#endif #endif
if (data->scaling_image) {
SDL_free(data->scaling_image->data);
data->scaling_image->data = NULL;
XDestroyImage(data->scaling_image);
}
if (data->pixels) { if (data->pixels) {
SDL_free(data->pixels); SDL_free(data->pixels);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment