Commit bc858ad7 authored by Sunny Sachanandani's avatar Sunny Sachanandani

X11_RenderFillRects and X11_RenderDrawRects use a server side mask pixmap of 1...

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.
parent 843724af
/* /*
SDL - Simple DirectMedia Layer SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga Copyright (C) 1997-2010 Sam Lantinga
...@@ -96,13 +97,14 @@ typedef struct ...@@ -96,13 +97,14 @@ typedef struct
Window xwindow; Window xwindow;
Pixmap pixmaps[3]; Pixmap pixmaps[3];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
Pixmap mask;
Picture xwindow_pict; Picture xwindow_pict;
Picture pixmap_picts[3]; Picture pixmap_picts[3];
Picture drawable_pict; Picture drawable_pict;
Picture mask_pict;
XRenderPictFormat* xwindow_pict_fmt; XRenderPictFormat* xwindow_pict_fmt;
XRenderPictureAttributes xwindow_pict_attr; GC mask_gc;
unsigned int xwindow_pict_attr_valuemask; SDL_bool use_xrender;
SDL_bool xrender_available;
#endif #endif
int current_pixmap; int current_pixmap;
Drawable drawable; Drawable drawable;
...@@ -122,7 +124,7 @@ typedef struct ...@@ -122,7 +124,7 @@ typedef struct
XRenderPictFormat* picture_fmt; XRenderPictFormat* picture_fmt;
XRenderPictureAttributes picture_attr; XRenderPictureAttributes picture_attr;
unsigned int picture_attr_valuemask; unsigned int picture_attr_valuemask;
SDL_bool xrender_available; SDL_bool use_xrender;
#endif #endif
XImage *image; XImage *image;
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY
...@@ -217,20 +219,32 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -217,20 +219,32 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
int event_basep, error_basep; int event_basep, error_basep;
if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { 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); data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual);
if(!data->xwindow_pict_fmt) { 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, data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt,
0, None); 0, NULL);
if(!data->xwindow_pict) { 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 { else {
data->xrender_available = SDL_FALSE; data->use_xrender = SDL_FALSE;
} }
fallback:
#endif #endif
renderer->DisplayModeChanged = X11_DisplayModeChanged; renderer->DisplayModeChanged = X11_DisplayModeChanged;
renderer->CreateTexture = X11_CreateTexture; renderer->CreateTexture = X11_CreateTexture;
...@@ -281,12 +295,12 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -281,12 +295,12 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
return NULL; return NULL;
} }
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->xrender_available == SDL_TRUE) { if(data->use_xrender == SDL_TRUE) {
data->pixmap_picts[i] = data->pixmap_picts[i] =
XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt,
0, None); 0, None);
if(!data->pixmap_picts[i]) { 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], XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i],
0, 0, 0, 0, 0, 0, window->w, window->h); 0, 0, 0, 0, 0, 0, window->w, window->h);
...@@ -296,14 +310,14 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -296,14 +310,14 @@ X11_CreateRenderer(SDL_Window * window, Uint32 flags)
if (n > 0) { if (n > 0) {
data->drawable = data->pixmaps[0]; data->drawable = data->pixmaps[0];
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #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]; data->drawable_pict = data->pixmap_picts[0];
#endif #endif
data->makedirty = SDL_TRUE; data->makedirty = SDL_TRUE;
} else { } else {
data->drawable = data->xwindow; data->drawable = data->xwindow;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->xrender_available == SDL_TRUE) if(data->use_xrender == SDL_TRUE)
data->drawable_pict = data->xwindow_pict; data->drawable_pict = data->xwindow_pict;
#endif #endif
data->makedirty = SDL_FALSE; data->makedirty = SDL_FALSE;
...@@ -367,12 +381,12 @@ X11_DisplayModeChanged(SDL_Renderer * renderer) ...@@ -367,12 +381,12 @@ X11_DisplayModeChanged(SDL_Renderer * renderer)
return -1; return -1;
} }
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->xrender_available == SDL_TRUE) { if(data->use_xrender == SDL_TRUE) {
data->pixmap_picts[i] = data->pixmap_picts[i] =
XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt,
0, None); 0, None);
if(!data->pixmap_picts[i]) { 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], XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], None, data->pixmap_picts[i],
0, 0, 0, 0, 0, 0, window->w, window->h); 0, 0, 0, 0, 0, 0, window->w, window->h);
...@@ -420,8 +434,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -420,8 +434,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
*/ */
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
// Assume the texture is supported by Xrender // Assume the texture is supported by Xrender
data->xrender_available = SDL_TRUE; data->use_xrender = SDL_TRUE;
if(renderdata->xrender_available == SDL_FALSE) { if(renderdata->use_xrender == SDL_FALSE) {
if (texture->format != display->current_mode.format) { if (texture->format != display->current_mode.format) {
SDL_SetError("Texture format doesn't match window format"); SDL_SetError("Texture format doesn't match window format");
return -1; return -1;
...@@ -544,8 +558,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -544,8 +558,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
} }
} }
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(renderdata->xrender_available && data->pixmap) { if(renderdata->use_xrender && data->pixmap) {
data->xrender_available = SDL_TRUE; 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 XRenderPictFormat x11_templ_fmt; // Format template
x11_fmt_mask = x11_fmt_mask =
...@@ -563,7 +577,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -563,7 +577,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
data->picture_fmt = data->picture_fmt =
XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1);
if(!data->picture_fmt) { if(!data->picture_fmt) {
data->xrender_available = SDL_FALSE; data->use_xrender = SDL_FALSE;
} }
data->picture_attr_valuemask = CPGraphicsExposure; data->picture_attr_valuemask = CPGraphicsExposure;
(data->picture_attr).graphics_exposures = False; (data->picture_attr).graphics_exposures = False;
...@@ -571,14 +585,14 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -571,14 +585,14 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt,
data->picture_attr_valuemask, &(data->picture_attr)); data->picture_attr_valuemask, &(data->picture_attr));
if(!data->picture) { 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 /* We thought we could render the texture with Xrender but this was
not possible for some reason. Now we must ensure that texture 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.
*/ */
if(data->xrender_available == SDL_FALSE) { if(data->use_xrender == SDL_FALSE) {
if (texture->format != display->current_mode.format) { if (texture->format != display->current_mode.format) {
SDL_SetError("Texture format doesn't match window format"); SDL_SetError("Texture format doesn't match window format");
return -1; return -1;
...@@ -974,9 +988,8 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -974,9 +988,8 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
X11_RenderData *data = (X11_RenderData *) renderer->driverdata; X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window; SDL_Window *window = renderer->window;
SDL_Rect clip, rect; SDL_Rect clip, rect;
unsigned long foreground;
XRectangle *xrects, *xrect;
int i, xcount; int i, xcount;
XRectangle *xrects, *xrect;
clip.x = 0; clip.x = 0;
clip.y = 0; clip.y = 0;
...@@ -984,47 +997,47 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -984,47 +997,47 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
clip.h = window->h; clip.h = window->h;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(data->xrender_available == SDL_TRUE) { if(data->use_xrender == SDL_TRUE) {
XRenderColor xrender_foreground; XRectangle xclip;
xrender_foreground = xrenderdrawcolor(renderer);
xrects = SDL_stack_alloc(XRectangle, 4*count); xclip.x = (short)clip.x;
xcount = 0; xclip.y = (short)clip.y;
for(i = 0; i < 4*count; i+=4) { xclip.width = (unsigned short)clip.w;
if(!SDL_IntersectRect(rects[i], &clip, &rect)) { xclip.height = (unsigned short)clip.h;
continue;
}
xrects[xcount].x = rect.x; XRenderColor foreground;
xrects[xcount].y = rect.y; foreground = xrenderdrawcolor(renderer);
xrects[xcount].width = 1;
xrects[xcount].height = rect.h; xrect = xrects = SDL_stack_alloc(XRectangle, count);
++xcount; xcount = 0;
xrects[xcount].x = rect.x; for (i = 0; i < count; ++i) {
xrects[xcount].y = rect.y+rect.h; xrect->x = (short)rects[i]->x;
xrects[xcount].width = rect.w; xrect->y = (short)rects[i]->y;
xrects[xcount].height = 1; xrect->width = (unsigned short)rects[i]->w;
++xcount; xrect->height = (unsigned short)rects[i]->h;
xrects[xcount].x = rect.x+rect.w; ++xrect;
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; ++xcount;
if(data->makedirty) {
SDL_AddDirtyRect(&data->dirty, &rect);
} }
if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, &clip);
} }
XRenderFillRectangles(data->display, PictOpOver, data->drawable_pict, XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict,
&xrender_foreground, xrects, xcount); 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 else
#endif #endif
{ {
unsigned long foreground;
foreground = renderdrawcolor(renderer, 1); foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground); XSetForeground(data->display, data->gc, foreground);
...@@ -1062,15 +1075,61 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -1062,15 +1075,61 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
X11_RenderData *data = (X11_RenderData *) renderer->driverdata; X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window; SDL_Window *window = renderer->window;
SDL_Rect clip, rect; SDL_Rect clip, rect;
unsigned long foreground;
XRectangle *xrects, *xrect;
int i, xcount;
clip.x = 0; clip.x = 0;
clip.y = 0; clip.y = 0;
clip.w = window->w; clip.w = window->w;
clip.h = window->h; clip.h = window->h;
int i, xcount;
XRectangle *xrects, *xrect;
xrect = xrects = SDL_stack_alloc(XRectangle, count);
xcount = 0;
#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); foreground = renderdrawcolor(renderer, 1);
XSetForeground(data->display, data->gc, foreground); XSetForeground(data->display, data->gc, foreground);
...@@ -1092,23 +1151,10 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) ...@@ -1092,23 +1151,10 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
SDL_AddDirtyRect(&data->dirty, &rect); 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);
}
else
#endif
{
XFillRectangles(data->display, data->drawable, data->gc, XFillRectangles(data->display, data->drawable, data->gc,
xrects, xcount); xrects, xcount);
SDL_stack_free(xrects);
} }
}
SDL_stack_free(xpoints);
return 0; return 0;
} }
...@@ -1299,10 +1345,10 @@ X11_RenderPresent(SDL_Renderer * renderer) ...@@ -1299,10 +1345,10 @@ X11_RenderPresent(SDL_Renderer * renderer)
for (dirty = data->dirty.list; dirty; dirty = dirty->next) { for (dirty = data->dirty.list; dirty; dirty = dirty->next) {
const SDL_Rect *rect = &dirty->rect; const SDL_Rect *rect = &dirty->rect;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #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, 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 else
#endif #endif
...@@ -1313,13 +1359,6 @@ X11_RenderPresent(SDL_Renderer * renderer) ...@@ -1313,13 +1359,6 @@ X11_RenderPresent(SDL_Renderer * renderer)
} }
} }
SDL_ClearDirtyRects(&data->dirty); 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); XSync(data->display, False);
...@@ -1389,10 +1428,35 @@ X11_DestroyRenderer(SDL_Renderer * renderer) ...@@ -1389,10 +1428,35 @@ X11_DestroyRenderer(SDL_Renderer * renderer)
if (data->pixmaps[i] != None) { if (data->pixmaps[i] != None) {
XFreePixmap(data->display, data->pixmaps[i]); 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) { if (data->gc) {
XFreeGC(data->display, 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_FreeDirtyRects(&data->dirty);
SDL_free(data); SDL_free(data);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment