symbian-qemu-0.9.1-12/libsdl-trunk/src/video/x11/SDL_x11image.c
changeset 1 2fb8b9db1c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/libsdl-trunk/src/video/x11/SDL_x11image.c	Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,318 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2006 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "SDL_endian.h"
+#include "../../events/SDL_events_c.h"
+#include "SDL_x11image_c.h"
+
+#ifndef NO_SHARED_MEMORY
+
+/* Shared memory error handler routine */
+static int shm_error;
+static int (*X_handler)(Display *, XErrorEvent *) = NULL;
+static int shm_errhandler(Display *d, XErrorEvent *e)
+{
+        if ( e->error_code == BadAccess ) {
+        	shm_error = True;
+        	return(0);
+        } else
+		return(X_handler(d,e));
+}
+
+static void try_mitshm(_THIS, SDL_Surface *screen)
+{
+	/* Dynamic X11 may not have SHM entry points on this box. */
+	if ((use_mitshm) && (!SDL_X11_HAVE_SHM))
+		use_mitshm = 0;
+
+	if(!use_mitshm)
+		return;
+	shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch,
+			       IPC_CREAT | 0777);
+	if ( shminfo.shmid >= 0 ) {
+		shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0);
+		shminfo.readOnly = False;
+		if ( shminfo.shmaddr != (char *)-1 ) {
+			shm_error = False;
+			X_handler = XSetErrorHandler(shm_errhandler);
+			XShmAttach(SDL_Display, &shminfo);
+			XSync(SDL_Display, True);
+			XSetErrorHandler(X_handler);
+			if ( shm_error )
+				shmdt(shminfo.shmaddr);
+		} else {
+			shm_error = True;
+		}
+		shmctl(shminfo.shmid, IPC_RMID, NULL);
+	} else {
+		shm_error = True;
+	}
+	if ( shm_error )
+		use_mitshm = 0;
+	if ( use_mitshm )
+		screen->pixels = shminfo.shmaddr;
+}
+#endif /* ! NO_SHARED_MEMORY */
+
+/* Various screen update functions available */
+static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
+static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects);
+
+int X11_SetupImage(_THIS, SDL_Surface *screen)
+{
+#ifndef NO_SHARED_MEMORY
+	try_mitshm(this, screen);
+	if(use_mitshm) {
+		SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual,
+					     this->hidden->depth, ZPixmap,
+					     shminfo.shmaddr, &shminfo, 
+					     screen->w, screen->h);
+		if(!SDL_Ximage) {
+			XShmDetach(SDL_Display, &shminfo);
+			XSync(SDL_Display, False);
+			shmdt(shminfo.shmaddr);
+			screen->pixels = NULL;
+			goto error;
+		}
+		this->UpdateRects = X11_MITSHMUpdate;
+	}
+	if(!use_mitshm)
+#endif /* not NO_SHARED_MEMORY */
+	{
+		int bpp;
+		screen->pixels = SDL_malloc(screen->h*screen->pitch);
+		if ( screen->pixels == NULL ) {
+			SDL_OutOfMemory();
+			return -1;
+		}
+ 	        bpp = screen->format->BytesPerPixel;
+		SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual,
+					  this->hidden->depth, ZPixmap, 0,
+					  (char *)screen->pixels, 
+					  screen->w, screen->h,
+					  32, 0);
+		if ( SDL_Ximage == NULL )
+			goto error;
+		/* XPutImage will convert byte sex automatically */
+		SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN)
+			                 ? MSBFirst : LSBFirst;
+		this->UpdateRects = X11_NormalUpdate;
+	}
+	screen->pitch = SDL_Ximage->bytes_per_line;
+	return(0);
+
+error:
+	SDL_SetError("Couldn't create XImage");
+	return 1;
+}
+
+void X11_DestroyImage(_THIS, SDL_Surface *screen)
+{
+	if ( SDL_Ximage ) {
+		XDestroyImage(SDL_Ximage);
+#ifndef NO_SHARED_MEMORY
+		if ( use_mitshm ) {
+			XShmDetach(SDL_Display, &shminfo);
+			XSync(SDL_Display, False);
+			shmdt(shminfo.shmaddr);
+		}
+#endif /* ! NO_SHARED_MEMORY */
+		SDL_Ximage = NULL;
+	}
+	if ( screen ) {
+		screen->pixels = NULL;
+	}
+}
+
+/* Determine the number of CPUs in the system */
+static int num_CPU(void)
+{
+       static int num_cpus = 0;
+
+       if(!num_cpus) {
+#if defined(__LINUX__)
+           char line[BUFSIZ];
+           FILE *pstat = fopen("/proc/stat", "r");
+           if ( pstat ) {
+               while ( fgets(line, sizeof(line), pstat) ) {
+                   if (SDL_memcmp(line, "cpu", 3) == 0 && line[3] != ' ') {
+                       ++num_cpus;
+                   }
+               }
+               fclose(pstat);
+           }
+#elif defined(__IRIX__)
+	   num_cpus = sysconf(_SC_NPROC_ONLN);
+#elif defined(_SC_NPROCESSORS_ONLN)
+	   /* number of processors online (SVR4.0MP compliant machines) */
+           num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(_SC_NPROCESSORS_CONF)
+	   /* number of processors configured (SVR4.0MP compliant machines) */
+           num_cpus = sysconf(_SC_NPROCESSORS_CONF);
+#endif
+           if ( num_cpus <= 0 ) {
+               num_cpus = 1;
+           }
+       }
+       return num_cpus;
+}
+
+int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags)
+{
+	int retval;
+
+	X11_DestroyImage(this, screen);
+        if ( flags & SDL_OPENGL ) {  /* No image when using GL */
+        	retval = 0;
+        } else {
+		retval = X11_SetupImage(this, screen);
+		/* We support asynchronous blitting on the display */
+		if ( flags & SDL_ASYNCBLIT ) {
+			/* This is actually slower on single-CPU systems,
+			   probably because of CPU contention between the
+			   X server and the application.
+			   Note: Is this still true with XFree86 4.0?
+			*/
+			if ( num_CPU() > 1 ) {
+				screen->flags |= SDL_ASYNCBLIT;
+			}
+		}
+	}
+	return(retval);
+}
+
+/* We don't actually allow hardware surfaces other than the main one */
+int X11_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+	return(-1);
+}
+void X11_FreeHWSurface(_THIS, SDL_Surface *surface)
+{
+	return;
+}
+
+int X11_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+	if ( (surface == SDL_VideoSurface) && blit_queued ) {
+		XSync(GFX_Display, False);
+		blit_queued = 0;
+	}
+	return(0);
+}
+void X11_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+	return;
+}
+
+int X11_FlipHWSurface(_THIS, SDL_Surface *surface)
+{
+	return(0);
+}
+
+static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
+{
+	int i;
+	
+	for (i = 0; i < numrects; ++i) {
+		if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */
+			continue;
+		}
+		XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
+			  rects[i].x, rects[i].y,
+			  rects[i].x, rects[i].y, rects[i].w, rects[i].h);
+	}
+	if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) {
+		XFlush(GFX_Display);
+		blit_queued = 1;
+	} else {
+		XSync(GFX_Display, False);
+	}
+}
+
+static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects)
+{
+#ifndef NO_SHARED_MEMORY
+	int i;
+
+	for ( i=0; i<numrects; ++i ) {
+		if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */
+			continue;
+		}
+		XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
+				rects[i].x, rects[i].y,
+				rects[i].x, rects[i].y, rects[i].w, rects[i].h,
+									False);
+	}
+	if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) {
+		XFlush(GFX_Display);
+		blit_queued = 1;
+	} else {
+		XSync(GFX_Display, False);
+	}
+#endif /* ! NO_SHARED_MEMORY */
+}
+
+/* There's a problem with the automatic refreshing of the display.
+   Even though the XVideo code uses the GFX_Display to update the
+   video memory, it appears that updating the window asynchronously
+   from a different thread will cause "blackouts" of the window.
+   This is a sort of a hacked workaround for the problem.
+*/
+static int enable_autorefresh = 1;
+
+void X11_DisableAutoRefresh(_THIS)
+{
+	--enable_autorefresh;
+}
+
+void X11_EnableAutoRefresh(_THIS)
+{
+	++enable_autorefresh;
+}
+
+void X11_RefreshDisplay(_THIS)
+{
+	/* Don't refresh a display that doesn't have an image (like GL)
+	   Instead, post an expose event so the application can refresh.
+	 */
+	if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) {
+		SDL_PrivateExpose();
+		return;
+	}
+#ifndef NO_SHARED_MEMORY
+	if ( this->UpdateRects == X11_MITSHMUpdate ) {
+		XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
+				0, 0, 0, 0, this->screen->w, this->screen->h,
+				False);
+	} else
+#endif /* ! NO_SHARED_MEMORY */
+	{
+		XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
+			  0, 0, 0, 0, this->screen->w, this->screen->h);
+	}
+	XSync(SDL_Display, False);
+}
+