aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/video/x11/SDL_x11image.c
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/x11/SDL_x11image.c')
-rw-r--r--distrib/sdl-1.2.15/src/video/x11/SDL_x11image.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/x11/SDL_x11image.c b/distrib/sdl-1.2.15/src/video/x11/SDL_x11image.c
new file mode 100644
index 0000000..464bc37
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/x11/SDL_x11image.c
@@ -0,0 +1,316 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 */
+ {
+ screen->pixels = SDL_malloc(screen->h*screen->pitch);
+ if ( screen->pixels == NULL ) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+ 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);
+}
+