/*
    pygame - Python Game Library
    Copyright (C) 2000-2001  Pete Shinners

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Pete Shinners
    pete@shinners.org
*/

/*
 *  pygame display module
 */
#define PYGAMEAPI_DISPLAY_INTERNAL
#include "pygame.h"
#include <SDL_syswm.h>


static PyObject* self_module = NULL;


staticforward PyTypeObject PyVidInfo_Type;
static PyObject* PyVidInfo_New(const SDL_VideoInfo* info);
static void do_set_icon(PyObject *surface);
static PyObject* DisplaySurfaceObject = NULL;
static int icon_was_set = 0;

#if (!defined(darwin))
static char* icon_defaultname = "pygame_icon.bmp";
static char* pkgdatamodule_name = "pygame.pkgdata";
static char* imagemodule_name = "pygame.image";
static char* resourcefunc_name = "getResource";
static char* load_basicfunc_name = "load_basic";
static PyObject *display_resource(char *filename) {
	PyObject* imagemodule = NULL;
	PyObject* load_basicfunc = NULL;
	PyObject* pkgdatamodule = NULL;
	PyObject* resourcefunc = NULL;
	PyObject* fresult = NULL;
	PyObject* result = NULL;

	pkgdatamodule = PyImport_ImportModule(pkgdatamodule_name);
	if (!pkgdatamodule) goto display_resource_end;

	resourcefunc = PyObject_GetAttrString(pkgdatamodule, resourcefunc_name);
	if (!resourcefunc) goto display_resource_end;

	imagemodule = PyImport_ImportModule(imagemodule_name);
	if (!imagemodule) goto display_resource_end;

	load_basicfunc = PyObject_GetAttrString(imagemodule, load_basicfunc_name);
	if (!load_basicfunc) goto display_resource_end;
	
	fresult = PyObject_CallFunction(resourcefunc, "s", filename);
	if (!fresult) goto display_resource_end;

	if (PyFile_Check(fresult)) {
		PyObject *tmp = PyFile_Name(fresult);
		Py_INCREF(tmp);
		Py_DECREF(fresult);
		fresult = tmp;
	}

	result = PyObject_CallFunction(load_basicfunc, "O", fresult);
	if (!result) goto display_resource_end;

display_resource_end:
	Py_XDECREF(pkgdatamodule);
	Py_XDECREF(resourcefunc);
	Py_XDECREF(imagemodule);
	Py_XDECREF(load_basicfunc);
	Py_XDECREF(fresult);
	return result;
}
#endif

#if 0
/*quick internal test to see if gamma is supported*/
static int check_hasgamma()
{
	int result = 0;
/*
	Uint8 r[256], g[256], b[256];
printf("checking for gamma...\n");
	result =  SDL_GetGammaRamp(r, g, b) != -1;
printf("...done\n");
*/
	return result;
}
#endif



/* init routines */
static void display_autoquit(void)
{
	if(DisplaySurfaceObject)
	{
		PySurface_AsSurface(DisplaySurfaceObject) = NULL;
		Py_DECREF(DisplaySurfaceObject);
		DisplaySurfaceObject = NULL;
	}
}

static PyObject* display_autoinit(PyObject* self, PyObject* arg)
{
	PyGame_RegisterQuit(display_autoquit);
	return PyInt_FromLong(1);
}


    /*DOC*/ static char doc_quit[] =
    /*DOC*/    "pygame.display.quit() -> None\n"
    /*DOC*/    "uninitialize the display module\n"
    /*DOC*/    "\n"
    /*DOC*/    "Manually uninitialize SDL's video subsystem. It is safe to call\n"
    /*DOC*/    "this if the video is currently not initialized.\n"
    /*DOC*/ ;

static PyObject* quit(PyObject* self, PyObject* arg)
{
	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	PyGame_Video_AutoQuit();
	display_autoquit();

	RETURN_NONE
}


    /*DOC*/ static char doc_init[] =
    /*DOC*/    "pygame.display.init() -> None\n"
    /*DOC*/    "initialize the display module\n"
    /*DOC*/    "\n"
    /*DOC*/    "Manually initialize SDL's video subsystem. Will raise an\n"
    /*DOC*/    "exception if it cannot be initialized. It is safe to call this\n"
    /*DOC*/    "function if the video has is currently initialized.\n"
    /*DOC*/ ;

static PyObject* init(PyObject* self, PyObject* arg)
{
/*  
	We'll just ignore the args
	XXX:  Why?!
*/
#if 0
	if(!PyArg_ParseTuple(arg, ""))
		return NULL;
#endif
	if(!PyGame_Video_AutoInit())
		return RAISE(PyExc_SDLError, SDL_GetError());
	if(!display_autoinit(NULL, NULL))
		return NULL;

	RETURN_NONE
}



    /*DOC*/ static char doc_get_init[] =
    /*DOC*/    "pygame.display.get_init() -> bool\n"
    /*DOC*/    "get status of display module initialization\n"
    /*DOC*/    "\n"
    /*DOC*/    "Returns true if SDL's video system is currently intialized.\n"
    /*DOC*/ ;

static PyObject* get_init(PyObject* self, PyObject* arg)
{
	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	return PyInt_FromLong(SDL_WasInit(SDL_INIT_VIDEO)!=0);
}



    /*DOC*/ static char doc_get_active[] =
    /*DOC*/    "pygame.display.get_active() -> bool\n"
    /*DOC*/    "get state of display mode\n"
    /*DOC*/    "\n"
    /*DOC*/    "Returns true if the current display is active on the screen. This\n"
    /*DOC*/    "done with the call to pygame.display.set_mode(). It is\n"
    /*DOC*/    "potentially subject to the activity of a running window manager.\n"
    /*DOC*/    "\n"
    /*DOC*/    "Calling set_mode() will change all existing display surface\n"
    /*DOC*/    "to reference the new display mode. The old display surface will\n"
    /*DOC*/    "be lost after this call.\n"
    /*DOC*/ ;

static PyObject* get_active(PyObject* self, PyObject* arg)
{
	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	return PyInt_FromLong((SDL_GetAppState()&SDL_APPACTIVE) != 0);
}



/* vidinfo object */

static void vidinfo_dealloc(PyObject* self)
{
	PyObject_DEL(self);
}



static PyObject *vidinfo_getattr(PyObject *self, char *name)
{
	SDL_VideoInfo* info = &((PyVidInfoObject*)self)->info;

	if(!strcmp(name, "hw"))
		return PyInt_FromLong(info->hw_available);
	else if(!strcmp(name, "wm"))
		return PyInt_FromLong(info->wm_available);
/*	else if(!strcmp(name, "gamma"))
		return PyInt_FromLong(check_hasgamma());
*/	else if(!strcmp(name, "blit_hw"))
		return PyInt_FromLong(info->blit_hw);
	else if(!strcmp(name, "blit_hw_CC"))
		return PyInt_FromLong(info->blit_hw_CC);
	else if(!strcmp(name, "blit_hw_A"))
		return PyInt_FromLong(info->blit_hw_A);
	else if(!strcmp(name, "blit_sw"))
		return PyInt_FromLong(info->blit_hw);
	else if(!strcmp(name, "blit_sw_CC"))
		return PyInt_FromLong(info->blit_hw_CC);
	else if(!strcmp(name, "blit_sw_A"))
		return PyInt_FromLong(info->blit_hw_A);
	else if(!strcmp(name, "blit_fill"))
		return PyInt_FromLong(info->blit_fill);
	else if(!strcmp(name, "video_mem"))
		return PyInt_FromLong(info->video_mem);
	else if(!strcmp(name, "bitsize"))
		return PyInt_FromLong(info->vfmt->BitsPerPixel);
	else if(!strcmp(name, "bytesize"))
		return PyInt_FromLong(info->vfmt->BytesPerPixel);
	else if(!strcmp(name, "masks"))
		return Py_BuildValue("(iiii)", info->vfmt->Rmask, info->vfmt->Gmask,
					info->vfmt->Bmask, info->vfmt->Amask);
	else if(!strcmp(name, "shifts"))
		return Py_BuildValue("(iiii)", info->vfmt->Rshift, info->vfmt->Gshift,
					info->vfmt->Bshift, info->vfmt->Ashift);
	else if(!strcmp(name, "losses"))
		return Py_BuildValue("(iiii)", info->vfmt->Rloss, info->vfmt->Gloss,
					info->vfmt->Bloss, info->vfmt->Aloss);

	return RAISE(PyExc_AttributeError, "does not exist in vidinfo");
}


PyObject* vidinfo_str(PyObject* self)
{
	char str[1024];
	SDL_VideoInfo* info = &((PyVidInfoObject*)self)->info;

	sprintf(str, "<VideoInfo(hw = %d, wm = %d,video_mem = %d\n"
				 "	     blit_hw = %d, blit_hw_CC = %d, blit_hw_A = %d,\n"
				 "	     blit_sw = %d, blit_sw_CC = %d, blit_sw_A = %d,\n"
				 "	     bitsize  = %d, bytesize = %d,\n"
				 "	     masks =  (%d, %d, %d, %d),\n"
				 "	     shifts = (%d, %d, %d, %d),\n"
				 "	     losses =  (%d, %d, %d, %d)>\n",
				info->hw_available, info->wm_available, info->video_mem,
				info->blit_hw, info->blit_hw_CC, info->blit_hw_A,
				info->blit_sw, info->blit_sw_CC, info->blit_sw_A,
				info->vfmt->BitsPerPixel, info->vfmt->BytesPerPixel,
				info->vfmt->Rmask, info->vfmt->Gmask, info->vfmt->Bmask, info->vfmt->Amask,
				info->vfmt->Rshift, info->vfmt->Gshift, info->vfmt->Bshift, info->vfmt->Ashift,
				info->vfmt->Rloss, info->vfmt->Gloss, info->vfmt->Bloss, info->vfmt->Aloss);

	return PyString_FromString(str);
}


static PyTypeObject PyVidInfo_Type =
{
	PyObject_HEAD_INIT(NULL)
	0,						/*size*/
	"VidInfo",				/*name*/
	sizeof(PyVidInfoObject),/*basic size*/
	0,						/*itemsize*/
	vidinfo_dealloc,		/*dealloc*/
	0,						/*print*/
	vidinfo_getattr,		/*getattr*/
	NULL,					/*setattr*/
	NULL,					/*compare*/
	vidinfo_str,			/*repr*/
	NULL,					/*as_number*/
	NULL,					/*as_sequence*/
	NULL,					/*as_mapping*/
	(hashfunc)NULL, 		/*hash*/
	(ternaryfunc)NULL,		/*call*/
	(reprfunc)NULL, 		/*str*/
};


static PyObject* PyVidInfo_New(const SDL_VideoInfo* i)
{
	PyVidInfoObject* info;

	if(!i) return RAISE(PyExc_SDLError, SDL_GetError());

	info = PyObject_NEW(PyVidInfoObject, &PyVidInfo_Type);
	if(!info) return NULL;

	memcpy(&info->info, i, sizeof(SDL_VideoInfo));
	return (PyObject*)info;
}



/* display functions */
#if 0
    /*DOC*/ static char docXX_set_driver[] =
    /*DOC*/    "pygame.display.set_driver(name) -> None\n"
    /*DOC*/    "override the default sdl video driver\n"
    /*DOC*/    "\n"
    /*DOC*/    "Changes the SDL environment to initialize with the given named\n"
    /*DOC*/    "videodriver. This can only be changed before the display is\n"
    /*DOC*/    "initialized. If this is not called, SDL will use it's default\n"
    /*DOC*/    "video driver, or the one in the environment variable\n"
    /*DOC*/    "SDL_VIDEODRIVER.\n"
    /*DOC*/ ;

static PyObject* set_driver(PyObject* self, PyObject* arg)
{
	char* name;
	if(!PyArg_ParseTuple(arg, "s", &name))
		return NULL;

	if(SDL_WasInit(SDL_INIT_VIDEO))
		return RAISE(PyExc_SDLError, "cannot switch video driver while initialized");

	/*override the default video driver*/
	/*environment variable: SDL_VIDEODRIVER*/

	RETURN_NONE
}
#endif

    /*DOC*/ static char doc_get_driver[] =
    /*DOC*/    "pygame.display.get_driver() -> name\n"
    /*DOC*/    "get the current sdl video driver\n"
    /*DOC*/    "\n"
    /*DOC*/    "Once the display is initialized, this will return the name of the\n"
    /*DOC*/    "currently running video driver. There is no way to get a list of\n"
    /*DOC*/    "all the supported video drivers.\n"
    /*DOC*/ ;

static PyObject* get_driver(PyObject* self, PyObject* args)
{
	char buf[256];

	if(!PyArg_ParseTuple(args, ""))
		return NULL;

	VIDEO_INIT_CHECK();

	if(!SDL_VideoDriverName(buf, sizeof(buf)))
	{
		Py_INCREF(Py_None);
		return Py_None;
	}
	return PyString_FromString(buf);
}



    /*DOC*/ static char doc_get_wm_info[] =
    /*DOC*/    "pygame.display.get_wm_info() -> dictionary\n"
    /*DOC*/    "get settings from the system window manager\n"
    /*DOC*/    "\n"
    /*DOC*/    "Creates a dictionary filled with name and value pairs.\n"
    /*DOC*/    "Most platforms will have a 'window' value, set to the\n"
    /*DOC*/    "system's window id number or handle.\n"
    /*DOC*/    "Different platforms will get different key values, which\n"
    /*DOC*/    "are entirely dependent on SDL.\n"
    /*DOC*/    "On rare platforms this is unimplmented in the SDL system, and\n"
    /*DOC*/    "you will get an empty dictionary.\n"
    /*DOC*/ ;

static PyObject* get_wm_info(PyObject* self, PyObject* args)
{
	PyObject *dict;
	SDL_SysWMinfo info;

	if(!PyArg_ParseTuple(args, ""))
		return NULL;

	VIDEO_INIT_CHECK();

	SDL_VERSION(&(info.version))
	dict = PyDict_New();
	if(!dict || !SDL_GetWMInfo(&info))
		return dict;

/*scary #ifdef's match SDL_syswm.h*/
#if (defined(unix) || defined(__unix__) || defined(_AIX) || defined(__OpenBSD__)) && \
	(!defined(DISABLE_X11) && !defined(__CYGWIN32__) && !defined(ENABLE_NANOX) && \
	 !defined(__QNXNTO__))
		PyDict_SetItemString(dict, "window", PyInt_FromLong(info.info.x11.window));
		PyDict_SetItemString(dict, "display", PyCObject_FromVoidPtr(info.info.x11.display, NULL));
		PyDict_SetItemString(dict, "lock_func", PyCObject_FromVoidPtr(info.info.x11.lock_func, NULL));
		PyDict_SetItemString(dict, "unlock_func", PyCObject_FromVoidPtr(info.info.x11.unlock_func, NULL));
		PyDict_SetItemString(dict, "fswindow", PyInt_FromLong(info.info.x11.fswindow));
		PyDict_SetItemString(dict, "wmwindow", PyInt_FromLong(info.info.x11.wmwindow));
#elif defined(ENABLE_NANOX)
		PyDict_SetItemString(dict, "window", PyInt_FromLong(info.window));
#elif defined(WIN32)
		PyDict_SetItemString(dict, "window", PyInt_FromLong((long)info.window));
		PyDict_SetItemString(dict, "hglrc", PyInt_FromLong((long)info.hglrc));
#elif defined(__riscos__)
		PyDict_SetItemString(dict, "window", PyInt_FromLong(info.window));
		PyDict_SetItemString(dict, "wimpVersion", PyInt_FromLong(info.wimpVersion));
		PyDict_SetItemString(dict, "taskHandle", PyInt_FromLong(info.taskHandle));
#else
		PyDict_SetItemString(dict, "data", PyInt_FromLong(info.data));
#endif
		
		return dict;
}



    /*DOC*/ static char doc_Info[] =
    /*DOC*/    "pygame.display.Info() -> VidInfo\n"
    /*DOC*/    "get display capabilities and settings\n"
    /*DOC*/    "\n"
    /*DOC*/    "Gets a vidinfo object that contains information about the\n"
    /*DOC*/    "capabilities and current state of the video driver. This can be\n"
    /*DOC*/    "called before the display mode is set, to determine the current\n"
    /*DOC*/    "video mode of a display.\n"
    /*DOC*/    "You can print the VidInfo object to see all its members and values.\n"
    /*DOC*/ ;

static PyObject* Info(PyObject* self, PyObject* arg)
{
	const SDL_VideoInfo* info;

	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	VIDEO_INIT_CHECK();

	info = SDL_GetVideoInfo();
	return PyVidInfo_New(info);
}




    /*DOC*/ static char doc_get_surface[] =
    /*DOC*/    "pygame.display.get_surface() -> Surface\n"
    /*DOC*/    "get current display surface\n"
    /*DOC*/    "\n"
    /*DOC*/    "Returns a Surface object representing the current display. Will\n"
    /*DOC*/    "return None if called before the display mode is set.\n"
    /*DOC*/ ;

static PyObject* get_surface(PyObject* self, PyObject* arg)
{
	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	if(!DisplaySurfaceObject)
		RETURN_NONE

	Py_INCREF(DisplaySurfaceObject);
	return DisplaySurfaceObject;
}

    /*DOC*/ static char doc_gl_set_attribute[] =
    /*DOC*/    "pygame.display.gl_set_attribute(flag, value) -> None\n"
    /*DOC*/    "set special OPENGL attributes\n"
    /*DOC*/    "\n"
    /*DOC*/    "When calling pygame.display.set_mode() with the OPENGL flag,\n"
    /*DOC*/    "pygame automatically handles setting the opengl attributes like\n"
    /*DOC*/    "color and doublebuffering. OPENGL offers several other attributes\n"
    /*DOC*/    "you may want control over. Pass one of these attributes as the\n"
    /*DOC*/    "flag, and its appropriate value.\n"
    /*DOC*/    "\n"
    /*DOC*/    "This must be called before pygame.display.set_mode()\n"
    /*DOC*/    "\n"
    /*DOC*/    "The OPENGL flags are; GL_ALPHA_SIZE, GL_DEPTH_SIZE, GL_STENCIL_SIZE,\n"
    /*DOC*/    "GL_ACCUM_RED_SIZE, GL_ACCUM_GREEN_SIZE, GL_ACCUM_BLUE_SIZE, GL_ACCUM_ALPHA_SIZE\n"
    /*DOC*/    "GL_MULTISAMPLEBUFFERS, GL_MULTISAMPLESAMPLES, GL_STEREO\n"
    /*DOC*/ ;

static PyObject* gl_set_attribute(PyObject* self, PyObject* arg)
{
        int flag, value, result;

	VIDEO_INIT_CHECK();

	if(!PyArg_ParseTuple(arg, "ii", &flag, &value))
		return NULL;
	if(flag == -1) /*an undefined/unsupported val, ignore*/
		RETURN_NONE

	result = SDL_GL_SetAttribute(flag, value);
	if(result == -1)
		return RAISE(PyExc_SDLError, SDL_GetError());
	RETURN_NONE
}


    /*DOC*/ static char doc_gl_get_attribute[] =
    /*DOC*/    "pygame.display.gl_get_attribute(flag) -> value\n"
    /*DOC*/    "get special OPENGL attributes\n"
    /*DOC*/    "\n"
    /*DOC*/    "After calling pygame.display.set_mode() with the OPENGL flag\n"
    /*DOC*/    "you will likely want to check the value of any special opengl\n"
    /*DOC*/    "attributes you requested. You will not always get what you\n"
    /*DOC*/    "requested.\n"
    /*DOC*/    "\n"
    /*DOC*/    "See pygame.display.gl_set_attribute() for a list of flags.\n"
    /*DOC*/    "\n"
    /*DOC*/    "The OPENGL flags are; GL_ALPHA_SIZE, GL_DEPTH_SIZE, GL_STENCIL_SIZE,\n"
    /*DOC*/    "GL_ACCUM_RED_SIZE, GL_ACCUM_GREEN_SIZE, GL_ACCUM_BLUE_SIZE, GL_ACCUM_ALPHA_SIZE,\n"
    /*DOC*/    "GL_RED_SIZE, GL_GREEN_SIZE, GL_BLUE_SIZE, GL_DEPTH_SIZE\n"
    /*DOC*/ ;

static PyObject* gl_get_attribute(PyObject* self, PyObject* arg)
{
	int flag, value, result;

	VIDEO_INIT_CHECK();

	if(!PyArg_ParseTuple(arg, "i", &flag))
		return NULL;

	result = SDL_GL_GetAttribute(flag, &value);
	if(result == -1)
		return RAISE(PyExc_SDLError, SDL_GetError());

	return PyInt_FromLong(value);
}



    /*DOC*/ static char doc_set_mode[] =
    /*DOC*/    "pygame.display.set_mode(size, [flags, [depth]]) -> Surface\n"
    /*DOC*/    "set the display mode\n"
    /*DOC*/    "\n"
    /*DOC*/    "Sets the current display mode. If calling this after the mode has\n"
    /*DOC*/    "already been set, this will change the display mode to the\n"
    /*DOC*/    "desired type. Sometimes an exact match for the requested video\n"
    /*DOC*/    "mode is not available. In this case SDL will try to find the\n"
    /*DOC*/    "closest match and work with that instead.\n"
    /*DOC*/    "\n"
    /*DOC*/    "The size is a 2-number-sequence containing the width and height\n"
    /*DOC*/    "of the desired display mode. Flags represents a set of different\n"
    /*DOC*/    "options for the new display mode. If omitted or given as 0, it\n"
    /*DOC*/    "will default to a simple software window. You can mix several\n"
    /*DOC*/    "flags together with the bitwise-or (|) operator. Possible flags\n"
    /*DOC*/    "are HWSURFACE (or the value 1), HWPALETTE, DOUBLEBUF, and/or\n"
    /*DOC*/    "FULLSCREEN. There are other flags available but these are the\n"
    /*DOC*/    "most usual. A full list of flags can be found in the pygame\n"
    /*DOC*/    "documentation.\n"
    /*DOC*/    "\n"
    /*DOC*/    "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 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*/ ;

static PyObject* set_mode(PyObject* self, PyObject* arg)
{
	SDL_Surface* surf;
	int depth = 0;
	int flags = SDL_SWSURFACE;
	int w, h, hasbuf;
	char *title, *icontitle;

	if(!PyArg_ParseTuple(arg, "(ii)|ii", &w, &h, &flags, &depth))
		return NULL;

	if(w <= 0 || h <= 0)
		return RAISE(PyExc_SDLError, "Cannot set 0 sized display mode");
		
	if(!SDL_WasInit(SDL_INIT_VIDEO))
	{
		/*note SDL works special like this too*/
		if(!init(NULL, NULL))
			return NULL;
	}

	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);
		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)
		SDL_WM_SetCaption("pygame window", "pygame");

	/*probably won't do much, but can't hurt, and might help*/
	SDL_PumpEvents();

	if(DisplaySurfaceObject)
		((PySurfaceObject*)DisplaySurfaceObject)->surf = surf;
	else
		DisplaySurfaceObject = PySurface_New(surf);


#if !defined(darwin)
	if(!icon_was_set)
	{
		PyObject* iconsurf = display_resource(icon_defaultname);
		if (!iconsurf)
			PyErr_Clear();
		else {
			SDL_SetColorKey(PySurface_AsSurface(iconsurf), SDL_SRCCOLORKEY, 0);
			do_set_icon(iconsurf);
			Py_DECREF(iconsurf);
		}
	}
#endif
	Py_INCREF(DisplaySurfaceObject);
	return DisplaySurfaceObject;
}



    /*DOC*/ static char doc_mode_ok[] =
    /*DOC*/    "pygame.display.mode_ok(size, [flags, [depth]]) -> int\n"
    /*DOC*/    "query a specific display mode\n"
    /*DOC*/    "\n"
    /*DOC*/    "This uses the same arguments as the call to\n"
    /*DOC*/    "pygame.display.set_mode(). It is used to determine if a requested\n"
    /*DOC*/    "display mode is available. It will return 0 if the requested mode\n"
    /*DOC*/    "is not possible. Otherwise it will return the best and closest\n"
    /*DOC*/    "matching bit depth for the mode requested.\n"
    /*DOC*/    "\n"
    /*DOC*/    "The size is a 2-number-sequence containing the width and height\n"
    /*DOC*/    "of the desired display mode. Flags represents a set of different\n"
    /*DOC*/    "options for the display mode. If omitted or given as 0, it will\n"
    /*DOC*/    "default to a simple software window. You can mix several flags\n"
    /*DOC*/    "together with the bitwise-or (|) operator. Possible flags are\n"
    /*DOC*/    "HWSURFACE (or the value 1), HWPALETTE, DOUBLEBUF, and/or\n"
    /*DOC*/    "FULLSCREEN. There are other flags available but these are the\n"
    /*DOC*/    "most usual. A full list of flags can be found in the SDL\n"
    /*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*/ ;

static PyObject* mode_ok(PyObject* self, PyObject* args)
{
	int depth=0;
	int w, h;
	int flags = SDL_SWSURFACE;

	VIDEO_INIT_CHECK();

	if(!PyArg_ParseTuple(args, "(ii)|ii", &w, &h, &flags, &depth))
		return NULL;
	if(!depth)
		depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;

	return PyInt_FromLong(SDL_VideoModeOK(w, h, depth, flags));
}



    /*DOC*/ static char doc_list_modes[] =
    /*DOC*/    "pygame.display.list_modes([depth, [flags]]) -> [[x,y],...] | -1\n"
    /*DOC*/    "query all resolutions for requested mode\n"
    /*DOC*/    "\n"
    /*DOC*/    "This function returns a list of possible dimensions for a\n"
    /*DOC*/    "specified color depth. The return value will be an empty list if\n"
    /*DOC*/    "no display modes are available with the given arguments. A return\n"
    /*DOC*/    "value of -1 means that any requested resolution should work (this\n"
    /*DOC*/    "is likely the case for windowed modes). Mode sizes are sorted\n"
    /*DOC*/    "from biggest to smallest.\n"
    /*DOC*/    "\n"
    /*DOC*/    "If depth is not passed or 0, SDL will choose the current/best\n"
    /*DOC*/    "color depth for the display. You will usually want to pass\n"
    /*DOC*/    "FULLSCREEN when using the flags, if flags is omitted, FULLSCREEN\n"
    /*DOC*/    "is the default.\n"
    /*DOC*/ ;

static PyObject* list_modes(PyObject* self, PyObject* args)
{
	SDL_PixelFormat format;
	SDL_Rect** rects;
	int flags=SDL_FULLSCREEN;
	PyObject *list, *size;

	format.BitsPerPixel = 0;
	if(PyTuple_Size(args)!=0 && !PyArg_ParseTuple(args, "|bi", &format.BitsPerPixel, &flags))
		return NULL;

	VIDEO_INIT_CHECK();

	if(!format.BitsPerPixel)
		format.BitsPerPixel = SDL_GetVideoInfo()->vfmt->BitsPerPixel;

	rects = SDL_ListModes(&format, flags);

	if(rects == (SDL_Rect**)-1)
		return PyInt_FromLong(-1);

	if(!(list = PyList_New(0)))
		return NULL;
	if(!rects)
		return list;

	for(; *rects; ++rects)
	{
		if(!(size = Py_BuildValue("(ii)", (*rects)->w, (*rects)->h)))
		{
			Py_DECREF(list);
			return NULL;
		}
		PyList_Append(list, size);
		Py_DECREF(size);
	}
	return list;
}



    /*DOC*/ static char doc_flip[] =
    /*DOC*/    "pygame.display.flip() -> None\n"
    /*DOC*/    "update the display\n"
    /*DOC*/    "\n"
    /*DOC*/    "This will update the contents of the entire display. If your\n"
    /*DOC*/    "display mode is using the flags HWSURFACE and DOUBLEBUF, this\n"
    /*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;

	VIDEO_INIT_CHECK();

	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());

	RETURN_NONE
}


/*BAD things happen when out-of-bound rects go to updaterect*/
static SDL_Rect* screencroprect(GAME_Rect* r, int w, int h, SDL_Rect* cur)
{
	if(r->x > w || r->y > h || (r->x + r->w) <= 0 || (r->y + r->h) <= 0)
		return 0;
	else
	{
		int right = min(r->x + r->w, w);
		int bottom = min(r->y + r->h, h);
		cur->x = (short)max(r->x, 0);
		cur->y = (short)max(r->y, 0);
		cur->w = (unsigned short)right - cur->x;
		cur->h = (unsigned short)bottom - cur->y;
	}
	return cur;
}

    /*DOC*/ static char doc_update[] =
    /*DOC*/    "pygame.display.update([rectstyle]) -> None\n"
    /*DOC*/    "update an area of the display\n"
    /*DOC*/    "\n"
    /*DOC*/    "This call will update a section (or sections) of the display\n"
    /*DOC*/    "screen. You must update an area of your display when you change\n"
    /*DOC*/    "its contents. If passed with no arguments, this will update the\n"
    /*DOC*/    "entire display surface. If you have many rects that need\n"
    /*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)
{
	SDL_Surface* screen;
	GAME_Rect *gr, temp = {0};
	int wide, high;
	PyObject* obj;

	VIDEO_INIT_CHECK();

	screen = SDL_GetVideoSurface();
	if(!screen)
		return RAISE(PyExc_SDLError, SDL_GetError());
	wide = screen->w;
	high = screen->h;
	if(screen->flags & SDL_OPENGL)
		return RAISE(PyExc_SDLError, "Cannot update an OPENGL display");

	/*determine type of argument we got*/
	if(PyTuple_Size(arg) == 0)
	{
		SDL_UpdateRect(screen, 0, 0, 0, 0);
		RETURN_NONE
	}
	else
	{
		obj = PyTuple_GET_ITEM(arg, 0);
		if(obj == Py_None)
		{
			gr = &temp;
		}
		else
		{
			gr = GameRect_FromObject(arg, &temp);
			if(!gr)
				PyErr_Clear();
			else if(gr != &temp)
			{
				memcpy(&temp, gr, sizeof(temp));
				gr = &temp;
			}
		}
	}

	if(gr)
	{
		SDL_Rect sdlr;
		if(screencroprect(gr, wide, high, &sdlr))
			SDL_UpdateRect(screen, sdlr.x, sdlr.y, sdlr.w, sdlr.h);
	}
	else
	{
		PyObject* seq;
		PyObject* r;
		int loop, num, count;
		SDL_Rect* rects;
		if(PyTuple_Size(arg) != 1)
				return RAISE(PyExc_ValueError, "update requires a rectstyle or sequence of recstyles");
		seq = PyTuple_GET_ITEM(arg, 0);
		if(!seq || !PySequence_Check(seq))
				return RAISE(PyExc_ValueError, "update requires a rectstyle or sequence of recstyles");

		num = PySequence_Length(seq);
		rects = PyMem_New(SDL_Rect, num);
		if(!rects) return NULL;
		count = 0;
		for(loop = 0; loop < num; ++loop)
		{
			SDL_Rect* cur_rect = (rects + count);

			/*get rect from the sequence*/
			r = PySequence_GetItem(seq, loop);
			if(r == Py_None)
			{
				Py_DECREF(r);
				continue;
			}
			gr = GameRect_FromObject(r, &temp);
			Py_XDECREF(r);
			if(!gr)
			{
				PyMem_Free((char*)rects);
				return RAISE(PyExc_ValueError, "update_rects requires a single list of rects");
			}

			if(gr->w < 1 && gr->h < 1)
				continue;

			/*bail out if rect not onscreen*/
			if(!screencroprect(gr, wide, high, cur_rect))
				continue;

			++count;
		}

		if(count)
			SDL_UpdateRects(screen, count, rects);
		PyMem_Free((char*)rects);
	}
	RETURN_NONE
}

    /*DOC*/ static char doc_set_palette[] =
    /*DOC*/    "pygame.display.set_palette([[r, g, b], ...]) -> None\n"
    /*DOC*/    "set the palette\n"
    /*DOC*/    "\n"
    /*DOC*/    "Displays with a HWPALETTE have two palettes. The display Surface\n"
    /*DOC*/    "palette and the visible 'onscreen' palette.\n"
    /*DOC*/    "\n"
    /*DOC*/    "This will change the video display's visible colormap. It does\n"
    /*DOC*/    "not effect the display Surface's base palette, only how it is\n"
    /*DOC*/    "displayed. Setting the palette for the display Surface will\n"
    /*DOC*/    "override this visible palette. Also passing no args will reset\n"
    /*DOC*/    "the display palette back to the Surface's palette.\n"
    /*DOC*/    "\n"
    /*DOC*/    "You can pass an incomplete list of RGB values, and\n"
    /*DOC*/    "this will only change the first colors in the palette.\n"
    /*DOC*/ ;

static PyObject* set_palette(PyObject* self, PyObject* args)
{
	SDL_Surface* surf;
	SDL_Palette* pal;
	SDL_Color* colors;
	PyObject* list, *item = NULL;
	int i, len;
	int r, g, b;

	VIDEO_INIT_CHECK();
	if(!PyArg_ParseTuple(args, "|O", &list))
		return NULL;
	surf = SDL_GetVideoSurface();
	if(!surf)
		return RAISE(PyExc_SDLError, "No display mode is set");
	pal = surf->format->palette;
	if(surf->format->BytesPerPixel != 1 || !pal)
		return RAISE(PyExc_SDLError, "Display mode is not colormapped");

	if(!list)
	{
		colors = pal->colors;
		len = pal->ncolors;
		SDL_SetPalette(surf, SDL_PHYSPAL, colors, 0, len);
		RETURN_NONE
	}


	if(!PySequence_Check(list))
		return RAISE(PyExc_ValueError, "Argument must be a sequence type");

	len = min(pal->ncolors, PySequence_Length(list));

	colors = (SDL_Color*)malloc(len * sizeof(SDL_Color));
	if(!colors)
		return NULL;

	for(i = 0; i < len; i++)
	{
		item = PySequence_GetItem(list, i);

		if(!PySequence_Check(item) || PySequence_Length(item) != 3)
		{
			Py_DECREF(item);
			free((char*)colors);
			return RAISE(PyExc_TypeError, "takes a sequence of sequence of RGB");
		}
		if(!IntFromObjIndex(item, 0, &r) || !IntFromObjIndex(item, 1, &g) || !IntFromObjIndex(item, 2, &b))
			return RAISE(PyExc_TypeError, "RGB sequence must contain numeric values");

		colors[i].r = (unsigned char)r;
		colors[i].g = (unsigned char)g;
		colors[i].b = (unsigned char)b;

		Py_DECREF(item);
	}

	SDL_SetPalette(surf, SDL_PHYSPAL, colors, 0, len);

	free((char*)colors);
	RETURN_NONE
}


    /*DOC*/ static char doc_set_gamma[] =
    /*DOC*/    "pygame.display.set_gamma(r, [g, b]) -> bool\n"
    /*DOC*/    "change the brightness of the display\n"
    /*DOC*/    "\n"
    /*DOC*/    "Sets the display gamma to the given amounts. If green and blue\n"
    /*DOC*/    "are ommitted, the red value will be used for all three colors.\n"
    /*DOC*/    "The color arguments are floating point values with 1.0 being the\n"
    /*DOC*/    "normal value. If you are using a display mode with a hardware\n"
    /*DOC*/    "palette, this will simply update the palette you are using. Not\n"
    /*DOC*/    "all hardware supports gamma. The return value will be true on\n"
    /*DOC*/    "success.\n"
    /*DOC*/ ;

static PyObject* set_gamma(PyObject* self, PyObject* arg)
{
	float r, g, b;
	int result;

	if(!PyArg_ParseTuple(arg, "f|ff", &r, &g, &b))
		return NULL;
	if(PyTuple_Size(arg) == 1)
		g = b = r;

	VIDEO_INIT_CHECK();

	result = SDL_SetGamma(r, g, b);
	return PyInt_FromLong(result == 0);
}

static int convert_to_uint16(PyObject* python_array, Uint16* c_uint16_array)
{
	int i;
	PyObject* item;

	if (!c_uint16_array) {
		RAISE(PyExc_RuntimeError, "Memory not allocated for c_uint16_array.");
		return 0;
	}

	if (!PySequence_Check(python_array))
	{
		RAISE(PyExc_TypeError, "Array must be sequence type");
		return 0;
	}

	if (PySequence_Size(python_array) != 256)
	{
		RAISE(PyExc_ValueError, "gamma ramp must be 256 elements long");
		return 0;
	}
	for (i=0; i<256; i++)
	{
		item = PySequence_GetItem(python_array, i);
		if(!PyInt_Check(item))
		{
			RAISE(PyExc_ValueError, "gamma ramp must contain integer elements");
			return 0;
		}
		c_uint16_array[i] = (Uint16)PyInt_AsLong(item);
	}
	return 1;
}

    /*DOC*/ static char doc_set_gamma_ramp[] =
    /*DOC*/    "pygame.display.set_gamma_ramp(r, g, b) -> bool\n"
    /*DOC*/    "advanced control over the display gamma ramps\n"
    /*DOC*/    "\n"
    /*DOC*/    "Pass three sequences with 256 elements. Each element must be a\n"
    /*DOC*/    "'16bit' unsigned integer value. This is from 0 to 65536.\n"
    /*DOC*/    "If you are using a display mode with a hardware\n"
    /*DOC*/    "palette, this will simply update the palette you are using.\n"
    /*DOC*/    "Not all hardware supports gamma. The return value will be\n"
    /*DOC*/    "true on success.\n";

static PyObject* set_gamma_ramp(PyObject* self, PyObject* arg)
{
 	Uint16 *r, *g, *b;

	int result;

	r = (Uint16 *)malloc(256 * sizeof(Uint16));
	if (!r)
	        return NULL;
	g = (Uint16 *)malloc(256 * sizeof(Uint16));
	if (!g)
	{
		free(r);
		return NULL;
	}
	b = (Uint16 *)malloc(256 * sizeof(Uint16));
	if (!b)
	{
		free(r);
		free(g);
		return NULL;
	}

	if(!PyArg_ParseTuple(arg, "O&O&O&",
			     convert_to_uint16, r,
			     convert_to_uint16, g,
			     convert_to_uint16, b))
	{
		free(r); free(g); free(b);
		return NULL;
	}

	VIDEO_INIT_CHECK();

	result = SDL_SetGammaRamp(r, g, b);

	free((char*)r);
	free((char*)g);
	free((char*)b);

	return PyInt_FromLong(result == 0);
}

    /*DOC*/ static char doc_set_caption[] =
    /*DOC*/    "pygame.display.set_caption(title, [icontitle]) -> None\n"
    /*DOC*/    "changes the title of the window\n"
    /*DOC*/    "\n"
    /*DOC*/    "If the display has a window title, this routine will change the\n"
    /*DOC*/    "name on the window. Some environments support a shorter icon\n"
    /*DOC*/    "title to be used when the display is minimized. If icontitle is\n"
    /*DOC*/    "omittied it will be the same as caption title.\n"
    /*DOC*/ ;

static PyObject* set_caption(PyObject* self, PyObject* arg)
{
	char* title, *icontitle=NULL;

	if(!PyArg_ParseTuple(arg, "s|s", &title, &icontitle))
		return NULL;

	if(!icontitle)
		icontitle = title;

	SDL_WM_SetCaption(title, icontitle);

	RETURN_NONE
}



    /*DOC*/ static char doc_get_caption[] =
    /*DOC*/    "pygame.display.get_caption() -> title, icontitle\n"
    /*DOC*/    "get the current title of the window\n"
    /*DOC*/    "\n"
    /*DOC*/    "Returns the current title and icontitle for the display window.\n"
    /*DOC*/ ;

static PyObject* get_caption(PyObject* self, PyObject* arg)
{
	char* title, *icontitle;

	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	SDL_WM_GetCaption(&title, &icontitle);

	if(title && *title)
		return Py_BuildValue("(ss)", title, icontitle);

	return Py_BuildValue("()");
}

static void do_set_icon(PyObject *surface)
{
	SDL_Surface* surf = PySurface_AsSurface(surface);
	surf = PySurface_AsSurface(surface);
	SDL_WM_SetIcon(surf, NULL);
	icon_was_set = 1;
}

    /*DOC*/ static char doc_set_icon[] =
    /*DOC*/    "pygame.display.set_icon(Surface) -> None\n"
    /*DOC*/    "changes the window manager icon for the window\n"
    /*DOC*/    "\n"
    /*DOC*/    "Sets the runtime icon that your system uses to decorate\n"
    /*DOC*/    "the program window. It is also used when the application\n"
    /*DOC*/    "is iconified and in the window frame.\n"
    /*DOC*/    "\n"
    /*DOC*/    "You likely want this to be a smaller image, a size that\n"
    /*DOC*/    "your system window manager will be able to deal with. It will\n"
    /*DOC*/    "also use the Surface colorkey if available.\n"
    /*DOC*/    "\n"
    /*DOC*/    "Some window managers on X11 don't allow you to change the \n"
    /*DOC*/    "icon after the window has been shown the first time.\n"
    /*DOC*/ ;

static PyObject* set_icon(PyObject* self, PyObject* arg)
{
	PyObject* surface;
	if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surface))
		return NULL;
	do_set_icon(surface);
	RETURN_NONE
}


    /*DOC*/ static char doc_iconify[] =
    /*DOC*/    "pygame.display.iconify() -> bool\n"
    /*DOC*/    "minimize the display window\n"
    /*DOC*/    "\n"
    /*DOC*/    "Tells the window manager (if available) to minimize the\n"
    /*DOC*/    "application. The call will return true if successful. You will\n"
    /*DOC*/    "receive an APPACTIVE event on the event queue when the window has\n"
    /*DOC*/    "been minimized.\n"
    /*DOC*/ ;

static PyObject* iconify(PyObject* self, PyObject* arg)
{
	int result;
	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	VIDEO_INIT_CHECK();

	result = SDL_WM_IconifyWindow();
	return PyInt_FromLong(result != 0);
}



    /*DOC*/ static char doc_toggle_fullscreen[] =
    /*DOC*/    "pygame.display.toggle_fullscreen() -> bool\n"
    /*DOC*/    "switch the display fullscreen mode\n"
    /*DOC*/    "\n"
    /*DOC*/    "Tells the window manager (if available) to switch between\n"
    /*DOC*/    "windowed and fullscreen mode. If available and successfull, will\n"
    /*DOC*/    "return true. Note, there is currently limited platform support\n"
    /*DOC*/    "for this call.\n"
    /*DOC*/ ;

static PyObject* toggle_fullscreen(PyObject* self, PyObject* arg)
{
	SDL_Surface* screen;
	int result;

	if(!PyArg_ParseTuple(arg, ""))
		return NULL;

	VIDEO_INIT_CHECK();

	screen = SDL_GetVideoSurface();
	if(!screen)
		return RAISE(PyExc_SDLError, SDL_GetError());

	result = SDL_WM_ToggleFullScreen(screen);
	return PyInt_FromLong(result != 0);
}



static PyMethodDef display_builtins[] =
{
	{ "__PYGAMEinit__", display_autoinit, 1, doc_init },
	{ "init", init, 1, doc_init },
	{ "quit", quit, 1, doc_quit },
	{ "get_init", get_init, 1, doc_get_init },
	{ "get_active", get_active, 1, doc_get_active },

/*	{ "set_driver", set_driver, 1, doc_set_driver },*/
	{ "get_driver", get_driver, 1, doc_get_driver },
	{ "get_wm_info", get_wm_info, 1, doc_get_wm_info },
	{ "Info", Info, 1, doc_Info },
	{ "get_surface", get_surface, 1, doc_get_surface },

	{ "set_mode", set_mode, 1, doc_set_mode },
	{ "mode_ok", mode_ok, 1, doc_mode_ok },
	{ "list_modes", list_modes, 1, doc_list_modes },

	{ "flip", flip, 1, doc_flip },
	{ "update", update, 1, doc_update },

	{ "set_palette", set_palette, 1, doc_set_palette },
	{ "set_gamma", set_gamma, 1, doc_set_gamma },
	{ "set_gamma_ramp", set_gamma_ramp, 1, doc_set_gamma_ramp },

	{ "set_caption", set_caption, 1, doc_set_caption },
	{ "get_caption", get_caption, 1, doc_get_caption },
	{ "set_icon", set_icon, 1, doc_set_icon },

	{ "iconify", iconify, 1, doc_iconify },
	{ "toggle_fullscreen", toggle_fullscreen, 1, doc_toggle_fullscreen },

	{ "gl_set_attribute", gl_set_attribute, 1, doc_gl_set_attribute },
	{ "gl_get_attribute", gl_get_attribute, 1, doc_gl_get_attribute },


	{ NULL, NULL }
};



    /*DOC*/ static char doc_pygame_display_MODULE[] =
    /*DOC*/    "Contains routines to work with the display. Mainly used for\n"
    /*DOC*/    "setting the display mode and updating the display surface.\n"
    /*DOC*/    "\n"
    /*DOC*/    "Pygame offers a fairly simple interface to the display buffer.\n"
    /*DOC*/    "The buffer is represented as an offscreen surface to which you\n"
    /*DOC*/    "can write directly. If you want the screen to show what you have\n"
    /*DOC*/    "written, the pygame.display.update() function will guarantee the\n"
    /*DOC*/    "the desired portion of the screen is updated. You can call\n"
    /*DOC*/    "pygame.display.flip() to update the entire screen, and also flip\n"
    /*DOC*/    "a hardware surface created with DOUBLEBUF.\n"
    /*DOC*/    "\n"
    /*DOC*/    "There are a number of ways to start the video display. The\n"
    /*DOC*/    "easiest way is to pick a common screen resolution and depth and\n"
    /*DOC*/    "just initialize the video, checking for exceptions. You will\n"
    /*DOC*/    "probably get what you want, but pygame may be emulating your\n"
    /*DOC*/    "requested mode and converting the display on update (this is not\n"
    /*DOC*/    "the fastest method). When calling pygame.display.set_mode() with\n"
    /*DOC*/    "the bit depth omitted or set to zero, pygame will determine the\n"
    /*DOC*/    "best video mode available and set to that. You can also query for\n"
    /*DOC*/    "more information on video modes with pygame.display.mode_ok(),\n"
    /*DOC*/    "pygame.display.list_modes(), and\n"
    /*DOC*/    "pygame.display.Info().\n"
    /*DOC*/    "\n"
    /*DOC*/    "When using a display depth other than what you graphic resources\n"
    /*DOC*/    "may be saved at, it is best to call the Surface.convert() routine\n"
    /*DOC*/    "to convert them to the same format as the display, this will\n"
    /*DOC*/    "result in the fastest blitting.\n"
    /*DOC*/    "\n"
    /*DOC*/    "Pygame currently supports any but depth >= 8 bits per pixl. 8bpp\n"
    /*DOC*/    "formats are considered to be 8-bit palettized modes, while 12,\n"
    /*DOC*/    "15, 16, 24, and 32 bits per pixel are considered 'packed pixel'\n"
    /*DOC*/    "modes, meaning each pixel contains the RGB color componsents\n"
    /*DOC*/    "packed into the bits of the pixel.\n"
    /*DOC*/    "\n"
    /*DOC*/    "After you have initialized your video mode, you can take the\n"
    /*DOC*/    "surface that was returned and write to it like any other Surface\n"
    /*DOC*/    "object. Be sure to call update() or flip() to keep what is on the\n"
    /*DOC*/    "screen synchronized with what is on the surface. Be sure not to call\n"
    /*DOC*/    "display routines that modify the display surface while it is locked.\n"
    /*DOC*/ ;

PYGAME_EXPORT
void initdisplay(void)
{
	PyObject *module, *dict, *apiobj;
	static void* c_api[PYGAMEAPI_DISPLAY_NUMSLOTS];

	PyType_Init(PyVidInfo_Type);


	/* create the module */
	module = Py_InitModule3("display", display_builtins, doc_pygame_display_MODULE);
	dict = PyModule_GetDict(module);
	self_module = module;

	/* export the c api */
	c_api[0] = &PyVidInfo_Type;
	c_api[1] = PyVidInfo_New;
	apiobj = PyCObject_FromVoidPtr(c_api, NULL);
	PyDict_SetItemString(dict, PYGAMEAPI_LOCAL_ENTRY, apiobj);
	Py_DECREF(apiobj);

	/*imported needed apis*/
	import_pygame_base();
	import_pygame_rect();
	import_pygame_surface();
}

