Mercurial > sdl-ios-xcode
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 |