Make the SW renderer work properly by fixing support for textures with no alpha channels.
authorSunny Sachanandani <sunnysachanandani@gmail.com>
Wed, 21 Jul 2010 23:08:09 +0530
changeset 4610 32991e17e2b6
parent 4609 630002c8be85
child 4611 a2ed55b5ff85
Make the SW renderer work properly by fixing support for textures with no alpha channels.
src/video/x11/SDL_x11render.c
--- a/src/video/x11/SDL_x11render.c	Wed Jul 21 18:38:40 2010 +0530
+++ b/src/video/x11/SDL_x11render.c	Wed Jul 21 23:08:09 2010 +0530
@@ -671,15 +671,20 @@
 #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;
+    if (sdl_mask == 0) {
+        *comp = 0;
+        *compMask = 0;
+    } else {
+        (*comp) = 0;
+        (*compMask) = 0;
+        while(!(sdl_mask & 1)) {
+            (*comp)++;
+            sdl_mask >>= 1;
+        }
+        while(sdl_mask & 1) {
+            (*compMask) = ((*compMask) << 1) | 1;
+            sdl_mask >>= 1;
+        }
     }
 }
 
@@ -687,13 +692,15 @@
 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);
-
+        if(!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
+            SDL_SetError("Unknown pixel format");
+            return NULL;
+        }
         XRenderPictFormat templ;
         unsigned long mask = (PictFormatType | PictFormatDepth | PictFormatRed |
                               PictFormatRedMask | PictFormatGreen | PictFormatGreenMask |
@@ -706,7 +713,6 @@
         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);
     }
     
@@ -774,37 +780,27 @@
         }
         data->format = display->current_mode.format;
     } else {
-        /* If Xrender support is builtin we only need to check whether
-           Xrender is available at runtime. If it is available there
-           can be no BadMatch error since Xrender takes care of that.
-        */
 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
-        if (renderdata->use_xrender == SDL_FALSE) {
-            if (texture->format != display->current_mode.format) {
-                SDL_SetError("Texture format doesn't match window format");
-                return -1;
-            }
-        } else {
+        if (renderdata->use_xrender)
+        {
             Uint32 Amask, Rmask, Gmask, Bmask;
             SDL_PixelFormatEnumToMasks(texture->format, &(data->depth),
                                        &Rmask, &Gmask, &Bmask, &Amask);
+            printf("%d %x %x %x %x\n", 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
-           get a BadMatch error when trying to putimage or copyarea.
-           This BadMatch error
-        */
-        if (texture->format != display->current_mode.format) {
-            SDL_SetError("Texture format doesn't match window format");
-            return -1;
+        else
+#endif
+        {
+            if (texture->format != display->current_mode.format)
+            {
+                SDL_SetError("Texture format doesn't match window format");
+                return -1;
+            }
         }
-#endif
         data->format = texture->format;
     }
-    data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format);
-    data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask;
-
+    
     if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) {
 #ifndef NO_SHARED_MEMORY
         XShmSegmentInfo *shminfo = &data->shminfo;
@@ -812,27 +808,68 @@
         shm_error = True;
 
         if (SDL_X11_HAVE_SHM) {
-            shminfo->shmid =
-                shmget(IPC_PRIVATE, texture->h * data->pitch,
-                       IPC_CREAT | 0777);
-            if (shminfo->shmid >= 0) {
-                shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
-                shminfo->readOnly = False;
-                if (shminfo->shmaddr != (char *) -1) {
-                    shm_error = False;
-                    X_handler = XSetErrorHandler(shm_errhandler);
-                    XShmAttach(renderdata->display, shminfo);
-                    XSync(renderdata->display, False);
-                    XSetErrorHandler(X_handler);
-                    if (shm_error) {
-                        shmdt(shminfo->shmaddr);
+            data->image =
+                XShmCreateImage(renderdata->display, data->visual,
+                                data->depth, ZPixmap, NULL,
+                                shminfo, texture->w, texture->h);
+            if (data->image) {
+                shminfo->shmid =
+                    shmget(IPC_PRIVATE, texture->h * data->image->bytes_per_line,
+                           IPC_CREAT | 0777);
+                if (shminfo->shmid >= 0) {
+                    shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+                    shminfo->readOnly = False;
+                    if (shminfo->shmaddr != (char *) -1) {
+                        shm_error = False;
+                        X_handler = XSetErrorHandler(shm_errhandler);
+                        XShmAttach(renderdata->display, shminfo);
+                        XSync(renderdata->display, False);
+                        XSetErrorHandler(X_handler);
+                        if (shm_error) {
+                            XShmDetach(renderdata->display, shminfo);
+                            shmdt(shminfo->shmaddr);
+                            XDestroyImage(data->image);
+                            XSync(renderdata->display, False);
+                        }
+                        else {
+                            data->pixels = data->image->data = shminfo->shmaddr;
+                            shmctl(shminfo->shmid, IPC_RMID, NULL);
+                            data->pixmap =
+                                XCreatePixmap(renderdata->display, renderdata->xwindow,
+                                              texture->w, texture->h, data->depth);
+                            if (!data->pixmap) {
+                                SDL_SetError("XCreatePixmap() failed");
+                                return -1;
+                            }
+                        }
                     }
                 }
-                shmctl(shminfo->shmid, IPC_RMID, NULL);
             }
         }
-        if (!shm_error) {
-            data->pixels = shminfo->shmaddr;
+        if (shm_error) {
+            shminfo->shmaddr = NULL;
+        }
+        if (!data->image)
+#endif /* not NO_SHARED_MEMORY */
+        {
+            data->image =
+                XCreateImage(renderdata->display, data->visual,
+                             data->depth, ZPixmap, 0, NULL,
+                             texture->w, texture->h,
+                             SDL_BYTESPERPIXEL(data->format) * 8,
+                             0);
+            if (!data->image) {
+                X11_DestroyTexture(renderer, texture);
+                SDL_SetError("XCreateImage() failed");
+                return -1;
+            }
+            data->pixels = SDL_malloc(texture->h * data->image->bytes_per_line);
+            if (!data->pixels) {
+                X11_DestroyTexture(renderer, texture);
+                SDL_OutOfMemory();
+                return -1;
+            }
+            data->image->data = data->pixels;
             data->pixmap =
                 XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
                               texture->h, data->depth);
@@ -841,53 +878,20 @@
                 SDL_SetError("XCreatePixmap() failed");
                 return -1;
             }
-            data->image =
-                XShmCreateImage(renderdata->display, data->visual,
-                                data->depth, ZPixmap, shminfo->shmaddr,
-                                shminfo, texture->w, texture->h);
-
-            if (!data->image) {
-                XShmDetach(renderdata->display, shminfo);
-                XSync(renderdata->display, False);
-                shmdt(shminfo->shmaddr);
-                shm_error = True;
-            }
-        }
-        if (shm_error) {
-            shminfo->shmaddr = NULL;
-        }
-        if (!data->image)
-#endif /* not NO_SHARED_MEMORY */
-        {
-            data->pixels = SDL_malloc(texture->h * data->pitch);
-            if (!data->pixels) {
-                X11_DestroyTexture(renderer, texture);
-                SDL_OutOfMemory();
-                return -1;
-            }
-
-            data->pixmap =
-                XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
-                              texture->h, data->depth);
-            if (data->pixmap == None) {
-                X11_DestroyTexture(renderer, texture);
-                SDL_SetError("XCreatePixmap() failed");
-                return -1;
-            }
-            data->image =
-                XCreateImage(renderdata->display, data->visual,
-                             data->depth, ZPixmap, 0, data->pixels,
-                             texture->w, texture->h,
-                             SDL_BYTESPERPIXEL(data->format) * 8,
-                             data->pitch);
-            if (!data->image) {
-                X11_DestroyTexture(renderer, texture);
-                SDL_SetError("XCreateImage() failed");
-                return -1;
-            }
         }
     } 
     else {
+        data->image =
+            XCreateImage(renderdata->display, data->visual,
+                         data->depth, ZPixmap, 0, NULL,
+                         texture->w, texture->h,
+                         SDL_BYTESPERPIXEL(data->format) * 8,
+                         0);
+        if (!data->image) {
+            X11_DestroyTexture(renderer, texture);
+            SDL_SetError("XCreateImage() failed");
+            return -1;
+        }
         data->pixmap =
             XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w,
                           texture->h, data->depth);
@@ -896,18 +900,10 @@
             SDL_SetError("XCreatePixmap() failed");
             return -1;
         }
-        data->image =
-            XCreateImage(renderdata->display, data->visual,
-                         data->depth, ZPixmap, 0, NULL,
-                         texture->w, texture->h,
-                         SDL_BYTESPERPIXEL(data->format) * 8,
-                         data->pitch);
-        if (!data->image) {
-            X11_DestroyTexture(renderer, texture);
-            SDL_SetError("XCreateImage() failed");
-            return -1;
-        }
     }
+
+    data->pitch = data->image->bytes_per_line;
+
 #ifdef SDL_VIDEO_DRIVER_X11_XRENDER
     if(renderdata->use_xrender) {
         gcv.graphics_exposures = False;
@@ -932,6 +928,8 @@
             SDL_SetError("XRenderCreatePicture() failed");
             return -1;
         }
+        texture->blendMode = SDL_BLENDMODE_NONE;
+        data->blend_op = PictOpSrc;
     }
 #endif
     return 0;
@@ -1713,7 +1711,7 @@
         if(texture->access == SDL_TEXTUREACCESS_STREAMING) {
 #ifndef NO_SHARED_MEMORY
             if(texturedata->shminfo.shmaddr) {
-                XShmPutImage(data->display, texturedata->pixmap, data->gc,
+                XShmPutImage(data->display, texturedata->pixmap, texturedata->gc,
                              texturedata->image, srcrect->x, srcrect->y,
                              srcrect->x, srcrect->y, srcrect->w, srcrect->h,
                              False);
@@ -1721,10 +1719,11 @@
             else
 #endif
             if (texturedata->pixels) {
-                XPutImage(data->display, texturedata->pixmap, data->gc,
-                          texturedata->image, srcrect->x, srcrect->y, dstrect->x,
-                          dstrect->y, srcrect->w, srcrect->h);
+                XPutImage(data->display, texturedata->pixmap, texturedata->gc,
+                          texturedata->image, srcrect->x, srcrect->y, srcrect->x,
+                          srcrect->y, srcrect->w, srcrect->h);
             }
+            XSync(data->display, False);
         }
         Picture mask;
         XRenderPictureAttributes attr;