147 lines
4.4 KiB
Python
Executable File
147 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
GTK4 Rendering Test - Verifies actual rendering by drawing and saving
|
|
Tests the s390x Mesa bug where GTK apps show black screens
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
|
|
# Parse renderer argument BEFORE importing GTK
|
|
# GSK_RENDERER must be set before GTK initializes
|
|
renderer = None
|
|
output_file = None
|
|
|
|
for i, arg in enumerate(sys.argv[1:], 1):
|
|
if arg.startswith('--renderer='):
|
|
renderer = arg.split('=', 1)[1]
|
|
elif not arg.startswith('--'):
|
|
output_file = arg
|
|
|
|
if renderer:
|
|
os.environ['GSK_RENDERER'] = renderer
|
|
print(f"Setting GSK_RENDERER={renderer} before GTK import")
|
|
|
|
#Set debug to print rear renderer of app
|
|
os.environ['GSK_DEBUG'] = "renderer"
|
|
|
|
# Now import GTK (after setting environment)
|
|
import gi
|
|
gi.require_version('Gtk', '4.0')
|
|
from gi.repository import Gtk, GLib
|
|
import cairo
|
|
|
|
class RenderTestApp(Gtk.Application):
|
|
def __init__(self, output_file):
|
|
super().__init__(application_id='org.test.gtk4render')
|
|
self.output_file = output_file
|
|
self.rendered = False
|
|
self.drawing_area = None
|
|
|
|
def do_activate(self):
|
|
window = Gtk.ApplicationWindow(application=self)
|
|
window.set_title("GTK4 Rendering Test")
|
|
window.set_default_size(400, 300)
|
|
|
|
self.drawing_area = Gtk.DrawingArea()
|
|
self.drawing_area.set_draw_func(self.draw_callback)
|
|
|
|
window.set_child(self.drawing_area)
|
|
window.present()
|
|
|
|
# Wait for rendering, then save and quit
|
|
GLib.timeout_add(2000, self.save_and_quit)
|
|
|
|
def draw_callback(self, area, cr, width, height):
|
|
"""Draw colorful pattern to prove rendering works"""
|
|
# Red rectangle
|
|
cr.set_source_rgb(1.0, 0.0, 0.0)
|
|
cr.rectangle(10, 10, 100, 100)
|
|
cr.fill()
|
|
|
|
# Green rectangle
|
|
cr.set_source_rgb(0.0, 1.0, 0.0)
|
|
cr.rectangle(130, 10, 100, 100)
|
|
cr.fill()
|
|
|
|
# Blue rectangle
|
|
cr.set_source_rgb(0.0, 0.0, 1.0)
|
|
cr.rectangle(250, 10, 100, 100)
|
|
cr.fill()
|
|
|
|
# Yellow circle
|
|
cr.set_source_rgb(1.0, 1.0, 0.0)
|
|
cr.arc(200, 200, 50, 0, 2 * 3.14159)
|
|
cr.fill()
|
|
|
|
print(f"Draw callback called - rendering {width}x{height} surface")
|
|
self.rendered = True
|
|
|
|
def save_and_quit(self):
|
|
"""Save the rendered surface to PNG and exit"""
|
|
if not self.rendered:
|
|
print("WARNING: Draw function not called yet")
|
|
print("RESULT: WARN - Rendering may not have occurred")
|
|
self.quit()
|
|
return False
|
|
|
|
try:
|
|
# Get the window and widget dimensions
|
|
width = self.drawing_area.get_width()
|
|
height = self.drawing_area.get_height()
|
|
|
|
print(f"Creating Cairo surface {width}x{height}")
|
|
|
|
# Create a Cairo image surface
|
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
|
|
cr = cairo.Context(surface)
|
|
|
|
# Re-render to this surface
|
|
self.draw_callback(None, cr, width, height)
|
|
|
|
# Save to PNG
|
|
surface.write_to_png(self.output_file)
|
|
|
|
# Check file was created and has reasonable size
|
|
if os.path.exists(self.output_file):
|
|
file_size = os.path.getsize(self.output_file)
|
|
print(f"SUCCESS: Saved rendering to {self.output_file} ({file_size} bytes)")
|
|
|
|
if file_size > 1000:
|
|
print("RESULT: PASS - Rendering verified")
|
|
else:
|
|
print(f"RESULT: FAIL - PNG file too small ({file_size} bytes)")
|
|
else:
|
|
print(f"RESULT: FAIL - Failed to create {self.output_file}")
|
|
|
|
except Exception as e:
|
|
print(f"ERROR: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
print("RESULT: FAIL - Exception during rendering")
|
|
|
|
self.quit()
|
|
return False
|
|
|
|
|
|
def main():
|
|
global output_file
|
|
|
|
if not output_file:
|
|
print(f"Usage: {sys.argv[0]} <output.png> [--renderer=ngl|gl|cairo|vulkan]")
|
|
print(f" --renderer: GSK renderer to use (default: auto-detect)")
|
|
sys.exit(1)
|
|
|
|
print(f"GTK4 Rendering Test - will save to {output_file}")
|
|
print(f"GSK_RENDERER: {os.environ.get('GSK_RENDERER', 'not set (auto-detect)')}")
|
|
print(f"GTK_RENDERER: {os.environ.get('GTK_RENDERER', 'not set')}")
|
|
|
|
app = RenderTestApp(output_file)
|
|
exit_status = app.run(None)
|
|
|
|
sys.exit(exit_status)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|