comparison src/video/x11/SDL_x11render.c @ 4610:32991e17e2b6

Make the SW renderer work properly by fixing support for textures with no alpha channels.
author Sunny Sachanandani <sunnysachanandani@gmail.com>
date Wed, 21 Jul 2010 23:08:09 +0530
parents 630002c8be85
children a2ed55b5ff85
comparison
equal deleted inserted replaced
4609:630002c8be85 4610:32991e17e2b6
669 } 669 }
670 670
671 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 671 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
672 static void 672 static void
673 SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) { 673 SDLMaskToXRenderMask(Uint32 sdl_mask, short *comp, short *compMask) {
674 (*comp) = 0; 674 if (sdl_mask == 0) {
675 (*compMask) = 0; 675 *comp = 0;
676 while(!(sdl_mask & 1)) { 676 *compMask = 0;
677 (*comp)++; 677 } else {
678 sdl_mask >>= 1; 678 (*comp) = 0;
679 } 679 (*compMask) = 0;
680 while(sdl_mask & 1) { 680 while(!(sdl_mask & 1)) {
681 (*compMask) = ((*compMask) << 1) | 1; 681 (*comp)++;
682 sdl_mask >>= 1; 682 sdl_mask >>= 1;
683 }
684 while(sdl_mask & 1) {
685 (*compMask) = ((*compMask) << 1) | 1;
686 sdl_mask >>= 1;
687 }
683 } 688 }
684 } 689 }
685 690
686 static XRenderPictFormat* 691 static XRenderPictFormat*
687 PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format) { 692 PixelFormatEnumToXRenderPictFormat(SDL_Renderer * renderer, Uint32 format) {
688 XRenderPictFormat* pict_fmt = NULL; 693 XRenderPictFormat* pict_fmt = NULL;
689 X11_RenderData *data = (X11_RenderData *) renderer->driverdata; 694 X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
690 695
691 if (data->use_xrender) { 696 if (data->use_xrender) {
692 697
693 int bpp; 698 int bpp;
694 Uint32 Amask, Rmask, Gmask, Bmask; 699 Uint32 Amask, Rmask, Gmask, Bmask;
695 SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); 700 if(!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
696 701 SDL_SetError("Unknown pixel format");
702 return NULL;
703 }
697 XRenderPictFormat templ; 704 XRenderPictFormat templ;
698 unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed | 705 unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed |
699 PictFormatRedMask | PictFormatGreen | PictFormatGreenMask | 706 PictFormatRedMask | PictFormatGreen | PictFormatGreenMask |
700 PictFormatBlue | PictFormatBlueMask | PictFormatAlpha | 707 PictFormatBlue | PictFormatBlueMask | PictFormatAlpha |
701 PictFormatAlphaMask); 708 PictFormatAlphaMask);
704 templ.depth = bpp; 711 templ.depth = bpp;
705 SDLMaskToXRenderMask(Amask, &(templ.direct.alpha), &(templ.direct.alphaMask)); 712 SDLMaskToXRenderMask(Amask, &(templ.direct.alpha), &(templ.direct.alphaMask));
706 SDLMaskToXRenderMask(Rmask, &(templ.direct.red), &(templ.direct.redMask)); 713 SDLMaskToXRenderMask(Rmask, &(templ.direct.red), &(templ.direct.redMask));
707 SDLMaskToXRenderMask(Gmask, &(templ.direct.green), &(templ.direct.greenMask)); 714 SDLMaskToXRenderMask(Gmask, &(templ.direct.green), &(templ.direct.greenMask));
708 SDLMaskToXRenderMask(Bmask, &(templ.direct.blue), &(templ.direct.blueMask)); 715 SDLMaskToXRenderMask(Bmask, &(templ.direct.blue), &(templ.direct.blueMask));
709
710 pict_fmt = XRenderFindFormat(data->display, mask, &templ, 0); 716 pict_fmt = XRenderFindFormat(data->display, mask, &templ, 0);
711 } 717 }
712 718
713 return pict_fmt; 719 return pict_fmt;
714 } 720 }
772 if (!data->yuv) { 778 if (!data->yuv) {
773 return -1; 779 return -1;
774 } 780 }
775 data->format = display->current_mode.format; 781 data->format = display->current_mode.format;
776 } else { 782 } else {
777 /* If Xrender support is builtin we only need to check whether 783 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
778 Xrender is available at runtime. If it is available there 784 if (renderdata->use_xrender)
779 can be no BadMatch error since Xrender takes care of that. 785 {
780 */
781 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
782 if (renderdata->use_xrender == SDL_FALSE) {
783 if (texture->format != display->current_mode.format) {
784 SDL_SetError("Texture format doesn't match window format");
785 return -1;
786 }
787 } else {
788 Uint32 Amask, Rmask, Gmask, Bmask; 786 Uint32 Amask, Rmask, Gmask, Bmask;
789 SDL_PixelFormatEnumToMasks(texture->format, &(data->depth), 787 SDL_PixelFormatEnumToMasks(texture->format, &(data->depth),
790 &Rmask, &Gmask, &Bmask, &Amask); 788 &Rmask, &Gmask, &Bmask, &Amask);
789 printf("%d %x %x %x %x\n", data->depth, Rmask, Gmask, Bmask, Amask);
791 data->visual = PixelFormatEnumToVisual(renderer, texture->format); 790 data->visual = PixelFormatEnumToVisual(renderer, texture->format);
792 } 791 }
793 #else 792 else
794 /* The image/pixmap depth must be the same as the window or you 793 #endif
795 get a BadMatch error when trying to putimage or copyarea. 794 {
796 This BadMatch error 795 if (texture->format != display->current_mode.format)
797 */ 796 {
798 if (texture->format != display->current_mode.format) { 797 SDL_SetError("Texture format doesn't match window format");
799 SDL_SetError("Texture format doesn't match window format"); 798 return -1;
800 return -1; 799 }
801 } 800 }
802 #endif
803 data->format = texture->format; 801 data->format = texture->format;
804 } 802 }
805 data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); 803
806 data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask;
807
808 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { 804 if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
809 #ifndef NO_SHARED_MEMORY 805 #ifndef NO_SHARED_MEMORY
810 XShmSegmentInfo *shminfo = &data->shminfo; 806 XShmSegmentInfo *shminfo = &data->shminfo;
811 807
812 shm_error = True; 808 shm_error = True;
813 809
814 if (SDL_X11_HAVE_SHM) { 810 if (SDL_X11_HAVE_SHM) {
815 shminfo->shmid = 811 data->image =
816 shmget(IPC_PRIVATE, texture->h * data->pitch, 812 XShmCreateImage(renderdata->display, data->visual,
817 IPC_CREAT | 0777); 813 data->depth, ZPixmap, NULL,
818 if (shminfo->shmid >= 0) { 814 shminfo, texture->w, texture->h);
819 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); 815 if (data->image) {
820 shminfo->readOnly = False; 816 shminfo->shmid =
821 if (shminfo->shmaddr != (char *) -1) { 817 shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line,
822 shm_error = False; 818 IPC_CREAT | 0777);
823 X_handler = XSetErrorHandler(shm_errhandler); 819 if (shminfo->shmid >= 0) {
824 XShmAttach(renderdata->display, shminfo); 820 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
825 XSync(renderdata->display, False); 821 shminfo->readOnly = False;
826 XSetErrorHandler(X_handler); 822 if (shminfo->shmaddr != (char *) -1) {
827 if (shm_error) { 823 shm_error = False;
828 shmdt(shminfo->shmaddr); 824 X_handler = XSetErrorHandler(shm_errhandler);
825 XShmAttach(renderdata->display, shminfo);
826 XSync(renderdata->display, False);
827 XSetErrorHandler(X_handler);
828 if (shm_error) {
829 XShmDetach(renderdata->display, shminfo);
830 shmdt(shminfo->shmaddr);
831 XDestroyImage(data->image);
832 XSync(renderdata->display, False);
833 }
834 else {
835 data->pixels = data->image->data = shminfo->shmaddr;
836 shmctl(shminfo->shmid, IPC_RMID, NULL);
837 data->pixmap =
838 XCreatePixmap(renderdata->display, renderdata->xwindow,
839 texture->w, texture->h, data->depth);
840 if (!data->pixmap) {
841 SDL_SetError("XCreatePixmap() failed");
842 return -1;
843 }
844 }
829 } 845 }
830 } 846 }
831 shmctl(shminfo->shmid, IPC_RMID, NULL); 847 }
832 } 848 }
833 } 849 if (shm_error) {
834 if (!shm_error) { 850 shminfo->shmaddr = NULL;
835 data->pixels = shminfo->shmaddr; 851 }
852 if (!data->image)
853 #endif /* not NO_SHARED_MEMORY */
854 {
855 data->image =
856 XCreateImage(renderdata->display, data->visual,
857 data->depth, ZPixmap, 0, NULL,
858 texture->w, texture->h,
859 SDL_BYTESPERPIXEL(data->format) * 8,
860 0);
861 if (!data->image) {
862 X11_DestroyTexture(renderer, texture);
863 SDL_SetError("XCreateImage() failed");
864 return -1;
865 }
866 data->pixels = SDL_malloc(texture->h * data->image->bytes_per_line);
867 if (!data->pixels) {
868 X11_DestroyTexture(renderer, texture);
869 SDL_OutOfMemory();
870 return -1;
871 }
872 data->image->data = data->pixels;
836 data->pixmap = 873 data->pixmap =
837 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, 874 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
838 texture->h, data->depth); 875 texture->h, data->depth);
839 if (data->pixmap == None) { 876 if (data->pixmap == None) {
840 X11_DestroyTexture(renderer, texture); 877 X11_DestroyTexture(renderer, texture);
841 SDL_SetError("XCreatePixmap() failed"); 878 SDL_SetError("XCreatePixmap() failed");
842 return -1; 879 return -1;
843 } 880 }
844 data->image =
845 XShmCreateImage(renderdata->display, data->visual,
846 data->depth, ZPixmap, shminfo->shmaddr,
847 shminfo, texture->w, texture->h);
848
849 if (!data->image) {
850 XShmDetach(renderdata->display, shminfo);
851 XSync(renderdata->display, False);
852 shmdt(shminfo->shmaddr);
853 shm_error = True;
854 }
855 }
856 if (shm_error) {
857 shminfo->shmaddr = NULL;
858 }
859 if (!data->image)
860 #endif /* not NO_SHARED_MEMORY */
861 {
862 data->pixels = SDL_malloc(texture->h * data->pitch);
863 if (!data->pixels) {
864 X11_DestroyTexture(renderer, texture);
865 SDL_OutOfMemory();
866 return -1;
867 }
868
869 data->pixmap =
870 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
871 texture->h, data->depth);
872 if (data->pixmap == None) {
873 X11_DestroyTexture(renderer, texture);
874 SDL_SetError("XCreatePixmap() failed");
875 return -1;
876 }
877 data->image =
878 XCreateImage(renderdata->display, data->visual,
879 data->depth, ZPixmap, 0, data->pixels,
880 texture->w, texture->h,
881 SDL_BYTESPERPIXEL(data->format) * 8,
882 data->pitch);
883 if (!data->image) {
884 X11_DestroyTexture(renderer, texture);
885 SDL_SetError("XCreateImage() failed");
886 return -1;
887 }
888 } 881 }
889 } 882 }
890 else { 883 else {
884 data->image =
885 XCreateImage(renderdata->display, data->visual,
886 data->depth, ZPixmap, 0, NULL,
887 texture->w, texture->h,
888 SDL_BYTESPERPIXEL(data->format) * 8,
889 0);
890 if (!data->image) {
891 X11_DestroyTexture(renderer, texture);
892 SDL_SetError("XCreateImage() failed");
893 return -1;
894 }
891 data->pixmap = 895 data->pixmap =
892 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, 896 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
893 texture->h, data->depth); 897 texture->h, data->depth);
894 if (data->pixmap == None) { 898 if (data->pixmap == None) {
895 X11_DestroyTexture(renderer, texture); 899 X11_DestroyTexture(renderer, texture);
896 SDL_SetError("XCreatePixmap() failed"); 900 SDL_SetError("XCreatePixmap() failed");
897 return -1; 901 return -1;
898 } 902 }
899 data->image = 903 }
900 XCreateImage(renderdata->display, data->visual, 904
901 data->depth, ZPixmap, 0, NULL, 905 data->pitch = data->image->bytes_per_line;
902 texture->w, texture->h, 906
903 SDL_BYTESPERPIXEL(data->format) * 8,
904 data->pitch);
905 if (!data->image) {
906 X11_DestroyTexture(renderer, texture);
907 SDL_SetError("XCreateImage() failed");
908 return -1;
909 }
910 }
911 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 907 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
912 if(renderdata->use_xrender) { 908 if(renderdata->use_xrender) {
913 gcv.graphics_exposures = False; 909 gcv.graphics_exposures = False;
914 data->gc = 910 data->gc =
915 XCreateGC(renderdata->display, data->pixmap, GCGraphicsExposures, &gcv); 911 XCreateGC(renderdata->display, data->pixmap, GCGraphicsExposures, &gcv);
930 if (!data->picture) { 926 if (!data->picture) {
931 X11_DestroyTexture(renderer, texture); 927 X11_DestroyTexture(renderer, texture);
932 SDL_SetError("XRenderCreatePicture() failed"); 928 SDL_SetError("XRenderCreatePicture() failed");
933 return -1; 929 return -1;
934 } 930 }
931 texture->blendMode = SDL_BLENDMODE_NONE;
932 data->blend_op = PictOpSrc;
935 } 933 }
936 #endif 934 #endif
937 return 0; 935 return 0;
938 } 936 }
939 937
1711 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER 1709 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
1712 if (data->use_xrender) { 1710 if (data->use_xrender) {
1713 if(texture->access == SDL_TEXTUREACCESS_STREAMING) { 1711 if(texture->access == SDL_TEXTUREACCESS_STREAMING) {
1714 #ifndef NO_SHARED_MEMORY 1712 #ifndef NO_SHARED_MEMORY
1715 if(texturedata->shminfo.shmaddr) { 1713 if(texturedata->shminfo.shmaddr) {
1716 XShmPutImage(data->display, texturedata->pixmap, data->gc, 1714 XShmPutImage(data->display, texturedata->pixmap, texturedata->gc,
1717 texturedata->image, srcrect->x, srcrect->y, 1715 texturedata->image, srcrect->x, srcrect->y,
1718 srcrect->x, srcrect->y, srcrect->w, srcrect->h, 1716 srcrect->x, srcrect->y, srcrect->w, srcrect->h,
1719 False); 1717 False);
1720 } 1718 }
1721 else 1719 else
1722 #endif 1720 #endif
1723 if (texturedata->pixels) { 1721 if (texturedata->pixels) {
1724 XPutImage(data->display, texturedata->pixmap, data->gc, 1722 XPutImage(data->display, texturedata->pixmap, texturedata->gc,
1725 texturedata->image, srcrect->x, srcrect->y, dstrect->x, 1723 texturedata->image, srcrect->x, srcrect->y, srcrect->x,
1726 dstrect->y, srcrect->w, srcrect->h); 1724 srcrect->y, srcrect->w, srcrect->h);
1727 } 1725 }
1726 XSync(data->display, False);
1728 } 1727 }
1729 Picture mask; 1728 Picture mask;
1730 XRenderPictureAttributes attr; 1729 XRenderPictureAttributes attr;
1731 const SDL_Rect *mrect; 1730 const SDL_Rect *mrect;
1732 if(texture->blendMode == SDL_BLENDMODE_NONE) { 1731 if(texture->blendMode == SDL_BLENDMODE_NONE) {