Moving to offscreen Driver

This commit is contained in:
2026-02-25 00:21:36 -06:00
parent aab94d5e96
commit cbdd4a2952
2 changed files with 32 additions and 8 deletions

View File

@@ -1,3 +1,4 @@
import mmap
import os
import threading
import time
@@ -147,7 +148,9 @@ class DisplayThread(threading.Thread):
if self.dev_mode:
os.environ.setdefault("SDL_VIDEODRIVER", "x11")
else:
os.environ["SDL_VIDEODRIVER"] = "kmsdrm"
# SDL kmsdrm is incompatible with the Amlogic MESON DRM driver.
# Use offscreen rendering and blit pixels directly to /dev/fb0.
os.environ["SDL_VIDEODRIVER"] = "offscreen"
try:
pygame.init()
@@ -166,6 +169,19 @@ class DisplayThread(threading.Thread):
clock = pygame.time.Clock()
screen_w, screen_h = screen.get_size()
# Open /dev/fb0 for direct pixel writes (framebuffer mode only)
fb0_mmap = None
fb0_file = None
if not self.dev_mode:
try:
bpp = int(Path("/sys/class/graphics/fb0/bits_per_pixel").read_text())
fb0_file = open("/dev/fb0", "rb+")
fb0_mmap = mmap.mmap(fb0_file.fileno(), screen_w * screen_h * (bpp // 8))
except Exception as e:
print(f"[display] Failed to open /dev/fb0: {e}")
pygame.quit()
return
clock_font_path = _find_font(self.config.clock_font_path, _CLOCK_FONT_CANDIDATES)
msg_font_path = _find_font(self.config.message_font_path, _MESSAGE_FONT_CANDIDATES)
@@ -205,9 +221,17 @@ class DisplayThread(threading.Thread):
last_msg_text = None
self._draw_clock(screen, clock_font, screen_w, screen_h)
pygame.display.flip()
if fb0_mmap is not None:
fb0_mmap.seek(0)
fb0_mmap.write(pygame.image.tostring(screen, "BGRA"))
else:
pygame.display.flip()
clock.tick(self.config.fps)
if fb0_mmap:
fb0_mmap.close()
if fb0_file:
fb0_file.close()
pygame.quit()
def _create_surface(self) -> pygame.Surface:
@@ -218,10 +242,10 @@ class DisplayThread(threading.Thread):
pygame.display.set_caption("KH Clock [DEV]")
return surface
flags = pygame.FULLSCREEN | pygame.NOFRAME
if self.config.width and self.config.height:
return pygame.display.set_mode((self.config.width, self.config.height), flags)
return pygame.display.set_mode((0, 0), flags)
# Read actual framebuffer dimensions from sysfs
size_str = Path("/sys/class/graphics/fb0/virtual_size").read_text().strip()
w, h = map(int, size_str.split(","))
return pygame.display.set_mode((w, h))
@staticmethod
def _draw_clock(