1. SDL_CreateTextureFromSurface() now tries to find surface's pixel format.
authorMike Gorchak <lestat@i.com.ua>
Tue, 09 Jun 2009 08:56:43 +0000
changeset 3178 72edc980789b
parent 3177 efe3b3971e4f
child 3179 9b34679fda8b
1. SDL_CreateTextureFromSurface() now tries to find surface's pixel format. 2. SDL_CreateTextureFromSurface() now has best texture format search for non-alpha pixel formats. 3. Added comparision for pixels packed order to the video mode sorting callback to avoid mixing 1555/565/4444 pixel formats. 4. Added sorting call for current video mode list after each new video mode addition, because SDL_GetClosestDisplayMode() requires video modes to be sorted, and this is one place only where we can detect video modes addition.
src/video/SDL_video.c
--- a/src/video/SDL_video.c	Tue Jun 09 04:34:50 2009 +0000
+++ b/src/video/SDL_video.c	Tue Jun 09 08:56:43 2009 +0000
@@ -147,6 +147,9 @@
     if (SDL_BITSPERPIXEL(a.format) != SDL_BITSPERPIXEL(b.format)) {
         return SDL_BITSPERPIXEL(b.format) - SDL_BITSPERPIXEL(a.format);
     }
+    if (SDL_PIXELLAYOUT(a.format) != SDL_PIXELLAYOUT(b.format)) {
+        return SDL_PIXELLAYOUT(b.format) - SDL_PIXELLAYOUT(a.format);
+    }
     if (a.refresh_rate != b.refresh_rate) {
         return b.refresh_rate - a.refresh_rate;
     }
@@ -408,6 +411,10 @@
     modes[nmodes] = *mode;
     display->num_display_modes++;
 
+    /* Re-sort video modes */
+    SDL_qsort(display->display_modes, display->num_display_modes,
+        sizeof(SDL_DisplayMode), cmpmodes);
+
     return SDL_TRUE;
 }
 
@@ -1620,15 +1627,105 @@
             return 0;
         }
     } else {
-        /* FIXME: Get the best supported texture format */
         if (surface->format->Amask
             || !(surface->map->info.flags &
                  (SDL_COPY_COLORKEY | SDL_COPY_MASK | SDL_COPY_BLEND))) {
+            int it;
+            int pfmt;
+
+            /* Pixel formats, sorted by best first */
+            static const Uint32 sdl_pformats[]={
+               SDL_PIXELFORMAT_ARGB8888,
+               SDL_PIXELFORMAT_RGBA8888,
+               SDL_PIXELFORMAT_ABGR8888,
+               SDL_PIXELFORMAT_BGRA8888,
+               SDL_PIXELFORMAT_RGB888,
+               SDL_PIXELFORMAT_BGR888,
+               SDL_PIXELFORMAT_RGB24,
+               SDL_PIXELFORMAT_BGR24,
+               SDL_PIXELFORMAT_RGB565,
+               SDL_PIXELFORMAT_BGR565,
+               SDL_PIXELFORMAT_ARGB1555,
+               SDL_PIXELFORMAT_ABGR1555,
+               SDL_PIXELFORMAT_RGB555,
+               SDL_PIXELFORMAT_BGR555,
+               SDL_PIXELFORMAT_ARGB4444,
+               SDL_PIXELFORMAT_ABGR4444,
+               SDL_PIXELFORMAT_RGB444,
+               SDL_PIXELFORMAT_ARGB2101010,
+               SDL_PIXELFORMAT_INDEX8,
+               SDL_PIXELFORMAT_INDEX4LSB,
+               SDL_PIXELFORMAT_INDEX4MSB,
+               SDL_PIXELFORMAT_RGB332,
+               SDL_PIXELFORMAT_INDEX1LSB,
+               SDL_PIXELFORMAT_INDEX1MSB,
+               SDL_PIXELFORMAT_UNKNOWN};
+
             bpp = fmt->BitsPerPixel;
             Rmask = fmt->Rmask;
             Gmask = fmt->Gmask;
             Bmask = fmt->Bmask;
             Amask = fmt->Amask;
+
+            format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
+            if (!format) {
+                SDL_SetError("Unknown pixel format");
+                return 0;
+            }
+
+            /* Search requested format in the supported texture */
+            /* formats by current renderer                      */
+            for (it=0; it<renderer->info.num_texture_formats; it++)
+            {
+                if (renderer->info.texture_formats[it]==format)
+                {
+                   break;
+                }
+            }
+
+            /* If requested format can't be found, search any best */
+            /* format which renderer provides                      */
+            if (it==renderer->info.num_texture_formats)
+            {
+                pfmt=0;
+                for (;;)
+                {
+                    if (sdl_pformats[pfmt]==SDL_PIXELFORMAT_UNKNOWN)
+                    {
+                        break;
+                    }
+
+                    for (it=0; it<renderer->info.num_texture_formats; it++)
+                    {
+                       if (renderer->info.texture_formats[it]==sdl_pformats[pfmt])
+                       {
+                          break;
+                       }
+                    }
+
+                    if (it!=renderer->info.num_texture_formats)
+                    {
+                       /* The best format has been found */
+                       break;
+                    }
+                    pfmt++;
+                }
+
+                /* If any format can't be found, then return an error */
+                if (it==renderer->info.num_texture_formats)
+                {
+                    SDL_SetError("Any of the supported pixel formats can't be found");
+                    return 0;
+                }
+
+                /* Convert found pixel format back to color masks */
+                if (SDL_PixelFormatEnumToMasks(renderer->info.texture_formats[it],
+                       &bpp, &Rmask, &Gmask, &Bmask, &Amask)!=SDL_TRUE)
+                {
+                    SDL_SetError("Unknown pixel format");
+                    return 0;
+                }
+            }
         } else {
             /* Need a format with alpha */
             int it;
@@ -1648,11 +1745,21 @@
                 SDL_PIXELFORMAT_UNKNOWN
             };
 
-            bpp = 32;
-            Rmask = 0x00FF0000;
-            Gmask = 0x0000FF00;
-            Bmask = 0x000000FF;
-            Amask = 0xFF000000;
+            if (surface->format->Amask) {
+                /* If surface already has alpha, then try an original */
+                /* surface format first                               */
+                bpp = fmt->BitsPerPixel;
+                Rmask = fmt->Rmask;
+                Gmask = fmt->Gmask;
+                Bmask = fmt->Bmask;
+                Amask = fmt->Amask;
+            } else {
+                bpp = 32;
+                Rmask = 0x00FF0000;
+                Gmask = 0x0000FF00;
+                Bmask = 0x000000FF;
+                Amask = 0xFF000000;
+            }
 
             format =
                 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);