/* 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 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, "\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(); }