From 0a4a7759f06c5491a1f99129527af572d0ba45bd Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 19 May 2010 18:58:28 +0530 Subject: [PATCH 01/47] Adding a few #defines for Xrender support. --- include/SDL_config.h.in | 1 + src/video/x11/SDL_x11dyn.h | 4 ++++ src/video/x11/SDL_x11video.h | 3 +++ 3 files changed, 8 insertions(+) diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 5c47f11b2..473a0f323 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -278,6 +278,7 @@ #undef SDL_VIDEO_DRIVER_X11_XINPUT #undef SDL_VIDEO_DRIVER_X11_SCRNSAVER #undef SDL_VIDEO_DRIVER_X11_XV +#undef SDL_VIDEO_DRIVER_X11_XRENDER #undef SDL_VIDEO_RENDER_D3D #undef SDL_VIDEO_RENDER_GDI diff --git a/src/video/x11/SDL_x11dyn.h b/src/video/x11/SDL_x11dyn.h index 0f722aff0..c06a2d6fe 100644 --- a/src/video/x11/SDL_x11dyn.h +++ b/src/video/x11/SDL_x11dyn.h @@ -52,6 +52,10 @@ #include #endif +#if SDL_VIDEO_DRIVER_X11_XRENDER +#include +#endif + /* * When using the "dynamic X11" functionality, we duplicate all the Xlib * symbols that would be referenced by SDL inside of SDL itself. diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 1ba0ba392..6c2377376 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -45,6 +45,9 @@ #if SDL_VIDEO_DRIVER_X11_SCRNSAVER #include #endif +#if SDL_VIDEO_DRIVER_X11_XRENDER +#include +#endif #include "SDL_x11dyn.h" From bcb2a5aa5ccc678afc4334be4f5815809ac4b429 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 24 May 2010 21:02:58 +0530 Subject: [PATCH 02/47] Added a #define option for compile time Xrender support. Added some more attributes (specific to Xrender) to the X11 structs. Added some code for querying the Xrender extension. --- src/video/x11/SDL_x11render.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index dcc26c1dc..e04a2ef3b 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -95,6 +95,13 @@ typedef struct int scanline_pad; Window xwindow; Pixmap pixmaps[3]; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + Picture xwindow_pict; + XRenderPictFormat* xwindow_pict_fmt; + XRenderPictureAttributes xwindow_pict_attr; + unsigned int xwindow_pict_attr_valuemask; + SDL_bool xrender_available; +#endif int current_pixmap; Drawable drawable; SDL_PixelFormat format; @@ -108,6 +115,9 @@ typedef struct SDL_SW_YUVTexture *yuv; Uint32 format; Pixmap pixmap; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + Picture picture; +#endif XImage *image; #ifndef NO_SHARED_MEMORY /* MIT shared memory extension information */ @@ -198,7 +208,22 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->depth = displaydata->depth; data->scanline_pad = displaydata->scanline_pad; data->xwindow = windowdata->xwindow; - +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + int event_basep, error_basep; + if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { + data->xrender_available = SDL_TRUE; + data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); + data->xwindow_pict_attr_valuemask = 0; // FIXME + data->xwindow_pict = XRenderCreatePicture(data->display, + data->xwindow, + data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, + &data->xwindow_pict_attr); + } + else { + data->xrender_available = SDL_FALSE; + } +#endif renderer->DisplayModeChanged = X11_DisplayModeChanged; renderer->CreateTexture = X11_CreateTexture; renderer->QueryTexturePixels = X11_QueryTexturePixels; From 1490cd435abf3e6a8b5fb5e50ccb5a6d564acb28 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 26 May 2010 20:11:56 +0530 Subject: [PATCH 03/47] Correctly handle the availability of Xrender in X11_CreateRenderer and X11_DisplayModeChanged. Fixed the XRenderPictureAttributes value in X11_CreateRenderer with graphics_exposures = False. Start work on Xrender specific additions to X11_TextureData and X11_CreateTexture. --- src/video/x11/SDL_x11render.c | 54 ++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index e04a2ef3b..30421b61f 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -97,6 +97,8 @@ typedef struct Pixmap pixmaps[3]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture xwindow_pict; + Picture pixmap_picts[3]; + Picture * drawable_pict; XRenderPictFormat* xwindow_pict_fmt; XRenderPictureAttributes xwindow_pict_attr; unsigned int xwindow_pict_attr_valuemask; @@ -117,6 +119,9 @@ typedef struct Pixmap pixmap; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture picture; + XRenderPictFormat* picture_fmt; + XRenderPictureAttributes picture_attr; + unsigned int picture_attr_valuemask; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -213,12 +218,10 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { data->xrender_available = SDL_TRUE; data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); - data->xwindow_pict_attr_valuemask = 0; // FIXME - data->xwindow_pict = XRenderCreatePicture(data->display, - data->xwindow, - data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, - &data->xwindow_pict_attr); + data->xwindow_pict_attr.graphics_exposures = False; + data->xwindow_pict_attr_valuemask = CPGraphicsExposure; + data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); } else { data->xrender_available = SDL_FALSE; @@ -272,12 +275,23 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_SetError("XCreatePixmap() failed"); return NULL; } + data->pixmap_picts[i] = + XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, &xwindow_pict_attr); } if (n > 0) { data->drawable = data->pixmaps[0]; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(data->xrender_available == 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->xrender_available == SDL_TRUE) + data->drawable_pict = &(data->xwindow_pict); +#endif data->makedirty = SDL_FALSE; } data->current_pixmap = 0; @@ -325,6 +339,9 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) if (data->pixmaps[i] != None) { XFreePixmap(data->display, data->pixmaps[i]); data->pixmaps[i] = None; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->pictures[i] = None; +#endif } } for (i = 0; i < n; ++i) { @@ -335,9 +352,17 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) SDL_SetError("XCreatePixmap() failed"); return -1; } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->pictures[i] = + XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); +#endif } if (n > 0) { data->drawable = data->pixmaps[0]; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->drawable_pict = &(data->pictures[0]); +#endif } data->current_pixmap = 0; @@ -360,7 +385,6 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } texture->driverdata = data; - if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { data->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); @@ -371,11 +395,21 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } else { /* The image/pixmap depth must be the same as the window or you get a BadMatch error when trying to putimage or copyarea. + This BadMatch error */ +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(renderdata->xrender_available == SDL_False) { + if (texture->format != display->current_mode.format) { + SDL_SetError("Texture format doesn't match window format"); + return -1; + } + } +#else if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; } +#endif data->format = texture->format; } data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); @@ -455,6 +489,12 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_SetError("XCreatePixmap() failed"); return -1; } + +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->picture_fmt = + XRenderFindVisualFormat(renderdata->display, + data->picture = + XCreatePicture(renderdata->display, data->pixmap, data->image = XCreateImage(renderdata->display, renderdata->visual, From f3d4dc95b25131f62946ebcfacaff543d9dec338 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Fri, 28 May 2010 20:40:09 +0530 Subject: [PATCH 04/47] Completed work on X11_CreateTexture. Added lots of safety features. These include support for drawing a texture using the core protocol while other textures are drawn using Xrender if Xrender does not support the color format of the said texture or any other fault with Xrender. --- src/video/x11/SDL_x11render.c | 87 +++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 30421b61f..4a8d3dca7 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -122,6 +122,7 @@ typedef struct XRenderPictFormat* picture_fmt; XRenderPictureAttributes picture_attr; unsigned int picture_attr_valuemask; + SDL_bool xrender_available; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -218,10 +219,16 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { data->xrender_available = SDL_TRUE; data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); + if(!xwindow_pict_fmt) { + data->xrender_available = SDL_FALSE; + } data->xwindow_pict_attr.graphics_exposures = False; data->xwindow_pict_attr_valuemask = CPGraphicsExposure; data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); + if(!data->xwindow_pict) { + data->xrender_available = SDL_FALSE; + } } else { data->xrender_available = SDL_FALSE; @@ -275,9 +282,16 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_SetError("XCreatePixmap() failed"); return NULL; } - data->pixmap_picts[i] = - XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, &xwindow_pict_attr); +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(data->xrender_available == SDL_TRUE) { + data->pixmap_picts[i] = + XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, &xwindow_pict_attr); + if(!data->pixmap_picts[i]) { + data->xrender_available = SDL_FALSE; + } + } +#endif } if (n > 0) { data->drawable = data->pixmaps[0]; @@ -353,9 +367,14 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) return -1; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->pictures[i] = - XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); + if(data->xrender_available == SDL_TRUE) { + data->pictures[i] = + XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); + if(!data->pictures[i]) { + data->xrender_available = SDL_FALSE; + } + } #endif } if (n > 0) { @@ -378,6 +397,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) X11_TextureData *data; int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); + data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); @@ -393,10 +413,10 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } data->format = display->current_mode.format; } else { - /* The image/pixmap depth must be the same as the window or you - get a BadMatch error when trying to putimage or copyarea. - This BadMatch error - */ + /* If Xrender support is builtin we only need to check whether + Xrender is available at runtime. If it is available there + can be no BadMatch error since Xrender takes care of that. + */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(renderdata->xrender_available == SDL_False) { if (texture->format != display->current_mode.format) { @@ -405,6 +425,10 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } } #else + /* The image/pixmap depth must be the same as the window or you + get a BadMatch error when trying to putimage or copyarea. + This BadMatch error + */ if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; @@ -491,11 +515,44 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->picture_fmt = - XRenderFindVisualFormat(renderdata->display, - data->picture = - XCreatePicture(renderdata->display, data->pixmap, - + if(renderdata->xrender_available) { + data->xrender_available = SDL_TRUE; + unsigned long x11_fmt_mask; // Format mask + XRenderPictFormat x11_templ_fmt; // Format template + x11_fmt_mask = + (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask + | PictFormatBlueMask); + x11_templ_fmt.depth = (data->format).BitsPerPixel; + x11_temp_fmt.direct.redMask = (data->format).Rmask; + x11_temp_fmt.direct.greenMask = (data->format).Gmask; + x11_temp_fmt.direct.blueMask = (data->format).Bmask; + x11_temp_fmt.direct.alphaMask = (data->format).Amask; + /* Return one matching XRenderPictFormat */ + data->pict_fmt = + XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); + if(!data->pict_fmt) { + data->xrender_available = SDL_FALSE; + } + data->picture_attr_valuemask = CPGraphicsExposure; + (data->picture_attr).graphics_exposures = False; + data->picture = + XCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, + data->picture_attr_valuemask, &(data->picture_attr)); + if(!data->picture) { + data->xrender_available = SDL_FALSE; + } + } + /* We thought we could render the texture with Xrender but this was + not possible for some reason. Now we must ensure that texture + format and window format match to avoid a BadMatch error. + */ + if(data->xrender_available == SDL_FALSE) { + if (texture->format != display->current_mode.format) { + SDL_SetError("Texture format doesn't match window format"); + return -1; + } + } +#endif data->image = XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, NULL, texture->w, From d4d53a4609c3f9fb72f45334618a6e3555779280 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Fri, 28 May 2010 20:47:24 +0530 Subject: [PATCH 05/47] Fix initial value of the xrender_available boolean in X11_CreateTexture. --- src/video/x11/SDL_x11render.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 4a8d3dca7..db2e42c07 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -397,7 +397,6 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) X11_TextureData *data; int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); - data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); @@ -418,6 +417,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) can be no BadMatch error since Xrender takes care of that. */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER + // Assume the texture is supported by Xrender + data->xrender_available = TRUE if(renderdata->xrender_available == SDL_False) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); From c8d828b8da2e7c5a106ddba5289f208573912587 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Fri, 28 May 2010 20:48:58 +0530 Subject: [PATCH 06/47] Fix typo. --- src/video/x11/SDL_x11render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index db2e42c07..939330687 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -418,7 +418,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER // Assume the texture is supported by Xrender - data->xrender_available = TRUE + data->xrender_available = SDL_TRUE; if(renderdata->xrender_available == SDL_False) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); From 54edf7b933d2dcadc705a50cd635232c20a5323a Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 30 May 2010 20:06:30 +0530 Subject: [PATCH 07/47] Add Xrender support to X11_FillRectangles. --- src/video/x11/SDL_x11render.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 939330687..0111ccacd 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -98,7 +98,7 @@ typedef struct #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture xwindow_pict; Picture pixmap_picts[3]; - Picture * drawable_pict; + Picture drawable_pict; XRenderPictFormat* xwindow_pict_fmt; XRenderPictureAttributes xwindow_pict_attr; unsigned int xwindow_pict_attr_valuemask; @@ -297,14 +297,14 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->drawable = data->pixmaps[0]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->xrender_available == SDL_TRUE) - data->drawable_pict = &(data->pixmap_picts[0]); + 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->xrender_available == SDL_TRUE) - data->drawable_pict = &(data->xwindow_pict); + data->drawable_pict = data->xwindow_pict; #endif data->makedirty = SDL_FALSE; } @@ -380,7 +380,7 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) if (n > 0) { data->drawable = data->pixmaps[0]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->drawable_pict = &(data->pictures[0]); + data->drawable_pict = data->pictures[0]; #endif } data->current_pixmap = 0; @@ -994,8 +994,18 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) } } if (xcount > 0) { +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(data->xrender_available == SDL_TRUE) + { + XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, + (XRenderColor)foreground, xrects, xcount); + } + else +#endif + { XFillRectangles(data->display, data->drawable, data->gc, xrects, xcount); + } } SDL_stack_free(xpoints); From 941436daab31addb7706293e74383dfd1ba789de Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 31 May 2010 13:27:27 +0530 Subject: [PATCH 08/47] Modified configure.in to allow building with Xrender. Fixed all problems that prevented compilation. Builds fine now :) --- configure.in | 33 ++++++++++++++++++++++---- include/SDL_config.h.in | 2 ++ src/video/x11/SDL_x11render.c | 44 +++++++++++++++++++++-------------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/configure.in b/configure.in index 00c15101d..bc901943b 100644 --- a/configure.in +++ b/configure.in @@ -1128,16 +1128,13 @@ AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for ful ]) if test x$have_xrandr_h_hdr = xyes; then if test x$enable_x11_shared = xyes && test x$xrandr_lib != x ; then - echo "-- dynamic libXrender -> $xrender_lib" echo "-- dynamic libXrandr -> $xrandr_lib" - AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER, "$xrender_lib") AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR, "$xrandr_lib") definitely_enable_video_x11_xrandr=yes else - AC_CHECK_LIB(Xrender, XRenderQueryExtension, have_xrender_lib=yes) AC_CHECK_LIB(Xrandr, XRRQueryExtension, have_xrandr_lib=yes) - if test x$have_xrender_lib = xyes && test x$have_xrandr_lib = xyes ; then - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr -lXrender" + if test x$have_xrandr_lib = xyes ; then + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXrandr" definitely_enable_video_x11_xrandr=yes fi fi @@ -1199,6 +1196,32 @@ AC_HELP_STRING([--enable-video-x11-scrnsaver], [enable X11 screensaver extension if test x$definitely_enable_video_x11_scrnsaver = xyes; then AC_DEFINE(SDL_VIDEO_DRIVER_X11_SCRNSAVER) fi + AC_ARG_ENABLE(video-x11-xrender, +AC_HELP_STRING([--enable-video-x11-xrender], [enable X11 Xrender extension [[default=yes]]]), + , enable_video_x11_xrender=yes) + if test x$enable_video_x11_xrender = xyes; then + AC_CHECK_HEADER(X11/extensions/Xrender.h, + have_xrender_h_hdr=yes, + have_xrender_h_hdr=no, + [#include + ]) + 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(render-x11, AC_HELP_STRING([--enable-render-x11], [enable the X11 render driver [[default=yes]]]), diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 473a0f323..b9e1ef300 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -280,6 +280,8 @@ #undef SDL_VIDEO_DRIVER_X11_XV #undef SDL_VIDEO_DRIVER_X11_XRENDER +#undef SDL_VIDEO_RENDER_X11 + #undef SDL_VIDEO_RENDER_D3D #undef SDL_VIDEO_RENDER_GDI #undef SDL_VIDEO_RENDER_OGL diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 0111ccacd..d5631197c 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -219,7 +219,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { data->xrender_available = SDL_TRUE; data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); - if(!xwindow_pict_fmt) { + if(!data->xwindow_pict_fmt) { data->xrender_available = SDL_FALSE; } data->xwindow_pict_attr.graphics_exposures = False; @@ -285,8 +285,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->xrender_available == SDL_TRUE) { data->pixmap_picts[i] = - XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, &xwindow_pict_attr); + XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, + data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); if(!data->pixmap_picts[i]) { data->xrender_available = SDL_FALSE; } @@ -354,7 +354,7 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) XFreePixmap(data->display, data->pixmaps[i]); data->pixmaps[i] = None; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->pictures[i] = None; + data->pixmap_picts[i] = None; #endif } } @@ -368,10 +368,10 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->xrender_available == SDL_TRUE) { - data->pictures[i] = - XCreatePicture(data->display, data->pixmap[i], data->xwindow_pict_fmt, + data->pixmap_picts[i] = + XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); - if(!data->pictures[i]) { + if(!data->pixmap_picts[i]) { data->xrender_available = SDL_FALSE; } } @@ -380,7 +380,7 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) if (n > 0) { data->drawable = data->pixmaps[0]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->drawable_pict = data->pictures[0]; + data->drawable_pict = data->pixmap_picts[0]; #endif } data->current_pixmap = 0; @@ -419,7 +419,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER // Assume the texture is supported by Xrender data->xrender_available = SDL_TRUE; - if(renderdata->xrender_available == SDL_False) { + if(renderdata->xrender_available == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; @@ -523,21 +523,24 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) x11_fmt_mask = (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask | PictFormatBlueMask); - x11_templ_fmt.depth = (data->format).BitsPerPixel; - x11_temp_fmt.direct.redMask = (data->format).Rmask; - x11_temp_fmt.direct.greenMask = (data->format).Gmask; - x11_temp_fmt.direct.blueMask = (data->format).Bmask; - x11_temp_fmt.direct.alphaMask = (data->format).Amask; + Uint32 Rmask, Gmask, Bmask, Amask; + int bpp; + SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + x11_templ_fmt.depth = bpp; + x11_templ_fmt.direct.redMask = Rmask; + x11_templ_fmt.direct.greenMask = Gmask; + x11_templ_fmt.direct.blueMask = Bmask; + x11_templ_fmt.direct.alphaMask = Amask; /* Return one matching XRenderPictFormat */ - data->pict_fmt = + data->picture_fmt = XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); - if(!data->pict_fmt) { + if(!data->picture_fmt) { data->xrender_available = SDL_FALSE; } data->picture_attr_valuemask = CPGraphicsExposure; (data->picture_attr).graphics_exposures = False; data->picture = - XCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, + XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, data->picture_attr_valuemask, &(data->picture_attr)); if(!data->picture) { data->xrender_available = SDL_FALSE; @@ -997,8 +1000,13 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->xrender_available == SDL_TRUE) { + XRenderColor xrender_foreground_color; + xrender_foreground_color.red = renderer->r; + xrender_foreground_color.green = renderer->g; + xrender_foreground_color.blue = renderer->b; + xrender_foreground_color.alpha = renderer->a; XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, - (XRenderColor)foreground, xrects, xcount); + &xrender_foreground_color, xrects, xcount); } else #endif From bb399ee9cf91e1512347d642add140c2446af276 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 31 May 2010 15:09:36 +0530 Subject: [PATCH 09/47] Xrender uses 16 bit color per channel. Fixed the color handling in X11_RenderFillRects to match this. Xrender just works now for filling rectangles :D . --- src/video/x11/SDL_x11render.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index d5631197c..b30336290 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1001,10 +1001,10 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) if(data->xrender_available == SDL_TRUE) { XRenderColor xrender_foreground_color; - xrender_foreground_color.red = renderer->r; - xrender_foreground_color.green = renderer->g; - xrender_foreground_color.blue = renderer->b; - xrender_foreground_color.alpha = renderer->a; + xrender_foreground_color.red = (unsigned short) ((renderer->r / 255.0) * 0xFFFF); + xrender_foreground_color.green = (unsigned short) ((renderer->g / 255.0) * 0xFFFF); + xrender_foreground_color.blue = (unsigned short) ((renderer->b / 255.0) * 0xFFFF); + xrender_foreground_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, &xrender_foreground_color, xrects, xcount); } From 83d881011d5c0a80d083433916fbbdf5f4e8ccaf Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 31 May 2010 17:04:20 +0530 Subject: [PATCH 10/47] X11_RenderPresent now uses XRender to blit back-buffers to the screen. --- src/video/x11/SDL_x11render.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index b30336290..184f7479a 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1205,9 +1205,19 @@ X11_RenderPresent(SDL_Renderer * renderer) if (!(renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)) { for (dirty = data->dirty.list; dirty; dirty = dirty->next) { const SDL_Rect *rect = &dirty->rect; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(data->xrender_available == SDL_TRUE) + { + XRenderComposite(data->display, PictOpSrc, 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); } @@ -1217,9 +1227,15 @@ X11_RenderPresent(SDL_Renderer * renderer) if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { data->current_pixmap = (data->current_pixmap + 1) % 2; data->drawable = data->pixmaps[data->current_pixmap]; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->drawable_pict = data->pixmap_picts[data->current_pixmap]; +#endif } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { data->current_pixmap = (data->current_pixmap + 1) % 3; data->drawable = data->pixmaps[data->current_pixmap]; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->drawable_pict = data->pixmap_picts[data->current_pixmap]; +#endif } } From 181aedae38682b63a7a1cb015fb065b02476ff96 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 2 Jun 2010 09:01:37 +0530 Subject: [PATCH 11/47] Fix the rendering color channels to be premultiplied with the alpha channel as thats what Xrender expects. Small fixes in X11_CreateTexture. Add some new functions in SDL_x11sym.h as well as support for Xrender. --- src/video/x11/SDL_x11dyn.h | 2 +- src/video/x11/SDL_x11render.c | 137 +++++++++++++++++++++------------- src/video/x11/SDL_x11sym.h | 11 +++ src/video/x11/SDL_x11video.h | 3 +- 4 files changed, 98 insertions(+), 55 deletions(-) diff --git a/src/video/x11/SDL_x11dyn.h b/src/video/x11/SDL_x11dyn.h index c06a2d6fe..f8b3114fd 100644 --- a/src/video/x11/SDL_x11dyn.h +++ b/src/video/x11/SDL_x11dyn.h @@ -53,7 +53,7 @@ #endif #if SDL_VIDEO_DRIVER_X11_XRENDER -#include +#include #endif /* diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 184f7479a..019845e12 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -473,7 +473,13 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) XShmCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); - if (!data->image) { + + // This Pixmap is used by Xrender + data->pixmap = + XShmCreatePixmap(renderdata->display, renderdata->xwindow, shminfo->shmaddr, + shminfo, texture->w, texture->h, renderdata->depth); + + if (!(data->pixmap && data->image)) { XShmDetach(renderdata->display, shminfo); XSync(renderdata->display, False); shmdt(shminfo->shmaddr); @@ -486,6 +492,14 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) if (!data->image) #endif /* not NO_SHARED_MEMORY */ { + /* This is the case where the server does not have + shared memory support and the texture is streaming. + It does not make sense to use Xrender here because + we would have to copy the data onto a server side + pixmap with XPutImage first and only then can we + use Xrender + */ + data->pixels = SDL_malloc(texture->h * data->pitch); if (!data->pixels) { X11_DestroyTexture(renderer, texture); @@ -505,7 +519,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) return -1; } } - } else { + } + else { data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, texture->h, renderdata->depth); @@ -514,53 +529,11 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_SetError("XCreatePixmap() failed"); return -1; } - -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(renderdata->xrender_available) { - data->xrender_available = SDL_TRUE; - unsigned long x11_fmt_mask; // Format mask - XRenderPictFormat x11_templ_fmt; // Format template - x11_fmt_mask = - (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask - | PictFormatBlueMask); - Uint32 Rmask, Gmask, Bmask, Amask; - int bpp; - SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); - x11_templ_fmt.depth = bpp; - x11_templ_fmt.direct.redMask = Rmask; - x11_templ_fmt.direct.greenMask = Gmask; - x11_templ_fmt.direct.blueMask = Bmask; - x11_templ_fmt.direct.alphaMask = Amask; - /* Return one matching XRenderPictFormat */ - data->picture_fmt = - XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); - if(!data->picture_fmt) { - data->xrender_available = SDL_FALSE; - } - data->picture_attr_valuemask = CPGraphicsExposure; - (data->picture_attr).graphics_exposures = False; - data->picture = - XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, - data->picture_attr_valuemask, &(data->picture_attr)); - if(!data->picture) { - data->xrender_available = SDL_FALSE; - } - } - /* We thought we could render the texture with Xrender but this was - not possible for some reason. Now we must ensure that texture - format and window format match to avoid a BadMatch error. - */ - if(data->xrender_available == SDL_FALSE) { - if (texture->format != display->current_mode.format) { - SDL_SetError("Texture format doesn't match window format"); - return -1; - } - } -#endif data->image = XCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, 0, NULL, texture->w, - texture->h, SDL_BYTESPERPIXEL(data->format) * 8, + renderdata->depth, ZPixmap, 0, NULL, + texture->w, texture->h, + SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); if (!data->image) { X11_DestroyTexture(renderer, texture); @@ -568,7 +541,48 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) return -1; } } - +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(renderdata->xrender_available && data->pixmap) { + data->xrender_available = SDL_TRUE; + unsigned long x11_fmt_mask; // Format mask + XRenderPictFormat x11_templ_fmt; // Format template + x11_fmt_mask = + (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask + | PictFormatBlueMask); + Uint32 Rmask, Gmask, Bmask, Amask; + int bpp; + SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + x11_templ_fmt.depth = bpp; + x11_templ_fmt.direct.redMask = Rmask; + x11_templ_fmt.direct.greenMask = Gmask; + x11_templ_fmt.direct.blueMask = Bmask; + x11_templ_fmt.direct.alphaMask = Amask; + /* Return one matching XRenderPictFormat */ + data->picture_fmt = + XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); + if(!data->picture_fmt) { + data->xrender_available = SDL_FALSE; + } + data->picture_attr_valuemask = CPGraphicsExposure; + (data->picture_attr).graphics_exposures = False; + data->picture = + XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, + data->picture_attr_valuemask, &(data->picture_attr)); + if(!data->picture) { + data->xrender_available = SDL_FALSE; + } + } + /* We thought we could render the texture with Xrender but this was + not possible for some reason. Now we must ensure that texture + format and window format match to avoid a BadMatch error. + */ + if(data->xrender_available == SDL_FALSE) { + if (texture->format != display->current_mode.format) { + SDL_SetError("Texture format doesn't match window format"); + return -1; + } + } +#endif return 0; } @@ -638,6 +652,7 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; if (data->pixels) { + // If we have already allocated memory or were given memory by XShm Uint8 *src, *dst; int row; size_t length; @@ -652,6 +667,23 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, src += pitch; dst += data->pitch; } + /* If this is a static texture we would use Xrender for it + but this requires that the server side Pixmap associated + with this texture be updated with the data as well and + that the pixmap is not a shared memory pixmap. + Hopefully the user will not update static textures so + frequently as to cause a slowdown. + */ + if (texture->access == SDL_TEXTUREACCESS_STATIC) { +#ifndef NO_SHARED_MEMORY + if(!data->shminfo.shmaddr) +#endif + { + XPutImage(renderdata->display, data->pixmap, renderdata->gc, + data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); + } + } + } else { data->image->width = rect->w; data->image->height = rect->h; @@ -1001,10 +1033,11 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) if(data->xrender_available == SDL_TRUE) { XRenderColor xrender_foreground_color; - xrender_foreground_color.red = (unsigned short) ((renderer->r / 255.0) * 0xFFFF); - xrender_foreground_color.green = (unsigned short) ((renderer->g / 255.0) * 0xFFFF); - xrender_foreground_color.blue = (unsigned short) ((renderer->b / 255.0) * 0xFFFF); - xrender_foreground_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); + // Premultiply the color channels as well as modulate them to a 16 bit color space + xrender_foreground_color.red = ((unsigned short)renderer->r + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1; XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, &xrender_foreground_color, xrects, xcount); } diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 0cdcfe8dc..d01503eec 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -177,6 +177,7 @@ SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b),(a,b),return) SDL_X11_SYM(Status,XShmDetach,(Display* a,XShmSegmentInfo* b),(a,b),return) SDL_X11_SYM(Status,XShmPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j,Bool k),(a,b,c,d,e,f,g,h,i,j,k),return) SDL_X11_SYM(XImage*,XShmCreateImage,(Display* a,Visual* b,unsigned int c,int d,char* e,XShmSegmentInfo* f,unsigned int g,unsigned int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(Pixmap,XShmCreatePixmap,(Display *a,Drawable b,char* c,XShmSegmentInfo* d, unsigned int e, unsigned int f, unsigned int g),(a,b,c,d,e,f,g),return) SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return) #endif @@ -232,6 +233,16 @@ SDL_X11_SYM(Status,XScreenSaverQueryVersion,(Display *dpy,int *major_versionp,in SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),return) #endif +/* XRender support */ +#if SDL_VIDEO_DRIVER_X11_XRENDER +SDL_X11_MODULE(XRENDER) +SDL_X11_SYM(Bool,XRenderQueryExtension,(Display *dpy,int *event_base,int *error_base),(dpy,event_base,error_base),return) +SDL_X11_SYM(XRenderPictFormat*,XRenderFindVisualFormat,(Display *dpy,_Xconst Visual *visual),(dpy,visual),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,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(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) +#endif /* *INDENT-ON* */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 6c2377376..7f5d73421 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -46,9 +46,8 @@ #include #endif #if SDL_VIDEO_DRIVER_X11_XRENDER -#include +#include #endif - #include "SDL_x11dyn.h" #include "SDL_x11events.h" From e4d5d55364ad2f53404bf3d4ee619e3464f51cf6 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 2 Jun 2010 11:45:15 +0530 Subject: [PATCH 12/47] Fix X11_FillRects to work with double buffering as well as triple buffering. This requires that the buffer pixmap be cleared after every render. --- src/video/x11/SDL_x11render.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 019845e12..9a91e966f 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -290,6 +290,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(!data->pixmap_picts[i]) { data->xrender_available = SDL_FALSE; } + XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i], + 0, 0, 0, 0, 0, 0, window->w, window->h); } #endif } @@ -374,6 +376,8 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) if(!data->pixmap_picts[i]) { data->xrender_available = SDL_FALSE; } + XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i], + 0, 0, 0, 0, 0, 0, window->w, window->h); } #endif } @@ -735,6 +739,13 @@ X11_SetDrawBlendMode(SDL_Renderer * renderer) switch (renderer->blendMode) { case SDL_BLENDMODE_NONE: return 0; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + case SDL_BLENDMODE_MASK: // Use src pict as mask + case SDL_BLENDMODE_ADD: // PictOpAdd + case SDL_BLENDMODE_BLEND: // PictOpOver + /* FIXME case SDL_BLENDMODE_MOD: */ +#endif + return 0; default: SDL_Unsupported(); renderer->blendMode = SDL_BLENDMODE_NONE; @@ -1038,7 +1049,7 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) xrender_foreground_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1; xrender_foreground_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1; xrender_foreground_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1; - XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, + XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, &xrender_foreground_color, xrects, xcount); } else @@ -1241,7 +1252,7 @@ X11_RenderPresent(SDL_Renderer * renderer) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->xrender_available == SDL_TRUE) { - XRenderComposite(data->display, PictOpSrc, data->drawable_pict, None, data->xwindow_pict, + XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, data->xwindow_pict, rect->x, rect->y, 0, 0, rect->x, rect->y, rect->w, rect->h); } else @@ -1253,6 +1264,13 @@ X11_RenderPresent(SDL_Renderer * renderer) } } SDL_ClearDirtyRects(&data->dirty); +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + // Clear each pixmap after a render + if(data->xrender_available == SDL_TRUE) { + XRenderComposite(data->display, PictOpClear, data->drawable_pict, None, data->drawable_pict, + 0, 0, 0, 0, 0, 0, renderer->window->w, renderer->window->h); + } +#endif } XSync(data->display, False); From d3ed0db8db6bc3f6ee45538a7e105ec359c5856b Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 2 Jun 2010 11:55:40 +0530 Subject: [PATCH 13/47] It seems that the off-screen buffers (or pixmaps) only need to be cleared while initializing. --- src/video/x11/SDL_x11render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 9a91e966f..5af377882 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1264,13 +1264,13 @@ X11_RenderPresent(SDL_Renderer * renderer) } } SDL_ClearDirtyRects(&data->dirty); -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +/*#ifdef SDL_VIDEO_DRIVER_X11_XRENDER // Clear each pixmap after a render if(data->xrender_available == SDL_TRUE) { XRenderComposite(data->display, PictOpClear, data->drawable_pict, None, data->drawable_pict, 0, 0, 0, 0, 0, 0, renderer->window->w, renderer->window->h); } -#endif +#endif*/ } XSync(data->display, False); From deb0d712cef48baa4df42e4fa87c67fccdf9a596 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Tue, 8 Jun 2010 19:26:32 +0530 Subject: [PATCH 14/47] X11_DrawRects now uses a very hacky way of drawing rectangles with XRender. This will be improved in some time. --- src/video/x11/SDL_x11render.c | 115 ++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 5af377882..405fda2a5 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -222,10 +222,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(!data->xwindow_pict_fmt) { data->xrender_available = SDL_FALSE; } - data->xwindow_pict_attr.graphics_exposures = False; - data->xwindow_pict_attr_valuemask = CPGraphicsExposure; data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); + 0, None); if(!data->xwindow_pict) { data->xrender_available = SDL_FALSE; } @@ -286,7 +284,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(data->xrender_available == SDL_TRUE) { data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); + 0, None); if(!data->pixmap_picts[i]) { data->xrender_available = SDL_FALSE; } @@ -372,7 +370,7 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) if(data->xrender_available == SDL_TRUE) { data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, - data->xwindow_pict_attr_valuemask, &data->xwindow_pict_attr); + 0, None); if(!data->pixmap_picts[i]) { data->xrender_available = SDL_FALSE; } @@ -769,6 +767,18 @@ renderdrawcolor(SDL_Renderer * renderer, int premult) return SDL_MapRGBA(&data->format, r, g, b, a); } +static XRenderColor +xrenderdrawcolor(SDL_Renderer *renderer) +{ + // Premultiply the color channels as well as modulate them to a 16 bit color space + XRenderColor xrender_color; + xrender_color.red = ((unsigned short)renderer->r + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1; + return xrender_color; +} + static int X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count) @@ -973,32 +983,75 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) 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->xrender_available == SDL_TRUE) { + XRenderColor xrender_foreground; + xrender_foreground = xrenderdrawcolor(renderer); + + xrects = SDL_stack_alloc(XRectangle, 4*count); + xcount = 0; + for(i = 0; i < 4*count; i+=4) { + if(!SDL_IntersectRect(rects[i], &clip, &rect)) { + continue; + } + + xrects[xcount].x = rect.x; + xrects[xcount].y = rect.y; + xrects[xcount].width = 1; + xrects[xcount].height = rect.h; + ++xcount; + xrects[xcount].x = rect.x; + xrects[xcount].y = rect.y+rect.h; + xrects[xcount].width = rect.w; + xrects[xcount].height = 1; + ++xcount; + xrects[xcount].x = rect.x+rect.w; + xrects[xcount].y = rect.y; + xrects[xcount].width = 1; + xrects[xcount].height = rect.h; + ++xcount; + xrects[xcount].x = rect.x; + xrects[xcount].y = rect.y; + xrects[xcount].width = rect.w; + xrects[xcount].height = 1; + ++xcount; + if(data->makedirty) { + SDL_AddDirtyRect(&data->dirty, &rect); + } } + XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, + &xrender_foreground, xrects, xcount); + } + else +#endif + { + 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; + } - 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); + 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); + } + } + if (xcount > 0) { + XDrawRectangles(data->display, data->drawable, data->gc, + xrects, xcount); } } - if (xcount > 0) { - XDrawRectangles(data->display, data->drawable, data->gc, - xrects, xcount); - } - SDL_stack_free(xpoints); + SDL_stack_free(xrects); return 0; } @@ -1044,11 +1097,7 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) if(data->xrender_available == SDL_TRUE) { XRenderColor xrender_foreground_color; - // Premultiply the color channels as well as modulate them to a 16 bit color space - xrender_foreground_color.red = ((unsigned short)renderer->r + 1) * ((unsigned short)renderer->a + 1) - 1; - xrender_foreground_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1; - xrender_foreground_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1; - xrender_foreground_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color = xrenderdrawcolor(renderer); XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, &xrender_foreground_color, xrects, xcount); } @@ -1253,7 +1302,7 @@ X11_RenderPresent(SDL_Renderer * renderer) if(data->xrender_available == SDL_TRUE) { XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, data->xwindow_pict, - rect->x, rect->y, 0, 0, rect->x, rect->y, rect->w, rect->h); + rect->x, rect->y, 0, 0, rect->x, rect->y, rect->w+1, rect->h+1); } else #endif From de6dd6c23c3f8a34ffd0d78f0ed3e6eb94606575 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 14 Jun 2010 18:22:48 +0530 Subject: [PATCH 15/47] X11_RenderFillRects and X11_RenderDrawRects use a server side mask pixmap of 1 bit depth now. All drawing on these pixmaps is done by server side functions such as XDrawRectangles and XFillRectangles. --- src/video/x11/SDL_x11render.c | 262 +++++++++++++++++++++------------- 1 file changed, 163 insertions(+), 99 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 405fda2a5..ec8fb943f 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1,4 +1,5 @@ /* + SDL - Simple DirectMedia Layer Copyright (C) 1997-2010 Sam Lantinga @@ -96,13 +97,14 @@ typedef struct Window xwindow; Pixmap pixmaps[3]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER + Pixmap mask; Picture xwindow_pict; Picture pixmap_picts[3]; Picture drawable_pict; + Picture mask_pict; XRenderPictFormat* xwindow_pict_fmt; - XRenderPictureAttributes xwindow_pict_attr; - unsigned int xwindow_pict_attr_valuemask; - SDL_bool xrender_available; + GC mask_gc; + SDL_bool use_xrender; #endif int current_pixmap; Drawable drawable; @@ -122,7 +124,7 @@ typedef struct XRenderPictFormat* picture_fmt; XRenderPictureAttributes picture_attr; unsigned int picture_attr_valuemask; - SDL_bool xrender_available; + SDL_bool use_xrender; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -217,20 +219,32 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER int event_basep, error_basep; if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { - data->xrender_available = SDL_TRUE; + data->use_xrender = SDL_TRUE; data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); if(!data->xwindow_pict_fmt) { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; + goto fallback; } data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, - 0, None); + 0, NULL); if(!data->xwindow_pict) { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; + goto fallback; } + // Create a 1 bit depth mask + data->mask = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 1); + data->mask_pict = XRenderCreatePicture(data->display, data->mask, + XRenderFindStandardFormat(data->display, PictStandardA1), + 0, NULL); + XGCValues gcv_mask; + gcv_mask.foreground = 1; + gcv_mask.background = 0; + data->mask_gc = XCreateGC(data->display, data->mask, GCBackground | GCForeground, &gcv_mask); } else { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; } + fallback: #endif renderer->DisplayModeChanged = X11_DisplayModeChanged; renderer->CreateTexture = X11_CreateTexture; @@ -281,12 +295,12 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) { + if(data->use_xrender == SDL_TRUE) { data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, 0, None); if(!data->pixmap_picts[i]) { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; } XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i], 0, 0, 0, 0, 0, 0, window->w, window->h); @@ -296,14 +310,14 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if (n > 0) { data->drawable = data->pixmaps[0]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) + 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->xrender_available == SDL_TRUE) + if(data->use_xrender == SDL_TRUE) data->drawable_pict = data->xwindow_pict; #endif data->makedirty = SDL_FALSE; @@ -367,12 +381,12 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) return -1; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) { + if(data->use_xrender == SDL_TRUE) { data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, 0, None); if(!data->pixmap_picts[i]) { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; } XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i], 0, 0, 0, 0, 0, 0, window->w, window->h); @@ -420,8 +434,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER // Assume the texture is supported by Xrender - data->xrender_available = SDL_TRUE; - if(renderdata->xrender_available == SDL_FALSE) { + data->use_xrender = SDL_TRUE; + if(renderdata->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; @@ -544,8 +558,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(renderdata->xrender_available && data->pixmap) { - data->xrender_available = SDL_TRUE; + if(renderdata->use_xrender && data->pixmap) { + data->use_xrender = SDL_TRUE; unsigned long x11_fmt_mask; // Format mask XRenderPictFormat x11_templ_fmt; // Format template x11_fmt_mask = @@ -563,7 +577,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) data->picture_fmt = XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); if(!data->picture_fmt) { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; } data->picture_attr_valuemask = CPGraphicsExposure; (data->picture_attr).graphics_exposures = False; @@ -571,14 +585,14 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, data->picture_attr_valuemask, &(data->picture_attr)); if(!data->picture) { - data->xrender_available = SDL_FALSE; + data->use_xrender = SDL_FALSE; } } /* We thought we could render the texture with Xrender but this was not possible for some reason. Now we must ensure that texture format and window format match to avoid a BadMatch error. */ - if(data->xrender_available == SDL_FALSE) { + if(data->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; @@ -974,57 +988,56 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) X11_RenderData *data = (X11_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; SDL_Rect clip, rect; - unsigned long foreground; - XRectangle *xrects, *xrect; int i, xcount; - + XRectangle *xrects, *xrect; + clip.x = 0; clip.y = 0; clip.w = window->w; clip.h = window->h; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) { - XRenderColor xrender_foreground; - xrender_foreground = xrenderdrawcolor(renderer); + if(data->use_xrender == SDL_TRUE) { + XRectangle xclip; - xrects = SDL_stack_alloc(XRectangle, 4*count); + xclip.x = (short)clip.x; + xclip.y = (short)clip.y; + xclip.width = (unsigned short)clip.w; + xclip.height = (unsigned short)clip.h; + + XRenderColor foreground; + foreground = xrenderdrawcolor(renderer); + + xrect = xrects = SDL_stack_alloc(XRectangle, count); xcount = 0; - for(i = 0; i < 4*count; i+=4) { - if(!SDL_IntersectRect(rects[i], &clip, &rect)) { - continue; - } - - xrects[xcount].x = rect.x; - xrects[xcount].y = rect.y; - xrects[xcount].width = 1; - xrects[xcount].height = rect.h; - ++xcount; - xrects[xcount].x = rect.x; - xrects[xcount].y = rect.y+rect.h; - xrects[xcount].width = rect.w; - xrects[xcount].height = 1; - ++xcount; - xrects[xcount].x = rect.x+rect.w; - xrects[xcount].y = rect.y; - xrects[xcount].width = 1; - xrects[xcount].height = rect.h; - ++xcount; - xrects[xcount].x = rect.x; - xrects[xcount].y = rect.y; - xrects[xcount].width = rect.w; - xrects[xcount].height = 1; + for (i = 0; i < count; ++i) { + xrect->x = (short)rects[i]->x; + xrect->y = (short)rects[i]->y; + xrect->width = (unsigned short)rects[i]->w; + xrect->height = (unsigned short)rects[i]->h; + ++xrect; ++xcount; - if(data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &rect); - } } - XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, - &xrender_foreground, xrects, xcount); + if (data->makedirty) { + SDL_AddDirtyRect(&data->dirty, &clip); + } + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XDrawRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); + Picture fill = + XRenderCreateSolidFill(data->display, &foreground); + XRenderSetPictureClipRectangles(data->display, data->drawable_pict, 0, 0, &xclip, 1); + XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderFreePicture(data->display, fill); + SDL_stack_free(xrects); } else #endif { + + unsigned long foreground; + foreground = renderdrawcolor(renderer, 1); XSetForeground(data->display, data->gc, foreground); @@ -1062,54 +1075,87 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) X11_RenderData *data = (X11_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; SDL_Rect clip, rect; - unsigned long foreground; - XRectangle *xrects, *xrect; - int i, xcount; - + clip.x = 0; clip.y = 0; clip.w = window->w; clip.h = window->h; - foreground = renderdrawcolor(renderer, 1); - XSetForeground(data->display, data->gc, foreground); + int i, xcount; + XRectangle *xrects, *xrect; xrect = xrects = SDL_stack_alloc(XRectangle, count); xcount = 0; - for (i = 0; i < count; ++i) { - if (!SDL_IntersectRect(rects[i], &clip, &rect)) { - continue; - } - xrect->x = (short)rect.x; - xrect->y = (short)rect.y; - xrect->width = (unsigned short)rect.w; - xrect->height = (unsigned short)rect.h; - ++xrect; - ++xcount; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(data->use_xrender == SDL_TRUE) { + XRectangle xclip; + + xclip.x = (short)clip.x; + xclip.y = (short)clip.y; + xclip.width = (unsigned short)clip.w; + xclip.height = (unsigned short)clip.h; + + XRenderColor foreground; + foreground = xrenderdrawcolor(renderer); + + for (i = 0; i < count; ++i) { + xrect->x = (short)rects[i]->x; + xrect->y = (short)rects[i]->y; + xrect->width = (unsigned short)rects[i]->w; + xrect->height = (unsigned short)rects[i]->h; + ++xrect; + ++xcount; + } if (data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &rect); + SDL_AddDirtyRect(&data->dirty, &clip); } + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XFillRectangles(data->display, data->mask, data->mask_gc, + xrects, xcount); + XRenderSetPictureClipRectangles(data->display, data->drawable_pict, 0, 0, &xclip, 1); + Picture fill = + XRenderCreateSolidFill(data->display, &foreground); + XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderFreePicture(data->display, fill); + SDL_stack_free(xrects); + } - if (xcount > 0) { -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) - { - XRenderColor xrender_foreground_color; - xrender_foreground_color = xrenderdrawcolor(renderer); - XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, - &xrender_foreground_color, xrects, xcount); - } - else + else #endif - { + { + unsigned long foreground; + XRectangle *xrects, *xrect; + + 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; + } + + 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); + } + } XFillRectangles(data->display, data->drawable, data->gc, xrects, xcount); - } + SDL_stack_free(xrects); } - SDL_stack_free(xpoints); - + return 0; } @@ -1299,10 +1345,10 @@ X11_RenderPresent(SDL_Renderer * renderer) for (dirty = data->dirty.list; dirty; dirty = dirty->next) { const SDL_Rect *rect = &dirty->rect; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) + if(data->use_xrender == SDL_TRUE) { XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, data->xwindow_pict, - rect->x, rect->y, 0, 0, rect->x, rect->y, rect->w+1, rect->h+1); + rect->x, rect->y, 0, 0, rect->x, rect->y, rect->w, rect->h); } else #endif @@ -1313,14 +1359,7 @@ X11_RenderPresent(SDL_Renderer * renderer) } } SDL_ClearDirtyRects(&data->dirty); -/*#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - // Clear each pixmap after a render - if(data->xrender_available == SDL_TRUE) { - XRenderComposite(data->display, PictOpClear, data->drawable_pict, None, data->drawable_pict, - 0, 0, 0, 0, 0, 0, renderer->window->w, renderer->window->h); - } -#endif*/ - } + } XSync(data->display, False); /* Update the flipping chain, if any */ @@ -1389,10 +1428,35 @@ X11_DestroyRenderer(SDL_Renderer * renderer) if (data->pixmaps[i] != None) { XFreePixmap(data->display, data->pixmaps[i]); } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->pixmap_picts[i] != None) { + XRenderFreePicture(data->display, data->pixmap_picts[i]); + } +#endif } if (data->gc) { XFreeGC(data->display, data->gc); } + if (data->drawable) { + XFreePixmap(data->display, data->drawable); + } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->mask_gc) { + XFreeGC(data->display, data->gc); + } + if (data->mask_pict) { + XRenderFreePicture(data->display, data->mask_pict); + } + if (data->mask) { + XFreePixmap(data->display, data->mask); + } + if (data->drawable_pict) { + XRenderFreePicture(data->display, data->drawable_pict); + } + if (data->xwindow_pict) { + XRenderFreePicture(data->display, data->xwindow_pict); + } +#endif SDL_FreeDirtyRects(&data->dirty); SDL_free(data); } From a218516b174590abc829157ce1b87809070331dc Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Tue, 15 Jun 2010 19:10:06 +0530 Subject: [PATCH 16/47] X11_RenderDrawLines and X11_RenderDrawPoints use XRender now. --- src/video/x11/SDL_x11render.c | 62 +++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index ec8fb943f..290008e38 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -799,7 +799,6 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, { X11_RenderData *data = (X11_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; - unsigned long foreground; XPoint *xpoints, *xpoint; int i, xcount; @@ -818,9 +817,6 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, SDL_AddDirtyRect(&data->dirty, &rect); } - foreground = renderdrawcolor(renderer, 1); - XSetForeground(data->display, data->gc, foreground); - xpoint = xpoints = SDL_stack_alloc(XPoint, count); xcount = 0; for (i = 0; i < count; ++i) { @@ -834,9 +830,30 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, ++xpoint; ++xcount; } - if (xcount > 0) { - XDrawPoints(data->display, data->drawable, data->gc, xpoints, xcount, +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender == SDL_TRUE) { + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XDrawPoints(data->display, data->mask, data->mask_gc, xpoints, xcount, CoordModeOrigin); + XRenderColor foreground = xrenderdrawcolor(renderer); + Picture fill = + XRenderCreateSolidFill(data->display, &foreground); + XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderFreePicture(data->display, fill); + } + 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); @@ -861,6 +878,22 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, clip.w = window->w; clip.h = window->h; + Pixmap drawable; + GC gc; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender == SDL_TRUE) { + drawable = data->mask; + gc = data->mask_gc; + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + } + else +#endif + { + drawable = data->drawable; + gc = data->gc; + } + foreground = renderdrawcolor(renderer, 1); XSetForeground(data->display, data->gc, foreground); @@ -915,10 +948,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, ++xpoint; ++xcount; } - XDrawLines(data->display, data->drawable, data->gc, + 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; @@ -962,10 +995,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, if (xcount > 1) { int x2 = xpoint[-1].x; int y2 = xpoint[-1].y; - XDrawLines(data->display, data->drawable, data->gc, xpoints, xcount, + 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; @@ -977,6 +1010,15 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, SDL_AddDirtyRect(&data->dirty, &rect); } } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(data->use_xrender == SDL_TRUE) { + XRenderColor xrforeground = xrenderdrawcolor(renderer); + Picture fill = XRenderCreateSolidFill(data->display, &xrforeground); + XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderFreePicture(data->display, fill); + } +#endif SDL_stack_free(xpoints); return 0; From 1c3bba7f8a3ea7593a106f82f93d2b50c78e0500 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 16 Jun 2010 10:50:01 +0530 Subject: [PATCH 17/47] SDL_Textures should work with XRender now provided that the texture format and screen format match. This is only a temporary limitation. --- src/video/x11/SDL_x11render.c | 258 +++++++++++++++++++--------------- 1 file changed, 141 insertions(+), 117 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 290008e38..95d9e0371 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -122,8 +122,6 @@ typedef struct #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture picture; XRenderPictFormat* picture_fmt; - XRenderPictureAttributes picture_attr; - unsigned int picture_attr_valuemask; SDL_bool use_xrender; #endif XImage *image; @@ -435,7 +433,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER // Assume the texture is supported by Xrender data->use_xrender = SDL_TRUE; - if(renderdata->use_xrender == SDL_FALSE) { + if (renderdata->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; @@ -490,12 +488,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) renderdata->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); - // This Pixmap is used by Xrender - data->pixmap = - XShmCreatePixmap(renderdata->display, renderdata->xwindow, shminfo->shmaddr, - shminfo, texture->w, texture->h, renderdata->depth); - - if (!(data->pixmap && data->image)) { + if (!data->image) { XShmDetach(renderdata->display, shminfo); XSync(renderdata->display, False); shmdt(shminfo->shmaddr); @@ -560,37 +553,41 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(renderdata->use_xrender && data->pixmap) { data->use_xrender = SDL_TRUE; - unsigned long x11_fmt_mask; // Format mask + /*unsigned long x11_fmt_mask; // Format mask XRenderPictFormat x11_templ_fmt; // Format template x11_fmt_mask = - (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask - | PictFormatBlueMask); + (PictFormatRedMask | PictFormatGreenMask + | PictFormatBlueMask | PictFormatAlphaMask); Uint32 Rmask, Gmask, Bmask, Amask; int bpp; SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); x11_templ_fmt.depth = bpp; - x11_templ_fmt.direct.redMask = Rmask; - x11_templ_fmt.direct.greenMask = Gmask; - x11_templ_fmt.direct.blueMask = Bmask; - x11_templ_fmt.direct.alphaMask = Amask; - /* Return one matching XRenderPictFormat */ + x11_templ_fmt.type = PictTypeDirect; + x11_templ_fmt.direct.red = Rmask / 0xff; + x11_templ_fmt.direct.green = Gmask / 0xff; + x11_templ_fmt.direct.blue = Bmask / 0xff; + x11_templ_fmt.direct.alpha = Amask / 0xff; + printf("%d %d %d %d\n", Rmask/0xff, Gmask/0xff, Bmask/0xff, Amask/0xff); + // Return a matching XRenderPictFormat + data->picture_fmt = + XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 0);*/ data->picture_fmt = - XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); + XRenderFindVisualFormat(renderdata->display, renderdata->visual); if(!data->picture_fmt) { + printf("XRenderFindFormat failed!\n"); data->use_xrender = SDL_FALSE; } - data->picture_attr_valuemask = CPGraphicsExposure; - (data->picture_attr).graphics_exposures = False; data->picture = - XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, - data->picture_attr_valuemask, &(data->picture_attr)); + XRenderCreatePicture(renderdata->display, data->pixmap, + data->picture_fmt, 0, NULL); if(!data->picture) { data->use_xrender = SDL_FALSE; } } /* We thought we could render the texture with Xrender but this was not possible for some reason. Now we must ensure that texture - format and window format match to avoid a BadMatch error. + format and window format match to avoid a BadMatch error when + rendering using the old pipeline. */ if(data->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { @@ -685,19 +682,13 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, } /* If this is a static texture we would use Xrender for it but this requires that the server side Pixmap associated - with this texture be updated with the data as well and - that the pixmap is not a shared memory pixmap. + with this texture be updated with the data as well. Hopefully the user will not update static textures so frequently as to cause a slowdown. */ if (texture->access == SDL_TEXTUREACCESS_STATIC) { -#ifndef NO_SHARED_MEMORY - if(!data->shminfo.shmaddr) -#endif - { XPutImage(renderdata->display, data->pixmap, renderdata->gc, data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); - } } } else { @@ -1211,103 +1202,136 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, if (data->makedirty) { SDL_AddDirtyRect(&data->dirty, dstrect); } - if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { -#ifndef NO_SHARED_MEMORY - if (texturedata->shminfo.shmaddr) { - XShmPutImage(data->display, data->drawable, data->gc, - texturedata->image, srcrect->x, srcrect->y, - dstrect->x, dstrect->y, srcrect->w, srcrect->h, - False); - } 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); +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender && texturedata->use_xrender && texture->access == SDL_TEXTUREACCESS_STATIC) { + if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) { + XRenderComposite(data->display, PictOpOver, texturedata->picture, None, data->drawable_pict, + srcrect->x, srcrect->y, 0, 0, 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); + Pixmap scaling_pixmap = + XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h, + data->depth); + Picture scaling_picture = + XRenderCreatePicture(data->display, scaling_pixmap, texturedata->picture_fmt, + 0, NULL); + XRenderComposite(data->display, PictOpClear, scaling_picture, None, scaling_picture, + 0, 0, 0, 0, 0, 0, dstrect->w, dstrect->h); + XRenderComposite(data->display, PictOpSrc, texturedata->picture, None, scaling_picture, + srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h); + 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, scaling_picture, &xform); + XRenderComposite(data->display, PictOpOver, scaling_picture, None, data->drawable_pict, + 0, 0, 0, 0, dstrect->x, dstrect->y, dstrect->w, dstrect->h); + XRenderFreePicture(data->display, scaling_picture); + XFreePixmap(data->display, scaling_pixmap); } - } 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; + } + 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; - 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; + 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; + /* 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 + 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; + src.pixels = texturedata->pixels; + src.pitch = texturedata->pitch; + + SDL_zero(dst); + dst.format = &fmt; + dst.w = image->width; + dst.h = image->height; + dst.pixels = image->data; + dst.pitch = image->bytes_per_line; + + fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format); + + rect.x = 0; + rect.y = 0; + rect.w = dstrect->w; + rect.h = dstrect->h; + if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) { + return -1; + } + XPutImage(data->display, data->drawable, data->gc, image, 0, 0, + dstrect->x, dstrect->y, dstrect->w, dstrect->h); + } else { + XCopyArea(data->display, texturedata->pixmap, data->drawable, + data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, + srcrect->x, srcrect->y); } - XPutImage(data->display, data->drawable, data->gc, image, 0, 0, - dstrect->x, dstrect->y, dstrect->w, dstrect->h); - } else { - XCopyArea(data->display, texturedata->pixmap, data->drawable, - data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, - srcrect->x, srcrect->y); } return 0; } From 30d6668868174c3cddfd104d0763ec7cc8a39069 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Tue, 22 Jun 2010 20:01:38 +0530 Subject: [PATCH 18/47] Texture rendering mostly works now. Even SDL_TEXTUREACCESS_STREAMING is supported now with a little overhead. Scaling of textures happens using XRender. :D --- src/video/x11/SDL_x11render.c | 185 +++++++++++++++------------------- 1 file changed, 82 insertions(+), 103 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 95d9e0371..04a91fd3c 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -482,6 +482,14 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } if (!shm_error) { data->pixels = shminfo->shmaddr; + data->pixmap = + XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, + texture->h, renderdata->depth); + if (data->pixmap == None) { + X11_DestroyTexture(renderer, texture); + SDL_SetError("XCreatePixmap() failed"); + return -1; + } data->image = XShmCreateImage(renderdata->display, renderdata->visual, @@ -516,6 +524,14 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) return -1; } + data->pixmap = + XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, + texture->h, renderdata->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, data->pixels, @@ -665,7 +681,6 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; if (data->pixels) { - // If we have already allocated memory or were given memory by XShm Uint8 *src, *dst; int row; size_t length; @@ -680,17 +695,6 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, src += pitch; dst += data->pitch; } - /* If this is a static texture we would use Xrender for it - but this requires that the server side Pixmap associated - with this texture be updated with the data as well. - Hopefully the user will not update static textures so - frequently as to cause a slowdown. - */ - if (texture->access == SDL_TEXTUREACCESS_STATIC) { - XPutImage(renderdata->display, data->pixmap, renderdata->gc, - data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); - } - } else { data->image->width = rect->w; data->image->height = rect->h; @@ -823,15 +827,22 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender == SDL_TRUE) { + XRenderColor foreground; + + foreground = xrenderdrawcolor(renderer); + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + 0, 0, 0, 0, 0, 0, window->w, window->h); + XDrawPoints(data->display, data->mask, data->mask_gc, xpoints, xcount, CoordModeOrigin); - XRenderColor foreground = xrenderdrawcolor(renderer); + Picture fill = XRenderCreateSolidFill(data->display, &foreground); + XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderFreePicture(data->display, fill); } else @@ -1023,7 +1034,24 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) SDL_Rect clip, rect; int i, xcount; XRectangle *xrects, *xrect; - + xrect = xrects = SDL_stack_alloc(XRectangle, count); + xcount = 0; + for (i = 0; i < count; ++i) { + if (!SDL_IntersectRect(rects[i], &clip, &rect)) { + continue; + } + + xrect->x = (short)rect.x; + xrect->y = (short)rect.y; + xrect->width = (unsigned short)rect.w; + xrect->height = (unsigned short)rect.h; + ++xrect; + ++xcount; + + if (data->makedirty) { + SDL_AddDirtyRect(&data->dirty, &rect); + } + } clip.x = 0; clip.y = 0; clip.w = window->w; @@ -1031,67 +1059,26 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { - XRectangle xclip; - - xclip.x = (short)clip.x; - xclip.y = (short)clip.y; - xclip.width = (unsigned short)clip.w; - xclip.height = (unsigned short)clip.h; - XRenderColor foreground; foreground = xrenderdrawcolor(renderer); - xrect = xrects = SDL_stack_alloc(XRectangle, count); - xcount = 0; - for (i = 0; i < count; ++i) { - xrect->x = (short)rects[i]->x; - xrect->y = (short)rects[i]->y; - xrect->width = (unsigned short)rects[i]->w; - xrect->height = (unsigned short)rects[i]->h; - ++xrect; - ++xcount; - } - if (data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &clip); - } XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XDrawRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); Picture fill = XRenderCreateSolidFill(data->display, &foreground); - XRenderSetPictureClipRectangles(data->display, data->drawable_pict, 0, 0, &xclip, 1); XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XRenderFreePicture(data->display, fill); - SDL_stack_free(xrects); } else #endif { - unsigned long foreground; 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; - } - - 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); - } - } if (xcount > 0) { XDrawRectangles(data->display, data->drawable, data->gc, xrects, xcount); @@ -1116,79 +1103,55 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) int i, xcount; XRectangle *xrects, *xrect; - xrect = xrects = SDL_stack_alloc(XRectangle, count); xcount = 0; + for (i = 0; i < count; ++i) { + if (!SDL_IntersectRect(rects[i], &clip, &rect)) { + continue; + } + + xrect->x = (short)rect.x; + xrect->y = (short)rect.y; + xrect->width = (unsigned short)rect.w; + xrect->height = (unsigned short)rect.h; + ++xrect; + ++xcount; + + if (data->makedirty) { + SDL_AddDirtyRect(&data->dirty, &rect); + } + } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { - XRectangle xclip; - - xclip.x = (short)clip.x; - xclip.y = (short)clip.y; - xclip.width = (unsigned short)clip.w; - xclip.height = (unsigned short)clip.h; - XRenderColor foreground; foreground = xrenderdrawcolor(renderer); - - for (i = 0; i < count; ++i) { - xrect->x = (short)rects[i]->x; - xrect->y = (short)rects[i]->y; - xrect->width = (unsigned short)rects[i]->w; - xrect->height = (unsigned short)rects[i]->h; - ++xrect; - ++xcount; - } - if (data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &clip); - } + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XFillRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); - XRenderSetPictureClipRectangles(data->display, data->drawable_pict, 0, 0, &xclip, 1); Picture fill = XRenderCreateSolidFill(data->display, &foreground); XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XRenderFreePicture(data->display, fill); - SDL_stack_free(xrects); - } else #endif { unsigned long foreground; - XRectangle *xrects, *xrect; - + 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; - } - - 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); - } - } + XFillRectangles(data->display, data->drawable, data->gc, xrects, xcount); - SDL_stack_free(xrects); } - + + SDL_stack_free(xrects); + return 0; } @@ -1203,7 +1166,23 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, SDL_AddDirtyRect(&data->dirty, dstrect); } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_xrender && texturedata->use_xrender && texture->access == SDL_TEXTUREACCESS_STATIC) { + if (data->use_xrender && texturedata->use_xrender) { + if(texture->access == SDL_TEXTUREACCESS_STREAMING) { +#ifndef NO_SHARED_MEMORY + if(texturedata->shminfo.shmaddr) { + XShmPutImage(data->display, texturedata->pixmap, data->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, data->gc, + texturedata->image, srcrect->x, srcrect->y, dstrect->x, + dstrect->y, srcrect->w, srcrect->h); + } + } if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) { XRenderComposite(data->display, PictOpOver, texturedata->picture, None, data->drawable_pict, srcrect->x, srcrect->y, 0, 0, dstrect->x, dstrect->y, srcrect->w, srcrect->h); From 11cb0401ef7764d697f256a43a6264a0212bf7d7 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 27 Jun 2010 09:51:51 +0530 Subject: [PATCH 19/47] Preliminary support for blending modes on drawing operations. --- src/video/x11/SDL_x11render.c | 43 ++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 04a91fd3c..fa1363b95 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -102,6 +102,7 @@ typedef struct Picture pixmap_picts[3]; Picture drawable_pict; Picture mask_pict; + int blend_op; XRenderPictFormat* xwindow_pict_fmt; GC mask_gc; SDL_bool use_xrender; @@ -743,14 +744,27 @@ X11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) static int X11_SetDrawBlendMode(SDL_Renderer * renderer) { + X11_RenderData *data = (X11_RenderData *) renderer->driverdata; switch (renderer->blendMode) { case SDL_BLENDMODE_NONE: - return 0; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->blend_op = PictOpSrc; + return 0; case SDL_BLENDMODE_MASK: // Use src pict as mask + data->blend_op = PictOpSrc; + return 0; case SDL_BLENDMODE_ADD: // PictOpAdd + data->blend_op = PictOpAdd; + return 0; case SDL_BLENDMODE_BLEND: // PictOpOver + data->blend_op = PictOpOver; + return 0; /* FIXME case SDL_BLENDMODE_MOD: */ + default: // PictOpSrc + SDL_Unsupported(); + renderer->blendMode = SDL_BLENDMODE_NONE; + data->blend_op = PictOpSrc; + return -1; #endif return 0; default: @@ -840,8 +854,8 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, Picture fill = XRenderCreateSolidFill(data->display, &foreground); - XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, + data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XRenderFreePicture(data->display, fill); } @@ -1016,8 +1030,8 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, if(data->use_xrender == SDL_TRUE) { XRenderColor xrforeground = xrenderdrawcolor(renderer); Picture fill = XRenderCreateSolidFill(data->display, &xrforeground); - XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, + data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XRenderFreePicture(data->display, fill); } #endif @@ -1067,8 +1081,8 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XDrawRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); Picture fill = XRenderCreateSolidFill(data->display, &foreground); - XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, + data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XRenderFreePicture(data->display, fill); } else @@ -1134,8 +1148,8 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) xrects, xcount); Picture fill = XRenderCreateSolidFill(data->display, &foreground); - XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, + data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XRenderFreePicture(data->display, fill); } else @@ -1392,8 +1406,15 @@ X11_RenderPresent(SDL_Renderer * renderer) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { - XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, data->xwindow_pict, - rect->x, rect->y, 0, 0, rect->x, rect->y, rect->w, rect->h); + if(renderer->blendMode == SDL_BLENDMODE_MASK) + XRenderComposite(data->display, data->blend_op, data->drawable_pict, + data->drawable_pict, data->xwindow_pict, rect->x, rect->y, + 0, 0, rect->x, rect->y, rect->w, rect->h); + else + 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 From d12b66dd2969262b6feaf4ca61f1aa53ca3fa5eb Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Thu, 1 Jul 2010 07:35:15 +0530 Subject: [PATCH 20/47] Fix blending modes for primitives. --- src/video/x11/SDL_x11render.c | 78 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index fa1363b95..fafe94809 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -231,9 +231,11 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) goto fallback; } // Create a 1 bit depth mask - data->mask = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 1); + data->mask = XCreatePixmap(data->display, data->xwindow, + window->w, window->h, 1); data->mask_pict = XRenderCreatePicture(data->display, data->mask, - XRenderFindStandardFormat(data->display, PictStandardA1), + XRenderFindStandardFormat(data->display, + PictStandardA1), 0, NULL); XGCValues gcv_mask; gcv_mask.foreground = 1; @@ -301,7 +303,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) if(!data->pixmap_picts[i]) { data->use_xrender = SDL_FALSE; } - XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i], + XRenderComposite(data->display, PictOpClear, + data->pixmap_picts[i], None, data->pixmap_picts[i], 0, 0, 0, 0, 0, 0, window->w, window->h); } #endif @@ -387,7 +390,8 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) if(!data->pixmap_picts[i]) { data->use_xrender = SDL_FALSE; } - XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i], + XRenderComposite(data->display, PictOpClear, + data->pixmap_picts[i], None, data->pixmap_picts[i], 0, 0, 0, 0, 0, 0, window->w, window->h); } #endif @@ -570,26 +574,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(renderdata->use_xrender && data->pixmap) { data->use_xrender = SDL_TRUE; - /*unsigned long x11_fmt_mask; // Format mask - XRenderPictFormat x11_templ_fmt; // Format template - x11_fmt_mask = - (PictFormatRedMask | PictFormatGreenMask - | PictFormatBlueMask | PictFormatAlphaMask); - Uint32 Rmask, Gmask, Bmask, Amask; - int bpp; - SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); - x11_templ_fmt.depth = bpp; - x11_templ_fmt.type = PictTypeDirect; - x11_templ_fmt.direct.red = Rmask / 0xff; - x11_templ_fmt.direct.green = Gmask / 0xff; - x11_templ_fmt.direct.blue = Bmask / 0xff; - x11_templ_fmt.direct.alpha = Amask / 0xff; - printf("%d %d %d %d\n", Rmask/0xff, Gmask/0xff, Bmask/0xff, Amask/0xff); - // Return a matching XRenderPictFormat data->picture_fmt = - XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 0);*/ - data->picture_fmt = - XRenderFindVisualFormat(renderdata->display, renderdata->visual); + XRenderFindVisualFormat(renderdata->display, renderdata->visual); if(!data->picture_fmt) { printf("XRenderFindFormat failed!\n"); data->use_xrender = SDL_FALSE; @@ -760,16 +746,14 @@ X11_SetDrawBlendMode(SDL_Renderer * renderer) data->blend_op = PictOpOver; return 0; /* FIXME case SDL_BLENDMODE_MOD: */ - default: // PictOpSrc - SDL_Unsupported(); - renderer->blendMode = SDL_BLENDMODE_NONE; - data->blend_op = PictOpSrc; - return -1; #endif return 0; default: SDL_Unsupported(); renderer->blendMode = SDL_BLENDMODE_NONE; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->blend_op = PictOpSrc; +#endif return -1; } } @@ -842,21 +826,31 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender == SDL_TRUE) { XRenderColor foreground; + XRenderPictureAttributes attributes; + unsigned long valuemask; foreground = xrenderdrawcolor(renderer); + /* Set the clip mask to restrict rendering to + * the primitive being drawn + */ + attributes.clip_mask = data->mask; + valuemask = CPClipMask; XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XDrawPoints(data->display, data->mask, data->mask_gc, xpoints, xcount, CoordModeOrigin); - + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &foreground); XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + // Reset the clip_mask + attributes.clip_mask = None; + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); XRenderFreePicture(data->display, fill); } else @@ -1029,9 +1023,15 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { XRenderColor xrforeground = xrenderdrawcolor(renderer); + XRenderPictureAttributes attributes; + attributes.clip_mask = data->mask; + unsigned long valuemask = CPClipMask; + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &xrforeground); XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + attributes.clip_mask = None; + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); XRenderFreePicture(data->display, fill); } #endif @@ -1074,15 +1074,23 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { XRenderColor foreground; + XRenderPictureAttributes attributes; + unsigned long valuemask; + foreground = xrenderdrawcolor(renderer); + valuemask = CPClipMask; + attributes.clip_mask = data->mask; XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XDrawRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &foreground); XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + attributes.clip_mask = None; + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); XRenderFreePicture(data->display, fill); } else @@ -1139,17 +1147,27 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { XRenderColor foreground; + XRenderPictureAttributes attributes; + unsigned long valuemask; foreground = xrenderdrawcolor(renderer); - + attributes.clip_mask = data->mask; + valuemask = CPClipMask; + attributes.clip_mask = data->mask; + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); XFillRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); + + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); + Picture fill = XRenderCreateSolidFill(data->display, &foreground); XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + attributes.clip_mask = None; + XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); XRenderFreePicture(data->display, fill); } else From 8446602801300d780c6b3c95fc381db0a37a041c Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Fri, 9 Jul 2010 21:36:41 +0530 Subject: [PATCH 21/47] Fix so many things that there is little place in this column to list them all but the result is that blending modes just work now for drawing primitives. Fixes involved: 1. Fix handling of alpha channel when SDL_BLENDMODE_NONE is set. 2. Make xrendercolor use floating-point values for color channels and then convert to 16 bit ints. 3. Fix handling of visuals in SDL_x11modes.c so that a 32 bit ARGB visual is used. 4. Fix the background pixel value in SDL_x11window.c so that the window background has an alpha value of 0xFF and not 0. --- src/video/x11/SDL_x11modes.c | 24 +++++-- src/video/x11/SDL_x11render.c | 119 +++++++++++++++++++--------------- src/video/x11/SDL_x11window.c | 3 + 3 files changed, 90 insertions(+), 56 deletions(-) diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 211bcb885..a4377fc19 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -23,7 +23,7 @@ #include "SDL_x11video.h" -//#define X11MODES_DEBUG +#define X11MODES_DEBUG #undef SDL_VIDEO_DRIVER_X11_XINERAMA #undef SDL_VIDEO_DRIVER_X11_XRANDR #undef SDL_VIDEO_DRIVER_X11_VIDMODE @@ -33,11 +33,12 @@ get_visualinfo(Display * display, int screen, XVisualInfo * vinfo) { const char *visual_id = SDL_getenv("SDL_VIDEO_X11_VISUALID"); int depth; + XVisualInfo *vi; + int nvis; /* Look for an exact visual, if requested */ if (visual_id) { - XVisualInfo *vi, template; - int nvis; + XVisualInfo template; SDL_zero(template); template.visualid = SDL_strtol(visual_id, NULL, 0); @@ -48,7 +49,22 @@ get_visualinfo(Display * display, int screen, XVisualInfo * vinfo) return 0; } } - +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + depth = 32; + long vinfo_mask; + XVisualInfo vinfo_templ; + vinfo_mask = (VisualDepthMask | VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask); + vinfo_templ.depth = 32; + vinfo_templ.red_mask = 0xFF0000; + vinfo_templ.green_mask = 0xFF00; + vinfo_templ.blue_mask = 0xFF; + vi = XGetVisualInfo(display, vinfo_mask, &vinfo_templ, &nvis); + if(vi) { + *vinfo = *vi; + XFree(vi); + return 0; + } +#endif depth = DefaultDepth(display, screen); if ((X11_UseDirectColorVisuals() && XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) || diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index fafe94809..24524dc8c 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -215,11 +215,37 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->depth = displaydata->depth; data->scanline_pad = displaydata->scanline_pad; data->xwindow = windowdata->xwindow; + + renderer->DisplayModeChanged = X11_DisplayModeChanged; + renderer->CreateTexture = X11_CreateTexture; + renderer->QueryTexturePixels = X11_QueryTexturePixels; + renderer->SetTextureBlendMode = X11_SetTextureBlendMode; + renderer->SetTextureScaleMode = X11_SetTextureScaleMode; + renderer->UpdateTexture = X11_UpdateTexture; + renderer->LockTexture = X11_LockTexture; + renderer->UnlockTexture = X11_UnlockTexture; + renderer->SetDrawBlendMode = X11_SetDrawBlendMode; + renderer->RenderDrawPoints = X11_RenderDrawPoints; + renderer->RenderDrawLines = X11_RenderDrawLines; + renderer->RenderDrawRects = X11_RenderDrawRects; + renderer->RenderFillRects = X11_RenderFillRects; + renderer->RenderCopy = X11_RenderCopy; + renderer->RenderReadPixels = X11_RenderReadPixels; + renderer->RenderWritePixels = X11_RenderWritePixels; + renderer->RenderPresent = X11_RenderPresent; + renderer->DestroyTexture = X11_DestroyTexture; + renderer->DestroyRenderer = X11_DestroyRenderer; + renderer->info = X11_RenderDriver.info; + renderer->window = window; + renderer->driverdata = data; + + renderer->info.flags = SDL_RENDERER_ACCELERATED; + #ifdef SDL_VIDEO_DRIVER_X11_XRENDER int event_basep, error_basep; if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { data->use_xrender = SDL_TRUE; - data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); + data->xwindow_pict_fmt = XRenderFindStandardFormat(data->display, PictStandardARGB32); if(!data->xwindow_pict_fmt) { data->use_xrender = SDL_FALSE; goto fallback; @@ -230,6 +256,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->use_xrender = SDL_FALSE; goto fallback; } + renderer->info.blend_modes |= + (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); // Create a 1 bit depth mask data->mask = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 1); @@ -241,37 +269,15 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) gcv_mask.foreground = 1; gcv_mask.background = 0; data->mask_gc = XCreateGC(data->display, data->mask, GCBackground | GCForeground, &gcv_mask); + renderer->blendMode = SDL_BLENDMODE_BLEND; + data->blend_op = PictOpOver; } else { data->use_xrender = SDL_FALSE; } fallback: #endif - renderer->DisplayModeChanged = X11_DisplayModeChanged; - renderer->CreateTexture = X11_CreateTexture; - renderer->QueryTexturePixels = X11_QueryTexturePixels; - renderer->SetTextureBlendMode = X11_SetTextureBlendMode; - renderer->SetTextureScaleMode = X11_SetTextureScaleMode; - renderer->UpdateTexture = X11_UpdateTexture; - renderer->LockTexture = X11_LockTexture; - renderer->UnlockTexture = X11_UnlockTexture; - renderer->SetDrawBlendMode = X11_SetDrawBlendMode; - renderer->RenderDrawPoints = X11_RenderDrawPoints; - renderer->RenderDrawLines = X11_RenderDrawLines; - renderer->RenderDrawRects = X11_RenderDrawRects; - renderer->RenderFillRects = X11_RenderFillRects; - renderer->RenderCopy = X11_RenderCopy; - renderer->RenderReadPixels = X11_RenderReadPixels; - renderer->RenderWritePixels = X11_RenderWritePixels; - renderer->RenderPresent = X11_RenderPresent; - renderer->DestroyTexture = X11_DestroyTexture; - renderer->DestroyRenderer = X11_DestroyRenderer; - renderer->info = X11_RenderDriver.info; - renderer->window = window; - renderer->driverdata = data; - - renderer->info.flags = SDL_RENDERER_ACCELERATED; - + if (flags & SDL_RENDERER_SINGLEBUFFER) { renderer->info.flags |= (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY); @@ -734,26 +740,30 @@ X11_SetDrawBlendMode(SDL_Renderer * renderer) switch (renderer->blendMode) { case SDL_BLENDMODE_NONE: #ifdef SDL_VIDEO_DRIVER_X11_XRENDER + //PictOpSrc data->blend_op = PictOpSrc; return 0; - case SDL_BLENDMODE_MASK: // Use src pict as mask - data->blend_op = PictOpSrc; + case SDL_BLENDMODE_BLEND: // PictOpOver + data->blend_op = PictOpOver; return 0; case SDL_BLENDMODE_ADD: // PictOpAdd data->blend_op = PictOpAdd; return 0; - case SDL_BLENDMODE_BLEND: // PictOpOver - data->blend_op = PictOpOver; - return 0; /* FIXME case SDL_BLENDMODE_MOD: */ #endif return 0; default: SDL_Unsupported(); - renderer->blendMode = SDL_BLENDMODE_NONE; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->blend_op = PictOpSrc; + if(data->use_xrender) { + renderer->blendMode = SDL_BLENDMODE_BLEND; + data->blend_op = PictOpOver; + } + else #endif + { + renderer->blendMode = SDL_BLENDMODE_NONE; + } return -1; } } @@ -779,10 +789,20 @@ xrenderdrawcolor(SDL_Renderer *renderer) { // Premultiply the color channels as well as modulate them to a 16 bit color space XRenderColor xrender_color; - xrender_color.red = ((unsigned short)renderer->r + 1) * ((unsigned short)renderer->a + 1) - 1; - xrender_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1; - xrender_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1; - xrender_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1; + double alphad; + if(renderer->blendMode == SDL_BLENDMODE_NONE) + alphad = 1.0; + else + alphad = (renderer->a) / 255.0; + + xrender_color.alpha = (unsigned short) (alphad * 0xFFFF); + + xrender_color.red = + (unsigned short) ((renderer->r / 255.0) * alphad * 0xFFFF); + xrender_color.green = + (unsigned short) ((renderer->g / 255.0) * alphad * 0xFFFF); + xrender_color.blue = + (unsigned short) ((renderer->b / 255.0) * alphad * 0xFFFF); return xrender_color; } @@ -1050,6 +1070,12 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XRectangle *xrects, *xrect; xrect = xrects = SDL_stack_alloc(XRectangle, count); xcount = 0; + + clip.x = 0; + clip.y = 0; + clip.w = window->w; + clip.h = window->h; + for (i = 0; i < count; ++i) { if (!SDL_IntersectRect(rects[i], &clip, &rect)) { continue; @@ -1066,11 +1092,7 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) SDL_AddDirtyRect(&data->dirty, &rect); } } - clip.x = 0; - clip.y = 0; - clip.w = window->w; - clip.h = window->h; - + #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { XRenderColor foreground; @@ -1151,7 +1173,6 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) unsigned long valuemask; foreground = xrenderdrawcolor(renderer); - attributes.clip_mask = data->mask; valuemask = CPClipMask; attributes.clip_mask = data->mask; @@ -1424,15 +1445,9 @@ X11_RenderPresent(SDL_Renderer * renderer) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { - if(renderer->blendMode == SDL_BLENDMODE_MASK) - XRenderComposite(data->display, data->blend_op, data->drawable_pict, - data->drawable_pict, data->xwindow_pict, rect->x, rect->y, - 0, 0, rect->x, rect->y, rect->w, rect->h); - else - 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); - + XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, + data->xwindow_pict, rect->x, rect->y, 0, 0, rect->x, rect->y, + rect->w+1, rect->h+1); } else #endif diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 18c0e478e..1edcb7122 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -513,6 +513,9 @@ X11_CreateWindow(_THIS, SDL_Window * window) } else { y = window->y; } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + xattr.background_pixel = 0xFF000000; +#endif w = XCreateWindow(data->display, RootWindow(data->display, displaydata->screen), x, y, From 859ed033d467f5e496605ff08db3c4a618ed8f55 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 14 Jul 2010 19:17:11 +0530 Subject: [PATCH 22/47] Implement blending modes for textures. Fix off-screen pixmaps to be ARGB rather than RGB to enable blending across frames. Clear the screen and off-screen pixmaps when the renderer is created. --- src/video/x11/SDL_x11modes.c | 4 +- src/video/x11/SDL_x11render.c | 208 +++++++++++++++++++++------------- src/video/x11/SDL_x11window.c | 7 +- 3 files changed, 138 insertions(+), 81 deletions(-) diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index a4377fc19..7498c79ef 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -49,7 +49,7 @@ get_visualinfo(Display * display, int screen, XVisualInfo * vinfo) return 0; } } -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +/*#ifdef SDL_VIDEO_DRIVER_X11_XRENDER depth = 32; long vinfo_mask; XVisualInfo vinfo_templ; @@ -64,7 +64,7 @@ get_visualinfo(Display * display, int screen, XVisualInfo * vinfo) XFree(vi); return 0; } -#endif +#endif*/ depth = DefaultDepth(display, screen); if ((X11_UseDirectColorVisuals() && XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) || diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 24524dc8c..5824052be 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -123,7 +123,8 @@ typedef struct #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture picture; XRenderPictFormat* picture_fmt; - SDL_bool use_xrender; + int blend_op; +// SDL_bool use_xrender; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -243,39 +244,46 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER int event_basep, error_basep; - if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { + if(XRenderQueryExtension(data->display, + &event_basep, + &error_basep) == True) { data->use_xrender = SDL_TRUE; - data->xwindow_pict_fmt = XRenderFindStandardFormat(data->display, PictStandardARGB32); - if(!data->xwindow_pict_fmt) { - data->use_xrender = SDL_FALSE; - goto fallback; - } - data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, + data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, + data->visual); + data->xwindow_pict = XRenderCreatePicture(data->display, + data->xwindow, + data->xwindow_pict_fmt, 0, NULL); - if(!data->xwindow_pict) { - data->use_xrender = SDL_FALSE; - goto fallback; - } + XRenderComposite(data->display, + PictOpClear, + data->xwindow_pict, + None, + data->xwindow_pict, + 0, 0, + 0, 0, + 0, 0, + window->w, window->h); renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); // Create a 1 bit depth mask data->mask = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 1); - data->mask_pict = XRenderCreatePicture(data->display, data->mask, - XRenderFindStandardFormat(data->display, - PictStandardA1), - 0, NULL); + data->mask_pict = + XRenderCreatePicture(data->display, data->mask, + XRenderFindStandardFormat(data->display, + PictStandardA1), + 0, NULL); XGCValues gcv_mask; gcv_mask.foreground = 1; gcv_mask.background = 0; - data->mask_gc = XCreateGC(data->display, data->mask, GCBackground | GCForeground, &gcv_mask); + data->mask_gc = XCreateGC(data->display, data->mask, + GCBackground | GCForeground, &gcv_mask); renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; } else { data->use_xrender = SDL_FALSE; } - fallback: #endif if (flags & SDL_RENDERER_SINGLEBUFFER) { @@ -293,9 +301,21 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) n = 1; } 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"); @@ -304,14 +324,21 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { data->pixmap_picts[i] = - XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, + XRenderCreatePicture(data->display, + data->pixmaps[i], + XRenderFindStandardFormat(data->display, + PictStandardARGB32), 0, None); - if(!data->pixmap_picts[i]) { - data->use_xrender = SDL_FALSE; - } - XRenderComposite(data->display, PictOpClear, - data->pixmap_picts[i], None, data->pixmap_picts[i], - 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderComposite(data->display, + PictOpClear, + data->pixmap_picts[i], + None, + data->pixmap_picts[i], + 0, 0, + 0, 0, + 0, 0, + window->w, window->h); + } #endif } @@ -381,9 +408,22 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) } } 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; @@ -391,15 +431,22 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { data->pixmap_picts[i] = - XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, + XRenderCreatePicture(data->display, + data->pixmaps[i], + XRenderFindStandardFormat(data->display, + PictStandardARGB32), 0, None); - if(!data->pixmap_picts[i]) { - data->use_xrender = SDL_FALSE; - } - XRenderComposite(data->display, PictOpClear, - data->pixmap_picts[i], None, data->pixmap_picts[i], - 0, 0, 0, 0, 0, 0, window->w, window->h); - } + 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) { @@ -442,8 +489,6 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) can be no BadMatch error since Xrender takes care of that. */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - // Assume the texture is supported by Xrender - data->use_xrender = SDL_TRUE; if (renderdata->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); @@ -578,32 +623,22 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(renderdata->use_xrender && data->pixmap) { - data->use_xrender = SDL_TRUE; - data->picture_fmt = - XRenderFindVisualFormat(renderdata->display, renderdata->visual); - if(!data->picture_fmt) { - printf("XRenderFindFormat failed!\n"); - data->use_xrender = SDL_FALSE; - } + if(renderdata->use_xrender) { + data->picture_fmt = renderdata->xwindow_pict_fmt; data->picture = XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, 0, NULL); - if(!data->picture) { - data->use_xrender = SDL_FALSE; - } } /* We thought we could render the texture with Xrender but this was not possible for some reason. Now we must ensure that texture format and window format match to avoid a BadMatch error when rendering using the old pipeline. - */ if(data->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; } - } + }*/ #endif return 0; } @@ -626,12 +661,26 @@ X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, static int X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) { + X11_TextureData *data = (X11_TextureData *) texture->driverdata; switch (texture->blendMode) { case SDL_BLENDMODE_NONE: +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->blend_op = PictOpSrc; + return 0; + case SDL_BLENDMODE_BLEND: + data->blend_op = PictOpOver; + return 0; + case SDL_BLENDMODE_ADD: + data->blend_op = PictOpAdd; return 0; +#endif default: SDL_Unsupported(); texture->blendMode = SDL_BLENDMODE_NONE; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + texture->blendMode = SDL_BLENDMODE_BLEND; + data->blend_op = PictOpOver; +#endif return -1; } } @@ -795,7 +844,7 @@ xrenderdrawcolor(SDL_Renderer *renderer) else alphad = (renderer->a) / 255.0; - xrender_color.alpha = (unsigned short) (alphad * 0xFFFF); + xrender_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); xrender_color.red = (unsigned short) ((renderer->r / 255.0) * alphad * 0xFFFF); @@ -1170,10 +1219,8 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) if(data->use_xrender == SDL_TRUE) { XRenderColor foreground; XRenderPictureAttributes attributes; - unsigned long valuemask; foreground = xrenderdrawcolor(renderer); - valuemask = CPClipMask; attributes.clip_mask = data->mask; XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, @@ -1181,15 +1228,14 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XFillRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - - Picture fill = - XRenderCreateSolidFill(data->display, &foreground); - XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, + XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); + Picture fill_pict = XRenderCreateSolidFill(data->display, + &foreground); + XRenderComposite(data->display, data->blend_op, fill_pict, None, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - XRenderFreePicture(data->display, fill); + XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); + XRenderFreePicture(data->display, fill_pict); } else #endif @@ -1219,7 +1265,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, SDL_AddDirtyRect(&data->dirty, dstrect); } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_xrender && texturedata->use_xrender) { + if (data->use_xrender) { if(texture->access == SDL_TEXTUREACCESS_STREAMING) { #ifndef NO_SHARED_MEMORY if(texturedata->shminfo.shmaddr) { @@ -1236,9 +1282,16 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, dstrect->y, srcrect->w, srcrect->h); } } + Picture pict; + if(texture->blendMode == SDL_BLENDMODE_NONE) + pict = None; + else + pict = texturedata->picture; if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) { - XRenderComposite(data->display, PictOpOver, texturedata->picture, None, data->drawable_pict, - srcrect->x, srcrect->y, 0, 0, dstrect->x, dstrect->y, srcrect->w, srcrect->h); + XRenderComposite(data->display, texturedata->blend_op, texturedata->picture, + pict, data->drawable_pict, srcrect->x, srcrect->y, + srcrect->x, srcrect->y, dstrect->x, dstrect->y, + srcrect->w, srcrect->h); } else { Pixmap scaling_pixmap = XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h, @@ -1248,7 +1301,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 0, NULL); XRenderComposite(data->display, PictOpClear, scaling_picture, None, scaling_picture, 0, 0, 0, 0, 0, 0, dstrect->w, dstrect->h); - XRenderComposite(data->display, PictOpSrc, texturedata->picture, None, scaling_picture, + XRenderComposite(data->display, PictOpSrc, texturedata->picture, pict, scaling_picture, srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h); double xscale = ((double) dstrect->w) / srcrect->w; double yscale = ((double) dstrect->h) / srcrect->h; @@ -1257,7 +1310,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}}; XRenderSetPictureTransform(data->display, scaling_picture, &xform); - XRenderComposite(data->display, PictOpOver, scaling_picture, None, data->drawable_pict, + XRenderComposite(data->display, texturedata->blend_op, scaling_picture, None, data->drawable_pict, 0, 0, 0, 0, dstrect->x, dstrect->y, dstrect->w, dstrect->h); XRenderFreePicture(data->display, scaling_picture); XFreePixmap(data->display, scaling_pixmap); @@ -1445,9 +1498,15 @@ X11_RenderPresent(SDL_Renderer * renderer) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { - XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, - data->xwindow_pict, rect->x, rect->y, 0, 0, rect->x, rect->y, - rect->w+1, rect->h+1); + 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 @@ -1536,12 +1595,9 @@ X11_DestroyRenderer(SDL_Renderer * renderer) if (data->gc) { XFreeGC(data->display, data->gc); } - if (data->drawable) { - XFreePixmap(data->display, data->drawable); - } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->mask_gc) { - XFreeGC(data->display, data->gc); + XFreeGC(data->display, data->mask_gc); } if (data->mask_pict) { XRenderFreePicture(data->display, data->mask_pict); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 1edcb7122..87a6e8e98 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -513,9 +513,6 @@ X11_CreateWindow(_THIS, SDL_Window * window) } else { y = window->y; } -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - xattr.background_pixel = 0xFF000000; -#endif w = XCreateWindow(data->display, RootWindow(data->display, displaydata->screen), x, y, @@ -526,6 +523,10 @@ X11_CreateWindow(_THIS, SDL_Window * window) SDL_SetError("Couldn't create window"); return -1; } +/*#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + //XSetWindowBackground(data->display, w, 0xFF000000); + //XSetWindowBackgroundPixmap(data->display, w, ParentRelative); +#endif*/ #if SDL_VIDEO_DRIVER_PANDORA /* Create the GLES window surface */ _this->gles_data->egl_surface = From d20f4fceb783b4e5d98c7e3f8045877042d4b072 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sat, 17 Jul 2010 11:41:43 +0530 Subject: [PATCH 23/47] Add necessary symbols to SDL_x11sym.h --- src/video/x11/SDL_x11sym.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index d01503eec..6b5285f92 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -238,10 +238,14 @@ SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),r 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(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(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(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) #endif /* *INDENT-ON* */ From d5430ff31320fb4f4d6da79b94469d98438ee3cf Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sat, 17 Jul 2010 15:38:24 +0530 Subject: [PATCH 24/47] Fixed so many things. See the changelog listed below. 1. Use SDL_X11_HAVE_XRENDER to check for RENDER at runtime. 2. Added lots of comments. 3. Added checks and lots of calls to SDL_SetError(). 4. Fixed X11_CreateTexture() so that the pixmap and image created are for the format specified by the user and not the window format. This is only for the RENDER case. 5. The above change required that functions to convert SDL pixel format enums to Visuals and XRenderPictFormats be added. 6. Fixed lots of 'style' issues. --- src/video/x11/SDL_x11modes.c | 18 +-- src/video/x11/SDL_x11render.c | 282 +++++++++++++++++++++++++++------- 2 files changed, 226 insertions(+), 74 deletions(-) diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 7498c79ef..8b99018d7 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -23,7 +23,7 @@ #include "SDL_x11video.h" -#define X11MODES_DEBUG +//#define X11MODES_DEBUG #undef SDL_VIDEO_DRIVER_X11_XINERAMA #undef SDL_VIDEO_DRIVER_X11_XRANDR #undef SDL_VIDEO_DRIVER_X11_VIDMODE @@ -49,22 +49,6 @@ get_visualinfo(Display * display, int screen, XVisualInfo * vinfo) return 0; } } -/*#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - depth = 32; - long vinfo_mask; - XVisualInfo vinfo_templ; - vinfo_mask = (VisualDepthMask | VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask); - vinfo_templ.depth = 32; - vinfo_templ.red_mask = 0xFF0000; - vinfo_templ.green_mask = 0xFF00; - vinfo_templ.blue_mask = 0xFF; - vi = XGetVisualInfo(display, vinfo_mask, &vinfo_templ, &nvis); - if(vi) { - *vinfo = *vi; - XFree(vi); - return 0; - } -#endif*/ depth = DefaultDepth(display, screen); if ((X11_UseDirectColorVisuals() && XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) || diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 5824052be..35dc620b6 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -120,6 +120,9 @@ typedef struct SDL_SW_YUVTexture *yuv; Uint32 format; Pixmap pixmap; + int depth; + Visual *visual; + GC gc; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture picture; XRenderPictFormat* picture_fmt; @@ -243,17 +246,32 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->info.flags = SDL_RENDERER_ACCELERATED; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - int event_basep, error_basep; - if(XRenderQueryExtension(data->display, - &event_basep, - &error_basep) == True) { - data->use_xrender = SDL_TRUE; + data->use_xrender = SDL_FALSE; + if (SDL_X11_HAVE_XRENDER) { + // Query the extension. This is the server runtime check. + int event_basep, error_basep; + if(XRenderQueryExtension(data->display, + &event_basep, &error_basep) == True) + data->use_xrender = SDL_TRUE; + } + 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, @@ -263,27 +281,39 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) 0, 0, 0, 0, window->w, window->h); + // Add some blending modes to the list of supported blending modes renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); - // Create a 1 bit depth mask + // Create a clip mask that is used for rendering primitives. data->mask = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 1); + if (!data->mask) { + SDL_SetError("XCreatePixmap() failed"); + return NULL; + } data->mask_pict = XRenderCreatePicture(data->display, data->mask, XRenderFindStandardFormat(data->display, PictStandardA1), 0, NULL); + if (!data->mask_pict) { + SDL_SetError("XRenderCreatePicture() failed"); + return NULL; + } + // Create the GC for the clip mask. XGCValues gcv_mask; gcv_mask.foreground = 1; gcv_mask.background = 0; data->mask_gc = XCreateGC(data->display, data->mask, GCBackground | GCForeground, &gcv_mask); + if (!data->mask_gc) { + SDL_SetError("XCreateGC() failed"); + return NULL; + } + // Set the default blending mode. renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; } - else { - data->use_xrender = SDL_FALSE; - } #endif if (flags & SDL_RENDERER_SINGLEBUFFER) { @@ -322,23 +352,29 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { + 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); - XRenderComposite(data->display, - PictOpClear, - data->pixmap_picts[i], - None, - data->pixmap_picts[i], - 0, 0, - 0, 0, - 0, 0, - window->w, window->h); + 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 } @@ -429,13 +465,17 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) return -1; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { + 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], @@ -460,6 +500,84 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) return 0; } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +static void +SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) { + (*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; + SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + + 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; +} +#endif + static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -468,12 +586,16 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_VideoDisplay *display = window->display; X11_TextureData *data; int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); - + XGCValues gcv; + data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } + data->depth = renderdata->depth; + data->visual = renderdata->visual; + data->gc = renderdata->gc; texture->driverdata = data; if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { @@ -494,6 +616,11 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_SetError("Texture format doesn't match window format"); return -1; } + } else { + Uint32 Amask, Rmask, Gmask, Bmask; + SDL_PixelFormatEnumToMasks(texture->format, &(data->depth), + &Rmask, &Gmask, &Bmask, &Amask); + data->visual = PixelFormatEnumToVisual(renderer, texture->format); } #else /* The image/pixmap depth must be the same as the window or you @@ -540,16 +667,15 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) data->pixels = shminfo->shmaddr; 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 = - XShmCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, shminfo->shmaddr, + XShmCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); if (!data->image) { @@ -582,15 +708,15 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 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, data->pixels, + XCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, 0, data->pixels, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); @@ -604,15 +730,15 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) else { data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, - texture->h, renderdata->depth); + texture->h, data->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreatePixmap() failed"); return -1; } data->image = - XCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, 0, NULL, + XCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, 0, NULL, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); @@ -624,21 +750,29 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(renderdata->use_xrender) { - data->picture_fmt = renderdata->xwindow_pict_fmt; + 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("Texture format not supported by driver"); + return -1; + } data->picture = XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, 0, NULL); - } - /* We thought we could render the texture with Xrender but this was - not possible for some reason. Now we must ensure that texture - format and window format match to avoid a BadMatch error when - rendering using the old pipeline. - if(data->use_xrender == SDL_FALSE) { - if (texture->format != display->current_mode.format) { - SDL_SetError("Texture format doesn't match window format"); + if (!data->picture) { + X11_DestroyTexture(renderer, texture); + SDL_SetError("XRenderCreatePicture() failed"); return -1; } - }*/ + } #endif return 0; } @@ -742,7 +876,7 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, data->image->height = rect->h; data->image->data = (char *) pixels; data->image->bytes_per_line = pitch; - XPutImage(renderdata->display, data->pixmap, renderdata->gc, + XPutImage(renderdata->display, data->pixmap, data->gc, data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); } return 0; @@ -913,6 +1047,10 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &foreground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); @@ -1097,6 +1235,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, unsigned long valuemask = CPClipMask; XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &xrforeground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; @@ -1158,6 +1300,10 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &foreground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; @@ -1229,13 +1375,17 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) xrects, xcount); XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - Picture fill_pict = XRenderCreateSolidFill(data->display, - &foreground); - XRenderComposite(data->display, data->blend_op, fill_pict, None, + Picture fill = XRenderCreateSolidFill(data->display, + &foreground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } + XRenderComposite(data->display, data->blend_op, fill, None, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - XRenderFreePicture(data->display, fill_pict); + XRenderFreePicture(data->display, fill); } else #endif @@ -1293,27 +1443,45 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w, srcrect->h); } else { - Pixmap scaling_pixmap = + /*Pixmap scaling_pixmap = XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h, data->depth); + if (!scaling_pixmap) { + SDL_SetError("XCreatePixmap() failed"); + return -1; + } Picture scaling_picture = XRenderCreatePicture(data->display, scaling_pixmap, texturedata->picture_fmt, 0, NULL); + if (!scaling_picture) { + SDL_SetError("XRenderCreatePicture() failed"); + return -1; + } XRenderComposite(data->display, PictOpClear, scaling_picture, None, scaling_picture, 0, 0, 0, 0, 0, 0, dstrect->w, dstrect->h); XRenderComposite(data->display, PictOpSrc, texturedata->picture, pict, scaling_picture, - srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h); + srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h);*/ 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, scaling_picture, &xform); - XRenderComposite(data->display, texturedata->blend_op, scaling_picture, None, data->drawable_pict, - 0, 0, 0, 0, dstrect->x, dstrect->y, dstrect->w, dstrect->h); - XRenderFreePicture(data->display, scaling_picture); - XFreePixmap(data->display, scaling_pixmap); + XTransform xform = {{ + {XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)}, + {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)}, + {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}}; + XRenderSetPictureTransform(data->display, texturedata->picture, &xform); + + XRenderComposite(data->display, texturedata->blend_op, + texturedata->picture, None, data->drawable_pict, + 0, 0, 0, 0, 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, texturedata->picture, &identity); + + /*XRenderFreePicture(data->display, scaling_picture); + XFreePixmap(data->display, scaling_pixmap);*/ } } else From 24c126f9be9e87fdbce823ea46499011863d48d2 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sat, 17 Jul 2010 15:41:34 +0530 Subject: [PATCH 25/47] Remove some redundant code. --- src/video/x11/SDL_x11render.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 35dc620b6..f558d7ba0 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1443,24 +1443,6 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w, srcrect->h); } else { - /*Pixmap scaling_pixmap = - XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h, - data->depth); - if (!scaling_pixmap) { - SDL_SetError("XCreatePixmap() failed"); - return -1; - } - Picture scaling_picture = - XRenderCreatePicture(data->display, scaling_pixmap, texturedata->picture_fmt, - 0, NULL); - if (!scaling_picture) { - SDL_SetError("XRenderCreatePicture() failed"); - return -1; - } - XRenderComposite(data->display, PictOpClear, scaling_picture, None, scaling_picture, - 0, 0, 0, 0, 0, 0, dstrect->w, dstrect->h); - XRenderComposite(data->display, PictOpSrc, texturedata->picture, pict, scaling_picture, - srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h);*/ double xscale = ((double) dstrect->w) / srcrect->w; double yscale = ((double) dstrect->h) / srcrect->h; XTransform xform = {{ @@ -1479,9 +1461,6 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}}; XRenderSetPictureTransform(data->display, texturedata->picture, &identity); - - /*XRenderFreePicture(data->display, scaling_picture); - XFreePixmap(data->display, scaling_pixmap);*/ } } else From 82b825258792968a3ff9644b573783b828b6d694 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sat, 17 Jul 2010 15:53:29 +0530 Subject: [PATCH 26/47] Fixed a minor bug with texture blending. --- src/video/x11/SDL_x11render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index f558d7ba0..ef73f0fa0 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1452,7 +1452,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, XRenderSetPictureTransform(data->display, texturedata->picture, &xform); XRenderComposite(data->display, texturedata->blend_op, - texturedata->picture, None, data->drawable_pict, + texturedata->picture, pict, data->drawable_pict, 0, 0, 0, 0, dstrect->x, dstrect->y, dstrect->w, dstrect->h); From 21fd4f16b82296771f871d25426ccf7486f9a1e1 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 18 Jul 2010 08:28:35 +0530 Subject: [PATCH 27/47] Got testsprite2 to work reasonably. --- src/video/x11/SDL_x11render.c | 106 ++++++++++++++-------------------- src/video/x11/SDL_x11sym.h | 3 + test/testsprite2.c | 2 +- 3 files changed, 47 insertions(+), 64 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index ef73f0fa0..9ab698442 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -101,7 +101,6 @@ typedef struct Picture xwindow_pict; Picture pixmap_picts[3]; Picture drawable_pict; - Picture mask_pict; int blend_op; XRenderPictFormat* xwindow_pict_fmt; GC mask_gc; @@ -182,6 +181,7 @@ X11_AddRenderDriver(_THIS) info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2; 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_ARGB8888; for (i = 0; i < _this->num_displays; ++i) { SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver); @@ -197,6 +197,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_Renderer *renderer; X11_RenderData *data; XGCValues gcv; + gcv.graphics_exposures = False; int i, n; int bpp; Uint32 Rmask, Gmask, Bmask, Amask; @@ -291,25 +292,15 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_SetError("XCreatePixmap() failed"); return NULL; } - data->mask_pict = - XRenderCreatePicture(data->display, data->mask, - XRenderFindStandardFormat(data->display, - PictStandardA1), - 0, NULL); - if (!data->mask_pict) { - SDL_SetError("XRenderCreatePicture() failed"); - return NULL; - } // Create the GC for the clip mask. - XGCValues gcv_mask; - gcv_mask.foreground = 1; - gcv_mask.background = 0; data->mask_gc = XCreateGC(data->display, data->mask, - GCBackground | GCForeground, &gcv_mask); + GCGraphicsExposures, &gcv); if (!data->mask_gc) { SDL_SetError("XCreateGC() failed"); return NULL; } + XSetBackground(data->display, data->mask_gc, 0); + XSetForeground(data->display, data->mask_gc, 1); // Set the default blending mode. renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; @@ -425,6 +416,16 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) SDL_Window *window = renderer->window; int i, n; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + XRenderFreePicture(data->display, data->xwindow_pict); + data->xwindow_pict_fmt = + XRenderFindVisualFormat(data->display, data->visual); + data->xwindow_pict = + XRenderCreatePicture(data->display, data->xwindow, + data->xwindow_pict_fmt, 0, NULL); + } +#endif if (renderer->info.flags & SDL_RENDERER_SINGLEBUFFER) { n = 0; } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { @@ -439,6 +440,7 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) 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 } @@ -1038,27 +1040,20 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, */ attributes.clip_mask = data->mask; valuemask = CPClipMask; - - XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + + XSetForeground(data->display, data->mask_gc, 0); + XFillRectangle(data->display, data->mask, data->mask_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 1); XDrawPoints(data->display, data->mask, data->mask_gc, xpoints, xcount, CoordModeOrigin); XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - Picture fill = - XRenderCreateSolidFill(data->display, &foreground); - if (!fill) { - SDL_SetError("XRenderCreateSolidFill() failed"); - return -1; - } - - XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, - data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); - + /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, + &foreground, 0, 0, window->w, window->h);*/ // Reset the clip_mask attributes.clip_mask = None; XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - XRenderFreePicture(data->display, fill); } else #endif @@ -1101,8 +1096,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, if (data->use_xrender == SDL_TRUE) { drawable = data->mask; gc = data->mask_gc; - XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 0); + XFillRectangle(data->display, data->mask, data->mask_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 1); } else #endif @@ -1234,16 +1231,10 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, attributes.clip_mask = data->mask; unsigned long valuemask = CPClipMask; XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - Picture fill = XRenderCreateSolidFill(data->display, &xrforeground); - if (!fill) { - SDL_SetError("XRenderCreateSolidFill() failed"); - return -1; - } - XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, - data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, + &xrforeground, 0, 0, window->w, window->h);*/ attributes.clip_mask = None; XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - XRenderFreePicture(data->display, fill); } #endif SDL_stack_free(xpoints); @@ -1294,21 +1285,17 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) valuemask = CPClipMask; attributes.clip_mask = data->mask; - XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 0); + XFillRectangle(data->display, data->mask, data->mask_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 1); + XDrawRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - Picture fill = - XRenderCreateSolidFill(data->display, &foreground); - if (!fill) { - SDL_SetError("XRenderCreateSolidFill() failed"); - return -1; - } - XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, - data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, + &foreground, 0, 0, window->w, window->h);*/ attributes.clip_mask = None; XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - XRenderFreePicture(data->display, fill); } else #endif @@ -1369,23 +1356,19 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) foreground = xrenderdrawcolor(renderer); attributes.clip_mask = data->mask; - XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, - 0, 0, 0, 0, 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 0); + XFillRectangle(data->display, data->mask, data->mask_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->mask_gc, 1); + XFillRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - Picture fill = XRenderCreateSolidFill(data->display, - &foreground); - if (!fill) { - SDL_SetError("XRenderCreateSolidFill() failed"); - return -1; - } - XRenderComposite(data->display, data->blend_op, fill, None, - data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); + /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, + &foreground, 0, 0, window->w, window->h);*/ attributes.clip_mask = None; XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - XRenderFreePicture(data->display, fill); } else #endif @@ -1746,9 +1729,6 @@ X11_DestroyRenderer(SDL_Renderer * renderer) if (data->mask_gc) { XFreeGC(data->display, data->mask_gc); } - if (data->mask_pict) { - XRenderFreePicture(data->display, data->mask_pict); - } if (data->mask) { XFreePixmap(data->display, data->mask); } diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 6b5285f92..235830c73 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -151,6 +151,8 @@ SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),r SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return) SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return) SDL_X11_SYM(XExtensionErrorHandler,XSetExtensionErrorHandler,(XExtensionErrorHandler a),(a),return) +SDL_X11_SYM(int,XFillRectangle,(Display *dpy,Drawable d,GC gc,int x,int y,unsigned int width,unsigned int height),(dpy,d,gc,x,y,width,height),return) +SDL_X11_SYM(int,XSetBackground,(Display *dpy,GC gc,unsigned long background),(dpy,gc,background),return) #if NeedWidePrototypes SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return) @@ -246,6 +248,7 @@ SDL_X11_SYM(void,XRenderChangePicture,(Display *dpy,Picture picture,unsigned lon 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) #endif /* *INDENT-ON* */ diff --git a/test/testsprite2.c b/test/testsprite2.c index 10c201fe4..6c866d12f 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -20,7 +20,7 @@ static int current_color = 0; static SDL_Rect *positions; static SDL_Rect *velocities; static int sprite_w, sprite_h; -static SDL_BlendMode blendMode = SDL_BLENDMODE_MASK; +static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND; static SDL_TextureScaleMode scaleMode = SDL_TEXTURESCALEMODE_NONE; /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ From f4064da52e7a60a0ede2e33d78ec5a9bed924a98 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 18 Jul 2010 12:43:04 +0530 Subject: [PATCH 28/47] Start experimental branch for client-side rasterization. --- src/SDL_error.c | 2 + src/video/x11/SDL_x11render.c | 569 +++++++++++++++++++--------------- src/video/x11/SDL_x11sym.h | 2 + 3 files changed, 328 insertions(+), 245 deletions(-) diff --git a/src/SDL_error.c b/src/SDL_error.c index 894409d86..dfb583f1f 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -38,6 +38,8 @@ extern SDL_error *SDL_GetErrBuf(void); #define SDL_ERRBUFIZE 1024 +#define DEBUG_ERROR + /* Private functions */ static const char * diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 9ab698442..01770720d 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -30,6 +30,7 @@ #include "../SDL_rect_c.h" #include "../SDL_pixels_c.h" #include "../SDL_yuv_sw_c.h" +#include "SDL_surface.h" /* X11 renderer implementation */ @@ -97,13 +98,21 @@ typedef struct Window xwindow; Pixmap pixmaps[3]; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - Pixmap mask; + Pixmap stencil; + Pixmap brush; + Picture brush_pict; +#ifndef NO_SHARED_MEMORY + XImage *stencil_image; + SDL_Surface *stencil_surface; + XShmSegmentInfo stencil_shminfo; +#endif Picture xwindow_pict; Picture pixmap_picts[3]; Picture drawable_pict; + Picture stencil_pict; int blend_op; XRenderPictFormat* xwindow_pict_fmt; - GC mask_gc; + GC stencil_gc; SDL_bool use_xrender; #endif int current_pixmap; @@ -286,21 +295,74 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); // Create a clip mask that is used for rendering primitives. - data->mask = XCreatePixmap(data->display, data->xwindow, - window->w, window->h, 1); - if (!data->mask) { - SDL_SetError("XCreatePixmap() failed"); - return NULL; - } + data->stencil = XCreatePixmap(data->display, data->xwindow, + window->w, window->h, 8); + // Create the GC for the clip mask. - data->mask_gc = XCreateGC(data->display, data->mask, + data->stencil_gc = XCreateGC(data->display, data->stencil, GCGraphicsExposures, &gcv); - if (!data->mask_gc) { - SDL_SetError("XCreateGC() failed"); - return NULL; + XSetBackground(data->display, data->stencil_gc, 0x00); + XSetForeground(data->display, data->stencil_gc, 0xFF); + data->stencil_pict = + XRenderCreatePicture(data->display, data->stencil, + XRenderFindStandardFormat(data->display, + PictStandardA8), + 0, NULL); + 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); +#ifndef NO_SHARED_MEMORY + /* Create a mask image using MIT-SHM */ + data->stencil_image = NULL; + data->stencil_surface = NULL; + XShmSegmentInfo *shminfo = &data->stencil_shminfo; + while (SDL_X11_HAVE_SHM) { + data->stencil_image = + XShmCreateImage(data->display, data->visual, 8, ZPixmap, + NULL, shminfo, window->w, window->h); + if (!data->stencil_image) { + printf("XShmCreateImage() failed"); + break; + } else { + printf("image created\n"); + } + shminfo->shmid = shmget(IPC_PRIVATE, + data->stencil_image->bytes_per_line * + data->stencil_image->height, + IPC_CREAT|0777); + if (!shminfo->shmid) { + printf("shmget() failed"); + break; + } else { + printf("shmid aquired\n"); + } + shminfo->shmaddr = data->stencil_image->data = shmat(shminfo->shmid, 0, 0); + shminfo->readOnly = False; + XShmAttach(data->display, shminfo); + XSync(data->display, False); + shmctl(shminfo->shmid, IPC_RMID, NULL); + data->stencil_surface = + SDL_CreateRGBSurfaceFrom(shminfo->shmaddr, + data->stencil_image->width, + data->stencil_image->height, + 8, + data->stencil_image->bytes_per_line, + 0, 0, 0, 0xFF); + if (!data->stencil_surface) { + printf("SDL_CreateRGBSurfaceFrom() failed"); + break; + } else { + printf("surface created\n"); + } + break; } - XSetBackground(data->display, data->mask_gc, 0); - XSetForeground(data->display, data->mask_gc, 1); +#endif // Set the default blending mode. renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; @@ -693,14 +755,6 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) if (!data->image) #endif /* not NO_SHARED_MEMORY */ { - /* This is the case where the server does not have - shared memory support and the texture is streaming. - It does not make sense to use Xrender here because - we would have to copy the data onto a server side - pixmap with XPutImage first and only then can we - use Xrender - */ - data->pixels = SDL_malloc(texture->h * data->pitch); if (!data->pixels) { X11_DestroyTexture(renderer, texture); @@ -999,61 +1053,74 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, SDL_Window *window = renderer->window; XPoint *xpoints, *xpoint; int i, xcount; + SDL_Rect clip, rect; - if (data->makedirty) { - SDL_Rect rect; - - /* Get the smallest rectangle that contains everything */ - rect.x = 0; - rect.y = 0; - rect.w = window->w; - rect.h = window->h; - if (!SDL_EnclosePoints(points, count, &rect, &rect)) { - /* Nothing to draw */ - return 0; + clip.x = 0; + clip.y = 0; + clip.w = window->w; + clip.h = window->h; + +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +#ifndef NO_SHARED_MEMORY + if (data->use_xrender && data->stencil_image && data->stencil_surface) { + SDL_FillRect(data->stencil_surface, NULL, 0x00); + + SDL_SetClipRect(data->stencil_surface, NULL); + SDL_DrawPoints(data->stencil_surface, points, count, 0xFF); + + XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, + 0, 0, 0, 0, window->w, window->h, False); + } else +#endif +#endif + { + if (data->makedirty) { + + /* Get the smallest rectangle that contains everything */ + rect.x = 0; + rect.y = 0; + rect.w = window->w; + rect.h = window->h; + if (!SDL_EnclosePoints(points, count, &rect, &rect)) { + /* Nothing to draw */ + return 0; + } + SDL_AddDirtyRect(&data->dirty, &rect); } - 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 = 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; } - xpoint->x = (short)x; - xpoint->y = (short)y; - ++xpoint; - ++xcount; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + XSetForeground(data->display, data->stencil_gc, 0x00); + XFillRectangle(data->display, data->stencil, data->stencil_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->stencil_gc, 0xFF); + XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount, + CoordModeOrigin); + } +#endif } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_xrender == SDL_TRUE) { + if (data->use_xrender) { XRenderColor foreground; - XRenderPictureAttributes attributes; - unsigned long valuemask; - foreground = xrenderdrawcolor(renderer); - /* Set the clip mask to restrict rendering to - * the primitive being drawn - */ - attributes.clip_mask = data->mask; - valuemask = CPClipMask; - - XSetForeground(data->display, data->mask_gc, 0); - XFillRectangle(data->display, data->mask, data->mask_gc, - 0, 0, window->w, window->h); - XSetForeground(data->display, data->mask_gc, 1); - - XDrawPoints(data->display, data->mask, data->mask_gc, xpoints, xcount, - CoordModeOrigin); - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, - &foreground, 0, 0, window->w, window->h);*/ - // Reset the clip_mask - attributes.clip_mask = None; - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); + XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, + &foreground, 0, 0, 1, 1); + 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); } else #endif @@ -1067,6 +1134,7 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, CoordModeOrigin); } } + SDL_stack_free(xpoints); return 0; @@ -1089,81 +1157,141 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, clip.y = 0; clip.w = window->w; clip.h = window->h; - - Pixmap drawable; - GC gc; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_xrender == SDL_TRUE) { - drawable = data->mask; - gc = data->mask_gc; - XSetForeground(data->display, data->mask_gc, 0); - XFillRectangle(data->display, data->mask, data->mask_gc, - 0, 0, window->w, window->h); - XSetForeground(data->display, data->mask_gc, 1); - } - else -#endif - { - drawable = data->drawable; - gc = data->gc; - } +#ifndef NO_SHARED_MEMORY + if (data->use_xrender && data->stencil_image && data->stencil_surface) { + SDL_FillRect(data->stencil_surface, NULL, 0x00); - foreground = renderdrawcolor(renderer, 1); - XSetForeground(data->display, data->gc, foreground); + SDL_SetClipRect(data->stencil_surface, NULL); + SDL_DrawLines(data->stencil_surface, points, count, 0xFF); - xpoint = xpoints = SDL_stack_alloc(XPoint, count); - xcount = 0; - minx = INT_MAX; - miny = INT_MAX; - maxx = INT_MIN; - maxy = INT_MIN; - for (i = 0; i < count; ++i) { - int x = points[i].x; - int y = points[i].y; - - /* If the point is inside the window, add it to the list */ - if (x >= 0 && x < window->w && y >= 0 && y < window->h) { - if (x < minx) { - minx = x; - } else if (x > maxx) { - maxx = x; - } - if (y < miny) { - miny = y; - } else if (y > maxy) { - maxy = y; - } - xpoint->x = (short)x; - xpoint->y = (short)y; - ++xpoint; - ++xcount; - continue; + XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, + 0, 0, 0, 0, window->w, window->h, False); + } else +#endif +#endif + { + Pixmap drawable; + GC gc; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + drawable = data->stencil; + gc = data->stencil_gc; + XSetForeground(data->display, data->stencil_gc, 0x00); + XFillRectangle(data->display, data->stencil, data->stencil_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->stencil_gc, 0xFF); + } + else +#endif + { + drawable = data->drawable; + gc = data->gc; } - /* We need to clip the line segments joined by this point */ - if (xcount > 0) { - int x1 = xpoint[-1].x; - int y1 = xpoint[-1].y; - int x2 = x; - int y2 = y; - if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { - if (x2 < minx) { - minx = x2; - } else if (x2 > maxx) { - maxx = x2; + foreground = renderdrawcolor(renderer, 1); + XSetForeground(data->display, data->gc, foreground); + + xpoint = xpoints = SDL_stack_alloc(XPoint, count); + xcount = 0; + minx = INT_MAX; + miny = INT_MAX; + maxx = INT_MIN; + maxy = INT_MIN; + for (i = 0; i < count; ++i) { + int x = points[i].x; + int y = points[i].y; + + /* If the point is inside the window, add it to the list */ + if (x >= 0 && x < window->w && y >= 0 && y < window->h) { + if (x < minx) { + minx = x; + } else if (x > maxx) { + maxx = x; } - if (y2 < miny) { - miny = y2; - } else if (y2 > maxy) { - maxy = y2; + if (y < miny) { + miny = y; + } else if (y > maxy) { + maxy = y; } - xpoint->x = (short)x2; - xpoint->y = (short)y2; + xpoint->x = (short)x; + xpoint->y = (short)y; ++xpoint; ++xcount; + continue; + } + + /* We need to clip the line segments joined by this point */ + if (xcount > 0) { + int x1 = xpoint[-1].x; + int y1 = xpoint[-1].y; + int x2 = x; + int y2 = y; + if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { + if (x2 < minx) { + minx = x2; + } else if (x2 > maxx) { + maxx = x2; + } + if (y2 < miny) { + miny = y2; + } else if (y2 > maxy) { + maxy = y2; + } + xpoint->x = (short)x2; + xpoint->y = (short)y2; + ++xpoint; + ++xcount; + } + XDrawLines(data->display, drawable, gc, + xpoints, xcount, CoordModeOrigin); + if (xpoints[0].x != x2 || xpoints[0].y != y2) { + XDrawPoint(data->display, drawable, gc, x2, y2); + } + if (data->makedirty) { + SDL_Rect rect; + + rect.x = minx; + rect.y = miny; + rect.w = (maxx - minx) + 1; + rect.h = (maxy - miny) + 1; + SDL_AddDirtyRect(&data->dirty, &rect); + } + xpoint = xpoints; + xcount = 0; + minx = INT_MAX; + miny = INT_MAX; + maxx = INT_MIN; + maxy = INT_MIN; + } + if (i < (count-1)) { + int x1 = x; + int y1 = y; + int x2 = points[i+1].x; + int y2 = points[i+1].y; + if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { + if (x1 < minx) { + minx = x1; + } else if (x1 > maxx) { + maxx = x1; + } + if (y1 < miny) { + miny = y1; + } else if (y1 > maxy) { + maxy = y1; + } + xpoint->x = (short)x1; + xpoint->y = (short)y1; + ++xpoint; + ++xcount; + } } - XDrawLines(data->display, drawable, gc, - xpoints, xcount, CoordModeOrigin); + } + if (xcount > 1) { + int x2 = xpoint[-1].x; + int y2 = xpoint[-1].y; + XDrawLines(data->display, drawable, gc, xpoints, xcount, + CoordModeOrigin); if (xpoints[0].x != x2 || xpoints[0].y != y2) { XDrawPoint(data->display, drawable, gc, x2, y2); } @@ -1176,65 +1304,16 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, rect.h = (maxy - miny) + 1; SDL_AddDirtyRect(&data->dirty, &rect); } - xpoint = xpoints; - xcount = 0; - minx = INT_MAX; - miny = INT_MAX; - maxx = INT_MIN; - maxy = INT_MIN; - } - if (i < (count-1)) { - int x1 = x; - int y1 = y; - int x2 = points[i+1].x; - int y2 = points[i+1].y; - if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { - if (x1 < minx) { - minx = x1; - } else if (x1 > maxx) { - maxx = x1; - } - if (y1 < miny) { - miny = y1; - } else if (y1 > maxy) { - maxy = y1; - } - xpoint->x = (short)x1; - xpoint->y = (short)y1; - ++xpoint; - ++xcount; - } - } - } - if (xcount > 1) { - int x2 = xpoint[-1].x; - int y2 = xpoint[-1].y; - XDrawLines(data->display, 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); } } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { + if (data->use_xrender) { XRenderColor xrforeground = xrenderdrawcolor(renderer); - XRenderPictureAttributes attributes; - attributes.clip_mask = data->mask; - unsigned long valuemask = CPClipMask; - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, - &xrforeground, 0, 0, window->w, window->h);*/ - attributes.clip_mask = None; - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); + XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, + &xrforeground, 0, 0, 1, 1); + 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); } #endif SDL_stack_free(xpoints); @@ -1258,44 +1337,60 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) clip.w = window->w; clip.h = window->h; - for (i = 0; i < count; ++i) { - if (!SDL_IntersectRect(rects[i], &clip, &rect)) { - continue; - } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +#ifndef NO_SHARED_MEMORY + if (data->use_xrender && data->stencil_image && data->stencil_surface) { + SDL_FillRect(data->stencil_surface, NULL, 0x00); - xrect->x = (short)rect.x; - xrect->y = (short)rect.y; - xrect->width = (unsigned short)rect.w; - xrect->height = (unsigned short)rect.h; - ++xrect; - ++xcount; + SDL_SetClipRect(data->stencil_surface, NULL); + SDL_DrawRects(data->stencil_surface, rects, count, 1); - if (data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &rect); - } + XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, + 0, 0, 0, 0, window->w, window->h, False); } - + else +#endif +#endif + { + + 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; + xrect->height = (unsigned short)rect.h; + ++xrect; + ++xcount; + + if (data->makedirty) { + SDL_AddDirtyRect(&data->dirty, &rect); + } + } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { - XRenderColor foreground; - XRenderPictureAttributes attributes; - unsigned long valuemask; + if (data->use_xrender) { + XSetForeground(data->display, data->stencil_gc, 0x00); + XFillRectangle(data->display, data->stencil, data->stencil_gc, + 0, 0, window->w, window->h); + XSetForeground(data->display, data->stencil_gc, 0xFF); + XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount); + } +#endif + } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + XRenderColor foreground; foreground = xrenderdrawcolor(renderer); - valuemask = CPClipMask; - attributes.clip_mask = data->mask; - - XSetForeground(data->display, data->mask_gc, 0); - XFillRectangle(data->display, data->mask, data->mask_gc, - 0, 0, window->w, window->h); - XSetForeground(data->display, data->mask_gc, 1); - - XDrawRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, - &foreground, 0, 0, window->w, window->h);*/ - attributes.clip_mask = None; - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); + + XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, + &foreground, 0, 0, 1, 1); + + 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); } else #endif @@ -1326,7 +1421,7 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) clip.y = 0; clip.w = window->w; clip.h = window->h; - + int i, xcount; XRectangle *xrects, *xrect; xrect = xrects = SDL_stack_alloc(XRectangle, count); @@ -1349,26 +1444,11 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { + if (data->use_xrender) { XRenderColor foreground; - XRenderPictureAttributes attributes; - foreground = xrenderdrawcolor(renderer); - attributes.clip_mask = data->mask; - - XSetForeground(data->display, data->mask_gc, 0); - XFillRectangle(data->display, data->mask, data->mask_gc, - 0, 0, window->w, window->h); - XSetForeground(data->display, data->mask_gc, 1); - - XFillRectangles(data->display, data->mask, data->mask_gc, - xrects, xcount); - - XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - /*XRenderFillRectangle(data->display, data->blend_op, data->drawable_pict, - &foreground, 0, 0, window->w, window->h);*/ - attributes.clip_mask = None; - XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); + XRenderFillRectangles(data->display, data->blend_op, data->drawable_pict, + &foreground, xrects, xcount); } else #endif @@ -1383,7 +1463,6 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) } SDL_stack_free(xrects); - return 0; } @@ -1726,11 +1805,11 @@ X11_DestroyRenderer(SDL_Renderer * renderer) XFreeGC(data->display, data->gc); } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->mask_gc) { - XFreeGC(data->display, data->mask_gc); + if (data->stencil_gc) { + XFreeGC(data->display, data->stencil_gc); } - if (data->mask) { - XFreePixmap(data->display, data->mask); + if (data->stencil) { + XFreePixmap(data->display, data->stencil); } if (data->drawable_pict) { XRenderFreePicture(data->display, data->drawable_pict); diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 235830c73..be4041f2e 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -153,6 +153,7 @@ SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,S 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) #if NeedWidePrototypes SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return) @@ -249,6 +250,7 @@ SDL_X11_SYM(void,XRenderComposite,(Display *dpy,int op,Picture src,Picture mask, 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) #endif /* *INDENT-ON* */ From 015c4dd21985c73181e0fddeb71ba36d74da7e02 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 18 Jul 2010 18:27:38 +0530 Subject: [PATCH 29/47] Major changes to drawing. Reverted back to core X11 functions due to regressions. --- src/video/x11/SDL_x11render.c | 116 ++++++++++++++++++++-------------- test/testsprite2.c | 4 +- 2 files changed, 71 insertions(+), 49 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 01770720d..e9dbc8b6d 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -32,6 +32,8 @@ #include "../SDL_yuv_sw_c.h" #include "SDL_surface.h" +//#define EXPT + /* X11 renderer implementation */ static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags); @@ -102,9 +104,11 @@ typedef struct Pixmap brush; Picture brush_pict; #ifndef NO_SHARED_MEMORY +#ifdef EXPT XImage *stencil_image; SDL_Surface *stencil_surface; XShmSegmentInfo stencil_shminfo; +#endif #endif Picture xwindow_pict; Picture pixmap_picts[3]; @@ -135,7 +139,6 @@ typedef struct Picture picture; XRenderPictFormat* picture_fmt; int blend_op; -// SDL_bool use_xrender; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -318,6 +321,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) PictStandardARGB32), CPRepeat, &brush_attr); #ifndef NO_SHARED_MEMORY +#ifdef EXPT /* Create a mask image using MIT-SHM */ data->stencil_image = NULL; data->stencil_surface = NULL; @@ -326,22 +330,10 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->stencil_image = XShmCreateImage(data->display, data->visual, 8, ZPixmap, NULL, shminfo, window->w, window->h); - if (!data->stencil_image) { - printf("XShmCreateImage() failed"); - break; - } else { - printf("image created\n"); - } shminfo->shmid = shmget(IPC_PRIVATE, data->stencil_image->bytes_per_line * data->stencil_image->height, IPC_CREAT|0777); - if (!shminfo->shmid) { - printf("shmget() failed"); - break; - } else { - printf("shmid aquired\n"); - } shminfo->shmaddr = data->stencil_image->data = shmat(shminfo->shmid, 0, 0); shminfo->readOnly = False; XShmAttach(data->display, shminfo); @@ -354,14 +346,9 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) 8, data->stencil_image->bytes_per_line, 0, 0, 0, 0xFF); - if (!data->stencil_surface) { - printf("SDL_CreateRGBSurfaceFrom() failed"); - break; - } else { - printf("surface created\n"); - } break; } +#endif #endif // Set the default blending mode. renderer->blendMode = SDL_BLENDMODE_BLEND; @@ -461,7 +448,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) /* 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"); @@ -1059,35 +1046,40 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, clip.y = 0; clip.w = window->w; clip.h = window->h; + if (data->makedirty) { + /* Get the smallest rectangle that contains everything */ + rect.x = 0; + rect.y = 0; + rect.w = window->w; + rect.h = window->h; + if (!SDL_EnclosePoints(points, count, &rect, &rect)) { + /* Nothing to draw */ + return 0; + } + SDL_AddDirtyRect(&data->dirty, &rect); + } +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifndef NO_SHARED_MEMORY +#ifdef EXPT if (data->use_xrender && data->stencil_image && data->stencil_surface) { - SDL_FillRect(data->stencil_surface, NULL, 0x00); + SDL_FillRect(data->stencil_surface, &rect, 0x00); SDL_SetClipRect(data->stencil_surface, NULL); + SDL_DrawPoints(data->stencil_surface, points, count, 0xFF); XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, - 0, 0, 0, 0, window->w, window->h, False); + rect.x, rect.y, rect.x, rect.y, rect.w, rect.h, False); + + XSync(data->display, False); } else #endif #endif +#endif +*/ { - if (data->makedirty) { - - /* Get the smallest rectangle that contains everything */ - rect.x = 0; - rect.y = 0; - rect.w = window->w; - rect.h = window->h; - if (!SDL_EnclosePoints(points, count, &rect, &rect)) { - /* Nothing to draw */ - return 0; - } - SDL_AddDirtyRect(&data->dirty, &rect); - } - xpoint = xpoints = SDL_stack_alloc(XPoint, count); xcount = 0; for (i = 0; i < count; ++i) { @@ -1101,17 +1093,19 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, ++xpoint; ++xcount; } +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XSetForeground(data->display, data->stencil_gc, 0x00); XFillRectangle(data->display, data->stencil, data->stencil_gc, - 0, 0, window->w, window->h); + rect.x, rect.y, rect.w, rect.h); XSetForeground(data->display, data->stencil_gc, 0xFF); XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount, CoordModeOrigin); } -#endif +#endif*/ } +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XRenderColor foreground; @@ -1120,10 +1114,11 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, &foreground, 0, 0, 1, 1); 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); + rect.x, rect.y, rect.x, rect.y, rect.x, rect.y, rect.w, rect.h); } else #endif +*/ { unsigned long foreground = renderdrawcolor(renderer, 1); XSetForeground(data->display, data->gc, foreground); @@ -1157,22 +1152,30 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, clip.y = 0; clip.w = window->w; clip.h = window->h; +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifndef NO_SHARED_MEMORY +#ifdef EXPT if (data->use_xrender && data->stencil_image && data->stencil_surface) { SDL_FillRect(data->stencil_surface, NULL, 0x00); - SDL_SetClipRect(data->stencil_surface, NULL); SDL_DrawLines(data->stencil_surface, points, count, 0xFF); + SDL_SetClipRect(data->stencil_surface, NULL); + XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, 0, 0, 0, 0, window->w, window->h, False); + + XSync(data->display, False); } else #endif #endif +#endif +*/ { Pixmap drawable; GC gc; +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { drawable = data->stencil; @@ -1184,6 +1187,7 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, } else #endif +*/ { drawable = data->drawable; gc = data->gc; @@ -1306,6 +1310,7 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, } } } +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XRenderColor xrforeground = xrenderdrawcolor(renderer); @@ -1316,6 +1321,7 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, 0, 0, 0, 0, 0, 0, window->w, window->h); } #endif +*/ SDL_stack_free(xpoints); return 0; @@ -1336,21 +1342,27 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) clip.y = 0; clip.w = window->w; clip.h = window->h; - +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifndef NO_SHARED_MEMORY +#ifdef EXPT if (data->use_xrender && data->stencil_image && data->stencil_surface) { SDL_FillRect(data->stencil_surface, NULL, 0x00); SDL_SetClipRect(data->stencil_surface, NULL); + SDL_DrawRects(data->stencil_surface, rects, count, 1); XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, 0, 0, 0, 0, window->w, window->h, False); + + XSync(data->display, False); } else #endif #endif +#endif +*/ { for (i = 0; i < count; ++i) { @@ -1369,6 +1381,7 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) SDL_AddDirtyRect(&data->dirty, &rect); } } +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XSetForeground(data->display, data->stencil_gc, 0x00); @@ -1379,7 +1392,9 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount); } #endif - } +*/ + } +/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XRenderColor foreground; @@ -1387,13 +1402,13 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, &foreground, 0, 0, 1, 1); - 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); } else #endif +*/ { unsigned long foreground; @@ -1447,8 +1462,15 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) if (data->use_xrender) { XRenderColor foreground; foreground = xrenderdrawcolor(renderer); - XRenderFillRectangles(data->display, data->blend_op, data->drawable_pict, - &foreground, xrects, xcount); + 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 @@ -1705,7 +1727,7 @@ X11_RenderPresent(SDL_Renderer * renderer) 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 == SDL_TRUE) + if (data->use_xrender) { XRenderComposite(data->display, data->blend_op, @@ -1726,7 +1748,7 @@ X11_RenderPresent(SDL_Renderer * renderer) } } SDL_ClearDirtyRects(&data->dirty); - } + } XSync(data->display, False); /* Update the flipping chain, if any */ diff --git a/test/testsprite2.c b/test/testsprite2.c index 6c866d12f..0c2e2d146 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -144,8 +144,8 @@ MoveSprites(SDL_Window * window, SDL_Texture * sprite) /* Test points */ SDL_SetRenderDrawColor(0xFF, 0x00, 0x00, 0xFF); SDL_RenderDrawPoint(0, 0); - SDL_RenderDrawPoint(window_w-1, 0); - SDL_RenderDrawPoint(0, window_h-1); + SDL_RenderDrawPoint(window_w/2-1, window_h/2-1); + SDL_RenderDrawPoint(window_w/2-1, window_h/2-1); SDL_RenderDrawPoint(window_w-1, window_h-1); /* Test horizontal and vertical lines */ From ee29d2d5f5f59460443afb3c303f879c3b01613b Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 18 Jul 2010 18:45:30 +0530 Subject: [PATCH 30/47] Remove experimental cruft. --- src/video/x11/SDL_x11render.c | 101 ---------------------------------- 1 file changed, 101 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index e9dbc8b6d..8c51dc54d 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -30,9 +30,6 @@ #include "../SDL_rect_c.h" #include "../SDL_pixels_c.h" #include "../SDL_yuv_sw_c.h" -#include "SDL_surface.h" - -//#define EXPT /* X11 renderer implementation */ @@ -103,13 +100,6 @@ typedef struct Pixmap stencil; Pixmap brush; Picture brush_pict; -#ifndef NO_SHARED_MEMORY -#ifdef EXPT - XImage *stencil_image; - SDL_Surface *stencil_surface; - XShmSegmentInfo stencil_shminfo; -#endif -#endif Picture xwindow_pict; Picture pixmap_picts[3]; Picture drawable_pict; @@ -320,36 +310,6 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) XRenderFindStandardFormat(data->display, PictStandardARGB32), CPRepeat, &brush_attr); -#ifndef NO_SHARED_MEMORY -#ifdef EXPT - /* Create a mask image using MIT-SHM */ - data->stencil_image = NULL; - data->stencil_surface = NULL; - XShmSegmentInfo *shminfo = &data->stencil_shminfo; - while (SDL_X11_HAVE_SHM) { - data->stencil_image = - XShmCreateImage(data->display, data->visual, 8, ZPixmap, - NULL, shminfo, window->w, window->h); - shminfo->shmid = shmget(IPC_PRIVATE, - data->stencil_image->bytes_per_line * - data->stencil_image->height, - IPC_CREAT|0777); - shminfo->shmaddr = data->stencil_image->data = shmat(shminfo->shmid, 0, 0); - shminfo->readOnly = False; - XShmAttach(data->display, shminfo); - XSync(data->display, False); - shmctl(shminfo->shmid, IPC_RMID, NULL); - data->stencil_surface = - SDL_CreateRGBSurfaceFrom(shminfo->shmaddr, - data->stencil_image->width, - data->stencil_image->height, - 8, - data->stencil_image->bytes_per_line, - 0, 0, 0, 0xFF); - break; - } -#endif -#endif // Set the default blending mode. renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; @@ -1059,26 +1019,6 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, } SDL_AddDirtyRect(&data->dirty, &rect); } -/* -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER -#ifndef NO_SHARED_MEMORY -#ifdef EXPT - if (data->use_xrender && data->stencil_image && data->stencil_surface) { - SDL_FillRect(data->stencil_surface, &rect, 0x00); - - SDL_SetClipRect(data->stencil_surface, NULL); - - SDL_DrawPoints(data->stencil_surface, points, count, 0xFF); - - XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, - rect.x, rect.y, rect.x, rect.y, rect.w, rect.h, False); - - XSync(data->display, False); - } else -#endif -#endif -#endif -*/ { xpoint = xpoints = SDL_stack_alloc(XPoint, count); xcount = 0; @@ -1152,26 +1092,6 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, clip.y = 0; clip.w = window->w; clip.h = window->h; -/* -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER -#ifndef NO_SHARED_MEMORY -#ifdef EXPT - if (data->use_xrender && data->stencil_image && data->stencil_surface) { - SDL_FillRect(data->stencil_surface, NULL, 0x00); - - SDL_DrawLines(data->stencil_surface, points, count, 0xFF); - - SDL_SetClipRect(data->stencil_surface, NULL); - - XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, - 0, 0, 0, 0, window->w, window->h, False); - - XSync(data->display, False); - } else -#endif -#endif -#endif -*/ { Pixmap drawable; GC gc; @@ -1342,27 +1262,6 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) clip.y = 0; clip.w = window->w; clip.h = window->h; -/* -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER -#ifndef NO_SHARED_MEMORY -#ifdef EXPT - if (data->use_xrender && data->stencil_image && data->stencil_surface) { - SDL_FillRect(data->stencil_surface, NULL, 0x00); - - SDL_SetClipRect(data->stencil_surface, NULL); - - SDL_DrawRects(data->stencil_surface, rects, count, 1); - - XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image, - 0, 0, 0, 0, window->w, window->h, False); - - XSync(data->display, False); - } - else -#endif -#endif -#endif -*/ { for (i = 0; i < count; ++i) { From 7aef9118e932fb345947f922fd74692367a05108 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Sun, 18 Jul 2010 19:03:39 +0530 Subject: [PATCH 31/47] Resync tip to default. Using named branches is a bad idea. --- test/testsprite2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/testsprite2.c b/test/testsprite2.c index 0c2e2d146..10c201fe4 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -20,7 +20,7 @@ static int current_color = 0; static SDL_Rect *positions; static SDL_Rect *velocities; static int sprite_w, sprite_h; -static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND; +static SDL_BlendMode blendMode = SDL_BLENDMODE_MASK; static SDL_TextureScaleMode scaleMode = SDL_TEXTURESCALEMODE_NONE; /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ @@ -144,8 +144,8 @@ MoveSprites(SDL_Window * window, SDL_Texture * sprite) /* Test points */ SDL_SetRenderDrawColor(0xFF, 0x00, 0x00, 0xFF); SDL_RenderDrawPoint(0, 0); - SDL_RenderDrawPoint(window_w/2-1, window_h/2-1); - SDL_RenderDrawPoint(window_w/2-1, window_h/2-1); + SDL_RenderDrawPoint(window_w-1, 0); + SDL_RenderDrawPoint(0, window_h-1); SDL_RenderDrawPoint(window_w-1, window_h-1); /* Test horizontal and vertical lines */ From 3b5100fa32069cc131105a23688815333b66b350 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 19 Jul 2010 17:46:37 +0530 Subject: [PATCH 32/47] Use XDamage to optimise drawing operations. --- src/video/x11/SDL_x11render.c | 42 ++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 8c51dc54d..1b458da3b 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -31,6 +31,9 @@ #include "../SDL_pixels_c.h" #include "../SDL_yuv_sw_c.h" +#include +#include + /* X11 renderer implementation */ static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags); @@ -108,6 +111,8 @@ typedef struct XRenderPictFormat* xwindow_pict_fmt; GC stencil_gc; SDL_bool use_xrender; + Damage stencil_damage; + XserverRegion stencil_parts; #endif int current_pixmap; Drawable drawable; @@ -295,12 +300,18 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->stencil_gc = XCreateGC(data->display, data->stencil, GCGraphicsExposures, &gcv); XSetBackground(data->display, data->stencil_gc, 0x00); + XSetForeground(data->display, data->stencil_gc, 0x00); + XFillRectangle(data->display, data->stencil, data->stencil_gc, + 0, 0, window->w, window->h); XSetForeground(data->display, data->stencil_gc, 0xFF); data->stencil_pict = XRenderCreatePicture(data->display, data->stencil, XRenderFindStandardFormat(data->display, PictStandardA8), 0, NULL); + data->stencil_damage = + XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty); + XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts); data->brush = XCreatePixmap(data->display, data->xwindow, 1, 1, 32); XRenderPictureAttributes brush_attr; @@ -1001,6 +1012,8 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, XPoint *xpoints, *xpoint; int i, xcount; SDL_Rect clip, rect; + /*Damage damage; + XserverRegion parts;*/ clip.x = 0; clip.y = 0; @@ -1033,32 +1046,39 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, ++xpoint; ++xcount; } -/* + #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XSetForeground(data->display, data->stencil_gc, 0x00); + XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, data->stencil_parts); XFillRectangle(data->display, data->stencil, data->stencil_gc, rect.x, rect.y, rect.w, rect.h); + XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); XSetForeground(data->display, data->stencil_gc, 0xFF); + /*damage = + XDamageCreate(data->display, data->stencil, XDamageReportRawRectangles);*/ XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount, CoordModeOrigin); + XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts); } -#endif*/ +#endif } -/* + #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XRenderColor foreground; foreground = xrenderdrawcolor(renderer); XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, &foreground, 0, 0, 1, 1); + XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, data->stencil_parts); XRenderComposite(data->display, data->blend_op, data->brush_pict, data->stencil_pict, data->drawable_pict, rect.x, rect.y, rect.x, rect.y, rect.x, rect.y, rect.w, rect.h); + XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None); + //XDamageDestroy(data->display, damage); } else #endif -*/ { unsigned long foreground = renderdrawcolor(renderer, 1); XSetForeground(data->display, data->gc, foreground); @@ -1087,6 +1107,8 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, int i, xcount; int minx, miny; int maxx, maxy; + XserverRegion parts; + Damage damage; clip.x = 0; clip.y = 0; @@ -1095,19 +1117,21 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, { Pixmap drawable; GC gc; -/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { drawable = data->stencil; gc = data->stencil_gc; XSetForeground(data->display, data->stencil_gc, 0x00); + XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, data->stencil_parts); XFillRectangle(data->display, data->stencil, data->stencil_gc, 0, 0, window->w, window->h); + XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); XSetForeground(data->display, data->stencil_gc, 0xFF); + /*damage = + XDamageCreate(data->display, data->stencil, XDamageReportRawRectangles);*/ } else #endif -*/ { drawable = data->drawable; gc = data->gc; @@ -1230,18 +1254,20 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, } } } -/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { XRenderColor xrforeground = xrenderdrawcolor(renderer); XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, &xrforeground, 0, 0, 1, 1); + XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts); + XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, data->stencil_parts); 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); + XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None); + //XDamageDestroy(data->display, damage); } #endif -*/ SDL_stack_free(xpoints); return 0; From 1cd3dbe1b70407b000f2a12e4c567208b26b7b4b Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 19 Jul 2010 18:57:02 +0530 Subject: [PATCH 33/47] Massive speed-up. Fixed the format that is set for the renderer. Included runtime checks for XDamage. --- src/video/x11/SDL_x11render.c | 258 +++++++++++++++++++++++++++------- 1 file changed, 204 insertions(+), 54 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 1b458da3b..d88f7b3f5 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -34,6 +34,8 @@ #include #include +#define SDL_VIDEO_DRIVER_X11_XDAMAGE + /* X11 renderer implementation */ static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags); @@ -108,11 +110,15 @@ typedef struct Picture drawable_pict; Picture stencil_pict; int blend_op; - XRenderPictFormat* xwindow_pict_fmt; + 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; @@ -255,16 +261,35 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER data->use_xrender = SDL_FALSE; + data->use_xdamage = SDL_FALSE; + int event_basep, error_basep; if (SDL_X11_HAVE_XRENDER) { - // Query the extension. This is the server runtime check. - int event_basep, error_basep; + /* Query the extension. This is the server runtime check. */ if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) data->use_xrender = SDL_TRUE; } +#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xrender) { - // Find the PictFormat from the visual. - // Should be an RGB PictFormat most of the time. + /* Query XDamage and XFixes */ + if(XDamageQueryExtension(data->display, + &event_basep, + &error_basep) == True && + (XFixesQueryExtension(data->display, + &event_basep, + &error_basep) == True)) { + int major_version, minor_version; + XFixesQueryVersion(data->display, + &major_version, + &minor_version); + /* Only XFixes v 2 or greater + * Required for XFixesSetPictureClipRegion() */ + if(major_version >= 2) + data->use_xdamage = SDL_TRUE; + } +#endif + /* 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) { @@ -289,14 +314,14 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) 0, 0, 0, 0, window->w, window->h); - // Add some blending modes to the list of supported blending modes + /* Add some blending modes to the list of supported blending modes */ renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); - // Create a clip mask that is used for rendering primitives. + /* Create a clip mask that is used for rendering primitives. */ data->stencil = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 8); - // Create the GC for the clip mask. + /* Create the GC for the clip mask. */ data->stencil_gc = XCreateGC(data->display, data->stencil, GCGraphicsExposures, &gcv); XSetBackground(data->display, data->stencil_gc, 0x00); @@ -309,9 +334,13 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) XRenderFindStandardFormat(data->display, PictStandardA8), 0, NULL); - data->stencil_damage = - XDamageCreate(data->display, data->stencil, XDamageReportNonEmpty); - XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts); +#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; @@ -341,6 +370,15 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; n = 1; } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + if (n > 0) + data->drawable_pict_fmt = + XRenderFindStandardFormat(data->display, PictStandardARGB32); + else + data->drawable_pict_fmt = data->xwindow_pict_fmt; + } +#endif for (i = 0; i < n; ++i) { #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { @@ -364,8 +402,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->use_xrender) { - // Create xrender pictures for each of the pixmaps - // and clear the pixmaps. + /* Create xrender pictures for each of the pixmaps + * and clear the pixmaps. */ data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], @@ -406,13 +444,29 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) } 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); @@ -1011,15 +1065,14 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, SDL_Window *window = renderer->window; XPoint *xpoints, *xpoint; int i, xcount; - SDL_Rect clip, rect; - /*Damage damage; - XserverRegion parts;*/ + SDL_Rect clip; clip.x = 0; clip.y = 0; clip.w = window->w; clip.h = window->h; if (data->makedirty) { + SDL_Rect rect; /* Get the smallest rectangle that contains everything */ rect.x = 0; @@ -1048,34 +1101,75 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_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, 0x00); - XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, data->stencil_parts); +#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, - rect.x, rect.y, rect.w, rect.h); - XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); + 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, 0xFF); - /*damage = - XDamageCreate(data->display, data->stencil, XDamageReportRawRectangles);*/ + XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount, CoordModeOrigin); - XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts); +#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) { + 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); - XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, data->stencil_parts); +#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, - rect.x, rect.y, rect.x, rect.y, rect.x, rect.y, rect.w, rect.h); - XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None); - //XDamageDestroy(data->display, damage); + 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 @@ -1107,8 +1201,6 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, int i, xcount; int minx, miny; int maxx, maxy; - XserverRegion parts; - Damage damage; clip.x = 0; clip.y = 0; @@ -1118,17 +1210,29 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, Pixmap drawable; GC gc; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_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, 0x00); - XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, data->stencil_parts); +#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); - XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); +#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, 0xFF); - /*damage = - XDamageCreate(data->display, data->stencil, XDamageReportRawRectangles);*/ } else #endif @@ -1255,17 +1359,32 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, } } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_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); - XDamageSubtract(data->display, data->stencil_damage, None, data->stencil_parts); - XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, data->stencil_parts); +#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); - XFixesSetPictureClipRegion(data->display, data->drawable_pict, 0, 0, None); - //XDamageDestroy(data->display, damage); +#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); @@ -1306,34 +1425,65 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) SDL_AddDirtyRect(&data->dirty, &rect); } } -/* #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_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, 0x00); +#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, 0xFF); 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) { + 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; From ebd50fe9c79d96b0d44e8374365eee1e63bc5dd6 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 19 Jul 2010 20:05:53 +0530 Subject: [PATCH 34/47] Integrate XFixes and XDamage into the build system. --- configure.in | 44 ++++++++++++++++++++++++++++++++--- include/SDL_config.h.in | 4 ++++ src/video/x11/SDL_x11dyn.h | 8 +++++++ src/video/x11/SDL_x11render.c | 35 +++++++++++++--------------- src/video/x11/SDL_x11sym.h | 16 +++++++++++++ 5 files changed, 85 insertions(+), 22 deletions(-) diff --git a/configure.in b/configure.in index bc901943b..a93d2e745 100644 --- a/configure.in +++ b/configure.in @@ -1055,7 +1055,9 @@ AC_HELP_STRING([--enable-x11-shared], [dynamically load X11 support [[default=ma xrandr_lib=[`find_lib "libXrandr.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`] xinput_lib=[`find_lib "libXi.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`] xss_lib=[`find_lib "libXss.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`] - ;; + xdamage_lib=[`find_lib "libXdamage.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`] + xfixes_lib=[`find_lib "libXfixes.so.*" "$X_LIBS -L/usr/X11/$base_libdir -L/usr/X11R6/$base_libdir" | sed 's/.*\/\(.*\)/\1/; q'`] +;; esac if test x$ac_cv_func_shmat != xyes; then @@ -1222,14 +1224,50 @@ AC_HELP_STRING([--enable-video-x11-xrender], [enable X11 Xrender extension [[def 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 + ]) + AC_CHECK_HEADER(X11/extensions/Xfixes.h, + have_xfixes_h_hdr=yes, + have_xfixes_h_hdr=no, + [#include + ]) + if test x$have_xdamage_h_hdr = xyes && test x$have_xfixes_h_hdr = xyes ; then + if test x$enable_x11_shared = xyes && test x$xdamage_lib != x && test x$xfixes_lib != x ; then + echo "-- dynamic libXdamage -> $xdamage_lib" + echo "-- dynamic libXfixes -> $xfixes_lib" + AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XDAMAGE, "$xdamage_lib") + AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES, "$xfixes_lib") + definitely_enable_video_x11_xdamage=yes + definitely_enable_video_x11_xfixes=yes + else + AC_CHECK_LIB(Xdamage, XDamageQueryExtension, have_xdamage_lib=yes) + AC_CHECK_LIB(Xfixes, XFixesQueryExtension, have_xfixes_lib=yes) + if test x$have_xdamage_lib = xyes && test x$have_xfixes_lib = xyes ; then + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lXdamage -lXfixes" + definitely_enable_video_x11_xdamage=yes + definitely_enable_video_x11_xfixes=yes + fi + fi + fi + fi + if test x$definitely_enable_video_x11_xdamage = xyes && test x$definitely_enable_video_x11_xfixes = xyes ; then + AC_DEFINE(SDL_VIDEO_DRIVER_X11_XDAMAGE) + AC_DEFINE(SDL_VIDEO_DRIVER_X11_XFIXES) + fi AC_ARG_ENABLE(render-x11, AC_HELP_STRING([--enable-render-x11], [enable the X11 render driver [[default=yes]]]), , enable_render_x11=yes) if test x$enable_render_x11 = xyes; then AC_DEFINE(SDL_VIDEO_RENDER_X11) fi - fi + fi fi } diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index b9e1ef300..0bb4af38f 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -272,6 +272,8 @@ #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XDAMAGE +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES #undef SDL_VIDEO_DRIVER_X11_VIDMODE #undef SDL_VIDEO_DRIVER_X11_XINERAMA #undef SDL_VIDEO_DRIVER_X11_XRANDR @@ -279,6 +281,8 @@ #undef SDL_VIDEO_DRIVER_X11_SCRNSAVER #undef SDL_VIDEO_DRIVER_X11_XV #undef SDL_VIDEO_DRIVER_X11_XRENDER +#undef SDL_VIDEO_DRIVER_X11_XDAMAGE +#undef SDL_VIDEO_DRIVER_X11_XFIXES #undef SDL_VIDEO_RENDER_X11 diff --git a/src/video/x11/SDL_x11dyn.h b/src/video/x11/SDL_x11dyn.h index f8b3114fd..408deec55 100644 --- a/src/video/x11/SDL_x11dyn.h +++ b/src/video/x11/SDL_x11dyn.h @@ -56,6 +56,14 @@ #include #endif +#if SDL_VIDEO_DRIVER_X11_XDAMAGE +#include +#endif + +#if SDL_VIDEO_DRIVER_X11_XFIXES +#include +#endif + /* * When using the "dynamic X11" functionality, we duplicate all the Xlib * symbols that would be referenced by SDL inside of SDL itself. diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index d88f7b3f5..ed38a948d 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -31,11 +31,6 @@ #include "../SDL_pixels_c.h" #include "../SDL_yuv_sw_c.h" -#include -#include - -#define SDL_VIDEO_DRIVER_X11_XDAMAGE - /* X11 renderer implementation */ static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags); @@ -271,21 +266,23 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) } #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xrender) { + if(SDL_X11_HAVE_XDAMAGE && SDL_X11_HAVE_XFIXES) { /* Query XDamage and XFixes */ - if(XDamageQueryExtension(data->display, - &event_basep, - &error_basep) == True && - (XFixesQueryExtension(data->display, - &event_basep, - &error_basep) == True)) { - int major_version, minor_version; - XFixesQueryVersion(data->display, - &major_version, - &minor_version); - /* Only XFixes v 2 or greater - * Required for XFixesSetPictureClipRegion() */ - if(major_version >= 2) - data->use_xdamage = SDL_TRUE; + if(XDamageQueryExtension(data->display, + &event_basep, + &error_basep) == True && + (XFixesQueryExtension(data->display, + &event_basep, + &error_basep) == True)) { + int major_version, minor_version; + XFixesQueryVersion(data->display, + &major_version, + &minor_version); + /* Only XFixes v 2 or greater + * Required for XFixesSetPictureClipRegion() */ + if(major_version >= 2) + data->use_xdamage = SDL_TRUE; + } } #endif /* Find the PictFormat from the visual. diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index be4041f2e..62bd8dfc3 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -252,6 +252,22 @@ SDL_X11_SYM(void,XRenderSetPictureTransform,(Display *dpy,Picture picture,XTrans 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) #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(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: */ From 8c9ab14570ea0f645bf3a5ae63bd0ccdea1a6abb Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Mon, 19 Jul 2010 21:02:49 +0530 Subject: [PATCH 35/47] Respect environment variables. --- src/SDL_error.c | 2 +- src/video/x11/SDL_x11render.c | 119 ++++++++++++++++++++++++++-------- src/video/x11/SDL_x11sym.h | 2 + src/video/x11/SDL_x11video.h | 6 ++ 4 files changed, 100 insertions(+), 29 deletions(-) diff --git a/src/SDL_error.c b/src/SDL_error.c index dfb583f1f..e1f90578c 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -38,7 +38,7 @@ extern SDL_error *SDL_GetErrBuf(void); #define SDL_ERRBUFIZE 1024 -#define DEBUG_ERROR +//#define DEBUG_ERROR /* Private functions */ diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index ed38a948d..176387d9e 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -176,11 +176,87 @@ UpdateYUVTextureData(SDL_Texture * texture) texture->h, data->pixels, data->pitch); } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +static SDL_bool +CheckXRender(Display *display, int *major, int *minor) { + const char *env; + + *major = *minor = 0; + + env = SDL_getenv("SDL_VIDEO_X11_XRENDER"); + + if (env && !SDL_atoi(env)) { + return SDL_FALSE; + } + + if (!SDL_X11_HAVE_XRENDER) { + return SDL_FALSE; + } + + if (!XRenderQueryVersion(display, major, minor)) { + return SDL_FALSE; + } + + return SDL_TRUE; +} +#endif + +#ifdef SDL_VIDEO_DRIVER_X11_XFIXES +static SDL_bool +CheckXFixes(Display *display, int *major, int *minor) { + const char *env; + + *major = *minor = 0; + + env = SDL_getenv("SDL_VIDEO_X11_XFIXES"); + + if (env && !SDL_atoi(env)) { + return SDL_FALSE; + } + + if (!SDL_X11_HAVE_XFIXES) { + return SDL_FALSE; + } + + if (!XFixesQueryVersion(display, major, minor)) { + return SDL_FALSE; + } + + return SDL_TRUE; +} +#endif + +#ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE +static SDL_bool +CheckXDamage(Display *display, int *major, int *minor) { + const char *env; + + *major = *minor = 0; + + env = SDL_getenv("SDL_VIDEO_X11_XDAMAGE"); + + if (env && !SDL_atoi(env)) { + return SDL_FALSE; + } + + if (!SDL_X11_HAVE_XDAMAGE) { + return SDL_FALSE; + } + + if (!XDamageQueryVersion(display, major, minor)) { + return SDL_FALSE; + } + + return SDL_TRUE; +} +#endif + 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; @@ -189,7 +265,13 @@ X11_AddRenderDriver(_THIS) info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_YUY2; 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_ARGB8888; + +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + int major, minor; + if (CheckXRender(data->display, &major, &minor)) { + info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_ARGB8888; + } +#endif for (i = 0; i < _this->num_displays; ++i) { SDL_AddRenderDriver(&_this->displays[i], &X11_RenderDriver); @@ -255,36 +337,17 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->info.flags = SDL_RENDERER_ACCELERATED; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - data->use_xrender = SDL_FALSE; - data->use_xdamage = SDL_FALSE; - int event_basep, error_basep; - if (SDL_X11_HAVE_XRENDER) { - /* Query the extension. This is the server runtime check. */ - if(XRenderQueryExtension(data->display, - &event_basep, &error_basep) == True) - data->use_xrender = SDL_TRUE; - } + int major, minor; + data->use_xrender = CheckXRender(data->display, &major, &minor); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE - if (data->use_xrender) { - if(SDL_X11_HAVE_XDAMAGE && SDL_X11_HAVE_XFIXES) { - /* Query XDamage and XFixes */ - if(XDamageQueryExtension(data->display, - &event_basep, - &error_basep) == True && - (XFixesQueryExtension(data->display, - &event_basep, - &error_basep) == True)) { - int major_version, minor_version; - XFixesQueryVersion(data->display, - &major_version, - &minor_version); - /* Only XFixes v 2 or greater - * Required for XFixesSetPictureClipRegion() */ - if(major_version >= 2) - data->use_xdamage = SDL_TRUE; - } + 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, diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 62bd8dfc3..c8256e914 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -240,6 +240,7 @@ SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),r #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) @@ -256,6 +257,7 @@ SDL_X11_SYM(void,XRenderFillRectangles,(Display *dpy,int op,Picture dst,_Xconst #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) diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 7f5d73421..d3aaf30d1 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -48,6 +48,12 @@ #if SDL_VIDEO_DRIVER_X11_XRENDER #include #endif +#if SDL_VIDEO_DRIVER_X11_XDAMAGE +#include +#endif +#if SDL_VIDEO_DRIVER_X11_XFIXES +#include +#endif #include "SDL_x11dyn.h" #include "SDL_x11events.h" From 71408638987f80f393f9d5b9b4ffa1d9571c8728 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Tue, 20 Jul 2010 11:43:13 +0530 Subject: [PATCH 36/47] Implement support for setting texture scale mode. --- src/video/x11/SDL_x11render.c | 133 +++++++++++++++++++++++++++------- src/video/x11/SDL_x11sym.h | 2 + 2 files changed, 109 insertions(+), 26 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 176387d9e..d7dfca0f6 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -135,6 +135,7 @@ typedef struct Picture picture; XRenderPictFormat* picture_fmt; int blend_op; + const char* filter; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -376,7 +377,7 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) window->w, window->h); /* Add some blending modes to the list of supported blending modes */ renderer->info.blend_modes |= - (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); + (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK | SDL_BLENDMODE_MOD); /* Create a clip mask that is used for rendering primitives. */ data->stencil = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 8); @@ -924,24 +925,40 @@ 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 - data->blend_op = PictOpSrc; - return 0; + if (renderdata->use_xrender) { + data->blend_op = PictOpSrc; + return 0; + } + case SDL_BLENDMODE_MOD: + if (renderdata->use_xrender) { + data->blend_op = PictOpSrc; + return 0; + } + case SDL_BLENDMODE_MASK: case SDL_BLENDMODE_BLEND: - data->blend_op = PictOpOver; - return 0; + if (renderdata->use_xrender) { + data->blend_op = PictOpOver; + return 0; + } case SDL_BLENDMODE_ADD: - data->blend_op = PictOpAdd; - return 0; + 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 - texture->blendMode = SDL_BLENDMODE_BLEND; - data->blend_op = PictOpOver; + if (renderdata->use_xrender) { + texture->blendMode = SDL_BLENDMODE_BLEND; + data->blend_op = PictOpOver; + } #endif return -1; } @@ -951,6 +968,7 @@ static int X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) { X11_TextureData *data = (X11_TextureData *) texture->driverdata; + X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; switch (texture->scaleMode) { case SDL_TEXTURESCALEMODE_NONE: @@ -960,10 +978,33 @@ X11_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { return 0; } - /* Fall through to unsupported case */ +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (renderdata->use_xrender) { + data->filter = FilterFast; + return 0; + } + case SDL_TEXTURESCALEMODE_SLOW: + if (renderdata->use_xrender) { + data->filter = FilterGood; + return 0; + } + case SDL_TEXTURESCALEMODE_BEST: + if (renderdata->use_xrender) { + data->filter = FilterBest; + return 0; + } +#endif + /* Fall through to unsupported case */ default: SDL_Unsupported(); - texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (renderdata->use_xrender) { + texture->scaleMode = SDL_TEXTURESCALEMODE_FAST; + data->filter = FilterFast; + } + else +#endif + texture->scaleMode = SDL_TEXTURESCALEMODE_NONE; return -1; } return 0; @@ -1054,6 +1095,8 @@ X11_SetDrawBlendMode(SDL_Renderer * renderer) //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; @@ -1114,6 +1157,7 @@ xrenderdrawcolor(SDL_Renderer *renderer) (unsigned short) ((renderer->g / 255.0) * alphad * 0xFFFF); xrender_color.blue = (unsigned short) ((renderer->b / 255.0) * alphad * 0xFFFF); + return xrender_color; } @@ -1167,7 +1211,7 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, renderer->blendMode != SDL_BLENDMODE_ADD && renderer->blendMode != SDL_BLENDMODE_MOD)) { - XSetForeground(data->display, data->stencil_gc, 0x00); + XSetForeground(data->display, data->stencil_gc, 0x00000000); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) { @@ -1279,7 +1323,7 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, drawable = data->stencil; gc = data->stencil_gc; - XSetForeground(data->display, data->stencil_gc, 0x00); + XSetForeground(data->display, data->stencil_gc, 0x00000000); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) XFixesSetGCClipRegion(data->display, data->stencil_gc, @@ -1492,7 +1536,7 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) renderer->blendMode != SDL_BLENDMODE_ADD && renderer->blendMode != SDL_BLENDMODE_MOD)) { - XSetForeground(data->display, data->stencil_gc, 0x00); + XSetForeground(data->display, data->stencil_gc, 0x00000000); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) XFixesSetGCClipRegion(data->display, data->stencil_gc, @@ -1651,16 +1695,35 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, dstrect->y, srcrect->w, srcrect->h); } } - Picture pict; - if(texture->blendMode == SDL_BLENDMODE_NONE) - pict = None; - else - pict = texturedata->picture; + Picture src, mask, dst; + XRenderPictureAttributes attr; + if(texture->blendMode == SDL_BLENDMODE_NONE) { + src = texturedata->picture; + mask = None; + dst = data->drawable_pict; + } + /*else if (texture->blendMode == SDL_BLENDMODE_MOD) { + src = data->drawable_pict; + mask = texturedata->picture; + dst = data->drawable_pict; + attr.alpha_map = mask; + }*/ + else { + src = texturedata->picture; + mask = texturedata->picture; + dst = data->drawable_pict; + } if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) { - XRenderComposite(data->display, texturedata->blend_op, texturedata->picture, - pict, data->drawable_pict, srcrect->x, srcrect->y, - srcrect->x, srcrect->y, dstrect->x, dstrect->y, - srcrect->w, srcrect->h); + /*if (texture->blendMode == SDL_BLENDMODE_MOD) { + attr.component_alpha = True; + XRenderChangePicture(data->display, texturedata->picture, + CPComponentAlpha, &attr); + XRenderChangePicture(data->display, src, CPAlphaMap, &attr); + }*/ + XRenderComposite(data->display, texturedata->blend_op, src, + mask, dst, srcrect->x, srcrect->y, + srcrect->x, srcrect->y, dstrect->x, dstrect->y, + srcrect->w, srcrect->h); } else { double xscale = ((double) dstrect->w) / srcrect->w; double yscale = ((double) dstrect->h) / srcrect->h; @@ -1669,11 +1732,21 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}}; XRenderSetPictureTransform(data->display, texturedata->picture, &xform); + + /*if (texture->blendMode == SDL_BLENDMODE_MOD) { + attr.component_alpha = True; + XRenderChangePicture(data->display, texturedata->picture, + CPComponentAlpha, &attr); + XRenderChangePicture(data->display, src, CPAlphaMap, &attr); + }*/ + + XRenderSetPictureFilter(data->display, texturedata->picture, + texturedata->filter, 0, 0); XRenderComposite(data->display, texturedata->blend_op, - texturedata->picture, pict, data->drawable_pict, - 0, 0, 0, 0, dstrect->x, dstrect->y, - dstrect->w, dstrect->h); + src, mask, dst, + srcrect->x, srcrect->y, srcrect->x, srcrect->y, + dstrect->x, dstrect->y, dstrect->w, dstrect->h); XTransform identity = {{ {XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0)}, @@ -1681,6 +1754,14 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}}; XRenderSetPictureTransform(data->display, texturedata->picture, &identity); } + /*if (renderer->blendMode == SDL_BLENDMODE_MOD) { + attr.component_alpha = False; + XRenderChangePicture(data->display, texturedata->picture, + CPComponentAlpha, &attr); + attr.alpha_map = None; + XRenderChangePicture(data->display, data->drawable_pict, + CPAlphaMap, &attr); + }*/ } else #endif diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index c8256e914..bfd05ce08 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -154,6 +154,7 @@ SDL_X11_SYM(XExtensionErrorHandler,XSetExtensionErrorHandler,(XExtensionErrorHan 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) @@ -252,6 +253,7 @@ SDL_X11_SYM(Picture,XRenderCreateSolidFill,(Display *dpy,const XRenderColor *col 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 From 4b32f5bec5bb7948ef954d633d412ec987e9d1cc Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 21 Jul 2010 17:54:31 +0530 Subject: [PATCH 37/47] Get SDL_BLENDMODE_MOD to work! Tested on nvidia only ATM. --- src/video/x11/SDL_x11render.c | 86 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index d7dfca0f6..f1930169f 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -380,20 +380,20 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK | SDL_BLENDMODE_MOD); /* Create a clip mask that is used for rendering primitives. */ data->stencil = XCreatePixmap(data->display, data->xwindow, - window->w, window->h, 8); + 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, 0x00); - XSetForeground(data->display, data->stencil_gc, 0x00); + 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, 0xFF); + XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF); data->stencil_pict = XRenderCreatePicture(data->display, data->stencil, XRenderFindStandardFormat(data->display, - PictStandardA8), + PictStandardARGB32), 0, NULL); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) { @@ -935,7 +935,7 @@ X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) } case SDL_BLENDMODE_MOD: if (renderdata->use_xrender) { - data->blend_op = PictOpSrc; + data->blend_op = PictOpOver; return 0; } case SDL_BLENDMODE_MASK: @@ -1211,7 +1211,7 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, renderer->blendMode != SDL_BLENDMODE_ADD && renderer->blendMode != SDL_BLENDMODE_MOD)) { - XSetForeground(data->display, data->stencil_gc, 0x00000000); + XSetForeground(data->display, data->stencil_gc, 0); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) { @@ -1229,7 +1229,7 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); } #endif - XSetForeground(data->display, data->stencil_gc, 0xFF); + XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF); XDrawPoints(data->display, data->stencil, data->stencil_gc, xpoints, xcount, CoordModeOrigin); @@ -1323,7 +1323,7 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, drawable = data->stencil; gc = data->stencil_gc; - XSetForeground(data->display, data->stencil_gc, 0x00000000); + XSetForeground(data->display, data->stencil_gc, 0); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) XFixesSetGCClipRegion(data->display, data->stencil_gc, @@ -1336,7 +1336,7 @@ X11_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); #endif - XSetForeground(data->display, data->stencil_gc, 0xFF); + XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF); } else #endif @@ -1536,7 +1536,7 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) renderer->blendMode != SDL_BLENDMODE_ADD && renderer->blendMode != SDL_BLENDMODE_MOD)) { - XSetForeground(data->display, data->stencil_gc, 0x00000000); + XSetForeground(data->display, data->stencil_gc, 0); #ifdef SDL_VIDEO_DRIVER_X11_XDAMAGE if (data->use_xdamage) XFixesSetGCClipRegion(data->display, data->stencil_gc, @@ -1549,7 +1549,7 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) XFixesSetGCClipRegion(data->display, data->stencil_gc, 0, 0, None); #endif - XSetForeground(data->display, data->stencil_gc, 0xFF); + XSetForeground(data->display, data->stencil_gc, 0xFFFFFFFF); XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount); @@ -1695,35 +1695,35 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, dstrect->y, srcrect->w, srcrect->h); } } - Picture src, mask, dst; + Picture mask; XRenderPictureAttributes attr; + const SDL_Rect *mrect; if(texture->blendMode == SDL_BLENDMODE_NONE) { - src = texturedata->picture; mask = None; - dst = data->drawable_pict; + mrect = srcrect; + } + else if (texture->blendMode == SDL_BLENDMODE_MOD) { + mask = data->stencil_pict; + mrect = dstrect; } - /*else if (texture->blendMode == SDL_BLENDMODE_MOD) { - src = data->drawable_pict; - mask = texturedata->picture; - dst = data->drawable_pict; - attr.alpha_map = mask; - }*/ else { - src = texturedata->picture; mask = texturedata->picture; - dst = data->drawable_pict; + mrect = srcrect; } if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) { - /*if (texture->blendMode == SDL_BLENDMODE_MOD) { + if (texture->blendMode == SDL_BLENDMODE_MOD) { + XRenderComposite(data->display, PictOpSrc, data->drawable_pict, + texturedata->picture, 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, texturedata->picture, + XRenderChangePicture(data->display, data->stencil_pict, CPComponentAlpha, &attr); - XRenderChangePicture(data->display, src, CPAlphaMap, &attr); - }*/ - XRenderComposite(data->display, texturedata->blend_op, src, - mask, dst, srcrect->x, srcrect->y, - srcrect->x, srcrect->y, dstrect->x, dstrect->y, - srcrect->w, srcrect->h); + } + XRenderComposite(data->display, texturedata->blend_op, texturedata->picture, + 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; @@ -1733,19 +1733,22 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}}; XRenderSetPictureTransform(data->display, texturedata->picture, &xform); - /*if (texture->blendMode == SDL_BLENDMODE_MOD) { + if (texture->blendMode == SDL_BLENDMODE_MOD) { + XRenderComposite(data->display, PictOpSrc, data->drawable_pict, + texturedata->picture, 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, texturedata->picture, + XRenderChangePicture(data->display, data->stencil_pict, CPComponentAlpha, &attr); - XRenderChangePicture(data->display, src, CPAlphaMap, &attr); - }*/ + } XRenderSetPictureFilter(data->display, texturedata->picture, texturedata->filter, 0, 0); XRenderComposite(data->display, texturedata->blend_op, - src, mask, dst, - srcrect->x, srcrect->y, srcrect->x, srcrect->y, + texturedata->picture, mask, data->drawable_pict, + srcrect->x, srcrect->y, mrect->x, mrect->y, dstrect->x, dstrect->y, dstrect->w, dstrect->h); XTransform identity = {{ @@ -1754,14 +1757,11 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}}; XRenderSetPictureTransform(data->display, texturedata->picture, &identity); } - /*if (renderer->blendMode == SDL_BLENDMODE_MOD) { + if (renderer->blendMode == SDL_BLENDMODE_MOD) { attr.component_alpha = False; - XRenderChangePicture(data->display, texturedata->picture, + XRenderChangePicture(data->display, data->stencil_pict, CPComponentAlpha, &attr); - attr.alpha_map = None; - XRenderChangePicture(data->display, data->drawable_pict, - CPAlphaMap, &attr); - }*/ + } } else #endif From 847d9103f7d153f58b478088725e7a4758a564d7 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 21 Jul 2010 18:33:13 +0530 Subject: [PATCH 38/47] Fix X11_DisplayModeChanged. --- src/video/x11/SDL_x11render.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index f1930169f..e1a7bc699 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -554,11 +554,42 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) #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) { From cee756f9c2624f10f4c3f1612f8c50af602e76c4 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 21 Jul 2010 18:38:40 +0530 Subject: [PATCH 39/47] Fix cleanup functions. --- src/video/x11/SDL_x11render.c | 38 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index e1a7bc699..23dbb854a 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -2040,6 +2040,13 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) shmdt(data->shminfo.shmaddr); data->pixels = NULL; } +#endif +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (renderdata->use_xrender) { + if (data->picture) { + XRenderFreePicture(renderdata->display, data->picture); + } + } #endif if (data->scaling_image) { SDL_free(data->scaling_image->data); @@ -2065,7 +2072,7 @@ X11_DestroyRenderer(SDL_Renderer * renderer) XFreePixmap(data->display, data->pixmaps[i]); } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->pixmap_picts[i] != None) { + if (data->use_xrender && data->pixmap_picts[i]) { XRenderFreePicture(data->display, data->pixmap_picts[i]); } #endif @@ -2074,17 +2081,24 @@ X11_DestroyRenderer(SDL_Renderer * renderer) XFreeGC(data->display, data->gc); } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->stencil_gc) { - XFreeGC(data->display, data->stencil_gc); - } - if (data->stencil) { - XFreePixmap(data->display, data->stencil); - } - if (data->drawable_pict) { - XRenderFreePicture(data->display, data->drawable_pict); - } - if (data->xwindow_pict) { - XRenderFreePicture(data->display, data->xwindow_pict); + 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); From 3d32d9275b93f14c50c5f5b7fae8bafcc7f62370 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 21 Jul 2010 23:08:09 +0530 Subject: [PATCH 40/47] Make the SW renderer work properly by fixing support for textures with no alpha channels. --- src/video/x11/SDL_x11render.c | 193 +++++++++++++++++----------------- 1 file changed, 96 insertions(+), 97 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 23dbb854a..a2ed912ca 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -671,15 +671,20 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER static void SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) { - (*comp) = 0; - (*compMask) = 0; - while(!(sdl_mask & 1)) { - (*comp)++; - sdl_mask >>= 1; - } - while(sdl_mask & 1) { - (*compMask) = ((*compMask) << 1) | 1; - sdl_mask >>= 1; + 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; + } } } @@ -687,13 +692,15 @@ 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; - SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); - + 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 | @@ -706,7 +713,6 @@ PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format) { 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); } @@ -774,37 +780,27 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } data->format = display->current_mode.format; } else { - /* If Xrender support is builtin we only need to check whether - Xrender is available at runtime. If it is available there - can be no BadMatch error since Xrender takes care of that. - */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (renderdata->use_xrender == SDL_FALSE) { - if (texture->format != display->current_mode.format) { - SDL_SetError("Texture format doesn't match window format"); - return -1; - } - } else { + if (renderdata->use_xrender) + { Uint32 Amask, Rmask, Gmask, Bmask; SDL_PixelFormatEnumToMasks(texture->format, &(data->depth), &Rmask, &Gmask, &Bmask, &Amask); + printf("%d %x %x %x %x\n", data->depth, Rmask, Gmask, Bmask, Amask); data->visual = PixelFormatEnumToVisual(renderer, texture->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. - This BadMatch error - */ - if (texture->format != display->current_mode.format) { - SDL_SetError("Texture format doesn't match window format"); - return -1; - } + 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; @@ -812,45 +808,42 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) shm_error = True; if (SDL_X11_HAVE_SHM) { - shminfo->shmid = - shmget(IPC_PRIVATE, texture->h * data->pitch, - IPC_CREAT | 0777); - if (shminfo->shmid >= 0) { - shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); - shminfo->readOnly = False; - if (shminfo->shmaddr != (char *) -1) { - shm_error = False; - X_handler = XSetErrorHandler(shm_errhandler); - XShmAttach(renderdata->display, shminfo); - XSync(renderdata->display, False); - XSetErrorHandler(X_handler); - if (shm_error) { - shmdt(shminfo->shmaddr); - } - } - shmctl(shminfo->shmid, IPC_RMID, NULL); - } - } - if (!shm_error) { - data->pixels = shminfo->shmaddr; - data->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; - } data->image = XShmCreateImage(renderdata->display, data->visual, - data->depth, ZPixmap, shminfo->shmaddr, + data->depth, ZPixmap, NULL, shminfo, texture->w, texture->h); - - if (!data->image) { - XShmDetach(renderdata->display, shminfo); - XSync(renderdata->display, False); - shmdt(shminfo->shmaddr); - shm_error = True; + if (data->image) { + shminfo->shmid = + shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line, + IPC_CREAT | 0777); + if (shminfo->shmid >= 0) { + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); + shminfo->readOnly = False; + if (shminfo->shmaddr != (char *) -1) { + shm_error = False; + X_handler = XSetErrorHandler(shm_errhandler); + XShmAttach(renderdata->display, shminfo); + XSync(renderdata->display, False); + XSetErrorHandler(X_handler); + if (shm_error) { + XShmDetach(renderdata->display, shminfo); + shmdt(shminfo->shmaddr); + XDestroyImage(data->image); + XSync(renderdata->display, False); + } + else { + data->pixels = data->image->data = shminfo->shmaddr; + shmctl(shminfo->shmid, IPC_RMID, NULL); + data->pixmap = + XCreatePixmap(renderdata->display, renderdata->xwindow, + texture->w, texture->h, data->depth); + if (!data->pixmap) { + SDL_SetError("XCreatePixmap() failed"); + return -1; + } + } + } + } } } if (shm_error) { @@ -859,13 +852,24 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) if (!data->image) #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) { 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); @@ -874,40 +878,32 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_SetError("XCreatePixmap() failed"); return -1; } - data->image = - XCreateImage(renderdata->display, data->visual, - data->depth, ZPixmap, 0, data->pixels, - texture->w, texture->h, - SDL_BYTESPERPIXEL(data->format) * 8, - data->pitch); - if (!data->image) { - X11_DestroyTexture(renderer, texture); - SDL_SetError("XCreateImage() failed"); - return -1; - } } } else { - data->pixmap = - XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, - texture->h, data->depth); - if (data->pixmap == None) { - X11_DestroyTexture(renderer, texture); - SDL_SetError("XCreatePixmap() failed"); - return -1; - } data->image = 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->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; + } } + + data->pitch = data->image->bytes_per_line; + #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(renderdata->use_xrender) { gcv.graphics_exposures = False; @@ -932,6 +928,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_SetError("XRenderCreatePicture() failed"); return -1; } + texture->blendMode = SDL_BLENDMODE_NONE; + data->blend_op = PictOpSrc; } #endif return 0; @@ -1713,7 +1711,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, if(texture->access == SDL_TEXTUREACCESS_STREAMING) { #ifndef NO_SHARED_MEMORY if(texturedata->shminfo.shmaddr) { - XShmPutImage(data->display, texturedata->pixmap, data->gc, + XShmPutImage(data->display, texturedata->pixmap, texturedata->gc, texturedata->image, srcrect->x, srcrect->y, srcrect->x, srcrect->y, srcrect->w, srcrect->h, False); @@ -1721,10 +1719,11 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, else #endif if (texturedata->pixels) { - XPutImage(data->display, texturedata->pixmap, data->gc, - texturedata->image, srcrect->x, srcrect->y, dstrect->x, - dstrect->y, srcrect->w, srcrect->h); + 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 mask; XRenderPictureAttributes attr; From 70c395fd0759d29fc42388965442b726d7e0337d Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 21 Jul 2010 23:18:53 +0530 Subject: [PATCH 41/47] Advertise support for blending modes and scaling modes in the render driver. --- src/video/x11/SDL_x11render.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index a2ed912ca..8e7a1c7ec 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -271,6 +271,10 @@ X11_AddRenderDriver(_THIS) int major, minor; if (CheckXRender(data->display, &major, &minor)) { info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_ARGB8888; + 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); } #endif @@ -378,6 +382,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) /* Add some blending modes to the list of supported blending modes */ renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK | SDL_BLENDMODE_MOD); + renderer->info.scale_modes |= + (SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST); /* Create a clip mask that is used for rendering primitives. */ data->stencil = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 32); From 392e02d3fd3572f775129e5aee2524a7e6f619f3 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Thu, 22 Jul 2010 10:53:41 +0530 Subject: [PATCH 42/47] Advertise support for all supported texture formats. --- include/SDL_video.h | 2 +- src/video/x11/SDL_x11render.c | 46 +++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index a0db406cd..6cdafd073 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -190,7 +190,7 @@ typedef struct SDL_RendererInfo Uint32 blend_modes; /**< A mask of supported blend modes */ Uint32 scale_modes; /**< A mask of supported scale modes */ Uint32 num_texture_formats; /**< The number of available texture formats */ - Uint32 texture_formats[20]; /**< The available texture formats */ + Uint32 texture_formats[50]; /**< The available texture formats */ int max_texture_width; /**< The maximimum texture width */ int max_texture_height; /**< The maximimum texture height */ } SDL_RendererInfo; diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 8e7a1c7ec..2554429ab 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -252,6 +252,28 @@ CheckXDamage(Display *display, int *major, int *minor) { } #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) { @@ -270,7 +292,23 @@ X11_AddRenderDriver(_THIS) #ifdef SDL_VIDEO_DRIVER_X11_XRENDER int major, minor; if (CheckXRender(data->display, &major, &minor)) { - info->texture_formats[info->num_texture_formats++] = SDL_PIXELFORMAT_ARGB8888; + 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 | @@ -379,11 +417,6 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) 0, 0, 0, 0, window->w, window->h); - /* Add some blending modes to the list of supported blending modes */ - renderer->info.blend_modes |= - (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK | SDL_BLENDMODE_MOD); - renderer->info.scale_modes |= - (SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST); /* Create a clip mask that is used for rendering primitives. */ data->stencil = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 32); @@ -422,7 +455,6 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) data->blend_op = PictOpOver; } #endif - if (flags & SDL_RENDERER_SINGLEBUFFER) { renderer->info.flags |= (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY); From 60b694500c7a1e5c3b13f30b179ff7fb52d61b4e Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Thu, 22 Jul 2010 11:55:32 +0530 Subject: [PATCH 43/47] Remove debugging code. --- src/video/x11/SDL_x11render.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 2554429ab..804f6af73 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -824,7 +824,6 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) Uint32 Amask, Rmask, Gmask, Bmask; SDL_PixelFormatEnumToMasks(texture->format, &(data->depth), &Rmask, &Gmask, &Bmask, &Amask); - printf("%d %x %x %x %x\n", data->depth, Rmask, Gmask, Bmask, Amask); data->visual = PixelFormatEnumToVisual(renderer, texture->format); } else From 6a3c35594ed799083a7024ecafd2bdfe54667769 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Thu, 22 Jul 2010 12:08:33 +0530 Subject: [PATCH 44/47] Code cleanup. --- src/video/x11/SDL_x11render.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 804f6af73..d4bc9c9c9 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1000,10 +1000,6 @@ X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) return 0; } case SDL_BLENDMODE_MOD: - if (renderdata->use_xrender) { - data->blend_op = PictOpOver; - return 0; - } case SDL_BLENDMODE_MASK: case SDL_BLENDMODE_BLEND: if (renderdata->use_xrender) { @@ -1765,15 +1761,18 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, Picture mask; XRenderPictureAttributes attr; const SDL_Rect *mrect; - if(texture->blendMode == SDL_BLENDMODE_NONE) { + if(texture->blendMode == SDL_BLENDMODE_NONE) + { mask = None; mrect = srcrect; } - else if (texture->blendMode == SDL_BLENDMODE_MOD) { + else if (texture->blendMode == SDL_BLENDMODE_MOD) + { mask = data->stencil_pict; - mrect = dstrect; + mrect = dstrect; } - else { + else + { mask = texturedata->picture; mrect = srcrect; } From acbcfe0fdc430013c5b3dc9cec676e7c7d5b8e7a Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Thu, 22 Jul 2010 16:00:18 +0530 Subject: [PATCH 45/47] Fixed drawing rectangles. X is evil! --- src/video/x11/SDL_x11render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index d4bc9c9c9..12b7fc69d 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1582,8 +1582,8 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) xrect->x = (short)rect.x; xrect->y = (short)rect.y; - xrect->width = (unsigned short)rect.w; - xrect->height = (unsigned short)rect.h; + xrect->width = (unsigned short)rect.w - 1; + xrect->height = (unsigned short)rect.h - 1; ++xrect; ++xcount; From 7b8568287060c8e226fdd3560a5dfca894feabb5 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 28 Jul 2010 11:56:17 +0530 Subject: [PATCH 46/47] Add support for texture modulation (both color and alpha). testsprite2 works now with --cyclealpha and --cyclecolor. --- src/video/x11/SDL_x11render.c | 158 ++++++++++++++++++++++++++++------ 1 file changed, 131 insertions(+), 27 deletions(-) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 12b7fc69d..30a89cc75 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -39,6 +39,8 @@ static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); static int X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, void **pixels, int *pitch); +static int X11_SetTextureRGBAMod(SDL_Renderer * renderer, + SDL_Texture * texture); static int X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture); static int X11_SetTextureScaleMode(SDL_Renderer * renderer, @@ -133,6 +135,8 @@ typedef struct 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; @@ -309,10 +313,11 @@ X11_AddRenderDriver(_THIS) else break; } - info->blend_modes = (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | + info->blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD | SDL_BLENDMODE_MASK); - info->scale_modes = (SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_SLOW | + info->scale_modes |= (SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST); + info->mod_modes |= (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA); } #endif @@ -357,6 +362,8 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) 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; @@ -788,6 +795,23 @@ PixelFormatEnumToVisual(SDL_Renderer * renderer, Uint32 format) { 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 @@ -965,6 +989,22 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * 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; } @@ -987,6 +1027,63 @@ 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; + + if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) { + a = texture->a; + } + + if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { + r = texture->r; + g = texture->g; + b = texture->b; + } + + 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); + } + + XRenderPictureAttributes attr; + if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { + attr.component_alpha = True; + XRenderChangePicture(renderdata->display, renderdata->brush_pict, + CPComponentAlpha, &attr); + } + + 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); + } + + 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) { @@ -1203,23 +1300,15 @@ renderdrawcolor(SDL_Renderer * renderer, int premult) static XRenderColor xrenderdrawcolor(SDL_Renderer *renderer) { - // Premultiply the color channels as well as modulate them to a 16 bit color space XRenderColor xrender_color; - double alphad; - if(renderer->blendMode == SDL_BLENDMODE_NONE) - alphad = 1.0; - else - alphad = (renderer->a) / 255.0; - - xrender_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); - - xrender_color.red = - (unsigned short) ((renderer->r / 255.0) * alphad * 0xFFFF); - xrender_color.green = - (unsigned short) ((renderer->g / 255.0) * alphad * 0xFFFF); - xrender_color.blue = - (unsigned short) ((renderer->b / 255.0) * alphad * 0xFFFF); - + 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; } @@ -1758,9 +1847,17 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, } XSync(data->display, False); } - Picture mask; + 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; @@ -1776,18 +1873,19 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 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, - texturedata->picture, data->stencil_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, texturedata->picture, - mask, data->drawable_pict, srcrect->x, srcrect->y, + 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 { @@ -1797,11 +1895,11 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}}; - XRenderSetPictureTransform(data->display, texturedata->picture, &xform); + XRenderSetPictureTransform(data->display, src, &xform); if (texture->blendMode == SDL_BLENDMODE_MOD) { XRenderComposite(data->display, PictOpSrc, data->drawable_pict, - texturedata->picture, data->stencil_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; @@ -1809,11 +1907,11 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, CPComponentAlpha, &attr); } - XRenderSetPictureFilter(data->display, texturedata->picture, + XRenderSetPictureFilter(data->display, src, texturedata->filter, 0, 0); XRenderComposite(data->display, texturedata->blend_op, - texturedata->picture, mask, data->drawable_pict, + src, mask, data->drawable_pict, srcrect->x, srcrect->y, mrect->x, mrect->y, dstrect->x, dstrect->y, dstrect->w, dstrect->h); @@ -1821,7 +1919,7 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, {XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}}; - XRenderSetPictureTransform(data->display, texturedata->picture, &identity); + XRenderSetPictureTransform(data->display, src, &identity); } if (renderer->blendMode == SDL_BLENDMODE_MOD) { attr.component_alpha = False; @@ -2081,6 +2179,12 @@ X11_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 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) { From c6dd7560cac891bbd6cc5021f709ab14d2a82750 Mon Sep 17 00:00:00 2001 From: Sunny Sachanandani Date: Wed, 28 Jul 2010 13:08:14 +0530 Subject: [PATCH 47/47] Add some comments. --- src/video/x11/SDL_x11render.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/video/x11/SDL_x11render.c b/src/video/x11/SDL_x11render.c index 30a89cc75..135c7e6e4 100644 --- a/src/video/x11/SDL_x11render.c +++ b/src/video/x11/SDL_x11render.c @@ -1038,16 +1038,19 @@ X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture) 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); @@ -1056,6 +1059,8 @@ X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture) 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; @@ -1063,6 +1068,8 @@ X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture) 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, @@ -1070,6 +1077,8 @@ X11_SetTextureRGBAMod(SDL_Renderer * renderer, SDL_Texture * texture) 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,