Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Fix the rendering color channels to be premultiplied with the alpha c…
Browse files Browse the repository at this point in the history
…hannel as thats what Xrender expects. Small fixes in X11_CreateTexture. Add some new functions in SDL_x11sym.h as well as support for Xrender.
  • Loading branch information
sunnyps committed Jun 2, 2010
1 parent 83d8810 commit 181aeda
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/video/x11/SDL_x11dyn.h
Expand Up @@ -53,7 +53,7 @@
#endif

#if SDL_VIDEO_DRIVER_X11_XRENDER
#include <X11/extensions/render.h>
#include <X11/extensions/Xrender.h>
#endif

/*
Expand Down
137 changes: 85 additions & 52 deletions src/video/x11/SDL_x11render.c
Expand Up @@ -473,7 +473,13 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
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);
Expand All @@ -486,6 +492,14 @@ 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);
Expand All @@ -505,7 +519,8 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
return -1;
}
}
} else {
}
else {
data->pixmap =
XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
texture->h, renderdata->depth);
Expand All @@ -514,61 +529,60 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
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);
SDL_SetError("XCreateImage() failed");
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;
}

Expand Down Expand Up @@ -638,6 +652,7 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
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;
Expand All @@ -652,6 +667,23 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
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;
Expand Down Expand Up @@ -1001,10 +1033,11 @@ X11_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
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);
}
Expand Down
11 changes: 11 additions & 0 deletions src/video/x11/SDL_x11sym.h
Expand Up @@ -177,6 +177,7 @@ SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b),(a,b),return)
SDL_X11_SYM(Status,XShmDetach,(Display* a,XShmSegmentInfo* b),(a,b),return)
SDL_X11_SYM(Status,XShmPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j,Bool k),(a,b,c,d,e,f,g,h,i,j,k),return)
SDL_X11_SYM(XImage*,XShmCreateImage,(Display* a,Visual* b,unsigned int c,int d,char* e,XShmSegmentInfo* f,unsigned int g,unsigned int h),(a,b,c,d,e,f,g,h),return)
SDL_X11_SYM(Pixmap,XShmCreatePixmap,(Display *a,Drawable b,char* c,XShmSegmentInfo* d, unsigned int e, unsigned int f, unsigned int g),(a,b,c,d,e,f,g),return)
SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return)
#endif

Expand Down Expand Up @@ -232,6 +233,16 @@ SDL_X11_SYM(Status,XScreenSaverQueryVersion,(Display *dpy,int *major_versionp,in
SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),return)
#endif

/* XRender support */
#if SDL_VIDEO_DRIVER_X11_XRENDER
SDL_X11_MODULE(XRENDER)
SDL_X11_SYM(Bool,XRenderQueryExtension,(Display *dpy,int *event_base,int *error_base),(dpy,event_base,error_base),return)
SDL_X11_SYM(XRenderPictFormat*,XRenderFindVisualFormat,(Display *dpy,_Xconst Visual *visual),(dpy,visual),return)
SDL_X11_SYM(XRenderPictFormat*,XRenderFindFormat,(Display *dpy,unsigned long mask,_Xconst XRenderPictFormat* templ,int count),(dpy,mask,templ,count),return)
SDL_X11_SYM(Picture,XRenderCreatePicture,(Display *dpy,Drawable drawable,_Xconst XRenderPictFormat* format,unsigned long valuemask,_Xconst XRenderPictureAttributes* attributes),(dpy,drawable,format,valuemask,attributes),return)
SDL_X11_SYM(void,XRenderComposite,(Display *dpy,int op,Picture src,Picture mask,Picture dst,int src_x,int src_y,int mask_x,int mask_y,int dst_x,int dst_y,unsigned int width,unsigned int height),(dpy,op,src,mask,dst,src_x,src_y,mask_x,mask_y,dst_x,dst_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* */

/* vi: set ts=4 sw=4 expandtab: */
3 changes: 1 addition & 2 deletions src/video/x11/SDL_x11video.h
Expand Up @@ -46,9 +46,8 @@
#include <X11/extensions/scrnsaver.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XRENDER
#include <X11/extensions/render.h>
#include <X11/extensions/Xrender.h>
#endif

#include "SDL_x11dyn.h"

#include "SDL_x11events.h"
Expand Down

0 comments on commit 181aeda

Please sign in to comment.