Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11render.c @ 4591:1e998db9b597
Implement blending modes for textures. Fix off-screen pixmaps to be ARGB rather than RGB to enable blending across frames. Clear the screen and off-screen pixmaps when the renderer is created.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Wed, 14 Jul 2010 19:17:11 +0530 |
parents | 1ad70fb49fcb |
children | 3892fe2f6537 |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11render.c Fri Jul 09 21:36:41 2010 +0530 +++ b/src/video/x11/SDL_x11render.c Wed Jul 14 19:17:11 2010 +0530 @@ -123,7 +123,8 @@ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER Picture picture; XRenderPictFormat* picture_fmt; - SDL_bool use_xrender; + int blend_op; +// SDL_bool use_xrender; #endif XImage *image; #ifndef NO_SHARED_MEMORY @@ -243,39 +244,46 @@ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER int event_basep, error_basep; - if(XRenderQueryExtension(data->display, &event_basep, &error_basep) == True) { + if(XRenderQueryExtension(data->display, + &event_basep, + &error_basep) == True) { data->use_xrender = SDL_TRUE; - data->xwindow_pict_fmt = XRenderFindStandardFormat(data->display, PictStandardARGB32); - if(!data->xwindow_pict_fmt) { - data->use_xrender = SDL_FALSE; - goto fallback; - } - data->xwindow_pict = XRenderCreatePicture(data->display, data->xwindow, data->xwindow_pict_fmt, + data->xwindow_pict_fmt = XRenderFindVisualFormat(data->display, + data->visual); + data->xwindow_pict = XRenderCreatePicture(data->display, + data->xwindow, + data->xwindow_pict_fmt, 0, NULL); - if(!data->xwindow_pict) { - data->use_xrender = SDL_FALSE; - goto fallback; - } + XRenderComposite(data->display, + PictOpClear, + data->xwindow_pict, + None, + data->xwindow_pict, + 0, 0, + 0, 0, + 0, 0, + window->w, window->h); renderer->info.blend_modes |= (SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MASK); // Create a 1 bit depth mask data->mask = XCreatePixmap(data->display, data->xwindow, window->w, window->h, 1); - data->mask_pict = XRenderCreatePicture(data->display, data->mask, - XRenderFindStandardFormat(data->display, - PictStandardA1), - 0, NULL); + data->mask_pict = + XRenderCreatePicture(data->display, data->mask, + XRenderFindStandardFormat(data->display, + PictStandardA1), + 0, NULL); XGCValues gcv_mask; gcv_mask.foreground = 1; gcv_mask.background = 0; - data->mask_gc = XCreateGC(data->display, data->mask, GCBackground | GCForeground, &gcv_mask); + data->mask_gc = XCreateGC(data->display, data->mask, + GCBackground | GCForeground, &gcv_mask); renderer->blendMode = SDL_BLENDMODE_BLEND; data->blend_op = PictOpOver; } else { data->use_xrender = SDL_FALSE; } - fallback: #endif if (flags & SDL_RENDERER_SINGLEBUFFER) { @@ -293,9 +301,21 @@ n = 1; } for (i = 0; i < n; ++i) { - data->pixmaps[i] = - XCreatePixmap(data->display, data->xwindow, window->w, window->h, - displaydata->depth); +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + data->pixmaps[i] = XCreatePixmap(data->display, + data->xwindow, + window->w, + window->h, + 32); + } + else +#endif + { + data->pixmaps[i] = + XCreatePixmap(data->display, data->xwindow, window->w, window->h, + displaydata->depth); + } if (data->pixmaps[i] == None) { X11_DestroyRenderer(renderer); SDL_SetError("XCreatePixmap() failed"); @@ -304,14 +324,21 @@ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { data->pixmap_picts[i] = - XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, + XRenderCreatePicture(data->display, + data->pixmaps[i], + XRenderFindStandardFormat(data->display, + PictStandardARGB32), 0, None); - if(!data->pixmap_picts[i]) { - data->use_xrender = SDL_FALSE; - } - XRenderComposite(data->display, PictOpClear, - data->pixmap_picts[i], None, data->pixmap_picts[i], - 0, 0, 0, 0, 0, 0, window->w, window->h); + XRenderComposite(data->display, + PictOpClear, + data->pixmap_picts[i], + None, + data->pixmap_picts[i], + 0, 0, + 0, 0, + 0, 0, + window->w, window->h); + } #endif } @@ -381,9 +408,22 @@ } } for (i = 0; i < n; ++i) { - data->pixmaps[i] = - XCreatePixmap(data->display, data->xwindow, window->w, window->h, - data->depth); +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + if (data->use_xrender) { + data->pixmaps[i] = + XCreatePixmap(data->display, + data->xwindow, + window->w, + window->h, + 32); + } + else +#endif + { + data->pixmaps[i] = + XCreatePixmap(data->display, data->xwindow, window->w, window->h, + data->depth); + } if (data->pixmaps[i] == None) { SDL_SetError("XCreatePixmap() failed"); return -1; @@ -391,15 +431,22 @@ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { data->pixmap_picts[i] = - XRenderCreatePicture(data->display, data->pixmaps[i], data->xwindow_pict_fmt, + XRenderCreatePicture(data->display, + data->pixmaps[i], + XRenderFindStandardFormat(data->display, + PictStandardARGB32), 0, None); - if(!data->pixmap_picts[i]) { - data->use_xrender = SDL_FALSE; - } - XRenderComposite(data->display, PictOpClear, - data->pixmap_picts[i], None, data->pixmap_picts[i], - 0, 0, 0, 0, 0, 0, window->w, window->h); - } + XRenderComposite(data->display, + PictOpClear, + data->pixmap_picts[i], + None, + data->pixmap_picts[i], + 0, 0, + 0, 0, + 0, 0, + window->w, window->h); + + } #endif } if (n > 0) { @@ -442,8 +489,6 @@ can be no BadMatch error since Xrender takes care of that. */ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - // Assume the texture is supported by Xrender - data->use_xrender = SDL_TRUE; if (renderdata->use_xrender == SDL_FALSE) { if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); @@ -578,32 +623,22 @@ } } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if(renderdata->use_xrender && data->pixmap) { - data->use_xrender = SDL_TRUE; - data->picture_fmt = - XRenderFindVisualFormat(renderdata->display, renderdata->visual); - if(!data->picture_fmt) { - printf("XRenderFindFormat failed!\n"); - data->use_xrender = SDL_FALSE; - } + if(renderdata->use_xrender) { + data->picture_fmt = renderdata->xwindow_pict_fmt; data->picture = XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt, 0, NULL); - if(!data->picture) { - data->use_xrender = 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 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"); return -1; } - } + }*/ #endif return 0; } @@ -626,12 +661,26 @@ static int X11_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) { + X11_TextureData *data = (X11_TextureData *) texture->driverdata; switch (texture->blendMode) { case SDL_BLENDMODE_NONE: +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + data->blend_op = PictOpSrc; return 0; + case SDL_BLENDMODE_BLEND: + data->blend_op = PictOpOver; + return 0; + case SDL_BLENDMODE_ADD: + data->blend_op = PictOpAdd; + return 0; +#endif default: SDL_Unsupported(); texture->blendMode = SDL_BLENDMODE_NONE; +#ifdef SDL_VIDEO_DRIVER_X11_XRENDER + texture->blendMode = SDL_BLENDMODE_BLEND; + data->blend_op = PictOpOver; +#endif return -1; } } @@ -795,7 +844,7 @@ else alphad = (renderer->a) / 255.0; - xrender_color.alpha = (unsigned short) (alphad * 0xFFFF); + xrender_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); xrender_color.red = (unsigned short) ((renderer->r / 255.0) * alphad * 0xFFFF); @@ -1170,10 +1219,8 @@ if(data->use_xrender == SDL_TRUE) { XRenderColor foreground; XRenderPictureAttributes attributes; - unsigned long valuemask; foreground = xrenderdrawcolor(renderer); - valuemask = CPClipMask; attributes.clip_mask = data->mask; XRenderComposite(data->display, PictOpClear, data->mask_pict, None, data->mask_pict, @@ -1181,15 +1228,14 @@ XFillRectangles(data->display, data->mask, data->mask_gc, xrects, xcount); - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - - Picture fill = - XRenderCreateSolidFill(data->display, &foreground); - XRenderComposite(data->display, data->blend_op, fill, data->mask_pict, + XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); + Picture fill_pict = XRenderCreateSolidFill(data->display, + &foreground); + XRenderComposite(data->display, data->blend_op, fill_pict, None, data->drawable_pict, 0, 0, 0, 0, 0, 0, window->w, window->h); attributes.clip_mask = None; - XRenderChangePicture(data->display, data->drawable_pict, valuemask, &attributes); - XRenderFreePicture(data->display, fill); + XRenderChangePicture(data->display, data->drawable_pict, CPClipMask, &attributes); + XRenderFreePicture(data->display, fill_pict); } else #endif @@ -1219,7 +1265,7 @@ SDL_AddDirtyRect(&data->dirty, dstrect); } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER - if (data->use_xrender && texturedata->use_xrender) { + if (data->use_xrender) { if(texture->access == SDL_TEXTUREACCESS_STREAMING) { #ifndef NO_SHARED_MEMORY if(texturedata->shminfo.shmaddr) { @@ -1236,9 +1282,16 @@ dstrect->y, srcrect->w, srcrect->h); } } + Picture pict; + if(texture->blendMode == SDL_BLENDMODE_NONE) + pict = None; + else + pict = texturedata->picture; if(srcrect->w == dstrect->w && srcrect->h == dstrect->h) { - XRenderComposite(data->display, PictOpOver, texturedata->picture, None, data->drawable_pict, - srcrect->x, srcrect->y, 0, 0, dstrect->x, dstrect->y, srcrect->w, srcrect->h); + XRenderComposite(data->display, texturedata->blend_op, texturedata->picture, + pict, data->drawable_pict, srcrect->x, srcrect->y, + srcrect->x, srcrect->y, dstrect->x, dstrect->y, + srcrect->w, srcrect->h); } else { Pixmap scaling_pixmap = XCreatePixmap(data->display, texturedata->pixmap, dstrect->w, dstrect->h, @@ -1248,7 +1301,7 @@ 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, + XRenderComposite(data->display, PictOpSrc, texturedata->picture, pict, 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; @@ -1257,7 +1310,7 @@ {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, + 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); @@ -1445,9 +1498,15 @@ #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if(data->use_xrender == SDL_TRUE) { - XRenderComposite(data->display, PictOpOver, data->drawable_pict, None, - data->xwindow_pict, rect->x, rect->y, 0, 0, rect->x, rect->y, - rect->w+1, rect->h+1); + XRenderComposite(data->display, + data->blend_op, + data->drawable_pict, + None, + data->xwindow_pict, + rect->x, rect->y, + 0, 0, + rect->x, rect->y, + rect->w, rect->h); } else #endif @@ -1536,12 +1595,9 @@ if (data->gc) { XFreeGC(data->display, data->gc); } - if (data->drawable) { - XFreePixmap(data->display, data->drawable); - } #ifdef SDL_VIDEO_DRIVER_X11_XRENDER if (data->mask_gc) { - XFreeGC(data->display, data->gc); + XFreeGC(data->display, data->mask_gc); } if (data->mask_pict) { XRenderFreePicture(data->display, data->mask_pict);