mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-30 19:33:45 +08:00
Reduce onroad UI work and move parameter refresh off render thread
This commit is contained in:
@@ -1,12 +1,23 @@
|
||||
from importlib.resources import as_file
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from openpilot.system.ui.lib import application
|
||||
|
||||
|
||||
def test_raylib_target_fps_limits_mici(monkeypatch):
|
||||
def test_raylib_target_fps_uses_mici_display_refresh(monkeypatch):
|
||||
monkeypatch.setattr(application, "OFFSCREEN", False)
|
||||
monkeypatch.setattr(application, "DEVICE_TYPE", "mici")
|
||||
monkeypatch.setattr(application, "PC", False)
|
||||
|
||||
assert application._raylib_target_fps(60) == 0
|
||||
|
||||
|
||||
def test_raylib_target_fps_limits_mici_desktop_preview(monkeypatch):
|
||||
monkeypatch.setattr(application, "OFFSCREEN", False)
|
||||
monkeypatch.setattr(application, "DEVICE_TYPE", "mici")
|
||||
monkeypatch.setattr(application, "PC", True)
|
||||
|
||||
assert application._raylib_target_fps(60) == 60
|
||||
|
||||
@@ -25,6 +36,62 @@ def test_raylib_target_fps_disables_limit_for_offscreen(monkeypatch):
|
||||
assert application._raylib_target_fps(60) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("covered", [False, True])
|
||||
def test_render_preserves_visible_layers_and_measures_complete_frame(monkeypatch, covered):
|
||||
monkeypatch.setattr(application, "PC", False)
|
||||
monkeypatch.setattr(application, "RECORD", False)
|
||||
monkeypatch.setattr(application.GuiApplication, "_set_log_callback", lambda _: None)
|
||||
app = application.GuiApplication(536, 240)
|
||||
app._scale = 1.0
|
||||
app._nav_stack_widgets_to_render = 2
|
||||
app._mouse = SimpleNamespace(get_events=list)
|
||||
app._burn_in_shift = lambda: (0, 0)
|
||||
app._monitor_fps = lambda: None
|
||||
app._show_fps = app._show_touches = False
|
||||
app._grid_size = app._profile_render_frames = 0
|
||||
|
||||
clock = SimpleNamespace(wall=10.0, cpu=1.0)
|
||||
monkeypatch.setattr(application.time, "monotonic", lambda: clock.wall)
|
||||
monkeypatch.setattr(application.time, "thread_time", lambda: clock.cpu)
|
||||
monkeypatch.setattr(application.rl, "window_should_close", lambda: False)
|
||||
monkeypatch.setattr(application.rl, "begin_drawing", lambda: None)
|
||||
monkeypatch.setattr(application.rl, "clear_background", lambda _: None)
|
||||
rendered = []
|
||||
|
||||
def draw(name):
|
||||
rendered.append(name)
|
||||
clock.wall += 0.004
|
||||
clock.cpu += 0.003
|
||||
|
||||
def present():
|
||||
clock.wall += 0.011
|
||||
clock.cpu += 0.001
|
||||
|
||||
def populate_cache():
|
||||
clock.wall += 0.003
|
||||
clock.cpu += 0.002
|
||||
|
||||
monkeypatch.setattr(application.rl, "end_drawing", present)
|
||||
app._populate_render_texture_cache = populate_cache
|
||||
app._nav_stack = [
|
||||
SimpleNamespace(render=lambda _: draw("road")),
|
||||
SimpleNamespace(covers_background=lambda _: covered, render=lambda _: draw("panel")),
|
||||
]
|
||||
frames = app.render()
|
||||
assert next(frames)
|
||||
clock.wall += 0.002
|
||||
clock.cpu += 0.001
|
||||
app.request_close()
|
||||
with pytest.raises(StopIteration):
|
||||
next(frames)
|
||||
|
||||
assert rendered == (["panel"] if covered else ["road", "panel"])
|
||||
draws = len(rendered)
|
||||
assert app.frame_timing == pytest.approx(application.FrameTiming(
|
||||
draws * 4 + 16, draws * 3 + 4, draws * 4, 2, 11,
|
||||
))
|
||||
|
||||
|
||||
def test_burn_in_shift_transitions_between_positions(monkeypatch):
|
||||
app = object.__new__(application.GuiApplication)
|
||||
app._burn_in_start_time = 100.0
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import pyray as rl
|
||||
import pytest
|
||||
from types import SimpleNamespace
|
||||
|
||||
from openpilot.system.ui import widgets
|
||||
from openpilot.system.ui.lib import scroll_panel2
|
||||
@@ -32,7 +33,7 @@ def make_scroller(monkeypatch):
|
||||
monkeypatch.setattr(gui_app, "_show_touches", False)
|
||||
monkeypatch.setattr(gui_app, "_mouse_events", [])
|
||||
monkeypatch.setattr(widgets, "PC", False)
|
||||
monkeypatch.setattr(widgets.device, "awake", True)
|
||||
monkeypatch.setattr(widgets, "device", SimpleNamespace(awake=True))
|
||||
monkeypatch.setattr(scroll_panel2, "TICI", True)
|
||||
|
||||
def make(items=None, **kwargs):
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import numpy as np
|
||||
import pyray as rl
|
||||
import pytest
|
||||
from types import SimpleNamespace
|
||||
|
||||
from openpilot.system.ui.lib.shader_polygon import triangulate
|
||||
from openpilot.system.ui.lib import shader_polygon
|
||||
from openpilot.system.ui.lib.shader_polygon import Gradient, draw_polygon, triangulate
|
||||
|
||||
|
||||
def test_triangulate_interleaves_polygon_chains():
|
||||
@@ -13,11 +17,11 @@ def test_triangulate_interleaves_polygon_chains():
|
||||
[10.0, 100.0],
|
||||
], dtype=np.float32)
|
||||
|
||||
assert triangulate(points) == [
|
||||
np.testing.assert_array_equal(triangulate(points), [
|
||||
[1.0, 10.0], [10.0, 100.0],
|
||||
[2.0, 20.0], [20.0, 200.0],
|
||||
[3.0, 30.0], [30.0, 300.0],
|
||||
]
|
||||
])
|
||||
|
||||
|
||||
def test_triangulate_drops_unpaired_last_point():
|
||||
@@ -29,7 +33,54 @@ def test_triangulate_drops_unpaired_last_point():
|
||||
[99.0, 99.0],
|
||||
], dtype=np.float32)
|
||||
|
||||
assert triangulate(points) == [
|
||||
np.testing.assert_array_equal(triangulate(points), [
|
||||
[1.0, 10.0], [10.0, 100.0],
|
||||
[2.0, 20.0], [20.0, 200.0],
|
||||
]
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("points", [
|
||||
np.arange(132, dtype=np.float32).reshape(-1, 2),
|
||||
np.arange(132, dtype=np.float64).reshape(-1, 2),
|
||||
np.arange(264, dtype=np.float64).reshape(-1, 2)[::2, ::-1],
|
||||
np.asfortranarray(np.arange(132, dtype=np.float32).reshape(-1, 2)),
|
||||
])
|
||||
def test_triangulate_preserves_coordinates_in_contiguous_float_buffer(points):
|
||||
original = points.copy()
|
||||
points.flags.writeable = False
|
||||
strip = triangulate(points)
|
||||
expected = [point for pair in zip(points[:len(points) // 2], points[len(points) // 2:][::-1], strict=True) for point in pair]
|
||||
|
||||
assert strip.dtype == np.float32
|
||||
assert strip.flags.c_contiguous
|
||||
np.testing.assert_array_equal(strip, np.asarray(expected, dtype=np.float32))
|
||||
np.testing.assert_array_equal(points, original)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("use_gradient", [False, True])
|
||||
@pytest.mark.parametrize("point_count", [4, 5, 66])
|
||||
def test_draw_polygon_passes_native_vertices(monkeypatch, use_gradient, point_count):
|
||||
points = np.arange(point_count * 4, dtype=np.float64).reshape(-1, 2)[::2]
|
||||
rect = rl.Rectangle(0, 0, 100, 100)
|
||||
color = rl.Color(10, 20, 30, 40)
|
||||
gradient = Gradient((0, 0), (1, 1), [color, rl.Color(*rl.WHITE)], [0, 1]) if use_gradient else None
|
||||
calls = []
|
||||
state = SimpleNamespace(initialize=lambda: calls.append("initialize"), shader="shader")
|
||||
|
||||
def draw_strip(vertices, count, fill):
|
||||
assert rl.ffi.typeof(vertices) == rl.ffi.typeof("Vector2 *")
|
||||
coordinates = [[vertices[i].x, vertices[i].y] for i in range(count)]
|
||||
np.testing.assert_array_equal(coordinates, triangulate(points))
|
||||
assert fill == (rl.WHITE if use_gradient else color)
|
||||
calls.append("draw")
|
||||
|
||||
monkeypatch.setattr(shader_polygon.ShaderState, "get_instance", lambda: state)
|
||||
monkeypatch.setattr(shader_polygon, "_configure_shader_color", lambda *args: calls.append(("configure", args)))
|
||||
monkeypatch.setattr(rl, "begin_shader_mode", lambda shader: calls.append(("begin", shader)))
|
||||
monkeypatch.setattr(rl, "end_shader_mode", lambda: calls.append("end"))
|
||||
monkeypatch.setattr(rl, "draw_triangle_strip", draw_strip)
|
||||
|
||||
draw_polygon(rect, points, gradient=gradient, color=None if use_gradient else color)
|
||||
|
||||
assert calls == (["initialize", ("configure", (state, None, gradient, rect)), ("begin", "shader"), "draw", "end"]
|
||||
if use_gradient else ["draw"])
|
||||
|
||||
Reference in New Issue
Block a user