Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11render.c @ 4603:dffa432f0e2b
Massive speed-up. Fixed the format that is set for the renderer. Included runtime checks for XDamage.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Mon, 19 Jul 2010 18:57:02 +0530 |
parents | 4fbf64d504cf |
children | d7535d7a40ea |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11render.c Mon Jul 19 17:46:37 2010 +0530 +++ b/src/video/x11/SDL_x11render.c Mon Jul 19 18:57:02 2010 +0530 @@ -34,6 +34,8 @@ #include <X11/extensions/Xdamage.h> #include <X11/extensions/Xfixes.h> +#define SDL_VIDEO_DRIVER_X11_XDAMAGE + /* X11 renderer implementation */ static SDL_Renderer *X11_CreateRenderer(SDL_Window * window, Uint32 flags); @@ -108,12 +110,16 @@ 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; SDL_PixelFormat format; @@ -255,16 +261,35 @@ #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 @@ 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 @@ 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 @@ 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 @@ } #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 @@ } 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 @@ 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 @@ } #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 @@ int i, xcount; int minx, miny; int maxx, maxy; - XserverRegion parts; - Damage damage; clip.x = 0; clip.y = 0; @@ -1118,17 +1210,29 @@ 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 @@ } } #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 @@ 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;