Hello, I’m making a simple 2D game which hence should be very fast. Everything seems to render the way i want it to at the moment but when frame buffers are used every frame in parts of the game, it slows down a lot. On one part of the game which uses one FBO, it runs about 40fps but will occasionally freeze for a second or two. The parts of the game where primitives and textures are only rendered directly to the screen, run fine. It must be these dreaded FBOs.
I’m using them to create rendered graphics which I then render collectively afterwards. This allows me to better apply alpha transparency and render things more than once without re-rendering the components.
The slow-downs happen even with minute frame buffers.
Now for my code. It’s using python but the pyOpenGL code is similar to code found on other languages. Thank you if anyone can help me with this.
I included the entire relevant module so nothing can be missed. It shouldn’t be too difficult to look for OpenGL parts. setup_framebuffer and end_framebuffer may be important functions.
#!/usr/bin/env python2.3
#
# Automatic Game Scaling and 2D surface library for OpenGL
#
# Allows resize of a Window while scaling the game, keeping the aspect ratio.
#
# Created by Matthew Mitchell on 13/09/2009.
# Copyright (c) 2009 Matthew Mitchell. All rights reserved.
#
#Import modules
import sys,os
import math as maths
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GL.ARB.framebuffer_object import *
from OpenGL.GL.EXT.framebuffer_object import *
import time,threading
arc_factors = ((1.0, 0.0), (0.99984769515639127, 0.017452406437283512), (0.99939082701909576, 0.034899496702500969), (0.99862953475457383, 0.052335956242943835), (0.9975640502598242, 0.069756473744125302), (0.99619469809174555, 0.087155742747658166), (0.99452189536827329, 0.10452846326765347), (0.99254615164132198, 0.12186934340514748), (0.99026806874157036, 0.13917310096006544), (0.98768834059513777, 0.15643446504023087), (0.98480775301220802, 0.17364817766693033), (0.98162718344766398, 0.1908089953765448), (0.97814760073380569, 0.20791169081775934), (0.97437006478523525, 0.224951054343865), (0.97029572627599647, 0.24192189559966773), (0.96592582628906831, 0.25881904510252074), (0.96126169593831889, 0.27563735581699916), (0.95630475596303544, 0.29237170472273677), (0.95105651629515353, 0.3090169943749474), (0.94551857559931685, 0.3255681544571567), (0.93969262078590843, 0.34202014332566871), (0.93358042649720174, 0.35836794954530027), (0.92718385456678742, 0.37460659341591201), (0.92050485345244037, 0.39073112848927377), (0.91354545764260087, 0.40673664307580021), (0.90630778703664994, 0.42261826174069944), (0.89879404629916704, 0.4383711467890774), (0.8910065241883679, 0.45399049973954675), (0.88294759285892699, 0.46947156278589081), (0.87461970713939574, 0.48480962024633706), (0.86602540378443871, 0.49999999999999994), (0.85716730070211233, 0.51503807491005416), (0.84804809615642596, 0.5299192642332049), (0.83867056794542405, 0.54463903501502708), (0.82903757255504162, 0.5591929034707469), (0.8191520442889918, 0.57357643635104605), (0.80901699437494745, 0.58778525229247314), (0.79863551004729283, 0.60181502315204827), (0.7880107536067219, 0.61566147532565829), (0.7771459614569709, 0.62932039104983739), (0.76604444311897812, 0.64278760968653925), (0.75470958022277201, 0.65605902899050728), (0.74314482547739424, 0.66913060635885824), (0.73135370161917046, 0.68199836006249848), (0.71933980033865119, 0.69465837045899725), (0.70710678118654757, 0.70710678118654746), (0.70710678118654746, 0.70710678118654757), (0.69465837045899725, 0.71933980033865119), (0.68199836006249848, 0.73135370161917046), (0.66913060635885824, 0.74314482547739424), (0.65605902899050728, 0.75470958022277201), (0.64278760968653925, 0.76604444311897812), (0.62932039104983739, 0.7771459614569709), (0.61566147532565829, 0.7880107536067219), (0.60181502315204827, 0.79863551004729283), (0.58778525229247314, 0.80901699437494745), (0.57357643635104605, 0.8191520442889918), (0.5591929034707469, 0.82903757255504162), (0.54463903501502708, 0.83867056794542405), (0.5299192642332049, 0.84804809615642596), (0.51503807491005416, 0.85716730070211233), (0.49999999999999994, 0.86602540378443871), (0.48480962024633706, 0.87461970713939574), (0.46947156278589081, 0.88294759285892699), (0.45399049973954675, 0.8910065241883679), (0.4383711467890774, 0.89879404629916704), (0.42261826174069944, 0.90630778703664994), (0.40673664307580021, 0.91354545764260087), (0.39073112848927377, 0.92050485345244037), (0.37460659341591201, 0.92718385456678742), (0.35836794954530027, 0.93358042649720174), (0.34202014332566871, 0.93969262078590843), (0.3255681544571567, 0.94551857559931685), (0.3090169943749474, 0.95105651629515353), (0.29237170472273677, 0.95630475596303544), (0.27563735581699916, 0.96126169593831889), (0.25881904510252074, 0.96592582628906831), (0.24192189559966773, 0.97029572627599647), (0.224951054343865, 0.97437006478523525), (0.20791169081775934, 0.97814760073380569), (0.1908089953765448, 0.98162718344766398), (0.17364817766693033, 0.98480775301220802), (0.15643446504023087, 0.98768834059513777), (0.13917310096006544, 0.99026806874157036), (0.12186934340514748, 0.99254615164132198), (0.10452846326765347, 0.99452189536827329), (0.087155742747658166, 0.99619469809174555), (0.069756473744125302, 0.9975640502598242), (0.052335956242943835, 0.99862953475457383), (0.034899496702500969, 0.99939082701909576), (0.017452406437283512, 0.99984769515639127), (0.0, 1.0))
MUSICEND = USEREVENT
def find_angle(dy,dx): #Find angle from dx and dy
if dx == 0: #Can't divide by 0
angle = 1.5707963267948966 #Should be pi/2 radians or 90 degrees
if dy > 0:
angle = -angle
else:
angle = maths.atan(float(dy)/float(dx)) #Find angle of line
return angle
def get_resolution(ss,gs):
gap = float(gs[0]) / float(gs[1])
sap = float(ss[0]) / float(ss[1])
if gap > sap:
#Game aspect ratio is greater than screen (wider) so scale width
factor = float(gs[0]) /float(ss[0])
new_h = gs[1]/factor #Divides the height by the factor which the width changes so the aspect ratio remians the same.
game_scaled = (ss[0],new_h)
elif gap < sap:
#Game aspect ratio is less than the screens.
factor = float(gs[1]) /float(ss[1])
new_w = gs[0]/factor #Divides the width by the factor which the height changes so the aspect ratio remians the same.
game_scaled = (new_w,ss[1])
else:
game_scaled = ss
return game_scaled
def sound(f):
if len(sys.argv) > 1:
if sys.argv[1] == "-m":
return DummySound()
return pygame.mixer.Sound(os.path.dirname(sys.argv[0]) + f)
def play_music(f):
if f != "":
mute = False
if len(sys.argv) > 1:
if sys.argv[1] == "-m":
mute = True
if not mute:
global music_stop
music_stop = False
pygame.mixer.music.load(os.path.dirname(sys.argv[0]) + f)
pygame.mixer.music.play(0)
pygame.mixer.music.set_endevent(MUSICEND)
def gaussian_blur(*args):
pass
def create_texture(surface):
surface.texture = glGenTextures(1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity() #Loads model matrix
glBindTexture(GL_TEXTURE_2D, surface.texture) #Binds the current 2D texture to the texture to be drawn
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) #Required to be set for maping the pixel data
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) #Similar as above
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface.surface_size[0], surface.surface_size[1], 0, GL_RGBA,GL_UNSIGNED_BYTE, surface.data) #Put surface pixel data into texture
if surface.data is None:
setup_framebuffer(surface)
c = [float(sc)/255.0 for sc in surface.colour] #Divide colours by 255 because OpenGL uses 0-1
if surface.background_alpha != None:
c[3] = float(surface.background_alpha)/255.0
glClearColor(*c)
glClear(GL_COLOR_BUFFER_BIT)
end_framebuffer()
Surface.texture_ready.append(surface)
def open_image(path):
img = pygame.image.load(path)
surf = Surface(img.get_size())
surf.data = pygame.image.tostring(img, "RGBA")
return surf
def add_line(surface,c,a,b,w = 1,antialias = False):
if surface.__class__ != Game: #Only use a frame buffer if the line isn't being drawn to the screen.
setup_framebuffer(surface)
glDisable(GL_TEXTURE_2D)
if antialias:
glEnable(GL_LINE_SMOOTH) #Enable line smoothing.
c = [float(sc)/255.0 for sc in c] #Divide colours by 255 because OpenGL uses 0-1
if len(c) != 4:
c.append(1) #Add a value for aplha transparency if needed
glMatrixMode(GL_MODELVIEW)
glLoadIdentity() #Loads model matrix
glColor4f(*c)
glLineWidth(w)
glBegin(GL_LINES)
glVertex2f(*a)
glVertex2f(*b)
glEnd()
if antialias:
glDisable(GL_LINE_SMOOTH) #Disable line smoothing.
glEnable(GL_TEXTURE_2D)
if surface.__class__ != Game:
end_framebuffer()
def setup_framebuffer(surface):
#Create texture if not done already
if surface.texture is None:
create_texture(surface)
#Render child to parent
if surface.frame_buffer is None:
surface.frame_buffer = glGenFramebuffersEXT(1)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surface.frame_buffer)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface.texture, 0)
glPushAttrib(GL_VIEWPORT_BIT)
glViewport(0,0,surface._scale[0],surface._scale[1])
glMatrixMode(GL_PROJECTION)
glLoadIdentity() #Load the projection matrix
gluOrtho2D(0,surface._scale[0],0,surface._scale[1])
def end_framebuffer():
glPopAttrib()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity() #Load the projection matrix
gluOrtho2D(0,1280,720,0) #Set an orthorgraphic view
def add_lines(surface,c,coordinates,w =1,antialias = True):
if surface.__class__ == Surface: #Only use a frame buffer if the line isn't being drawn to the screen.
setup_framebuffer(surface)
last = None
glDisable(GL_TEXTURE_2D)
if antialias:
glEnable(GL_LINE_SMOOTH) #Enable line smoothing.
c = [float(sc)/255.0 for sc in c] #Divide colours by 255 because OpenGL uses 0-1
if len(c) != 4:
c.append(1) #Add a value for aplha transparency if needed
glColor4f(*c)
glLineWidth(w)
glBegin(GL_LINE_STRIP)
for coordinate in coordinates: #Loop though the coordinates and draw the lines
glVertex2f(*coordinate)
glEnd()
if antialias:
glDisable(GL_LINE_SMOOTH) #Disable line smoothing.
glEnable(GL_TEXTURE_2D)
if surface.__class__ == Surface: #Only use a frame buffer if the line isn't being drawn to the screen.
end_framebuffer()
def font_convert(font):
surf = Surface(font.get_size())
surf.data = pygame.image.tostring(font, "RGBA")
return surf
def rotate_coordinate(coordinate,centre,angle):
dx = coordinate[0] - centre[0] #Remove centre point ordinates so the rotation only applies from this center.
dy = - coordinate[1] + centre[1] #Remember that the y-axis is flipped with Open GL top low to bottom high
return (centre[0] + dx*maths.cos(angle) + dy*maths.sin(angle),centre[1] - dy*maths.cos(angle) + dx*maths.sin(angle)) #Rotation trigonometry with the centre point added
def draw_texture(texture,offset,size,a,rounded,sides,angle,point):
glMatrixMode(GL_MODELVIEW)
glLoadIdentity() #Loads model matrix
glColor4f(1,1,1,float(a)/255.0)
glBindTexture(GL_TEXTURE_2D, texture)
if rounded == 0:
if angle == 0:
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0)
glVertex2i(*offset) #Top Left
glTexCoord2f(0.0, 1.0)
glVertex2i(offset[0],offset[1] + size[1]) #Bottom Left
glTexCoord2f(1.0, 1.0)
glVertex2i(offset[0] + size[0],offset[1] + size[1]) #Bottom, Right
glTexCoord2f(1.0, 0.0)
glVertex2i(offset[0] + size[0],offset[1]) #Top, Right
glEnd()
else:
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0)
glVertex2f(*rotate_coordinate(offset,point,angle)) #Top Left
glTexCoord2f(0.0, 1.0)
glVertex2f(*rotate_coordinate((offset[0],offset[1] + size[1]),point,angle)) #Bottom Left
glTexCoord2f(1.0, 1.0)
glVertex2f(*rotate_coordinate((offset[0] + size[0],offset[1] + size[1]),point,angle)) #Bottom, Right
glTexCoord2f(1.0, 0.0)
glVertex2f(*rotate_coordinate((offset[0] + size[0],offset[1]),point,angle)) #Top, Right
glEnd()
else:
global arc_factors
arc = [[o*rounded for o in c] for c in arc_factors]
glBegin(GL_POLYGON)
if sides % 2:
for c in arc:
coordinates = (offset[0] + rounded - c[0],offset[1] + rounded - c[1])
glTexCoord2f((coordinates[0]-offset[0])/size[0],(coordinates[1]-offset[1])/size[1])
glVertex2f(*coordinates)
else:
glTexCoord2f(0.0, 0.0)
glVertex2f(*rotate_coordinate(offset,point,angle)) #Top Left
if sides % 4 > 1:
for c in arc[::-1]:
coordinates = (offset[0] + size[0] - rounded + c[0],offset[1] + rounded - c[1])
glTexCoord2f((coordinates[0]-offset[0])/size[0],(coordinates[1]-offset[1])/size[1])
glVertex2f(*coordinates)
else:
glTexCoord2f(1.0, 0.0)
glVertex2f(*rotate_coordinate((offset[0] + size[0],offset[1]),point,angle)) #Top, Right
if sides % 8 > 3:
for c in arc:
coordinates = (offset[0] + size[0] - rounded + c[0],offset[1] + size[1] - rounded + c[1])
glTexCoord2f((coordinates[0]-offset[0])/size[0],(coordinates[1]-offset[1])/size[1])
glVertex2f(*coordinates)
else:
glTexCoord2f(1.0, 1.0)
glVertex2f(*rotate_coordinate((offset[0] + size[0],offset[1] + size[1]),point,angle)) #Bottom, Right
if sides > 7:
for c in arc[::-1]:
coordinates = (offset[0] + rounded - c[0],offset[1] + size[1] - rounded + c[1])
glTexCoord2f((coordinates[0]-offset[0])/size[0],(coordinates[1]-offset[1])/size[1])
glVertex2f(*coordinates)
else:
glTexCoord2f(0.0, 1.0)
glVertex2f(*rotate_coordinate((offset[0],offset[1] + size[1]),point,angle)) #Bottom Left
glEnd()
def texture_to_texture(target,surface,offset,rounded,rotation,point):
#Create texture if not done already
if surface.texture is None:
create_texture(surface)
#Render child to parent
setup_framebuffer(target)
draw_texture(surface.texture,offset,surface._scale,surface.colour[3],rounded,surface.rounded_sides,rotation,point)
end_framebuffer()
def texture_to_screen(surface,offset,rotation,point):
if surface.texture is None:
create_texture(surface)
draw_texture(surface.texture,offset,surface._scale,surface.colour[3],surface.rounded,surface.rounded_sides,rotation,point)
class DummySound():
def play(self):
pass
def set_volume(self):
pass
class Surface():
texture_ready = []
def __init__(self,size,extra = None):
self._offset = (0,0)
self.children = []
self.blitted = False
self.last_offset = [0,0]
self.surface_size = list(size)
self.colour = [0,0,0,255]
self.data = None
self.rounded = 0
self.parent = None
self.parent_offset = (0,0)
self.texture = None
self.frame_buffer = None
self._scale = size
self.background_alpha = None
self.rounded_sides = 0
def blit(self,surface,offset,rotation = 0,point = (0,0)):
texture_to_texture(self,surface,offset,surface.rounded,rotation,point)
if surface not in self.children:
self.children.append(surface)
if surface.parent_offset != offset or not surface.blitted:
surface.parent_offset = offset
surface._offset = [offset[0] + self._offset[0],offset[1] + self._offset[1]]
surface.recursive_offset_change() #Add to the children's offsets
surface.blitted = True
def set_background_alpha(self,alpha):
self.background_alpha = float(alpha)/255.0
def recursive_offset_change(self):
for child in self.children:
child._offset = (self._offset[0] + child.parent_offset[0],self._offset[1] + child.parent_offset[1])
child.recursive_offset_change()
def get_offset(self):
return self._offset
def fill(self,colour):
colour = list(colour)
if len(colour) < 4:
colour.append(255)
self.children = []
self.textures = []
self.colour = colour
if self.texture != None:
glDeleteTextures([self.texture])
self.data = None
create_texture(self)
def get_size(self):
return self.surface_size
def get_width(self):
return self.surface_size[0]
def get_height(self):
return self.surface_size[1]
def round_corners(self,r,sides = 15):
self.rounded = r
self.rounded_sides = sides
def get_rect(self):
return Rect(self._offset,self.surface_size)
def scale(self,scale):
self._scale = scale
return self
def __del__(self):
if self.texture != None:
glDeleteTextures([self.texture])
if self.frame_buffer != None:
glDeleteFramebuffersEXT(1, [int(self.frame_buffer)])
class Game(Surface):
game_size = None
first_screen = None
screen = None
fs = False #Fullscreen false to start
clock = None
resize = True
game_gap = None
game_scaled = (0,0)
title = None
fps = -1
enter_fullscreen = False
exit_fullscreen = False
scale_to_screen = False
iconify = False
on_focus_fullscreen = False
f_key = False
fade = 0
p_key = False
music_stop = False
unfade = False
event_after_fade = -1
loaded = False
fade = 255
unfade = True
homedir = os.path.expanduser("~")
fade_screen = False
keys = []
events = []
sections = []
back_key = False
transfer_args = ()
mouse_pos = (0,0)
def __init__(self,title,game_size,on_exit = sys.exit):
self.keys = [False] * 323
self.events = []
pygame.font.init()
pygame.mixer.init()
self.title = title
self.game_size = game_size
self.first_screen = (1280,720) #Take 120 pixels from the height because the menu bar, window bar and dock takes space
glutInit(sys.argv)
glutInitWindowPosition(0,0)
glutInitWindowSize(*game_size)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA)
glutGameModeString("1280x720:32@60") #720 HD
glutCreateWindow(title)
glutSetIconTitle(title)
self.callbacks()
self.game_gap = (0,0)
self.on_exit = on_exit
self.mod_key = 1024 if sys.platform == "darwin" else 64
Surface.__init__(self,game_size)
self.screen_change = True
self.frames = [time.time()]
self.fps = 60
self.last_time = 0
self.fade_surface = Surface([1280,720])
def callbacks(self):
glutReshapeFunc(self.reshaped)
glutKeyboardFunc(self.keydown)
glutKeyboardUpFunc(self.keyup)
glutSpecialFunc(self.specialdown)
glutSpecialUpFunc(self.specialup)
glutDisplayFunc(self.game_loop)
glutIdleFunc(self.game_loop)
glutMouseFunc(self.mouse_func)
glutPassiveMotionFunc(self.mouse_move)
glutMotionFunc(self.mouse_move)
glViewport(0,0,self.first_screen[0],self.first_screen[1]) #Creates the viewport which is mapped to the window
glEnable(GL_BLEND) #Enable alpha blending
glEnable(GL_TEXTURE_2D) #Enable 2D Textures
glEnable(GL_POLYGON_SMOOTH) #Enable antialiased polygons
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glMatrixMode(GL_PROJECTION)
glLoadIdentity() #Load the projection matrix
gluOrtho2D(0,1280,720,0) #Set an orthorgraphic view
def add_section(self,section_object):
self.sections.append(section_object)
def mouse_func(self,button, state, x, y):
self.events.append((state,button,x,y))
def mouse_move(self,x,y):
self.events.append((MOUSEMOTION,x - self.mouse_pos[0], y - self.mouse_pos[1]))
self.mouse_pos = (x,y)
def keydown(self,char,x,y):
#300 miliusecond delay, 50 milisecond repeat
self.change_keys(char,True)
def keyup(self,char,x,y):
self.change_keys(char,False)
def change_keys(self,char,bool):
char = ord(char)
#Switch backspace and delete
if char == 8:
char = 127
elif char == 127:
char = 8
self.keys[char] = bool
def specialdown(self,char,x,y):
if char == GLUT_KEY_UP:
self.keys[K_UP] = True
if char == GLUT_KEY_DOWN:
self.keys[K_DOWN] = True
if char == GLUT_KEY_LEFT:
self.keys[K_LEFT] = True
if char == GLUT_KEY_RIGHT:
self.keys[K_RIGHT] = True
def specialup(self,char,x,y):
if char == GLUT_KEY_UP:
self.keys[K_UP] = False
if char == GLUT_KEY_DOWN:
self.keys[K_DOWN] = False
if char == GLUT_KEY_LEFT:
self.keys[K_LEFT] = False
if char == GLUT_KEY_RIGHT:
self.keys[K_RIGHT] = False
def reshaped(self,w,h):
#Scale game to screen resolution, keeping aspect ratio
self.screen_change = True
self.game_scaled = get_resolution((w,h),self.game_size)
glutReshapeWindow(*self.game_scaled)
glViewport(0,0,self.game_scaled[0],self.game_scaled[1])
glutPositionWindow((1280- w)/2,(720 - h)/2)
def game_loop(self):
self.section.loop()
if self.unfade:
if self.fade == 255:
play_music(self.section.music)
if self.fade > 0:
self.fade -= 5
else:
self.music_stop = False
self.unfade = False
if self.fade_screen and not self.unfade: #Fade out
if self.fade == 0:
sound("/sounds/menu3/fade.ogg").play()
self.music_stop = True
pygame.mixer.music.fadeout(850)
if self.fade < 255:
self.fade += 5
else:
self.fade_screen = False
self.unfade = True
if self.fade_screen == False:
if self.event_after_fade != -1:
self.section = self.sections[self.event_after_fade]
self.section.transfer(*self.transfer_args)
self.transfer_args = ()
self.event_after_fade = -1
self.fade_surface.fill((0,0,0,self.fade))
self.blit(self.fade_surface,(0,0))
for event in self.events:
if event[1] == MUSICEND and self.music_stop == False:
play_music(self.section.music)
self.events = [] #Remove events
global draw_texture_time
#Updates screen properly
for event in self.events:
if event.type == QUIT:
self.on_exit()
if True:
if self.keys[K_f]:
if self.f_key == False:
self.f_key = True
if self.fs == False:
self.enter_fullscreen = True
else:
self.exit_fullscreen = True
else:
self.f_key = False
if self.on_focus_fullscreen and pygame.display.get_active():
self.on_focus_fullscreen = False
self.enter_fullscreen = True
pixel_data = []
if self.enter_fullscreen or self.exit_fullscreen:
for surface in Surface.texture_ready:
if surface.texture != None:
glBindTexture(GL_TEXTURE_2D, surface.texture)
glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_BYTE,surface.data)
surface.texture = None
if surface.frame_buffer != None:
pixel_data.append((surface,None))
glReadPixels(0,0,surface.surface_size[0],surface.surface_size[1],GL_BGRA,GL_UNSIGNED_BYTE,pixel_data[-1][1])
Surface.texture_ready = []
if self.enter_fullscreen:
glutEnterGameMode()
self.callbacks()
self.fs = True
self.enter_fullscreen = False
elif self.exit_fullscreen:
glutSetCursor(GLUT_CURSOR_INHERIT)
self.fs = False
glutLeaveGameMode()
self.callbacks()
self.exit_fullscreen = False
if self.iconify:
self.on_focus_fullscreen = True
if self.enter_fullscreen or self.exit_fullscreen:
for surface, data in pixel_data:
surface.frame_buffer = glGenFramebuffersEXT(1)
setup_framebuffer(surface)
glDrawPixels(surface.surface_size[0],surface.surface_size[1],GL_RGBA,GL_UNSIGNED_BYTE,data)
end_framebuffer()
if self.iconify:
pygame.display.iconify() #Minimise
self.iconify = False
glFlush()
glutSwapBuffers() #Flip buffer
glClear(GL_COLOR_BUFFER_BIT)
self.frames.append(time.time())
time_d = (self.frames[-1] - self.frames[-2])
if time_d < 0.01667:
time.sleep(0.01667 - time_d)
self.frames[-1] = time.time()
self.fps = len(self.frames)/(self.frames[-1] - self.frames[0])
if self.fps > 60:
self.fps = 60
self.frames = [frame for frame in self.frames if (self.frames[-1] - frame) < 1]
glutSetWindowTitle(self.title + " - " + str(int(self.fps)) + "fps")
def blit(self,surface,offset,rotation = 0,point = (0,0)):
if surface.get_offset() != offset or not surface.blitted:
surface._offset = offset
surface.recursive_offset_change() #Add to the children's offsets
surface.blitted = True
texture_to_screen(surface,offset,rotation,point)
def transfer_section(self,section,args=()):
self.transfer_args = args
self.event_after_fade = section
self.fade_screen = True