clock: implement rfps (real frame displayed on screen)

base: display and flip only when needed (might be have some bugs.)
This commit is contained in:
Mathieu Virbel 2010-11-07 20:43:49 -05:00
parent dd91a1f940
commit e838e13e96
7 changed files with 52 additions and 26 deletions

View File

@ -6,7 +6,8 @@ from kivy.lang import Builder
class KvApp(App):
def _print_fps(self, *largs):
print 'FPS:', Clock.get_fps()
print 'FPS: %2.4f (real draw: %d)' % (
Clock.get_fps(), Clock.get_rfps())
def build(self):
Clock.schedule_interval(self._print_fps, 1)
return Builder.load_file(self.options['filename'])

View File

@ -12,6 +12,7 @@ from kivy.logger import Logger
from kivy.exceptions import ExceptionManager
from kivy.clock import Clock
from kivy.input import TouchFactory, kivy_postproc_modules
from kivy.graphics import GraphicContext
# private vars
EventLoop = None
@ -211,7 +212,9 @@ class EventLoopBase(object):
self.dispatch_input()
window = self.window
if window:
need_redraw = GraphicContext.instance().need_redraw
if window and need_redraw:
Clock.tick_draw()
window.dispatch('on_draw')
window.dispatch('on_flip')

View File

@ -7,7 +7,7 @@ cdef class GraphicContext:
cdef readonly int need_flush
cdef Shader _default_shader
cdef object _default_texture
cdef int need_redraw
cdef int _need_redraw
cpdef post_update(self)
cpdef finish_frame(self)

View File

@ -45,18 +45,22 @@ cdef class GraphicContext:
self.journal = set()
self.need_flush = 0
self._default_shader = None
self._need_redraw = 1
def __init__(self):
# create initial state
self.reset()
self.save()
self.need_redraw = 1
property need_redraw:
def __get__(self):
return self._need_redraw
cpdef post_update(self):
self.need_redraw = 1
self._need_redraw = 1
cpdef finish_frame(self):
self.need_redraw = 0
self._need_redraw = 0
err = glGetError()
if err:
Logger.warning('GContext: GL Error while drawing frame: %d' % err)

View File

@ -17,8 +17,9 @@ If the callback return False, the schedule will be removed.
__all__ = ('Clock', )
import time
from time import time, sleep
from kivy.weakmethod import WeakMethod
from kivy.config import Config
class _Event(object):
@ -63,16 +64,19 @@ class _Event(object):
class ClockBase(object):
'''A clock object, that support events'''
__slots__ = ('_dt', '_last_fps_tick', '_last_tick', '_fps',
'_fps_counter', '_events')
__slots__ = ('_dt', '_last_fps_tick', '_last_tick', '_fps', '_rfps',
'_fps_counter', '_rfps_counter', '_events', '_max_fps')
def __init__(self):
self._dt = 0.0001
self._last_tick = time.time()
self._last_tick = time()
self._fps = 0
self._rfps = 0
self._fps_counter = 0
self._rfps_counter = 0
self._last_fps_tick = None
self._events = []
self._max_fps = float(Config.getint('graphics', 'fps'))
@property
def frametime(self):
@ -83,8 +87,16 @@ class ClockBase(object):
def tick(self):
'''Advance clock to the next step. Must be called every frame.
The default clock have the tick() function called by Kivy'''
# do we need to sleep ?
if self._max_fps > 0:
fps = self._max_fps
s = 1 / fps - (time() - self._last_tick)
if s > 0:
sleep(s)
# tick the current time
current = time.time()
current = time()
self._dt = current - self._last_tick
self._fps_counter += 1
self._last_tick = current
@ -93,19 +105,37 @@ class ClockBase(object):
if self._last_fps_tick == None:
self._last_fps_tick = current
elif current - self._last_fps_tick > 1:
self._fps = self._fps_counter / float(current - self._last_fps_tick)
d = float(current - self._last_fps_tick)
self._fps = self._fps_counter / d
self._rfps = self._rfps_counter
self._last_fps_tick = current
self._fps_counter = 0
self._rfps_counter = 0
# process event
self._process_events()
return self._dt
def tick_draw(self):
'''Tick the drawing counter
'''
self._rfps_counter += 1
def get_fps(self):
'''Get the current FPS calculated by the clock'''
'''Get the current FPS calculated by the clock
'''
return self._fps
def get_rfps(self):
'''Get the current "real" FPS calculated by the clock.
This counter reflect the real frame displayed on the screen.
In contrary to get_fps(), this function return a counter of the number
of frame, not a average of frame per seconds
'''
return self._rfps
def get_time(self):
'''Get the last tick made by the clock'''
return self._last_tick

View File

@ -7,7 +7,6 @@ __all__ = ('WindowPygame', )
from . import WindowBase
import os
from time import sleep, time
from kivy.config import Config
from kivy.clock import Clock
from kivy.exceptions import ExceptionManager
@ -138,17 +137,6 @@ class WindowPygame(WindowBase):
pygame.display.flip()
super(WindowPygame, self).flip()
# do software vsync if asked
# FIXME: vsync is surely not 60 for everyone
# this is not a real vsync. this must be done by driver...
# but pygame can't do vsync on X11, and some people
# use hack to make it work under darwin...
fps = self._fps
if fps > 0:
s = 1 / fps - (time() - Clock.get_time())
if s > 0:
sleep(s)
def toggle_fullscreen(self):
if self.flags & pygame.FULLSCREEN:
self.flags &= ~pygame.FULLSCREEN

View File

@ -8,7 +8,7 @@
source: 'data/images/button.png'
Label:
text: root.text
font_size: 18
font_size: 12
canvas:
Color:
rgb: (1, 1, 1)