Add draw list to reduce CPU load from 40% to 8%

This commit is contained in:
Admar Schoonen 2023-02-17 21:27:33 +01:00
parent 7c350359b7
commit aabc73d6a1
1 changed files with 69 additions and 27 deletions

View File

@ -5,6 +5,11 @@ import math
import sys
import traceback
from kivy.config import Config
Config.set('graphics', 'width', '800')
Config.set('graphics', 'height', '480')
Config.set('graphics', 'maxfps', '60')
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
@ -18,10 +23,6 @@ from multiprocessing import Process
from playsound import playsound
import pulsectl
from kivy.config import Config
Config.set('graphics', 'width', '800')
Config.set('graphics', 'height', '480')
Builder.load_string('''
<MyClockWidget>:
on_pos: self.update_display()
@ -254,6 +255,12 @@ class MyClockWidget(FloatLayout):
# we need a dirty hack to sensure that radio button is always in sync with selected setting
settings_menu_wake_up_sound_select_button_cb_hack = False
# defer drawing to improve application speed: if list of draw calls for
# this frame is identical to list of previous frame then nothing needs to
# be drawed
draw_list_last_frame = []
draw_list_curr_frame = []
def hide_widget(self, widget, hide=True):
if hasattr(widget, 'saved_attrs'):
if not hide:
@ -333,10 +340,11 @@ class MyClockWidget(FloatLayout):
rgb = [1.0, 1.0, 1.0]
set_alarm_button = self.ids["set_alarm_button"]
set_alarm_button.canvas.clear()
self.draw_list_curr_frame.append(["canvas.clear()", set_alarm_button])
with set_alarm_button.canvas:
Color(rgb[0], rgb[1], rgb[2])
Rectangle(size=set_alarm_button.size, pos=set_alarm_button.pos, source=source)
self.draw_list_curr_frame.append(["Color", set_alarm_button.canvas, rgb[0], rgb[1], rgb[2]])
# Rectangle(size=set_alarm_button.size, pos=set_alarm_button.pos, source=source)
self.draw_list_curr_frame.append(["Rectangle", set_alarm_button.canvas, set_alarm_button.size, set_alarm_button.pos, source])
def update_settings_button(self):
alarm_settings = App.get_running_app().alarm_settings
@ -349,10 +357,11 @@ class MyClockWidget(FloatLayout):
rgb = [1.0, 1.0, 1.0]
settings_button = self.ids["settings_button"]
settings_button.canvas.clear()
self.draw_list_curr_frame.append(["canvas.clear()", settings_button])
with settings_button.canvas:
Color(rgb[0], rgb[1], rgb[2])
Rectangle(size=settings_button.size, pos=settings_button.pos, source=source)
self.draw_list_curr_frame.append(["Color", settings_button.canvas, rgb[0], rgb[1], rgb[2]])
# Rectangle(size=settings_button.size, pos=settings_button.pos, source=source)
self.draw_list_curr_frame.append(["Rectangle", settings_button.canvas, settings_button.size, settings_button.pos, source])
def sun_rise(self):
alarm_settings = App.get_running_app().alarm_settings
@ -412,8 +421,8 @@ class MyClockWidget(FloatLayout):
self.check_play_sound()
def update_clock(self):
self.hide_widget(self.ids["face"], False)
self.hide_widget(self.ids["hands"], False)
self.draw_list_curr_frame.append(["self.hide_widget", self.ids["face"], False])
self.draw_list_curr_frame.append(["self.hide_widget", self.ids["hands"], False])
alarm_settings = App.get_running_app().alarm_settings
if self.view == "set_alarm":
@ -428,16 +437,19 @@ class MyClockWidget(FloatLayout):
self.update_face()
hands.canvas.clear()
#hands.canvas.clear()
self.draw_list_curr_frame.append(["canvas.clear()", hands])
update_rate = App.get_running_app().update_rate
with hands.canvas:
if self.view == "set_alarm":
if self.grabbed != "" or self.set_alarm_timeout_counter < 1 * update_rate or \
self.set_alarm_timeout_counter % update_rate <= update_rate / 2 or alarm_settings.alarm_modified == False:
Color(0.9, 0.0, 0.0)
Line(points=[hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], width=3, cap="round")
Color(0.8, 0.0, 0.0)
Line(points=[hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], width=2, cap="round")
self.draw_list_curr_frame.append(["Color", hands.canvas, 0.9, 0.0, 0.0])
# Line(points=[hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], width=3, cap="round")
self.draw_list_curr_frame.append(["Line", hands.canvas, [hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], 3, "round"])
self.draw_list_curr_frame.append(["Color", hands.canvas, 0.8, 0.0, 0.0])
#Line(points=[hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], width=2, cap="round")
self.draw_list_curr_frame.append(["Line", hands.canvas, [hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], 2, "round"])
if self.grabbed == "":
self.set_alarm_timeout_counter += 1
@ -450,12 +462,15 @@ class MyClockWidget(FloatLayout):
alarm_settings.alarm_activated = True
alarm_settings.alarm_modified = False
else:
Color(0.9, 0.9, 0.9)
Line(points=[hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], width=3, cap="round")
Color(0.8, 0.8, 0.8)
Line(points=[hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], width=2, cap="round")
Color(0.7, 0.7, 0.7)
Line(points=[hands.center_x, hands.center_y, seconds_hand.x, seconds_hand.y], width=1, cap="round")
self.draw_list_curr_frame.append(["Color", hands.canvas, 0.9, 0.9, 0.9])
# Line(points=[hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], width=3, cap="round")
self.draw_list_curr_frame.append(["Line", hands.canvas, [hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], 3, "round"])
self.draw_list_curr_frame.append(["Color", hands.canvas, 0.8, 0.8, 0.8])
# Line(points=[hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], width=2, cap="round")
self.draw_list_curr_frame.append(["Line", hands.canvas, [hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], 2, "round"])
self.draw_list_curr_frame.append(["Color", hands.canvas, 0.7, 0.7, 0.7])
# Line(points=[hands.center_x, hands.center_y, seconds_hand.x, seconds_hand.y], width=1, cap="round")
self.draw_list_curr_frame.append(["Line", hands.canvas, [hands.center_x, hands.center_y, seconds_hand.x, seconds_hand.y], 1, "round"])
def update_settings(self):
if self.view == "settings_menu":
@ -463,14 +478,37 @@ class MyClockWidget(FloatLayout):
elif self.view == "settings_menu_wake_up_sound":
self.hide_widget(self.ids["settings_menu_wake_up_sound"], False)
def draw_display(self):
time = datetime.datetime.now()
if self.draw_list_curr_frame != self.draw_list_last_frame:
for i in self.draw_list_curr_frame:
if i[0] == "self.hide_widget":
self.hide_widget(i[1], i[2])
elif i[0] == "canvas.clear()":
i[1].canvas.clear()
elif i[0] == "Color":
with i[1]:
Color(i[2], i[3], i[4])
elif i[0] == "Rectangle":
with i[1]:
Rectangle(size=i[2], pos=i[3], source=i[4])
elif i[0] == "Line":
with i[1]:
Line(points=i[2], width=i[3], cap=i[4])
else:
print("Unknown draw command: " + i[0])
self.draw_list_last_frame = self.draw_list_curr_frame
self.draw_list_curr_frame = []
def update_display(self, *args):
self.check_alarm()
# Hide all dynamic widgets; will be enabled when updating respecive view
self.hide_widget(self.ids["face"], True)
self.hide_widget(self.ids["hands"], True)
self.hide_widget(self.ids["settings_menu"], True)
self.hide_widget(self.ids["settings_menu_wake_up_sound"], True)
self.draw_list_curr_frame.append(["self.hide_widget", self.ids["face"], True])
self.draw_list_curr_frame.append(["self.hide_widget", self.ids["hands"], True])
self.draw_list_curr_frame.append(["self.hide_widget", self.ids["settings_menu"], True])
self.draw_list_curr_frame.append(["self.hide_widget", self.ids["settings_menu_wake_up_sound"], True])
self.update_set_alarm_button()
self.update_settings_button()
@ -478,6 +516,10 @@ class MyClockWidget(FloatLayout):
self.update_clock()
elif self.view.startswith("settings_menu"):
self.update_settings()
else:
print("unknown view: " + self.view)
self.draw_display()
def settings_menu_wake_up_sound_select_button_cb(self):
self.settings_menu_wake_up_sound_select_button_cb_hack = True