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 ...@@ -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'`] 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'`] 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'`] 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 esac
...@@ -1128,16 +1130,13 @@ AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for ful ...@@ -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$have_xrandr_h_hdr = xyes; then
if test x$enable_x11_shared = xyes && test x$xrandr_lib != x ; then if test x$enable_x11_shared = xyes && test x$xrandr_lib != x ; then
echo "-- dynamic libXrender -> $xrender_lib"
echo "-- dynamic libXrandr -> $xrandr_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") AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR, "$xrandr_lib")
definitely_enable_video_x11_xrandr=yes definitely_enable_video_x11_xrandr=yes
else else
AC_CHECK_LIB(Xrender, XRenderQueryExtension, have_xrender_lib=yes)
AC_CHECK_LIB(Xrandr, XRRQueryExtension, have_xrandr_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 if test x$have_xrandr_lib = xyes ; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr -lXrender" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr"
definitely_enable_video_x11_xrandr=yes definitely_enable_video_x11_xrandr=yes
fi fi
fi fi
...@@ -1199,7 +1198,69 @@ AC_HELP_STRING([--enable-video-x11-scrnsaver], [enable X11 screensaver extension ...@@ -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 if test x$definitely_enable_video_x11_scrnsaver = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_X11_SCRNSAVER) AC_DEFINE(SDL_VIDEO_DRIVER_X11_SCRNSAVER)
fi 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_ARG_ENABLE(render-x11,
AC_HELP_STRING([--enable-render-x11], [enable the X11 render driver [[default=yes]]]), AC_HELP_STRING([--enable-render-x11], [enable the X11 render driver [[default=yes]]]),
, enable_render_x11=yes) , enable_render_x11=yes)
......
...@@ -272,12 +272,19 @@ ...@@ -272,12 +272,19 @@
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS #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_VIDMODE
#undef SDL_VIDEO_DRIVER_X11_XINERAMA #undef SDL_VIDEO_DRIVER_X11_XINERAMA
#undef SDL_VIDEO_DRIVER_X11_XRANDR #undef SDL_VIDEO_DRIVER_X11_XRANDR
#undef SDL_VIDEO_DRIVER_X11_XINPUT #undef SDL_VIDEO_DRIVER_X11_XINPUT
#undef SDL_VIDEO_DRIVER_X11_SCRNSAVER #undef SDL_VIDEO_DRIVER_X11_SCRNSAVER
#undef SDL_VIDEO_DRIVER_X11_XV #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_D3D
#undef SDL_VIDEO_RENDER_GDI #undef SDL_VIDEO_RENDER_GDI
......
...@@ -189,7 +189,7 @@ typedef struct SDL_RendererInfo ...@@ -189,7 +189,7 @@ typedef struct SDL_RendererInfo
Uint32 blend_modes; /**< A mask of supported blend modes */ Uint32 blend_modes; /**< A mask of supported blend modes */
Uint32 scale_modes; /**< A mask of supported scale modes */ Uint32 scale_modes; /**< A mask of supported scale modes */
Uint32 num_texture_formats; /**< The number of available texture formats */ 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_width; /**< The maximimum texture width */
int max_texture_height; /**< The maximimum texture height */ int max_texture_height; /**< The maximimum texture height */
} SDL_RendererInfo; } SDL_RendererInfo;
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_error_c.h" #include "SDL_error_c.h"
/*#define DEBUG_ERROR*/
/* Routine to get the thread-specific error variable */ /* Routine to get the thread-specific error variable */
#if SDL_THREADS_DISABLED #if SDL_THREADS_DISABLED
/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */ /* !!! FIXME: what does this comment mean? Victim of Search and Replace? */
......
...@@ -52,6 +52,18 @@ ...@@ -52,6 +52,18 @@
#include <X11/extensions/XInput.h> #include <X11/extensions/XInput.h>
#endif #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 * When using the "dynamic X11" functionality, we duplicate all the Xlib
* symbols that would be referenced by SDL inside of SDL itself. * symbols that would be referenced by SDL inside of SDL itself.
......
/* /*
SDL - Simple DirectMedia Layer SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga Copyright (C) 1997-2010 Sam Lantinga
...@@ -39,6 +40,8 @@ static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); ...@@ -39,6 +40,8 @@ static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
static int X11_QueryTexturePixels(SDL_Renderer * renderer, static int X11_QueryTexturePixels(SDL_Renderer * renderer,
SDL_Texture * texture, void **pixels, SDL_Texture * texture, void **pixels,
int *pitch); int *pitch);
static int X11_SetTextureRGBAMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int X11_SetTextureBlendMode(SDL_Renderer * renderer, static int X11_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture); SDL_Texture * texture);
static int X11_SetTextureScaleMode(SDL_Renderer * renderer, static int X11_SetTextureScaleMode(SDL_Renderer * renderer,
...@@ -96,6 +99,25 @@ typedef struct ...@@ -96,6 +99,25 @@ typedef struct
int scanline_pad; int scanline_pad;
Window xwindow; Window xwindow;
Pixmap pixmaps[3]; 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; int current_pixmap;
Drawable drawable; Drawable drawable;
SDL_PixelFormat format; SDL_PixelFormat format;
...@@ -109,6 +131,17 @@ typedef struct ...@@ -109,6 +131,17 @@ typedef struct
SDL_SW_YUVTexture *yuv; SDL_SW_YUVTexture *yuv;
Uint32 format; Uint32 format;
Pixmap pixmap; 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; XImage *image;
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY
/* MIT shared memory extension information */ /* MIT shared memory extension information */
...@@ -149,11 +182,109 @@ UpdateYUVTextureData(SDL_Texture * texture) ...@@ -149,11 +182,109 @@ UpdateYUVTextureData(SDL_Texture * texture)
texture->h, data->pixels, data->pitch); 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 void
X11_AddRenderDriver(_THIS) X11_AddRenderDriver(_THIS)
{ {
SDL_RendererInfo *info = &X11_RenderDriver.info; SDL_RendererInfo *info = &X11_RenderDriver.info;
SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode; SDL_DisplayMode *mode = &SDL_CurrentDisplay->desktop_mode;
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
int i; int i;
info->texture_formats[info->num_texture_formats++] = mode->format; info->texture_formats[info->num_texture_formats++] = mode->format;
...@@ -163,6 +294,34 @@ X11_AddRenderDriver(_THIS) ...@@ -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_UYVY;
info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YVYU; 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) { for (i = 0; i < _this->num_displays; ++i) {
SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver); SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver);
} }
...@@ -177,6 +336,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -177,6 +336,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_Renderer *renderer; SDL_Renderer *renderer;
X11_RenderData *data; X11_RenderData *data;
XGCValues gcv; XGCValues gcv;
gcv.graphics_exposures = False;
int i, n; int i, n;
int bpp; int bpp;
Uint32 Rmask, Gmask, Bmask, Amask; Uint32 Rmask, Gmask, Bmask, Amask;
...@@ -203,6 +363,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -203,6 +363,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->DisplayModeChanged = X11_DisplayModeChanged; renderer->DisplayModeChanged = X11_DisplayModeChanged;
renderer->CreateTexture = X11_CreateTexture; renderer->CreateTexture = X11_CreateTexture;
renderer->QueryTexturePixels = X11_QueryTexturePixels; renderer->QueryTexturePixels = X11_QueryTexturePixels;
renderer->SetTextureAlphaMod = X11_SetTextureRGBAMod;
renderer->SetTextureColorMod = X11_SetTextureRGBAMod;
renderer->SetTextureBlendMode = X11_SetTextureBlendMode; renderer->SetTextureBlendMode = X11_SetTextureBlendMode;
renderer->SetTextureScaleMode = X11_SetTextureScaleMode; renderer->SetTextureScaleMode = X11_SetTextureScaleMode;
renderer->UpdateTexture = X11_UpdateTexture; renderer->UpdateTexture = X11_UpdateTexture;
...@@ -225,6 +387,82 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -225,6 +387,82 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags = SDL_RENDERER_ACCELERATED; 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) { if (flags & SDL_RENDERER_SINGLEBUFFER) {
renderer->info.flags |= renderer->info.flags |=
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY); (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY);
...@@ -239,25 +477,95 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -239,25 +477,95 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
n = 1; 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) { for (i = 0; i < n; ++i) {
#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] = data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h, XCreatePixmap(data->display, data->xwindow, window->w, window->h,
displaydata->depth); displaydata->depth);
}
if (data->pixmaps[i] == None) { if (data->pixmaps[i] == None) {
X11_DestroyRenderer(renderer); X11_DestroyRenderer(renderer);
SDL_SetError("XCreatePixmap() failed"); SDL_SetError("XCreatePixmap() failed");
return NULL; 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) { if (n > 0) {
data->drawable = data->pixmaps[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; data->makedirty = SDL_TRUE;
} else { } else {
data->drawable = data->xwindow; 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->makedirty = SDL_FALSE;
} }
data->current_pixmap = 0; data->current_pixmap = 0;
#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 */ /* Get the format of the window */
if (!SDL_PixelFormatEnumToMasks if (!SDL_PixelFormatEnumToMasks
(display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask, (display->current_mode.format, &bpp, &Rmask, &Gmask, &Bmask,
...@@ -266,12 +574,13 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -266,12 +574,13 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
X11_DestroyRenderer(renderer); X11_DestroyRenderer(renderer);
return NULL; return NULL;
} }
}
SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask); SDL_InitFormat(&data->format, bpp, Rmask, Gmask, Bmask, Amask);
/* Create the drawing context */ /* Create the drawing context */
gcv.graphics_exposures = False; gcv.graphics_exposures = False;
data->gc = data->gc =
XCreateGC(data->display, data->xwindow, GCGraphicsExposures, &gcv); XCreateGC(data->display, data->drawable, GCGraphicsExposures, &gcv);
if (!data->gc) { if (!data->gc) {
X11_DestroyRenderer(renderer); X11_DestroyRenderer(renderer);
SDL_SetError("XCreateGC() failed"); SDL_SetError("XCreateGC() failed");
...@@ -288,6 +597,47 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) ...@@ -288,6 +597,47 @@ X11_DisplayModeChanged(SDL_Renderer * renderer)
SDL_Window *window = renderer->window; SDL_Window *window = renderer->window;
int i, n; 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) { if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) {
n = 0; n = 0;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
...@@ -301,25 +651,170 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) ...@@ -301,25 +651,170 @@ X11_DisplayModeChanged(SDL_Renderer * renderer)
if (data->pixmaps[i] != None) { if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]); XFreePixmap(data->display, data->pixmaps[i]);
data->pixmaps[i] = None; 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) { for (i = 0; i < n; ++i) {
#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] = data->pixmaps[i] =
XCreatePixmap(data->display, data->xwindow, window->w, window->h, XCreatePixmap(data->display, data->xwindow, window->w, window->h,
data->depth); data->depth);
}
if (data->pixmaps[i] == None) { if (data->pixmaps[i] == None) {
SDL_SetError("XCreatePixmap() failed"); SDL_SetError("XCreatePixmap() failed");
return -1; 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) { if (n > 0) {
data->drawable = data->pixmaps[0]; data->drawable = data->pixmaps[0];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
data->drawable_pict = data->pixmap_picts[0];
#endif
} }
data->current_pixmap = 0; data->current_pixmap = 0;
return 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 static int
X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{ {
...@@ -328,15 +823,18 @@ 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; SDL_VideoDisplay *display = window->display;
X11_TextureData *data; X11_TextureData *data;
int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1);
XGCValues gcv;
data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); data = (X11_TextureData *) SDL_calloc(1, sizeof(*data));
if (!data) { if (!data) {
SDL_OutOfMemory(); SDL_OutOfMemory();
return -1; return -1;
} }
data->depth = renderdata->depth;
data->visual = renderdata->visual;
data->gc = renderdata->gc;
texture->driverdata = data; texture->driverdata = data;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
data->yuv = data->yuv =
SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
...@@ -345,17 +843,25 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -345,17 +843,25 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
} }
data->format = display->current_mode.format; data->format = display->current_mode.format;
} else { } else {
/* The image/pixmap depth must be the same as the window or you #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
get a BadMatch error when trying to putimage or copyarea. if (renderdata->use_xrender)
*/ {
if (texture->format != display->current_mode.format) { 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"); SDL_SetError("Texture format doesn't match window format");
return -1; return -1;
} }
}
data->format = texture->format; 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) { if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY
...@@ -364,8 +870,13 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -364,8 +870,13 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
shm_error = True; shm_error = True;
if (SDL_X11_HAVE_SHM) { if (SDL_X11_HAVE_SHM) {
data->image =
XShmCreateImage(renderdata->display, data->visual,
data->depth, ZPixmap, NULL,
shminfo, texture->w, texture->h);
if (data->image) {
shminfo->shmid = shminfo->shmid =
shmget(IPC_PRIVATE, texture->h * data->pitch, shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line,
IPC_CREAT | 0777); IPC_CREAT | 0777);
if (shminfo->shmid >= 0) { if (shminfo->shmid >= 0) {
shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
...@@ -377,24 +888,24 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -377,24 +888,24 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
XSync(renderdata->display, False); XSync(renderdata->display, False);
XSetErrorHandler(X_handler); XSetErrorHandler(X_handler);
if (shm_error) { if (shm_error) {
XShmDetach(renderdata->display, shminfo);
shmdt(shminfo->shmaddr); shmdt(shminfo->shmaddr);
XDestroyImage(data->image);
XSync(renderdata->display, False);
} }
} else {
data->pixels = data->image->data = shminfo->shmaddr;
shmctl(shminfo->shmid, IPC_RMID, NULL); 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) {
data->pixels = shminfo->shmaddr;
data->image =
XShmCreateImage(renderdata->display, renderdata->visual,
renderdata->depth, ZPixmap, shminfo->shmaddr,
shminfo, texture->w, texture->h);
if (!data->image) {
XShmDetach(renderdata->display, shminfo);
XSync(renderdata->display, False);
shmdt(shminfo->shmaddr);
shm_error = True;
} }
} }
if (shm_error) { if (shm_error) {
...@@ -403,47 +914,102 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -403,47 +914,102 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (!data->image) if (!data->image)
#endif /* not NO_SHARED_MEMORY */ #endif /* not NO_SHARED_MEMORY */
{ {
data->pixels = SDL_malloc(texture->h * data->pitch); 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;
}
data->pixels = SDL_malloc(texture->h * data->image->bytes_per_line);
if (!data->pixels) { if (!data->pixels) {
X11_DestroyTexture(renderer, texture); X11_DestroyTexture(renderer, texture);
SDL_OutOfMemory(); SDL_OutOfMemory();
return -1; 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 = data->image =
XCreateImage(renderdata->display, renderdata->visual, XCreateImage(renderdata->display, data->visual,
renderdata->depth, ZPixmap, 0, data->pixels, data->depth, ZPixmap, 0, NULL,
texture->w, texture->h, texture->w, texture->h,
SDL_BYTESPERPIXEL(data->format) * 8, SDL_BYTESPERPIXEL(data->format) * 8,
data->pitch); 0);
if (!data->image) { if (!data->image) {
X11_DestroyTexture(renderer, texture); X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed"); SDL_SetError("XCreateImage() failed");
return -1; return -1;
} }
}
} else {
data->pixmap = data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
texture->h, renderdata->depth); texture->h, data->depth);
if (data->pixmap == None) { if (data->pixmap == None) {
X11_DestroyTexture(renderer, texture); X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreatePixmap() failed"); SDL_SetError("XCreatePixmap() failed");
return -1; return -1;
} }
}
data->image = data->pitch = data->image->bytes_per_line;
XCreateImage(renderdata->display, renderdata->visual,
renderdata->depth, ZPixmap, 0, NULL, texture->w, #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
texture->h, SDL_BYTESPERPIXEL(data->format) * 8, if(renderdata->use_xrender) {
data->pitch); gcv.graphics_exposures = False;
if (!data->image) { 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); X11_DestroyTexture(renderer, texture);
SDL_SetError("XCreateImage() failed"); SDL_SetError("Texture format not supported by driver");
return -1; 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; return 0;
} }
...@@ -462,15 +1028,107 @@ X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -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 static int
X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) 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) { switch (texture->blendMode) {
case SDL_BLENDMODE_NONE: 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; return 0;
default: default:
SDL_Unsupported(); SDL_Unsupported();
texture->blendMode = SDL_BLENDMODE_NONE; 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; return -1;
} }
} }
...@@ -479,6 +1137,7 @@ static int ...@@ -479,6 +1137,7 @@ 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; X11_TextureData *data = (X11_TextureData *) texture->driverdata;
X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
switch (texture->scaleMode) { switch (texture->scaleMode) {
case SDL_TEXTURESCALEMODE_NONE: case SDL_TEXTURESCALEMODE_NONE:
...@@ -488,9 +1147,32 @@ X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -488,9 +1147,32 @@ X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
return 0; return 0;
} }
#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 */ /* Fall through to unsupported case */
default: default:
SDL_Unsupported(); SDL_Unsupported();
#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; texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
return -1; return -1;
} }
...@@ -532,7 +1214,7 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -532,7 +1214,7 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
data->image->height = rect->h; data->image->height = rect->h;
data->image->data = (char *) pixels; data->image->data = (char *) pixels;
data->image->bytes_per_line = pitch; 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); data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
} }
return 0; return 0;
...@@ -575,12 +1257,36 @@ X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -575,12 +1257,36 @@ X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
static int static int
X11_SetDrawBlendMode(SDL_Renderer * renderer) X11_SetDrawBlendMode(SDL_Renderer * renderer)
{ {
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
switch (renderer->blendMode) { switch (renderer->blendMode) {
case SDL_BLENDMODE_NONE: 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; return 0;
default: default:
SDL_Unsupported(); SDL_Unsupported();
#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; renderer->blendMode = SDL_BLENDMODE_NONE;
}
return -1; return -1;
} }
} }
...@@ -601,16 +1307,35 @@ renderdrawcolor(SDL_Renderer * renderer, int premult) ...@@ -601,16 +1307,35 @@ renderdrawcolor(SDL_Renderer * renderer, int premult)
return SDL_MapRGBA(&data->format, r, g, b, a); 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 static int
X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
int count) int count)
{ {
X11_RenderData *data = (X11_RenderData *) renderer->driverdata; X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window; SDL_Window *window = renderer->window;
unsigned long foreground;
XPoint *xpoints, *xpoint; XPoint *xpoints, *xpoint;
int i, xcount; int i, xcount;
SDL_Rect clip;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
if (data->makedirty) { if (data->makedirty) {
SDL_Rect rect; SDL_Rect rect;
...@@ -625,10 +1350,7 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, ...@@ -625,10 +1350,7 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
} }
SDL_AddDirtyRect(&data->dirty, &rect); SDL_AddDirtyRect(&data->dirty, &rect);
} }
{
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
xpoint = xpoints = SDL_stack_alloc(XPoint, count); xpoint = xpoints = SDL_stack_alloc(XPoint, count);
xcount = 0; xcount = 0;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
...@@ -642,10 +1364,91 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, ...@@ -642,10 +1364,91 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
++xpoint; ++xpoint;
++xcount; ++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
}
#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)
{
/* Update only those parts which drawn
* to in the current drawing operation */
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
}
else
#endif
{
unsigned long foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
if (xcount > 0) { if (xcount > 0) {
XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount, XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
CoordModeOrigin); CoordModeOrigin);
} }
}
SDL_stack_free(xpoints); SDL_stack_free(xpoints);
return 0; return 0;
...@@ -668,6 +1471,40 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, ...@@ -668,6 +1471,40 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
clip.y = 0; clip.y = 0;
clip.w = window->w; clip.w = window->w;
clip.h = window->h; clip.h = window->h;
{
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;
}
foreground = renderdrawcolor(renderer, 1); foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground); XSetForeground(data->display, data->gc, foreground);
...@@ -723,10 +1560,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, ...@@ -723,10 +1560,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
++xpoint; ++xpoint;
++xcount; ++xcount;
} }
XDrawLines(data->display, data->drawable, data->gc, XDrawLines(data->display, drawable, gc,
xpoints, xcount, CoordModeOrigin); xpoints, xcount, CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) { 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) { if (data->makedirty) {
SDL_Rect rect; SDL_Rect rect;
...@@ -770,10 +1607,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, ...@@ -770,10 +1607,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
if (xcount > 1) { if (xcount > 1) {
int x2 = xpoint[-1].x; int x2 = xpoint[-1].x;
int y2 = xpoint[-1].y; int y2 = xpoint[-1].y;
XDrawLines(data->display, data->drawable, data->gc, xpoints, xcount, XDrawLines(data->display, drawable, gc, xpoints, xcount,
CoordModeOrigin); CoordModeOrigin);
if (xpoints[0].x != x2 || xpoints[0].y != y2) { 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) { if (data->makedirty) {
SDL_Rect rect; SDL_Rect rect;
...@@ -785,6 +1622,36 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, ...@@ -785,6 +1622,36 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
SDL_AddDirtyRect(&data->dirty, &rect); 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))
{
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);
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); SDL_stack_free(xpoints);
return 0; return 0;
...@@ -796,20 +1663,17 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -796,20 +1663,17 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
X11_RenderData *data = (X11_RenderData *) renderer->driverdata; X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window; SDL_Window *window = renderer->window;
SDL_Rect clip, rect; SDL_Rect clip, rect;
unsigned long foreground;
XRectangle *xrects, *xrect;
int i, xcount; int i, xcount;
XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
clip.x = 0; clip.x = 0;
clip.y = 0; clip.y = 0;
clip.w = window->w; clip.w = window->w;
clip.h = window->h; clip.h = window->h;
{
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
if (!SDL_IntersectRect(rects[i], &clip, &rect)) { if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
continue; continue;
...@@ -817,8 +1681,8 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -817,8 +1681,8 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
xrect->x = (short)rect.x; xrect->x = (short)rect.x;
xrect->y = (short)rect.y; xrect->y = (short)rect.y;
xrect->width = (unsigned short)rect.w; xrect->width = (unsigned short)rect.w - 1;
xrect->height = (unsigned short)rect.h; xrect->height = (unsigned short)rect.h - 1;
++xrect; ++xrect;
++xcount; ++xcount;
...@@ -826,11 +1690,77 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -826,11 +1690,77 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
SDL_AddDirtyRect(&data->dirty, &rect); 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);
XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount);
#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE
if (data->use_xdamage)
XDamageSubtract(data->display, data->stencil_damage,
None, data->stencil_parts);
#endif
}
#endif
}
#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
}
else
#endif
{
unsigned long foreground;
foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground);
if (xcount > 0) { if (xcount > 0) {
XDrawRectangles(data->display, data->drawable, data->gc, XDrawRectangles(data->display, data->drawable, data->gc,
xrects, xcount); xrects, xcount);
} }
SDL_stack_free(xpoints); }
SDL_stack_free(xrects);
return 0; return 0;
} }
...@@ -841,18 +1771,14 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -841,18 +1771,14 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
X11_RenderData *data = (X11_RenderData *) renderer->driverdata; X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window; SDL_Window *window = renderer->window;
SDL_Rect clip, rect; SDL_Rect clip, rect;
unsigned long foreground;
XRectangle *xrects, *xrect;
int i, xcount;
clip.x = 0; clip.x = 0;
clip.y = 0; clip.y = 0;
clip.w = window->w; clip.w = window->w;
clip.h = window->h; clip.h = window->h;
foreground = renderdrawcolor(renderer, 1); int i, xcount;
XSetForeground(data->display, data->gc, foreground); XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count); xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0; xcount = 0;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
...@@ -871,12 +1797,34 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -871,12 +1797,34 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
SDL_AddDirtyRect(&data->dirty, &rect); 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, XFillRectangles(data->display, data->drawable, data->gc,
xrects, xcount); xrects, xcount);
} }
SDL_stack_free(xpoints);
SDL_stack_free(xrects);
return 0; return 0;
} }
...@@ -890,6 +1838,108 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -890,6 +1838,108 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
if (data->makedirty) { if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, dstrect); SDL_AddDirtyRect(&data->dirty, dstrect);
} }
#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, 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);
}
Picture src, mask;
XRenderPictureAttributes attr;
const SDL_Rect *mrect;
if (texture->modMode == SDL_TEXTUREMODULATE_NONE) {
src = texturedata->picture;
}
else {
src = texturedata->modulated_picture;
}
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;
}
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);
}
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);
}
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) { 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) {
...@@ -988,6 +2038,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -988,6 +2038,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
srcrect->x, srcrect->y); srcrect->x, srcrect->y);
} }
}
return 0; return 0;
} }
...@@ -1065,10 +2116,27 @@ X11_RenderPresent(SDL_Renderer * renderer) ...@@ -1065,10 +2116,27 @@ X11_RenderPresent(SDL_Renderer * renderer)
if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) { if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) {
for (dirty = data->dirty.list; dirty; dirty = dirty->next) { for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
const SDL_Rect *rect = &dirty->rect; 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, XCopyArea(data->display, data->drawable, data->xwindow,
data->gc, rect->x, rect->y, rect->w, rect->h, data->gc, rect->x, rect->y, rect->w, rect->h,
rect->x, rect->y); rect->x, rect->y);
} }
}
SDL_ClearDirtyRects(&data->dirty); SDL_ClearDirtyRects(&data->dirty);
} }
XSync(data->display, False); XSync(data->display, False);
...@@ -1077,9 +2145,15 @@ X11_RenderPresent(SDL_Renderer * renderer) ...@@ -1077,9 +2145,15 @@ X11_RenderPresent(SDL_Renderer * renderer)
if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
data->current_pixmap = (data->current_pixmap + 1) % 2; data->current_pixmap = (data->current_pixmap + 1) % 2;
data->drawable = data->pixmaps[data->current_pixmap]; 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) { } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
data->current_pixmap = (data->current_pixmap + 1) % 3; data->current_pixmap = (data->current_pixmap + 1) % 3;
data->drawable = data->pixmaps[data->current_pixmap]; 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) ...@@ -1109,6 +2183,19 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
shmdt(data->shminfo.shmaddr); shmdt(data->shminfo.shmaddr);
data->pixels = NULL; 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 #endif
if (data->scaling_image) { if (data->scaling_image) {
SDL_free(data->scaling_image->data); SDL_free(data->scaling_image->data);
...@@ -1133,10 +2220,36 @@ X11_DestroyRenderer(SDL_Renderer * renderer) ...@@ -1133,10 +2220,36 @@ X11_DestroyRenderer(SDL_Renderer * renderer)
if (data->pixmaps[i] != None) { if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]); 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) { if (data->gc) {
XFreeGC(data->display, 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_FreeDirtyRects(&data->dirty);
SDL_free(data); SDL_free(data);
} }
......
...@@ -156,6 +156,10 @@ SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),r ...@@ -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_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(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(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 #if NeedWidePrototypes
SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return) 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) ...@@ -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,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(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(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) SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return)
#endif #endif
...@@ -237,6 +242,41 @@ SDL_X11_SYM(Status,XScreenSaverQueryVersion,(Display *dpy,int *major_versionp,in ...@@ -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) SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),return)
#endif #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* */ /* *INDENT-ON* */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -45,7 +45,15 @@ ...@@ -45,7 +45,15 @@
#if SDL_VIDEO_DRIVER_X11_SCRNSAVER #if SDL_VIDEO_DRIVER_X11_SCRNSAVER
#include <X11/extensions/scrnsaver.h> #include <X11/extensions/scrnsaver.h>
#endif #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_x11dyn.h"
#include "SDL_x11clipboard.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