Commits

Anonymous committed 7926b46

Added first sdl.video.Surface.blit tests.
Removed SDL quitting hooks, which do not work well anyways.
Made base, sdl.base, sdl.cdrom and sdl.event mostly interpreter-safe for Python 3.x.

  • Participants
  • Parent commits aa2758e
  • Branches pgreloaded

Comments (0)

Files changed (20)

 * use copy.copy and copy.deepcopy for consistent object copies
 * Rewrite and fix up numpysurfarray and numpysndarray
 * Add prebuilt package for Win32 VC++ builds.
-* Refine quitting for SDL_QuitSubSystem wrapper.
 * Check display surface tracking for multiple calls to set_mode using
   different return variables.
 * Argument parsing must handle 64-bit conversions correctly.

File doc/capi/sdlbase.rst

 Functions
 ---------
 
-.. cfunction:: int RegisterQuitCallback (quit_func)
-
-  Registers a callback to be invoked before SDL's *SDL_Quit()* function
-  is raised to shutdown the SDL library. The quit function callback
-  hook, *quit_func* is defined as::
-  
-    void (*quit_func)(void)
-
-  As the functions also will upon exiting the Python interpreter instance,
-  no Python specific objects or calls must be used.
-
-  This will not check the argument for being *NULL*.
-
 .. cfunction:: int Uint8FromObj (PyObject *obj, Uint8 *val)
 
   Tries to convert the PyObject to a Uint8 and stores the result in

File src/base/basemod.c

 #include "pgbase.h"
 #include "base_doc.h"
 
-PyObject* PyExc_PyGameError;
+static int _base_traverse (PyObject *mod, visitproc visit, void *arg);
+static int _base_clear (PyObject *mod);
 
 static PyMethodDef _base_methods[] = {
     { NULL, NULL, 0, NULL }
     return 1;
 }
 
+static int
+_base_traverse (PyObject *mod, visitproc visit, void *arg)
+{
+    Py_VISIT (BASE_MOD_STATE(mod)->error);
+    return 0;
+}
+
+static int
+_base_clear (PyObject *mod)
+{
+    Py_CLEAR (BASE_MOD_STATE(mod)->error);
+    return 0;
+}
+
+#ifdef IS_PYTHON_3
+struct PyModuleDef _basemodule = {
+    PyModuleDef_HEAD_INIT,
+    "base",
+    DOC_BASE, 
+    sizeof (_BaseState),
+    _base_methods,
+    NULL,
+    _base_traverse,
+    _base_clear,
+    NULL
+};
+#else
+_BaseState _modstate;
+#endif
+
 #ifdef IS_PYTHON_3
 PyMODINIT_FUNC PyInit_base (void)
 #else
 #endif
 {
     static void* c_api[PYGAME_BASE_SLOTS];
-
-#ifdef IS_PYTHON_3
-    static struct PyModuleDef _basemodule = {
-        PyModuleDef_HEAD_INIT,
-        "base",
-        DOC_BASE, 
-        -1,
-        _base_methods,
-        NULL,
-        NULL,
-        NULL,
-        NULL
-    };
-#endif
-
+    _BaseState *state;
     PyObject *mod, *c_api_obj;
     
     /* Complete types */
 #endif
     if (!mod)
         MODINIT_RETURN(NULL);
+    state = BASE_MOD_STATE(mod);
+
+    /* Setup the pygame exeption */
+    state->error = PyErr_NewException ("base.Error", NULL, NULL);
+    if (!state->error)
+    {
+        Py_DECREF (mod);
+        MODINIT_RETURN(NULL);
+    }
+
+    Py_INCREF(state->error);
+    PyModule_AddObject (mod, "Error", state->error);
 
     PyModule_AddObject (mod, "Color", (PyObject *) &PyColor_Type);
     PyModule_AddObject (mod, "Rect", (PyObject *) &PyRect_Type);
     PyModule_AddObject (mod, "Surface", (PyObject *) &PySurface_Type);
     PyModule_AddObject (mod, "Font", (PyObject *) &PyFont_Type);
     
-    /* Setup the pygame exeption */
-    PyExc_PyGameError = PyErr_NewException ("base.Error", NULL, NULL);
-    Py_INCREF(PyExc_PyGameError);
-    PyModule_AddObject (mod, "Error", PyExc_PyGameError);
-    
     /* Export C API */
-    c_api[PYGAME_BASE_FIRSTSLOT] = PyExc_PyGameError;
+    c_api[PYGAME_BASE_FIRSTSLOT] = state->error;
     c_api[PYGAME_BASE_FIRSTSLOT+1] = DoubleFromObj;
     c_api[PYGAME_BASE_FIRSTSLOT+2] = IntFromObj;
     c_api[PYGAME_BASE_FIRSTSLOT+3] = UintFromObj;

File src/base/internals.h

 #define PYGAME_SURFACE_INTERNAL
 #define PYGAME_FONT_INTERNAL
 
-extern PyObject* PyExc_PyGameError;
+typedef struct {
+    PyObject* error;
+} _BaseState;
+
+#ifdef IS_PYTHON_3
+extern struct PyModuleDef _basemodule;
+#define BASE_MOD_STATE(mod) ((_BaseState*)PyModule_GetState(mod))
+#define BASE_STATE BASE_MOD_STATE(PyState_FindModule(&_basemodule))
+#else
+extern _BaseState _modstate;
+#define BASE_MOD_STATE(mod) (&_modstate)
+#define BASE_STATE BASE_MOD_STATE(NULL)
+#endif
+#define PyExc_PyGameError (BASE_STATE->error)
 
 int DoubleFromObj (PyObject* obj, double* val);
 int IntFromObj (PyObject* obj, int* val);

File src/freetype/ft_mod.c

     if (c_api_obj)
         PyModule_AddObject(mod, PYGAME_FREETYPE_ENTRY, c_api_obj);    
 
-/*    RegisterQuitCallback(_quit); */
-
     MODINIT_RETURN(mod);
 
 fail:

File src/pgcompat.h

 
 #define IsTextObj(x) (PyString_Check(x) || PyUnicode_Check(x))
 
+#define PyState_FindModule(obj) (NULL)
+
 #endif  /* PY_VERSION_HEX >= 0x03000000 */ 
 
 #endif /* _PYGAME_PYTHONCOMPAT_H_ */

File src/sdl/audiomod.c

 #include "pgsdl.h"
 #include "sdlaudio_doc.h"
 
-static void _quit (void);
-
 static PyObject* _sdl_audioinit (PyObject *self);
 static PyObject* _sdl_audiowasinit (PyObject *self);
 static PyObject* _sdl_audioquit (PyObject *self);
     { NULL, NULL, 0, NULL }
 };
 
-static void
-_quit (void)
-{
-    if (SDL_WasInit (SDL_INIT_AUDIO))
-        SDL_QuitSubSystem (SDL_INIT_AUDIO);
-}
-
 static PyObject*
 _sdl_audioinit (PyObject *self)
 {
 static PyObject*
 _sdl_audioquit (PyObject *self)
 {
-    _quit ();
+    if (SDL_WasInit (SDL_INIT_AUDIO))
+        SDL_QuitSubSystem (SDL_INIT_AUDIO);
     Py_RETURN_NONE;
 }
 
     if (import_pygame2_sdl_base () < 0)
         goto fail;
     
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

File src/sdl/cdrommod.c

 #include "pgsdl.h"
 #include "sdlcdrom_doc.h"
 
-#define MAX_CDROMS 32
-static SDL_CD *_cdrom_drives[MAX_CDROMS] = { NULL };
-
-static void _quit (void);
+static int _cdrom_clear (PyObject *mod);
 
 static PyObject* _sdl_cdinit (PyObject *self);
 static PyObject* _sdl_cdwasinit (PyObject *self);
     { NULL, NULL, 0, NULL }
 };
 
-static void
-_quit (void)
-{
-    int i;
-    for (i = 0; i < MAX_CDROMS; i++)
-    {
-        /* Close all open cdroms. */
-        if (_cdrom_drives[i])
-        {
-            SDL_CDClose (_cdrom_drives[i]);
-            _cdrom_drives[i] = NULL;
-        }
-    }
-
-    if (SDL_WasInit (SDL_INIT_CDROM))
-        SDL_QuitSubSystem (SDL_INIT_CDROM);
-}
-
 static PyObject*
 _sdl_cdinit (PyObject *self)
 {
 static PyObject*
 _sdl_cdquit (PyObject *self)
 {
-    _quit ();
+    int i;
+    for (i = 0; i < MAX_CDROMS; i++)
+    {
+        /* Close all open cdroms. */
+        if (SDLCDROM_MOD_STATE(self)->cdrom_drives[i])
+        {
+            SDL_CDClose (SDLCDROM_MOD_STATE(self)->cdrom_drives[i]);
+            SDLCDROM_MOD_STATE(self)->cdrom_drives[i] = NULL;
+        }
+    }
+
+    if (SDL_WasInit (SDL_INIT_CDROM))
+        SDL_QuitSubSystem (SDL_INIT_CDROM);
     Py_RETURN_NONE;
 }
 
     return Text_FromUTF8 (SDL_CDName (drive));
 }
 
+static int
+_cdrom_clear (PyObject *mod)
+{
+    int i;
+    for (i = 0; i < MAX_CDROMS; i++)
+    {
+        /* Close all open cdroms. */
+        if (SDLCDROM_MOD_STATE(mod)->cdrom_drives[i])
+        {
+            SDL_CDClose (SDLCDROM_MOD_STATE(mod)->cdrom_drives[i]);
+            SDLCDROM_MOD_STATE(mod)->cdrom_drives[i] = NULL;
+        }
+    }
+    return 0;
+}
+
 void
 cdrommod_add_drive (int _index, SDL_CD *cdrom)
 {
     if (_index < 0 || _index >= MAX_CDROMS)
         return;
-    _cdrom_drives[_index] = cdrom;
+    SDLCDROM_STATE->cdrom_drives[_index] = cdrom;
 }
 
 void
 {
     if (_index < 0 || _index >= MAX_CDROMS)
         return;
-    _cdrom_drives[_index] = NULL;
+    SDLCDROM_STATE->cdrom_drives[_index] = NULL;
 }
 
 SDL_CD*
 {
     if (_index < 0 || _index >= MAX_CDROMS)
         return NULL;
-    return _cdrom_drives[_index];
+    return SDLCDROM_STATE->cdrom_drives[_index];
 }
 
 #ifdef IS_PYTHON_3
+struct PyModuleDef _cdrommodule = {
+    PyModuleDef_HEAD_INIT,
+    "cdrom",
+    DOC_CDROM,
+    sizeof (_SDLCDromState),
+    _cdrom_methods,
+    NULL,
+    NULL,
+    _cdrom_clear,
+    NULL
+};
+#else
+_SDLCDromState _modstate;
+#endif
+
+
+#ifdef IS_PYTHON_3
 PyMODINIT_FUNC PyInit_cdrom (void)
 #else
 PyMODINIT_FUNC initcdrom (void)
 #endif
 {
+    int i;
     PyObject *mod = NULL;
     PyObject *c_api_obj;
+    _SDLCDromState *state;
+
     static void *c_api[PYGAME_SDLCDROM_SLOTS];
-
-#ifdef IS_PYTHON_3
-    static struct PyModuleDef _cdrommodule = {
-        PyModuleDef_HEAD_INIT, "cdrom", DOC_CDROM, -1, _cdrom_methods,
-        NULL, NULL, NULL, NULL
-    };
-#endif
     
     /* Complete types */
     if (PyType_Ready (&PyCD_Type) < 0)
     if (!mod)
         goto fail;
 
+    state = BASE_MOD_STATE(mod);
+    for (i = 0; i < MAX_CDROMS; i++)
+        state->cdrom_drives[i] = NULL;
+
     PyModule_AddObject (mod, "CD", (PyObject *) &PyCD_Type);
     PyModule_AddObject (mod, "CDTrack", (PyObject *) &PyCDTrack_Type);
 
     if (import_pygame2_sdl_base () < 0)
         goto fail;
     
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

File src/sdl/cdrommod.h

 extern PyTypeObject PyCD_Type;
 extern PyTypeObject PyCDTrack_Type;
 
+#define MAX_CDROMS 32
+typedef struct {
+    SDL_CD *cdrom_drives[MAX_CDROMS];
+} _SDLCDromState;
+
+#ifdef IS_PYTHON_3
+extern struct PyModuleDef _cdrommodule;
+#define SDLCDROM_MOD_STATE(mod) ((_SDLCDromState*)PyModule_GetState(mod))
+#define SDLCDROM_STATE SDLCDROM_MOD_STATE(PyState_FindModule(&_cdrommodule))
+#else
+extern _SDLCDromState _modstate;
+#define SDLCDROM_MOD_STATE(mod) (&_modstate)
+#define SDLCDROM_STATE SDLCDROM_MOD_STATE(NULL)
+#endif
+
 #define PyCD_Check(x) (PyObject_TypeCheck (x, &PyCD_Type))
 #define PyCDTrack_Check(x) (PyObject_TypeCheck (x, &PyCDTrack_Type))
 PyObject* PyCD_New (int index);

File src/sdl/eventmod.c

 #include "pgsdl.h"
 #include "sdlevent_doc.h"
 
-static PyObject *_filterhook = NULL;
+static int _event_traverse (PyObject *mod, visitproc visit, void *arg);
+static int _event_clear (PyObject *mod);
+
 static int _sdl_filter_events (const SDL_Event *event);
 
 static PyObject* _sdl_eventpump (PyObject *self);
     PyObject *result, *ev;
     int retval;
 
-    if (!_filterhook)
+    if (!SDLEVENT_STATE->filterhook)
         return 1;
     
     ev = PyEvent_New ((SDL_Event*)event);
     if (!ev)
         return 0;
 
-    result = PyObject_CallObject (_filterhook, ev);
+    result = PyObject_CallObject (SDLEVENT_STATE->filterhook, ev);
     Py_DECREF (ev);
 
     retval = PyObject_IsTrue (result);
     if (hook == Py_None)
     {
         /* Reset the filter hook */
-        Py_XDECREF (_filterhook);
+        Py_XDECREF (SDLEVENT_MOD_STATE(self)->filterhook);
         SDL_SetEventFilter (NULL);
-        _filterhook = NULL;
+        SDLEVENT_MOD_STATE(self)->filterhook = NULL;
         Py_RETURN_NONE;
     }
 
     }
 
     Py_INCREF (hook);
-    _filterhook = hook;
+    SDLEVENT_MOD_STATE(self)->filterhook = hook;
     SDL_SetEventFilter (_sdl_filter_events);
 
     Py_RETURN_NONE;
 {
     ASSERT_VIDEO_INIT(NULL);
 
-    if (!_filterhook)
+    if (!SDLEVENT_MOD_STATE(self)->filterhook)
         Py_RETURN_NONE;
-    Py_INCREF (_filterhook);
-    return _filterhook;
+    Py_INCREF (SDLEVENT_MOD_STATE(self)->filterhook);
+    return SDLEVENT_MOD_STATE(self)->filterhook;
 }
 
 static PyObject*
     return PyInt_FromLong (SDL_GetAppState ());
 }
 
+static int
+_event_traverse (PyObject *mod, visitproc visit, void *arg)
+{
+    Py_VISIT (SDLEVENT_MOD_STATE(mod)->filterhook);
+    return 0;
+}
+
+static int
+_event_clear (PyObject *mod)
+{
+    Py_CLEAR (SDLEVENT_MOD_STATE(mod)->filterhook);
+    return 0;
+}
+
+#ifdef IS_PYTHON_3
+struct PyModuleDef _module = {
+    PyModuleDef_HEAD_INIT,
+    "event",
+    DOC_EVENT,
+    -1,
+    _event_methods,
+    NULL,
+    _event_traverse,
+    _event_clear,
+    NULL
+};
+#else
+_SDLEventState _modstate;
+#endif
+
 #ifdef IS_PYTHON_3
 PyMODINIT_FUNC PyInit_event (void)
 #else
 {
     PyObject *mod = NULL;
     PyObject *c_api_obj;
+    _SDLEventState *state;
     static void *c_api[PYGAME_SDLEVENT_SLOTS];
 
-#ifdef IS_PYTHON_3
-    static struct PyModuleDef _module = {
-        PyModuleDef_HEAD_INIT, "event", DOC_EVENT, -1, _event_methods,
-        NULL, NULL, NULL, NULL
-    };
-#endif
-
     /* Complete types */
     if (PyType_Ready (&PyEvent_Type) < 0)
         goto fail;
 #endif
     if (!mod)
         goto fail;
+    state = SDLEVENT_MOD_STATE(mod);
+    state->filterhook = NULL;
 
     PyModule_AddObject (mod, "Event", (PyObject *) &PyEvent_Type);
 

File src/sdl/eventmod.h

 
 #define PYGAME_SDLEVENT_INTERNAL
 
+typedef struct {
+    PyObject *filterhook;
+} _SDLEventState;
+
+#ifdef IS_PYTHON_3
+extern struct PyModuleDef _eventmodule;
+#define SDLEVENT_MOD_STATE(mod) ((_SDLEventState*)PyModule_GetState(mod))
+#define SDLEVENT_STATE SDLEVENT_MOD_STATE(PyState_FindModule(&_eventmodule))
+#else
+extern _SDLEventState _modstate;
+#define SDLEVENT_MOD_STATE(mod) (&_modstate)
+#define SDLEVENT_STATE SDLEVENT_MOD_STATE(NULL)
+#endif
+
 extern PyTypeObject PyEvent_Type;
 
 #define PyEvent_Check(x) (PyObject_TypeCheck (x, &PyEvent_Type))

File src/sdl/joystickmod.c

     { NULL, NULL, 0, NULL }
 };
 
-static void
-_quit (void)
-{
-    int i;
-    for (i = 0; i < MAX_JOYSTICKS; i++)
-    {
-        /* Close all open joysticks. */
-        if (_joysticks[i])
-        {
-            SDL_JoystickClose (_joysticks[i]);
-            _joysticks[i] = NULL;
-        }
-    }
-
-    if (SDL_WasInit (SDL_INIT_JOYSTICK))
-        SDL_QuitSubSystem (SDL_INIT_JOYSTICK);
-}
-
 static PyObject*
 _sdl_joyinit (PyObject *self)
 {
 static PyObject*
 _sdl_joyquit (PyObject *self)
 {
-    _quit ();
+    int i;
+    for (i = 0; i < MAX_JOYSTICKS; i++)
+    {
+        /* Close all open joysticks. */
+        if (_joysticks[i])
+        {
+            SDL_JoystickClose (_joysticks[i]);
+            _joysticks[i] = NULL;
+        }
+    }
+
+    if (SDL_WasInit (SDL_INIT_JOYSTICK))
+        SDL_QuitSubSystem (SDL_INIT_JOYSTICK);
     Py_RETURN_NONE;
 }
 
     if (import_pygame2_sdl_base () < 0)
         goto fail;
 
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

File src/sdl/pgsdl.h

 extern "C" {
 #endif
 
-typedef void (*quit_func)(void);
-
 #define PYGAME_SDLBASE_FIRSTSLOT 0
-#define PYGAME_SDLBASE_NUMSLOTS 11
+#define PYGAME_SDLBASE_NUMSLOTS 10
 #ifndef PYGAME_SDLBASE_INTERNAL
-#define RegisterQuitCallback                                            \
-    (*(int(*)(quit_func))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT])
 #define Uint8FromObj                                                    \
-    (*(int(*)(PyObject*,Uint8*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+1])
+    (*(int(*)(PyObject*,Uint8*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT])
 #define Uint16FromObj                                                   \
-    (*(int(*)(PyObject*,Uint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+2])
+    (*(int(*)(PyObject*,Uint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+1])
 #define Sint16FromObj                                                   \
-    (*(int(*)(PyObject*,Sint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+3])
+    (*(int(*)(PyObject*,Sint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+2])
 #define Uint32FromObj                                                   \
-    (*(int(*)(PyObject*,Uint32*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+4])
+    (*(int(*)(PyObject*,Uint32*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+3])
 #define Uint8FromSeqIndex                                               \
-    (*(int(*)(PyObject*,Py_ssize_t,Uint8*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+5])
+    (*(int(*)(PyObject*,Py_ssize_t,Uint8*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+4])
 #define Uint16FromSeqIndex                                              \
-    (*(int(*)(PyObject*,Py_ssize_t,Uint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+6])
+    (*(int(*)(PyObject*,Py_ssize_t,Uint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+5])
 #define Sint16FromSeqIndex                                              \
-    (*(int(*)(PyObject*,Py_ssize_t,Sint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+7])
+    (*(int(*)(PyObject*,Py_ssize_t,Sint16*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+6])
 #define Uint32FromSeqIndex                                              \
-    (*(int(*)(PyObject*,Py_ssize_t,Uint32*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+8])
+    (*(int(*)(PyObject*,Py_ssize_t,Uint32*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+7])
 #define IsValidRect                                                     \
-    (*(int(*)(PyObject*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+9])
+    (*(int(*)(PyObject*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+8])
 #define SDLRect_FromRect                                                \
-    (*(int(*)(PyObject*,SDL_Rect*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+10])
+    (*(int(*)(PyObject*,SDL_Rect*))PyGameSDLBase_C_API[PYGAME_SDLBASE_FIRSTSLOT+9])
 #endif /* PYGAME_SDLBASE_INTERNAL */
 
 /**

File src/sdl/sdlmod.c

 #include "pgsdl.h"
 #include "sdlbase_doc.h"
 
-static int _quitcount = 0;
-static quit_func *_quitcallbacks = NULL;
-static int _register_quitcallback (quit_func func);
 static void _quit (void);
 static int _check_sdl (void);
 
     { NULL, NULL, 0, NULL },
 };
 
-static int
-_register_quitcallback (quit_func func)
-{
-    if (_quitcount == 0)
-    {
-        _quitcallbacks = malloc (sizeof (quit_func));
-        if (!_quitcallbacks)
-            return 0;
-    }
-    else
-    {
-        void *tmp = _quitcallbacks;
-        tmp = realloc (_quitcallbacks, sizeof (quit_func) * (_quitcount + 1));
-        if (!tmp)
-            return 0;
-        _quitcallbacks = tmp;
-    }
-    _quitcallbacks[_quitcount] = func;
-    _quitcount++;
-    return 1;
-}
-
 static void
 _quit (void)
 {
-    int i;
-    if (_quitcallbacks != NULL)
-        for (i = 0; i < _quitcount; i++)
-            (*_quitcallbacks[i])();
     SDL_Quit ();
 }
 
         DOC_BASE,
         -1,
         _sdl_methods,
-        NULL, NULL, NULL, NULL
+        NULL,
+        NULL,
+        NULL,
+        NULL
     };
     mod = PyModule_Create (&_sdlmodule);
 #else
         goto fail;
     
     /* Export C API */
-    c_api[PYGAME_SDLBASE_FIRSTSLOT] = _register_quitcallback;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+1] = Uint8FromObj;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+2] = Uint16FromObj;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+3] = Sint16FromObj;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+4] = Uint32FromObj;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+5] = Uint8FromSeqIndex;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+6] = Uint16FromSeqIndex;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+7] = Sint16FromSeqIndex;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+8] = Uint32FromSeqIndex;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+9] = IsValidRect;
-    c_api[PYGAME_SDLBASE_FIRSTSLOT+10] = SDLRect_FromRect;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT] = Uint8FromObj;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+1] = Uint16FromObj;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+2] = Sint16FromObj;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+3] = Uint32FromObj;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+4] = Uint8FromSeqIndex;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+5] = Uint16FromSeqIndex;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+6] = Sint16FromSeqIndex;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+7] = Uint32FromSeqIndex;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+8] = IsValidRect;
+    c_api[PYGAME_SDLBASE_FIRSTSLOT+9] = SDLRect_FromRect;
    
     c_api_obj = PyCObject_FromVoidPtr ((void *) c_api, NULL);
     if (c_api_obj)
         PyModule_AddObject (mod, PYGAME_SDLBASE_ENTRY, c_api_obj);    
 
     Py_AtExit (_quit);
+
     if (import_pygame2_base () < 0)
         goto fail;
 

File src/sdl/videomod.c

 #include "pgsdl.h"
 #include "sdlvideo_doc.h"
 
-static void _quit (void);
 static int _seq_to_uint16 (PyObject *seq, Uint16 *array, Py_ssize_t array_size);
 
 static PyObject* _sdl_videoinit (PyObject *self);
     { NULL, NULL, 0, NULL }
 };
 
-static void
-_quit (void)
-{
-    if (SDL_WasInit (SDL_INIT_VIDEO))
-        SDL_QuitSubSystem (SDL_INIT_VIDEO);
-}
-
 static int
 _seq_to_uint16 (PyObject *seq, Uint16 *array, Py_ssize_t array_size)
 {
 static PyObject*
 _sdl_videoquit (PyObject *self)
 {
-    _quit ();
+    if (SDL_WasInit (SDL_INIT_VIDEO))
+        SDL_QuitSubSystem (SDL_INIT_VIDEO);
     Py_RETURN_NONE;
 }
 
 
     if (import_pygame2_base () < 0)
         goto fail;
+    if (import_pygame2_sdl_base () < 0)
+        goto fail;
     if (import_pygame2_sdl_rwops () < 0)
         goto fail;
-    if (import_pygame2_sdl_base () < 0)
-        goto fail;
 
     /* Complete types */
     PySDLSurface_Type.tp_base = &PySurface_Type; 
     if (c_api_obj)
         PyModule_AddObject (mod, PYGAME_SDLVIDEO_ENTRY, c_api_obj);    
 
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN(mod);
 
 fail:

File src/sdlext/fasteventmod.c

         return (x);                                                     \
     }
 
-static void _quit (void);
-
 static PyObject* _sdl_feventinit (PyObject *self);
 static PyObject* _sdl_feventquit (PyObject *self);
 static PyObject* _sdl_feventpump (PyObject *self);
     { NULL, NULL, 0, NULL }
 };
 
-static void 
-_quit (void)
-{
-    if (!_fewasinit)
-        return;
-    FE_Quit ();
-    _fewasinit = 0;
-}
-
 static PyObject*
 _sdl_feventinit (PyObject *self)
 {
 static PyObject*
 _sdl_feventquit (PyObject *self)
 {
-    _quit ();
+    if (!_fewasinit)
+        return;
+    FE_Quit ();
+    _fewasinit = 0;
     Py_RETURN_NONE;
 }
 
         }
     }
 
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

File src/sdlext/scrapmod.c

 static PyObject *_scrapselection = NULL;
 static PyObject *_scrapclipboard = NULL;
 
-static void _quit (void);
-
 static PyObject* _scrap_init (PyObject* self);
 static PyObject* _scrap_quit (PyObject* self);
 static PyObject* _scrap_wasinit (PyObject* self);
     { NULL, NULL, 0, NULL }
 };
 
-static void
-_quit (void)
-{
-    if (pyg_scrap_was_init ())
-        pyg_scrap_quit ();
-}
-
 static PyObject*
 _scrap_init (PyObject* self)
 {
     _scrapclipboard = NULL;
     _scrapselection = NULL;
 
-    _quit ();
+    if (pyg_scrap_was_init ())
+        pyg_scrap_quit ();
     Py_RETURN_NONE;
 }
 
         goto fail;
     if (import_pygame2_sdl_video () < 0)
         goto fail;
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN (mod);
 fail:
     Py_XDECREF (mod);

File src/sdlmixer/mixermod.c

 #include "pgsdl.h"
 #include "sdlmixerbase_doc.h"
 
-static void _quit (void);
-
 static PyObject* _mixer_init (PyObject *self);
 static PyObject* _mixer_wasinit (PyObject *self);
 static PyObject* _mixer_quit (PyObject *self);
     { NULL, NULL, 0, NULL },
 };
 
-static void
-_quit (void)
-{
-    if (SDL_WasInit (SDL_INIT_AUDIO))
-        SDL_QuitSubSystem (SDL_INIT_AUDIO);
-}
-
 static PyObject*
 _mixer_init (PyObject *self)
 {
 static PyObject*
 _mixer_quit (PyObject *self)
 {
-    _quit ();
+    if (SDL_WasInit (SDL_INIT_AUDIO))
+        SDL_QuitSubSystem (SDL_INIT_AUDIO);
     Py_RETURN_NONE;
 }
 
         goto fail;
     if (import_pygame2_sdl_rwops () < 0)
         goto fail;
-    RegisterQuitCallback (_quit);
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

File src/sdlttf/ttfmod.c

 #include "pgsdl.h"
 #include "sdlttfbase_doc.h"
 
-
-static void _quit (void);
-
 static PyObject* _ttf_init (PyObject *self);
 static PyObject* _ttf_wasinit (PyObject *self);
 static PyObject* _ttf_quit (PyObject *self);
     { NULL, NULL, 0, NULL },
 };
 
-static void
-_quit (void)
-{
-    if (TTF_WasInit ())
-        TTF_Quit ();
-}
-
 static PyObject*
 _ttf_init (PyObject *self)
 {
 static PyObject*
 _ttf_quit (PyObject *self)
 {
-    _quit ();
+    if (TTF_WasInit ())
+        TTF_Quit ();
     Py_RETURN_NONE;
 }
 
         goto fail;
     if (import_pygame2_sdl_video () < 0)
         goto fail;
-    RegisterQuitCallback (_quit);
+
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

File test/sdl_video_surface_blit_test.py

-import sys
-try:
-    import pygame2.test.pgunittest as unittest
-except:
-    import pgunittest as unittest
-
-import pygame2
-from pygame2 import Color, Rect
-import pygame2.sdl.video as video
-import pygame2.sdl.constants as constants
-
-def cmpcolor (surface, color, area=None):
-    # Simple color comparision with clip area support
-    getat = surface.get_at
-    sx, sy = 0, 0
-    w, h = surface.size
-    if area:
-        sx, sy = area.x, area.y 
-        w, h = area.w, area.h
-
-    c = surface.format.map_rgba (color)
-    for x in range (sx, sx + w):
-        for y in range (sy, sy + h):
-            if getat (x, y) != c:
-                #print (x, y, getat (x, y), c, color)
-                return False
-    return True
-
-class SDLVideoSurfaceBlitTest (unittest.TestCase):
-    # __doc__ (as of 2009-05-15) for pygame2.sdl.video.Surface.blit:
-
-    # blit (srcsurface[, destrect, srcrect, blendargs]) -> Rect
-    # 
-    # Draws the passed source surface onto this surface.
-    # 
-    # Draws the passed source surface onto this surface. The dstrect
-    # and srcrect arguments are used for clipping the destionation
-    # area (on this surface) and source area (on the source
-    # surface). For the destination rectangle, the width and height
-    # are ignored, only the position is taken into account. For the
-    # source rectangle, all values, position as well as the size are
-    # used for clipping.
-    # 
-    # The optional blending arguments for the drawing operation perform
-    # certain specialised pixel manipulations. For those, pixels on the same
-    # position are evaluated and the result manipulated according to the
-    # argument.
-    # 
-    # +---------------------------+----------------------------------------+
-    # | Blend type                | Effect                                 |
-    # +===========================+========================================+
-    # | BLEND_RGB_ADD             | The sum of both pixel values will be   |
-    # |                           | set as resulting pixel.                |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGB_SUB             | The difference of both pixel values    |
-    # |                           | will be set as resulting pixel.        |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGB_MIN             | The minimum of each R, G and B channel |
-    # |                           | of the pixels will be set as result.   |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGB_MAX             | The maximum of each R, G and B channel |
-    # |                           | of the pixels will be set as result.   |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGB_MULT            | The result of a multiplication of both |
-    # |                           | pixel values will be used.             |
-    # +---------------------------+----------------------------------------+
-    # 
-    # The BLEND_RGB_*** flags do not take the alpha channel into
-    # account and thus are much faster for most blit operations
-    # without alpha transparency. Whenever alpha transparency has to
-    # be taken into account, the blending flags below should be
-    # used.
-    # 
-    # +---------------------------+----------------------------------------+
-    # | Blend type                | Effect                                 |
-    # +===========================+========================================+
-    # | BLEND_RGBA_ADD            | The sum of both pixel values will be   |
-    # |                           | set as resulting pixel.                |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGBA_SUB            | The difference of both pixel values    |
-    # |                           | will be set as resulting pixel.        |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGBA_MIN            | The minimum of each R, G, B and A      |
-    # |                           | channel of the pixels will be set as   |
-    # |                           | result.                                |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGBA_MAX            | The maximum of each R, G, B and A      |
-    # |                           | channel of the pixels will be set as   |
-    # |                           | result.                                |
-    # +---------------------------+----------------------------------------+
-    # | BLEND_RGBA_MULT           | The result of a multiplication of both |
-    # |                           | pixel values will be used.             |
-    # +---------------------------+----------------------------------------+    
-    
-    def test_simple_32bpp_blit (self):
-        # Simple 32bpp blit
-        video.init ()
-        sf1 = video.Surface (10, 10, 32)
-        sf2 = video.Surface ( 5,  5, 32)
-        
-        sf1.fill (Color (127, 0, 0))
-        sf2.fill (Color (0, 127, 0))
-        
-        # Solid, destructive blit.
-        sf1.blit (sf2)
-        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
-        video.quit ()
-    
-    def test_simple_24bpp_blit (self):
-        # Simple 24bpp blit
-        video.init ()
-        sf1 = video.Surface (10, 10, 24)
-        sf2 = video.Surface ( 5,  5, 24)
-        
-        sf1.fill (Color (127, 0, 0))
-        sf2.fill (Color (0, 127, 0))
-        
-        # Solid, destructive blit.
-        sf1.blit (sf2)
-        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
-        video.quit ()
-    
-    def todo_test_simple_16bpp_blit (self):
-        # Simple 16bpp blit
-        video.init ()
-        sf1 = video.Surface (10, 10, 16)
-        sf2 = video.Surface ( 5,  5, 16)
-        
-        sf1.fill (Color (127, 0, 0))
-        sf2.fill (Color (0, 127, 0))
-        
-        # Solid, destructive blit.
-        sf1.blit (sf2)
-        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
-        video.quit ()
-    
-    def test_simple_8bpp_blit (self):
-        # Simple 8bpp blit
-        video.init ()
-        sf1 = video.Surface (10, 10, 8)
-        sf2 = video.Surface ( 5,  5, 8)
-        
-        sf1.fill (Color (127, 0, 0))
-        sf2.fill (Color (0, 127, 0))
-        
-        # Solid, destructive blit.
-        sf1.blit (sf2)
-        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
-        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
-        video.quit ()
-
-if __name__ == "__main__":
-    unittest.main ()
+import sys
+try:
+    import pygame2.test.pgunittest as unittest
+except:
+    import pgunittest as unittest
+
+import pygame2
+from pygame2 import Color, Rect
+import pygame2.sdl.video as video
+import pygame2.sdl.constants as constants
+
+def cmpcolor (surface, color, area=None):
+    # Simple color comparision with clip area support
+    getat = surface.get_at
+    sx, sy = 0, 0
+    w, h = surface.size
+    if area:
+        sx, sy = area.x, area.y 
+        w, h = area.w, area.h
+
+    c = surface.format.map_rgba (color)
+    for x in range (sx, sx + w):
+        for y in range (sy, sy + h):
+            if getat (x, y) != c:
+                #print (x, y, getat (x, y), c, color)
+                return False
+    return True
+
+class SDLVideoSurfaceBlitTest (unittest.TestCase):
+    # __doc__ (as of 2009-05-15) for pygame2.sdl.video.Surface.blit:
+
+    # blit (srcsurface[, destrect, srcrect, blendargs]) -> Rect
+    # 
+    # Draws the passed source surface onto this surface.
+    # 
+    # Draws the passed source surface onto this surface. The dstrect
+    # and srcrect arguments are used for clipping the destionation
+    # area (on this surface) and source area (on the source
+    # surface). For the destination rectangle, the width and height
+    # are ignored, only the position is taken into account. For the
+    # source rectangle, all values, position as well as the size are
+    # used for clipping.
+    # 
+    # The optional blending arguments for the drawing operation perform
+    # certain specialised pixel manipulations. For those, pixels on the same
+    # position are evaluated and the result manipulated according to the
+    # argument.
+    # 
+    # +---------------------------+----------------------------------------+
+    # | Blend type                | Effect                                 |
+    # +===========================+========================================+
+    # | BLEND_RGB_ADD             | The sum of both pixel values will be   |
+    # |                           | set as resulting pixel.                |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGB_SUB             | The difference of both pixel values    |
+    # |                           | will be set as resulting pixel.        |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGB_MIN             | The minimum of each R, G and B channel |
+    # |                           | of the pixels will be set as result.   |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGB_MAX             | The maximum of each R, G and B channel |
+    # |                           | of the pixels will be set as result.   |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGB_MULT            | The result of a multiplication of both |
+    # |                           | pixel values will be used.             |
+    # +---------------------------+----------------------------------------+
+    # 
+    # The BLEND_RGB_*** flags do not take the alpha channel into
+    # account and thus are much faster for most blit operations
+    # without alpha transparency. Whenever alpha transparency has to
+    # be taken into account, the blending flags below should be
+    # used.
+    # 
+    # +---------------------------+----------------------------------------+
+    # | Blend type                | Effect                                 |
+    # +===========================+========================================+
+    # | BLEND_RGBA_ADD            | The sum of both pixel values will be   |
+    # |                           | set as resulting pixel.                |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGBA_SUB            | The difference of both pixel values    |
+    # |                           | will be set as resulting pixel.        |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGBA_MIN            | The minimum of each R, G, B and A      |
+    # |                           | channel of the pixels will be set as   |
+    # |                           | result.                                |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGBA_MAX            | The maximum of each R, G, B and A      |
+    # |                           | channel of the pixels will be set as   |
+    # |                           | result.                                |
+    # +---------------------------+----------------------------------------+
+    # | BLEND_RGBA_MULT           | The result of a multiplication of both |
+    # |                           | pixel values will be used.             |
+    # +---------------------------+----------------------------------------+    
+    
+    def test_simple_32bpp_blit (self):
+        # Simple 32bpp blit
+        video.init ()
+        sf1 = video.Surface (10, 10, 32)
+        sf2 = video.Surface ( 5,  5, 32)
+        
+        sf1.fill (Color (127, 0, 0))
+        sf2.fill (Color (0, 127, 0))
+        
+        # Solid, destructive blit.
+        sf1.blit (sf2)
+        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
+        video.quit ()
+    
+    def test_simple_24bpp_blit (self):
+        # Simple 24bpp blit
+        video.init ()
+        sf1 = video.Surface (10, 10, 24)
+        sf2 = video.Surface ( 5,  5, 24)
+        
+        sf1.fill (Color (127, 0, 0))
+        sf2.fill (Color (0, 127, 0))
+        
+        # Solid, destructive blit.
+        sf1.blit (sf2)
+        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
+        video.quit ()
+    
+    def todo_test_simple_16bpp_blit (self):
+        # Simple 16bpp blit
+        video.init ()
+        sf1 = video.Surface (10, 10, 16)
+        sf2 = video.Surface ( 5,  5, 16)
+        
+        sf1.fill (Color (127, 0, 0))
+        sf2.fill (Color (0, 127, 0))
+        
+        # Solid, destructive blit.
+        sf1.blit (sf2)
+        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
+        video.quit ()
+    
+    def test_simple_8bpp_blit (self):
+        # Simple 8bpp blit
+        video.init ()
+        sf1 = video.Surface (10, 10, 8)
+        sf2 = video.Surface ( 5,  5, 8)
+        
+        sf1.fill (Color (127, 0, 0))
+        sf2.fill (Color (0, 127, 0))
+        
+        # Solid, destructive blit.
+        sf1.blit (sf2)
+        self.assert_ (cmpcolor (sf1, Color (0, 127, 0), Rect (0, 0, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (0, 5, 5, 5)))
+        self.assert_ (cmpcolor (sf1, Color (127, 0, 0), Rect (5, 0, 5, 5)))
+        video.quit ()
+
+if __name__ == "__main__":
+    unittest.main ()