Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11render.c @ 4580:cfea5b007bc7
Fix the rendering color channels to be premultiplied with the alpha channel as thats what Xrender expects. Small fixes in X11_CreateTexture. Add some new functions in SDL_x11sym.h as well as support for Xrender.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Wed, 02 Jun 2010 09:01:37 +0530 |
parents | d490d63bcc5e |
children | ef0aa488fff6 |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11render.c Mon May 31 17:04:20 2010 +0530 +++ b/src/video/x11/SDL_x11render.c Wed Jun 02 09:01:37 2010 +0530 @@ -473,7 +473,13 @@ XShmCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); - if (!data->image) { + + // This Pixmap is used by Xrender + data->pixmap = + XShmCreatePixmap(renderdata->display, renderdata->xwindow, shminfo->shmaddr, + shminfo, texture->w, texture->h, renderdata->depth); + + if (!(data->pixmap && data->image)) { XShmDetach(renderdata->display, shminfo); XSync(renderdata->display, False); shmdt(shminfo->shmaddr); @@ -486,6 +492,14 @@ 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); @@ -505,7 +519,8 @@ return -1; } } - } else { + } + else { data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, texture->h, renderdata->depth); @@ -514,53 +529,11 @@ SDL_SetError("XCreatePixmap() failed"); return -1; } - -#ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(renderdata->xrender_available) { - data->xrender_available = SDL_TRUE; - unsigned long x11_fmt_mask; // Format mask - XRenderPictFormat x11_templ_fmt; // Format template - x11_fmt_mask = - (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask - | PictFormatBlueMask); - Uint32 Rmask, Gmask, Bmask, Amask; - int bpp; - SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); - x11_templ_fmt.depth = bpp; - x11_templ_fmt.direct.redMask = Rmask; - x11_templ_fmt.direct.greenMask = Gmask; - x11_templ_fmt.direct.blueMask = Bmask; - x11_templ_fmt.direct.alphaMask = Amask; - /* Return one matching XRenderPictFormat */ - data->picture_fmt = - XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); - if(!data->picture_fmt) { - data->xrender_available = SDL_FALSE; - } - data->picture_attr_valuemask = CPGraphicsExposure; - (data->picture_attr).graphics_exposures = False; - data->picture = - XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, - data->picture_attr_valuemask, &(data->picture_attr)); - if(!data->picture) { - data->xrender_available = 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 (texture->format != display->current_mode.format) { - SDL_SetError("Texture format doesn't match window format"); - return -1; - } - } -#endif data->image = XCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, 0, NULL, texture->w, - texture->h, SDL_BYTESPERPIXEL(data->format) * 8, + renderdata->depth, ZPixmap, 0, NULL, + texture->w, texture->h, + SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); if (!data->image) { X11_DestroyTexture(renderer, texture); @@ -568,7 +541,48 @@ return -1; } } - +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if(renderdata->xrender_available && data->pixmap) { + data->xrender_available = SDL_TRUE; + unsigned long x11_fmt_mask; // Format mask + XRenderPictFormat x11_templ_fmt; // Format template + x11_fmt_mask = + (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask + | PictFormatBlueMask); + Uint32 Rmask, Gmask, Bmask, Amask; + int bpp; + SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + x11_templ_fmt.depth = bpp; + x11_templ_fmt.direct.redMask = Rmask; + x11_templ_fmt.direct.greenMask = Gmask; + x11_templ_fmt.direct.blueMask = Bmask; + x11_templ_fmt.direct.alphaMask = Amask; + /* Return one matching XRenderPictFormat */ + data->picture_fmt = + XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); + if(!data->picture_fmt) { + data->xrender_available = SDL_FALSE; + } + data->picture_attr_valuemask = CPGraphicsExposure; + (data->picture_attr).graphics_exposures = False; + data->picture = + XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, + data->picture_attr_valuemask, &(data->picture_attr)); + if(!data->picture) { + data->xrender_available = 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 (texture->format != display->current_mode.format) { + SDL_SetError("Texture format doesn't match window format"); + return -1; + } + } +#endif return 0; } @@ -638,6 +652,7 @@ X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; if (data->pixels) { + // If we have already allocated memory or were given memory by XShm Uint8 *src, *dst; int row; size_t length; @@ -652,6 +667,23 @@ src += pitch; dst += data->pitch; } + /* If this is a static texture we would use Xrender for it + but this requires that the server side Pixmap associated + with this texture be updated with the data as well and + that the pixmap is not a shared memory pixmap. + Hopefully the user will not update static textures so + frequently as to cause a slowdown. + */ + if (texture->access == SDL_TEXTUREACCESS_STATIC) { +#ifndef NO_SHARED_MEMORY + if(!data->shminfo.shmaddr) +#endif + { + XPutImage(renderdata->display, data->pixmap, renderdata->gc, + data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); + } + } + } else { data->image->width = rect->w; data->image->height = rect->h; @@ -1001,10 +1033,11 @@ if(data->xrender_available == SDL_TRUE) { XRenderColor xrender_foreground_color; - xrender_foreground_color.red = (unsigned short) ((renderer->r / 255.0) * 0xFFFF); - xrender_foreground_color.green = (unsigned short) ((renderer->g / 255.0) * 0xFFFF); - xrender_foreground_color.blue = (unsigned short) ((renderer->b / 255.0) * 0xFFFF); - xrender_foreground_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); + // Premultiply the color channels as well as modulate them to a 16 bit color space + xrender_foreground_color.red = ((unsigned short)renderer->r + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1; + xrender_foreground_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1; XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, &xrender_foreground_color, xrects, xcount); }