Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11render.c @ 4584:9907c8cc6015
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.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Mon, 14 Jun 2010 18:22:48 +0530 |
parents | 5c925d4f220f |
children | 21600c6d6445 |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11render.c Tue Jun 08 19:26:32 2010 +0530 +++ b/src/video/x11/SDL_x11render.c Mon Jun 14 18:22:48 2010 +0530 @@ -1,4 +1,5 @@ /* + SDL - Simple DirectMedia Layer Copyright (C) 1997-2010 Sam Lantinga @@ -96,13 +97,14 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ */ #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 @@ } } #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 @@ 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 @@ 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_RenderData *data = (X11_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; SDL_Rect clip, rect; - unsigned long foreground; + int i, xcount; XRectangle *xrects, *xrect; - int i, xcount; - + 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); - } + } + if (data->makedirty) { + SDL_AddDirtyRect(&data->dirty, &clip); } - XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, - &xrender_foreground, xrects, xcount); + 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_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; - } + +#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; - xrect->x = (short)rect.x; - xrect->y = (short)rect.y; - xrect->width = (unsigned short)rect.w; - xrect->height = (unsigned short)rect.h; - ++xrect; - ++xcount; + XRenderColor foreground; + foreground = xrenderdrawcolor(renderer); + + for (i = 0; i < count; ++i) { + xrect->x = (short)rects[i]->x; + xrect->y = (short)rects[i]->y; + xrect->width = (unsigned short)rects[i]->w; + xrect->height = (unsigned short)rects[i]->h; + ++xrect; + ++xcount; + } if (data->makedirty) { - SDL_AddDirtyRect(&data->dirty, &rect); + SDL_AddDirtyRect(&data->dirty, &clip); } + XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XFillRectangles(data->display, data->mask, data->mask_gc, + xrects, xcount); + XRenderSetPictureClipRectangles(data->display, data->drawable_pict, 0, 0, &xclip, 1); + Picture fill = + XRenderCreateSolidFill(data->display, &foreground); + XRenderComposite(data->display, PictOpOver, fill, data->mask_pict, data->drawable_pict, + 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderFreePicture(data->display, fill); + SDL_stack_free(xrects); + } - if (xcount > 0) { -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->xrender_available == SDL_TRUE) - { - XRenderColor xrender_foreground_color; - xrender_foreground_color = xrenderdrawcolor(renderer); - XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, - &xrender_foreground_color, xrects, xcount); + else +#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); + } } - else -#endif - { XFillRectangles(data->display, data->drawable, data->gc, xrects, xcount); - } + SDL_stack_free(xrects); } - SDL_stack_free(xpoints); - + return 0; } @@ -1299,10 +1345,10 @@ 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 @@ } } 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 @@ 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); }