JeDy111
Posts: 27
Joined: Tue Sep 03, 2019 8:35 pm

PI3D - specify the HDMI port to use

Wed Apr 08, 2020 8:13 pm

Hello,

In PI3D, is it possible to specify the HDMI port to use?

I have two monitors and my python script should display a video on HDMI-0 and PI3D on HDMI-1.

Please apologize if the answer is obvious, but I have not been able to find this information in the documentation nor in the examples.
I guess it should be in the pi3d.Display.create function arguments.

Note: I have "use_glx=True"

Thanks

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Sat Apr 11, 2020 10:00 pm

Hi, it's not obvious! I will play around with this tomorrow and see if I can figure it out. (It will need to have the option added to the arguments of Display.create() as you say.)

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

wcasey
Posts: 1
Joined: Sun Apr 12, 2020 4:35 am

Re: PI3D - specify the HDMI port to use

Sun Apr 12, 2020 4:43 am

I think I'm looking for the same thing. I want to modify the pi3d PictureFrame.py demo script to simultaneously drive two different displays (HDMI1 and HDMI2) so each frame displays pix from a different subfolder from the other. Can't see how I might specify the display differently in the same script. Seems a shame to have to buy 2 RPi 4s when 1 has two ports. Ideas?

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Sun Apr 12, 2020 1:04 pm

OK I've proved to myself that this will require the help of someone else with two displays attached to their RPi. (I can't even get one to work properly, I have to take my HDMI through an HDMI to VGA adapter. Probably because I am using an ancient display). This is what I would do if I had two working displays:

1. With only one diplay plugged in ``ls /tmp/.X11-unix`` in a terminal (you should get something like X0)
2. With two displays ``ls /tmp/.X11-unix`` don't know what you will get but hopefully something additional
3. Edit pi3d/util/DisplayOpenGL.py which will either be in /usr/local/lib/python3.7/dist-packages/ or if you clone the github repository, wherever that is (normally /home/pi/pi3d, path in /home/pi3d_demos/demo.py) something like (from about line 70):

Code: Select all

      display_name = None #previous to RPi4 this worked but now problems..
      for f in os.listdir('/tmp/.X11-unix'):
        display_name = b':' + f[1:].encode('utf-8')
        if display_name == b':0':
          break # use X0 if this exist, else use last in list (which might work!)
      ##########
      display_name = b':0.1' # or b':1', or other permutations
      ##########
      self.d = xlib.XOpenDisplay(display_name)
Then run ``python3 Minimal.py`` from a terminal.

If you get a chance to try this let me know how you get on. Depending on results I might try more things, then modify the module to cope with this in a more structured way. Thanks for your help.

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

/tmp/sven
Posts: 5
Joined: Sat Apr 18, 2020 1:04 pm

Re: PI3D - specify the HDMI port to use

Sat Apr 18, 2020 2:39 pm

Hi all,
I ran into the same problem trying to get PictureFrame running on a Pi4 using both HDMI outputs.

To sum up what I did.
in /boot/config:

Code: Select all

#dtoverlay=vc4-fkms-v3d
max_framebuffers=2
So I got /dev/fb0 and /dev/fb1 seperate allowing Xorg to create 2 screens.
In my case left display is ":0.0" and right display is ":0.1".

To answer paddygs question:

Code: Select all

l /tmp/.X11-unix/
total 0
srwxrwxrwx 1 root root 0 Apr 18 15:44 X0
Running any pi3d templates will result in python to freeze at

Code: Select all

import 'pi3d' # <_frozen_importlib_external.SourceFileLoader object at 0xb668ecd0>
Trying to work my way thru paddyg's suggestions I hard set

Code: Select all

#Line 75
self.d = xlib.XOpenDisplay(b':0.0')
in DisplayOpenGL.py but it never gets to that code because on line 49 "elif PLATFORM == PLATFORM_PI:" matches first.

So I commented almost everyhting out which resulted in

Code: Select all

    self.d = xlib.XOpenDisplay(b':0.0')
NameError: name 'xlib' is not defined
Of course because "PLATFORM == PLATFORM_PI" matches somewhere else not including xlib.

Follwing the appraoch of setting platform permanent to PLATFORM_LINUX (in constants/__init__.py) results in

Code: Select all

  File "/usr/local/lib/python3.7/dist-packages/pi3d/util/DisplayOpenGL.py", line 152, in create_display
    if b"ES" in version:
TypeError: argument of type 'NoneType' is not iterable
And unfortunately I'm lost here now.


Sven

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Sat Apr 18, 2020 10:47 pm

Sven, thanks for having a look at this for me. I'm not sure what you mean by "running any pi3d templates..." have you managed to run any of the pi3d_demos scripts OK before trying to get both screens working?

I will have a look on my RPi in the morning and see what's happening. The platform is set in pi3d/constants/__init__.py First pi3d looks in /proc/modules to see if there's a line starting "vc4" if there is then it assumes that the accelerated graphics as used on the RPi4 is being used (i.e. FakeKMS) It then checks to see if the libbcm_host.so file is there and only if acceleration is not in use, and bcm_host is there, does it set platform to PLATFORM_PI. So it's hard to see why the standard X11 linux code in DisplayOpenGL.py isn't running... But this probably needs reviewing as there must be a better way to determine what setup pi3d should use.

Let you know what I find tomorrow.

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Sun Apr 19, 2020 9:09 am

Sven, OK, I had quick look on my RPi4 this morning. The only way I can get any OpenGL output is if I set the driver (using raspi-config/advanced/GLdriver) to Fake KMS. I checked that does indeed toggle the existence of the vc4 line in /proc/modules. So for pi3d to work on RPi4, PLATFORM has to be PLATFORM_LINUX (i.e. 3). (Also the X11 server has to be running, using boot to desktop, startx or xinit etc)

Can I suggest you revert all your changes and make sure pi3d is working normally ($ cd ~/pi3d_demos; python3 Minimal.py). Then put some print()s into DisplayOpenGL.py to check which bits are running (do this one change at a time and test after each). You could do:

Code: Select all

class DisplayOpenGL(object):
  def __init__(self):
    print(f"PLATFORM={PLATFORM}") #<<<<<<<<<<
    self.d = None # display if x11 window or pygame used
then when that's reliably giving you a 3, try

Code: Select all

          break # use X0 if this exist, else use last in list (which might work!)
      print(f"display={display_name}")
      self.d = xlib.XOpenDisplay(display_name)
finally try setting display_name to b':0.0' That works fine on my RPi4 and laptop. Finally, with the additional screen plugged in try b'0.1'

Let me know what happens! Thanks for your help

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

/tmp/sven
Posts: 5
Joined: Sat Apr 18, 2020 1:04 pm

Re: PI3D - specify the HDMI port to use

Mon Apr 20, 2020 12:43 pm

Hey Paddy,
thank you for guiding me into the right direction.

To get both displays running I can't use 'dtoverlay=vc4-fkms-v3d'.
But having this commented out vc4 module isn't loaded.

I loaded it by hand and all of a sudden everything just works fine.

To sum things up:
config.txt

Code: Select all

[pi4]
# dtoverlay=vc4-fkms-v3d
max_framebuffers=2
Xorg.conf

Code: Select all

Section "Device"
  Identifier "fb0"
  driver "fbdev"
  Option "fbdev" "/dev/fb0"
 Option "ShadowFB" "off"
#  Option "Rotate" "CCW"
EndSection

Section "Device"
  Identifier "fb1"
  driver "fbdev"
  Option "fbdev" "/dev/fb1"
  Option "ShadowFB" "off"
#  Option "Rotate" "CCW"
EndSection

Section "Monitor"
  Identifier "left"
EndSection

Section "Monitor"
  Identifier "right"
EndSection

Section "Screen"
  Identifier "right"
  Device "fb1"
  Monitor "right"
EndSection

Section "Screen"
  Identifier "left"
  Device "fb0"
  Monitor "left"
EndSection

Section "ServerLayout"
  Identifier   "Main"
  Screen       0 "left"
  Screen       1 "right" RightOf "left"
EndSection
This gives you displays :0.0 and :0.1
And don't forget to load vc4

I made a quick change in DisplayOpenGL.py to simple use DISPLAY env variable.

Code: Select all

    else: # use libX11
      #import subprocess # default name using XOpenDisplay(None) doesn't work on RPi4
      import os
      display_name = None #previous to RPi4 this worked but now problems..
      '''for f in os.listdir('/tmp/.X11-unix'):
        display_name = b':' + f[1:].encode('utf-8')
        if display_name == b':0':
          break # use X0 if this exist, else use last in list (which might work!)
      self.d = xlib.XOpenDisplay(display_name)'''
      display_name = os.environ["DISPLAY"]
      print("Using DISPLAY {}".format(display_name))
      self.d = xlib.XOpenDisplay(str.encode(display_name))
      if self.d:
        self.screen = xlib.XDefaultScreenOfDisplay(self.d)
        self.width, self.height = xlib.XWidthOfScreen(self.screen), xlib.XHeightOfScreen(self.screen)
      else:
        print('************************\nX11 needs to be running\n************************')
        assert False, 'Couldnt open DISPLAY {}'.format(display_name)
Sven

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 26671
Joined: Sat Jul 30, 2011 7:41 pm

Re: PI3D - specify the HDMI port to use

Mon Apr 20, 2020 1:22 pm

/tmp/sven wrote:
Mon Apr 20, 2020 12:43 pm
Hey Paddy,
thank you for guiding me into the right direction.

To get both displays running I can't use 'dtoverlay=vc4-fkms-v3d'.
But having this commented out vc4 module isn't loaded.

I loaded it by hand and all of a sudden everything just works fine.

To sum things up:
config.txt

Code: Select all

[pi4]
# dtoverlay=vc4-fkms-v3d
max_framebuffers=2
Xorg.conf

Code: Select all

Section "Device"
  Identifier "fb0"
  driver "fbdev"
  Option "fbdev" "/dev/fb0"
 Option "ShadowFB" "off"
#  Option "Rotate" "CCW"
EndSection

Section "Device"
  Identifier "fb1"
  driver "fbdev"
  Option "fbdev" "/dev/fb1"
  Option "ShadowFB" "off"
#  Option "Rotate" "CCW"
EndSection

Section "Monitor"
  Identifier "left"
EndSection

Section "Monitor"
  Identifier "right"
EndSection

Section "Screen"
  Identifier "right"
  Device "fb1"
  Monitor "right"
EndSection

Section "Screen"
  Identifier "left"
  Device "fb0"
  Monitor "left"
EndSection

Section "ServerLayout"
  Identifier   "Main"
  Screen       0 "left"
  Screen       1 "right" RightOf "left"
EndSection
This gives you displays :0.0 and :0.1
And don't forget to load vc4

I made a quick change in DisplayOpenGL.py to simple use DISPLAY env variable.

Code: Select all

    else: # use libX11
      #import subprocess # default name using XOpenDisplay(None) doesn't work on RPi4
      import os
      display_name = None #previous to RPi4 this worked but now problems..
      '''for f in os.listdir('/tmp/.X11-unix'):
        display_name = b':' + f[1:].encode('utf-8')
        if display_name == b':0':
          break # use X0 if this exist, else use last in list (which might work!)
      self.d = xlib.XOpenDisplay(display_name)'''
      display_name = os.environ["DISPLAY"]
      print("Using DISPLAY {}".format(display_name))
      self.d = xlib.XOpenDisplay(str.encode(display_name))
      if self.d:
        self.screen = xlib.XDefaultScreenOfDisplay(self.d)
        self.width, self.height = xlib.XWidthOfScreen(self.screen), xlib.XHeightOfScreen(self.screen)
      else:
        print('************************\nX11 needs to be running\n************************')
        assert False, 'Couldnt open DISPLAY {}'.format(display_name)
Sven
That shouldn't work. The reason you get two displays with KMS disabled is that you are using the legacy graphics driver. THis instantiates two framebuffers. WIth KMS you only have one frame buffer than covers the two displays (It's a pain - we have talked about how to change that, but it will involve some work in the graphics driver). I am not at all sure what happens if you have two frame buffers already and then start up KMS, if indeed KMS can be started up late.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Contrary to popular belief, humorous signatures are allowed.
I've been saying "Mucho" to my Spanish friend a lot more lately. It means a lot to him.

/tmp/sven
Posts: 5
Joined: Sat Apr 18, 2020 1:04 pm

Re: PI3D - specify the HDMI port to use

Mon Apr 20, 2020 1:31 pm

Indeed, performance is quite non-existing.

Any other hint to get access to the screens individually in Xorg by 0.0 and 0.1?

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Mon Apr 20, 2020 1:45 pm

Maybe. I'm out now (exercise ration) but will explain when back.

OK back now.

What I can do on my ubuntu laptop - which sounds like it's the way rasbian might be set up - is to start a second instance of pi3d running, and in that one move the display off to one side. If I make the x position equal to the screen width it goes right off and appears on a second screen plugged into the laptop. If it's set to be full screen then it fills the second screen - however the aspect ratio is derived from the first screen so I have to change the size to match. Fortunately pi3d Display uses resize to move the x11 display so that allows resizing to happen then.

My laptop has screen 1366x768 and the extra screen is 1280x1024 so the code goes

Code: Select all

display = pi3d.Display.create(x=0, y=0, w=0, h=0...) #these are all defaults so can be left out, they make the display full screen
display.resize(x=1366, y=0, w=1280, h=1024)
...
There are no changes required in pi3d to get it to do this... if it works!

Paddy

PS this seems to work with use_glx=True i.e. with transparent background to the x11 window.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

/tmp/sven
Posts: 5
Joined: Sat Apr 18, 2020 1:04 pm

Re: PI3D - specify the HDMI port to use

Mon Apr 20, 2020 4:50 pm

Creating the pi3d window on the second screen works just fine with:

Code: Select all

DISPLAY = pi3d.Display.create(x=1920, y=0, w=1920, h=1080, ..
Might be off topic now but is there a way to disable the screen spanning having 2 screens (:0.0, :0.1) with 1920x1080 instead of 1 screen with 3840x1080?

Thanks,
Sven

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Mon Apr 20, 2020 5:35 pm

Sven, from James' comment it sounds like there might be issues with that. At some stage I will get a second screen set up and do some experiments...

Meanwhile have you managed to get two instances of the PictureFrame app running at the same time? Does it run OK? There might be problems with memory if you have big screens as you need foreground and background textures for both screens.

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

/tmp/sven
Posts: 5
Joined: Sat Apr 18, 2020 1:04 pm

Re: PI3D - specify the HDMI port to use

Tue Apr 21, 2020 6:09 pm

Ran fine the whole day.
Only the transition looks a little jerky, especially when both instances doing it at the same time, but can't see any memory or cpu peaks.

Might be an idea to change the code to use single pi3d instance and 2 sprites or something..

Sven

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: PI3D - specify the HDMI port to use

Tue Apr 21, 2020 8:12 pm

Sven, that sounds good. Rather than try to do any major re-engineering inside pi3d to cope with two Display instances, it's probably easiest to a) make the transition time long so the change in alpha with each frame is very small b) ensure that only one PictureFrame.py is transitioning at once with no other processing going on. To do that, I think I would make a very simple semaphore system where the fading process creates a file on /dev/shm something along the lines of (you could also use a FIFO pipe etc)

Code: Select all

while DISPLAY.loop_running():
  tm = time.time()
  if nFi > 0:
    if (tm > nexttm and not paused) or (tm - nexttm) >= 86400.0: # this must run first iteration of loop
      ############################ Don't do file loading while other instance is doing it, or fading
      while "flag" in os.listdir("/dev/shm"):
        time.sleep(0.1)
      with open("/dev/shm/flag","w") as f:
        f.write("-")
      ############################
      nexttm = tm + time_delay
      a = 0.0 # alpha - proportion front image to back
      sbg = sfg
      sfg = None
      ...
    if a < 1.0: # transition is happening
      a += delta_alpha
      ...
    else: # no transition effect safe to resuffle etc
      ############################ release flag
      os.remove("/dev/shm/flag")
      ############################
      if tm > next_check_tm:

 
PS if the GPU is struggling then that won't show in the normal CPU or memory checks.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

Return to “Graphics programming”