Lenard Lindstrom avatar Lenard Lindstrom committed 67f1c85

Updating other modules using Pygame's new buffer protocol C api: point save

The pygame.mixer.Sound type now uses PgObject_GetBuffer to access an
exporter's buffer. This means Sound will also accept objects with
a __array_interface__ property. The pygame.Surface type also has
been mostly rewritten to use the reworked PgBufproxy_New api function.
There are problems with surfarray locking, though.

Comments (0)

Files changed (7)

 /* Py_buffer internal data for an array struct */
 typedef struct view_internals_s {
     PyObject* cobj;
-    PyObject* obj;
     char format[4];      /* make 4 byte word sized */
     Py_ssize_t imem[1];
 } ViewInternals;
 static void PyGame_Video_AutoQuit (void);
 static int GetArrayInterface (PyObject*, PyObject**, PyArrayInterface**);
 static PyObject* ArrayStructAsDict (PyArrayInterface*);
-static PyObject* ViewAsDict (Py_buffer*);
-static PyObject* ViewAndFlagsAsArrayStruct (Py_buffer*, int);
-static int ViewIsByteSwapped (const Py_buffer*);
-static void ReleaseView (Py_buffer*);
-static int GetView (PyObject*, Py_buffer*);
-static int ArrayInterface_AsView (Py_buffer*, PyObject*);
-static int Dict_AsView (Py_buffer*, PyObject*);
+static PyObject* PgBuffer_AsArrayInterface (Py_buffer*);
+static PyObject* PgBuffer_AsArrayStruct (Py_buffer*);
+static int _buffer_is_byteswapped (Py_buffer*);
+static void PgBuffer_Release (Pg_buffer*);
+static int PgObject_GetBuffer (PyObject*, Pg_buffer*, int);
+static int ArrayInterface_AsView (Pg_buffer*, PyObject*, int);
+static int PgDict_AsBuffer (Pg_buffer*, PyObject*, int);
 static int _shape_arg_convert (PyObject *, Py_buffer*);
 static int _typestr_arg_convert (PyObject *, Py_buffer*);
 static int _data_arg_convert (PyObject*, Py_buffer*);
 static PyObject* view_get_shape_obj (Py_buffer*);
 static PyObject* view_get_strides_obj (Py_buffer*);
 static PyObject* view_get_data_obj (Py_buffer*);
-static char _as_arrayinter_typekind (const Py_buffer*);
-static char _as_arrayinter_byteorder (const Py_buffer*);
-static int _as_arrayinter_flags (const Py_buffer*, int);
-static CapsuleInterface* _new_capsuleinterface (const Py_buffer*, int);
+static char _as_arrayinter_typekind (Py_buffer*);
+static char _as_arrayinter_byteorder (Py_buffer*);
+static int _as_arrayinter_flags (Py_buffer*);
+static CapsuleInterface* _new_capsuleinterface (Py_buffer*);
 static void _free_capsuleinterface (void*);
 #if PY3
 static void _capsule_free_capsuleinterface (PyObject*);
 static PyObject* _strides_as_tuple (PyArrayInterface*);
 static PyObject* _data_as_tuple (PyArrayInterface*);
 static PyObject* get_array_interface (PyObject*, PyObject*);
+static void _release_buffer_array (Py_buffer*);
+static void _release_buffer_generic (Py_buffer*);
 
-static PyObject _None[1];  /* Unique object address; do not reference count */
+#if PY_VERSION_HEX < 0x02060000
+static int
+_IsFortranContiguous(Py_buffer *view)
+{
+    Py_ssize_t sd, dim;
+    int i;
+
+    if (view->ndim == 0) return 1;
+    if (view->strides == NULL) return (view->ndim == 1);
+
+    sd = view->itemsize;
+    if (view->ndim == 1) return (view->shape[0] == 1 ||
+                               sd == view->strides[0]);
+    for (i=0; i<view->ndim; i++) {
+        dim = view->shape[i];
+        if (dim == 0) return 1;
+        if (view->strides[i] != sd) return 0;
+        sd *= dim;
+    }
+    return 1;
+}
+
+static int
+_IsCContiguous(Py_buffer *view)
+{
+    Py_ssize_t sd, dim;
+    int i;
+
+    if (view->ndim == 0) return 1;
+    if (view->strides == NULL) return 1;
+
+    sd = view->itemsize;
+    if (view->ndim == 1) return (view->shape[0] == 1 ||
+                               sd == view->strides[0]);
+    for (i=view->ndim-1; i>=0; i--) {
+        dim = view->shape[i];
+        if (dim == 0) return 1;
+        if (view->strides[i] != sd) return 0;
+        sd *= dim;
+    }
+    return 1;
+}
+
+static int
+PyBuffer_IsContiguous(Py_buffer *view, char fort)
+{
+
+    if (view->suboffsets != NULL) return 0;
+
+    if (fort == 'C')
+        return _IsCContiguous(view);
+    else if (fort == 'F')
+        return _IsFortranContiguous(view);
+    else if (fort == 'A')
+        return (_IsCContiguous(view) || _IsFortranContiguous(view));
+    return 0;
+}
+#endif /* #if PY_VERSION_HEX < 0x02060000 */
 
 static int
 CheckSDLVersions (void) /*compare compiled to linked*/
 }
 
 static PyObject*
-ViewAsDict (Py_buffer* view)
+PgBuffer_AsArrayInterface (Py_buffer* view_p)
 {
     return Py_BuildValue ("{sisNsNsNsN}",
                           "version", (int)3,
-                          "typestr", view_get_typestr_obj (view),
-                          "shape", view_get_shape_obj (view),
-                          "strides", view_get_strides_obj (view),
-                          "data", view_get_data_obj (view));
+                          "typestr", view_get_typestr_obj (view_p),
+                          "shape", view_get_shape_obj (view_p),
+                          "strides", view_get_strides_obj (view_p),
+                          "data", view_get_data_obj (view_p));
 }
 
 static PyObject*
-ViewAndFlagsAsArrayStruct (Py_buffer* view, int flags)
+PgBuffer_AsArrayStruct (Py_buffer* view_p)
 {
-    void *cinter_p  = _new_capsuleinterface (view, flags);
+    void *cinter_p  = _new_capsuleinterface (view_p);
     PyObject *capsule;
 
     if (!cinter_p) {
     capsule = PyCObject_FromVoidPtr (cinter_p, _free_capsuleinterface);
 #endif
     if (!capsule) {
-        _free_capsuleinterface ((void *)cinter_p);
+        _free_capsuleinterface ((void*)cinter_p);
         return 0;
     }
     return capsule;
 }
 
 static CapsuleInterface*
-_new_capsuleinterface (const Py_buffer *view, int flags)
+_new_capsuleinterface (Py_buffer *view_p)
 {
-    int ndim = view->ndim;
+    int ndim = view_p->ndim;
     Py_ssize_t cinter_size;
     CapsuleInterface *cinter_p;
     int i;
     }
     cinter_p->inter.two = 2;
     cinter_p->inter.nd = ndim;
-    cinter_p->inter.typekind = _as_arrayinter_typekind (view);
-    cinter_p->inter.itemsize = view->itemsize;
-    cinter_p->inter.flags = _as_arrayinter_flags (view, flags);
-    if (view->shape) {
+    cinter_p->inter.typekind = _as_arrayinter_typekind (view_p);
+    cinter_p->inter.itemsize = view_p->itemsize;
+    cinter_p->inter.flags = _as_arrayinter_flags (view_p);
+    if (view_p->shape) {
         cinter_p->inter.shape = cinter_p->imem;
         for (i = 0; i < ndim; ++i) {
-            cinter_p->inter.shape[i] = (Py_intptr_t)view->shape[i];
+            cinter_p->inter.shape[i] = (Py_intptr_t)view_p->shape[i];
         }
     }
-    if (view->strides) {
+    if (view_p->strides) {
         cinter_p->inter.strides = cinter_p->imem + ndim;
         for (i = 0; i < ndim; ++i) {
-            cinter_p->inter.strides[i] = (Py_intptr_t)view->strides[i];
+            cinter_p->inter.strides[i] = (Py_intptr_t)view_p->strides[i];
         }
     }
-    cinter_p->inter.data = view->buf;
+    cinter_p->inter.data = view_p->buf;
     cinter_p->inter.descr = 0;
-    cinter_p->parent = view->obj;
+    cinter_p->parent = view_p->obj;
     Py_XINCREF (cinter_p->parent);
     return cinter_p;
 }
 #endif
 
 static int
-_as_arrayinter_flags (const Py_buffer* view, int flags)
+_as_arrayinter_flags (Py_buffer* view_p)
 {
     int inter_flags = PAI_ALIGNED; /* atomic int types always aligned */
 
-    if (!view->readonly) {
+    if (!view_p->readonly) {
         inter_flags |= PAI_WRITEABLE;
     }
-    inter_flags |= ViewIsByteSwapped (view) ? 0 : PAI_NOTSWAPPED;
-    if (flags & VIEW_CONTIGUOUS) {
+    inter_flags |= _buffer_is_byteswapped (view_p) ? 0 : PAI_NOTSWAPPED;
+    if (PyBuffer_IsContiguous (view_p, 'C')) {
         inter_flags |= PAI_CONTIGUOUS;
     }
-    if (flags & VIEW_F_ORDER) {
+    if (PyBuffer_IsContiguous (view_p, 'F')) {
         inter_flags |= PAI_FORTRAN;
     }
     return inter_flags;
 }
 
 static char
-_as_arrayinter_typekind (const Py_buffer* view)
+_as_arrayinter_typekind (Py_buffer* view)
 {
-    char type = view->format[0];
+    char type = view->format ? view->format[0] : 'B';
     char typekind;
 
     switch (type) {
     }
     switch (type) {
 
-    case 'c':
+    case 'b':
     case 'h':
     case 'i':
     case 'l':
     case 'q':
         typekind = 'i';
         break;
-    case 'b':
     case 'B':
     case 'H':
     case 'I':
     case 'L':
     case 'Q':
-    case 's':
         typekind = 'u';
         break;
+    case 'f':
+    case 'd':
+        typekind = 'f';
+        break;
     default:
         /* Unknown type */
         typekind = 's';
 }
 
 static char
-_as_arrayinter_byteorder (const Py_buffer* view)
+_as_arrayinter_byteorder (Py_buffer* view)
 {
-    char format_0 = view->format[0];
+    char format_0 = view->format ? view->format[0] : 'B';
     char byteorder;
 
-    switch (format_0) {
+    if (view->itemsize == 1) {
+        byteorder = '|';
+    }
+    else {
+        switch (format_0) {
 
-    case '<':
-    case '>':
-        byteorder = format_0;
-        break;
-    case '!':
-        byteorder = '>';
-        break;
-    case 'c':
-    case 's':
-    case 'p':
-    case 'b':
-    case 'B':
-        byteorder = '|';
-        break;
-    default:
-        byteorder = PAI_MY_ENDIAN;
+        case '<':
+        case '>':
+            byteorder = format_0;
+            break;
+        case '!':
+            byteorder = '>';
+            break;
+        case 'c':
+        case 's':
+        case 'p':
+        case 'b':
+        case 'B':
+            byteorder = '|';
+            break;
+        default:
+            byteorder = PAI_MY_ENDIAN;
+        }
     }
     return byteorder;
 }
 }
 
 static int
-GetView (PyObject* obj, Py_buffer* view)
+PgObject_GetBuffer (PyObject* obj, Pg_buffer* pg_view_p, int flags)
 {
+    Py_buffer* view_p = (Py_buffer*)pg_view_p;
     PyObject* cobj = 0;
     PyArrayInterface* inter_p = 0;
     ViewInternals* internal_p;
     char fchar;
     Py_ssize_t i;
 
-#if PY3
+    pg_view_p->release_buffer = _release_buffer_generic;
+    view_p->len = 0;
+
+#if PG_ENABLE_NEWBUF
     char *fchar_p;
 
     if (PyObject_CheckBuffer (obj)) {
-        if (PyObject_GetBuffer (obj, view, PyBUF_RECORDS)) {
+        if (PyObject_GetBuffer (obj, view_p, flags)) {
             return -1;
         }
-        fchar_p = view->format;
+        pg_view_p->release_buffer = PyBuffer_Release;
+        fchar_p = view_p->format;
         switch (*fchar_p) {
 
         case '@':
         case 'H':
         case 'i':
         case 'I':
+        case 'q':
+        case 'Q':
+        case 'f':
+        case 'd':
             ++fchar_p;
             break;
-        case 'q':
-        case 'Q':
-            PyErr_SetString (PyExc_ValueError,
-                              "Unsupported integer size of 8 bytes");
-            PyBuffer_Release (view);
-            return -1;
         case '0':
         case '1':
         case '2':
             /* A record: will raise exception later */
             break;
         default:
+            PgBuffer_Release (pg_view_p);
             PyErr_SetString (PyExc_ValueError,
-                              "Unsupported array element type");
-            PyBuffer_Release (view);
+                             "Unsupported array element type");
             return -1;
         }
         if (*fchar_p != '\0') {
+            PgBuffer_Release (pg_view_p);
             PyErr_SetString (PyExc_ValueError,
-                              "Arrays of records are unsupported");
-            PyBuffer_Release (view);
+                             "Arrays of records are unsupported");
             return -1;
         }
     }
     else
 #endif
     if (PyObject_HasAttrString (obj, "__array_struct__")) {
-        if (!GetArrayInterface (obj, &cobj, &inter_p)) {
+        if (GetArrayInterface (obj, &cobj, &inter_p)) {
             return -1;
         }
         sz = (sizeof (ViewInternals) + 
             case 4:
                 fchar = 'i';
                 break;
+            case 8:
+                fchar = 'q';
+                break;
             default:
                 PyErr_Format (PyExc_ValueError,
                               "Unsupported signed interger size %d",
             case 4:
                 fchar = 'I';
                 break;
+            case 8:
+                fchar = 'Q';
+                break;
             default:
                 PyErr_Format (PyExc_ValueError,
                               "Unsupported unsigned interger size %d",
                 return -1;
             }
             break;
+        case 'f':
+            switch (inter_p->itemsize) {
+
+            case 4:
+                fchar = 'f';
+                break;
+            case 8:
+                fchar = 'd';
+                break;
+            default:
+                PyErr_Format (PyExc_ValueError,
+                              "Unsupported float size %d",
+                              (int)inter_p->itemsize);
+                Py_DECREF (cobj);
+                return -1;
+            }
+            break;
         default:
             PyErr_Format (PyExc_ValueError,
                           "Unsupported value type '%c'",
             Py_DECREF (cobj);
             return -1;
         }
-        view->internal = internal_p;
-        view->format = internal_p->format;
-        view->shape = internal_p->imem;
-        view->strides = view->shape + view->ndim;
+        view_p->internal = internal_p;
+        view_p->format = internal_p->format;
+        view_p->shape = internal_p->imem;
+        view_p->strides = view_p->shape + inter_p->nd;
         internal_p->cobj = cobj;
-        internal_p->obj = obj;
+        view_p->buf = inter_p->data;
         Py_INCREF (obj);
-        view->obj = _None;
-        view->ndim = (Py_ssize_t)inter_p->nd;
-        view->itemsize = (Py_ssize_t)inter_p->itemsize;
-        view->readonly = inter_p->flags & PAI_WRITEABLE ? 0 : 1;
-        view->format[0] = (inter_p->flags & PAI_NOTSWAPPED ?
+        view_p->obj = obj;
+        view_p->ndim = (Py_ssize_t)inter_p->nd;
+        view_p->itemsize = (Py_ssize_t)inter_p->itemsize;
+        view_p->readonly = inter_p->flags & PAI_WRITEABLE ? 0 : 1;
+        view_p->format[0] = (inter_p->flags & PAI_NOTSWAPPED ?
                            PAI_MY_ENDIAN : PAI_OTHER_ENDIAN);
-        view->format[1] = fchar;
-        view->format[2] = '\0';
-        for (i = 0; i < view->ndim; ++i) {
-            view->shape[i] = (Py_ssize_t)inter_p->shape[i];
-            view->strides[i] = (Py_ssize_t)inter_p->strides[i];
+        view_p->format[1] = fchar;
+        view_p->format[2] = '\0';
+        for (i = 0; i < view_p->ndim; ++i) {
+            view_p->shape[i] = (Py_ssize_t)inter_p->shape[i];
+            view_p->strides[i] = (Py_ssize_t)inter_p->strides[i];
         }
-        view->suboffsets = 0;
+        view_p->suboffsets = 0;
+        view_p->len = view_p->itemsize;
+        for (i = 0; i < view_p->ndim; ++i) {
+            view_p->len *= view_p->shape[i];
+        }
+        pg_view_p->release_buffer = _release_buffer_array;
     }
     else if (PyObject_HasAttrString (obj, "__array_interface__")) {
-        if (ArrayInterface_AsView (view, obj)) {
+        if (ArrayInterface_AsView (pg_view_p, obj, flags)) {
             return -1;
         }
     }
                       Py_TYPE (obj)->tp_name);
         return -1;
     }
+    if (!view_p->len) {
+        view_p->len = view_p->itemsize;
+        for (i = 0; i < view_p->ndim; ++i) {
+            view_p->len *= view_p->shape[i];
+        }
+    }
     return 0;
 }
 
 static void
-ReleaseView (Py_buffer* view)
+PgBuffer_Release (Pg_buffer* pg_view_p)
 {
-    if (view->obj == _None && view->internal) {
-        Py_XDECREF (((ViewInternals*)view->internal)->cobj);
-        Py_XDECREF (((ViewInternals*)view->internal)->obj);
-        PyMem_Free (view->internal);
-        view->obj = 0;
-        view->internal = 0;
+    assert(pg_view_p && pg_view_p->release_buffer);
+    pg_view_p->release_buffer ((Py_buffer*)pg_view_p);
+}
+
+static void
+_release_buffer_generic (Py_buffer* view_p)
+{
+    if (view_p->obj) {
+        Py_XDECREF (view_p->obj);
+        view_p->obj = 0;
     }
-#if PY3
-    else {
-        PyBuffer_Release (view);
+}
+
+static void
+_release_buffer_array (Py_buffer* view_p)
+{
+    /* This is deliberately made safe for use on an unitialized *view_p */
+    if (view_p->internal) {
+        Py_XDECREF (((ViewInternals*)view_p->internal)->cobj);
+        PyMem_Free (view_p->internal);
+        view_p->internal = 0;
     }
-#endif
+    if (view_p->obj) {
+        Py_DECREF (view_p->obj);
+        view_p->obj = 0;
+    }
 }
 
 static int
-ViewIsByteSwapped (const Py_buffer* view)
+_buffer_is_byteswapped (Py_buffer* view)
 {
     if (view->format) {
         switch (view->format[0]) {
 }
 
 static int
-ArrayInterface_AsView (Py_buffer* view, PyObject* obj)
+ArrayInterface_AsView (Pg_buffer* pg_view_p, PyObject* obj, int flags)
 {
     PyObject* dict = PyObject_GetAttrString (obj, "__array_interface__");
 
         Py_DECREF (dict);
         return -1;
     }
-    if (Dict_AsView (view, dict)) {
+    if (PgDict_AsBuffer (pg_view_p, dict, flags)) {
         Py_DECREF (dict);
         return -1;
     }
-    ((ViewInternals*)view->internal)->obj = obj;
     Py_INCREF (obj);
+    ((Py_buffer*)pg_view_p)->obj = obj;
     Py_DECREF (dict);
     return 0;
 }
 
 static int
-Dict_AsView (Py_buffer* view, PyObject* dict)
+PgDict_AsBuffer (Pg_buffer* pg_view_p, PyObject* dict, int flags)
 {
+    Py_buffer* view_p = (Py_buffer*)pg_view_p;
     PyObject* pyshape = PyDict_GetItemString (dict, "shape");
     PyObject* pytypestr = PyDict_GetItemString (dict, "typestr");
     PyObject* pydata = PyDict_GetItemString (dict, "data");
     PyObject* pystrides = PyDict_GetItemString (dict, "strides");
     int i;
 
+#warning I really do not know what to do with the flags argument.
     if (!pyshape) {
         PyErr_SetString (PyExc_ValueError,
                          "required \"shape\" item is missing");
     }
     /* The item processing order is important:
        "strides" and "typestr" must follow "shape". */
-    view->internal = 0;
-    view->obj = _None;
-    if (_shape_arg_convert (pyshape, view)) {
-        ReleaseView (view);
+    view_p->internal = 0;
+    view_p->obj = 0;
+    pg_view_p->release_buffer = _release_buffer_array;
+    if (_shape_arg_convert (pyshape, view_p)) {
+        PgBuffer_Release (pg_view_p);
         return -1;
     }
-    if (_typestr_arg_convert (pytypestr, view)) {
-        ReleaseView (view);
+    if (_typestr_arg_convert (pytypestr, view_p)) {
+        PgBuffer_Release (pg_view_p);
         return -1;
     }
-    if (_data_arg_convert (pydata, view)) {
-        ReleaseView (view);
+    if (_data_arg_convert (pydata, view_p)) {
+        PgBuffer_Release (pg_view_p);
         return -1;
     }
-    if (pystrides && _strides_arg_convert (pystrides, view)) { /* cond. && */
-        ReleaseView (view);
+    if (_strides_arg_convert (pystrides, view_p)) {
+        PgBuffer_Release (pg_view_p);
         return -1;
     }
-    view->len = view->itemsize;
-    for (i = 0; i < view->ndim; ++i) {
-        view->len *= view->shape[i];
+    view_p->len = view_p->itemsize;
+    for (i = 0; i < view_p->ndim; ++i) {
+        view_p->len *= view_p->shape[i];
     }
     return 0;
 }
     Py_ssize_t* a;
     size_t sz;
 
+    view->obj = 0;
     view->internal = 0;
     if (!PyTuple_Check (o)) {
         PyErr_Format (PyExc_TypeError,
         return -1;
     }
     internal_p->cobj = 0;
-    internal_p->obj = 0;
     a = internal_p->imem;
     for (i = 0; i < n; ++i) {
         a[i] = PyInt_AsSsize_t (PyTuple_GET_ITEM (o, i));
     switch (typestr[1]) {
 
     case 'i':
-        is_signed = 1;
+        switch (typestr[2]) {
+
+        case '1':
+            type = 'b';
+            itemsize = 1;
+            break;
+        case '2':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'h';
+            itemsize = 2;
+            break;
+        case '4':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'i';
+            itemsize = 4;
+            break;
+        case '8':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'q';
+            itemsize = 8;
+            break;
+        default:
+            PyErr_Format (PyExc_ValueError,
+                          "unsupported size %c in typestr",
+                          typestr[2]);
+            Py_DECREF (s);
+            return -1;
+        }
         break;
     case 'u':
-        is_signed = 0;
+        switch (typestr[2]) {
+
+        case '1':
+            type = 'B';
+            itemsize = 1;
+            break;
+        case '2':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'H';
+            itemsize = 2;
+            break;
+        case '4':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'H';
+            itemsize = 4;
+            break;
+        case '8':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'Q';
+            itemsize = 8;
+            break;
+        default:
+            PyErr_Format (PyExc_ValueError,
+                          "unsupported size %c in typestr",
+                          typestr[2]);
+            Py_DECREF (s);
+            return -1;
+        }
+        break;
+    case 'f':
+        switch (typestr[2]) {
+
+        case '4':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'f';
+            itemsize = 4;
+            break;
+        case '8':
+            byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
+            type = 'd';
+            itemsize = 8;
+            break;
+        default:
+            PyErr_Format (PyExc_ValueError,
+                          "unsupported size %c in typestr",
+                          typestr[2]);
+            Py_DECREF (s);
+            return -1;
+        }
         break;
     default:
         PyErr_Format (PyExc_ValueError,
         Py_DECREF (s);
         return -1;
     }
-    switch (typestr[2]) {
-
-    case '1':
-        type = is_signed ? 'c' : 'B';
-        itemsize = 1;
-        break;
-    case '2':
-        byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
-        type = is_signed ? 'h' : 'H';
-        itemsize = 2;
-        break;
-    case '3':
-        type = 's';
-        itemsize = 3;
-        break;
-    case '4':
-        byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
-        type = is_signed ? 'i' : 'I';
-        itemsize = 4;
-        break;
-    case '6':
-        type = 's';
-        itemsize = 6;
-        break;
-    case '8':
-        byteorder = is_swapped ? PAI_OTHER_ENDIAN : '=';
-        type = is_signed ? 'q' : 'Q';
-        itemsize = 8;
-        break;
-    default:
-        PyErr_Format (PyExc_ValueError,
-                      "unsupported size %c in typestr",
-                      typestr[2]);
-        Py_DECREF (s);
-        return -1;
-    }
     if (byteorder != '\0') {
         view->format[0] = byteorder;
         view->format[1] = type;
     }
 
     /* export the c api */
-#if PYGAMEAPI_BASE_NUMSLOTS != 21
+#if PYGAMEAPI_BASE_NUMSLOTS != 20
 #warning export slot count mismatch
 #endif
     c_api[0] = PyExc_SDLError;
     c_api[11] = PyGame_Video_AutoInit;
     c_api[12] = RGBAFromObj;
     c_api[13] = ArrayStructAsDict;
-    c_api[14] = ViewAsDict;
+    c_api[14] = PgBuffer_AsArrayInterface;
     c_api[15] = GetArrayInterface;
-    c_api[16] = ViewAndFlagsAsArrayStruct;
-    c_api[17] = ViewIsByteSwapped;
-    c_api[18] = GetView;
-    c_api[19] = ReleaseView;
-    c_api[20] = Dict_AsView;
+    c_api[16] = PgBuffer_AsArrayStruct;
+    c_api[17] = PgObject_GetBuffer;
+    c_api[18] = PgBuffer_Release;
+    c_api[19] = PgDict_AsBuffer;
     apiobj = encapsulate_api (c_api, "base");
     if (apiobj == NULL) {
         Py_XDECREF (atexit_register);

src/bufferproxy.c

 typedef struct PgBufproxyObject_s {
     PyObject_HEAD
     PyObject *obj;                             /* Wrapped object              */
-    Py_buffer *view_p;                         /* For array interface export  */
-    PgBufproxy_CallbackGet get_buffer;         /* Py_buffer get callback      */
-    PgBufproxy_CallbackRelease release_buffer; /* Py_buffer release callback  */
+    Pg_buffer *view_p;                         /* For array interface export  */
+    pg_getbufferfunc get_buffer;               /* Pg_buffer get callback      */
     PyObject *dict;                            /* Allow arbitrary attributes  */
     PyObject *weakrefs;                        /* Reference cycles can happen */
 } PgBufproxyObject;
 
-typedef struct Py_buffer_d_s {
-    Py_buffer view;
+typedef struct Pg_buffer_d_s {
+    Pg_buffer view;
     PyObject *dict;
-} Py_buffer_d;
+} Pg_buffer_d;
 
 static int PgBufproxy_Trip(PyObject *);
-static void _free_view(Py_buffer *);
 
 /* $$ Transitional stuff */
 #warning Transitional stuff: must disappear!
                  "Not ready yet. (line %i in %s)", __LINE__, __FILE__); \
     return rcode
 
-
-#if PY_VERSION_HEX < 0x02060000
-static int
-_IsFortranContiguous(Py_buffer *view)
-{
-    Py_ssize_t sd, dim;
-    int i;
-
-    if (view->ndim == 0) return 1;
-    if (view->strides == NULL) return (view->ndim == 1);
-
-    sd = view->itemsize;
-    if (view->ndim == 1) return (view->shape[0] == 1 ||
-                               sd == view->strides[0]);
-    for (i=0; i<view->ndim; i++) {
-        dim = view->shape[i];
-        if (dim == 0) return 1;
-        if (view->strides[i] != sd) return 0;
-        sd *= dim;
-    }
-    return 1;
-}
+/* Use Dict_AsView alternative with flags arg. */
+static void _release_buffer_from_dict(Py_buffer *);
 
 static int
-_IsCContiguous(Py_buffer *view)
-{
-    Py_ssize_t sd, dim;
-    int i;
-
-    if (view->ndim == 0) return 1;
-    if (view->strides == NULL) return 1;
-
-    sd = view->itemsize;
-    if (view->ndim == 1) return (view->shape[0] == 1 ||
-                               sd == view->strides[0]);
-    for (i=view->ndim-1; i>=0; i--) {
-        dim = view->shape[i];
-        if (dim == 0) return 1;
-        if (view->strides[i] != sd) return 0;
-        sd *= dim;
-    }
-    return 1;
-}
-
-int
-PyBuffer_IsContiguous(Py_buffer *view, char fort)
-{
-
-    if (view->suboffsets != NULL) return 0;
-
-    if (fort == 'C')
-        return _IsCContiguous(view);
-    else if (fort == 'F')
-        return _IsFortranContiguous(view);
-    else if (fort == 'A')
-        return (_IsCContiguous(view) || _IsFortranContiguous(view));
-    return 0;
-}
-#endif /* #if PY_VERSION_HEX < 0x02060000 */
-
-/* Stub for base.c function */
-static int
-PgObject_GetBuffer(PyObject *obj, Py_buffer *view_p, int flags)
-{
-#if PY3
-    if (PyObject_CheckBuffer(obj)) {
-        return PyObject_GetBuffer(obj, view_p, flags);
-    }
-#endif
-    PyErr_SetString(PyExc_NotImplementedError, "TODO: implement in base.c");
-    return -1;
-}
-
-/* Stub for base.c function */
-static PyObject *
-PgBuffer_AsArrayStruct(Py_buffer *view_p) {
-    int flags = 0;
-
-    if (PyBuffer_IsContiguous(view_p, 'C')) {
-        flags |= VIEW_CONTIGUOUS | VIEW_C_ORDER;
-    }
-    if (PyBuffer_IsContiguous(view_p, 'F')) {
-        flags |= VIEW_CONTIGUOUS | VIEW_F_ORDER;
-    }
-    return ViewAndFlagsAsArrayStruct(view_p, flags);
-}
-
-/* Stub for base.c function */
-static PyObject *
-PgBuffer_AsArrayInterface(Py_buffer *view_p) {
-    return ViewAsDict(view_p);
-}
-
-/* Stub for base.c function */
-static void
-PgBuffer_Release(Py_buffer *view_p)
-{
-#if PY3
-    if (view_p && view_p->obj && PyObject_CheckBuffer(view_p->obj)) {
-        PyBuffer_Release(view_p);
-    }
-#else
-    printf("How did I get here? (line %i in %s)\n", __LINE__, __FILE__);
-#endif
-}
-
-/* Use Dict_AsView alternative with flags arg. */
-static int
-_get_buffer_from_dict(PyObject *dict, Py_buffer *view_p, int flags) {
+_get_buffer_from_dict(PyObject *dict, Pg_buffer *pg_view_p, int flags) {
     PyObject *obj;
-    Py_buffer_d *dict_view_p;
+    Py_buffer *view_p = (Py_buffer *)pg_view_p;
+    Pg_buffer *pg_dict_view_p;
+    Py_buffer *dict_view_p;
     PyObject *py_callback;
     PyObject *py_rval;
 
     assert(dict && PyDict_Check(dict));
     assert(view_p);
     view_p->obj = 0;
-    dict_view_p = PyMem_New(Py_buffer_d, 1);
-    if (!dict_view_p) {
+    pg_dict_view_p = PyMem_New(Pg_buffer, 1);
+    if (!pg_dict_view_p) {
         PyErr_NoMemory();
         return -1;
     }
-    if (Dict_AsView(&dict_view_p->view, dict)/* $$ Change here */) {
-        PyMem_Free(dict_view_p);
+    if (PgDict_AsBuffer(pg_dict_view_p, dict, flags)) {
+        PyMem_Free(pg_dict_view_p);
         return -1;
     }
+    dict_view_p = (Py_buffer *)pg_dict_view_p;
     obj = PyDict_GetItemString(dict, "parent");
     if (!obj) {
         obj = Py_None;
         py_rval = PyObject_CallFunctionObjArgs(py_callback, obj, NULL);
         Py_DECREF(py_callback);
         if (!py_rval) {
-            ReleaseView(&dict_view_p->view);
+            PgBuffer_Release(pg_dict_view_p);
             Py_DECREF(obj);
             return -1;
         }
         Py_DECREF(py_rval);
     }
     Py_INCREF(dict);
-    dict_view_p->dict = dict;
+    dict_view_p->obj = dict;
     view_p->obj = obj;
-    view_p->buf = dict_view_p->view.buf;
-    view_p->len = dict_view_p->view.len;
-    view_p->readonly = dict_view_p->view.readonly;
-    view_p->itemsize = dict_view_p->view.itemsize;
-    view_p->format = dict_view_p->view.format;
-    view_p->ndim = dict_view_p->view.ndim;
-    view_p->shape = dict_view_p->view.shape;
-    view_p->strides = dict_view_p->view.strides;
-    view_p->suboffsets = dict_view_p->view.suboffsets;
-    view_p->internal = dict_view_p;
+    view_p->buf = dict_view_p->buf;
+    view_p->len = dict_view_p->len;
+    view_p->readonly = dict_view_p->readonly;
+    view_p->itemsize = dict_view_p->itemsize;
+    view_p->format = dict_view_p->format;
+    view_p->ndim = dict_view_p->ndim;
+    view_p->shape = dict_view_p->shape;
+    view_p->strides = dict_view_p->strides;
+    view_p->suboffsets = dict_view_p->suboffsets;
+    view_p->internal = pg_dict_view_p;
+    pg_view_p->release_buffer = _release_buffer_from_dict;
     return 0;
 }
 
-/* This will need changes, including replacing ReleaseView call. */
+/* This will need changes */
 static void
 _release_buffer_from_dict(Py_buffer *view_p)
 {
-    Py_buffer_d *dict_view_p;
+    Py_buffer *dict_view_p;
     PyObject *dict;
     PyObject *obj;
     PyObject *py_callback;
 
     assert(view_p && view_p->internal);
     obj = view_p->obj;
-    dict_view_p = (Py_buffer_d *)view_p->internal;
-    dict = dict_view_p->dict;
+    dict_view_p = (Py_buffer *)view_p->internal;
+    dict = dict_view_p->obj;
     assert(dict && PyDict_Check(dict));
     py_callback = PyDict_GetItemString(dict, "after");
     if (py_callback) {
         }
         Py_DECREF(py_callback);
     }
-    ReleaseView(&dict_view_p->view);
-    Py_DECREF(dict);
+    PgBuffer_Release((Pg_buffer *)dict_view_p);
     PyMem_Free(dict_view_p);
     view_p->obj = 0;
     Py_DECREF(obj);
 }
 
-/* Backward compatible stub: replace me */
-static int
-mok_PgBufproxy_New(Py_buffer *view,
-                   int flags,
-                   PgBufproxy_CallbackBefore before,
-                   PgBufproxy_CallbackAfter after)
-{
-    NOTIMPLEMENTED(-1);
-}
-
 /* Stub functions */
 static PyObject *proxy_get_raw(PgBufproxyObject *, PyObject *);
 
 static PyObject *
 _proxy_subtype_new(PyTypeObject *type,
                    PyObject *obj,
-                   PgBufproxy_CallbackGet get_buffer,
-                   PgBufproxy_CallbackRelease release_buffer)
+                   pg_getbufferfunc get_buffer)
 {
     PgBufproxyObject *self = (PgBufproxyObject *)type->tp_alloc(type, 0);
 
     Py_XINCREF(obj);
     self->obj = obj;
     self->get_buffer = get_buffer;
-    self->release_buffer = release_buffer;
     return (PyObject *)self;
 }
 
 static Py_buffer *
 _proxy_get_view(PgBufproxyObject *proxy) {
-    Py_buffer *view_p = proxy->view_p;
+    Pg_buffer *view_p = proxy->view_p;
 
     if (!view_p) {
-        view_p = PyMem_New(Py_buffer, 1);
+        view_p = PyMem_New(Pg_buffer, 1);
         if (!view_p) {
             PyErr_NoMemory();
         }
             proxy->view_p = view_p;
         }
     }
-    return view_p;
-}
-
-static int
-_tuple_as_ints(PyObject *o,
-               const char *keyword,
-               Py_ssize_t **array,
-               int *length)
-{
-    /* Convert o as a C array of integers and return 1, otherwise
-     * raise a Python exception and return 0. keyword is the function
-     * argument name to use in the exception.
-     */
-    Py_ssize_t i, n;
-    Py_ssize_t *a;
-
-    if (!PyTuple_Check(o)) {
-        PyErr_Format(PyExc_TypeError,
-                     "Expected a tuple for argument %s: found %s",
-                     keyword, Py_TYPE(o)->tp_name);
-        return 0;
-    }
-    n = PyTuple_GET_SIZE(o);
-    a = PyMem_New(Py_intptr_t, n);
-    for (i = 0; i < n; ++i) {
-        a[i] = PyInt_AsSsize_t(PyTuple_GET_ITEM(o, i));
-        if (a[i] == -1 && PyErr_Occurred() /* conditional && */) {
-            PyMem_Free(a);
-            PyErr_Format(PyExc_TypeError,
-                         "%s tuple has a non-integer at position %d",
-                         keyword, (int)i);
-            return 0;
-        }
-    }
-    *array = a;
-    *length = n;
-    return 1;
-}
-
-static int
-_shape_arg_convert(PyObject *o, void *a)
-{
-    Py_buffer *view = (Py_buffer *)a;
-
-    if (!_tuple_as_ints(o, "shape", &view->shape, &view->ndim)) {
-        return 0;
-    }
-    return 1;
-}
-
-static int
-_typestr_arg_convert(PyObject *o, void *a)
-{
-    /* Due to incompatibilities between the array and new buffer interfaces,
-     * as well as significant unicode changes in Python 3.3, this will
-     * only handle integer types.
-     */
-    Py_buffer *view = (Py_buffer *)a;
-    char type;
-    int is_signed;
-    int is_swapped;
-    char byteorder = '\0';
-    int itemsize;
-    char *format;
-    PyObject *s;
-    const char *typestr;
-
-    format = (char *)&view->internal;
-    if (PyUnicode_Check(o)) {
-        s = PyUnicode_AsASCIIString(o);
-        if (!s) {
-            return 0;
-        }
-    }
-    else {
-        Py_INCREF(o);
-        s = o;
-    }
-    if (!Bytes_Check(s)) {
-        PyErr_Format(PyExc_TypeError, "Expected a string for typestr: got %s",
-                     Py_TYPE(s)->tp_name);
-        Py_DECREF(s);
-        return 0;
-    }
-    if (Bytes_GET_SIZE(s) != 3) {
-        PyErr_SetString(PyExc_TypeError, "Expected typestr to be length 3");
-        Py_DECREF(s);
-        return 0;
-    }
-    typestr = Bytes_AsString(s);
-    switch (typestr[0]) {
-
-    case BUFPROXY_MY_ENDIAN:
-        is_swapped = 0;
-        break;
-    case BUFPROXY_OTHER_ENDIAN:
-        is_swapped = 1;
-        break;
-    case '|':
-        is_swapped = 0;
-        break;
-    default:
-        PyErr_Format(PyExc_ValueError,
-                     "unknown byteorder character %c in typestr",
-                     typestr[0]);
-        Py_DECREF(s);
-        return 0;
-    }
-    switch (typestr[1]) {
-
-    case 'i':
-        is_signed = 1;
-        break;
-    case 'u':
-        is_signed = 0;
-        break;
-    default:
-        PyErr_Format(PyExc_ValueError,
-                     "unsupported typekind %c in typestr",
-                     typestr[1]);
-        Py_DECREF(s);
-        return 0;
-    }
-    switch (typestr[2]) {
-
-    case '1':
-        type = is_signed ? 'c' : 'B';
-        itemsize = 1;
-        break;
-    case '2':
-        byteorder = is_swapped ? BUFPROXY_OTHER_ENDIAN : '=';
-        type = is_signed ? 'h' : 'H';
-        itemsize = 2;
-        break;
-    case '3':
-        type = 's';
-        itemsize = 3;
-        break;
-    case '4':
-        byteorder = is_swapped ? BUFPROXY_OTHER_ENDIAN : '=';
-        type = is_signed ? 'i' : 'I';
-        itemsize = 4;
-        break;
-    case '6':
-        type = 's';
-        itemsize = 6;
-        break;
-    case '8':
-        byteorder = is_swapped ? BUFPROXY_OTHER_ENDIAN : '=';
-        type = is_signed ? 'q' : 'Q';
-        itemsize = 8;
-        break;
-    default:
-        PyErr_Format(PyExc_ValueError,
-                     "unsupported size %c in typestr",
-                     typestr[2]);
-        Py_DECREF(s);
-        return 0;
-    }
-    if (byteorder != '\0') {
-        format[0] = byteorder;
-        format[1] = type;
-        format[2] = '\0';
-    }
-    else {
-        format[0] = type;
-        format[1] = '\0';
-    }
-    view->format = format;
-    view->itemsize = itemsize;
-    return 1;
-}
-
-static int
-_strides_arg_convert(PyObject *o, void *a)
-{
-    /* Must be called after the array interface nd field has been filled in.
-     */
-    Py_buffer *view = (Py_buffer *)a;
-    int n = 0;
-
-    if (o == Py_None) {
-        return 1; /* no strides (optional) given */
-    }
-    if (!_tuple_as_ints(o, "strides", &view->strides, &n)) {
-        return 0;
-    }
-    if (n != view->ndim) {
-        PyErr_SetString(PyExc_TypeError,
-                        "strides and shape tuple lengths differ");
-        return 0;
-    }
-    return 1;
-}
-
-static int
-_data_arg_convert(PyObject *o, void *a)
-{
-    Py_buffer *view = (Py_buffer *)a;
-    Py_ssize_t address;
-    int readonly;
-
-    if (!PyTuple_Check(o)) {
-        PyErr_Format(PyExc_TypeError, "expected a tuple for data: got %s",
-                     Py_TYPE(o)->tp_name);
-        return 0;
-    }
-    if (PyTuple_GET_SIZE(o) != 2) {
-        PyErr_SetString(PyExc_TypeError, "expected a length 2 tuple for data");
-        return 0;
-    }
-    address = PyInt_AsSsize_t(PyTuple_GET_ITEM(o, 0));
-    if (address == -1 && PyErr_Occurred()) {
-        PyErr_Clear();
-        PyErr_Format(PyExc_TypeError,
-                     "expected an integer address for data item 0: got %s",
-                     Py_TYPE(PyTuple_GET_ITEM(o, 0))->tp_name);
-        return 0;
-    }
-    readonly = PyObject_IsTrue(PyTuple_GET_ITEM(o, 1));
-    if (readonly == -1) {
-        PyErr_Clear();
-        PyErr_Format(PyExc_TypeError,
-                     "expected a boolean flag for data item 1: got %s",
-                     Py_TYPE(PyTuple_GET_ITEM(o, 0))->tp_name);
-        return 0;
-    }
-    view->buf = (void *)address;
-    view->readonly = readonly;
-    return 1;
-}
-
-static int
-_parent_arg_convert(PyObject *o, void *a)
-{
-    Py_buffer *view = (Py_buffer *)a;
-
-    if (o != Py_None) {
-        view->obj = o;
-        Py_INCREF(o);
-    }
-    return 1;
+    return (Py_buffer *)view_p;
 }
 
 static void
-_free_view(Py_buffer *view)
-{
-    if (view->shape) {
-        PyMem_Free(view->shape);
-    }
-    if (view->strides) {
-        PyMem_Free(view->strides);
+_proxy_release_view(PgBufproxyObject *proxy) {
+    Pg_buffer *view_p = proxy->view_p;
+
+    if (view_p) {
+        proxy->view_p = 0;
+        PgBuffer_Release(view_p);
+        PyMem_Free(view_p);
     }
 }
 
 /**
  * Return a new PgBufproxyObject (Python level constructor).
  */
-static int
-_fill_view_from_array_interface(PyObject *dict, Py_buffer *view)
-{
-    PyObject *pyshape = PyDict_GetItemString(dict, "shape");
-    PyObject *pytypestr = PyDict_GetItemString(dict, "typestr");
-    PyObject *pydata = PyDict_GetItemString(dict, "data");
-    PyObject *pystrides = PyDict_GetItemString(dict, "strides");
-    int i;
-
-    if (!pyshape) {
-        PyErr_SetString(PyExc_ValueError,
-                        "required \"shape\" item is missing");
-        return -1;
-    }
-    if (!pytypestr) {
-        PyErr_SetString(PyExc_ValueError,
-                        "required \"typestr\" item is missing");
-        return -1;
-    }
-    if (!pydata) {
-        PyErr_SetString(PyExc_ValueError,
-                        "required \"data\" item is missing");
-        return -1;
-    }
-    /* The item processing order is important: "strides" must follow "shape". */
-    if (!_shape_arg_convert(pyshape, view)) {
-        return -1;
-    }
-    if (!_typestr_arg_convert(pytypestr, view)) {
-        return -1;
-    }
-    if (!_data_arg_convert(pydata, view)) {
-        return -1;
-    }
-    if (pystrides && !_strides_arg_convert(pystrides, view)) { /* cond. && */
-        return -1;
-    }
-    view->len = view->itemsize;
-    for (i = 0; i < view->ndim; ++i) {
-        view->len *= view->shape[i];
-    }
-    return 0;
-}
-
 static PyObject *
 proxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *obj = 0;
-    PgBufproxy_CallbackGet get_buffer = PgObject_GetBuffer;
-    PgBufproxy_CallbackRelease release_buffer = PgBuffer_Release;
+    pg_getbufferfunc get_buffer = PgObject_GetBuffer;
 
     if (!PyArg_ParseTuple(args, "O:Bufproxy", &obj)) {
         return 0;
     }
     if (PyDict_Check(obj)) {
         get_buffer = _get_buffer_from_dict;
-        release_buffer = _release_buffer_from_dict;
     }
-    return _proxy_subtype_new(type, obj, get_buffer, release_buffer);
+    return _proxy_subtype_new(type, obj, get_buffer);
 }
 
 /**
 proxy_dealloc(PgBufproxyObject *self)
 {
     PyObject_GC_UnTrack(self);
-    if (self->view_p) {
-        self->release_buffer(self->view_p);
-        PyMem_Free(self->view_p);
-    }
+    _proxy_release_view(self);
     Py_XDECREF(self->obj);
     Py_XDECREF(self->dict);
     if (self->weakrefs) {
     if (self->obj) {
         Py_VISIT(self->obj);
     }
-    if (self->view_p && self->view_p->obj) /* conditional && */ {
-        Py_VISIT(self->view_p->obj);
+    if (self->view_p && ((Py_buffer *)self->view_p)->obj) /* conditional && */ {
+        Py_VISIT(((Py_buffer *)self->view_p)->obj);
     }
     if (self->dict) {
         Py_VISIT(self->dict);
 }
 
 /**** Getter and setter access ****/
-#if PY3
-#define Capsule_New(p) PyCapsule_New((p), 0, 0);
-#else
-#define Capsule_New(p) PyCObject_FromVoidPtr((p), 0);
-#endif
-
 static PyObject *
 proxy_get_arraystruct(PgBufproxyObject *self, PyObject *closure)
 {
-    Py_buffer *view_p = self->view_p;
+    Py_buffer *view_p = _proxy_get_view(self);
     PyObject *capsule;
 
     if (!view_p) {
-        view_p = PyMem_New(Py_buffer, 1);
-        if (!view_p) {
-            return PyErr_NoMemory();
-        }
-        if (self->get_buffer(self->obj, view_p, PyBUF_RECORDS)) {
-            PyMem_Free(view_p);
-            return 0;
-        }
+        return 0;
     }
     capsule = PgBuffer_AsArrayStruct(view_p);
     if (!capsule) {
-        if (!self->view_p) {
-            self->release_buffer(view_p);
-            PyMem_Free(view_p);
-        }
-        return 0;
+        _proxy_release_view(self);
     }
-    self->view_p = view_p;
     return capsule;
 }
 
 static PyObject *
 proxy_get_arrayinterface(PgBufproxyObject *self, PyObject *closure)
 {
-    Py_buffer *view_p = self->view_p;
+    Py_buffer *view_p = _proxy_get_view(self);
     PyObject *dict;
 
     if (!view_p) {
-        view_p = PyMem_New(Py_buffer, 1);
-        if (!view_p) {
-            return PyErr_NoMemory();
-        }
-        if (self->get_buffer(self->obj, view_p, PyBUF_RECORDS)) {
-            PyMem_Free(view_p);
-            return 0;
-        }
+        return 0;
     }
     dict = PgBuffer_AsArrayInterface(view_p);
     if (!dict) {
-        if (!self->view_p) {
-            self->release_buffer(view_p);
-            PyMem_Free(view_p);
-        }
-        return 0;
+        _proxy_release_view(self);
     }
-    self->view_p = view_p;
     return dict;
 }
 
 proxy_get_parent(PgBufproxyObject *self, PyObject *closure)
 {
     Py_buffer *view_p = _proxy_get_view(self);
+    PyObject *obj;
 
     if (!view_p) {
         return 0;
     }
-    if (!view_p->obj) {
-        Py_RETURN_NONE;
-    }
-    Py_INCREF(view_p->obj);
-    return view_p->obj;
+    obj = view_p->obj ? view_p->obj : Py_None;
+    Py_INCREF(obj);
+    return obj;
 }
 
 static PyObject *
     {0, 0, 0, 0, 0}
 };
 
-#if PY3
+#if PG_ENABLE_NEWBUF
 static int
 proxy_getbuffer(PgBufproxyObject *self, Py_buffer *view_p, int flags)
 {
-    Py_buffer *obj_view_p = PyMem_New(Py_buffer, 1);
+    Pg_buffer *pg_obj_view_p = PyMem_New(Pg_buffer, 1);
+    Py_buffer *obj_view_p = (Py_buffer *)pg_obj_view_p;
 
     view_p->obj = 0;
-    if (!obj_view_p) {
+    if (!pg_obj_view_p) {
         PyErr_NoMemory();
         return -1;
     }
-    if (self->get_buffer(self->obj, view_p, flags)) {
-        PyMem_Free(obj_view_p);
+    if (self->get_buffer(self->obj, pg_obj_view_p, flags)) {
+        PyMem_Free(pg_obj_view_p);
         return -1;
     }
     Py_INCREF(self);
 static void
 proxy_releasebuffer(PgBufproxyObject *self, Py_buffer *view_p)
 {
-    self->release_buffer((Py_buffer *)view_p->internal);
+    PgBuffer_Release((Pg_buffer *)view_p->internal);
     PyMem_Free(view_p->internal);
 }
 
 #endif
 };
 
-#endif /* #if PY3 */
+#endif /* #if PG_ENABLE_NEWBUF */
 
 #define PROXY_TPFLAGS \
     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC)
 /**** Public C api ***/
 
 static PyObject *
-PgBufproxy_New(PyObject *obj,
-               PgBufproxy_CallbackGet get_buffer,
-               PgBufproxy_CallbackRelease release_buffer)
+PgBufproxy_New(PyObject *obj, pg_getbufferfunc get_buffer)
 {
     if (!get_buffer) {
         if (!obj) {
         }
         get_buffer = PgObject_GetBuffer;
     }
-    if (!release_buffer) {
-        if (!obj) {
-            PyErr_SetString(PyExc_ValueError,
-                            "One of arguments 'obj' or 'release_buffer' is "
-                            "required: both NULL instead");
-            return 0;
-        }
-        release_buffer = PgBuffer_Release;
-    }
-    return _proxy_subtype_new(&PgBufproxy_Type,
-                              obj,
-                              get_buffer,
-                              release_buffer);
+    return _proxy_subtype_new(&PgBufproxy_Type, obj, get_buffer);
 }
 
 static PyObject *
-PgBufproxy_GetParent(PyObject *bufproxy)
+PgBufproxy_GetParent(PyObject *obj)
 {
-    PyObject *parent =
-        (PyObject *)((PgBufproxyObject *) bufproxy)->obj;
-
-    if (!parent) {
-        parent = Py_None;
+    if (!PyObject_IsInstance (obj, (PyObject *)&PgBufproxy_Type)) {
+        PyErr_Format(PyExc_TypeError,
+                     "Expected a BufferProxy object: got %s instance instead",
+                     Py_TYPE(obj)->tp_name);
+        return 0;
     }
-    Py_INCREF(parent);
-    return parent;
+    return proxy_get_parent((PgBufproxyObject *)obj, 0);
 }
 
 static int
 PgBufproxy_Trip(PyObject *obj)
 {
-    NOTIMPLEMENTED(-1);
+    if (!PyObject_IsInstance (obj, (PyObject *)&PgBufproxy_Type)) {
+        PyErr_Format(PyExc_TypeError,
+                     "Expected a BufferProxy object: got %s instance instead",
+                     Py_TYPE(obj)->tp_name);
+        return -1;
+    }
+    return _proxy_get_view((PgBufproxyObject *)obj) ? 0 : -1;
 }
 
 /*DOC*/ static char bufferproxy_doc[] =
 #error export slot count mismatch
 #endif
     c_api[0] = &PgBufproxy_Type;
-/*    c_api[1] = PgBufproxy_New; */
-    c_api[1] = mok_PgBufproxy_New; /* $$ **Temporary** */
+    c_api[1] = PgBufproxy_New;
     c_api[2] = PgBufproxy_GetParent;
     c_api[3] = PgBufproxy_Trip;
     apiobj = encapsulate_api(c_api, PROXY_MODNAME);
     return size;
 }
 
-static PG_sample_format_t
-_format_inter_to_audio(PyArrayInterface *inter)
-{
-    PG_sample_format_t format = 0;
-    int itemsize = inter->itemsize;
-
-    switch (inter->typekind) {
-        case 'u':
-        break;
-
-        case 'i':
-        format |= PG_SAMPLE_SIGNED;
-        break;
-
-        default:
-        PyErr_Format(PyExc_ValueError,
-                     "Array has unsupported item format '%c'",
-                     (int)inter->typekind);
-        return 0;
-    }
-    if (itemsize <= 0 || itemsize > 0xFFFFl) {
-        PyErr_Format(PyExc_ValueError,
-                     "Array has unsupported integer size %d", itemsize);
-        return 0;
-    }
-    format += itemsize;
-    format |= inter->flags & PAI_NOTSWAPPED ? PG_SAMPLE_NATIVE_ENDIAN : 0;
-    return format;
-}
-
 #if HAVE_NEW_BUFPROTO
 static PG_sample_format_t
 _format_view_to_audio(Py_buffer *view)
         format += native_size ? sizeof(unsigned short int) : 2;
         break;
 
+    case 'i':
+        format |= PG_SAMPLE_SIGNED;
+        format += native_size ? sizeof(short int) : 4;
+        break;
+
+    case 'I':
+        format += native_size ? sizeof(unsigned short int) : 4;
+        break;
+
     case 'l':
         format |= PG_SAMPLE_SIGNED;
         format += native_size ? sizeof(long int) : 4;
 {
     Py_buffer view;
     PyObject* cobj;
-    int view_flags = VIEW_CONTIGUOUS | VIEW_C_ORDER;
 
-    if (snd_getbuffer (self, &view, PyBUF_STRIDES)) {
+    if (snd_getbuffer (self, &view, PyBUF_RECORDS)) {
         return 0;
     }
-    if (view.ndim == 1) {
-        view_flags |= VIEW_F_ORDER;
-    }
-    cobj = ViewAndFlagsAsArrayStruct (&view, view_flags);
+    cobj = PgBuffer_AsArrayStruct (&view);
     snd_releasebuffer (view.obj, &view);
     Py_XDECREF (view.obj);
     return cobj;
     }
 #endif
 
-#if HAVE_NEW_BUFPROTO
-    if (array != NULL && /* conditional and */
-        PyObject_CheckBuffer(array)) {
-        Py_buffer view;
+    if (array != NULL) {
+        Pg_buffer pg_view;
         PG_sample_format_t view_format;
         int rcode;
 
-        view.itemsize = 0;
-        view.obj = 0;
-        if (PyObject_GetBuffer(array, &view, PyBUF_FORMAT | PyBUF_ND)) {
+        pg_view.view.itemsize = 0;
+        pg_view.view.obj = 0;
+        if (PgObject_GetBuffer(array, &pg_view, PyBUF_FORMAT | PyBUF_ND)) {
             return -1;
         }
-        view_format = _format_view_to_audio(&view);
+        view_format = _format_view_to_audio((Py_buffer *)&pg_view);
         if (!view_format) {
-            PyBuffer_Release(&view);
+            PgBuffer_Release(&pg_view);
             return -1;
         }
-        rcode = _chunk_from_array(view.buf, view_format, view.ndim,
-                                  view.shape, view.strides,
+        rcode = _chunk_from_array(pg_view.view.buf,
+                                  view_format,
+                                  pg_view.view.ndim,
+                                  pg_view.view.shape,
+                                  pg_view.view.strides,
                                   &chunk, &mem);
-        PyBuffer_Release(&view);
-        if (rcode) {
-            return -1;
-        }
-        ((PySoundObject *)self)->mem = mem;
-    }
-#endif
-
-    if (chunk == NULL && array != NULL) {
-        PyArrayInterface *inter = 0;
-        PyObject *cobj = 0;
-        PG_sample_format_t array_format;
-        int rcode;
-
-        if (GetArrayInterface(array, &cobj, &inter)) {
-            return -1;
-        }
-        if (!(inter->flags & PAI_CONTIGUOUS)) {
-            RAISE(PyExc_ValueError,
-                  "Array is discontiguous");
-            Py_DECREF(cobj);
-            return -1;
-        }
-        if (inter->nd > 1 && inter->flags & PAI_FORTRAN) {
-            RAISE(PyExc_ValueError, "Array is channel first");
-            Py_DECREF(cobj);
-            return -1;
-        }
-        array_format = _format_inter_to_audio(inter);
-        if (!array_format) {
-            Py_DECREF(cobj);
-            return -1;
-        }
-        rcode = _chunk_from_array(inter->data, array_format, inter->nd,
-                                  inter->shape, inter->strides,
-                                  &chunk, &mem);
-        Py_DECREF(cobj);
+        PgBuffer_Release(&pg_view);
         if (rcode) {
             return -1;
         }

src/pgbufferproxy.h

  */
 #if !defined(PG_BUFPROXY_HEADER)
 
-/* $$ Transitional stuff: to be removed */
-#warning Transitional stuff: Remove me!
-typedef int (*PgBufproxy_CallbackBefore)(PyObject *);
-typedef void (*PgBufproxy_CallbackAfter)(PyObject *);
-/* end transitional stuff */
-
-typedef int (*PgBufproxy_CallbackGet)(PyObject *, Py_buffer *, int);
-typedef void (*PgBufproxy_CallbackRelease)(Py_buffer *);
+typedef int (*pg_getbufferfunc)(PyObject *, struct pg_bufferinfo_s *, int);
 
 #define PYGAMEAPI_BUFPROXY_NUMSLOTS 4
 #define PYGAMEAPI_BUFPROXY_FIRSTSLOT 0
 #if !(defined(PYGAMEAPI_BUFPROXY_INTERNAL) || defined(NO_PYGAME_C_API))
 static void *PgBUFPROXY_C_API[PYGAMEAPI_BUFPROXY_NUMSLOTS];
 
-typedef PyObject *(*_pgbufproxy_new_t)(Py_buffer *,
-                                   int,
-                                   PgBufproxy_CallbackBefore,
-                                   PgBufproxy_CallbackAfter);
+typedef PyObject *(*_pgbufproxy_new_t)(PyObject *, pg_getbufferfunc);
 typedef PyObject *(*_pgbufproxy_get_obj_t)(PyObject *);
 typedef int (*_pgbufproxy_trip_t)(PyObject *);
 
 #define PyInt_FromSsizt_t PyInt_FromLong
 #endif
 
-/* Python 2.5 and earlier (PEP 3118) Py_buffer */
-#if PY_VERSION_HEX < 0x02060000
-typedef struct bufferinfo {
-    void *buf;
-    PyObject *obj;
-    Py_ssize_t len;
-    Py_ssize_t itemsize;
-    int readonly;
-    int ndim;
-    char *format;
-    Py_ssize_t *shape;
-    Py_ssize_t *strides;
-    Py_ssize_t *suboffsets;
-    void *internal;
-} Py_buffer;
-
-/* Flags for getting buffers */
-#define PyBUF_SIMPLE 0
-#define PyBUF_WRITABLE 0x0001
-/*  we used to include an E, backwards compatible alias  */
-#define PyBUF_WRITEABLE PyBUF_WRITABLE
-#define PyBUF_FORMAT 0x0004
-#define PyBUF_ND 0x0008
-#define PyBUF_STRIDES (0x0010 | PyBUF_ND)
-#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
-#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
-#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
-#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
-
-#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE)
-#define PyBUF_CONTIG_RO (PyBUF_ND)
-
-#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE)
-#define PyBUF_STRIDED_RO (PyBUF_STRIDES)
-
-#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT)
-#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT)
-
-#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
-#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT)
-
-
-#define PyBUF_READ  0x100
-#define PyBUF_WRITE 0x200
-#define PyBUF_SHADOW 0x400
-#endif /* #if PY_VERSION_HEX < 0x02060000 */
+/* Support new buffer protocol? */
+#if PY3
+#define PG_ENABLE_NEWBUF 1
+#else
+#define PG_ENABLE_NEWBUF 0
+#endif
 
 #endif /* #if !defined(PGCOMPAT_H) */
 #define PyCapsule_CheckExact(obj) PyCObject_Check(obj)
 #endif
 
+/* Pygame uses Py_buffer (PEP 3118) to exchange array information internally;
+ * define here as needed.
+ */
+#if !defined(PyBUF_SIMPLE)
+typedef struct bufferinfo {
+    void *buf;
+    PyObject *obj;
+    Py_ssize_t len;
+    Py_ssize_t itemsize;
+    int readonly;
+    int ndim;
+    char *format;
+    Py_ssize_t *shape;
+    Py_ssize_t *strides;
+    Py_ssize_t *suboffsets;
+    void *internal;
+} Py_buffer;
+
+/* Flags for getting buffers */
+#define PyBUF_SIMPLE 0
+#define PyBUF_WRITABLE 0x0001
+/*  we used to include an E, backwards compatible alias  */
+#define PyBUF_WRITEABLE PyBUF_WRITABLE
+#define PyBUF_FORMAT 0x0004
+#define PyBUF_ND 0x0008
+#define PyBUF_STRIDES (0x0010 | PyBUF_ND)
+#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
+#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
+#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
+#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+
+#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE)
+#define PyBUF_CONTIG_RO (PyBUF_ND)
+
+#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE)
+#define PyBUF_STRIDED_RO (PyBUF_STRIDES)
+
+#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT)
+#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT)
+
+#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
+#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT)
+
+
+#define PyBUF_READ  0x100
+#define PyBUF_WRITE 0x200
+#define PyBUF_SHADOW 0x400
+#endif /* #if !defined(PyBUF_SIMPLE) */
+
+/* Array information exchange struct C type; inherits from Py_buffer */
+
+struct pg_bufferinfo_s;
+typedef void (*pg_releasebufferfunc)(struct bufferinfo *);
+
+typedef struct pg_bufferinfo_s {
+    Py_buffer view;
+    pg_releasebufferfunc release_buffer;
+} Pg_buffer;
+
 // No signal()
 #if defined(__SYMBIAN32__) && defined(HAVE_SIGNAL_H)
 #undef HAVE_SIGNAL_H
 #define VIEW_F_ORDER       4
 
 #define PYGAMEAPI_BASE_FIRSTSLOT 0
-#define PYGAMEAPI_BASE_NUMSLOTS 21
+#define PYGAMEAPI_BASE_NUMSLOTS 20
 #ifndef PYGAMEAPI_BASE_INTERNAL
 #define PyExc_SDLError ((PyObject*)PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT])
 
     (*(PyObject*(*)(PyArrayInterface*))                                 \
      PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 13])
 
-#define ViewAsDict                                                      \
+#define PgBuffer_AsArrayInterface                                       \
     (*(PyObject*(*)(Py_buffer*)) PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 14])
 
 #define GetArrayInterface                                               \
     (*(int(*)(PyObject*, PyObject**, PyArrayInterface**))               \
      PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 15])
 
-#define ViewAndFlagsAsArrayStruct                                       \
-    (*(PyObject*(*)(Py_buffer*, int))                                   \
+#define PgBuffer_AsArrayStruct                                          \
+    (*(PyObject*(*)(Py_buffer*))                                        \
      PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 16])
 
-#define ViewIsByteSwapped                                               \
-    (*(int(*)(const Py_buffer*)) PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 17])
+#define PgObject_GetBuffer                                              \
+    (*(int(*)(PyObject*, Pg_buffer*, int))                              \
+     PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 17])
 
-#define GetView                                                         \
-    (*(int(*)(PyObject*, Py_buffer*))                                   \
+#define PgBuffer_Release                                                \
+    (*(void(*)(Pg_buffer*))                                             \
      PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 18])
 
-#define ReleaseView                                                     \
-    (*(void(*)(Py_buffer*))                                             \
+#define PgDict_AsBuffer                                                 \
+    (*(int(*)(Pg_buffer*, PyObject*, int))                              \
      PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 19])
 
-#define Dict_AsView                                                     \
-    (*(int(*)(Py_buffer*, PyObject*))                                   \
-     PyGAME_C_API[PYGAMEAPI_BASE_FIRSTSLOT + 20])
-
 #define import_pygame_base() IMPORT_PYGAME_MODULE(base, BASE)
 #endif
 
                                          PyObject *kwargs);
 static PyObject *surf_get_pixels_address (PyObject *self,
                                           PyObject *closure);
-static int _view_kind(PyObject *obj, void *view_kind_vptr);
-static int _proxy_before(PyObject *proxy);
-static void _proxy_after(PyObject *proxy);
+static int _view_kind (PyObject *obj, void *view_kind_vptr);
+static int _get_buffer_0D (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_1D (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_2D (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_3D (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_red (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_green (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_blue (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_alpha (PyObject *obj, Pg_buffer *pg_view_p, int flags);
+static int _get_buffer_colorplane (PyObject *obj,
+                                   Pg_buffer *pg_view_p,
+                                   int flags,
+                                   char *name,
+                                   Uint32 mask);
+static void _release_buffer(Py_buffer *view_p);
+static void _release_buffer_nomem(Py_buffer *view_p);
 static PyObject *_raise_get_view_ndim_error(int bitsize, SurfViewKind kind);
 
-
 static PyGetSetDef surface_getsets[] = {
     { "_pixels_address", (getter)surf_get_pixels_address,
       NULL, "pixel buffer address (readonly)", NULL },
 static PyObject*
 surf_get_buffer (PyObject *self, PyObject *args)
 {
-#   define SURF_GET_BUFFER_MAXDIM 3
-    const int lilendian = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
-    const int maxdim = SURF_GET_BUFFER_MAXDIM;
-    Py_ssize_t shape[SURF_GET_BUFFER_MAXDIM];
-    Py_ssize_t strides[SURF_GET_BUFFER_MAXDIM];
-    char format[] = {'B', '\0', '\0'};
-    Py_buffer view;
-#   undef SURF_GET_BUFFER_MAXDIM
+    SDL_Surface *surface = PySurface_AsSurface (self);
+    SDL_PixelFormat *format;
+    Uint32 mask = 0;
     SurfViewKind view_kind = VIEWKIND_RAW;
-    int ndim = maxdim;
-    Py_ssize_t len = 0;
-    SDL_Surface *surface = PySurface_AsSurface (self);
-    int pixelsize;
-    Py_ssize_t itemsize = 0;
-    Uint8 *startpixel;
-    Uint32 mask = 0;
-    int pixelstep;
-    int flags = 0;
+    pg_getbufferfunc get_buffer = 0;
     PyObject *proxy_obj;
 
     if (!PyArg_ParseTuple (args, "|O&", _view_kind, &view_kind)) {
         return RAISE (PyExc_SDLError, "display Surface quit");
     }
 
-    view.readonly = 0;
-    view.shape = shape;
-    view.strides = strides;
-    view.format = format;
-    view.suboffsets = 0;
-    view.internal = 0;
-
-    startpixel = surface->pixels;
-    pixelsize = surface->format->BytesPerPixel;
-    shape[0] = (Py_ssize_t)surface->w;
-    shape[1] = (Py_ssize_t)surface->h;
-    strides[0] = (Py_ssize_t)pixelsize;
-    strides[1] = (Py_ssize_t)surface->pitch;
+    format = surface->format;
     switch (view_kind) {
 
     case VIEWKIND_0D:
-        if (strides[1] != pixelsize * shape[0]) {
+        if (surface->pitch != format->BytesPerPixel * surface->w) {
             PyErr_SetString (PyExc_ValueError,
                              "Surface data is not contiguous");
             return 0;
         }
-        ndim = 0;
-        itemsize = 1;
-        flags |= VIEW_CONTIGUOUS;
-        len = pixelsize * shape[0] * shape[1];
+        get_buffer = _get_buffer_0D;
         break;
     case VIEWKIND_1D:
-        if (strides[1] != pixelsize * shape[0]) {
+        if (surface->pitch != format->BytesPerPixel * surface->w) {
             PyErr_SetString (PyExc_ValueError,
                              "Surface data is not contiguous");
             return 0;
         }
-        ndim = 1;
-        len = pixelsize * shape[0] * shape[1];
-        shape[0] = shape[0] * shape[1];
-        itemsize = pixelsize;
-        flags |= VIEW_CONTIGUOUS | VIEW_C_ORDER | VIEW_F_ORDER;
+        if (format->BytesPerPixel == 3) {
+            return _raise_get_view_ndim_error (format->BytesPerPixel * 8,
+                                               view_kind);
+        }
+        get_buffer = _get_buffer_1D;
         break;
     case VIEWKIND_2D:
-        ndim = 2;
-        itemsize = pixelsize;
-        len = itemsize * shape[0] * shape[1];
-        flags |= VIEW_F_ORDER;
-        if (strides[1] == shape[0] * itemsize) {
-            flags |= VIEW_CONTIGUOUS;
+        if (format->BytesPerPixel == 3) {
+            return _raise_get_view_ndim_error (format->BytesPerPixel * 8,
+                                               view_kind);
         }
+        get_buffer = _get_buffer_2D;
         break;
     case VIEWKIND_3D:
-        if (pixelsize < 3) {
-            return _raise_get_view_ndim_error (pixelsize * 8, view_kind);
+        if (format->BytesPerPixel < 3) {
+            return _raise_get_view_ndim_error (format->BytesPerPixel * 8,
+                                               view_kind);
         }
-        ndim = 3;
-        itemsize = 1;
-        shape[2] = 3;
-        len = itemsize * shape[0] * shape[1] * shape[2];
-        if (surface->format->Rmask == 0xff0000 &&
-            surface->format->Gmask == 0x00ff00 &&
-            surface->format->Bmask == 0x0000ff)   {
-            strides[2] = lilendian ? -1 : 1;
-            startpixel += lilendian ? 2 : 1;
-        }
-        else if (surface->format->Bmask == 0xff0000 &&
-                 surface->format->Gmask == 0x00ff00 &&
-                 surface->format->Rmask == 0x0000ff)   {
-            strides[2] = lilendian ? 1 : -1;
-            startpixel += lilendian ? 0 : (pixelsize - 1);
-        }
-        else {
+        if (format->Gmask != 0x00ff00) {
             return RAISE (PyExc_ValueError,
                           "unsupport colormasks for 3D reference array");
         }
-        if (strides[1] == shape[2] * shape[1]) {
-            flags |= VIEW_CONTIGUOUS;
-        }
+        get_buffer = _get_buffer_3D;
         break;
     case VIEWKIND_RED:
-        mask = surface->format->Rmask;
+        mask = format->Rmask;
+        if (mask != 0x000000ffU &&
+            mask != 0x0000ff00U &&
+            mask != 0x00ff0000U &&
+            mask != 0xff000000U    ) {
+            return RAISE (PyExc_ValueError,
+                          "unsupported colormasks for red reference array");
+        }
+        get_buffer = _get_buffer_red;
         break;
     case VIEWKIND_GREEN:
-        mask = surface->format->Gmask;
+        mask = format->Gmask;
+        if (mask != 0x000000ffU &&
+            mask != 0x0000ff00U &&
+            mask != 0x00ff0000U &&
+            mask != 0xff000000U    ) {
+            return RAISE (PyExc_ValueError,
+                          "unsupported colormasks for green reference array");
+        }
+        get_buffer = _get_buffer_green;
         break;
     case VIEWKIND_BLUE:
-        mask = surface->format->Bmask;
+        mask = format->Bmask;
+        if (mask != 0x000000ffU &&
+            mask != 0x0000ff00U &&
+            mask != 0x00ff0000U &&
+            mask != 0xff000000U    ) {
+            return RAISE (PyExc_ValueError,
+                          "unsupported colormasks for blue reference array");
+        }
+        get_buffer = _get_buffer_blue;
         break;
     case VIEWKIND_ALPHA:
-        mask = surface->format->Amask;
+        mask = format->Amask;
+        if (mask != 0x000000ffU &&
+            mask != 0x0000ff00U &&
+            mask != 0x00ff0000U &&
+            mask != 0xff000000U    ) {
+            return RAISE (PyExc_ValueError,
+                          "unsupported colormasks for alpha reference array");
+        }
+        get_buffer = _get_buffer_alpha;
         break;
     case VIEWKIND_RAW:
-        ndim = 0;
-        itemsize = 1;
-        flags |= VIEW_CONTIGUOUS; /* Assumes knowledgable consumers */
-        len = surface->pitch * surface->h;
+        get_buffer = _get_buffer_0D;
         break;
     default:
         PyErr_Format (PyExc_SystemError,
                       " unrecognized view kind %d", (int)view_kind);
         return 0;
     }
-    if (!itemsize) {
-        /* Color plane */
-        ndim = 2;
-        pixelstep = pixelsize;
-        itemsize = 1;
-        len = itemsize * shape[0] * shape[1];
-        flags |= VIEW_F_ORDER;
-        switch (mask) {
-
-        case 0x000000ffU:
-            startpixel += lilendian ? 0 : 3;
-            break;
-        case 0x0000ff00U:
-            startpixel += lilendian ? 1 : 2;
-            break;
-        case 0x00ff0000U:
-            startpixel += lilendian ? 2 : 1;
-            break;
-        case 0xff000000U:
-            startpixel += lilendian ? 3 : 0;
-            break;
-        default:
-            return RAISE (PyExc_ValueError,
-                          "unsupported colormasks for alpha reference array");
-        }
-    }
-    view.ndim = ndim;
-    view.buf = startpixel;
-    view.itemsize = itemsize;
-    switch (itemsize) {
-
-    case 1:
-        break; /* default */
-    case 2:
-        format[0] = '=';
-        format[1] = 'H';
-        break;
-    case 3:
-        format[0] = 's';
-        break;
-    case 4:
-        format[0] = '=';
-        format[1] = 'I';
-        break;
-    default:
-        /* Should not get here. */
-        PyErr_Format (PyExc_SystemError,
-                      "Pygame: Surface.get_item: unrecognized itemsize %d",
-                      (int)itemsize);
-        return 0;
-    }
-    view.len = len;
-    view.obj = self;
-    Py_INCREF (self);
-
-    proxy_obj = PgBufproxy_New (&view, flags, _proxy_before, _proxy_after);
+    assert (get_buffer);
+    proxy_obj = PgBufproxy_New (self, get_buffer);
     if (proxy_obj && view_kind == VIEWKIND_RAW) {
         if (PgBufproxy_Trip (proxy_obj)) {
             Py_DECREF (proxy_obj);
 }
 
 static int
+_get_buffer_0D (PyObject *obj, Pg_buffer *pg_view_p, int flags)
+{
+    SDL_Surface *surface = PySurface_AsSurface (obj);
+    Py_buffer *view_p = (Py_buffer *)pg_view_p;
+
+    view_p->obj = 0;
+    if (!PySurface_Lock (obj)) {
+        PyErr_SetString (PyExc_BufferError, "Unable to lock the surface");
+        return -1;
+    }
+    view_p->buf = surface->pixels;
+    view_p->itemsize = 1;
+    view_p->len = surface->pitch * surface->h;
+    view_p->readonly = 0;
+    view_p->internal = 0;
+    view_p->format = (flags & PyBUF_FORMAT) ? "B" : 0;
+    view_p->shape = (flags & PyBUF_ND) ? &view_p->len : 0;
+    view_p->strides = (flags & PyBUF_STRIDES) ? &view_p->itemsize : 0;
+    view_p->suboffsets = 0;
+    view_p->internal = 0;
+    Py_INCREF (obj);
+    view_p->obj = obj;
+    pg_view_p->release_buffer = _release_buffer_nomem;
+    return 0;
+}
+
+static int
+_get_buffer_1D (PyObject *obj, Pg_buffer *pg_view_p, int flags)
+{
+    Py_buffer *view_p = (Py_buffer *)pg_view_p;
+    SDL_Surface *surface = PySurface_AsSurface (obj);
+    Py_ssize_t itemsize = surface->format->BytesPerPixel;
+
+    view_p->obj = 0;
+    if (itemsize == 1) {
+        return _get_buffer_0D (obj, pg_view_p, flags);
+    }
+    if (flags == PyBUF_SIMPLE) {
+        PyErr_Format (PyExc_BufferError,