SDL  2.0
SDL_x11framebuffer.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_X11
24 
25 #include "SDL_x11video.h"
26 #include "SDL_x11framebuffer.h"
27 
28 
29 #ifndef NO_SHARED_MEMORY
30 
31 /* Shared memory error handler routine */
32 static int shm_error;
33 static int (*X_handler)(Display *, XErrorEvent *) = NULL;
34 static int shm_errhandler(Display *d, XErrorEvent *e)
35 {
36  if ( e->error_code == BadAccess ) {
37  shm_error = True;
38  return(0);
39  } else
40  return(X_handler(d,e));
41 }
42 
43 static SDL_bool have_mitshm(void)
44 {
45  /* Only use shared memory on local X servers */
46  if ( (SDL_strncmp(X11_XDisplayName(NULL), ":", 1) == 0) ||
47  (SDL_strncmp(X11_XDisplayName(NULL), "unix:", 5) == 0) ) {
48  return SDL_X11_HAVE_SHM;
49  }
50  return SDL_FALSE;
51 }
52 
53 #endif /* !NO_SHARED_MEMORY */
54 
55 int
57  void ** pixels, int *pitch)
58 {
60  Display *display = data->videodata->display;
61  XGCValues gcv;
62  XVisualInfo vinfo;
63 
64  /* Free the old framebuffer surface */
66 
67  /* Create the graphics context for drawing */
68  gcv.graphics_exposures = False;
69  data->gc = X11_XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv);
70  if (!data->gc) {
71  return SDL_SetError("Couldn't create graphics context");
72  }
73 
74  /* Find out the pixel format and depth */
75  if (X11_GetVisualInfoFromVisual(display, data->visual, &vinfo) < 0) {
76  return SDL_SetError("Couldn't get window visual information");
77  }
78 
79  *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo);
80  if (*format == SDL_PIXELFORMAT_UNKNOWN) {
81  return SDL_SetError("Unknown window pixel format");
82  }
83 
84  /* Calculate pitch */
85  *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
86 
87  /* Create the actual image */
88 #ifndef NO_SHARED_MEMORY
89  if (have_mitshm()) {
90  XShmSegmentInfo *shminfo = &data->shminfo;
91 
92  shminfo->shmid = shmget(IPC_PRIVATE, window->h*(*pitch), IPC_CREAT | 0777);
93  if ( shminfo->shmid >= 0 ) {
94  shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0);
95  shminfo->readOnly = False;
96  if ( shminfo->shmaddr != (char *)-1 ) {
97  shm_error = False;
98  X_handler = X11_XSetErrorHandler(shm_errhandler);
99  X11_XShmAttach(display, shminfo);
100  X11_XSync(display, False);
101  X11_XSetErrorHandler(X_handler);
102  if ( shm_error )
103  shmdt(shminfo->shmaddr);
104  } else {
105  shm_error = True;
106  }
107  shmctl(shminfo->shmid, IPC_RMID, NULL);
108  } else {
109  shm_error = True;
110  }
111  if (!shm_error) {
112  data->ximage = X11_XShmCreateImage(display, data->visual,
113  vinfo.depth, ZPixmap,
114  shminfo->shmaddr, shminfo,
115  window->w, window->h);
116  if (!data->ximage) {
117  X11_XShmDetach(display, shminfo);
118  X11_XSync(display, False);
119  shmdt(shminfo->shmaddr);
120  } else {
121  /* Done! */
122  data->use_mitshm = SDL_TRUE;
123  *pixels = shminfo->shmaddr;
124  return 0;
125  }
126  }
127  }
128 #endif /* not NO_SHARED_MEMORY */
129 
130  *pixels = SDL_malloc(window->h*(*pitch));
131  if (*pixels == NULL) {
132  return SDL_OutOfMemory();
133  }
134 
135  data->ximage = X11_XCreateImage(display, data->visual,
136  vinfo.depth, ZPixmap, 0, (char *)(*pixels),
137  window->w, window->h, 32, 0);
138  if (!data->ximage) {
139  SDL_free(*pixels);
140  return SDL_SetError("Couldn't create XImage");
141  }
142  return 0;
143 }
144 
145 int
147  int numrects)
148 {
149  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
150  Display *display = data->videodata->display;
151  int i;
152  int x, y, w ,h;
153 #ifndef NO_SHARED_MEMORY
154  if (data->use_mitshm) {
155  for (i = 0; i < numrects; ++i) {
156  x = rects[i].x;
157  y = rects[i].y;
158  w = rects[i].w;
159  h = rects[i].h;
160 
161  if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0) {
162  /* Clipped? */
163  continue;
164  }
165  if (x < 0)
166  {
167  x += w;
168  w += rects[i].x;
169  }
170  if (y < 0)
171  {
172  y += h;
173  h += rects[i].y;
174  }
175  if (x + w > window->w)
176  w = window->w - x;
177  if (y + h > window->h)
178  h = window->h - y;
179 
180  X11_XShmPutImage(display, data->xwindow, data->gc, data->ximage,
181  x, y, x, y, w, h, False);
182  }
183  }
184  else
185 #endif /* !NO_SHARED_MEMORY */
186  {
187  for (i = 0; i < numrects; ++i) {
188  x = rects[i].x;
189  y = rects[i].y;
190  w = rects[i].w;
191  h = rects[i].h;
192 
193  if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0) {
194  /* Clipped? */
195  continue;
196  }
197  if (x < 0)
198  {
199  x += w;
200  w += rects[i].x;
201  }
202  if (y < 0)
203  {
204  y += h;
205  h += rects[i].y;
206  }
207  if (x + w > window->w)
208  w = window->w - x;
209  if (y + h > window->h)
210  h = window->h - y;
211 
212  X11_XPutImage(display, data->xwindow, data->gc, data->ximage,
213  x, y, x, y, w, h);
214  }
215  }
216 
217  X11_XSync(display, False);
218 
219  return 0;
220 }
221 
222 void
224 {
225  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
226  Display *display;
227 
228  if (!data) {
229  /* The window wasn't fully initialized */
230  return;
231  }
232 
233  display = data->videodata->display;
234 
235  if (data->ximage) {
236  XDestroyImage(data->ximage);
237 
238 #ifndef NO_SHARED_MEMORY
239  if (data->use_mitshm) {
240  X11_XShmDetach(display, &data->shminfo);
241  X11_XSync(display, False);
242  shmdt(data->shminfo.shmaddr);
243  data->use_mitshm = SDL_FALSE;
244  }
245 #endif /* !NO_SHARED_MEMORY */
246 
247  data->ximage = NULL;
248  }
249  if (data->gc) {
250  X11_XFreeGC(display, data->gc);
251  data->gc = NULL;
252  }
253 }
254 
255 #endif /* SDL_VIDEO_DRIVER_X11 */
256 
257 /* vi: set ts=4 sw=4 expandtab: */
Uint32 X11_GetPixelFormatFromVisualInfo(Display *display, XVisualInfo *vinfo)
XShmSegmentInfo shminfo
Definition: SDL_x11window.h:53
SDL_bool use_mitshm
Definition: SDL_x11window.h:52
int X11_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
Visual * visual
Definition: SDL_x11window.h:48
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
struct wl_display * display
GLfloat GLfloat GLfloat GLfloat h
XImage * ximage
Definition: SDL_x11window.h:55
int X11_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects)
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
uint32_t Uint32
Definition: SDL_stdinc.h:181
void X11_DestroyWindowFramebuffer(_THIS, SDL_Window *window)
#define SDL_strncmp
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
#define _THIS
struct SDL_VideoData * videodata
#define SDL_free
GLubyte GLubyte GLubyte GLubyte w
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h:66
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
int w
Definition: SDL_rect.h:67
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
#define SDL_SetError
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
int h
Definition: SDL_rect.h:67
The type used to identify a window.
Definition: SDL_sysvideo.h:73
#define SDL_malloc
void * driverdata
Definition: SDL_sysvideo.h:111
EGLSurface EGLint * rects
Definition: eglext.h:282
int X11_GetVisualInfoFromVisual(Display *display, Visual *visual, XVisualInfo *vinfo)
int y
Definition: SDL_rect.h:66
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64