Paul Morelle  committed 9a70b76

[Offscreen rendering] Avoid memory leaks by freeing objects for virtual renderer (MacOSX)

  • Participants
  • Parent commits 670a1d7

Comments (0)

Files changed (4)

File soya/_macosx.pyx

 cdef class MacOSX_SDLSurface(SDLSurface):
   cdef CGLContextObj opengl_context
+  cdef GLuint framebuffer
+  cdef GLuint renderbuffer
   def __cinit__(self, int flags, int width, int height, int bpp):
     cdef CGLPixelFormatAttribute attribs[1]
     cdef CGLError error
     cdef GLubyte *strExt
     cdef GLenum status
-    cdef GLuint framebuffer
-    cdef GLuint renderbuffer
     cdef GLboolean bresult
     attribs[0] = <CGLPixelFormatAttribute>0
     pixel_format = NULL
     npix = 0
     self.opengl_context = NULL
-    framebuffer = 0
-    renderbuffer = 0
+    self.framebuffer = 0
+    self.renderbuffer = 0
     error = CGLChoosePixelFormat(attribs, &pixel_format, &npix)
     if error != kCGLNoError:
       sys.stderr.write(s + "\n")
       raise RuntimeError(s)
+    CGLReleasePixelFormat(pixel_format)
+    pixel_format = NULL
     error = CGLSetCurrentContext(self.opengl_context)
     if error != kCGLNoError:
       s = "CGL error #%d"%error
-    glGenFramebuffersEXT(1, &framebuffer)
-    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer)
-    glGenRenderbuffersEXT(1, &renderbuffer)
-    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer)
+    glGenFramebuffersEXT(1, &self.framebuffer)
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, self.framebuffer)
+    glGenRenderbuffersEXT(1, &self.renderbuffer)
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, self.renderbuffer)
     glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height)
+    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, self.renderbuffer)
     status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
       raise RuntimeError(s)
     self.sdl_surface = SDL_CreateRGBSurface(flags, width, height, bpp, 0, 0, 0, 0)
+  def __dealloc__(self):
+    glDeleteRenderbuffersEXT(1, &self.renderbuffer)
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)
+    glDeleteFramebuffersEXT(1, &self.framebuffer)
+    CGLClearDrawable(self.opengl_context)
+    CGLReleaseContext(self.opengl_context)

File soya/c_opengl.pxd

 	cdef void glBindRenderbufferEXT(GLenum target, GLuint id)
 	cdef void glRenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height)
 	cdef void glFramebufferRenderbufferEXT(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbufferId)
+	cdef void glDeleteFramebuffersEXT(GLsizei n, GLuint *framebuffers)
+	cdef void glDeleteRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
 	cdef GLenum glCheckFramebufferStatusEXT(GLenum target)
 	int GLU_EXT_object_space_tess

File soya/definitions/_macosx.pxd

 cdef extern from "OpenGL/OpenGL.h":
 	cdef CGLError CGLChoosePixelFormat(CGLPixelFormatAttribute *attribs, CGLPixelFormatObj *pix, GLint *npix)
+	cdef void CGLReleasePixelFormat(CGLPixelFormatObj pix)
 	cdef CGLError CGLCreateContext(CGLPixelFormatObj pix, CGLContextObj share, CGLContextObj *ctx)
 	cdef CGLError CGLSetOffScreen(CGLContextObj ctx, GLsizei width, GLsizei height, GLint rowbytes, void *baseaddr)
+	cdef CGLError CGLClearDrawable(CGLContextObj ctx)
+	cdef void CGLReleaseContext(CGLContextObj ctx)
 cdef extern from "OpenGL/CGLCurrent.h":
 	cdef CGLError CGLSetCurrentContext(CGLContextObj ctx)

File soya/tutorial/

 # Initializes Soya (creates and displays the 3D window).
 # Add the path "tutorial/data" to the list of soya data path. When soya loads some data,
 # like a model or a texture, it always searches the data in soya.path.
 # Uncomment this line to save a 320x240 screenshot in the results directory.
-#soya.render(); soya.screenshot().resize((320, 240)).save(os.path.join(os.path.dirname(sys.argv[0]), "results", os.path.basename(sys.argv[0])[:-3] + ".jpeg"))
+soya.render(); soya.screenshot().resize((320, 240)).save(os.path.join(os.path.dirname(sys.argv[0]), "results", os.path.basename(sys.argv[0])[:-3] + ".jpeg"))
 # Creates an 'MainLoop' for the scene, and launch it.
 # The MainLoop is the object that manages the Soya's mainloop. It take care of :
 #  - computing FPS
 #  - rendering the screen