4

I am stuck on a screen tearing problem for about a week now.

Here is my problem: I would like to make a program that can display a sequence of PNG pictures really fast (at a rate of 30 fps or more). To do this I use the pygame library, especially pygame.display.blit and pygame.display.flip.

Here is an example of the code (with a homemade delay function):

import time
import pygame

screen=pygame.display.set_mode(size, pygame.FULLSCREEN)
nbPicturesToLoad=12
pictures=range(nbPicturesToLoad)
for i in range(nbPicturesToLoad):
    pictures[i]=pygame.image.load(pictureName).convert() //Here pictureName depends on the value of i

(...)

for i in range(nbPicturesToLoad):
    timer1=time.time()
    screen.blit(pictures[i], (0,0))
    pygame.display.flip()
    timer2=time.time()
    timer=timer2-timer1
    while(timer<0.03333):
        timer2=time.time()
        timer=timer2-timer1

The timer allows me to have the same refresh rate on the screen. My problem is that one can see with their own eyes that there is a screen tearing problem (https://en.wikipedia.org/wiki/Screen_tearing). On the pygame documentation they recommend to use other flags for the screen init (pygame.HWSURFACE and pygame.DOUBLEBUF, http://www.pygame.org/docs/ref/display, y.set_mode). Apparently these could help to correct the screen tearing problems. But when I use these flags I see no screen tearing correction.

I've seen somewhere that pygame can't handle vsync on X11, which would explain why I see no difference with the HWSURFACE and DOUBLEBUF flags.

Has anyone ever encountered this vsync issue on the Raspberry Pi? Is there a parameter to put in the "config.txt" file? Does anyone have a way to get real vsync information to avoid these screen tearing effects?

I've seen that pyglet could handle vsync in the created windows, but for unknown reasons I can't display images in the pyglet window and I'm really not sure if it would fix the problem, especially if a Raspberry can't handle vsync right now.

Jongware
  • 21,058
  • 8
  • 43
  • 86
Chumbucket
  • 43
  • 1
  • 4
  • As someone with epilepsy, I need to ask why you want to do this, and you are aware that this sort of flickering of the display can cause problems for people like me, right? – marienbad May 24 '16 at 09:53
  • I am fully aware of this ;). It is not a game or something that everyone can download, it is a personnal project and will only be used by myself : I am developping a 3D scanner using a projector and a camera. The camera captures the frames that the projector displays. – Chumbucket May 24 '16 at 10:23

1 Answers1

0

Try using the Pygame clock to handle timing, it is much easier to implement and understand and it may solve the issue.

shown below:

import pygame as py
py.init()

WINDOW = (400,400)
screen = py.display.set_mode(WINDOW)

nbPicturesToLoad=12
pictures = range(nbPicturesToLoad)
for i in range(nbPicturesToLoad):
    pictures[i]=py.image.load(pictureName).convert()

FPS = 30
clock = py.time.Clock() # Create a clock object

done = False
while not done:
    for event in py.event.get():
        if event.type == py.QUIT:
            done = True
    for i in range(nbPicturesToLoad):
        screen.fill((255,255,255))
        screen.blit(pictures[i],(0,0))
        py.display.flip()
        clock.tick(FPS) # use pygame.time.Clock to wait 1/30th of a second
py.quit()

However, since this is a screen tearing problem the solution may be to stop using Pygame altogether. How to avoid tearing with pygame on Linux/X11 This question seems to cover what you may be looking for.

Good luck.

Community
  • 1
  • 1
DCA-
  • 1,092
  • 1
  • 15
  • 32