Anonymous avatar Anonymous committed aebbaf3

added opengl, other small fixes

Comments (0)

Files changed (8)

 # BREAK = change breaks existing code
 # BUG   = fixed a bug that was crashing
 
+Apr 18, 2001
+	added opengl support
+	fixed display.get_init()
+	current music is free'd when mixer is quit
+	better thread sharing in various video calls
+
 Apr 10, 2001
 	mixer now uses the requested sample format/size
 

docs/ref/pygame_display.html

 will wait for a vertical retrace and swap the surfaces. If you
 are using a different type of display mode, it will simply update
 the entire contents of the surface.
+<br>&nbsp;<br>
+When using an OPENGL display mode this will perform a gl buffer swap.
 </ul><br>&nbsp;<br>
 
 <a name=get_active><font size=+2><b>get_active
 documentation. The optional depth arguement is the requested bits
 per pixel. It will usually be left omitted, in which case the
 display will use the best/fastest pixel depth available.
+<br>&nbsp;<br>
+You can also create an OpenGL surface (for use with PyOpenGL)
+by passing the OPENGL flag. You will likely want to use the
+DOUBLEBUF flag when using OPENGL. In which case, the <a href=#flip>flip()</a>
+function will perform the GL buffer swaps. When you are using
+an OPENGL video mode, you will not be able to perform most of the
+pygame drawing functions (fill, set_at, etc) on the display surface.
+You can also use the special display flag OPENGLBLIT which will
+create a full OpenGL display, but also allow for limited pygame
+blitting.
 </ul><br>&nbsp;<br>
 
 <a name=toggle_fullscreen><font size=+2><b>toggle_fullscreen
 updating, it is best to combine them into a sequence and pass
 them all at once. This call will accept a sequence of rectstyle
 arguments. Any None's in the list will be ignored.
+<br>&nbsp;<br>
+This call cannot be used on OPENGL displays, and will generate
+an exception.
 </ul><br>&nbsp;<br>
 
 
 	DEC_CONST(RESIZABLE);
 	DEC_CONST(ASYNCBLIT);
 	DEC_CONST(OPENGL);
+	DEC_CONST(OPENGLBLIT)
 	DEC_CONST(ANYFORMAT);
 	DEC_CONST(HWPALETTE);
 	DEC_CONST(DOUBLEBUF);
 	if(!PyArg_ParseTuple(arg, ""))
 		return NULL;
 
-	return PyInt_FromLong(SDL_WasInit(SDL_INIT_CDROM)!=0);
+	return PyInt_FromLong(SDL_WasInit(SDL_INIT_VIDEO)!=0);
 }
 
 
     /*DOC*/    "documentation. The optional depth arguement is the requested bits\n"
     /*DOC*/    "per pixel. It will usually be left omitted, in which case the\n"
     /*DOC*/    "display will use the best/fastest pixel depth available.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "You can also create an OpenGL surface (for use with PyOpenGL)\n"
+    /*DOC*/    "by passing the OPENGL flag. You will likely want to use the\n"
+    /*DOC*/    "DOUBLEBUF flag when using OPENGL. In which case, the flip()\n"
+    /*DOC*/    "function will perform the GL buffer swaps. When you are using\n"
+    /*DOC*/    "an OPENGL video mode, you will not be able to perform most of the\n"
+    /*DOC*/    "pygame drawing functions (fill, set_at, etc) on the display surface.\n"
+    /*DOC*/    "You can also use the special display flag OPENGLBLIT which will\n"
+    /*DOC*/    "create a full OpenGL display, but also allow for limited pygame\n"
+    /*DOC*/    "blitting.\n"
     /*DOC*/ ;
 
 static PyObject* set_mode(PyObject* self, PyObject* arg)
 {
 	SDL_Surface* surf;
 	int flags = SDL_SWSURFACE, depth = 0;
-	int w, h;
+	int w, h, hasbuf;
 	char* title, *icontitle;
 
 	if(!PyArg_ParseTuple(arg, "(ii)|ii", &w, &h, &flags, &depth))
 
 	VIDEO_INIT_CHECK();
 
-	if(!depth)
-		flags |= SDL_ANYFORMAT;
+	if(flags & SDL_OPENGL)
+	{
+		if(flags & SDL_DOUBLEBUF)
+		{
+			flags &= ~SDL_DOUBLEBUF;
+			SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+		}
+		else
+			SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
+		if(depth)
+			SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depth);
+		Py_BEGIN_ALLOW_THREADS
+		surf = SDL_SetVideoMode(w, h, depth, flags);
+		Py_END_ALLOW_THREADS
+		if(!surf)
+			return RAISE(PyExc_SDLError, SDL_GetError());
 
-	surf = SDL_SetVideoMode(w, h, depth, flags);
-	if(!surf)
-		return RAISE(PyExc_SDLError, SDL_GetError());
+		SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &hasbuf);
+		if(hasbuf)
+		{
+			surf->flags |= SDL_DOUBLEBUF;
+		}
+	}
+	else
+	{
+		if(!depth)
+			flags |= SDL_ANYFORMAT;
+		Py_BEGIN_ALLOW_THREADS
+		surf = SDL_SetVideoMode(w, h, depth, flags);
+		Py_END_ALLOW_THREADS
+		if(!surf)
+			return RAISE(PyExc_SDLError, SDL_GetError());
+	}
 
 	SDL_WM_GetCaption(&title, &icontitle);
 	if(!title || !*title)
     /*DOC*/    "will wait for a vertical retrace and swap the surfaces. If you\n"
     /*DOC*/    "are using a different type of display mode, it will simply update\n"
     /*DOC*/    "the entire contents of the surface.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "When using an OPENGL display mode this will perform a gl buffer swap.\n"
     /*DOC*/ ;
 
 static PyObject* flip(PyObject* self, PyObject* arg)
 {
 	SDL_Surface* screen;
+	int status = 0;
 
 	if(!PyArg_ParseTuple(arg, ""))
 		return NULL;
 
 	screen = SDL_GetVideoSurface();
 	if(!screen)
+		return RAISE(PyExc_SDLError, "Display mode not set");
+
+	Py_BEGIN_ALLOW_THREADS
+	if(screen->flags & SDL_OPENGL)
+		SDL_GL_SwapBuffers();
+	else
+		status = SDL_Flip(screen) == -1;
+	Py_END_ALLOW_THREADS
+
+	if(status == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
-	if(SDL_Flip(screen) == -1)
-		return RAISE(PyExc_SDLError, SDL_GetError());
-	
+
 	RETURN_NONE
 }
 
     /*DOC*/    "updating, it is best to combine them into a sequence and pass\n"
     /*DOC*/    "them all at once. This call will accept a sequence of rectstyle\n"
     /*DOC*/    "arguments. Any None's in the list will be ignored.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "This call cannot be used on OPENGL displays, and will generate\n"
+    /*DOC*/    "an exception.\n"
     /*DOC*/ ;
 
 static PyObject* update(PyObject* self, PyObject* arg)
 	wide = screen->w;
 	high = screen->h;
 
+
+	if(screen->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot update() an OPENGL display");
+
 	if(gr) /*single or no rect given*/
 	{
 		if(screencroprect(gr, wide, high))
 }
 
 
-PyObject* testgl1(PyObject* self, PyObject* arg)
-{
-	if(!PyArg_ParseTuple(arg, ""))
-		return NULL;
-	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
-	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
-	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
-	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
-	RETURN_NONE
-}
-
-PyObject* testgl2(PyObject* self, PyObject* arg)
-{
-	int r, g, b, d;
-	if(!PyArg_ParseTuple(arg, ""))
-		return NULL;
-	SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &r );
-	SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &g );
-	SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &b );
-	SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &d );
-
-	printf("R,G,B,D = %d,%d,%d, %d\n", r, g, b, d);
-
-	RETURN_NONE
-}
-
-static PyObject* gl_swap_buffers(PyObject* self, PyObject* arg)
-{
-    if(!PyArg_ParseTuple(arg, ""))
-        return NULL;
-
-    VIDEO_INIT_CHECK();
-
-    SDL_GL_SwapBuffers();
-
-    RETURN_NONE
-}
-
 
 static PyMethodDef display_builtins[] =
 {
 	{ "iconify", iconify, 1, doc_iconify },
 	{ "toggle_fullscreen", toggle_fullscreen, 1, doc_toggle_fullscreen },
 
-	{ "testgl1", testgl1, 1, NULL },
-	{ "testgl2", testgl2, 1, NULL },
-{ "gl_swap_buffers", gl_swap_buffers, 1, NULL },
-
 	{ NULL, NULL }
 };
 
 static int request_size = MIX_DEFAULT_FORMAT;
 static int request_stereo = 1;
 
+Mix_Music** current_music;
 
 
 static void autoquit(void)
 {
 	if(SDL_WasInit(SDL_INIT_AUDIO))
 	{
+		if(current_music)
+		{
+			if(*current_music)
+			{
+				Mix_FreeMusic(*current_music);
+				*current_music = NULL;
+			}
+			current_music = NULL;
+		}
+
 		Mix_CloseAudio();
 		SDL_QuitSubSystem(SDL_INIT_AUDIO);
 	}
 
 	music = PyImport_ImportModule("pygame.mixer_music");
 	if(music) 
+	{
+		PyObject* ptr, *dict;
 		PyModule_AddObject(module, "music", music);
+		dict = PyModule_GetDict(music);
+		ptr = PyDict_GetItemString(dict, "_MUSIC_POINTER");
+		current_music = (Mix_Music**)PyCObject_AsVoidPtr(ptr);
+	}	
 	else /*music module not compiled? cleanly ignore*/
+	{
+		current_music = NULL;
 		PyErr_Clear();
+	}
 }
 
 PYGAME_EXPORT
 void initmixer_music(void)
 {
-	PyObject *module, *dict;
+	PyObject *module;
 
 	PyMIXER_C_API[0] = PyMIXER_C_API[0]; /*clean an unused warning*/
 
     /* create the module */
 	module = Py_InitModule3("mixer_music", music_builtins, doc_pygame_mixer_music_MODULE);
-	dict = PyModule_GetDict(module);
+	PyModule_AddObject(module, "_MUSIC_POINTER", PyCObject_FromVoidPtr(&current_music, NULL));
 
 	/*imported needed apis*/
 	import_pygame_base();
 	if(!PyArg_ParseTuple(arg, "(ii)", &x, &y))
 		return NULL;
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(x < 0 || x >= surf->w || y < 0 || y >= surf->h)
 		return RAISE(PyExc_IndexError, "pixel index out of range");
 
 	if(!PyArg_ParseTuple(args, "(ii)O", &x, &y, &rgba_obj))
 		return NULL;
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(x < 0 || x >= surf->w || y < 0 || y >= surf->h)
 	{
 		PyErr_SetString(PyExc_IndexError, "pixel index out of range");
 	if(!PyArg_ParseTuple(args, "|Oi", &rgba_obj, &flags))
 		return NULL;
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(rgba_obj)
 	{
 		if(PyInt_Check(rgba_obj))
 	if(!PyArg_ParseTuple(args, ""))
 		return NULL;
 	
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(!(surf->flags&SDL_SRCCOLORKEY))
 		RETURN_NONE
 
 	if(!PyArg_ParseTuple(args, "|bi", &alpha, &flags))
 		return NULL;
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(PyTuple_Size(args) > 0)
 		flags |= SDL_SRCALPHA;
 
 	if(!PyArg_ParseTuple(args, ""))
 		return NULL;
 	
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(surf->flags&SDL_SRCALPHA)
 		return PyInt_FromLong(surf->format->alpha);
 
 	if(!PyArg_ParseTuple(args, "O|O", &rgba_obj, &r))
 		return NULL;
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(PyInt_Check(rgba_obj))
 		color = (Uint32)PyInt_AsLong(rgba_obj);
 	else if(RGBAFromObj(rgba_obj, rgba))
 		return NULL;
 	src = PySurface_AsSurface(srcobject);
 
+	if(dest->flags & SDL_OPENGL && !(dest->flags&(SDL_OPENGLBLIT&~SDL_OPENGL)))
+		return RAISE(PyExc_SDLError, "Cannot blit to OPENGL Surfaces (OPENGLBLIT is ok)");
+
 	if((src_rect = GameRect_FromObject(argpos, &temp)))
 	{
 		dx = src_rect->x;
 
 	PySurface_Prep(self);
 	PySurface_Prep(srcobject);
+	Py_BEGIN_ALLOW_THREADS
 	result = SDL_BlitSurface(src, (SDL_Rect*)src_rect, dest, &dest_rect);
+	Py_END_ALLOW_THREADS
 	PySurface_Unprep(self);
 	PySurface_Unprep(srcobject);
 
 	if(result == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
-
+	if(result == -2)
+		return RAISE(PyExc_SDLError, "Surface was lost");
 
 
 	return PyRect_New((GAME_Rect*)&dest_rect);
 
 	VIDEO_INIT_CHECK();
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(PyString_Check(file))
 	{
 		char* name = PyString_AsString(file);
 
 	VIDEO_INIT_CHECK();
 
+	if(surf->flags & SDL_OPENGL)
+		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
+
 	if(!(rect = GameRect_FromObject(args, &temp)))
 		return RAISE(PyExc_ValueError, "invalid rectstyle argument");
 	if(rect->x < 0 || rect-> y < 0 || rect->x + rect->w > surf->w || rect->y + rect->h > surf->h)
 	{
 		if(surf->subsurface)
 			PySurface_Prep(surfobj);
-		if(SDL_LockSurface(surf->surf) == -1)
+		if(SDL_LockSurface(surf->surf) >= -1)
 		{
 			PyErr_SetString(PyExc_RuntimeError, "error locking surface");
 			return 0;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.