Automatically choosing displays

I just ran across a problem of running Panda in non-opengl compatible hardware. I don’t want to have to configure Config.prc so I wrote the following snippet so that my portfolio will just fallback into the next display type that works. Replace:

import direct.directbase.DirectStart

With this:

import sys, getopt, subprocess # If you import these before, remove
def detectDisplay():
    # Display type detection
    test_order = ["opengl", "dx9", "dx8", "tiny"] # Feel free to reorder to your taste
    py_path = "python" # The path to the python executable to be invoked
    try:
        options, args = getopt.getopt(sys.argv[1:], "d:t:", ["display=","tested="])
        tried_displays = []
        # Parse arguments passed to the script
        for opt, arg in options:
            if opt in ("-d", "--display"):
                #print "Trying display",arg
                if arg == "opengl":
                    loadPrcFileData("", "load-display pandagl")
                    tried_displays.append("opengl")
                elif arg == "dx8":
                    loadPrcFileData("", "load-display pandadx8")
                    tried_displays.append("dx8")
                elif arg == "dx9":
                    loadPrcFileData("", "load-display pandadx9")
                    tried_displays.append("dx9")
                elif arg == "tiny":
                    loadPrcFileData("", "load-display tinydisplay")
                    tried_displays.append("tiny")
            if opt in ("-t", "--tested"):
                prev_tested = arg.split(",")
                tried_displays.extend(prev_tested)
        try: # Now try to DirectStart
            import direct.directbase.DirectStart
        except StandardError: # If DirectStart fails, try other display modes
            # Remove from test_order the modes in tried_displays
            new_test = []
            for display in test_order:
                if display not in tried_displays:
                    new_test.append(display)
            if len(new_test) == 0:
                print "All displays failed. Quitting"
                sys.exit(2)
            print "Display failed to initialize, trying",new_test[0]
            subprocess.Popen(["%s %s --display %s --tested %s" % (py_path, sys.argv[0], new_test[0], ",".join(tried_displays))], shell=True)
            sys.exit(2)
    except getopt.GetoptError: # If nothing was passed via commandline, just DirectStart normally
        try:
            import direct.directbase.DirectStart
        except StandardError: # DirectStart failed, start testing other displays
            subprocess.Popen(["%s %s --display %s" % (py_path, sys.argv[0], test_order[0])], shell=True)
            sys.exit(2)
detectDisplay()

The first variable is the order which the display types will be tested. You can change this to your liking. The second variable is in case you will be using a python that isn’t installed in the system, you can change this path to the copy of python you want. I just wrapped it in a function to stop polluting the global namespace.

Hope this is useful to someone else. This is under the public domain.

Hee hee, I hate to tell you, but try this in Config.prc:

load-display pandagl
aux-display pandadx9
aux-display pandadx8
aux-display tinydisplay

That will fallback to other display modules when one of them fails loading. =)

Oh. Hmm. Going to go through the manual to document this better then.

ZeroByte dont feel bad. I have this all the time. I write something but then panda3d already does it better.