Commits

pygame  committed 1f71329

major locking enhancements. Surface.subsurface added

  • Participants
  • Parent commits a4ffbbd

Comments (0)

Files changed (8)

 rect src/rect.c $(SDL)
 rwobject src/rwobject.c $(SDL)
 surface src/surface.c $(SDL)
+surflock src/surflock.c $(SDL)
 time src/time.c $(SDL)
 joystick src/joystick.c $(SDL)
 draw src/draw.c $(SDL)
 
  * Support for OpenGL (initial testing not so good)
  * Support for Piddle (drawing lines, shapes, text)
- * Surfarray with alpha and colormap support
  * Interface with PIL images
  * GUI library. There's a few out there
  * Simple image transforms; flip, rotate-90, double
 # BREAK = change breaks existing code
 # BUG   = fixed a bug that was crashing
 
+Jan 29, 2001
+	extremely revamped surface locking mechnisms
+	new Surface.subsurface for shared surfaces
+
 Jan 25, 2001
 	added the draw module, with clipped line function
 	added alpha routines in surfarray module

File docs/ref/Surface.html

 set a palette entry</td></tr>
 
 
+<tr><td><a href=#subsurface>subsurface</a></td><td> -
+create a new surface that shares pixel data</td></tr>
+
+
 <tr><td><a href=#unlock>unlock</a></td><td> -
 locks Surface for pixel access</td></tr>
 
 This function sets the palette color at a specific entry.
 </ul><br>&nbsp;<br>
 
+<a name=subsurface><font size=+2><b>subsurface
+</b></font><br><font size=+1><tt>
+Surface.subsurface(rectstyle) -> Surface
+</tt></font><ul>
+Creates a new surface that shares pixel data of the given surface.
+Note that only the pixel data is shared. Things like clipping rectangles
+and colorkeys will be unique for the new surface.
+<br>&nbsp;<br>
+The fill is subject to be clipped by the active clipping
+rectangle. The return value contains the actual area filled.
+</ul><br>&nbsp;<br>
+
 <a name=unlock><font size=+2><b>unlock
 </b></font><br><font size=+1><tt>
 Surface.unlock() -> None
 	int pts[4];
 	Uint8 rgba[4];
 	Uint32 color;
-	int didlock = 0;
 
 	/*get all the arguments*/
 	if(!PyArg_ParseTuple(arg, "O!OOO", &PySurface_Type, &surfobj, &colorobj, &start, &end))
 				surf->clip_rect.y + surf->clip_rect.h - 1))
 		return PyRect_New4(startx, starty, 0, 0);
 
-	if(!surf->pixels)
-	{
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-		didlock = 1;
-	}
+	if(!PySurface_Lock(surfobj)) return NULL;
 
-	/*a nice help would be horizontal and vertical drawers too*/
 	if(pts[1] == pts[3])
 		drawhorzline(surf, color, pts[0], pts[1], pts[2], pts[3]);
 	else
 		drawline(surf, color, pts[0], pts[1], pts[2], pts[3]);
 
-	if(didlock)
-		SDL_UnlockSurface(surf);
+	if(!PySurface_Unlock(surfobj)) return NULL;
 
 	/*compute return rect*/
 	if(startx < endx)

File src/pygame.h

 typedef struct {
 	PyObject_HEAD
 	SDL_Surface* surf;
+	struct SubSurface_Data* subsurface;  /*ptr to subsurface data (if a subsurface)*/
+	int lockcount;
+	int didlock;
 } PySurfaceObject;
 #define PySurface_AsSurface(x) (((PySurfaceObject*)x)->surf)
 #ifndef PYGAMEAPI_SURFACE_INTERNAL
 			int i; void** localptr = (void*)PyCObject_AsVoidPtr(c_api); \
 			for(i = 0; i < PYGAMEAPI_SURFACE_NUMSLOTS; ++i) \
 				PyGAME_C_API[i + PYGAMEAPI_SURFACE_FIRSTSLOT] = localptr[i]; \
+	} } \
+	module = PyImport_ImportModule("pygame.surflock"); \
+	if (module != NULL) { \
+		PyObject *dict = PyModule_GetDict(module); \
+		PyObject *c_api = PyDict_GetItemString(dict, PYGAMEAPI_LOCAL_ENTRY); \
+		if(PyCObject_Check(c_api)) {\
+			int i; void** localptr = (void*)PyCObject_AsVoidPtr(c_api); \
+			for(i = 0; i < PYGAMEAPI_SURFLOCK_NUMSLOTS; ++i) \
+				PyGAME_C_API[i + PYGAMEAPI_SURFLOCK_FIRSTSLOT] = localptr[i]; \
 } } }
 #endif
 
 
+
+/* SURFLOCK */    /*auto import/init by surface*/
+#define PYGAMEAPI_SURFLOCK_FIRSTSLOT 43
+#define PYGAMEAPI_SURFLOCK_NUMSLOTS 5
+struct SubSurface_Data
+{
+	PyObject* owner;
+	int pixeloffset;
+};
+#ifndef PYGAMEAPI_SURFLOCK_INTERNAL
+#define PySurface_Prep(x) if(((PySurfaceObject*)x)->subsurface)(*(*(void(*)(PyObject*))PyGAME_C_API[PYGAMEAPI_SURFLOCK_FIRSTSLOT + 0]))(x)
+#define PySurface_Unprep(x) if(((PySurfaceObject*)x)->subsurface)(*(*(void(*)(PyObject*))PyGAME_C_API[PYGAMEAPI_SURFLOCK_FIRSTSLOT + 1]))(x)
+#define PySurface_Lock (*(int(*)(PyObject*))PyGAME_C_API[PYGAMEAPI_SURFLOCK_FIRSTSLOT + 2])
+#define PySurface_Unlock (*(int(*)(PyObject*))PyGAME_C_API[PYGAMEAPI_SURFLOCK_FIRSTSLOT + 3])
+#define PySurface_LockLifetime (*(PyObject*(*)(PyObject*))PyGAME_C_API[PYGAMEAPI_SURFLOCK_FIRSTSLOT + 4])
+#endif
+
+
+
 /* EVENT */
-#define PYGAMEAPI_EVENT_FIRSTSLOT 45
+#define PYGAMEAPI_EVENT_FIRSTSLOT 49
 #define PYGAMEAPI_EVENT_NUMSLOTS 2
 typedef struct {
 	PyObject_HEAD
 
 /* RWOBJECT */
 /*the rwobject are only needed for C side work, not accessable from python*/
-#define PYGAMEAPI_RWOBJECT_FIRSTSLOT 50
+#define PYGAMEAPI_RWOBJECT_FIRSTSLOT 53
 #define PYGAMEAPI_RWOBJECT_NUMSLOTS 1
 #ifndef PYGAMEAPI_RWOBJECT_INTERNAL
 #define RWopsFromPython (*(SDL_RWops*(*)(PyObject*))PyGAME_C_API[PYGAMEAPI_RWOBJECT_FIRSTSLOT + 0])

File src/surface.c

 	if(x < 0 || x >= surf->w || y < 0 || y >= surf->h)
 		return RAISE(PyExc_IndexError, "pixel index out of range");
 
-	if(!surf->pixels)
-	{
-		didlock = 1;
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-	}
+	if(format->BytesPerPixel < 1 || format->BytesPerPixel > 4)
+		return RAISE(PyExc_RuntimeError, "invalid color depth for surface");
+
+	if(!PySurface_Lock(self)) return NULL;
 	pixels = (Uint8*)surf->pixels;
 
-
 	switch(format->BytesPerPixel)
 	{
 		case 1:
 			color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16);
 #endif
 			break;
-		case 4:
+		default: /*case 4:*/
 			color = *((Uint32*)(pixels + y * surf->pitch) + x);
 			break;
-		default:
-			if(didlock) SDL_UnlockSurface(surf);
-			return RAISE(PyExc_RuntimeError, "Unable to determine color depth.");
 	}
-	if(didlock) SDL_UnlockSurface(surf);
+	if(!PySurface_Unlock(self)) return NULL;
 
 	SDL_GetRGBA(color, format, &r, &g, &b, &a);
 	return Py_BuildValue("(bbbb)", r, g, b, a);
 
 	if(x < 0 || x >= surf->w || y < 0 || y >= surf->h)
 	{
-		printf("%d,%d  -  %d,%d\n",x,y, surf->w, surf->h);
 		PyErr_SetString(PyExc_IndexError, "pixel index out of range");
 		return NULL;
 	}
 
+	if(format->BytesPerPixel < 1 || format->BytesPerPixel > 4)
+		return RAISE(PyExc_RuntimeError, "invalid color depth for surface");
+
 	if(!RGBAFromObj(rgba_obj, rgba))
 		return RAISE(PyExc_TypeError, "Invalid RGBA object");
 	color = SDL_MapRGBA(surf->format, rgba[0], rgba[1], rgba[2], rgba[3]);
 
-	if(!surf->pixels)
-	{
-		didlock = 1;
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-	}
+	if(!PySurface_Lock(self)) return NULL;
 	pixels = (Uint8*)surf->pixels;
 
 	switch(format->BytesPerPixel)
 			*(byte_buf + (format->Gshift >> 3)) = rgba[1];
 			*(byte_buf + (format->Bshift >> 3)) = rgba[2];	
 			break;
-		case 4:
+		default: /*case 4:*/
 			*((Uint32*)(pixels + y * surf->pitch) + x) = color;
 			break;
-		default:
-			if(didlock) SDL_UnlockSurface(surf);
-			return RAISE(PyExc_SDLError, "Unable to determine color depth.");
 	}
 
-	if(didlock) SDL_UnlockSurface(surf);
+	if(!PySurface_Unlock(self)) return NULL;
 	RETURN_NONE
 }
 
 	if(!PyArg_ParseTuple(args, ""))
 		return NULL;
 
-	if(SDL_LockSurface(surf) == -1)
-		return RAISE(PyExc_SDLError, SDL_GetError());
+	if(!PySurface_Lock(self))
+		return NULL;
 
 	RETURN_NONE
 }
 	if(!PyArg_ParseTuple(args, ""))
 		return NULL;
 
-	SDL_UnlockSurface(surf);
+	if(!PySurface_Unlock(self))
+		return NULL;
+
 	RETURN_NONE
 }
 
 }
 
 
+    /*DOC*/ static char doc_surf_get_locked[] =
+    /*DOC*/    "Surface.get_locked() -> bool\n"
+    /*DOC*/    "check if the surface needs locking\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "Returns true if the surface is currently locked.\n"
+    /*DOC*/ ;
+
+static PyObject* surf_get_locked(PyObject* self, PyObject* args)
+{
+	PySurfaceObject* surf = (PySurfaceObject*)self;
+
+	if(!PyArg_ParseTuple(args, ""))
+		return NULL;
+	
+	return PyInt_FromLong(surf->lockcount);
+}
+
+
 
     /*DOC*/ static char doc_surf_get_palette[] =
     /*DOC*/    "Surface.get_palette() -> [[r, g, b], ...]\n"
 	Uint32 flags = 0, key = 0;
 	PyObject* rgba_obj = NULL;
 	Uint8 rgba[4];
+	int result;
 
 	if(!PyArg_ParseTuple(args, "|Oi", &rgba_obj, &flags))
 		return NULL;
 	if(PyTuple_Size(args) > 0)
 		flags |= SDL_SRCCOLORKEY;
 
-	if(SDL_SetColorKey(surf, flags, key) == -1)
+	PySurface_Prep(self);
+	result = SDL_SetColorKey(surf, flags, key);
+	PySurface_Unprep(self);
+
+	if(result == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
+	
 	RETURN_NONE
 }
 
 	SDL_Surface* surf = PySurface_AsSurface(self);
 	Uint32 flags = 0;
 	Uint8 alpha = 0;
+	int result;
 
 	if(!PyArg_ParseTuple(args, "|bi", &alpha, &flags))
 		return NULL;
 	if(PyTuple_Size(args) > 0)
 		flags |= SDL_SRCALPHA;
 
-	if(SDL_SetAlpha(surf, flags, alpha) == -1)
+	PySurface_Prep(self);
+	result = SDL_SetAlpha(surf, flags, alpha);
+	PySurface_Unprep(self);
+		
+	if(result == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
+	
 	RETURN_NONE
 }
 
 	if(!PyArg_ParseTuple(args, "|O!", &PySurface_Type, &srcsurf))
 		return NULL;
 
+	PySurface_Prep(self);
 	if(srcsurf)
 	{
 		src = PySurface_AsSurface(srcsurf);
 	}
 	else
 		newsurf = SDL_DisplayFormat(surf);
+	PySurface_Unprep(self);
 
 	return PySurface_New(newsurf);
 }
 	if(!PyArg_ParseTuple(args, "|O!", &PySurface_Type, &srcsurf))
 		return NULL;
 
+	PySurface_Prep(self);
 	if(srcsurf)
 	{
 		/*hmm, we have to figure this out, not all depths have good support for alpha*/
 	}
 	else
 		newsurf = SDL_DisplayFormatAlpha(surf);
+	PySurface_Unprep(self);
 
 	return PySurface_New(newsurf);
 }
 		rect = &temp;
 	}
 
+	PySurface_Prep(self);
 	result = SDL_FillRect(surf, (SDL_Rect*)rect, color);
+	PySurface_Unprep(self);
+
 	if(result == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
 	return PyRect_New(rect);
 	dest_rect.w = (unsigned short)src_rect->w;
 	dest_rect.h = (unsigned short)src_rect->h;
 
+	PySurface_Prep(self);
+	PySurface_Prep(srcobject);
 	result = SDL_BlitSurface(src, (SDL_Rect*)src_rect, dest, &dest_rect);
+	PySurface_Unprep(self);
+	PySurface_Unprep(srcobject);
+
 	if(result == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
 
+
+
 	return PyRect_New((GAME_Rect*)&dest_rect);
 }
 
 	{
 		char* name = PyString_AsString(file);
 		Py_BEGIN_ALLOW_THREADS
+		PySurface_Prep(self);
 		result = SDL_SaveBMP(surf, name);
+		PySurface_Unprep(self);
 		Py_END_ALLOW_THREADS
 	}
 	else
 		if(!(rw = RWopsFromPython(file)))
 			return NULL;
 		Py_BEGIN_ALLOW_THREADS
+		PySurface_Prep(self);
 		result = SDL_SaveBMP_RW(surf, rw, 1);
+		PySurface_Unprep(self);
 		Py_END_ALLOW_THREADS
 	}
 
 
 
 
+    /*DOC*/ static char doc_surf_subsurface[] =
+    /*DOC*/    "Surface.subsurface(rectstyle) -> Surface\n"
+    /*DOC*/    "create a new surface that shares pixel data\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "Creates a new surface that shares pixel data of the given surface.\n"
+    /*DOC*/    "Note that only the pixel data is shared. Things like clipping rectangles\n"
+    /*DOC*/    "and colorkeys will be unique for the new surface.\n"
+    /*DOC*/ ;
+
+static PyObject* surf_subsurface(PyObject* self, PyObject* args)
+{
+	SDL_Surface* surf = PySurface_AsSurface(self);
+	SDL_PixelFormat* format = surf->format;
+	GAME_Rect *rect, temp;
+	PyObject* r;
+	SDL_Surface* sub;
+	PyObject* subobj;
+	int didlock = 0;
+	int pixeloffset;
+	char* startpixel;
+	struct SubSurface_Data* data;
+
+	if(!PyArg_ParseTuple(args, "O", &r))
+		return NULL;
+
+	if(!(rect = GameRect_FromObject(r, &temp)))
+		return RAISE(PyExc_ValueError, "invalid rectstyle object");
+	if(rect->x < 0 || rect-> y < 0 || rect->x + rect->w > surf->w || rect->y + rect->h > surf->h)
+		return RAISE(PyExc_ValueError, "subsurface rectangle outside surface area");
+
+
+	if(!surf->pixels)
+	{
+		if(SDL_LockSurface(surf) == -1)
+			return RAISE(PyExc_SDLError, SDL_GetError());
+		didlock = 1;
+	}
+
+	pixeloffset = rect->x * format->BytesPerPixel + rect->y * surf->pitch;
+	startpixel = ((char*)surf->pixels) + pixeloffset;
+
+	sub = SDL_CreateRGBSurfaceFrom(startpixel, rect->w, rect->h, format->BitsPerPixel, \
+				surf->pitch, format->Rmask, format->Gmask, format->Bmask, format->Amask);
+
+	if(didlock)
+		SDL_UnlockSurface(surf);
+		
+	if(!sub)
+		return RAISE(PyExc_SDLError, SDL_GetError());
+
+	data = PyMem_New(struct SubSurface_Data, 1);
+	if(!data) return NULL;
+
+	subobj = PySurface_New(sub);
+	if(!subobj)
+	{
+		PyMem_Del(data);
+		return NULL;
+	}
+
+	Py_INCREF(self);
+	data->owner = self;
+	data->pixeloffset = pixeloffset;
+	((PySurfaceObject*)subobj)->subsurface = data;
+
+	return subobj;
+}
+
+
 
 static struct PyMethodDef surface_methods[] =
 {
 	{"lock",			surf_lock,			1, doc_surf_lock },
 	{"unlock",			surf_unlock,		1, doc_surf_unlock },
 	{"mustlock",		surf_mustlock,		1, doc_surf_mustlock },
+	{"get_locked",		surf_get_locked,	1, doc_surf_get_locked },
 
 	{"set_colorkey",	surf_set_colorkey,	1, doc_surf_set_colorkey },
 	{"get_colorkey",	surf_get_colorkey,	1, doc_surf_get_colorkey },
 	{"get_shifts",		surf_get_shifts,	1, doc_surf_get_shifts },
 	{"get_losses",		surf_get_losses,	1, doc_surf_get_losses },
 
-	{"save",		surf_save,		1, doc_surf_save }, 
+	{"save",			surf_save,			1, doc_surf_save }, 
+	{"subsurface",		surf_subsurface,	1, doc_surf_subsurface },
 
 	{NULL,		NULL}
 };
 static void surface_dealloc(PyObject* self)
 {
 	PySurfaceObject* surf = (PySurfaceObject*)self;
+	struct SubSurface_Data* data = ((PySurfaceObject*)self)->subsurface;
 
 	if(SDL_WasInit(SDL_INIT_VIDEO))
 		SDL_FreeSurface(surf->surf);
+	if(data)
+	{
+		Py_XDECREF(data->owner);
+		PyMem_Del(data);
+	}
+
 	PyMem_DEL(self);	
 }
 
     /*DOC*/    "to see if a Surface really needs to be locked with the mustlock()\n"
     /*DOC*/    "function.\n"
     /*DOC*/ ;
-#if 0 /*extra help, only for docs*/
-    /*DOC*/ static char doc_Surface_EXTRA[] =
-    /*DOC*/    "Here is the quick breakdown of how packed pixels work (don't worry if\n"
-    /*DOC*/    "you don't quite understand this, it is only here for informational\n"
-    /*DOC*/    "purposes, it is not needed). Each colorplane mask can be used to\n"
-    /*DOC*/    "isolate the values for a colorplane from the packed pixel color.\n"
-    /*DOC*/    "Therefore PACKED_COLOR & RED_MASK == REDPLANE. Note that the\n"
-    /*DOC*/    "REDPLANE is not exactly the red color value, but it is the red\n"
-    /*DOC*/    "color value bitwise left shifted a certain amount. The losses and\n"
-    /*DOC*/    "masks can be used to convert back and forth between each\n"
-    /*DOC*/    "colorplane and the actual color for that plane. Here are the\n"
-    /*DOC*/    "final formulas used be map and unmap (not exactly, heh).\n"
-    /*DOC*/    "PACKED_COLOR = RED>>losses[0]<<shifts[0] |\n"
-    /*DOC*/    "      GREEN>>losses[1]<<shifts[1] | BLUE>>losses[2]<<shifts[2]\n"
-    /*DOC*/    "RED = PACKED_COLOR & masks[0] >> shifts[0] << losses[0]\n"
-    /*DOC*/    "GREEN = PACKED_COLOR & masks[1] >> shifts[1] << losses[1]\n"
-    /*DOC*/    "BLUE = PACKED_COLOR & masks[2] >> shifts[2] << losses[2]\n"
-    /*DOC*/    "There is also an alpha channel for some Surfaces. The alpha\n"
-    /*DOC*/    "channel works this same exact way, and the map_rgba() and\n"
-    /*DOC*/    "unmap_rgba() functions can be used to do the conversion for you.\n"
-#endif
 
 
 static PyTypeObject PySurface_Type =
 
 	surf = PyObject_NEW(PySurfaceObject, &PySurface_Type);
 	if(surf)
+	{
 		surf->surf = s;
-
+		surf->subsurface = NULL;
+		surf->didlock = 0;
+		surf->lockcount = 0;
+	}
 	return (PyObject*)surf;
 }
 
 
 void initsurface(void)
 {
-	PyObject *module, *dict, *apiobj;
+	PyObject *module, *dict, *apiobj, *lockmodule;
 	static void* c_api[PYGAMEAPI_SURFACE_NUMSLOTS];
 
 	PyType_Init(PySurface_Type);
 	/*imported needed apis*/
 	import_pygame_base();
 	import_pygame_rect();
+
+	/*import the surflock module manually*/
+	lockmodule = PyImport_ImportModule("pygame.surflock");
+	if (module != NULL)
+	{
+		PyObject *dict = PyModule_GetDict(lockmodule);
+		PyObject *c_api = PyDict_GetItemString(dict, PYGAMEAPI_LOCAL_ENTRY);
+		if(PyCObject_Check(c_api))
+		{
+			int i; void** localptr = (void*)PyCObject_AsVoidPtr(c_api);
+			for(i = 0; i < PYGAMEAPI_SURFLOCK_NUMSLOTS; ++i)
+				PyGAME_C_API[i + PYGAMEAPI_SURFLOCK_FIRSTSLOT] = localptr[i];
+		}
+	}
 }
 

File src/surfarray.c

 #include<SDL_byteorder.h>
 
 
-#define TEMP_UNLOCK 	if(didlock) SDL_UnlockSurface(surf)
-
 
 
     /*DOC*/ static char doc_pixels3d[] =
 	char* startpixel;
 	int pixelstep;
 	const int lilendian = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
+	PyObject* lifelock;
 	
 	if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &array))
 		return NULL;
 	if(surf->format->BytesPerPixel <= 2 || surf->format->BytesPerPixel > 4)
 		return RAISE(PyExc_ValueError, "unsupport bit depth for 3D reference array");
 
+	lifelock = PySurface_LockLifetime(array);
+	if(!lifelock) return NULL;
+
 	/*must discover information about how data is packed*/
 	if(surf->format->Rmask == 0xff<<16 && 
 				surf->format->Gmask == 0xff<<8 &&
 		((PyArrayObject*)array)->strides[2] = pixelstep;
 		((PyArrayObject*)array)->strides[1] = surf->pitch;
 		((PyArrayObject*)array)->strides[0] = surf->format->BytesPerPixel;
-		((PyArrayObject*)array)->base = array;
-		Py_INCREF(array);
+		((PyArrayObject*)array)->base = lifelock;
 	}
 	return array;
 }
 	stridex = ((PyArrayObject*)array)->strides[0];
 	stridey = ((PyArrayObject*)array)->strides[1];
 
-	if(!surf->pixels)
-	{
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-		didlock = 1;
-	}
+	if(!PySurface_Lock(array)) return NULL;
 
 	switch(surf->format->BytesPerPixel)
 	{
 		}break;
 	}
 
-	TEMP_UNLOCK;
+	if(!PySurface_Unlock(array)) return NULL;
 	return array;
 }
 
 	stridex = ((PyArrayObject*)array)->strides[0];
 	stridey = ((PyArrayObject*)array)->strides[1];
 
-	if(!surf->pixels)
-	{
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-		didlock = 1;
-	}
+	if(!PySurface_Lock(array)) return NULL;
 	
 	switch(surf->format->BytesPerPixel)
 	{
 	case 1:
 		if(!format->palette)
 		{
-			TEMP_UNLOCK;
+			if(!PySurface_Unlock(array)) return NULL;
 			return RAISE(PyExc_RuntimeError, "8bit surface has no palette");
 		}
 		palette = format->palette->colors;
 		}break;
 	}
 
-	TEMP_UNLOCK;
+	if(!PySurface_Unlock(array)) return NULL;
 	return array;
 }
 
 	stridex = ((PyArrayObject*)array)->strides[0];
 	stridey = ((PyArrayObject*)array)->strides[1];
 
-	if(!surf->pixels)
-	{
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-		didlock = 1;
-	}
+	if(!PySurface_Lock(array)) return NULL;
 
 	switch(surf->format->BytesPerPixel)
 	{
 		}break;
 	}
 
-	TEMP_UNLOCK;
+	if(!PySurface_Unlock(array)) return NULL;
 	return array;
 }
 
 	stridex = ((PyArrayObject*)array)->strides[0];
 	stridey = ((PyArrayObject*)array)->strides[1];
 
-	if(!surf->pixels)
-	{
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-		didlock = 1;
-	}
+	if(!PySurface_Lock(array)) return NULL;
+
 	switch(surf->format->BytesPerPixel)
 	{
 	case 1:
 		}break;
 	}
 
-	TEMP_UNLOCK;
+	if(!PySurface_Lock(array)) return NULL;
 	return array;
 }
 
 
 	if(sizex != surf->w || sizey != surf->h)
 		return RAISE(PyExc_ValueError, "array must match surface dimensions");
-
-	if(!surf->pixels)
-	{
-		if(SDL_LockSurface(surf) == -1)
-			return RAISE(PyExc_SDLError, SDL_GetError());
-		didlock = 1;
-	}
+	if(!PySurface_Lock(surfobj)) return NULL;
 
 	switch(surf->format->BytesPerPixel)
 	{
 				case sizeof(Uint16): COPYMACRO_2D(Uint8, Uint16)  break;
 				case sizeof(Uint32): COPYMACRO_2D(Uint8, Uint32)  break;
 				default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		}
 		break;
 				case sizeof(Uint16): COPYMACRO_2D(Uint16, Uint16)  break;
 				case sizeof(Uint32): COPYMACRO_2D(Uint16, Uint32)  break;
 				default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		} else {
 			switch(array->descr->elsize) {
 				case sizeof(Uint16):COPYMACRO_3D(Uint16, Uint16)  break;
 				case sizeof(Uint32):COPYMACRO_3D(Uint16, Uint32)  break;
 				default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		}
 		break;
 				case sizeof(Uint16): COPYMACRO_2D_24(Uint16)  break;
 				case sizeof(Uint32): COPYMACRO_2D_24(Uint32)  break;
 				default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		} else {
 			switch(array->descr->elsize) {
 				case sizeof(Uint16):COPYMACRO_3D_24(Uint16)  break;
 				case sizeof(Uint32):COPYMACRO_3D_24(Uint32)  break;
 				default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		}
 		break;
 				case sizeof(Uint16): COPYMACRO_2D(Uint32, Uint16)  break;
 				case sizeof(Uint32): COPYMACRO_2D(Uint32, Uint32)  break;
 			default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		} else {
 			switch(array->descr->elsize) {
 				case sizeof(Uint16):COPYMACRO_3D(Uint32, Uint16)  break;
 				case sizeof(Uint32):COPYMACRO_3D(Uint32, Uint32)  break;
 				default: 
-					TEMP_UNLOCK; return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
+					if(!PySurface_Unlock(surfobj)) return NULL;
+					return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 			}
 		}
 		break;
 	default:
-		TEMP_UNLOCK; return RAISE(PyExc_RuntimeError, "unsupported bit depth for image");
+		if(!PySurface_Unlock(surfobj)) return NULL;
+		return RAISE(PyExc_RuntimeError, "unsupported bit depth for image");
 	}
 
-	TEMP_UNLOCK;
+	if(!PySurface_Unlock(surfobj)) return NULL;
 	RETURN_NONE
 }
 
 
 
 
-
     /*DOC*/ static char doc_pygame_surfarray_MODULE[] =
     /*DOC*/    "Contains routines for mixing numeric arrays with\n"
     /*DOC*/    "surfaces\n"