# HG changeset patch # User Sam Lantinga # Date 1296871520 28800 # Node ID 073b86030262bd0df06819cad400789c41c9ec70 # Parent d2652aafafbb8087a775b928c4d0e60e41da454b Added the X11 framebuffer implementation. Simple! :) diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11framebuffer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11framebuffer.c Fri Feb 04 18:05:20 2011 -0800 @@ -0,0 +1,214 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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 "SDL_x11video.h" +#include "SDL_x11framebuffer.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 SDL_bool have_mitshm(void) +{ + /* Only use shared memory on local X servers */ + if ( (SDL_strncmp(XDisplayName(NULL), ":", 1) == 0) || + (SDL_strncmp(XDisplayName(NULL), "unix:", 5) == 0) ) { + return SDL_X11_HAVE_SHM; + } + return SDL_FALSE; +} + +#endif /* !NO_SHARED_MEMORY */ + +int +X11_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, + void ** pixels, int *pitch) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + XGCValues gcv; + XVisualInfo vinfo; + + /* Free the old framebuffer surface */ + X11_DestroyWindowFramebuffer(_this, window); + + /* Create the graphics context for drawing */ + gcv.graphics_exposures = False; + data->gc = XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv); + if (!data->gc) { + SDL_SetError("Couldn't create graphics context"); + return -1; + } + + /* Find out the pixel format and depth */ + if (X11_GetVisualInfoFromVisual(display, data->visual, &vinfo) < 0) { + SDL_SetError("Couldn't get window visual information"); + return -1; + } + + *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo); + if (*format == SDL_PIXELFORMAT_UNKNOWN) { + SDL_SetError("Unknown window pixel format"); + return -1; + } + + /* Calculate pitch */ + *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3); + + /* Create the actual image */ +#ifndef NO_SHARED_MEMORY + if (have_mitshm()) { + XShmSegmentInfo *shminfo = &data->shminfo; + + shminfo->shmid = shmget(IPC_PRIVATE, window->h*(*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(display, shminfo); + XSync(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) { + data->ximage = XShmCreateImage(display, data->visual, + vinfo.depth, ZPixmap, + shminfo->shmaddr, shminfo, + window->w, window->h); + if (!data->ximage) { + XShmDetach(display, shminfo); + XSync(display, False); + shmdt(shminfo->shmaddr); + } else { + /* Done! */ + data->use_mitshm = SDL_TRUE; + *pixels = shminfo->shmaddr; + return 0; + } + } + } +#endif /* not NO_SHARED_MEMORY */ + + *pixels = SDL_malloc(window->h*(*pitch)); + if (*pixels == NULL) { + SDL_OutOfMemory(); + return -1; + } + + data->ximage = XCreateImage(display, data->visual, + vinfo.depth, ZPixmap, 0, (char *)(*pixels), + window->w, window->h, 32, 0); + if (!data->ximage) { + SDL_free(*pixels); + SDL_SetError("Couldn't create XImage"); + return -1; + } + return 0; +} + +int +X11_UpdateWindowFramebuffer(_THIS, SDL_Window * window, + int numrects, SDL_Rect * rects) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + int i; + SDL_Rect *rect; + +#ifndef NO_SHARED_MEMORY + if (data->use_mitshm) { + for (i = 0; i < numrects; ++i) { + rect = &rects[i]; + + if (rect->w == 0 || rect->h == 0) { /* Clipped? */ + continue; + } + XShmPutImage(display, data->xwindow, data->gc, data->ximage, + rect->x, rect->y, + rect->x, rect->y, rect->w, rect->h, False); + } + } + else +#endif /* !NO_SHARED_MEMORY */ + { + for (i = 0; i < numrects; ++i) { + rect = &rects[i]; + + if (rect->w == 0 || rect->h == 0) { /* Clipped? */ + continue; + } + XPutImage(display, data->xwindow, data->gc, data->ximage, + rect->x, rect->y, + rect->x, rect->y, rect->w, rect->h); + } + } + XSync(display, False); +} + +void +X11_DestroyWindowFramebuffer(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + if (data->ximage) { + XDestroyImage(data->ximage); + +#ifndef NO_SHARED_MEMORY + if (data->use_mitshm) { + XShmDetach(display, &data->shminfo); + XSync(display, False); + shmdt(data->shminfo.shmaddr); + data->use_mitshm = SDL_FALSE; + } +#endif /* !NO_SHARED_MEMORY */ + + data->ximage = NULL; + } + if (data->gc) { + XFreeGC(display, data->gc); + data->gc = NULL; + } +} + +/* vi: set ts=4 sw=4 expandtab: */ diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11framebuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11framebuffer.h Fri Feb 04 18:05:20 2011 -0800 @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 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" + + +extern int X11_CreateWindowFramebuffer(_THIS, SDL_Window * window, + Uint32 * format, + void ** pixels, int *pitch); +extern int X11_UpdateWindowFramebuffer(_THIS, SDL_Window * window, + int numrects, SDL_Rect * rects); +extern void X11_DestroyWindowFramebuffer(_THIS, SDL_Window * window); + +/* vi: set ts=4 sw=4 expandtab: */ diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11modes.c --- a/src/video/x11/SDL_x11modes.c Fri Feb 04 16:55:50 2011 -0800 +++ b/src/video/x11/SDL_x11modes.c Fri Feb 04 18:05:20 2011 -0800 @@ -57,7 +57,23 @@ return -1; } -static Uint32 +int +X11_GetVisualInfoFromVisual(Display * display, Visual * visual, XVisualInfo * vinfo) +{ + XVisualInfo *vi; + int nvis; + + vinfo->visualid = XVisualIDFromVisual(visual); + vi = XGetVisualInfo(display, VisualIDMask, vinfo, &nvis); + if (vi) { + *vinfo = *vi; + XFree(vi); + return 0; + } + return -1; +} + +Uint32 X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo) { if (vinfo->class == DirectColor || vinfo->class == TrueColor) { diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11modes.h --- a/src/video/x11/SDL_x11modes.h Fri Feb 04 16:55:50 2011 -0800 +++ b/src/video/x11/SDL_x11modes.h Fri Feb 04 18:05:20 2011 -0800 @@ -59,6 +59,12 @@ extern int X11_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); extern void X11_QuitModes(_THIS); +/* Some utility functions for working with visuals */ +extern int X11_GetVisualInfoFromVisual(Display * display, Visual * visual, + XVisualInfo * vinfo); +extern Uint32 X11_GetPixelFormatFromVisualInfo(Display * display, + XVisualInfo * vinfo); + #endif /* _SDL_x11modes_h */ /* vi: set ts=4 sw=4 expandtab: */ diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11video.c --- a/src/video/x11/SDL_x11video.c Fri Feb 04 16:55:50 2011 -0800 +++ b/src/video/x11/SDL_x11video.c Fri Feb 04 18:05:20 2011 -0800 @@ -29,6 +29,7 @@ #include "../SDL_pixels_c.h" #include "SDL_x11video.h" +#include "SDL_x11framebuffer.h" #include "SDL_x11shape.h" #include "SDL_x11touch.h" @@ -204,10 +205,15 @@ device->RestoreWindow = X11_RestoreWindow; device->SetWindowGrab = X11_SetWindowGrab; device->DestroyWindow = X11_DestroyWindow; + device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer; + device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer; + device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer; device->GetWindowWMInfo = X11_GetWindowWMInfo; + device->shape_driver.CreateShaper = X11_CreateShaper; device->shape_driver.SetWindowShape = X11_SetWindowShape; device->shape_driver.ResizeWindowShape = X11_ResizeWindowShape; + #if SDL_VIDEO_OPENGL_GLX device->GL_LoadLibrary = X11_GL_LoadLibrary; device->GL_GetProcAddress = X11_GL_GetProcAddress; diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11window.c --- a/src/video/x11/SDL_x11window.c Fri Feb 04 16:55:50 2011 -0800 +++ b/src/video/x11/SDL_x11window.c Fri Feb 04 18:05:20 2011 -0800 @@ -176,6 +176,7 @@ } else { window->flags &= ~SDL_WINDOW_SHOWN; } + data->visual = attrib.visual; } { diff -r d2652aafafbb -r 073b86030262 src/video/x11/SDL_x11window.h --- a/src/video/x11/SDL_x11window.h Fri Feb 04 16:55:50 2011 -0800 +++ b/src/video/x11/SDL_x11window.h Fri Feb 04 18:05:20 2011 -0800 @@ -28,6 +28,14 @@ { SDL_Window *window; Window xwindow; + Visual *visual; +#ifndef NO_SHARED_MEMORY + /* MIT shared memory extension information */ + SDL_bool use_mitshm; + XShmSegmentInfo shminfo; +#endif + XImage *ximage; + GC gc; XIC ic; SDL_bool created; struct SDL_VideoData *videodata;