Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11render.c @ 4593:3892fe2f6537
Fixed so many things. See the changelog listed below.
1. Use SDL_X11_HAVE_XRENDER to check for RENDER at runtime.
2. Added lots of comments.
3. Added checks and lots of calls to SDL_SetError().
4. Fixed X11_CreateTexture() so that the pixmap and image created
are for the format specified by the user and not the window
format. This is only for the RENDER case.
5. The above change required that functions to convert SDL
pixel format enums to Visuals and XRenderPictFormats be added.
6. Fixed lots of 'style' issues.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Sat, 17 Jul 2010 15:38:24 +0530 |
parents | 1e998db9b597 |
children | f28c23cc1a08 |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11render.c Sat Jul 17 11:41:43 2010 +0530 +++ b/src/video/x11/SDL_x11render.c Sat Jul 17 15:38:24 2010 +0530 @@ -120,6 +120,9 @@ SDL_SW_YUVTexture *yuv; Uint32 format; Pixmap pixmap; + int depth; + Visual *visual; + GC gc; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture picture; XRenderPictFormat* picture_fmt; @@ -243,17 +246,32 @@ renderer->info.flags = SDL_RENDERER_ACCELERATED; #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - int event_basep, error_basep; - if(XRenderQueryExtension(data->display, - &event_basep, - &error_basep) == True) { - data->use_xrender = SDL_TRUE; + data->use_xrender = SDL_FALSE; + if (SDL_X11_HAVE_XRENDER) { + // Query the extension. This is the server runtime check. + int event_basep, error_basep; + if(XRenderQueryExtension(data->display, + &event_basep, &error_basep) == True) + data->use_xrender = SDL_TRUE; + } + if (data->use_xrender) { + // Find the PictFormat from the visual. + // Should be an RGB PictFormat most of the time. data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, data->visual); + if (!data->xwindow_pict_fmt) { + SDL_SetError("XRenderFindVisualFormat() failed"); + return NULL; + } data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, 0, NULL); + if (!data->xwindow_pict) { + SDL_SetError("XRenderCreatePicture() failed"); + return NULL; + } + // FIXME: Clear the window. Is this required? XRenderComposite(data->display, PictOpClear, data->xwindow_pict, @@ -263,27 +281,39 @@ 0, 0, 0, 0, window->w, window->h); + // Add some blending modes to the list of supported blending modes renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); - // Create a 1 bit depth 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->mask_pict = XRenderCreatePicture(data->display, data->mask, XRenderFindStandardFormat(data->display, PictStandardA1), 0, NULL); + if (!data->mask_pict) { + SDL_SetError("XRenderCreatePicture() failed"); + return NULL; + } + // Create the GC for the clip mask. XGCValues gcv_mask; gcv_mask.foreground = 1; gcv_mask.background = 0; data->mask_gc = XCreateGC(data->display, data->mask, GCBackground | GCForeground, &gcv_mask); + if (!data->mask_gc) { + SDL_SetError("XCreateGC() failed"); + return NULL; + } + // Set the default blending mode. renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; } - else { - data->use_xrender = SDL_FALSE; - } #endif if (flags & SDL_RENDERER_SINGLEBUFFER) { @@ -322,23 +352,29 @@ return NULL; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { + if (data->use_xrender) { + // Create xrender pictures for each of the pixmaps + // and clear the pixmaps. data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], XRenderFindStandardFormat(data->display, PictStandardARGB32), 0, None); - XRenderComposite(data->display, - PictOpClear, - data->pixmap_picts[i], - None, - data->pixmap_picts[i], - 0, 0, - 0, 0, - 0, 0, - window->w, window->h); + if (!data->pixmap_picts[i]) { + SDL_SetError("XRenderCreatePicture() failed"); + return NULL; + } + XRenderComposite(data->display, + PictOpClear, + data->pixmap_picts[i], + None, + data->pixmap_picts[i], + 0, 0, + 0, 0, + 0, 0, + window->w, window->h); } #endif } @@ -429,13 +465,17 @@ return -1; } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(data->use_xrender == SDL_TRUE) { + if (data->use_xrender) { data->pixmap_picts[i] = XRenderCreatePicture(data->display, data->pixmaps[i], XRenderFindStandardFormat(data->display, PictStandardARGB32), 0, None); + if (!data->pixmap_picts[i]) { + SDL_SetError("XRenderCreatePicture() failed"); + return -1; + } XRenderComposite(data->display, PictOpClear, data->pixmap_picts[i], @@ -460,6 +500,84 @@ return 0; } +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER +static void +SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) { + (*comp) = 0; + (*compMask) = 0; + while(!(sdl_mask & 1)) { + (*comp)++; + sdl_mask >>= 1; + } + while(sdl_mask & 1) { + (*compMask) = ((*compMask) << 1) | 1; + sdl_mask >>= 1; + } +} + +static XRenderPictFormat* +PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format) { + XRenderPictFormat* pict_fmt = NULL; + X11_RenderData *data = (X11_RenderData *) renderer->driverdata; + + if (data->use_xrender) { + + int bpp; + Uint32 Amask, Rmask, Gmask, Bmask; + SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + + XRenderPictFormat templ; + unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed | + PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | + PictFormatBlue | PictFormatBlueMask | PictFormatAlpha | + PictFormatAlphaMask); + + templ.type = PictTypeDirect; + templ.depth = bpp; + SDLMaskToXRenderMask(Amask, &(templ.direct.alpha), &(templ.direct.alphaMask)); + SDLMaskToXRenderMask(Rmask, &(templ.direct.red), &(templ.direct.redMask)); + SDLMaskToXRenderMask(Gmask, &(templ.direct.green), &(templ.direct.greenMask)); + SDLMaskToXRenderMask(Bmask, &(templ.direct.blue), &(templ.direct.blueMask)); + + pict_fmt = XRenderFindFormat(data->display, mask, &templ, 0); + } + + return pict_fmt; +} + + +static Visual* +PixelFormatEnumToVisual(SDL_Renderer * renderer, Uint32 format) { + X11_RenderData *data = (X11_RenderData *) renderer->driverdata; + + if (data->use_xrender) { + int bpp; + Uint32 Amask, Rmask, Gmask, Bmask; + SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + + XVisualInfo vinfo_templ; + long vinfo_mask; + int nitems_return; + + vinfo_mask = (VisualDepthMask | VisualRedMaskMask | + VisualGreenMaskMask | VisualBlueMaskMask); + vinfo_templ.depth = bpp; + vinfo_templ.red_mask = Rmask; + vinfo_templ.green_mask = Gmask; + vinfo_templ.blue_mask = Bmask; + + XVisualInfo * ret = XGetVisualInfo(data->display, vinfo_mask, + &vinfo_templ, &nitems_return); + + if (nitems_return) { + return ret[0].visual; + } + } + + return NULL; +} +#endif + static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -468,12 +586,16 @@ SDL_VideoDisplay *display = window->display; X11_TextureData *data; int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); - + XGCValues gcv; + data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } + data->depth = renderdata->depth; + data->visual = renderdata->visual; + data->gc = renderdata->gc; texture->driverdata = data; if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { @@ -494,6 +616,11 @@ SDL_SetError("Texture format doesn't match window format"); return -1; } + } else { + Uint32 Amask, Rmask, Gmask, Bmask; + SDL_PixelFormatEnumToMasks(texture->format, &(data->depth), + &Rmask, &Gmask, &Bmask, &Amask); + data->visual = PixelFormatEnumToVisual(renderer, texture->format); } #else /* The image/pixmap depth must be the same as the window or you @@ -540,16 +667,15 @@ data->pixels = shminfo->shmaddr; data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, - texture->h, renderdata->depth); + texture->h, data->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreatePixmap() failed"); return -1; } - data->image = - XShmCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, shminfo->shmaddr, + XShmCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); if (!data->image) { @@ -582,15 +708,15 @@ data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, - texture->h, renderdata->depth); + texture->h, data->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreatePixmap() failed"); return -1; } data->image = - XCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, 0, data->pixels, + XCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, 0, data->pixels, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); @@ -604,15 +730,15 @@ else { data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, - texture->h, renderdata->depth); + texture->h, data->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreatePixmap() failed"); return -1; } data->image = - XCreateImage(renderdata->display, renderdata->visual, - renderdata->depth, ZPixmap, 0, NULL, + XCreateImage(renderdata->display, data->visual, + data->depth, ZPixmap, 0, NULL, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); @@ -624,21 +750,29 @@ } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(renderdata->use_xrender) { - data->picture_fmt = renderdata->xwindow_pict_fmt; + gcv.graphics_exposures = False; + data->gc = + XCreateGC(renderdata->display, data->pixmap, GCGraphicsExposures, &gcv); + if (!data->gc) { + SDL_SetError("XCreateGC() failed"); + return -1; + } + data->picture_fmt = + PixelFormatEnumToXRenderPictFormat(renderer, texture->format); + if (data->picture_fmt == NULL) { + X11_DestroyTexture(renderer, texture); + SDL_SetError("Texture format not supported by driver"); + return -1; + } data->picture = XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, 0, NULL); - } - /* 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 when - rendering using the old pipeline. - if(data->use_xrender == SDL_FALSE) { - if (texture->format != display->current_mode.format) { - SDL_SetError("Texture format doesn't match window format"); + if (!data->picture) { + X11_DestroyTexture(renderer, texture); + SDL_SetError("XRenderCreatePicture() failed"); return -1; } - }*/ + } #endif return 0; } @@ -742,7 +876,7 @@ data->image->height = rect->h; data->image->data = (char *) pixels; data->image->bytes_per_line = pitch; - XPutImage(renderdata->display, data->pixmap, renderdata->gc, + XPutImage(renderdata->display, data->pixmap, data->gc, data->image, 0, 0, rect->x, rect->y, rect->w, rect->h); } return 0; @@ -913,6 +1047,10 @@ XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &foreground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); @@ -1097,6 +1235,10 @@ unsigned long valuemask = CPClipMask; XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &xrforeground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; @@ -1158,6 +1300,10 @@ XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); Picture fill = XRenderCreateSolidFill(data->display, &foreground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; @@ -1229,13 +1375,17 @@ xrects, xcount); XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - Picture fill_pict = XRenderCreateSolidFill(data->display, - &foreground); - XRenderComposite(data->display, data->blend_op, fill_pict, None, + Picture fill = XRenderCreateSolidFill(data->display, + &foreground); + if (!fill) { + SDL_SetError("XRenderCreateSolidFill() failed"); + return -1; + } + XRenderComposite(data->display, data->blend_op, fill, None, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); - XRenderFreePicture(data->display, fill_pict); + XRenderFreePicture(data->display, fill); } else #endif @@ -1293,27 +1443,45 @@ srcrect->x, srcrect->y, dstrect->x, dstrect->y, srcrect->w, srcrect->h); } else { - Pixmap scaling_pixmap = + /*Pixmap scaling_pixmap = XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h, data->depth); + if (!scaling_pixmap) { + SDL_SetError("XCreatePixmap() failed"); + return -1; + } Picture scaling_picture = XRenderCreatePicture(data->display, scaling_pixmap, texturedata->picture_fmt, 0, NULL); + if (!scaling_picture) { + SDL_SetError("XRenderCreatePicture() failed"); + return -1; + } 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, pict, scaling_picture, - srcrect->x, srcrect->y, 0, 0, 0, 0, srcrect->w, srcrect->h); + 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, texturedata->blend_op, 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); + XTransform xform = {{ + {XDoubleToFixed(xscale), XDoubleToFixed(0), XDoubleToFixed(0)}, + {XDoubleToFixed(0), XDoubleToFixed(yscale), XDoubleToFixed(0)}, + {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(xscale * yscale)}}}; + XRenderSetPictureTransform(data->display, texturedata->picture, &xform); + + XRenderComposite(data->display, texturedata->blend_op, + texturedata->picture, None, data->drawable_pict, + 0, 0, 0, 0, dstrect->x, dstrect->y, + dstrect->w, dstrect->h); + + XTransform identity = {{ + {XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0)}, + {XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0)}, + {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)}}}; + XRenderSetPictureTransform(data->display, texturedata->picture, &identity); + + /*XRenderFreePicture(data->display, scaling_picture); + XFreePixmap(data->display, scaling_pixmap);*/ } } else