Commit d8e7cebd authored by Sam Lantinga's avatar Sam Lantinga

Merged Sunny's XRender changes from SDL-gsoc2010_xrender

parents 8d14ec12 b277b530
......@@ -1055,6 +1055,8 @@ AC_HELP_STRING([--enable-x11-shared], [dynamically load X11 support [[default=ma
xrandr_lib=[`find_lib "libXrandr.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`]
xinput_lib=[`find_lib "libXi.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`]
xss_lib=[`find_lib "libXss.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`]
xdamage_lib=[`find_lib "libXdamage.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`]
xfixes_lib=[`find_lib "libXfixes.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`]
;;
esac
......@@ -1128,16 +1130,13 @@ AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for ful
])
if test x$have_xrandr_h_hdr = xyes; then
if test x$enable_x11_shared = xyes && test x$xrandr_lib != x ; then
echo "-- dynamic libXrender -> $xrender_lib"
echo "-- dynamic libXrandr -> $xrandr_lib"
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER, "$xrender_lib")
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR, "$xrandr_lib")
definitely_enable_video_x11_xrandr=yes
else
AC_CHECK_LIB(Xrender, XRenderQueryExtension, have_xrender_lib=yes)
AC_CHECK_LIB(Xrandr, XRRQueryExtension, have_xrandr_lib=yes)
if test x$have_xrender_lib = xyes && test x$have_xrandr_lib = xyes ; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr -lXrender"
if test x$have_xrandr_lib = xyes ; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr"
definitely_enable_video_x11_xrandr=yes
fi
fi
......@@ -1199,7 +1198,69 @@ AC_HELP_STRING([--enable-video-x11-scrnsaver], [enable X11 screensaver extension
if test x$definitely_enable_video_x11_scrnsaver = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_X11_SCRNSAVER)
fi
AC_ARG_ENABLE(video-x11-xrender,
AC_HELP_STRING([--enable-video-x11-xrender], [enable X11 Xrender extension [[default=yes]]]),
, enable_video_x11_xrender=yes)
if test x$enable_video_x11_xrender = xyes; then
AC_CHECK_HEADER(X11/extensions/Xrender.h,
have_xrender_h_hdr=yes,
have_xrender_h_hdr=no,
[#include <X11/Xlib.h>
])
if test x$have_xrender_h_hdr = xyes; then
if test x$enable_x11_shared = xyes && test x$xrender_lib != x ; then
echo "-- dynamic libXrender -> $xrender_lib"
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER, "$xrender_lib")
definitely_enable_video_x11_xrender=yes
else
AC_CHECK_LIB(Xrender, XRenderQueryExtension, have_xrender_lib=yes)
if test x$have_xrender_lib = xyes ; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrender"
definitely_enable_video_x11_xrender=yes
fi
fi
fi
fi
if test x$definitely_enable_video_x11_xrender = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XRENDER)
fi
AC_ARG_ENABLE(video-x11-xdamage-xfixes,
AC_HELP_STRING([--enable-video-x11-xdamage-xfixes], [enable X11 Xdamage and Xfixes extensions [[default=yes]]]),
, enable_video_x11_xdamage=yes)
if test x$enable_video_x11_xdamage = xyes && test x$definitely_enable_video_x11_xrender = xyes ; then
AC_CHECK_HEADER(X11/extensions/Xdamage.h,
have_xdamage_h_hdr=yes,
have_xdamage_h_hdr=no,
[#include <X11/Xlib.h>
])
AC_CHECK_HEADER(X11/extensions/Xfixes.h,
have_xfixes_h_hdr=yes,
have_xfixes_h_hdr=no,
[#include <X11/Xlib.h>
])
if test x$have_xdamage_h_hdr = xyes && test x$have_xfixes_h_hdr = xyes ; then
if test x$enable_x11_shared = xyes && test x$xdamage_lib != x && test x$xfixes_lib != x ; then
echo "-- dynamic libXdamage -> $xdamage_lib"
echo "-- dynamic libXfixes -> $xfixes_lib"
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XDAMAGE, "$xdamage_lib")
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES, "$xfixes_lib")
definitely_enable_video_x11_xdamage=yes
definitely_enable_video_x11_xfixes=yes
else
AC_CHECK_LIB(Xdamage, XDamageQueryExtension, have_xdamage_lib=yes)
AC_CHECK_LIB(Xfixes, XFixesQueryExtension, have_xfixes_lib=yes)
if test x$have_xdamage_lib = xyes && test x$have_xfixes_lib = xyes ; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXdamage -lXfixes"
definitely_enable_video_x11_xdamage=yes
definitely_enable_video_x11_xfixes=yes
fi
fi
fi
fi
if test x$definitely_enable_video_x11_xdamage = xyes && test x$definitely_enable_video_x11_xfixes = xyes ; then
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XDAMAGE)
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XFIXES)
fi
AC_ARG_ENABLE(render-x11,
AC_HELP_STRING([--enable-render-x11], [enable the X11 render driver [[default=yes]]]),
, enable_render_x11=yes)
......
......@@ -272,12 +272,19 @@
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XDAMAGE
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES
#undef SDL_VIDEO_DRIVER_X11_VIDMODE
#undef SDL_VIDEO_DRIVER_X11_XINERAMA
#undef SDL_VIDEO_DRIVER_X11_XRANDR
#undef SDL_VIDEO_DRIVER_X11_XINPUT
#undef SDL_VIDEO_DRIVER_X11_SCRNSAVER
#undef SDL_VIDEO_DRIVER_X11_XV
#undef SDL_VIDEO_DRIVER_X11_XRENDER
#undef SDL_VIDEO_DRIVER_X11_XDAMAGE
#undef SDL_VIDEO_DRIVER_X11_XFIXES
#undef SDL_VIDEO_RENDER_X11
#undef SDL_VIDEO_RENDER_D3D
#undef SDL_VIDEO_RENDER_GDI
......
......@@ -189,7 +189,7 @@ typedef struct SDL_RendererInfo
Uint32 blend_modes; /**< A mask of supported blend modes */
Uint32 scale_modes; /**< A mask of supported scale modes */
Uint32 num_texture_formats; /**< The number of available texture formats */
Uint32 texture_formats[20]; /**< The available texture formats */
Uint32 texture_formats[50]; /**< The available texture formats */
int max_texture_width; /**< The maximimum texture width */
int max_texture_height; /**< The maximimum texture height */
} SDL_RendererInfo;
......
......@@ -26,6 +26,8 @@
#include "SDL_error.h"
#include "SDL_error_c.h"
/*#define DEBUG_ERROR*/
/* Routine to get the thread-specific error variable */
#if SDL_THREADS_DISABLED
/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */
......
......@@ -52,6 +52,18 @@
#include <X11/extensions/XInput.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XRENDER
#include <X11/extensions/Xrender.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XDAMAGE
#include <X11/extensions/Xdamage.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
/*
* When using the "dynamic X11" functionality, we duplicate all the Xlib
* symbols that would be referenced by SDL inside of SDL itself.
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
......@@ -39,6 +40,8 @@ static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int X11_QueryTexturePixels(SDL_Renderer * renderer,
SDL_Texture * texture, void **pixels,
int *pitch);
static int X11_SetTextureRGBAMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int X11_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int X11_SetTextureScaleMode(SDL_Renderer * renderer,
......@@ -96,6 +99,25 @@ typedef struct
int scanline_pad;
Window xwindow;
Pixmap pixmaps[3];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
Pixmap stencil;
Pixmap brush;
Picture brush_pict;
Picture xwindow_pict;
Picture pixmap_picts[3];
Picture drawable_pict;
Picture stencil_pict;
int blend_op;
XRenderPictFormat *xwindow_pict_fmt;
XRenderPictFormat *drawable_pict_fmt;
GC stencil_gc;
SDL_bool use_xrender;
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
SDL_bool use_xdamage;
Damage stencil_damage;
XserverRegion stencil_parts;
#endif
#endif
int current_pixmap;
Drawable drawable;
SDL_PixelFormat format;
......@@ -109,6 +131,17 @@ typedef struct
SDL_SW_YUVTexture *yuv;
Uint32 format;
Pixmap pixmap;
int depth;
Visual *visual;
GC gc;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
Picture picture;
Pixmap modulated_pixmap;
Picture modulated_picture;
XRenderPictFormat* picture_fmt;
int blend_op;
const char* filter;
#endif
XImage *image;
#ifndef NO_SHARED_MEMORY
/* MIT shared memory extension information */
......@@ -149,11 +182,109 @@ UpdateYUVTextureData(SDL_Texture * texture)
texture->h, data->pixels, data->pitch);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static SDL_bool
CheckXRender(Display *display, int *major, int *minor) {
const char *env;
*major = *minor = 0;
env = SDL_getenv("SDL_VIDEO_X11_XRENDER");
if (env && !SDL_atoi(env)) {
return SDL_FALSE;
}
if (!SDL_X11_HAVE_XRENDER) {
return SDL_FALSE;
}
if (!XRenderQueryVersion(display, major, minor)) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
static SDL_bool
CheckXFixes(Display *display, int *major, int *minor) {
const char *env;
*major = *minor = 0;
env = SDL_getenv("SDL_VIDEO_X11_XFIXES");
if (env && !SDL_atoi(env)) {
return SDL_FALSE;
}
if (!SDL_X11_HAVE_XFIXES) {
return SDL_FALSE;
}
if (!XFixesQueryVersion(display, major, minor)) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
static SDL_bool
CheckXDamage(Display *display, int *major, int *minor) {
const char *env;
*major = *minor = 0;
env = SDL_getenv("SDL_VIDEO_X11_XDAMAGE");
if (env && !SDL_atoi(env)) {
return SDL_FALSE;
}
if (!SDL_X11_HAVE_XDAMAGE) {
return SDL_FALSE;
}
if (!XDamageQueryVersion(display, major, minor)) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static Uint32
XRenderPictFormatToSDLPixelFormatEnum(XRenderPictFormat *pict_format) {
if (pict_format->type != PictTypeDirect) {
SDL_SetError("Indexed pict formats not supported ATM");
return 0;
}
Uint32 Amask, Rmask, Gmask, Bmask;
int bpp;
Rmask = pict_format->direct.redMask << pict_format->direct.red;
Gmask = pict_format->direct.greenMask << pict_format->direct.green;
Bmask = pict_format->direct.blueMask << pict_format->direct.blue;
Amask = pict_format->direct.alphaMask << pict_format->direct.alpha;
bpp = pict_format->depth;
Uint32 format;
format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
return format;
}
#endif
void
X11_AddRenderDriver(_THIS)
{
SDL_RendererInfo *info = &X11_RenderDriver.info;
SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode;
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
int i;
info->texture_formats[info->num_texture_formats++] = mode->format;
......@@ -163,6 +294,34 @@ X11_AddRenderDriver(_THIS)
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
int major, minor;
if (CheckXRender(data->display, &major, &minor)) {
XRenderPictFormat templ;
templ.type = PictTypeDirect;
XRenderPictFormat *pict_format;
Uint32 format;
int i = 0;
while (info->num_texture_formats < 50) {
pict_format =
XRenderFindFormat(data->display, PictFormatType, &templ, i++);
if (pict_format) {
format = XRenderPictFormatToSDLPixelFormatEnum(pict_format);
if (format != SDL_PIXELTYPE_UNKNOWN) {
info->texture_formats[info->num_texture_formats++] = format;
}
}
else
break;
}
info->blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD |
SDL_BLENDMODE_MOD | SDL_BLENDMODE_MASK);
info->scale_modes |= (SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_SLOW |
SDL_TEXTURESCALEMODE_BEST);
info->mod_modes |= (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA);
}
#endif
for (i = 0; i < _this->num_displays; ++i) {
SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver);
}
......@@ -177,6 +336,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_Renderer *renderer;
X11_RenderData *data;
XGCValues gcv;
gcv.graphics_exposures = False;
int i, n;
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
......@@ -199,10 +359,12 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
data->depth = displaydata->depth;
data->scanline_pad = displaydata->scanline_pad;
data->xwindow = windowdata->xwindow;
renderer->DisplayModeChanged = X11_DisplayModeChanged;
renderer->CreateTexture = X11_CreateTexture;
renderer->QueryTexturePixels = X11_QueryTexturePixels;
renderer->SetTextureAlphaMod = X11_SetTextureRGBAMod;
renderer->SetTextureColorMod = X11_SetTextureRGBAMod;
renderer->SetTextureBlendMode = X11_SetTextureBlendMode;
renderer->SetTextureScaleMode = X11_SetTextureScaleMode;
renderer->UpdateTexture = X11_UpdateTexture;
......@@ -225,6 +387,82 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags = SDL_RENDERER_ACCELERATED;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
int major, minor;
data->use_xrender = CheckXRender(data->display, &major, &minor);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (CheckXDamage(data->display, &major, &minor)) {
if (CheckXFixes(data->display, &major, &minor)) {
if (major >= 2)
data->use_xdamage = SDL_TRUE;
}
}
#endif
if (data->use_xrender) {
/* Find the PictFormat from the visual.
* Should be an RGB PictFormat most of the time. */
data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display,
data->visual);
if (!data->xwindow_pict_fmt) {
SDL_SetError("XRenderFindVisualFormat() failed");
return NULL;
}
data->xwindow_pict = XRenderCreatePicture(data->display,
data->xwindow,
data->xwindow_pict_fmt,
0, NULL);
if (!data->xwindow_pict) {
SDL_SetError("XRenderCreatePicture() failed");
return NULL;
}
// FIXME: Clear the window. Is this required?
XRenderComposite(data->display,
PictOpClear,
data->xwindow_pict,
None,
data->xwindow_pict,
0, 0,
0, 0,
0, 0,
window->w, window->h);
/* Create a clip mask that is used for rendering primitives. */
data->stencil = XCreatePixmap(data->display, data->xwindow,
window->w, window->h, 32);
/* Create the GC for the clip mask. */
data->stencil_gc = XCreateGC(data->display, data->stencil,
GCGraphicsExposures, &gcv);
XSetBackground(data->display, data->stencil_gc, 0);
XSetForeground(data->display, data->stencil_gc, 0);
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
data->stencil_pict =
XRenderCreatePicture(data->display, data->stencil,
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, NULL);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage) {
data->stencil_damage =
XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty);
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
}
#endif
data->brush =
XCreatePixmap(data->display, data->xwindow, 1, 1, 32);
XRenderPictureAttributes brush_attr;
brush_attr.repeat = RepeatNormal;
data->brush_pict =
XRenderCreatePicture(data->display, data->brush,
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
CPRepeat, &brush_attr);
// Set the default blending mode.
renderer->blendMode = SDL_BLENDMODE_BLEND;
data->blend_op = PictOpOver;
}
#endif
if (flags & SDL_RENDERER_SINGLEBUFFER) {
renderer->info.flags |=
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
......@@ -239,39 +477,110 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
n = 1;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
if (n > 0)
data->drawable_pict_fmt =
XRenderFindStandardFormat(data->display, PictStandardARGB32);
else
data->drawable_pict_fmt = data->xwindow_pict_fmt;
}
#endif
for (i = 0; i < n; ++i) {
data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h,
displaydata->depth);
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
data->pixmaps[i] = XCreatePixmap(data->display,
data->xwindow,
window->w,
window->h,
32);
}
else
#endif
{
data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h,
displaydata->depth);
}
if (data->pixmaps[i] == None) {
X11_DestroyRenderer(renderer);
SDL_SetError("XCreatePixmap() failed");
return NULL;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
/* Create xrender pictures for each of the pixmaps
* and clear the pixmaps. */
data->pixmap_picts[i] =
XRenderCreatePicture(data->display,
data->pixmaps[i],
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, None);
if (!data->pixmap_picts[i]) {
SDL_SetError("XRenderCreatePicture() failed");
return NULL;
}
XRenderComposite(data->display,
PictOpClear,
data->pixmap_picts[i],
None,
data->pixmap_picts[i],
0, 0,
0, 0,
0, 0,
window->w, window->h);
}
#endif
}
if (n > 0) {
data->drawable = data->pixmaps[0];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->use_xrender == SDL_TRUE)
data->drawable_pict = data->pixmap_picts[0];
#endif
data->makedirty = SDL_TRUE;
} else {
data->drawable = data->xwindow;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->use_xrender == SDL_TRUE)
data->drawable_pict = data->xwindow_pict;
#endif
data->makedirty = SDL_FALSE;
}
data->current_pixmap = 0;
/* Get the format of the window */
if (!SDL_PixelFormatEnumToMasks
(display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
&Amask)) {
SDL_SetError("Unknown display format");
X11_DestroyRenderer(renderer);
return NULL;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
bpp = data->drawable_pict_fmt->depth;
Rmask = ((data->drawable_pict_fmt->direct.redMask)
<< (data->drawable_pict_fmt->direct.red));
Gmask = ((data->drawable_pict_fmt->direct.greenMask)
<< (data->drawable_pict_fmt->direct.green));
Bmask = ((data->drawable_pict_fmt->direct.blueMask)
<< (data->drawable_pict_fmt->direct.blue));
Amask = ((data->drawable_pict_fmt->direct.alphaMask)
<< (data->drawable_pict_fmt->direct.alpha));
}
else
#endif
{
/* Get the format of the window */
if (!SDL_PixelFormatEnumToMasks
(display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
&Amask)) {
SDL_SetError("Unknown display format");
X11_DestroyRenderer(renderer);
return NULL;
}
}
SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
/* Create the drawing context */
gcv.graphics_exposures = False;
data->gc =
XCreateGC(data->display, data->xwindow, GCGraphicsExposures, &gcv);
XCreateGC(data->display, data->drawable, GCGraphicsExposures, &gcv);
if (!data->gc) {
X11_DestroyRenderer(renderer);
SDL_SetError("XCreateGC() failed");
......@@ -288,6 +597,47 @@ X11_DisplayModeChanged(SDL_Renderer * renderer)
SDL_Window *window = renderer->window;
int i, n;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
XRenderFreePicture(data->display, data->xwindow_pict);
data->xwindow_pict_fmt =
XRenderFindVisualFormat(data->display, data->visual);
data->xwindow_pict =
XRenderCreatePicture(data->display, data->xwindow,
data->xwindow_pict_fmt, 0, NULL);
XRenderComposite(data->display,
PictOpClear,
data->xwindow_pict,
None,
data->xwindow_pict,
0, 0,
0, 0,
0, 0,
window->w, window->h);
XFreePixmap(data->display, data->stencil);
/* Create a clip mask that is used for rendering primitives. */
data->stencil = XCreatePixmap(data->display, data->xwindow,
window->w, window->h, 32);
XRenderFreePicture(data->display, data->stencil_pict);
data->stencil_pict =
XRenderCreatePicture(data->display, data->stencil,
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, NULL);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
XDamageDestroy(data->display, data->stencil_damage);
if (data->use_xdamage) {
data->stencil_damage =
XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty);
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
}
#endif
}
#endif
if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
n = 0;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
......@@ -301,25 +651,170 @@ X11_DisplayModeChanged(SDL_Renderer * renderer)
if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]);
data->pixmaps[i] = None;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
XRenderFreePicture(data->display, data->pixmap_picts[i]);
data->pixmap_picts[i] = None;
#endif
}
}
for (i = 0; i < n; ++i) {
data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h,
data->depth);
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
data->pixmaps[i] =
XCreatePixmap(data->display,
data->xwindow,
window->w,
window->h,
32);
}
else
#endif
{
data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h,
data->depth);
}
if (data->pixmaps[i] == None) {
SDL_SetError("XCreatePixmap() failed");
return -1;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
data->pixmap_picts[i] =
XRenderCreatePicture(data->display,
data->pixmaps[i],
XRenderFindStandardFormat(data->display,
PictStandardARGB32),
0, None);
if (!data->pixmap_picts[i]) {
SDL_SetError("XRenderCreatePicture() failed");
return -1;
}
XRenderComposite(data->display,
PictOpClear,
data->pixmap_picts[i],
None,
data->pixmap_picts[i],
0, 0,
0, 0,
0, 0,
window->w, window->h);
}
#endif
}
if (n > 0) {
data->drawable = data->pixmaps[0];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[0];
#endif
}
data->current_pixmap = 0;
return 0;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
static void
SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) {
if (sdl_mask == 0) {
*comp = 0;
*compMask = 0;
} else {
(*comp) = 0;
(*compMask) = 0;
while(!(sdl_mask & 1)) {
(*comp)++;
sdl_mask >>= 1;
}
while(sdl_mask & 1) {
(*compMask) = ((*compMask) << 1) | 1;
sdl_mask >>= 1;
}
}
}
static XRenderPictFormat*
PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format) {
XRenderPictFormat* pict_fmt = NULL;
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
if (data->use_xrender) {
int bpp;
Uint32 Amask, Rmask, Gmask, Bmask;
if(!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
SDL_SetError("Unknown pixel format");
return NULL;
}
XRenderPictFormat templ;
unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed |
PictFormatRedMask | PictFormatGreen | PictFormatGreenMask |
PictFormatBlue | PictFormatBlueMask | PictFormatAlpha |
PictFormatAlphaMask);
templ.type = PictTypeDirect;
templ.depth = bpp;
SDLMaskToXRenderMask(Amask, &(templ.direct.alpha), &(templ.direct.alphaMask));
SDLMaskToXRenderMask(Rmask, &(templ.direct.red), &(templ.direct.redMask));
SDLMaskToXRenderMask(Gmask, &(templ.direct.green), &(templ.direct.greenMask));
SDLMaskToXRenderMask(Bmask, &(templ.direct.blue), &(templ.direct.blueMask));
pict_fmt = XRenderFindFormat(data->display, mask, &templ, 0);
}
return pict_fmt;
}
static Visual*
PixelFormatEnumToVisual(SDL_Renderer * renderer, Uint32 format) {
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
if (data->use_xrender) {
int bpp;
Uint32 Amask, Rmask, Gmask, Bmask;
SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
XVisualInfo vinfo_templ;
long vinfo_mask;
int nitems_return;
vinfo_mask = (VisualDepthMask | VisualRedMaskMask |
VisualGreenMaskMask | VisualBlueMaskMask);
vinfo_templ.depth = bpp;
vinfo_templ.red_mask = Rmask;
vinfo_templ.green_mask = Gmask;
vinfo_templ.blue_mask = Bmask;
XVisualInfo * ret = XGetVisualInfo(data->display, vinfo_mask,
&vinfo_templ, &nitems_return);
if (nitems_return) {
return ret[0].visual;
}
}
return NULL;
}
static XRenderColor
SDLColorToXRenderColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
double rd, gd, bd, ad;
XRenderColor ret;
rd = r / 255.0;
gd = g / 255.0;
bd = b / 255.0;
ad = a / 255.0;
ret.red = (unsigned short) (rd * ad * 0xFFFF);
ret.green = (unsigned short) (gd * ad * 0xFFFF);
ret.blue = (unsigned short) (bd * ad * 0xFFFF);
ret.alpha = (unsigned short) (ad * 0xFFFF);
return ret;
}
#endif
static int
X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
......@@ -328,15 +823,18 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
SDL_VideoDisplay *display = window->display;
X11_TextureData *data;
int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1);
XGCValues gcv;
data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
if (!data) {
SDL_OutOfMemory();
return -1;
}
data->depth = renderdata->depth;
data->visual = renderdata->visual;
data->gc = renderdata->gc;
texture->driverdata = data;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
data->yuv =
SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
......@@ -345,18 +843,26 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
}
data->format = display->current_mode.format;
} else {
/* The image/pixmap depth must be the same as the window or you
get a BadMatch error when trying to putimage or copyarea.
*/
if (texture->format != display->current_mode.format) {
SDL_SetError("Texture format doesn't match window format");
return -1;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender)
{
Uint32 Amask, Rmask, Gmask, Bmask;
SDL_PixelFormatEnumToMasks(texture->format, &(data->depth),
&Rmask, &Gmask, &Bmask, &Amask);
data->visual = PixelFormatEnumToVisual(renderer, texture->format);
}
else
#endif
{
if (texture->format != display->current_mode.format)
{
SDL_SetError("Texture format doesn't match window format");
return -1;
}
}
data->format = texture->format;
}
data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format);
data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask;
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
#ifndef NO_SHARED_MEMORY
XShmSegmentInfo *shminfo = &data->shminfo;
......@@ -364,37 +870,42 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
shm_error = True;
if (SDL_X11_HAVE_SHM) {
shminfo->shmid =
shmget(IPC_PRIVATE, texture->h * data->pitch,
IPC_CREAT | 0777);
if (shminfo->shmid >= 0) {
shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
shminfo->readOnly = False;
if (shminfo->shmaddr != (char *) -1) {
shm_error = False;
X_handler = XSetErrorHandler(shm_errhandler);
XShmAttach(renderdata->display, shminfo);
XSync(renderdata->display, False);
XSetErrorHandler(X_handler);
if (shm_error) {
shmdt(shminfo->shmaddr);
}
}
shmctl(shminfo->shmid, IPC_RMID, NULL);
}
}
if (!shm_error) {
data->pixels = shminfo->shmaddr;
data->image =
XShmCreateImage(renderdata->display, renderdata->visual,
renderdata->depth, ZPixmap, shminfo->shmaddr,
XShmCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, NULL,
shminfo, texture->w, texture->h);
if (!data->image) {
XShmDetach(renderdata->display, shminfo);
XSync(renderdata->display, False);
shmdt(shminfo->shmaddr);
shm_error = True;
if (data->image) {
shminfo->shmid =
shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line,
IPC_CREAT | 0777);
if (shminfo->shmid >= 0) {
shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
shminfo->readOnly = False;
if (shminfo->shmaddr != (char *) -1) {
shm_error = False;
X_handler = XSetErrorHandler(shm_errhandler);
XShmAttach(renderdata->display, shminfo);
XSync(renderdata->display, False);
XSetErrorHandler(X_handler);
if (shm_error) {
XShmDetach(renderdata->display, shminfo);
shmdt(shminfo->shmaddr);
XDestroyImage(data->image);
XSync(renderdata->display, False);
}
else {
data->pixels = data->image->data = shminfo->shmaddr;
shmctl(shminfo->shmid, IPC_RMID, NULL);
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow,
texture->w, texture->h, data->depth);
if (!data->pixmap) {
SDL_SetError("XCreatePixmap() failed");
return -1;
}
}
}
}
}
}
if (shm_error) {
......@@ -403,47 +914,102 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (!data->image)
#endif /* not NO_SHARED_MEMORY */
{
data->pixels = SDL_malloc(texture->h * data->pitch);
if (!data->pixels) {
X11_DestroyTexture(renderer, texture);
SDL_OutOfMemory();
return -1;
}
data->image =
XCreateImage(renderdata->display, renderdata->visual,
renderdata->depth, ZPixmap, 0, data->pixels,
XCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, 0, NULL,
texture->w, texture->h,
SDL_BYTESPERPIXEL(data->format) * 8,
data->pitch);
0);
if (!data->image) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed");
return -1;
}
data->pixels = SDL_malloc(texture->h * data->image->bytes_per_line);
if (!data->pixels) {
X11_DestroyTexture(renderer, texture);
SDL_OutOfMemory();
return -1;
}
data->image->data = data->pixels;
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
texture->h, data->depth);
if (data->pixmap == None) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed");
return -1;
}
}
}
else {
data->image =
XCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, 0, NULL,
texture->w, texture->h,
SDL_BYTESPERPIXEL(data->format) * 8,
0);
if (!data->image) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed");
return -1;
}
} else {
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
texture->h, renderdata->depth);
texture->h, data->depth);
if (data->pixmap == None) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed");
return -1;
}
}
data->image =
XCreateImage(renderdata->display, renderdata->visual,
renderdata->depth, ZPixmap, 0, NULL, texture->w,
texture->h, SDL_BYTESPERPIXEL(data->format) * 8,
data->pitch);
if (!data->image) {
data->pitch = data->image->bytes_per_line;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(renderdata->use_xrender) {
gcv.graphics_exposures = False;
data->gc =
XCreateGC(renderdata->display, data->pixmap, GCGraphicsExposures, &gcv);
if (!data->gc) {
SDL_SetError("XCreateGC() failed");
return -1;
}
data->picture_fmt =
PixelFormatEnumToXRenderPictFormat(renderer, texture->format);
if (data->picture_fmt == NULL) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed");
SDL_SetError("Texture format not supported by driver");
return -1;
}
data->picture =
XRenderCreatePicture(renderdata->display, data->pixmap,
data->picture_fmt, 0, NULL);
if (!data->picture) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XRenderCreatePicture() failed");
return -1;
}
data->modulated_pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow,
texture->w, texture->h, data->depth);
if (!data->modulated_pixmap) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed");
return -1;
}
data->modulated_picture =
XRenderCreatePicture(renderdata->display, data->modulated_pixmap,
data->picture_fmt, 0, NULL);
if (!data->modulated_picture) {
X11_DestroyTexture(renderer, texture);
SDL_SetError("XRenderCreatePicture() failed");
return -1;
}
texture->blendMode = SDL_BLENDMODE_NONE;
data->blend_op = PictOpSrc;
}
#endif
return 0;
}
......@@ -462,15 +1028,107 @@ X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
}
}
static int
X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
if (renderdata->use_xrender) {
Uint8 r = 0xFF, g = 0xFF, b = 0xFF, a = 0xFF;
/* Check if alpha modulation is required. */
if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
a = texture->a;
}
/* Check if color modulation is required. */
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
r = texture->r;
g = texture->g;
b = texture->b;
}
/* We can save some labour if no modulation is required. */
if (texture->modMode != SDL_TEXTUREMODULATE_NONE) {
XRenderColor mod_color =
SDLColorToXRenderColor(r, g, b, a);
XRenderFillRectangle(renderdata->display, PictOpSrc,
renderdata->brush_pict, &mod_color,
0, 0, 1, 1);
}
/* We can save some labour dealing with component alpha
* if color modulation is not required. */
XRenderPictureAttributes attr;
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
attr.component_alpha = True;
XRenderChangePicture(renderdata->display, renderdata->brush_pict,
CPComponentAlpha, &attr);
}
/* Again none of this is necessary is no modulation
* is required. */
if (texture->modMode != SDL_TEXTUREMODULATE_NONE) {
XRenderComposite(renderdata->display, PictOpSrc,
data->picture, renderdata->brush_pict,
data->modulated_picture,
0, 0, 0, 0, 0, 0, texture->w, texture->h);
}
/* We only need to reset the component alpha
* attribute if color modulation is required. */
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
attr.component_alpha = False;
XRenderChangePicture(renderdata->display, renderdata->brush_pict,
CPComponentAlpha, &attr);
}
return 0;
}
else {
SDL_Unsupported();
return -1;
}
}
static int
X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
switch (texture->blendMode) {
case SDL_BLENDMODE_NONE:
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
data->blend_op = PictOpSrc;
return 0;
}
case SDL_BLENDMODE_MOD:
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND:
if (renderdata->use_xrender) {
data->blend_op = PictOpOver;
return 0;
}
case SDL_BLENDMODE_ADD:
if (renderdata->use_xrender) {
data->blend_op = PictOpAdd;
return 0;
}
#endif
return 0;
default:
SDL_Unsupported();
texture->blendMode = SDL_BLENDMODE_NONE;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
texture->blendMode = SDL_BLENDMODE_BLEND;
data->blend_op = PictOpOver;
}
#endif
return -1;
}
}
......@@ -479,6 +1137,7 @@ static int
X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
switch (texture->scaleMode) {
case SDL_TEXTURESCALEMODE_NONE:
......@@ -488,10 +1147,33 @@ X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
return 0;
}
/* Fall through to unsupported case */
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
data->filter = FilterFast;
return 0;
}
case SDL_TEXTURESCALEMODE_SLOW:
if (renderdata->use_xrender) {
data->filter = FilterGood;
return 0;
}
case SDL_TEXTURESCALEMODE_BEST:
if (renderdata->use_xrender) {
data->filter = FilterBest;
return 0;
}
#endif
/* Fall through to unsupported case */
default:
SDL_Unsupported();
texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
texture->scaleMode = SDL_TEXTURESCALEMODE_FAST;
data->filter = FilterFast;
}
else
#endif
texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
return -1;
}
return 0;
......@@ -532,7 +1214,7 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
data->image->height = rect->h;
data->image->data = (char *) pixels;
data->image->bytes_per_line = pitch;
XPutImage(renderdata->display, data->pixmap, renderdata->gc,
XPutImage(renderdata->display, data->pixmap, data->gc,
data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
}
return 0;
......@@ -575,12 +1257,36 @@ X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
static int
X11_SetDrawBlendMode(SDL_Renderer * renderer)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
switch (renderer->blendMode) {
case SDL_BLENDMODE_NONE:
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
//PictOpSrc
data->blend_op = PictOpSrc;
return 0;
case SDL_BLENDMODE_MOD:
case SDL_BLENDMODE_MASK:
case SDL_BLENDMODE_BLEND: // PictOpOver
data->blend_op = PictOpOver;
return 0;
case SDL_BLENDMODE_ADD: // PictOpAdd
data->blend_op = PictOpAdd;
return 0;
/* FIXME case SDL_BLENDMODE_MOD: */
#endif
return 0;
default:
SDL_Unsupported();
renderer->blendMode = SDL_BLENDMODE_NONE;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->use_xrender) {
renderer->blendMode = SDL_BLENDMODE_BLEND;
data->blend_op = PictOpOver;
}
else
#endif
{
renderer->blendMode = SDL_BLENDMODE_NONE;
}
return -1;
}
}
......@@ -601,16 +1307,35 @@ renderdrawcolor(SDL_Renderer * renderer, int premult)
return SDL_MapRGBA(&data->format, r, g, b, a);
}
static XRenderColor
xrenderdrawcolor(SDL_Renderer *renderer)
{
XRenderColor xrender_color;
if(renderer->blendMode == SDL_BLENDMODE_NONE) {
xrender_color =
SDLColorToXRenderColor(renderer->r, renderer->g, renderer->b, 0xFF);
}
else {
xrender_color =
SDLColorToXRenderColor(renderer->r, renderer->g, renderer->b, renderer->a);
}
return xrender_color;
}
static int
X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
int count)
{
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
unsigned long foreground;
XPoint *xpoints, *xpoint;
int i, xcount;
SDL_Rect clip;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
if (data->makedirty) {
SDL_Rect rect;
......@@ -625,27 +1350,105 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
}
SDL_AddDirtyRect(&data->dirty, &rect);
}
{
xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0;
for (i = 0; i < count; ++i) {
int x = points[i].x;
int y = points[i].y;
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
continue;
}
xpoint->x = (short)x;
xpoint->y = (short)y;
++xpoint;
++xcount;
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XSetForeground(data->display, data->stencil_gc, 0);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
/* Update only those parts which were changed
* in the previous drawing operation */
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, data->stencil_parts);
}
#endif
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None);
}
#endif
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount,
CoordModeOrigin);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
/* Store the damaged region in stencil_parts */
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
}
#endif
}
#endif
}
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0;
for (i = 0; i < count; ++i) {
int x = points[i].x;
int y = points[i].y;
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
continue;
XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
&foreground, 0, 0, 1, 1);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
/* Update only those parts which drawn
* to in the current drawing operation */
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, data->stencil_parts);
}
xpoint->x = (short)x;
xpoint->y = (short)y;
++xpoint;
++xcount;
#endif
XRenderComposite(data->display, data->blend_op, data->brush_pict,
data->stencil_pict, data->drawable_pict,
0, 0, 0, 0, 0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None);
}
#endif
}
if (xcount > 0) {
XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
CoordModeOrigin);
else
#endif
{
unsigned long foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
if (xcount > 0) {
XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
CoordModeOrigin);
}
}
SDL_stack_free(xpoints);
return 0;
......@@ -668,65 +1471,146 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0;
minx = INT_MAX;
miny = INT_MAX;
maxx = INT_MIN;
maxy = INT_MIN;
for (i = 0; i < count; ++i) {
int x = points[i].x;
int y = points[i].y;
/* If the point is inside the window, add it to the list */
if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
xpoint->x = (short)x;
xpoint->y = (short)y;
++xpoint;
++xcount;
continue;
{
Pixmap drawable;
GC gc;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
drawable = data->stencil;
gc = data->stencil_gc;
XSetForeground(data->display, data->stencil_gc, 0);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, data->stencil_parts);
#endif
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, None);
#endif
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
}
else
#endif
{
drawable = data->drawable;
gc = data->gc;
}
/* We need to clip the line segments joined by this point */
if (xcount > 0) {
int x1 = xpoint[-1].x;
int y1 = xpoint[-1].y;
int x2 = x;
int y2 = y;
if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
if (x2 < minx) {
minx = x2;
} else if (x2 > maxx) {
maxx = x2;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0;
minx = INT_MAX;
miny = INT_MAX;
maxx = INT_MIN;
maxy = INT_MIN;
for (i = 0; i < count; ++i) {
int x = points[i].x;
int y = points[i].y;
/* If the point is inside the window, add it to the list */
if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y2 < miny) {
miny = y2;
} else if (y2 > maxy) {
maxy = y2;
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
xpoint->x = (short)x2;
xpoint->y = (short)y2;
xpoint->x = (short)x;
xpoint->y = (short)y;
++xpoint;
++xcount;
continue;
}
/* We need to clip the line segments joined by this point */
if (xcount > 0) {
int x1 = xpoint[-1].x;
int y1 = xpoint[-1].y;
int x2 = x;
int y2 = y;
if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
if (x2 < minx) {
minx = x2;
} else if (x2 > maxx) {
maxx = x2;
}
if (y2 < miny) {
miny = y2;
} else if (y2 > maxy) {
maxy = y2;
}
xpoint->x = (short)x2;
xpoint->y = (short)y2;
++xpoint;
++xcount;
}
XDrawLines(data->display, drawable, gc,
xpoints, xcount, CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) {
XDrawPoint(data->display, drawable, gc, x2, y2);
}
if (data->makedirty) {
SDL_Rect rect;
rect.x = minx;
rect.y = miny;
rect.w = (maxx - minx) + 1;
rect.h = (maxy - miny) + 1;
SDL_AddDirtyRect(&data->dirty, &rect);
}
xpoint = xpoints;
xcount = 0;
minx = INT_MAX;
miny = INT_MAX;
maxx = INT_MIN;
maxy = INT_MIN;
}
if (i < (count-1)) {
int x1 = x;
int y1 = y;
int x2 = points[i+1].x;
int y2 = points[i+1].y;
if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
if (x1 < minx) {
minx = x1;
} else if (x1 > maxx) {
maxx = x1;
}
if (y1 < miny) {
miny = y1;
} else if (y1 > maxy) {
maxy = y1;
}
xpoint->x = (short)x1;
xpoint->y = (short)y1;
++xpoint;
++xcount;
}
}
XDrawLines(data->display, data->drawable, data->gc,
xpoints, xcount, CoordModeOrigin);
}
if (xcount > 1) {
int x2 = xpoint[-1].x;
int y2 = xpoint[-1].y;
XDrawLines(data->display, drawable, gc, xpoints, xcount,
CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) {
XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
XDrawPoint(data->display, drawable, gc, x2, y2);
}
if (data->makedirty) {
SDL_Rect rect;
......@@ -737,54 +1621,37 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
rect.h = (maxy - miny) + 1;
SDL_AddDirtyRect(&data->dirty, &rect);
}
xpoint = xpoints;
xcount = 0;
minx = INT_MAX;
miny = INT_MAX;
maxx = INT_MIN;
maxy = INT_MIN;
}
if (i < (count-1)) {
int x1 = x;
int y1 = y;
int x2 = points[i+1].x;
int y2 = points[i+1].y;
if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
if (x1 < minx) {
minx = x1;
} else if (x1 > maxx) {
maxx = x1;
}
if (y1 < miny) {
miny = y1;
} else if (y1 > maxy) {
maxy = y1;
}
xpoint->x = (short)x1;
xpoint->y = (short)y1;
++xpoint;
++xcount;
}
}
}
if (xcount > 1) {
int x2 = xpoint[-1].x;
int y2 = xpoint[-1].y;
XDrawLines(data->display, data->drawable, data->gc, xpoints, xcount,
CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) {
XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
}
if (data->makedirty) {
SDL_Rect rect;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XRenderColor xrforeground = xrenderdrawcolor(renderer);
XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
&xrforeground, 0, 0, 1, 1);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
{
XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts);
rect.x = minx;
rect.y = miny;
rect.w = (maxx - minx) + 1;
rect.h = (maxy - miny) + 1;
SDL_AddDirtyRect(&data->dirty, &rect);
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, data->stencil_parts);
}
#endif
XRenderComposite(data->display, data->blend_op, data->brush_pict,
data->stencil_pict, data->drawable_pict,
0, 0, 0, 0, 0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, None);
#endif
}
#endif
SDL_stack_free(xpoints);
return 0;
......@@ -796,41 +1663,104 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
unsigned long foreground;
XRectangle *xrects, *xrect;
int i, xcount;
XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
{
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
for (i = 0; i < count; ++i) {
if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
continue;
}
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
for (i = 0; i < count; ++i) {
if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
continue;
xrect->x = (short)rect.x;
xrect->y = (short)rect.y;
xrect->width = (unsigned short)rect.w - 1;
xrect->height = (unsigned short)rect.h - 1;
++xrect;
++xcount;
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XSetForeground(data->display, data->stencil_gc, 0);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, data->stencil_parts);
#endif
XFillRectangle(data->display, data->stencil, data->stencil_gc,
0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetGCClipRegion(data->display, data->stencil_gc,
0, 0, None);
#endif
XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF);
xrect->x = (short)rect.x;
xrect->y = (short)rect.y;
xrect->width = (unsigned short)rect.w;
xrect->height = (unsigned short)rect.h;
++xrect;
++xcount;
XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount);
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, &rect);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XDamageSubtract(data->display, data->stencil_damage,
None, data->stencil_parts);
#endif
}
#endif
}
if (xcount > 0) {
XDrawRectangles(data->display, data->drawable, data->gc,
xrects, xcount);
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender &&
(renderer->blendMode != SDL_BLENDMODE_NONE) &&
!(renderer->a == 0xFF &&
renderer->blendMode != SDL_BLENDMODE_ADD &&
renderer->blendMode != SDL_BLENDMODE_MOD))
{
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict,
&foreground, 0, 0, 1, 1);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, data->stencil_parts);
#endif
XRenderComposite(data->display, data->blend_op, data->brush_pict,
data->stencil_pict, data->drawable_pict,
0, 0, 0, 0, 0, 0, window->w, window->h);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XFixesSetPictureClipRegion(data->display, data->drawable_pict,
0, 0, None);
#endif
}
SDL_stack_free(xpoints);
else
#endif
{
unsigned long foreground;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
if (xcount > 0) {
XDrawRectangles(data->display, data->drawable, data->gc,
xrects, xcount);
}
}
SDL_stack_free(xrects);
return 0;
}
......@@ -841,18 +1771,14 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
unsigned long foreground;
XRectangle *xrects, *xrect;
int i, xcount;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
int i, xcount;
XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
for (i = 0; i < count; ++i) {
......@@ -871,12 +1797,34 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
if (xcount > 0) {
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
if (xcount == 1) {
XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict,
&foreground, xrects[0].x, xrects[0].y,
xrects[0].width, xrects[0].height);
}
else if (xcount > 1) {
XRenderFillRectangles(data->display, data->blend_op, data->drawable_pict,
&foreground, xrects, xcount);
}
}
else
#endif
{
unsigned long foreground;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
XFillRectangles(data->display, data->drawable, data->gc,
xrects, xcount);
}
SDL_stack_free(xpoints);
SDL_stack_free(xrects);
return 0;
}
......@@ -890,103 +1838,206 @@ 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) {
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
if(texture->access == SDL_TEXTUREACCESS_STREAMING) {
#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
#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);
} else {
XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w,
dstrect->h, dstrect->x, dstrect->y);
if(texturedata->shminfo.shmaddr) {
XShmPutImage(data->display, texturedata->pixmap, texturedata->gc,
texturedata->image, srcrect->x, srcrect->y,
srcrect->x, srcrect->y, srcrect->w, srcrect->h,
False);
}
else
#endif
if (texturedata->pixels) {
XPutImage(data->display, texturedata->pixmap, texturedata->gc,
texturedata->image, srcrect->x, srcrect->y, srcrect->x,
srcrect->y, srcrect->w, srcrect->h);
}
XSync(data->display, False);
}
} else if (texturedata->yuv
|| texture->access == SDL_TEXTUREACCESS_STREAMING) {
SDL_Surface src, dst;
SDL_PixelFormat fmt;
SDL_Rect rect;
XImage *image = texturedata->scaling_image;
Picture src, mask;
XRenderPictureAttributes attr;
const SDL_Rect *mrect;
if (!image) {
void *pixels;
int pitch;
if (texture->modMode == SDL_TEXTUREMODULATE_NONE) {
src = texturedata->picture;
}
else {
src = texturedata->modulated_picture;
}
pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
pixels = SDL_malloc(dstrect->h * pitch);
if (!pixels) {
SDL_OutOfMemory();
return -1;
}
if(texture->blendMode == SDL_BLENDMODE_NONE)
{
mask = None;
mrect = srcrect;
}
else if (texture->blendMode == SDL_BLENDMODE_MOD)
{
mask = data->stencil_pict;
mrect = dstrect;
}
else
{
mask = texturedata->picture;
mrect = srcrect;
}
image =
XCreateImage(data->display, data->visual, data->depth,
ZPixmap, 0, pixels, dstrect->w, dstrect->h,
SDL_BYTESPERPIXEL(texturedata->format) * 8,
pitch);
if (!image) {
SDL_SetError("XCreateImage() failed");
return -1;
if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
if (texture->blendMode == SDL_BLENDMODE_MOD) {
XRenderComposite(data->display, PictOpSrc, data->drawable_pict,
src, data->stencil_pict,
dstrect->x, dstrect->y, srcrect->x, srcrect->y,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
attr.component_alpha = True;
XRenderChangePicture(data->display, data->stencil_pict,
CPComponentAlpha, &attr);
}
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;
XRenderComposite(data->display, texturedata->blend_op,
src, mask, data->drawable_pict, srcrect->x, srcrect->y,
mrect->x, mrect->y, dstrect->x, dstrect->y,
dstrect->w, dstrect->h);
} else {
double xscale = ((double) dstrect->w) / srcrect->w;
double yscale = ((double) dstrect->h) / srcrect->h;
XTransform xform = {{
{XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}};
XRenderSetPictureTransform(data->display, src, &xform);
if (texture->blendMode == SDL_BLENDMODE_MOD) {
XRenderComposite(data->display, PictOpSrc, data->drawable_pict,
src, data->stencil_pict,
dstrect->x, dstrect->y, srcrect->x, srcrect->y,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
attr.component_alpha = True;
XRenderChangePicture(data->display, data->stencil_pict,
CPComponentAlpha, &attr);
}
}
/* Set up fake surfaces for SDL_SoftStretch() */
SDL_zero(src);
src.format = &fmt;
src.w = texture->w;
src.h = texture->h;
XRenderSetPictureFilter(data->display, src,
texturedata->filter, 0, 0);
XRenderComposite(data->display, texturedata->blend_op,
src, mask, data->drawable_pict,
srcrect->x, srcrect->y, mrect->x, mrect->y,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
XTransform identity = {{
{XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}};
XRenderSetPictureTransform(data->display, src, &identity);
}
if (renderer->blendMode == SDL_BLENDMODE_MOD) {
attr.component_alpha = False;
XRenderChangePicture(data->display, data->stencil_pict,
CPComponentAlpha, &attr);
}
}
else
#endif
{
if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
#ifndef NO_SHARED_MEMORY
if (texturedata->shminfo.shmaddr) {
src.pixels = texturedata->shminfo.shmaddr;
} 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
src.pixels = texturedata->pixels;
src.pitch = texturedata->pitch;
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, dstrect->x, dstrect->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;
SDL_zero(dst);
dst.format = &fmt;
dst.w = image->width;
dst.h = image->height;
dst.pixels = image->data;
dst.pitch = image->bytes_per_line;
if (!image) {
void *pixels;
int pitch;
pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
pixels = SDL_malloc(dstrect->h * pitch);
if (!pixels) {
SDL_OutOfMemory();
return -1;
}
fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
image =
XCreateImage(data->display, data->visual, data->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;
}
}
rect.x = 0;
rect.y = 0;
rect.w = dstrect->w;
rect.h = dstrect->h;
if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
return -1;
/* Set up fake surfaces for SDL_SoftStretch() */
SDL_zero(src);
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;
SDL_zero(dst);
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,
srcrect->x, srcrect->y);
}
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,
srcrect->x, srcrect->y);
}
return 0;
}
......@@ -1065,9 +2116,26 @@ X11_RenderPresent(SDL_Renderer * renderer)
if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
const SDL_Rect *rect = &dirty->rect;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender)
{
XRenderComposite(data->display,
data->blend_op,
data->drawable_pict,
None,
data->xwindow_pict,
rect->x, rect->y,
0, 0,
rect->x, rect->y,
rect->w, rect->h);
}
else
#endif
{
XCopyArea(data->display, data->drawable, data->xwindow,
data->gc, rect->x, rect->y, rect->w, rect->h,
rect->x, rect->y);
}
}
SDL_ClearDirtyRects(&data->dirty);
}
......@@ -1077,9 +2145,15 @@ X11_RenderPresent(SDL_Renderer * renderer)
if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
data->current_pixmap = (data->current_pixmap + 1) % 2;
data->drawable = data->pixmaps[data->current_pixmap];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[data->current_pixmap];
#endif
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
data->current_pixmap = (data->current_pixmap + 1) % 3;
data->drawable = data->pixmaps[data->current_pixmap];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[data->current_pixmap];
#endif
}
}
......@@ -1109,6 +2183,19 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
shmdt(data->shminfo.shmaddr);
data->pixels = NULL;
}
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (renderdata->use_xrender) {
if (data->picture) {
XRenderFreePicture(renderdata->display, data->picture);
}
if (data->modulated_pixmap) {
XFreePixmap(renderdata->display, data->modulated_pixmap);
}
if (data->modulated_picture) {
XRenderFreePicture(renderdata->display, data->modulated_picture);
}
}
#endif
if (data->scaling_image) {
SDL_free(data->scaling_image->data);
......@@ -1133,10 +2220,36 @@ X11_DestroyRenderer(SDL_Renderer * renderer)
if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender && data->pixmap_picts[i]) {
XRenderFreePicture(data->display, data->pixmap_picts[i]);
}
#endif
}
if (data->gc) {
XFreeGC(data->display, data->gc);
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
if (data->stencil_gc) {
XFreeGC(data->display, data->stencil_gc);
}
if (data->stencil) {
XFreePixmap(data->display, data->stencil);
}
if (data->stencil_pict) {
XRenderFreePicture(data->display, data->stencil_pict);
}
if (data->xwindow_pict) {
XRenderFreePicture(data->display, data->xwindow_pict);
}
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage && data->stencil_damage) {
XDamageDestroy(data->display, data->stencil_damage);
}
#endif
}
#endif
SDL_FreeDirtyRects(&data->dirty);
SDL_free(data);
}
......
......@@ -156,6 +156,10 @@ SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),r
SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return)
SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return)
SDL_X11_SYM(XExtensionErrorHandler,XSetExtensionErrorHandler,(XExtensionErrorHandler a),(a),return)
SDL_X11_SYM(int,XFillRectangle,(Display *dpy,Drawable d,GC gc,int x,int y,unsigned int width,unsigned int height),(dpy,d,gc,x,y,width,height),return)
SDL_X11_SYM(int,XSetBackground,(Display *dpy,GC gc,unsigned long background),(dpy,gc,background),return)
SDL_X11_SYM(Status,XInitImage,(XImage *image),(image),return)
SDL_X11_SYM(int,XSetClipMask,(Display *dpy,GC gc,Pixmap pixmap),(dpy,gc,pixmap),return)
#if NeedWidePrototypes
SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return)
......@@ -182,6 +186,7 @@ SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b),(a,b),return)
SDL_X11_SYM(Status,XShmDetach,(Display* a,XShmSegmentInfo* b),(a,b),return)
SDL_X11_SYM(Status,XShmPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j,Bool k),(a,b,c,d,e,f,g,h,i,j,k),return)
SDL_X11_SYM(XImage*,XShmCreateImage,(Display* a,Visual* b,unsigned int c,int d,char* e,XShmSegmentInfo* f,unsigned int g,unsigned int h),(a,b,c,d,e,f,g,h),return)
SDL_X11_SYM(Pixmap,XShmCreatePixmap,(Display *a,Drawable b,char* c,XShmSegmentInfo* d, unsigned int e, unsigned int f, unsigned int g),(a,b,c,d,e,f,g),return)
SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return)
#endif
......@@ -237,6 +242,41 @@ SDL_X11_SYM(Status,XScreenSaverQueryVersion,(Display *dpy,int *major_versionp,in
SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),return)
#endif
/* XRender support */
#if SDL_VIDEO_DRIVER_X11_XRENDER
SDL_X11_MODULE(XRENDER)
SDL_X11_SYM(Bool,XRenderQueryExtension,(Display *dpy,int *event_base,int *error_base),(dpy,event_base,error_base),return)
SDL_X11_SYM(Bool,XRenderQueryVersion,(Display *dpy,int *major,int *minor),(dpy,major,minor),return)
SDL_X11_SYM(XRenderPictFormat*,XRenderFindVisualFormat,(Display *dpy,_Xconst Visual *visual),(dpy,visual),return)
SDL_X11_SYM(XRenderPictFormat*,XRenderFindStandardFormat,(Display *dpy,int format),(dpy,format),return)
SDL_X11_SYM(XRenderPictFormat*,XRenderFindFormat,(Display *dpy,unsigned long mask,_Xconst XRenderPictFormat* templ,int count),(dpy,mask,templ,count),return)
SDL_X11_SYM(Picture,XRenderCreatePicture,(Display *dpy,Drawable drawable,_Xconst XRenderPictFormat* format,unsigned long valuemask,_Xconst XRenderPictureAttributes* attributes),(dpy,drawable,format,valuemask,attributes),return)
SDL_X11_SYM(void,XRenderFreePicture,(Display *dpy,Picture picture),(dpy,picture),return)
SDL_X11_SYM(void,XRenderChangePicture,(Display *dpy,Picture picture,unsigned long valuemask,_Xconst XRenderPictureAttributes* attributes),(dpy,picture,valuemask,attributes),return)
SDL_X11_SYM(void,XRenderComposite,(Display *dpy,int op,Picture src,Picture mask,Picture dst,int src_x,int src_y,int mask_x,int mask_y,int dst_x,int dst_y,unsigned int width,unsigned int height),(dpy,op,src,mask,dst,src_x,src_y,mask_x,mask_y,dst_x,dst_y,width,height),return)
SDL_X11_SYM(Picture,XRenderCreateSolidFill,(Display *dpy,const XRenderColor *color),(dpy,color),return)
SDL_X11_SYM(void,XRenderSetPictureTransform,(Display *dpy,Picture picture,XTransform *transform),(dpy,picture,transform),return)
SDL_X11_SYM(void,XRenderFillRectangle,(Display *dpy,int op,Picture dst,_Xconst XRenderColor *color,int x,int y,unsigned int width,unsigned int height),(dpy,op,dst,color,x,y,width,height),return)
SDL_X11_SYM(void,XRenderFillRectangles,(Display *dpy,int op,Picture dst,_Xconst XRenderColor *color,_Xconst XRectangle *rectangles,int n_rects),(dpy,op,dst,color,rectangles,n_rects),return)
SDL_X11_SYM(void,XRenderSetPictureFilter,(Display *dpy,Picture picture,const char *filter,XFixed *params,int nparams),(dpy,picture,filter,params,nparams),return)
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
SDL_X11_MODULE(XDAMAGE)
SDL_X11_SYM(Bool,XDamageQueryExtension,(Display *dpy,int *event_base_return,int *error_base_return),(dpy,event_base_return,error_base_return),return)
SDL_X11_SYM(Status,XDamageQueryVersion,(Display *dpy,int *major,int *minor),(dpy,major,minor),return)
SDL_X11_SYM(Damage,XDamageCreate,(Display *dpy,Drawable d,int level),(dpy,d,level),return)
SDL_X11_SYM(void,XDamageSubtract,(Display *dpy,Damage damage,XserverRegion repair,XserverRegion parts),(dpy,damage,repair,parts),return)
SDL_X11_SYM(void,XDamageDestroy,(Display *dpy,Damage damage),(dpy,damage),return)
#endif
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
SDL_X11_MODULE(XFIXES)
SDL_X11_SYM(Bool,XFixesQueryExtension,(Display *dpy,int *event_base,int *error_base),(dpy,event_base,error_base),return)
SDL_X11_SYM(Status,XFixesQueryVersion,(Display *dpy,int *major,int *minor),(dpy,major,minor),return)
SDL_X11_SYM(void,XFixesSetGCClipRegion,(Display *dpy,GC gc,int clip_x,int clip_y,XserverRegion region),(dpy,gc,clip_x,clip_y,region),return)
SDL_X11_SYM(void,XFixesSetPictureClipRegion,(Display *dpy,XID picture,int clip_x,int clip_y,XserverRegion region),(dpy,picture,clip_x,clip_y,region),return)
#endif
/* *INDENT-ON* */
/* vi: set ts=4 sw=4 expandtab: */
......@@ -45,7 +45,15 @@
#if SDL_VIDEO_DRIVER_X11_SCRNSAVER
#include <X11/extensions/scrnsaver.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XRENDER
#include <X11/extensions/Xrender.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XDAMAGE
#include <X11/extensions/Xdamage.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
#include "SDL_x11dyn.h"
#include "SDL_x11clipboard.h"
......
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