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
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
......
......@@ -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!
*/
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;
......
/*
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 @@
#include "SDL_video.h"
#include "SDL_cpuinfo.h"
#include "SDL_stretch_c.h"
#include "SDL_yuv_sw_c.h"
......
......@@ -97,6 +97,7 @@ typedef struct
/* MIT shared memory extension information */
XShmSegmentInfo shminfo;
#endif
XImage *scaling_image;
void *pixels;
int pitch;
} X11_TextureData;
......@@ -131,6 +132,21 @@ UpdateYUVTextureData(SDL_Texture * texture)
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 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
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 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
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 @@ X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
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 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
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);
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);
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 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
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);
}
......
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