Skip to content

Commit 5c91c65

Browse files
authored
Merge pull request cztomczak#410 from neilmunday/master
Added frame rate limiting code to PySDL2 example for issue cztomczak#324
2 parents 5119d9d + c46055d commit 5c91c65

File tree

1 file changed

+94
-28
lines changed

1 file changed

+94
-28
lines changed

examples/pysdl2.py

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@
55
further down. Pull requests for the missing functionality are welcome.
66
77
Requires PySDL2 and SDL2 libraries.
8-
8+
9+
Usage:
10+
11+
python pysdl2.py [-v] [-h]
12+
13+
-v turn on debug messages
14+
-h display help info
15+
916
Tested configurations:
1017
- Windows 7: SDL 2.0.7 and PySDL2 0.9.6
11-
- Fedora 25: SDL2 2.0.5 with PySDL2 0.9.3
18+
- Fedora 26: SDL2 2.0.7 with PySDL2 0.9.6
1219
- Ubuntu 14.04: SDL2 with PySDL2 0.9.6
1320
1421
Install instructions:
@@ -19,7 +26,7 @@
1926
- Ubuntu: sudo apt-get install libsdl2-dev
2027
2. Install PySDL2 using pip package manager:
2128
pip install PySDL2
22-
29+
2330
Missing functionality:
2431
- Performance is still not perfect, see Issue #324 for further details
2532
- Keyboard modifiers that are not yet handled in this example:
@@ -36,33 +43,65 @@
3643
https://github.com/neilmunday/pes/blob/master/lib/pes/ui.py
3744
"""
3845

46+
import argparse
47+
import logging
3948
import sys
49+
50+
51+
def die(msg):
52+
"""
53+
Helper function to exit application on failed imports etc.
54+
"""
55+
sys.stderr.write("%s\n" % msg)
56+
sys.exit(1)
57+
58+
4059
try:
4160
# noinspection PyUnresolvedReferences
4261
from cefpython3 import cefpython as cef
4362
except ImportError:
44-
print("ERROR: cefpython3 package not found")
45-
print("To install type: `pip install cefpython3`")
46-
sys.exit(1)
63+
die("""ERROR: cefpython3 package not found\n
64+
To install type: `pip install cefpython3`""")
4765
try:
4866
# noinspection PyUnresolvedReferences
4967
import sdl2
5068
# noinspection PyUnresolvedReferences
5169
import sdl2.ext
5270
except ImportError:
53-
print("ERROR: SDL2 package not found")
54-
print("To install type: `pip install PySDL2`")
55-
sys.exit(1)
71+
die("ERROR: SDL2 package not found\nTo install type: `pip install PySDL2`")
5672
try:
5773
# noinspection PyUnresolvedReferences
5874
from PIL import Image
5975
except ImportError:
60-
print("ERROR: PIL package not found")
61-
print("To install type: pip install Pillow")
62-
sys.exit(1)
76+
die("ERROR: PIL package not found\nTo install type: pip install Pillow")
6377

6478

6579
def main():
80+
parser = argparse.ArgumentParser(
81+
description='PySDL2 / cefpython example',
82+
add_help=True
83+
)
84+
parser.add_argument(
85+
'-v',
86+
'--verbose',
87+
help='Turn on debug info',
88+
dest='verbose',
89+
action='store_true'
90+
)
91+
args = parser.parse_args()
92+
logLevel = logging.INFO
93+
if args.verbose:
94+
logLevel = logging.DEBUG
95+
logging.basicConfig(
96+
format='[%(filename)s %(levelname)s]: %(message)s',
97+
level=logLevel
98+
)
99+
logging.info("Using PySDL2 %s" % sdl2.__version__)
100+
version = sdl2.SDL_version()
101+
sdl2.SDL_GetVersion(version)
102+
logging.info(
103+
"Using SDL2 %s.%s.%s" % (version.major, version.minor, version.patch)
104+
)
66105
# The following variables control the dimensions of the window
67106
# and browser display area
68107
width = 800
@@ -74,6 +113,8 @@ def main():
74113
browserWidth = width
75114
# Mouse wheel fudge to enhance scrolling
76115
scrollEnhance = 40
116+
# desired frame rate
117+
frameRate = 100
77118
# Initialise CEF for offscreen rendering
78119
sys.excepthook = cef.ExceptHook
79120
switches = {
@@ -86,16 +127,18 @@ def main():
86127
}
87128
browser_settings = {
88129
# Tweaking OSR performance (Issue #240)
89-
"windowless_frame_rate": 100
130+
"windowless_frame_rate": frameRate
90131
}
91132
cef.Initialize(settings={"windowless_rendering_enabled": True},
92133
switches=switches)
134+
logging.debug("cef initialised")
93135
window_info = cef.WindowInfo()
94136
window_info.SetAsOffscreen(0)
95137
# Initialise SDL2 for video (add other init constants if you
96138
# require other SDL2 functionality e.g. mixer,
97139
# TTF, joystick etc.
98140
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
141+
logging.debug("SDL2 initialised")
99142
# Create the window
100143
window = sdl2.video.SDL_CreateWindow(
101144
'cefpython3 SDL2 Demo',
@@ -124,7 +167,17 @@ def main():
124167
browser.WasResized()
125168
# Begin the main rendering loop
126169
running = True
170+
# FPS debug variables
171+
frames = 0
172+
logging.debug("beginning rendering loop")
173+
resetFpsTime = True
174+
fpsTime = 0
127175
while running:
176+
# record when we started drawing this frame
177+
startTime = sdl2.timer.SDL_GetTicks()
178+
if resetFpsTime:
179+
fpsTime = sdl2.timer.SDL_GetTicks()
180+
resetFpsTime = False
128181
# Convert SDL2 events into CEF events (where appropriate)
129182
events = sdl2.ext.get_events()
130183
for event in events:
@@ -269,6 +322,17 @@ def main():
269322
sdl2.SDL_Rect(0, headerHeight, browserWidth, browserHeight)
270323
)
271324
sdl2.SDL_RenderPresent(renderer)
325+
# FPS debug code
326+
frames += 1
327+
if sdl2.timer.SDL_GetTicks() - fpsTime > 1000:
328+
logging.debug("FPS: %d" % frames)
329+
frames = 0
330+
resetFpsTime = True
331+
# regulate frame rate
332+
if sdl2.timer.SDL_GetTicks() - startTime < 1000.0 / frameRate:
333+
sdl2.timer.SDL_Delay(
334+
(1000 / frameRate) - (sdl2.timer.SDL_GetTicks() - startTime)
335+
)
272336
# User exited
273337
exit_app()
274338

@@ -289,31 +353,33 @@ def get_key_code(key):
289353
if key in key_map:
290354
return key_map[key]
291355
# Key not mapped, raise exception
292-
print("[pysdl2.py] Keyboard mapping incomplete:"
293-
" unsupported SDL key %d."
294-
" See https://wiki.libsdl.org/SDLKeycodeLookup for mapping."
295-
% key)
356+
logging.error(
357+
"""
358+
Keyboard mapping incomplete: unsupported SDL key %d.
359+
See https://wiki.libsdl.org/SDLKeycodeLookup for mapping.
360+
""" % key
361+
)
296362
return None
297363

298364

299365
class LoadHandler(object):
300366
"""Simple handler for loading URLs."""
301-
367+
302368
def OnLoadingStateChange(self, is_loading, **_):
303369
if not is_loading:
304-
print("[pysdl2.py] Page loading complete")
305-
370+
logging.info("Page loading complete")
371+
306372
def OnLoadError(self, frame, failed_url, **_):
307373
if not frame.IsMain():
308374
return
309-
print("[pysdl2.py] Failed to load %s" % failed_url)
375+
logging.error("Failed to load %s" % failed_url)
310376

311377

312378
class RenderHandler(object):
313379
"""
314380
Handler for rendering web pages to the
315381
screen via SDL2.
316-
382+
317383
The object's texture property is exposed
318384
to allow the main rendering loop to access
319385
the SDL2 texture.
@@ -324,11 +390,11 @@ def __init__(self, renderer, width, height):
324390
self.__height = height
325391
self.__renderer = renderer
326392
self.texture = None
327-
393+
328394
def GetViewRect(self, rect_out, **_):
329395
rect_out.extend([0, 0, self.__width, self.__height])
330396
return True
331-
397+
332398
def OnPaint(self, element_type, paint_buffer, **_):
333399
"""
334400
Using the pixel data from CEF's offscreen rendering
@@ -378,9 +444,9 @@ def OnPaint(self, element_type, paint_buffer, **_):
378444
depth = 32
379445
pitch = self.__width * 4
380446
else:
381-
print("[pysdl2.py] ERROR: Unsupported mode: %s" % mode)
447+
logging.error("ERROR: Unsupported mode: %s" % mode)
382448
exit_app()
383-
449+
384450
pxbuf = image.tobytes()
385451
# Create surface
386452
surface = sdl2.SDL_CreateRGBSurfaceFrom(
@@ -403,14 +469,14 @@ def OnPaint(self, element_type, paint_buffer, **_):
403469
# Free the surface
404470
sdl2.SDL_FreeSurface(surface)
405471
else:
406-
print("[pysdl2.py] WARNING: Unsupport element_type in OnPaint")
472+
logging.warning("Unsupport element_type in OnPaint")
407473

408474

409475
def exit_app():
410476
"""Tidy up SDL2 and CEF before exiting."""
411477
sdl2.SDL_Quit()
412478
cef.Shutdown()
413-
print("[pysdl2.py] Exited gracefully")
479+
logging.info("Exited gracefully")
414480

415481

416482
if __name__ == "__main__":

0 commit comments

Comments
 (0)