symbian-qemu-0.9.1-12/libsdl-trunk/src/video/x11/SDL_x11image.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997-2006 Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Lesser General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2.1 of the License, or (at your option) any later version.
       
     9 
       
    10     This library is distributed in the hope that it will be useful,
       
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13     Lesser General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Lesser General Public
       
    16     License along with this library; if not, write to the Free Software
       
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 */
       
    22 #include "SDL_config.h"
       
    23 
       
    24 #include <stdio.h>
       
    25 #include <unistd.h>
       
    26 
       
    27 #include "SDL_endian.h"
       
    28 #include "../../events/SDL_events_c.h"
       
    29 #include "SDL_x11image_c.h"
       
    30 
       
    31 #ifndef NO_SHARED_MEMORY
       
    32 
       
    33 /* Shared memory error handler routine */
       
    34 static int shm_error;
       
    35 static int (*X_handler)(Display *, XErrorEvent *) = NULL;
       
    36 static int shm_errhandler(Display *d, XErrorEvent *e)
       
    37 {
       
    38         if ( e->error_code == BadAccess ) {
       
    39         	shm_error = True;
       
    40         	return(0);
       
    41         } else
       
    42 		return(X_handler(d,e));
       
    43 }
       
    44 
       
    45 static void try_mitshm(_THIS, SDL_Surface *screen)
       
    46 {
       
    47 	/* Dynamic X11 may not have SHM entry points on this box. */
       
    48 	if ((use_mitshm) && (!SDL_X11_HAVE_SHM))
       
    49 		use_mitshm = 0;
       
    50 
       
    51 	if(!use_mitshm)
       
    52 		return;
       
    53 	shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch,
       
    54 			       IPC_CREAT | 0777);
       
    55 	if ( shminfo.shmid >= 0 ) {
       
    56 		shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0);
       
    57 		shminfo.readOnly = False;
       
    58 		if ( shminfo.shmaddr != (char *)-1 ) {
       
    59 			shm_error = False;
       
    60 			X_handler = XSetErrorHandler(shm_errhandler);
       
    61 			XShmAttach(SDL_Display, &shminfo);
       
    62 			XSync(SDL_Display, True);
       
    63 			XSetErrorHandler(X_handler);
       
    64 			if ( shm_error )
       
    65 				shmdt(shminfo.shmaddr);
       
    66 		} else {
       
    67 			shm_error = True;
       
    68 		}
       
    69 		shmctl(shminfo.shmid, IPC_RMID, NULL);
       
    70 	} else {
       
    71 		shm_error = True;
       
    72 	}
       
    73 	if ( shm_error )
       
    74 		use_mitshm = 0;
       
    75 	if ( use_mitshm )
       
    76 		screen->pixels = shminfo.shmaddr;
       
    77 }
       
    78 #endif /* ! NO_SHARED_MEMORY */
       
    79 
       
    80 /* Various screen update functions available */
       
    81 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
       
    82 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects);
       
    83 
       
    84 int X11_SetupImage(_THIS, SDL_Surface *screen)
       
    85 {
       
    86 #ifndef NO_SHARED_MEMORY
       
    87 	try_mitshm(this, screen);
       
    88 	if(use_mitshm) {
       
    89 		SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual,
       
    90 					     this->hidden->depth, ZPixmap,
       
    91 					     shminfo.shmaddr, &shminfo, 
       
    92 					     screen->w, screen->h);
       
    93 		if(!SDL_Ximage) {
       
    94 			XShmDetach(SDL_Display, &shminfo);
       
    95 			XSync(SDL_Display, False);
       
    96 			shmdt(shminfo.shmaddr);
       
    97 			screen->pixels = NULL;
       
    98 			goto error;
       
    99 		}
       
   100 		this->UpdateRects = X11_MITSHMUpdate;
       
   101 	}
       
   102 	if(!use_mitshm)
       
   103 #endif /* not NO_SHARED_MEMORY */
       
   104 	{
       
   105 		int bpp;
       
   106 		screen->pixels = SDL_malloc(screen->h*screen->pitch);
       
   107 		if ( screen->pixels == NULL ) {
       
   108 			SDL_OutOfMemory();
       
   109 			return -1;
       
   110 		}
       
   111  	        bpp = screen->format->BytesPerPixel;
       
   112 		SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual,
       
   113 					  this->hidden->depth, ZPixmap, 0,
       
   114 					  (char *)screen->pixels, 
       
   115 					  screen->w, screen->h,
       
   116 					  32, 0);
       
   117 		if ( SDL_Ximage == NULL )
       
   118 			goto error;
       
   119 		/* XPutImage will convert byte sex automatically */
       
   120 		SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN)
       
   121 			                 ? MSBFirst : LSBFirst;
       
   122 		this->UpdateRects = X11_NormalUpdate;
       
   123 	}
       
   124 	screen->pitch = SDL_Ximage->bytes_per_line;
       
   125 	return(0);
       
   126 
       
   127 error:
       
   128 	SDL_SetError("Couldn't create XImage");
       
   129 	return 1;
       
   130 }
       
   131 
       
   132 void X11_DestroyImage(_THIS, SDL_Surface *screen)
       
   133 {
       
   134 	if ( SDL_Ximage ) {
       
   135 		XDestroyImage(SDL_Ximage);
       
   136 #ifndef NO_SHARED_MEMORY
       
   137 		if ( use_mitshm ) {
       
   138 			XShmDetach(SDL_Display, &shminfo);
       
   139 			XSync(SDL_Display, False);
       
   140 			shmdt(shminfo.shmaddr);
       
   141 		}
       
   142 #endif /* ! NO_SHARED_MEMORY */
       
   143 		SDL_Ximage = NULL;
       
   144 	}
       
   145 	if ( screen ) {
       
   146 		screen->pixels = NULL;
       
   147 	}
       
   148 }
       
   149 
       
   150 /* Determine the number of CPUs in the system */
       
   151 static int num_CPU(void)
       
   152 {
       
   153        static int num_cpus = 0;
       
   154 
       
   155        if(!num_cpus) {
       
   156 #if defined(__LINUX__)
       
   157            char line[BUFSIZ];
       
   158            FILE *pstat = fopen("/proc/stat", "r");
       
   159            if ( pstat ) {
       
   160                while ( fgets(line, sizeof(line), pstat) ) {
       
   161                    if (SDL_memcmp(line, "cpu", 3) == 0 && line[3] != ' ') {
       
   162                        ++num_cpus;
       
   163                    }
       
   164                }
       
   165                fclose(pstat);
       
   166            }
       
   167 #elif defined(__IRIX__)
       
   168 	   num_cpus = sysconf(_SC_NPROC_ONLN);
       
   169 #elif defined(_SC_NPROCESSORS_ONLN)
       
   170 	   /* number of processors online (SVR4.0MP compliant machines) */
       
   171            num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
       
   172 #elif defined(_SC_NPROCESSORS_CONF)
       
   173 	   /* number of processors configured (SVR4.0MP compliant machines) */
       
   174            num_cpus = sysconf(_SC_NPROCESSORS_CONF);
       
   175 #endif
       
   176            if ( num_cpus <= 0 ) {
       
   177                num_cpus = 1;
       
   178            }
       
   179        }
       
   180        return num_cpus;
       
   181 }
       
   182 
       
   183 int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags)
       
   184 {
       
   185 	int retval;
       
   186 
       
   187 	X11_DestroyImage(this, screen);
       
   188         if ( flags & SDL_OPENGL ) {  /* No image when using GL */
       
   189         	retval = 0;
       
   190         } else {
       
   191 		retval = X11_SetupImage(this, screen);
       
   192 		/* We support asynchronous blitting on the display */
       
   193 		if ( flags & SDL_ASYNCBLIT ) {
       
   194 			/* This is actually slower on single-CPU systems,
       
   195 			   probably because of CPU contention between the
       
   196 			   X server and the application.
       
   197 			   Note: Is this still true with XFree86 4.0?
       
   198 			*/
       
   199 			if ( num_CPU() > 1 ) {
       
   200 				screen->flags |= SDL_ASYNCBLIT;
       
   201 			}
       
   202 		}
       
   203 	}
       
   204 	return(retval);
       
   205 }
       
   206 
       
   207 /* We don't actually allow hardware surfaces other than the main one */
       
   208 int X11_AllocHWSurface(_THIS, SDL_Surface *surface)
       
   209 {
       
   210 	return(-1);
       
   211 }
       
   212 void X11_FreeHWSurface(_THIS, SDL_Surface *surface)
       
   213 {
       
   214 	return;
       
   215 }
       
   216 
       
   217 int X11_LockHWSurface(_THIS, SDL_Surface *surface)
       
   218 {
       
   219 	if ( (surface == SDL_VideoSurface) && blit_queued ) {
       
   220 		XSync(GFX_Display, False);
       
   221 		blit_queued = 0;
       
   222 	}
       
   223 	return(0);
       
   224 }
       
   225 void X11_UnlockHWSurface(_THIS, SDL_Surface *surface)
       
   226 {
       
   227 	return;
       
   228 }
       
   229 
       
   230 int X11_FlipHWSurface(_THIS, SDL_Surface *surface)
       
   231 {
       
   232 	return(0);
       
   233 }
       
   234 
       
   235 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
       
   236 {
       
   237 	int i;
       
   238 	
       
   239 	for (i = 0; i < numrects; ++i) {
       
   240 		if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */
       
   241 			continue;
       
   242 		}
       
   243 		XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
       
   244 			  rects[i].x, rects[i].y,
       
   245 			  rects[i].x, rects[i].y, rects[i].w, rects[i].h);
       
   246 	}
       
   247 	if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) {
       
   248 		XFlush(GFX_Display);
       
   249 		blit_queued = 1;
       
   250 	} else {
       
   251 		XSync(GFX_Display, False);
       
   252 	}
       
   253 }
       
   254 
       
   255 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects)
       
   256 {
       
   257 #ifndef NO_SHARED_MEMORY
       
   258 	int i;
       
   259 
       
   260 	for ( i=0; i<numrects; ++i ) {
       
   261 		if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */
       
   262 			continue;
       
   263 		}
       
   264 		XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
       
   265 				rects[i].x, rects[i].y,
       
   266 				rects[i].x, rects[i].y, rects[i].w, rects[i].h,
       
   267 									False);
       
   268 	}
       
   269 	if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) {
       
   270 		XFlush(GFX_Display);
       
   271 		blit_queued = 1;
       
   272 	} else {
       
   273 		XSync(GFX_Display, False);
       
   274 	}
       
   275 #endif /* ! NO_SHARED_MEMORY */
       
   276 }
       
   277 
       
   278 /* There's a problem with the automatic refreshing of the display.
       
   279    Even though the XVideo code uses the GFX_Display to update the
       
   280    video memory, it appears that updating the window asynchronously
       
   281    from a different thread will cause "blackouts" of the window.
       
   282    This is a sort of a hacked workaround for the problem.
       
   283 */
       
   284 static int enable_autorefresh = 1;
       
   285 
       
   286 void X11_DisableAutoRefresh(_THIS)
       
   287 {
       
   288 	--enable_autorefresh;
       
   289 }
       
   290 
       
   291 void X11_EnableAutoRefresh(_THIS)
       
   292 {
       
   293 	++enable_autorefresh;
       
   294 }
       
   295 
       
   296 void X11_RefreshDisplay(_THIS)
       
   297 {
       
   298 	/* Don't refresh a display that doesn't have an image (like GL)
       
   299 	   Instead, post an expose event so the application can refresh.
       
   300 	 */
       
   301 	if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) {
       
   302 		SDL_PrivateExpose();
       
   303 		return;
       
   304 	}
       
   305 #ifndef NO_SHARED_MEMORY
       
   306 	if ( this->UpdateRects == X11_MITSHMUpdate ) {
       
   307 		XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
       
   308 				0, 0, 0, 0, this->screen->w, this->screen->h,
       
   309 				False);
       
   310 	} else
       
   311 #endif /* ! NO_SHARED_MEMORY */
       
   312 	{
       
   313 		XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
       
   314 			  0, 0, 0, 0, this->screen->w, this->screen->h);
       
   315 	}
       
   316 	XSync(SDL_Display, False);
       
   317 }
       
   318