Start experimental branch for client-side rasterization.

--HG--
branch : experimental
This commit is contained in:
Sunny Sachanandani 2010-07-18 12:43:04 +05:30
parent 7c46b950ed
commit 6a534a4046
3 changed files with 329 additions and 246 deletions

View file

@ -38,6 +38,8 @@ extern SDL_error *SDL_GetErrBuf(void);
#define SDL_ERRBUFIZE 1024
#define DEBUG_ERROR
/* Private functions */
static const char *

View file

@ -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");
}
XSetBackground(data->display, data->mask_gc, 0);
XSetForeground(data->display, data->mask_gc, 1);
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;
}
#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,9 +1053,28 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
SDL_Window *window = renderer->window;
XPoint *xpoints, *xpoint;
int i, xcount;
SDL_Rect clip, rect;
clip.x = 0;
clip.y = 0;
clip.w = window->w;
clip.h = window->h;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
#ifndef NO_SHARED_MEMORY
if (data->use_xrender && data->stencil_image && data->stencil_surface) {
SDL_FillRect(data->stencil_surface, NULL, 0x00);
SDL_SetClipRect(data->stencil_surface, NULL);
SDL_DrawPoints(data->stencil_surface, points, count, 0xFF);
XShmPutImage(data->display, data->stencil, data->stencil_gc, data->stencil_image,
0, 0, 0, 0, window->w, window->h, False);
} else
#endif
#endif
{
if (data->makedirty) {
SDL_Rect rect;
/* Get the smallest rectangle that contains everything */
rect.x = 0;
@ -1029,31 +1102,25 @@ X11_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
++xcount;
}
#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;
XSetForeground(data->display, data->mask_gc, 0);
XFillRectangle(data->display, data->mask, data->mask_gc,
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->mask_gc, 1);
XDrawPoints(data->display, data->mask, data->mask_gc, xpoints, xcount,
XSetForeground(data->display, data->stencil_gc, 0xFF);
XDrawPoints(data->display, data->stencil, data->stencil_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);
}
#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);
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,17 +1157,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
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
{
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,
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->mask_gc, 1);
XSetForeground(data->display, data->stencil_gc, 0xFF);
}
else
#endif
@ -1224,17 +1305,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) {
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,6 +1337,22 @@ X11_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
clip.w = window->w;
clip.h = window->h;
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
#ifndef NO_SHARED_MEMORY
if (data->use_xrender && data->stencil_image && data->stencil_surface) {
SDL_FillRect(data->stencil_surface, NULL, 0x00);
SDL_SetClipRect(data->stencil_surface, NULL);
SDL_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;
@ -1274,28 +1369,28 @@ 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 == SDL_TRUE) {
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,
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->mask_gc, 1);
XSetForeground(data->display, data->stencil_gc, 0xFF);
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);
XDrawRectangles(data->display, data->stencil, data->stencil_gc, xrects, xcount);
}
#endif
}
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if (data->use_xrender) {
XRenderColor foreground;
foreground = xrenderdrawcolor(renderer);
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
@ -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);

View file

@ -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* */