Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11render.c @ 4597:95be206b3cb7 experimental
Start experimental branch for client-side rasterization.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Sun, 18 Jul 2010 12:43:04 +0530 |
parents | dc26c37ad70e |
children | 66e13a224bd6 |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11render.c Sun Jul 18 08:28:35 2010 +0530 +++ b/src/video/x11/SDL_x11render.c Sun Jul 18 12:43:04 2010 +0530 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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; + +#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); - /* 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; + 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 @@ CoordModeOrigin); } } + SDL_stack_free(xpoints); return 0; @@ -1089,81 +1157,141 @@ 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); - 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 + 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 @@ 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 @@ 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); + + XRenderFillRectangle(data->display, PictOpSrc, data->brush_pict, + &foreground, 0, 0, 1, 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); + 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 @@ 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 @@ } #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 @@ } SDL_stack_free(xrects); - return 0; } @@ -1726,11 +1805,11 @@ 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);