Commit 3782e9a0 authored by Sunny Sachanandani's avatar Sunny Sachanandani

SDL_Textures should work with XRender now provided that the texture format and...

SDL_Textures should work with XRender now provided that the texture format and screen format match. This is only a temporary limitation.
parent f499e5e7
...@@ -122,8 +122,6 @@ typedef struct ...@@ -122,8 +122,6 @@ typedef struct
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
Picture picture; Picture picture;
XRenderPictFormat* picture_fmt; XRenderPictFormat* picture_fmt;
XRenderPictureAttributes picture_attr;
unsigned int picture_attr_valuemask;
SDL_bool use_xrender; SDL_bool use_xrender;
#endif #endif
XImage *image; XImage *image;
...@@ -435,7 +433,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -435,7 +433,7 @@ 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->use_xrender = SDL_TRUE; data->use_xrender = SDL_TRUE;
if(renderdata->use_xrender == 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;
...@@ -490,12 +488,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -490,12 +488,7 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
renderdata->depth, ZPixmap, shminfo->shmaddr, renderdata->depth, ZPixmap, shminfo->shmaddr,
shminfo, texture->w, texture->h); shminfo, texture->w, texture->h);
// This Pixmap is used by Xrender if (!data->image) {
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); XShmDetach(renderdata->display, shminfo);
XSync(renderdata->display, False); XSync(renderdata->display, False);
shmdt(shminfo->shmaddr); shmdt(shminfo->shmaddr);
...@@ -560,37 +553,41 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -560,37 +553,41 @@ X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
#ifdef SDL_VIDEO_DRIVER_X11_XRENDER #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
if(renderdata->use_xrender && data->pixmap) { if(renderdata->use_xrender && data->pixmap) {
data->use_xrender = 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 =
(PictFormatDepth | PictFormatRedMask | PictFormatGreenMask (PictFormatRedMask | PictFormatGreenMask
| PictFormatBlueMask); | PictFormatBlueMask | PictFormatAlphaMask);
Uint32 Rmask, Gmask, Bmask, Amask; Uint32 Rmask, Gmask, Bmask, Amask;
int bpp; int bpp;
SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
x11_templ_fmt.depth = bpp; x11_templ_fmt.depth = bpp;
x11_templ_fmt.direct.redMask = Rmask; x11_templ_fmt.type = PictTypeDirect;
x11_templ_fmt.direct.greenMask = Gmask; x11_templ_fmt.direct.red = Rmask / 0xff;
x11_templ_fmt.direct.blueMask = Bmask; x11_templ_fmt.direct.green = Gmask / 0xff;
x11_templ_fmt.direct.alphaMask = Amask; x11_templ_fmt.direct.blue = Bmask / 0xff;
/* Return one matching XRenderPictFormat */ x11_templ_fmt.direct.alpha = Amask / 0xff;
printf("%d %d %d %d\n", Rmask/0xff, Gmask/0xff, Bmask/0xff, Amask/0xff);
// Return a matching XRenderPictFormat
data->picture_fmt =
XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 0);*/
data->picture_fmt = data->picture_fmt =
XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1); XRenderFindVisualFormat(renderdata->display, renderdata->visual);
if(!data->picture_fmt) { if(!data->picture_fmt) {
printf("XRenderFindFormat failed!\n");
data->use_xrender = SDL_FALSE; data->use_xrender = SDL_FALSE;
} }
data->picture_attr_valuemask = CPGraphicsExposure;
(data->picture_attr).graphics_exposures = False;
data->picture = data->picture =
XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, XRenderCreatePicture(renderdata->display, data->pixmap,
data->picture_attr_valuemask, &(data->picture_attr)); data->picture_fmt, 0, NULL);
if(!data->picture) { if(!data->picture) {
data->use_xrender = 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 when
rendering using the old pipeline.
*/ */
if(data->use_xrender == SDL_FALSE) { if(data->use_xrender == SDL_FALSE) {
if (texture->format != display->current_mode.format) { if (texture->format != display->current_mode.format) {
...@@ -685,19 +682,13 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -685,19 +682,13 @@ X11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
} }
/* If this is a static texture we would use Xrender for it /* If this is a static texture we would use Xrender for it
but this requires that the server side Pixmap associated but this requires that the server side Pixmap associated
with this texture be updated with the data as well and with this texture be updated with the data as well.
that the pixmap is not a shared memory pixmap.
Hopefully the user will not update static textures so Hopefully the user will not update static textures so
frequently as to cause a slowdown. frequently as to cause a slowdown.
*/ */
if (texture->access == SDL_TEXTUREACCESS_STATIC) { if (texture->access == SDL_TEXTUREACCESS_STATIC) {
#ifndef NO_SHARED_MEMORY
if(!data->shminfo.shmaddr)
#endif
{
XPutImage(renderdata->display, data->pixmap, renderdata->gc, XPutImage(renderdata->display, data->pixmap, renderdata->gc,
data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
}
} }
} else { } else {
...@@ -1211,103 +1202,136 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -1211,103 +1202,136 @@ X11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
if (data->makedirty) { if (data->makedirty) {
SDL_AddDirtyRect(&data->dirty, dstrect); SDL_AddDirtyRect(&data->dirty, dstrect);
} }
if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) { #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
#ifndef NO_SHARED_MEMORY if (data->use_xrender && texturedata->use_xrender && texture->access == SDL_TEXTUREACCESS_STATIC) {
if (texturedata->shminfo.shmaddr) { if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
XShmPutImage(data->display, data->drawable, data->gc, XRenderComposite(data->display, PictOpOver, texturedata->picture, None, data->drawable_pict,
texturedata->image, srcrect->x, srcrect->y, srcrect->x, srcrect->y, 0, 0, dstrect->x, dstrect->y, srcrect->w, srcrect->h);
dstrect->x, dstrect->y, srcrect->w, srcrect->h,
False);
} else
#endif
if (texturedata->pixels) {
XPutImage(data->display, data->drawable, data->gc,
texturedata->image, srcrect->x, srcrect->y, dstrect->x,
dstrect->y, srcrect->w, srcrect->h);
} else { } else {
XCopyArea(data->display, texturedata->pixmap, data->drawable, Pixmap scaling_pixmap =
data->gc, srcrect->x, srcrect->y, dstrect->w, XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h,
dstrect->h, dstrect->x, dstrect->y); data->depth);
Picture scaling_picture =
XRenderCreatePicture(data->display, scaling_pixmap, texturedata->picture_fmt,
0, NULL);
XRenderComposite(data->display, PictOpClear, scaling_picture, None, scaling_picture,
0, 0, 0, 0, 0, 0, dstrect->w, dstrect->h);
XRenderComposite(data->display, PictOpSrc, texturedata->picture, None, scaling_picture,
srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h);
double xscale = ((double) dstrect->w) / srcrect->w;
double yscale = ((double) dstrect->h) / srcrect->h;
XTransform xform =
{{{XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)},
{XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}};
XRenderSetPictureTransform(data->display, scaling_picture, &xform);
XRenderComposite(data->display, PictOpOver, scaling_picture, None, data->drawable_pict,
0, 0, 0, 0, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
XRenderFreePicture(data->display, scaling_picture);
XFreePixmap(data->display, scaling_pixmap);
} }
} else if (texturedata->yuv }
|| texture->access == SDL_TEXTUREACCESS_STREAMING) { else
SDL_Surface src, dst; #endif
SDL_PixelFormat fmt; {
SDL_Rect rect; if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
XImage *image = texturedata->scaling_image; #ifndef NO_SHARED_MEMORY
if (texturedata->shminfo.shmaddr) {
if (!image) { XShmPutImage(data->display, data->drawable, data->gc,
void *pixels; texturedata->image, srcrect->x, srcrect->y,
int pitch; dstrect->x, dstrect->y, srcrect->w, srcrect->h,
False);
pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format); } else
pixels = SDL_malloc(dstrect->h * pitch); #endif
if (!pixels) { if (texturedata->pixels) {
SDL_OutOfMemory(); XPutImage(data->display, data->drawable, data->gc,
return -1; texturedata->image, srcrect->x, srcrect->y, dstrect->x,
dstrect->y, srcrect->w, srcrect->h);
} else {
XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w,
dstrect->h, dstrect->x, dstrect->y);
} }
} else if (texturedata->yuv
|| texture->access == SDL_TEXTUREACCESS_STREAMING) {
SDL_Surface src, dst;
SDL_PixelFormat fmt;
SDL_Rect rect;
XImage *image = texturedata->scaling_image;
image =
XCreateImage(data->display, data->visual, data->depth,
ZPixmap, 0, pixels, dstrect->w, dstrect->h,
SDL_BYTESPERPIXEL(texturedata->format) * 8,
pitch);
if (!image) { if (!image) {
SDL_SetError("XCreateImage() failed"); void *pixels;
return -1; int pitch;
}
texturedata->scaling_image = image; pitch = dstrect->w * SDL_BYTESPERPIXEL(texturedata->format);
pixels = SDL_malloc(dstrect->h * pitch);
} else if (image->width != dstrect->w || image->height != dstrect->h if (!pixels) {
|| !image->data) { SDL_OutOfMemory();
image->width = dstrect->w; return -1;
image->height = dstrect->h; }
image->bytes_per_line =
image->width * SDL_BYTESPERPIXEL(texturedata->format); image =
image->data = XCreateImage(data->display, data->visual, data->depth,
(char *) SDL_realloc(image->data, ZPixmap, 0, pixels, dstrect->w, dstrect->h,
image->height * image->bytes_per_line); SDL_BYTESPERPIXEL(texturedata->format) * 8,
if (!image->data) { pitch);
SDL_OutOfMemory(); if (!image) {
return -1; SDL_SetError("XCreateImage() failed");
return -1;
}
texturedata->scaling_image = image;
} else if (image->width != dstrect->w || image->height != dstrect->h
|| !image->data) {
image->width = dstrect->w;
image->height = dstrect->h;
image->bytes_per_line =
image->width * SDL_BYTESPERPIXEL(texturedata->format);
image->data =
(char *) SDL_realloc(image->data,
image->height * image->bytes_per_line);
if (!image->data) {
SDL_OutOfMemory();
return -1;
}
} }
}
/* Set up fake surfaces for SDL_SoftStretch() */ /* Set up fake surfaces for SDL_SoftStretch() */
SDL_zero(src); SDL_zero(src);
src.format = &fmt; src.format = &fmt;
src.w = texture->w; src.w = texture->w;
src.h = texture->h; src.h = texture->h;
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY
if (texturedata->shminfo.shmaddr) { if (texturedata->shminfo.shmaddr) {
src.pixels = texturedata->shminfo.shmaddr; src.pixels = texturedata->shminfo.shmaddr;
} else } else
#endif #endif
src.pixels = texturedata->pixels; src.pixels = texturedata->pixels;
src.pitch = texturedata->pitch; src.pitch = texturedata->pitch;
SDL_zero(dst); SDL_zero(dst);
dst.format = &fmt; dst.format = &fmt;
dst.w = image->width; dst.w = image->width;
dst.h = image->height; dst.h = image->height;
dst.pixels = image->data; dst.pixels = image->data;
dst.pitch = image->bytes_per_line; dst.pitch = image->bytes_per_line;
fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format); fmt.BytesPerPixel = SDL_BYTESPERPIXEL(texturedata->format);
rect.x = 0; rect.x = 0;
rect.y = 0; rect.y = 0;
rect.w = dstrect->w; rect.w = dstrect->w;
rect.h = dstrect->h; rect.h = dstrect->h;
if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) { if (SDL_SoftStretch(&src, srcrect, &dst, &rect) < 0) {
return -1; return -1;
}
XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
} else {
XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
srcrect->x, srcrect->y);
} }
XPutImage(data->display, data->drawable, data->gc, image, 0, 0,
dstrect->x, dstrect->y, dstrect->w, dstrect->h);
} else {
XCopyArea(data->display, texturedata->pixmap, data->drawable,
data->gc, srcrect->x, srcrect->y, dstrect->w, dstrect->h,
srcrect->x, srcrect->y);
} }
return 0; return 0;
} }
......
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