I have a small python3 and PySDL2 application that needs to run on a GUI-less debian linux. This is an embedded project running on a Librea Computer Board AML-S905X-CC. I have the HDMI output connected to a monitor and I can see the console so the video driver works. The desktop environment costs too much performance and is entirely unnecessary for my use case.
I have found someone else who has been able to achieve this a while back and the process seems familiar: https://discourse.libsdl.org/t/possible-to-run-sdl2-headless/25665
The code is pretty simple:
import sys
import os
import sdl2.ext
os.putenv("SDL_VIDEODRIVER","dummy")
RESOURCES = sdl2.ext.Resources(__file__, "resources")
print("start")
sdl2.ext.init()
window = sdl2.ext.Window("Hello World!",size=(720,480), flags=sdl2.SDL_WINDOW_HIDDEN)
window.show()
while True:
continue
The application does run, however it just stays on the console screen.
As far as I know if there is no driver, linux just writes to the framebuffer directly. So if I can set up PySDL2 to do that, and show the gui in full screen, that's all I am looking for.
Last note is that I know this is possible because this is something I managed to achieve once before, about a year ago. However, due to a drive crash, that example has been lost.
I got it working. Ok so here's what I did.
The most important part was running the UpdateWindow(w) and RenderPresent(r) which were not mentioned in the PySDL docs. But maybe that's because it was such a niche use case scenario.
Bare in mind, this is likely not perfect code and that's because I'm no expert. But since all the experts don't bother to help figure these sort of questions out, this is the best you get:
import ctypes
import sys
from sdl2 import *
import time
SDL_Init(SDL_INIT_EVENTS)
w = SDL_CreateWindow(b"test", 0,0, 800,600, SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_HIDDEN)
SDL_ShowWindow(w)
SDL_RaiseWindow(w)
window_surface = SDL_GetWindowSurface(w)
r = SDL_CreateSoftwareRenderer(window_surface)
#r = sdl2.ext.Renderer(w, -1, (800,600), sdl2.SDL_RENDERER_SOFTWARE)
#sprite_factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=r)
#sprite = sprite_factory.from_image("resources/imgs/fr.png")
event = SDL_Event()
running = True
while running:
while SDL_PollEvent(event) != 0:
print("events were present", event.key.keysym.sym)
#print(SDL_GetKeyName(event.key.keysym.sym))
if event.type == SDL_QUIT:
running = False
break
if event.type == SDL_KEYDOWN:
#if event.key.keysym.sym == sdl2.SDLK_ESCAPE:
running = False
print("keydown detected")
break
SDL_RenderClear(r)
#sprite_render = sprite_factory.create_sprite_render_system(r)
#sprite_render.render(sprite, x=100, y=100)
#WHITE = sdl2.ext.Color(255,255,255,255)
#r.draw_rect((5,5,64,64), WHITE)
SDL_UpdateWindowSurface(w)
SDL_RenderPresent(r)
SDL_DestroyWindow(w)
SDL_Quit()
exit()