comparison 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
comparison
equal deleted inserted replaced
4579:d490d63bcc5e 4580:cfea5b007bc7
471 471
472 data->image = 472 data->image =
473 XShmCreateImage(renderdata->display, renderdata->visual, 473 XShmCreateImage(renderdata->display, renderdata->visual,
474 renderdata->depth, ZPixmap, shminfo->shmaddr, 474 renderdata->depth, ZPixmap, shminfo->shmaddr,
475 shminfo, texture->w, texture->h); 475 shminfo, texture->w, texture->h);
476 if (!data->image) { 476
477 // This Pixmap is used by Xrender
478 data->pixmap =
479 XShmCreatePixmap(renderdata->display, renderdata->xwindow, shminfo->shmaddr,
480 shminfo, texture->w, texture->h, renderdata->depth);
481
482 if (!(data->pixmap && data->image)) {
477 XShmDetach(renderdata->display, shminfo); 483 XShmDetach(renderdata->display, shminfo);
478 XSync(renderdata->display, False); 484 XSync(renderdata->display, False);
479 shmdt(shminfo->shmaddr); 485 shmdt(shminfo->shmaddr);
480 shm_error = True; 486 shm_error = True;
481 } 487 }
484 shminfo->shmaddr = NULL; 490 shminfo->shmaddr = NULL;
485 } 491 }
486 if (!data->image) 492 if (!data->image)
487 #endif /* not NO_SHARED_MEMORY */ 493 #endif /* not NO_SHARED_MEMORY */
488 { 494 {
495 /* This is the case where the server does not have
496 shared memory support and the texture is streaming.
497 It does not make sense to use Xrender here because
498 we would have to copy the data onto a server side
499 pixmap with XPutImage first and only then can we
500 use Xrender
501 */
502
489 data->pixels = SDL_malloc(texture->h * data->pitch); 503 data->pixels = SDL_malloc(texture->h * data->pitch);
490 if (!data->pixels) { 504 if (!data->pixels) {
491 X11_DestroyTexture(renderer, texture); 505 X11_DestroyTexture(renderer, texture);
492 SDL_OutOfMemory(); 506 SDL_OutOfMemory();
493 return -1; 507 return -1;
503 X11_DestroyTexture(renderer, texture); 517 X11_DestroyTexture(renderer, texture);
504 SDL_SetError("XCreateImage() failed"); 518 SDL_SetError("XCreateImage() failed");
505 return -1; 519 return -1;
506 } 520 }
507 } 521 }
508 } else { 522 }
523 else {
509 data->pixmap = 524 data->pixmap =
510 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, 525 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
511 texture->h, renderdata->depth); 526 texture->h, renderdata->depth);
512 if (data->pixmap == None) { 527 if (data->pixmap == None) {
513 X11_DestroyTexture(renderer, texture); 528 X11_DestroyTexture(renderer, texture);
514 SDL_SetError("XCreatePixmap() failed"); 529 SDL_SetError("XCreatePixmap() failed");
515 return -1; 530 return -1;
516 } 531 }
517
518 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
519 if(renderdata->xrender_available) {
520 data->xrender_available = SDL_TRUE;
521 unsigned long x11_fmt_mask; // Format mask
522 XRenderPictFormat x11_templ_fmt; // Format template
523 x11_fmt_mask =
524 (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask
525 | PictFormatBlueMask);
526 Uint32 Rmask, Gmask, Bmask, Amask;
527 int bpp;
528 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
529 x11_templ_fmt.depth = bpp;
530 x11_templ_fmt.direct.redMask = Rmask;
531 x11_templ_fmt.direct.greenMask = Gmask;
532 x11_templ_fmt.direct.blueMask = Bmask;
533 x11_templ_fmt.direct.alphaMask = Amask;
534 /* Return one matching XRenderPictFormat */
535 data->picture_fmt =
536 XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1);
537 if(!data->picture_fmt) {
538 data->xrender_available = SDL_FALSE;
539 }
540 data->picture_attr_valuemask = CPGraphicsExposure;
541 (data->picture_attr).graphics_exposures = False;
542 data->picture =
543 XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt,
544 data->picture_attr_valuemask, &(data->picture_attr));
545 if(!data->picture) {
546 data->xrender_available = SDL_FALSE;
547 }
548 }
549 /* We thought we could render the texture with Xrender but this was
550 not possible for some reason. Now we must ensure that texture
551 format and window format match to avoid a BadMatch error.
552 */
553 if(data->xrender_available == SDL_FALSE) {
554 if (texture->format != display->current_mode.format) {
555 SDL_SetError("Texture format doesn't match window format");
556 return -1;
557 }
558 }
559 #endif
560 data->image = 532 data->image =
561 XCreateImage(renderdata->display, renderdata->visual, 533 XCreateImage(renderdata->display, renderdata->visual,
562 renderdata->depth, ZPixmap, 0, NULL, texture->w, 534 renderdata->depth, ZPixmap, 0, NULL,
563 texture->h, SDL_BYTESPERPIXEL(data->format) * 8, 535 texture->w, texture->h,
536 SDL_BYTESPERPIXEL(data->format) * 8,
564 data->pitch); 537 data->pitch);
565 if (!data->image) { 538 if (!data->image) {
566 X11_DestroyTexture(renderer, texture); 539 X11_DestroyTexture(renderer, texture);
567 SDL_SetError("XCreateImage() failed"); 540 SDL_SetError("XCreateImage() failed");
568 return -1; 541 return -1;
569 } 542 }
570 } 543 }
571 544 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
545 if(renderdata->xrender_available && data->pixmap) {
546 data->xrender_available = SDL_TRUE;
547 unsigned long x11_fmt_mask; // Format mask
548 XRenderPictFormat x11_templ_fmt; // Format template
549 x11_fmt_mask =
550 (PictFormatDepth | PictFormatRedMask | PictFormatGreenMask
551 | PictFormatBlueMask);
552 Uint32 Rmask, Gmask, Bmask, Amask;
553 int bpp;
554 SDL_PixelFormatEnumToMasks(data->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
555 x11_templ_fmt.depth = bpp;
556 x11_templ_fmt.direct.redMask = Rmask;
557 x11_templ_fmt.direct.greenMask = Gmask;
558 x11_templ_fmt.direct.blueMask = Bmask;
559 x11_templ_fmt.direct.alphaMask = Amask;
560 /* Return one matching XRenderPictFormat */
561 data->picture_fmt =
562 XRenderFindFormat(renderdata->display, x11_fmt_mask, &x11_templ_fmt, 1);
563 if(!data->picture_fmt) {
564 data->xrender_available = SDL_FALSE;
565 }
566 data->picture_attr_valuemask = CPGraphicsExposure;
567 (data->picture_attr).graphics_exposures = False;
568 data->picture =
569 XRenderCreatePicture(renderdata->display, data->pixmap, data->picture_fmt,
570 data->picture_attr_valuemask, &(data->picture_attr));
571 if(!data->picture) {
572 data->xrender_available = SDL_FALSE;
573 }
574 }
575 /* We thought we could render the texture with Xrender but this was
576 not possible for some reason. Now we must ensure that texture
577 format and window format match to avoid a BadMatch error.
578 */
579 if(data->xrender_available == SDL_FALSE) {
580 if (texture->format != display->current_mode.format) {
581 SDL_SetError("Texture format doesn't match window format");
582 return -1;
583 }
584 }
585 #endif
572 return 0; 586 return 0;
573 } 587 }
574 588
575 static int 589 static int
576 X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, 590 X11_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
636 return 0; 650 return 0;
637 } else { 651 } else {
638 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; 652 X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata;
639 653
640 if (data->pixels) { 654 if (data->pixels) {
655 // If we have already allocated memory or were given memory by XShm
641 Uint8 *src, *dst; 656 Uint8 *src, *dst;
642 int row; 657 int row;
643 size_t length; 658 size_t length;
644 659
645 src = (Uint8 *) pixels; 660 src = (Uint8 *) pixels;
650 for (row = 0; row < rect->h; ++row) { 665 for (row = 0; row < rect->h; ++row) {
651 SDL_memcpy(dst, src, length); 666 SDL_memcpy(dst, src, length);
652 src += pitch; 667 src += pitch;
653 dst += data->pitch; 668 dst += data->pitch;
654 } 669 }
670 /* If this is a static texture we would use Xrender for it
671 but this requires that the server side Pixmap associated
672 with this texture be updated with the data as well and
673 that the pixmap is not a shared memory pixmap.
674 Hopefully the user will not update static textures so
675 frequently as to cause a slowdown.
676 */
677 if (texture->access == SDL_TEXTUREACCESS_STATIC) {
678 #ifndef NO_SHARED_MEMORY
679 if(!data->shminfo.shmaddr)
680 #endif
681 {
682 XPutImage(renderdata->display, data->pixmap, renderdata->gc,
683 data->image, 0, 0, rect->x, rect->y, rect->w, rect->h);
684 }
685 }
686
655 } else { 687 } else {
656 data->image->width = rect->w; 688 data->image->width = rect->w;
657 data->image->height = rect->h; 689 data->image->height = rect->h;
658 data->image->data = (char *) pixels; 690 data->image->data = (char *) pixels;
659 data->image->bytes_per_line = pitch; 691 data->image->bytes_per_line = pitch;
999 if (xcount > 0) { 1031 if (xcount > 0) {
1000 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 1032 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1001 if(data->xrender_available == SDL_TRUE) 1033 if(data->xrender_available == SDL_TRUE)
1002 { 1034 {
1003 XRenderColor xrender_foreground_color; 1035 XRenderColor xrender_foreground_color;
1004 xrender_foreground_color.red = (unsigned short) ((renderer->r / 255.0) * 0xFFFF); 1036 // Premultiply the color channels as well as modulate them to a 16 bit color space
1005 xrender_foreground_color.green = (unsigned short) ((renderer->g / 255.0) * 0xFFFF); 1037 xrender_foreground_color.red = ((unsigned short)renderer->r + 1) * ((unsigned short)renderer->a + 1) - 1;
1006 xrender_foreground_color.blue = (unsigned short) ((renderer->b / 255.0) * 0xFFFF); 1038 xrender_foreground_color.green = ((unsigned short)renderer->g + 1) * ((unsigned short)renderer->a + 1) - 1;
1007 xrender_foreground_color.alpha = (unsigned short) ((renderer->a / 255.0) * 0xFFFF); 1039 xrender_foreground_color.blue = ((unsigned short)renderer->b + 1) * ((unsigned short)renderer->a + 1) - 1;
1040 xrender_foreground_color.alpha = ((unsigned short)renderer->a + 1) * ((unsigned short)renderer->a + 1) - 1;
1008 XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict, 1041 XRenderFillRectangles(data->display, PictOpSrc, data->drawable_pict,
1009 &xrender_foreground_color, xrects, xcount); 1042 &xrender_foreground_color, xrects, xcount);
1010 } 1043 }
1011 else 1044 else
1012 #endif 1045 #endif