Get supported display resolutions

Hi community,
is there a way to get a list of screen resolutions that are supported by the hardware?
I couldn’t find anything in the bge.render functions.
In sdl there is a function called SDL_ListModes which returns a list of all possible resolutions (I hope you get what I’m talking about).

Id like to prevent the player from choosing a resolution in the options menue which causes a crash.

Since sdl is bundled with blender(player) it should be somehow possible to access the libs via python.

Thanks in advance :slight_smile:

I do not think this should be a feature of the bge. So yes try to access the SDL to retrieve this information from the right libraries.

Why shouldn’t it be a function for the BGE?

@Wendigo - I don’t think there’s a way to access SDL from Python, unfortunately. Anyway, you could set the window to a huge size, which should get restricted by the desktop, and then get the window’s current size to get the desktop size (which would probably be the desktop size that the player’s playing on). It would be nice to be able to tell what the desktop’s resolution is with a function, at least.

I though about that. My first intention was to say “because this is not game related”. But indeed the BGE could wrap the according OS API to provide some information.

It already allows to switch screen resolution. So this information would be a logical consequence.

For now you can use Pygame
Pygame wraps all STL commands. But you have to install it. After the installation you can copy the installed files from the Python lib to the Blender Lib directory.

modes = pygame.display.list_modes(depth=0, flags=pygame.FULLSCREEN) 

Thanks for your responses :slight_smile:

I think that functionality would be a nice feature for the game engine since it would allow to easyly get all supported screen resolutions which can be passed to “setWindowSize” as you already stated.
Furthermore the sdl.dll is already used and bundled with the bge. The SDL Function could be used like 1:1 exposed as a python function which delivers a tuple like [res-x, res-y, depth].
It should be quite easyly implemended.
How about adding a "BGE proposal: python function - List Video Modes "?

Yes that woud be an option but I don’t want to blow up the size of my little jump’n run by adding files of another game engine.

I think I’ll do as you said and manually create a list of common screen resolution “capped” by the resolution currently used by the system. This would be the easyest way to implement though I think accessing the sdl - lib directly would also work but it is quite complicated.

I have managed to successfully load the sdl.dll using ctypes module in python.

import ctypes
sdl_dll = ctypes.CDLL("sdl.dll")
# here comes the problem:
modes = sdl_dll.SDL_ListModes(None, None)

SDL_ListModes returns an array of SDL_Rect objects which are a “c” struct.
To handle that none primitive data types I would have to write an according python class wrapper which can be assigned to the python sdl_dll variable to handle the return value.
But this is beyond my capabilities at the moment. I haven’t used ctypes at all till now and it looks kind of complex.
Unless someone who already used the sdl lib in a project would be so kind to share a code snippet that I could adapt I’ll go with your method.

Here is an example for the SDL_VideoInfo that I made for someone else.

from ctypes import *

sdl = CDLL("sdl")

class SDL_VideoInfo(Structure):
   _fields_ = [('bitfield', c_uint),
            ('video_mem', c_uint),
            ('_vfmt',  c_void_p), # POINTER(SDL_PixelFormat)),
            ('_current_w', c_int),
            ('_current_h', c_int)]

sdl.SDL_GetVideoInfo.restype = POINTER(SDL_VideoInfo)

sdl.SDL_VideoInit(None, 0) #Video Hardware initialisieren
videoInfo = sdl.SDL_GetVideoInfo().contents #Pointer dereferenzieren

print (videoInfo._current_w)
print (videoInfo._current_h)

I tried to make an SDL_ListModes example for you. But it will always crash because I don’t know how to dereference the first pointer to a list.

from ctypes import *

sdl = CDLL("sdl")

class SDL_PixelFormat(Structure):
    _fields_ = [('_palette', c_void_p), #POINTER(SDL_Palette)),
                ('BitsPerPixel', c_ubyte),
                ('BytesPerPixel', c_ubyte),
                ('Rloss', c_ubyte),
                ('Gloss', c_ubyte),
                ('Bloss', c_ubyte),
                ('Aloss', c_ubyte),
                ('Rshift', c_ubyte),
                ('Gshift', c_ubyte),
                ('Bshift', c_ubyte),
                ('Ashift', c_ubyte),
                ('Rmask', c_uint),
                ('Gmask', c_uint),
                ('Bmask', c_uint),
                ('Amask', c_uint),
                ('colorkey', c_uint),
                ('alpha', c_ubyte)]

    def __copy__(self):
        f = SDL_PixelFormat()
        f._palette = self._palette
        f.BitsPerPixel = self.BitsPerPixel
        f.BytesPerPixel = self.BytesPerPixel
        f.Rloss = self.Rloss
        f.Gloss = self.Gloss
        f.Bloss = self.Bloss
        f.Aloss = self.Aloss
        f.Rshift = self.Rshift
        f.Gshift = self.Gshift
        f.Bshift = self.Bshift
        f.Ashift = self.Ashift
        f.Rmask = self.Rmask
        f.Gmask = self.Gmask
        f.Bmask = self.Bmask
        f.Amask = self.Amask
        f.colorkey = self.colorkey
        f.alpha = self.alpha
        return f

class SDL_Rect(Structure):

    _fields_ = [('x', c_short),
                ('y', c_short),
                ('w', c_ushort),
                ('h', c_ushort)]

    def __init__(self, x=0, y=0, w=0, h=0):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
    def __repr__(self):
        return 'SDL_Rect(x=%d, y=%d, w=%d, h=%d)' % \
            (self.x, self.y, self.w, self.h)

    def __copy__(self):
        return SDL_Rect(self.x, self.y, self.w, self.h)

    def __deepcopy__(self, memo):
        return SDL_Rect(self.x, self.y, self.w, self.h)

#class SDL_ListModes(Structure):
#    _fields_ = [('_list',  POINTER(SDL_Rect))]

#    def __getattr__(self, name):
#        if name == 'list':  # Dereferenziere list pointer.
#            if self._vfmt:
#                return self._list.contents
#        return None

sdl.SDL_VideoInit(None, 0)

sdl.SDL_ListModes.restype = POINTER(POINTER(SDL_Rect))
sdl.SDL_ListModes.argtypes = [POINTER(SDL_PixelFormat), c_uint]

def SDL_ListModes(format, flags):

    ar = sdl.SDL_ListModes(format, flags)#.contens
    if not ar:
        return []
    if addressof(ar.contents) == -1:
        return -1

    i = 0
    lst = []

    while ar[i]:
       i += 1
    return lst

    #for obj in ar:
    #return lst

#SDL_ListModes(None, 66)
print (SDL_ListModes(None, 66))

Thanks, I’ll have a look at it :slight_smile:

I got it to work. The problem were the flags bits. I thought they are normally binary sorted but they have different numbers.
I also removed all unnecessary code.

from ctypes import *

sdl = CDLL("sdl.dll")

SDL_SWSURFACE    Create the video surface in system memory
SDL_HWSURFACE    Create the video surface in video memory
SDL_ASYNCBLIT    Enables the use of asynchronous updates of the display surface. This will usually slow down blitting on single CPU machines, but may provide a speed increase on SMP systems.
SDL_ANYFORMAT    Normally, if a video surface of the requested bits-per-pixel (bpp) is not available, SDL will emulate one with a shadow surface. Passing SDL_ANYFORMAT prevents this and causes SDL to use the video surface, regardless of its pixel depth.
SDL_HWPALETTE    Give SDL exclusive palette access. Without this flag you may not always get the colors you request with SDL_SetColors or SDL_SetPalette.
SDL_DOUBLEBUF    Enable hardware double buffering; only valid with SDL_HWSURFACE. Calling SDL_Flip will flip the buffers and update the screen. All drawing will take place on the surface that is not displayed at the moment. If double buffering could not be enabled then SDL_Flip will just perform a SDL_UpdateRect on the entire screen.
SDL_FULLSCREEN    SDL will attempt to use a fullscreen mode. If a hardware resolution change is not possible (for whatever reason), the next higher resolution will be used and the display window centered on a black background.
SDL_OPENGL        Create an OpenGL rendering context. You should have previously set OpenGL video attributes with SDL_GL_SetAttribute.
SDL_OPENGLBLT    Create an OpenGL rendering context, like above, but allow normal blitting operations. The screen (2D) surface may have an alpha channel, and SDL_UpdateRects must be used for updating changes to the screen surface. NOTE: This option is kept for compatibility only, and will be removed in next versions. Is not recommended for new code.
SDL_RESIZABLE    Create a resizable window. When the window is resized by the user a SDL_VIDEORESIZE event is generated and SDL_SetVideoMode can be called again with the new size.
SDL_NOFRAME        If possible, SDL_NOFRAME causes SDL to create a window with no title bar or frame decoration. Fullscreen modes automatically have this flag set.

SDL_ANYFORMAT = 268435456
SDL_HWPALETTE = 536870912
SDL_DOUBLEBUF = 1073741824
SDL_FULLSCREEN = 2147483648

class SDL_Rect(Structure):
    _fields_ = [('x', c_short),
                ('y', c_short),
                ('w', c_ushort),
                ('h', c_ushort)]

sdl.SDL_VideoInit(None, 0)

sdl.SDL_ListModes.restype = POINTER(POINTER(SDL_Rect))
sdl.SDL_ListModes.argtypes = [c_void_p, c_uint]

def SDL_ListModes2(format, flags):
    ar = sdl.SDL_ListModes(format, flags)
    if not ar:
        return []
    if addressof(ar.contents) == -1:
        return SDL_ANY_DIMENSION

    i = 0
    lst = []
    while ar[i]:
        lst2 = []
        i += 1
    return lst

print (modes)

Cool, works like a charm :slight_smile:
Whats your license for the code?

Seams like Monster didn’t read this thread any further, maybe I’ll create a proposal thread for adding the function to the bge myself.

Whats your license for the code?

I share it without license. If you like, you can credit my but there is no need.