From 7551aa6dd90084c25591762677a09de59a4f311e 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 d5fe34e303302ec276ae83ae907c52e2e872191c 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 b88a72e77499a0af6d0c8c3d93e517c4911acef1 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 e049cc403a22ec8882f934d5298ed7ae2f9a5c35 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 e9e630c7e012a9c5fae64ab32c6fb379b30d0fc1 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 ab9cb8143c89f867c442cd7d3b921337bd541cf1 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 503af03024fd8dcc05d4bc78790ce815298472ca 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 bc6683eed7dd2139d84cf0adde3bcf1e5354d4e8 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 e07a3ef80cd8316c58a830c3e81db03611517d44 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 6b6045f23699e066d529fd88f8ccc36b9d2e60f6 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 0ed5e533143af9e6bf5971da324aee30cd8bc304 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 e51d41dac5b78a5326c63a73016afc4ed01d1af0 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 a067ba2b4f83d0e1fdf5946845d9ba0031cb6497 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 64241e79567f0569943c24ea411eb1e2b5362a97 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 5725c792310184c339ef3de9e665d46b7b9d4de6 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 | 266 +++++++++++++++++++++------------- 1 file changed, 165 insertions(+), 101 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; + 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; - 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); + 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; - - if (data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &rect); - } - } - 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); + 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; } - else + 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(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 7da64e5b57fcd5ccd71c5fc96e6101fde06a6872 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 ed2719210f1ec449755b6e26f81e8b2b79aa5546 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 | 270 ++++++++++++++++++---------------- 1 file changed, 147 insertions(+), 123 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, 1); + XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 0);*/ + data->picture_fmt = + 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 +#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 { + 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 #endif - if (texturedata->pixels) { - XPutImage(data->display, data->drawable, data->gc, - texturedata->image, srcrect->x, srcrect->y, dstrect->x, - dstrect->y, srcrect->w, srcrect->h); + { + if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { +#ifndef NO_SHARED_MEMORY + if (texturedata->shminfo.shmaddr) { + XShmPutImage(data->display, data->drawable, data->gc, + texturedata->image, srcrect->x, srcrect->y, + dstrect->x, dstrect->y, srcrect->w, srcrect->h, + False); + } else +#endif + if (texturedata->pixels) { + XPutImage(data->display, data->drawable, data->gc, + texturedata->image, srcrect->x, srcrect->y, dstrect->x, + dstrect->y, srcrect->w, srcrect->h); + } else { + XCopyArea(data->display, texturedata->pixmap, data->drawable, + data->gc, srcrect->x, srcrect->y, dstrect->w, + dstrect->h, dstrect->x, dstrect->y); + } + } else if (texturedata->yuv + || texture->access == SDL_TEXTUREACCESS_STREAMING) { + SDL_Surface src, dst; + SDL_PixelFormat fmt; + SDL_Rect rect; + XImage *image = texturedata->scaling_image; + + if (!image) { + void *pixels; + int pitch; + + pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format); + pixels = SDL_malloc(dstrect->h * pitch); + if (!pixels) { + SDL_OutOfMemory(); + return -1; + } + + image = + XCreateImage(data->display, data->visual, data->depth, + ZPixmap, 0, pixels, dstrect->w, dstrect->h, + SDL_BYTESPERPIXEL(texturedata->format) * 8, + pitch); + if (!image) { + SDL_SetError("XCreateImage() failed"); + return -1; + } + texturedata->scaling_image = image; + + } else if (image->width != dstrect->w || image->height != dstrect->h + || !image->data) { + image->width = dstrect->w; + image->height = dstrect->h; + image->bytes_per_line = + image->width * SDL_BYTESPERPIXEL(texturedata->format); + image->data = + (char *) SDL_realloc(image->data, + image->height * image->bytes_per_line); + if (!image->data) { + SDL_OutOfMemory(); + return -1; + } + } + + /* Set up fake surfaces for SDL_SoftStretch() */ + SDL_zero(src); + src.format = &fmt; + src.w = texture->w; + src.h = texture->h; +#ifndef NO_SHARED_MEMORY + if (texturedata->shminfo.shmaddr) { + src.pixels = texturedata->shminfo.shmaddr; + } else +#endif + src.pixels = texturedata->pixels; + src.pitch = texturedata->pitch; + + SDL_zero(dst); + dst.format = &fmt; + dst.w = image->width; + dst.h = image->height; + dst.pixels = image->data; + dst.pitch = image->bytes_per_line; + + fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format); + + rect.x = 0; + rect.y = 0; + rect.w = dstrect->w; + rect.h = dstrect->h; + if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) { + return -1; + } + 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, dstrect->x, dstrect->y); + data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h, + srcrect->x, srcrect->y); } - } else if (texturedata->yuv - || texture->access == SDL_TEXTUREACCESS_STREAMING) { - SDL_Surface src, dst; - SDL_PixelFormat fmt; - SDL_Rect rect; - XImage *image = texturedata->scaling_image; - - if (!image) { - void *pixels; - int pitch; - - pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format); - pixels = SDL_malloc(dstrect->h * pitch); - if (!pixels) { - SDL_OutOfMemory(); - return -1; - } - - image = - XCreateImage(data->display, data->visual, data->depth, - ZPixmap, 0, pixels, dstrect->w, dstrect->h, - SDL_BYTESPERPIXEL(texturedata->format) * 8, - pitch); - if (!image) { - SDL_SetError("XCreateImage() failed"); - return -1; - } - texturedata->scaling_image = image; - - } else if (image->width != dstrect->w || image->height != dstrect->h - || !image->data) { - image->width = dstrect->w; - image->height = dstrect->h; - image->bytes_per_line = - image->width * SDL_BYTESPERPIXEL(texturedata->format); - image->data = - (char *) SDL_realloc(image->data, - image->height * image->bytes_per_line); - if (!image->data) { - SDL_OutOfMemory(); - return -1; - } - } - - /* Set up fake surfaces for SDL_SoftStretch() */ - SDL_zero(src); - src.format = &fmt; - src.w = texture->w; - src.h = texture->h; -#ifndef NO_SHARED_MEMORY - if (texturedata->shminfo.shmaddr) { - src.pixels = texturedata->shminfo.shmaddr; - } else -#endif - src.pixels = texturedata->pixels; - src.pitch = texturedata->pitch; - - SDL_zero(dst); - dst.format = &fmt; - dst.w = image->width; - dst.h = image->height; - dst.pixels = image->data; - dst.pitch = image->bytes_per_line; - - fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format); - - rect.x = 0; - rect.y = 0; - rect.w = dstrect->w; - rect.h = dstrect->h; - if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) { - return -1; - } - 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 e076e2d536b88b34a5e5f312e542e16f08d92999 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 12efdd0c9a16e386675677a8d95596358a3068f0 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 adb7883461c0c95ed8bccb05587783d13c36d331 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 737d17d1a93efea825d29af9473a52a0fdd829e9 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 | 133 +++++++++++++++++++--------------- src/video/x11/SDL_x11window.c | 3 + 3 files changed, 97 insertions(+), 63 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,38 +215,7 @@ 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->use_xrender = SDL_TRUE; - data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); - if(!data->xwindow_pict_fmt) { - data->use_xrender = SDL_FALSE; - goto fallback; - } - 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; - } - // 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->use_xrender = SDL_FALSE; - } - fallback: -#endif + renderer->DisplayModeChanged = X11_DisplayModeChanged; renderer->CreateTexture = X11_CreateTexture; renderer->QueryTexturePixels = X11_QueryTexturePixels; @@ -272,6 +241,43 @@ 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->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, + 0, NULL); + if(!data->xwindow_pict) { + 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); + 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); + renderer->blendMode = SDL_BLENDMODE_BLEND; + data->blend_op = PictOpOver; + } + else { + data->use_xrender = SDL_FALSE; + } + fallback: +#endif + 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; - return 0; - case SDL_BLENDMODE_ADD: // PictOpAdd - data->blend_op = PictOpAdd; - return 0; case SDL_BLENDMODE_BLEND: // PictOpOver data->blend_op = PictOpOver; return 0; + case SDL_BLENDMODE_ADD: // PictOpAdd + data->blend_op = PictOpAdd; + return 0; /* FIXME case SDL_BLENDMODE_MOD: */ #endif return 0; default: SDL_Unsupported(); - renderer->blendMode = SDL_BLENDMODE_NONE; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - 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 be82664fd222268058b2116b836bb22cca68fe48 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 fe5dc5364e7500881bba7345605dd64be5d64701 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 39bc51bc48ab6a0e00241f7b572eb128b62adc98 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 2e46009f819dacd080e37885eeedd7847269d2c2 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 03538d7a6ece1dc34031994761f6b542cb24eace 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 70b00cda4c0642ae9643de822cfca635fbd7ba03 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 666481e9a917504afe9acc4fcc0a7c2b35bee30d 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. --HG-- branch : experimental --- src/SDL_error.c | 2 + src/video/x11/SDL_x11render.c | 571 +++++++++++++++++++--------------- src/video/x11/SDL_x11sym.h | 2 + 3 files changed, 329 insertions(+), 246 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; + clip.x = 0; + clip.y = 0; + clip.w = window->w; + clip.h = window->h; - /* 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; +#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 +#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_DrawLines(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 { - drawable = data->drawable; - gc = data->gc; - } - - foreground = renderdrawcolor(renderer, 1); - XSetForeground(data->display, data->gc, foreground); - - xpoint = xpoints = SDL_stack_alloc(XPoint, count); - xcount = 0; - minx = INT_MAX; - miny = INT_MAX; - maxx = INT_MIN; - maxy = INT_MIN; - for (i = 0; i < count; ++i) { - int x = points[i].x; - int y = points[i].y; - - /* If the point is inside the window, add it to the list */ - if (x >= 0 && x < window->w && y >= 0 && y < window->h) { - if (x < minx) { - minx = x; - } else if (x > maxx) { - maxx = x; - } - if (y < miny) { - miny = y; - } else if (y > maxy) { - maxy = y; - } - xpoint->x = (short)x; - xpoint->y = (short)y; - ++xpoint; - ++xcount; - continue; + Pixmap drawable; + GC gc; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + 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; } - XDrawLines(data->display, drawable, gc, - xpoints, xcount, CoordModeOrigin); + + /* We need to clip the line segments joined by this point */ + if (xcount > 0) { + int x1 = xpoint[-1].x; + int y1 = xpoint[-1].y; + int x2 = x; + int y2 = y; + if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { + if (x2 < minx) { + minx = x2; + } else if (x2 > maxx) { + maxx = x2; + } + if (y2 < miny) { + miny = y2; + } else if (y2 > maxy) { + maxy = y2; + } + xpoint->x = (short)x2; + xpoint->y = (short)y2; + ++xpoint; + ++xcount; + } + XDrawLines(data->display, drawable, gc, + xpoints, xcount, CoordModeOrigin); + if (xpoints[0].x != x2 || xpoints[0].y != y2) { + XDrawPoint(data->display, drawable, gc, x2, y2); + } + if (data->makedirty) { + SDL_Rect rect; + + rect.x = minx; + rect.y = miny; + rect.w = (maxx - minx) + 1; + rect.h = (maxy - miny) + 1; + SDL_AddDirtyRect(&data->dirty, &rect); + } + xpoint = xpoints; + xcount = 0; + minx = INT_MAX; + miny = INT_MAX; + maxx = INT_MIN; + maxy = INT_MIN; + } + if (i < (count-1)) { + int x1 = x; + int y1 = y; + int x2 = points[i+1].x; + int y2 = points[i+1].y; + if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) { + if (x1 < minx) { + minx = x1; + } else if (x1 > maxx) { + maxx = x1; + } + if (y1 < miny) { + miny = y1; + } else if (y1 > maxy) { + maxy = y1; + } + xpoint->x = (short)x1; + xpoint->y = (short)y1; + ++xpoint; + ++xcount; + } + } + } + if (xcount > 1) { + int x2 = xpoint[-1].x; + int y2 = xpoint[-1].y; + XDrawLines(data->display, drawable, gc, xpoints, xcount, + CoordModeOrigin); if (xpoints[0].x != x2 || xpoints[0].y != y2) { XDrawPoint(data->display, 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; - } - - 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) { +#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_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); + } + 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) { + 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; - XRenderPictureAttributes attributes; - unsigned long valuemask; - 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 0d8e74ac5a8e0f41c7feeb6ab179b5cde01140da 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 1662c33408f95b65f3d9d47958c6c4dfb2c4c9de 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 72f6c2402629bbdb51edf9fa45e81955813f9686 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 93948935c43f83b665bab227a6c5bc93b046c87d 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 c19650cfdf59191b5c757667d6ab62d698d2eb52 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 51b997ebadc8954e542d4dad542b7d7ffe073468 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 b496cf65508adf69992a6684d6e65cc1e56408b7 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 bed6ddfa0000ed17d8c491245bea72d69305ecb8 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 b478f42ed4d7a7acd200b50fa78b3abbf275a0aa 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 74aebea86f393ffe891639b1ea6e895293b1c562 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 96abad3e25c3aaa78a54f83246aed5ca7b6b3b72 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 1b6afb37014cb51ff48da93908346b654e154edc 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 | 197 +++++++++++++++++----------------- 1 file changed, 98 insertions(+), 99 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,20 +878,20 @@ 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->image = + XCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, 0, NULL, + texture->w, texture->h, + SDL_BYTESPERPIXEL(data->format) * 8, + 0); + if (!data->image) { + X11_DestroyTexture(renderer, texture); + SDL_SetError("XCreateImage() failed"); + return -1; + } data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, texture->h, data->depth); @@ -896,18 +900,10 @@ 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, NULL, - texture->w, texture->h, - SDL_BYTESPERPIXEL(data->format) * 8, - data->pitch); - if (!data->image) { - X11_DestroyTexture(renderer, texture); - SDL_SetError("XCreateImage() 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 47341645ba8fe8c28acb4c3a0699b119ad0e568b 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 2fcfc81241a7f97328a22f39b8b98b4d213d121e 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 5e60ceaa97430b374acf87d5762187d13780e975 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 29c1c990d14a2bc587e4e3e3c25a8dbfcade75a3 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 1d826dcfadd656aa46a80b5f6e8e7b12d9471794 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 2e3071de9013d203dd1ba589fbcf11815a704dd6 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 f8e9cd32ad8e5c028659c6c199d1a6f99b5f0bba 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,