Added very slow software scaling to the X11 renderer
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403289
This commit is contained in:
parent
a403d94807
commit
4a86bb6ebf
5 changed files with 130 additions and 52 deletions
|
@ -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)
|
||||||
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;
|
||||||
|
|
|
@ -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: */
|
|
|
@ -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
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
|
False);
|
||||||
} else
|
} 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)
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue