--- a/src/video/x11/SDL_x11render.c Tue Jul 27 21:31:28 2010 -0700
+++ b/src/video/x11/SDL_x11render.c Wed Jul 28 00:54:23 2010 -0700
@@ -1,4 +1,5 @@
/*
+
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
@@ -39,6 +40,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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);
+ data->image =
+ XShmCreateImage(renderdata->display, data->visual,
+ data->depth, ZPixmap, NULL,
+ shminfo, texture->w, texture->h);
+ 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;
+ }
+ }
}
}
- 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,
- 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) {
@@ -403,47 +914,102 @@
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 {
+ }
+ 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;
+ }
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;
}
@@ -463,14 +1029,106 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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;
+ }
- 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))
+ {
+ 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);
- 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;
+ 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
}
- xpoint->x = (short)x;
- xpoint->y = (short)y;
- ++xpoint;
- ++xcount;
+#endif
}
- if (xcount > 0) {
- XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
- CoordModeOrigin);
+
+#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) {
+ XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount,
+ CoordModeOrigin);
+ }
+ }
+
SDL_stack_free(xpoints);
return 0;
@@ -668,65 +1471,146 @@
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;
+ {
+ 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;
- /* 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;
+ 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;
}
- XDrawLines(data->display, data->drawable, data->gc,
- xpoints, xcount, CoordModeOrigin);
+
+ /* 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;
+ }
+ }
+ }
+ 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 @@
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);
+#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);
}
- 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);
- }
+#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,18 +1663,122 @@
X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_Rect clip, rect;
- unsigned long foreground;
+ int i, xcount;
XRectangle *xrects, *xrect;
- int i, xcount;
-
+ 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->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);
+
+ 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) {
+ XDrawRectangles(data->display, data->drawable, data->gc,
+ xrects, xcount);
+ }
+ }
+ SDL_stack_free(xrects);
+
+ return 0;
+}
+
+static int
+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;
+
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = window->w;
+ clip.h = window->h;
+
+ int i, xcount;
+ XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
for (i = 0; i < count; ++i) {
@@ -826,57 +1797,34 @@
SDL_AddDirtyRect(&data->dirty, &rect);
}
}
- if (xcount > 0) {
- XDrawRectangles(data->display, data->drawable, data->gc,
- xrects, xcount);
- }
- SDL_stack_free(xpoints);
- return 0;
-}
-
-static int
-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);
-
- xrect = xrects = SDL_stack_alloc(XRectangle, count);
- xcount = 0;
- for (i = 0; i < count; ++i) {
- if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
- continue;
+#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);
}
-
- xrect->x = (short)rect.x;
- xrect->y = (short)rect.y;
- xrect->width = (unsigned short)rect.w;
- xrect->height = (unsigned short)rect.h;
- ++xrect;
- ++xcount;
-
- if (data->makedirty) {
- SDL_AddDirtyRect(&data->dirty, &rect);
+ else if (xcount > 1) {
+ XRenderFillRectangles(data->display, data->blend_op, data->drawable_pict,
+ &foreground, xrects, xcount);
}
}
- if (xcount > 0) {
+ 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 @@
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
+ 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, data->drawable, data->gc,
- texturedata->image, srcrect->x, srcrect->y, dstrect->x,
- dstrect->y, srcrect->w, srcrect->h);
+ 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 {
- 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;
-
- 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;
+ 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);
}
- image =
- XCreateImage(data->display, data->visual, data->depth,
- ZPixmap, 0, pixels, dstrect->w, dstrect->h,
- SDL_BYTESPERPIXEL(texturedata->format) * 8,
- pitch);
+ 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) {
+ 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);
+ }
+ } else if (texturedata->yuv
+ || texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ SDL_Surface src, dst;
+ SDL_PixelFormat fmt;
+ SDL_Rect rect;
+ XImage *image = texturedata->scaling_image;
+
if (!image) {
- SDL_SetError("XCreateImage() failed");
+ void *pixels;
+ int pitch;
+
+ pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
+ pixels = SDL_malloc(dstrect->h * pitch);
+ if (!pixels) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+
+ 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;
+ }
+ }
+
+ /* 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;
}
- 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;
- }
+ 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);
}
-
- /* 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);
}
return 0;
}
@@ -1065,9 +2116,26 @@
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 @@
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
}
}
@@ -1110,6 +2184,19 @@
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);
data->scaling_image->data = NULL;
@@ -1133,10 +2220,36 @@
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);
}
--- a/src/video/x11/SDL_x11sym.h Tue Jul 27 21:31:28 2010 -0700
+++ b/src/video/x11/SDL_x11sym.h Wed Jul 28 00:54:23 2010 -0700
@@ -156,6 +156,10 @@
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,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(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: */