Commits

Paul Morelle  committed 9c9c992

Enable rendering to a virtual SDL Surface

  • Participants
  • Parent commits 7b2c825

Comments (0)

Files changed (7)

File soya/_macosx.pyx

+include "definitions/_macosx.pxd"
+include "sdl.pxd"
+import sys
+
+cdef class MacOSX_SDLSurface(SDLSurface):
+  cdef CGLContextObj opengl_context
+
+  def __cinit__(self, int flags, int width, int height, int bpp):
+    cdef CGLPixelFormatAttribute attribs[1]
+    cdef CGLPixelFormatObj pixel_format
+    cdef GLint npix
+    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
+
+    error = CGLChoosePixelFormat(attribs, &pixel_format, &npix)
+    if error != kCGLNoError:
+      s = "CGL error #%d"%error
+      sys.stderr.write(s + "\n")
+      raise RuntimeError(s)
+
+    error = CGLCreateContext(pixel_format, NULL, &self.opengl_context)
+    if error != kCGLNoError:
+      s = "CGL error #%d"%error
+      sys.stderr.write(s + "\n")
+      raise RuntimeError(s)
+
+    error = CGLSetCurrentContext(self.opengl_context)
+    if error != kCGLNoError:
+      s = "CGL error #%d"%error
+      sys.stderr.write(s + "\n")
+      raise RuntimeError(s)
+
+    strExt = glGetString(GL_EXTENSIONS)
+    bresult = gluCheckExtension(<GLubyte *><char *>"GL_EXT_framebuffer_object", strExt)
+    if bresult != GL_TRUE:
+      s = "GL_EXT_framebuffer_object is not supported"
+      sys.stderr.write(s + "\n")
+      raise RuntimeError(s)
+
+    glewInit()
+
+    glGenFramebuffersEXT(1, &framebuffer)
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer)
+    glGenRenderbuffersEXT(1, &renderbuffer)
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer)
+    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height)
+    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, renderbuffer)
+
+    status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
+    if status != GL_FRAMEBUFFER_COMPLETE_EXT:
+      s = "Could not initialize framebuffer"
+      sys.stderr.write(s + "\n")
+      raise RuntimeError(s)
+
+    self.sdl_surface = SDL_CreateRGBSurface(flags, width, height, bpp, 0, 0, 0, 0)

File soya/c_opengl.pxd

 ctypedef void (*_GLUfuncptr)()
 
 cdef extern from "include_glew.h":
-	ctypedef unsigned int		GLenum
-	ctypedef unsigned char  GLboolean
-	ctypedef unsigned int		GLbitfield
-	ctypedef void						GLvoid
-	ctypedef signed char    GLbyte
-	ctypedef short					GLshort
-	ctypedef int						GLint
-	ctypedef unsigned char  GLubyte
-	ctypedef unsigned short	GLushort
-	ctypedef unsigned int		GLuint
-	ctypedef int						GLsizei
-	ctypedef float					GLfloat
-	ctypedef float					GLclampf
-	ctypedef double					GLdouble
-	ctypedef double					GLclampd
-	ctypedef char 					GLchar
-	ctypedef unsigned int   GLhandleARB
+	ctypedef unsigned int    GLenum
+	ctypedef unsigned char   GLboolean
+	ctypedef unsigned int    GLbitfield
+	ctypedef void            GLvoid
+	ctypedef signed char     GLbyte
+	ctypedef short           GLshort
+	ctypedef int             GLint
+	ctypedef unsigned char   GLubyte
+	ctypedef unsigned short  GLushort
+	ctypedef unsigned int    GLuint
+	ctypedef int             GLsizei
+	ctypedef long            GLsizeiptr
+	ctypedef float           GLfloat
+	ctypedef float           GLclampf
+	ctypedef double          GLdouble
+	ctypedef double          GLclampd
+	ctypedef char            GLchar
+	ctypedef unsigned int    GLhandleARB
 	
 	int GL_FALSE
 	int GL_TRUE
 	int GL_DOT3_RGBA
 	int GL_CLAMP_TO_BORDER
 	int GL_DEPTH_COMPONENT24
+	int GL_FRAMEBUFFER_EXT
+	int GL_RENDERBUFFER_EXT
+	int GL_COLOR_ATTACHMENT0_EXT
+	int GL_FRAMEBUFFER_COMPLETE_EXT
 	
 	cdef void glClearIndex(GLfloat c)
 	cdef void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 	cdef void glMultTransposeMatrixd(GLdouble m[16])
 	cdef void glMultTransposeMatrixf(GLfloat m[16])
 	cdef void glSampleCoverage(GLclampf value, GLboolean invert)
+	cdef void glGenFramebuffersEXT(GLsizei n, GLuint* ids)
+	cdef void glBindFramebufferEXT(GLenum target, GLuint id)
+	cdef void glGenRenderbuffersEXT(GLsizei n, GLuint* ids)
+	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 GLenum glCheckFramebufferStatusEXT(GLenum target)
 	
 	int GLU_EXT_object_space_tess
 	int GLU_EXT_nurbs_tessellator

File soya/definitions/_macosx.pxd

+include "../c_opengl.pxd"
+
+cdef extern from "OpenGL/CGLTypes.h":
+	ctypedef void *CGLContextObj
+	ctypedef void *CGLPixelFormatObj
+
+	ctypedef enum CGLPixelFormatAttribute:
+		kCGLPFAAllRenderers          =   1	# choose from all available renderers
+		kCGLPFADoubleBuffer          =   5	# choose a double buffered pixel format
+		kCGLPFAStereo                =   6	# stereo buffering supported
+		kCGLPFAAuxBuffers            =   7	# number of aux buffers
+		kCGLPFAColorSize             =   8	# number of color buffer bits
+		kCGLPFAAlphaSize             =  11	# number of alpha component bits
+		kCGLPFADepthSize             =  12	# number of depth buffer bits
+		kCGLPFAStencilSize           =  13	# number of stencil buffer bits
+		kCGLPFAAccumSize             =  14	# number of accum buffer bits
+		kCGLPFAMinimumPolicy         =  51	# never choose smaller buffers than requested
+		kCGLPFAMaximumPolicy         =  52	# choose largest buffers of type requested
+		kCGLPFAOffScreen             =  53	# choose an off-screen capable renderer
+		kCGLPFAFullScreen            =  54	# choose a full-screen capable renderer
+		kCGLPFASampleBuffers         =  55	# number of multi sample buffers
+		kCGLPFASamples               =  56	# number of samples per multi sample buffer
+		kCGLPFAAuxDepthStencil       =  57	# each aux buffer has its own depth stencil
+		kCGLPFAColorFloat            =  58	# color buffers store floating point pixels
+		kCGLPFAMultisample           =  59	# choose multisampling
+		kCGLPFASupersample           =  60	# choose supersampling
+		kCGLPFASampleAlpha           =  61	# request alpha filtering
+
+		kCGLPFARendererID            =  70	# request renderer by ID
+		kCGLPFASingleRenderer        =  71	# choose a single renderer for all screens
+		kCGLPFANoRecovery            =  72	# disable all failure recovery systems
+		kCGLPFAAccelerated           =  73	# choose a hardware accelerated renderer
+		kCGLPFAClosestPolicy         =  74	# choose the closest color buffer to request
+		kCGLPFABackingStore          =  76	# back buffer contents are valid after swap
+		kCGLPFAWindow                =  80	# can be used to render to an onscreen window
+		kCGLPFACompliant             =  83	# renderer is opengl compliant
+		kCGLPFADisplayMask           =  84	# mask limiting supported displays
+		kCGLPFAPBuffer               =  90	# can be used to render to a pbuffer
+		kCGLPFARemotePBuffer         =  91	# can be used to render offline to a pbuffer
+		kCGLPFAAllowOfflineRenderers =  96	# show offline renderers in pixel formats
+		kCGLPFAVirtualScreenCount    =  128	# number of virtual screens in this format
+
+	ctypedef enum CGLError:
+		kCGLNoError            = 0    	# no error
+		kCGLBadAttribute       = 10000	# invalid pixel format attribute
+		kCGLBadProperty        = 10001	# invalid renderer property
+		kCGLBadPixelFormat     = 10002	# invalid pixel format
+		kCGLBadRendererInfo    = 10003	# invalid renderer info
+		kCGLBadContext         = 10004	# invalid context
+		kCGLBadDrawable        = 10005	# invalid drawable
+		kCGLBadDisplay         = 10006	# invalid graphics device
+		kCGLBadState           = 10007	# invalid context state
+		kCGLBadValue           = 10008	# invalid numerical value
+		kCGLBadMatch           = 10009	# invalid share context
+		kCGLBadEnumeration     = 10010	# invalid enumerant
+		kCGLBadOffScreen       = 10011	# invalid offscreen drawable
+		kCGLBadFullScreen      = 10012	# invalid offscreen drawable
+		kCGLBadWindow          = 10013	# invalid window
+		kCGLBadAddress         = 10014	# invalid pointer
+		kCGLBadCodeModule      = 10015	# invalid code module
+		kCGLBadAlloc           = 10016	# invalid memory allocation
+		kCGLBadConnection      = 10017	# invalid CoreGraphics connection
+
+cdef extern from "OpenGL/OpenGL.h":
+	cdef CGLError CGLChoosePixelFormat(CGLPixelFormatAttribute *attribs, CGLPixelFormatObj *pix, GLint *npix)
+	cdef CGLError CGLCreateContext(CGLPixelFormatObj pix, CGLContextObj share, CGLContextObj *ctx)
+	cdef CGLError CGLSetOffScreen(CGLContextObj ctx, GLsizei width, GLsizei height, GLint rowbytes, void *baseaddr)
+
+cdef extern from "OpenGL/CGLCurrent.h":
+	cdef CGLError CGLSetCurrentContext(CGLContextObj ctx)

File soya/init.pyx

 		renderer.engine_option = renderer.engine_option | WIREFRAME
 		
 cdef void dump_info():
+	tmp_gl_version = <char*> glGetString(GL_VERSION)
+	tmp_gl_renderer = <char*> glGetString(GL_RENDERER)
+	tmp_gl_vendor = <char*> glGetString(GL_VENDOR)
+
+	if tmp_gl_version == NULL: gl_version = ""
+	else: gl_version = PyString_FromString(tmp_gl_version)
+
+	if tmp_gl_renderer == NULL: gl_renderer = ""
+	else: gl_renderer = PyString_FromString(tmp_gl_renderer)
+
+	if tmp_gl_vendor == NULL: gl_vendor = ""
+	else: gl_vendor = PyString_FromString(tmp_gl_vendor)
+
 	sys.stdout.write("""
 * Soya * version %s
 * Using OpenGL %s
 *   - maximum texture size            : %s pixels
 """ % (
 		VERSION,
-		PyString_FromString(<char*> glGetString(GL_VERSION)),
-		PyString_FromString(<char*> glGetString(GL_RENDERER)),
-		PyString_FromString(<char*> glGetString(GL_VENDOR)),
+		gl_version,
+		gl_renderer,
+		gl_vendor,
 		MAX_LIGHTS,
 		MAX_CLIP_PLANES,
 		MAX_TEXTURES,
 				sys.stderr.write(s + '\n')
 				raise RuntimeError(s)
 
-def set_video(int width, int height, int fullscreen, int resizable, int quiet = False, int sdl_blit = 0, int additional_flags = 0):
+def set_video(int width, int height, int fullscreen, int resizable, int quiet = False, int sdl_blit = 0, int additional_flags = 0, int virtual = False):
 	cdef int stencil, bits_per_pixel
 	#cdef unsigned int flags
 	cdef int flags
 	cdef void* tmp
 	renderer.screen_width  = width
 	renderer.screen_height = height
+
 	# Information about the current video settings
 	tmp = SDL_GetVideoInfo()
 	info = <SDL_VideoInfo*> tmp  # cast for constness adjustment
 	while stencil > 1:
 		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencil)
 		# Set the video mode
-		renderer.screen = SDL_SetVideoMode(width, height, bits_per_pixel, flags)
+		if virtual:
+			renderer.screen = Soya_SetVirtualVideoMode(width, height, bits_per_pixel, flags, quiet)
+		else:
+			renderer.screen = SDL_SetVideoMode(width, height, bits_per_pixel, flags)
 		if renderer.screen == NULL: stencil = stencil >> 1
 		else: break
 		
 	if renderer.screen == NULL:
 		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0)
-		renderer.screen = SDL_SetVideoMode(width, height, bits_per_pixel, flags)
+		if virtual:
+			renderer.screen = Soya_SetVirtualVideoMode(width, height, bits_per_pixel, flags, quiet)
+		else:
+			renderer.screen = SDL_SetVideoMode(width, height, bits_per_pixel, flags)
 		if renderer.screen == NULL:
 			s = "Video mode set failed : %s" % SDL_GetError()
 			sys.stderr.write(s + '\n')
 	if not root_widget is None:
 		root_widget.resize(0, 0, renderer.screen_width, renderer.screen_height)
 		
-		
-cdef void init_video(char* title, int width, int height, int fullscreen, int resizable, int quiet, int sdl_blit, int additional_flags):
+cdef SDL_Surface* Soya_SetVirtualVideoMode(int width, int height, int bpp, unsigned int flags, int quiet=False):
+	cdef SDL_Surface *ret
+	cdef SDLSurface surface
+
+	# Using the default masks for the depth
+	if not quiet:
+		sys.stdout.write("* Soya * Using a virtual SDL surface\n")
+
+	if "darwin" in sys.platform:
+		import soya._macosx
+		surface = <SDLSurface>soya._macosx.MacOSX_SDLSurface(flags, width, height, bpp)
+		ret = surface.sdl_surface
+	else:
+		s = "Virtual rendering is not supported by Soya3D for platform %s"%sys.platform
+		sys.stderr.write(s + '\n')
+		raise RuntimeError(s)
+
+	return ret
+
+cdef void init_video(char* title, int width, int height, int fullscreen, int resizable, int quiet, int sdl_blit, int additional_flags, int virtual):
 	import sys
 	if sys.platform == "darwin":
 		if not quiet:
 		s = "Could not initialize SDL : %s" % SDL_GetError()
 		sys.stderr.write(s + '\n')
 		raise RuntimeError(s)
-	set_video(width, height, fullscreen, resizable, quiet, sdl_blit, additional_flags)
+	set_video(width, height, fullscreen, resizable, quiet, sdl_blit, additional_flags, virtual)
 	if title != NULL: SDL_WM_SetCaption(title, NULL)
 
 
-def init(title = "Soya 3D", int width = 640, int height = 480, int fullscreen = 0, int resizeable = 1, int create_surface = 1, int sound = 0, sound_device = "", int sound_frequency = 44100, float sound_reference_distance = 1.0, float sound_doppler_factor = 0.01, int quiet=False, int sdl_blit = 0, int additional_flags = 0):
-	"""init(title = "Soya 3D", width = 640, height = 480, fullscreen = 0, resizeable = 1, create_surface = 1, sound = 0, sound_device = "", sound_frequency = 44100, sound_reference_distance = 1.0, sound_doppler_factor = 0.01, quiet=False)
+def init(title = "Soya 3D", int width = 640, int height = 480, int fullscreen = 0, int resizeable = 1, int create_surface = 1, int sound = 0, sound_device = "", int sound_frequency = 44100, float sound_reference_distance = 1.0, float sound_doppler_factor = 0.01, int quiet=False, int sdl_blit = 0, int additional_flags = 0, int virtual = False):
+	"""init(title = "Soya 3D", width = 640, height = 480, fullscreen = 0, resizeable = 1, create_surface = 1, sound = 0, sound_device = "", sound_frequency = 44100, sound_reference_distance = 1.0, sound_doppler_factor = 0.01, quiet=False, virtual=False)
 
 Inits Soya 3D and display the 3D view.
 
 	if not(renderer.engine_option & INITED):
 		base_init()
 		if create_surface:
-			init_video(title, width, height, fullscreen, resizeable, quiet, sdl_blit, additional_flags)
+			init_video(title, width, height, fullscreen, resizeable, quiet, sdl_blit, additional_flags, virtual)
 		init_joysticks()
 		init_gl()
 		glewInit()

File soya/opengl.pyx

 
 def glGenTextures(int n):
 	cdef GLuint ret
+	ret = 0
 	c_opengl.glGenTextures(n,&ret)
 	return ret
  

File soya/sdl.pxd

 
 SDL_ALLEVENTS = 0xFFFFFFFF
 
+cdef extern from "SDL/SDL_stdinc.h":
+	ctypedef unsigned short Uint16
+	ctypedef unsigned int Uint32
+
 cdef extern from "SDL/SDL.h":
 	ctypedef struct SDL_Rect:
 		unsigned short      x, y
 		unsigned short      w, h
 		
-	ctypedef struct SDL_Surface
+	ctypedef struct SDL_Surface:
+		Uint32 flags
+		SDL_PixelFormat *format
+		int w, h
+		Uint16 pitch
+		void *pixels
+		int offset
+		void *hwdata
+		SDL_Rect clip_rect
+		Uint32 unused1
+		Uint32 locked
+		void *map
+		unsigned int format_version
+		int refcount
+
 	ctypedef struct SDL_Joystick
 	ctypedef struct SDL_PixelFormat:
 		#SDL_Palette *palette
 	int SDLK_EURO
 	int SDLK_UNDO
 
+cdef class SDLSurface:
+	cdef SDL_Surface *sdl_surface

File soya/setup.py

 				},
 		}
 
+	if "darwin" in sys.platform:
+		KARGS["ext_modules"].append(Extension("soya._macosx", ["_macosx.pyx"],
+							include_dirs=INCDIR, library_dirs=LIBDIR,
+							libraries=LIBS, define_macros=DEFINES,
+							extra_compile_args = COMPILE_ARGS,
+							extra_link_args = LINK_ARGS,
+							))
 	
 else:
 	print
 				},
 		}
 
+	if "darwin" in sys.platform:
+		KARGS["ext_modules"].append(Extension("soya._macosx", ["_macosx.c"],
+							include_dirs=INCDIR, library_dirs=LIBDIR,
+							libraries=LIBS, define_macros=DEFINES,
+							extra_compile_args = COMPILE_ARGS, 
+							))
+
 	
 
 setup(