Bug in SDL_ListModes

According to the documentation, SDL_ListModes should return a list of
all available screen dimensions at a given format, sorted largest to
smallest. When using the “windib” video driver with graphics hardware
that supports screen rotation, the list is sorted incorrectly. The
following debug output was the list returned to my program on a machine
with Intel 82865G integrated video:

<3828> 09/29 15:09:44.718 debug: SDL_ListModes
<3828> 09/29 15:09:44.718 debug: 768 x 1280
<3828> 09/29 15:09:44.718 debug: 600 x 1280
<3828> 09/29 15:09:44.718 debug: 1280 x 1024
<3828> 09/29 15:09:44.718 debug: 1024 x 1280
<3828> 09/29 15:09:44.718 debug: 1152 x 864
<3828> 09/29 15:09:44.718 debug: 1280 x 768
<3828> 09/29 15:09:44.718 debug: 1280 x 600
<3828> 09/29 15:09:44.718 debug: 1024 x 768
<3828> 09/29 15:09:44.718 debug: 800 x 600
<3828> 09/29 15:09:44.718 debug: 768 x 1024
<3828> 09/29 15:09:44.718 debug: 640 x 480
<3828> 09/29 15:09:44.718 debug: 600 x 800
<3828> 09/29 15:09:44.718 debug: 400 x 640 <–I like these
<3828> 09/29 15:09:44.718 debug: 480 x 640 <-- especially
<3828> 09/29 15:09:44.718 debug: 640 x 400
<3828> 09/29 15:09:44.718 debug: 512 x 384
<3828> 09/29 15:09:44.718 debug: 400 x 300
<3828> 09/29 15:09:44.718 debug: 384 x 512
<3828> 09/29 15:09:44.718 debug: 320 x 240
<3828> 09/29 15:09:44.718 debug: 320 x 200

The culprit is a minor error in the comparison function used to sort the
list, in video/windib/SDL_dibvideo.c:

static int cmpmodes(const void *va, const void *vb)
{
SDL_Rect *a = *(SDL_Rect **)va;
SDL_Rect *b = *(SDL_Rect **)vb;
if(a->w > b->w)
return -1;
return b->h - a->h;
}

The intent of the code seems to be that modes are sorted first by width,
then by height, but in the case where (a->w <= b->w), sorting becomes
based strictly on height. A better comparison function would be:

static int cmpmodes(const void *va, const void *vb)
{
SDL_Rect *a = *(SDL_Rect **)va;
SDL_Rect *b = *(SDL_Rect **)vb;
if(a->w == b->w)
return b->h - a->h;
return b->w - a->w;
}

I have not checked the source for other targets, but I suspect similar
bugs might be present for other platforms as well.

Matt

This was fixed for Linux (in SDL_x11modes.c 1.19) with the slightly
more verbose;

if( (a->vdisplay > b->vdisplay) && (a->hdisplay >= b->hdisplay) )
return -1;
return b->hdisplay - a->hdisplay;

Although I must have been slightly drunk when I wrote the email
as I mixed up horizontal and vertical in the last sentence about
changing cmpmodes…On Thu, 2004-09-30 at 15:06, Matt Field wrote:

I have not checked the source for other targets, but I suspect
similar bugs might be present for other platforms as well.


Alan.

“One must never be purposelessnessnesslessness.”
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20040930/83103583/attachment.pgp

The culprit is a minor error in the comparison function used to sort the
list, in video/windib/SDL_dibvideo.c:

static int cmpmodes(const void *va, const void *vb)
{
SDL_Rect *a = *(SDL_Rect **)va;
SDL_Rect *b = *(SDL_Rect **)vb;
if(a->w > b->w)
return -1;
return b->h - a->h;
}

The intent of the code seems to be that modes are sorted first by width,
then by height, but in the case where (a->w <= b->w), sorting becomes
based strictly on height. A better comparison function would be:

static int cmpmodes(const void *va, const void *vb)
{
SDL_Rect *a = *(SDL_Rect **)va;
SDL_Rect *b = *(SDL_Rect **)vb;
if(a->w == b->w)
return b->h - a->h;
return b->w - a->w;
}

Yep, thank you very much. I’m changing all the mode comparison functions
to use the same sorting algorithm (sorted by width then height).

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

Le Fri, 12 Nov 2004 12:59:10 -0800
Sam Lantinga a ?crit:

Yep, thank you very much. I’m changing all the mode comparison
functions to use the same sorting algorithm (sorted by width then
height).

Does it mean that all video drivers should now report video modes sorted
by width, then height ?

Wouldn’t it be possible for SDL to sort the list returned by a driver
before passing it to the application (so lazy driver coders could return
video modes unsorted) ?

Well, if the driver can do it, SDL don’t have to. I just want to know what
is the wanted behaviour. And I assume, for the SDL apps I wrote, that I
consider the returned list not sorted the way I want, so I sort it
thereafter.–
Patrice Mandin
WWW: http://membres.lycos.fr/pmandin/
Programmeur Linux, Atari
Sp?cialit?: D?veloppement, jeux

Does it mean that all video drivers should now report video modes sorted
by width, then height ?

Yes.

Wouldn’t it be possible for SDL to sort the list returned by a driver
before passing it to the application (so lazy driver coders could return
video modes unsorted) ?

Yes. :slight_smile:
However, to prevent extra work, I’m leaving it to the drivers to sort
the list when they build the list.

Well, if the driver can do it, SDL don’t have to. I just want to know what
is the wanted behaviour. And I assume, for the SDL apps I wrote, that I
consider the returned list not sorted the way I want, so I sort it
thereafter.

Yes, that’s fine too. :slight_smile:

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment