Fullscreen acting up with dual monitors

I’m attempting to implement a simple approach to switching to- and from- fullscreen mode, based on the suggestion given here.

Unfortunately, while it appears to work well in the menu, it acts up somewhat once gameplay begins.

The behaviour witnessed seems to be consistent.

To start with, when I enter fullscreen mode, the game insists on doing so on the secondary monitor, regardless of which monitor the game was on while windowed.

Now, if I simply run the game, enter fullscreen mode at the menu, and start the game, I get a partially-rendered image, and nothing more–the image is static. Sound cues seem to indicate that the game is, however, updating. Pressing “escape” to resummon the menu has no visible effect, but again, sound cues indicate that the menu is being opened.

However, if I then alt-tab to something else, the game suddenly springs over to the primary monitor, and starts rendering as expected.

A quick test seems to indicate that this is related to an issue with getting display-sizes under Ubuntu: the following code:

print (base.pipe.getDisplayWidth(), base.pipe.getDisplayHeight())

Produces the following result:

2646 1058

Note that neither monitor has such a resolution.

At a guess, it may be that Panda is attempting to render at that huge resolution, and the system is unhappy about it. When I alt-tab, perhaps the window is re-made or re-sized, resulting in a more appropriate resolution. The initial placement on the secondary monitor might be related to that monitor having the higher vertical resolution (albeit with a lower horizontal resolution).

This is, I think, an issue that I’ve seen mentioned elsewhere before as a problem under Ubuntu (or perhaps Linux in general; I forget). I don’t know what other developers may have done about it, if anything. :/

I’m using Ubuntu 18.04.2.

Hmm, I use this construct on the Window, and it works as it should.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import WindowProperties
from collections import OrderedDict

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        mode_display = OrderedDict()

        mode = base.pipe.getDisplayInformation()

        for i in range( mode.getTotalDisplayModes()):
            width  = mode.getDisplayModeWidth(i)
            height = mode.getDisplayModeHeight(i)
            bits   = mode.getDisplayModeBitsPerPixel(i)
            frequency = mode.getDisplayModeRefreshRate(i)
            mode_display[str(width)+' '+str(height)] = [str(bits), str(frequency)]
            
        mode_display_list = list(mode_display.items())
        get_el = mode_display_list[-1][0].split(' ')
        
        print (mode_display_list)
        
        #props = WindowProperties()
        #props.setSize(int(get_el[0]), int(get_el[1]))
        #base.win.requestProperties(props)

app = MyApp()
app.run()

Hmm… In my case I get only one “display mode”, and it has the same width and height as reported in my previous post. :/

(You say that you use the above “on the Window”–do you mean the game-window, or the Windows OS? If you mean the Windows OS, then indeed, I don’t think that this issue is present there–it seems to be an Ubuntu (or perhaps a Linux; I’m not sure) thing.

If you are using Linux, would you tell me what distribution you’re using, please?)

I meant the operating system. There may be a problem with the availability of a second monitor, which is likely the panda is confused.

I’m not sure that it’s Panda, however–I think that I’ve seen mention of this elsewhere.

That said, I don’t seem to be finding a reference for that in my current searches, so perhaps I’m mistaken; I stand to be corrected.

I’ve opened an issue for this on GitHub.

I installed Linux Mint-19.1-Cinnamon-64bit and checked this code, and it works. However, what surprised me was the inverse of the list - “mode_display_list”. In addition, the value of mode.getDisplayModeBitsPerPixel is -1. And my monitor supports a maximum refresh rate of 60, but mode.getDisplayModeRefreshRate returns 120, 119, 118, 59, which is odd. Under Windows, I get the expected values.

Linux Mint-19.1
[('1920 1080', ['-1', '120']), ('1680 1050', ['-1', '60']), ('1600 1024', ['-1', '60']), ('1400 1050', ['-1', '60']), ('1600 900', ['-1', '60']), ('1280 1024', ['-1', '60']), ('1440 900', ['-1', '60']), ('1400 900', ['-1', '60']), ('1280 960', ['-1', '60']), ('1440 810', ['-1', '120']), ('1368 768', ['-1', '60']), ('1360 768', ['-1', '60']), ('1280 800', ['-1', '60']), ('1152 864', ['-1', '60']), ('1280 720', ['-1', '60']), ('1024 768', ['-1', '60']), ('960 720', ['-1', '120']), ('928 696', ['-1', '120']), ('896 672', ['-1', '120']), ('1024 576', ['-1', '60']), ('960 600', ['-1', '120']), ('960 540', ['-1', '60']), ('800 600', ['-1', '56']), ('840 525', ['-1', '120']), ('864 486', ['-1', '60']), ('800 512', ['-1', '120']), ('700 525', ['-1', '120']), ('800 450', ['-1', '120']), ('640 512', ['-1', '120']), ('720 450', ['-1', '120']), ('700 450', ['-1', '120']), ('640 480', ['-1', '60']), ('720 405', ['-1', '59']), ('684 384', ['-1', '120']), ('680 384', ['-1', '120']), ('640 400', ['-1', '120']), ('576 432', ['-1', '120']), ('640 360', ['-1', '59']), ('512 384', ['-1', '120']), ('512 288', ['-1', '120']), ('480 270', ['-1', '120']), ('400 300', ['-1', '113']), ('432 243', ['-1', '119']), ('320 240', ['-1', '120']), ('360 202', ['-1', '118']), ('320 180', ['-1', '119'])]

Windows 7
[('320 200', ['32', '60']), ('320 240', ['32', '60']), ('400 300', ['32', '60']), ('512 384', ['32', '60']), ('640 400', ['32', '60']), ('640 480', ['32', '60']), ('800 600', ['32', '60']), ('1024 768', ['32', '60']), ('1152 864', ['32', '60']), ('180 600', ['32', '60']), ('1280 720', ['32', '60']), ('1280 768', ['32', '60']), ('1280 800', ['32', '60']), ('1280 960', ['32', '60']), ('1280 1024', ['32', '60']), ('1360 768', ['32', '60']), ('1366 768', ['32', '60']), ('1400 1050', ['32', '60']),('1440 900', ['32', '60']), ('1600 900', ['32', '60']), ('1680 1050', ['32', '60']), ('1920 1080', ['32', '60'])]

Hmm, odd. Perhaps “-1” has some specific meaning–an error code (like “no value found”), or some such thing?

I note that the listing provided by Windows seems to be shorter than the one provided by Mint. Have you compared the two lists? Do the resolutions given match, and do those match what each OS’s monitor-settings programs offer?

One more thing–would you try the following code under Mint, please, and see what output it produces?

from Xlib import X, display
from Xlib.ext import randr

d = display.Display()
s = d.screen()
window = s.root.create_window(0, 0, 1, 1, 1, s.root_depth)

res = randr.get_screen_resources(window)
for mode in res.modes:
    w, h = mode.width, mode.height
    print ("Width: {}, height: {}".format(w, h))

[edit]
In fact, researching the module used in the code just above, I don’t see a mention of bits per pixel in the information that it gives. Maybe Panda is reporting “-1” as the value for the “bits per pixel” because randr doesn’t provide that information?

Honestly, I still do not know Mint and do not even know where to look at it, but I think I’ll find out.

Width: 1920, height: 1080
Width: 1920, height: 1080
Width: 1920, height: 1080
Width: 1920, height: 1080
Width: 1680, height: 1050
Width: 1680, height: 1050
Width: 1600, height: 1024
Width: 1400, height: 1050
Width: 1600, height: 900
Width: 1600, height: 900
Width: 1600, height: 900
Width: 1600, height: 900
Width: 1280, height: 1024
Width: 1440, height: 900
Width: 1400, height: 900
Width: 1400, height: 900
Width: 1280, height: 960
Width: 1440, height: 810
Width: 1440, height: 810
Width: 1368, height: 768
Width: 1368, height: 768
Width: 1360, height: 768
Width: 1360, height: 768
Width: 1280, height: 800
Width: 1280, height: 800
Width: 1280, height: 800
Width: 1280, height: 800
Width: 1152, height: 864
Width: 1280, height: 720
Width: 1280, height: 720
Width: 1280, height: 720
Width: 1280, height: 720
Width: 1024, height: 768
Width: 1024, height: 768
Width: 960, height: 720
Width: 928, height: 696
Width: 896, height: 672
Width: 1024, height: 576
Width: 1024, height: 576
Width: 1024, height: 576
Width: 1024, height: 576
Width: 960, height: 600
Width: 960, height: 600
Width: 960, height: 540
Width: 960, height: 540
Width: 960, height: 540
Width: 960, height: 540
Width: 800, height: 600
Width: 800, height: 600
Width: 800, height: 600
Width: 840, height: 525
Width: 840, height: 525
Width: 864, height: 486
Width: 864, height: 486
Width: 800, height: 512
Width: 700, height: 525
Width: 800, height: 450
Width: 800, height: 450
Width: 640, height: 512
Width: 720, height: 450
Width: 700, height: 450
Width: 700, height: 450
Width: 640, height: 480
Width: 640, height: 480
Width: 720, height: 405
Width: 720, height: 405
Width: 684, height: 384
Width: 684, height: 384
Width: 680, height: 384
Width: 680, height: 384
Width: 640, height: 400
Width: 640, height: 400
Width: 576, height: 432
Width: 640, height: 360
Width: 640, height: 360
Width: 640, height: 360
Width: 640, height: 360
Width: 512, height: 384
Width: 512, height: 288
Width: 512, height: 288
Width: 480, height: 270
Width: 480, height: 270
Width: 400, height: 300
Width: 400, height: 300
Width: 432, height: 243
Width: 432, height: 243
Width: 320, height: 240
Width: 360, height: 202
Width: 360, height: 202
Width: 320, height: 180
Width: 320, height: 180

I think the number of modes depends on the video card driver.

I use Ubuntu, and if Mint is similar, you should find it in the “settings” application, which should be available from your applications menu.

Regarding the list of resolutions output by the code that I gave, at a glance the first few entries look the same as those produced in your original output.

You may well be right, indeed. Still, it will be interesting to compare the lists output by our code with those given in the monitor settings, I think.

Thank you for looking into this, by the way! :slight_smile:

(And I hope that you enjoy Linux Mint! ^_^)

If we consider that the xrandr utility is used, and the output is plausible in terms of screen resolution, and the outdated dimensions are simply discarded in the Lunix GUI, in Windows there is a tick for this to discard all outdated modes.

In your case, the xrandr is to blame, she returns some mythical maximum size. If you write your own parser of all modes, then this is easy. The fact that this problem is easily solved, and makes it possible to know the available sizes. In Panda3D, before the start of the start run () this is very necessary. This is currently not possible with the Panda3D API.

I definitely like the fact that I collected Panda3D without a headache and at least some kind of mistake, so far I can not believe what is possible. Although in Windows I stumbled at every step, installed the compiler, installed the IDE, there were problems: that the compiler is not the one, the version is not the same, then it is not updated and so infinitely.

That is possible, indeed.

I’ve considered this, but for the moment I’d rather wait and see what solution the Panda devs come up with–I imagine that they’ll want the API to work on all available platforms. That way I can stick to using Panda, rather than figuring out some other API.

I’m surprised that you had so much trouble under Windows! But conversely, glad that you seem to be having a much easier time under Linux!

I installed the driver on the recommended Nvidia, now my code:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import WindowProperties
from collections import OrderedDict

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        mode_display = OrderedDict()

        mode = base.pipe.getDisplayInformation()

        for i in range( mode.getTotalDisplayModes()):
            width  = mode.getDisplayModeWidth(i)
            height = mode.getDisplayModeHeight(i)
            bits   = mode.getDisplayModeBitsPerPixel(i)
            frequency = mode.getDisplayModeRefreshRate(i)
            mode_display[str(width)+' '+str(height)] = [str(bits), str(frequency)]
            
        mode_display_list = list(mode_display.items())
        get_el = mode_display_list[-1][0].split(' ')
        
        print (mode_display_list)
        
        #props = WindowProperties()
        #props.setSize(int(get_el[0]), int(get_el[1]))
        #base.win.requestProperties(props)

app = MyApp()
app.run()

Really returns one mode that is current.

Your problem is that you have combined the displays into one workspace, the answer is here:

I’ve seen suggestions to this effect before in my searches–but I’m not sure of what to do about them. I don’t think that this is something that I intentionally did, as far as I recall–although it’s possible that I’m forgetting, or, more likely, that I did so by accident.

Looking at that screen, I don’t see an option to have it not combine them. The drop-down seems to select either the combined space, or one monitor or the other. Selecting one seems to have no effect on the output of my code. Unless this only works after a reset? (There’s no indication to that effect that I see.)

And the thing is, is this something that we can expect the average user to set up? It’s not exactly obvious, and the result in Panda looks like an bug in the game.

Furthermore, the Python “randr” code that I gave above does seem to come up with a list of resolutions. So unless it’s using a fallback list, it seems, at least, that there’s some way of getting more than just the combined resolution…

I meant the problem, after turning off the second display. You stated that your screen resolution remains the same, which is actually not normal. Combining monitors is actually mandatory if you need a common space. However, after an additional monitor is turned off, a reset will occur.

As I said, after installing the Nvidia driver, I received only one resolution when using my code. On the main (free) driver, I got all the monitor resolutions. It seems that the problem has a pattern and is associated with the driver. All this happens on the side of the panda.

But I decided for myself that I would use randr, bypassing the panda directly. I suggest this is a guaranteed way to find out the available resolution.

I think that I meant that I still get only a single “mode” and “resolution”, not that the reported resolution remains the same. (Sorry if I previously worded that unclearly! ^^; )

(And indeed, double-checking, that does seem to be the case: if I pull out my HDMI cable, I still get only a single “mode”, but it now has a resolution matching that of my laptop’s monitor (1366 x 768).

Hmm… That’s interesting. Unfortunately, I’m not sure that the default drivers are as effective as the NVidia drivers in my case–I vaguely recall that I had some reason for installing the NVidia drivers, rather than just using the defaults. (It may have been–although I’m guessing here–that the defaults didn’t correctly handle the fact that my laptop has two GPUs: a relatively-powerful one, and a weaker, integrated one.)

Fair enough! It does seem reliable right now, indeed. Still, for myself I think that I still want to wait to see what solution the Panda devs come up with–for now, at least.

Just to put an update in this thread: it turns out that Panda can be making a better call to Xrandr than it currently is to find out the full list of resolutions, and I’ll be making a change to Panda to get this full list.

I would like to know if it will be available without calling ShowBase, in fact it is useful to know the screen sizes before the panda is launched, to set the maximum resolution of the screen at the start. However, in this case, you have to set the minimum 800 * 600, which obliges the user to unnecessary action to change the resolution.

You can delay opening a window and access the GraphicsPipe earlier to query the available resolutions:

1 Like

This is a good solution, but it would be nice to have something like an independent utility. In fact, this is easy to do, as there is a GitHub - tobspr/P3DModuleBuilder: Toolkit to make C++ modules and extensions for the Panda3D engine tool and many C ++ solutions online for obtaining monitor resolution for different OSs. I think I will go this way.