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);
|
||||
|
||||
/**
|
||||
* \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;
|
||||
|
|
|
@ -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_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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue