|
@@ -131,6 +131,18 @@ static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] =
|
|
|
{ 235, 235, 235 }, // SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
|
|
|
};
|
|
|
|
|
|
+static int g_shm_error;
|
|
|
+static int (*g_old_error_handler)(Display *, XErrorEvent *) = NULL;
|
|
|
+
|
|
|
+static int X11Toolkit_SharedMemoryErrorHandler(Display *d, XErrorEvent *e)
|
|
|
+{
|
|
|
+ if (e->error_code == BadAccess || e->error_code == BadRequest) {
|
|
|
+ g_shm_error = True;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return g_old_error_handler(d, e);
|
|
|
+}
|
|
|
+
|
|
|
int X11Toolkit_SettingsGetInt(XSettingsClient *client, const char *key, int fallback_value) {
|
|
|
XSettingsSetting *setting = NULL;
|
|
|
int res = fallback_value;
|
|
@@ -297,7 +309,62 @@ static void X11Toolkit_SettingsNotify(const char *name, XSettingsAction action,
|
|
|
}
|
|
|
|
|
|
X11_XFreePixmap(window->display, window->drawable);
|
|
|
- window->drawable = X11_XCreatePixmap(window->display, window->window, window->pixmap_width, window->pixmap_height, window->depth);
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (window->shm) {
|
|
|
+ X11_XShmDetach(window->display, &window->shm_info);
|
|
|
+ XDestroyImage(window->image);
|
|
|
+ shmdt(window->shm_info.shmaddr);
|
|
|
+
|
|
|
+ window->image = X11_XShmCreateImage(window->display, window->visual, window->depth, ZPixmap, NULL, &window->shm_info, window->pixmap_width, window->pixmap_height);
|
|
|
+ if (window->image) {
|
|
|
+ window->shm_bytes_per_line = window->image->bytes_per_line;
|
|
|
+ window->shm_info.shmid = shmget(IPC_PRIVATE, window->image->bytes_per_line * window->image->height, IPC_CREAT | 0777);
|
|
|
+ if (window->shm_info.shmid < 0) {
|
|
|
+ XDestroyImage(window->image);
|
|
|
+ window->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ window->shm_info.readOnly = False;
|
|
|
+ window->shm_info.shmaddr = window->image->data = (char *)shmat(window->shm_info.shmid, 0, 0);
|
|
|
+ if (((signed char *)window->shm_info.shmaddr) == (signed char *)-1) {
|
|
|
+ XDestroyImage(window->image);
|
|
|
+ window->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_shm_error = False;
|
|
|
+ g_old_error_handler = X11_XSetErrorHandler(X11Toolkit_SharedMemoryErrorHandler);
|
|
|
+ X11_XShmAttach(window->display, &window->shm_info);
|
|
|
+ X11_XSync(window->display, False);
|
|
|
+ X11_XSetErrorHandler(g_old_error_handler);
|
|
|
+ if (g_shm_error) {
|
|
|
+ XDestroyImage(window->image);
|
|
|
+ shmdt(window->shm_info.shmaddr);
|
|
|
+ shmctl(window->shm_info.shmid, IPC_RMID, 0);
|
|
|
+ window->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (window->shm_pixmap) {
|
|
|
+ window->drawable = X11_XShmCreatePixmap(window->display, window->window, window->shm_info.shmaddr, &window->shm_info, window->pixmap_width, window->pixmap_height, window->depth);
|
|
|
+ if (window->drawable == None) {
|
|
|
+ window->shm_pixmap = False;
|
|
|
+ } else {
|
|
|
+ XDestroyImage(window->image);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ shmctl(window->shm_info.shmid, IPC_RMID, 0);
|
|
|
+ } else {
|
|
|
+ window->shm = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (!window->shm_pixmap) {
|
|
|
+ window->drawable = X11_XCreatePixmap(window->display, window->window, window->pixmap_width, window->pixmap_height, window->depth);
|
|
|
+ }
|
|
|
+#else
|
|
|
+ window->drawable = X11_XCreatePixmap(window->display, window->window, window->pixmap_width, window->pixmap_height, window->depth);
|
|
|
+#endif
|
|
|
} else {
|
|
|
if (!dbe_already_setup) {
|
|
|
X11_XFreePixmap(window->display, window->drawable);
|
|
@@ -485,6 +552,22 @@ SDL_ToolkitWindowX11 *X11Toolkit_CreateWindowStruct(SDL_Window *parent, SDL_Tool
|
|
|
window->xrandr = X11_XRRQueryExtension(window->display, &xrandr_event_base, &xrandr_error_base);
|
|
|
#endif
|
|
|
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ window->shm_pixmap = False;
|
|
|
+ window->shm = X11_XShmQueryExtension(window->display) ? SDL_X11_HAVE_SHM : false;
|
|
|
+ if (window->shm) {
|
|
|
+ int major;
|
|
|
+ int minor;
|
|
|
+
|
|
|
+ X11_XShmQueryVersion(window->display, &major, &minor, &window->shm_pixmap);
|
|
|
+ if (window->shm_pixmap) {
|
|
|
+ if (X11_XShmPixmapFormat(window->display) != ZPixmap) {
|
|
|
+ window->shm_pixmap = False;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
/* Scale/Xsettings */
|
|
|
window->pixmap = false;
|
|
|
window->xsettings_first_time = true;
|
|
@@ -906,7 +989,59 @@ bool X11Toolkit_CreateWindowRes(SDL_ToolkitWindowX11 *data, int w, int h, int cx
|
|
|
#endif
|
|
|
|
|
|
if (data->pixmap) {
|
|
|
- data->drawable = X11_XCreatePixmap(display, data->window, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (!data->shm_pixmap) {
|
|
|
+ data->drawable = X11_XCreatePixmap(display, data->window, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+ }
|
|
|
+#else
|
|
|
+ data->drawable = X11_XCreatePixmap(display, data->window, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+#endif
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (data->shm) {
|
|
|
+ data->image = X11_XShmCreateImage(display, data->visual, data->depth, ZPixmap, NULL, &data->shm_info, data->pixmap_width, data->pixmap_height);
|
|
|
+ if (data->image) {
|
|
|
+ data->shm_bytes_per_line = data->image->bytes_per_line;
|
|
|
+
|
|
|
+ data->shm_info.shmid = shmget(IPC_PRIVATE, data->image->bytes_per_line * data->image->height, IPC_CREAT | 0777);
|
|
|
+ if (data->shm_info.shmid < 0) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ data->shm_info.readOnly = False;
|
|
|
+ data->shm_info.shmaddr = data->image->data = (char *)shmat(data->shm_info.shmid, 0, 0);
|
|
|
+ if (((signed char *)data->shm_info.shmaddr) == (signed char *)-1) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_shm_error = False;
|
|
|
+ g_old_error_handler = X11_XSetErrorHandler(X11Toolkit_SharedMemoryErrorHandler);
|
|
|
+ X11_XShmAttach(display, &data->shm_info);
|
|
|
+ X11_XSync(display, False);
|
|
|
+ X11_XSetErrorHandler(g_old_error_handler);
|
|
|
+ if (g_shm_error) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ shmdt(data->shm_info.shmaddr);
|
|
|
+ shmctl(data->shm_info.shmid, IPC_RMID, 0);
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data->shm_pixmap) {
|
|
|
+ data->drawable = X11_XShmCreatePixmap(display, data->window, data->shm_info.shmaddr, &data->shm_info, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+ if (data->drawable == None) {
|
|
|
+ data->shm_pixmap = False;
|
|
|
+ } else {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ shmctl(data->shm_info.shmid, IPC_RMID, 0);
|
|
|
+ } else {
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
SDL_zero(ctx_vals);
|
|
@@ -941,7 +1076,8 @@ bool X11Toolkit_CreateWindowRes(SDL_ToolkitWindowX11 *data, int w, int h, int cx
|
|
|
}
|
|
|
|
|
|
static void X11Toolkit_DrawWindow(SDL_ToolkitWindowX11 *data) {
|
|
|
- int i;
|
|
|
+ SDL_Rect rect;
|
|
|
+ int i;
|
|
|
|
|
|
#ifdef SDL_VIDEO_DRIVER_X11_XDBE
|
|
|
if (SDL_X11_HAVE_XDBE && data->xdbe && !data->pixmap) {
|
|
@@ -978,24 +1114,39 @@ static void X11Toolkit_DrawWindow(SDL_ToolkitWindowX11 *data) {
|
|
|
#endif
|
|
|
|
|
|
if (data->pixmap) {
|
|
|
- XImage *pixmap_image;
|
|
|
- XImage *put_image;
|
|
|
- SDL_Surface *pixmap_surface;
|
|
|
- SDL_Surface *put_surface;
|
|
|
-
|
|
|
- /* FIXME: Implement SHM transport? */
|
|
|
- pixmap_image = X11_XGetImage(data->display, data->drawable, 0, 0 , data->pixmap_width, data->pixmap_height, AllPlanes, ZPixmap);
|
|
|
- pixmap_surface = SDL_CreateSurfaceFrom(data->pixmap_width, data->pixmap_height, X11_GetPixelFormatFromVisualInfo(data->display, &data->vi), pixmap_image->data, pixmap_image->bytes_per_line);
|
|
|
- put_surface = SDL_ScaleSurface(pixmap_surface, data->window_width, data->window_height, SDL_SCALEMODE_LINEAR);
|
|
|
- put_image = X11_XCreateImage(data->display, data->visual, data->vi.depth, ZPixmap, 0, put_surface->pixels, data->window_width, data->window_height, 32, put_surface->pitch);
|
|
|
- X11_XPutImage(data->display, data->window, data->ctx, put_image, 0, 0, 0, 0, data->window_width, data->window_height);
|
|
|
-
|
|
|
- XDestroyImage(pixmap_image);
|
|
|
- /* Needed because XDestroyImage results in a double-free otherwise */
|
|
|
- put_image->data = NULL;
|
|
|
- XDestroyImage(put_image);
|
|
|
- SDL_DestroySurface(pixmap_surface);
|
|
|
- SDL_DestroySurface(put_surface);
|
|
|
+ SDL_Surface *scale_surface;
|
|
|
+
|
|
|
+ rect.x = rect.y = 0;
|
|
|
+ rect.w = data->window_width;
|
|
|
+ rect.h = data->window_height;
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (data->shm) {
|
|
|
+ if (data->shm_pixmap) {
|
|
|
+ X11_XFlush(data->display);
|
|
|
+ X11_XSync(data->display, false);
|
|
|
+ scale_surface = SDL_CreateSurfaceFrom(data->pixmap_width, data->pixmap_height, X11_GetPixelFormatFromVisualInfo(data->display, &data->vi), data->shm_info.shmaddr, data->shm_bytes_per_line);
|
|
|
+ SDL_BlitSurfaceScaled(scale_surface, NULL, scale_surface, &rect, SDL_SCALEMODE_LINEAR);
|
|
|
+ SDL_DestroySurface(scale_surface);
|
|
|
+ X11_XCopyArea(data->display, data->drawable, data->window, data->ctx, 0, 0, data->window_width, data->window_height, 0, 0);
|
|
|
+ } else {
|
|
|
+ X11_XShmGetImage(data->display, data->drawable, data->image, 0, 0, AllPlanes);
|
|
|
+ scale_surface = SDL_CreateSurfaceFrom(data->pixmap_width, data->pixmap_height, X11_GetPixelFormatFromVisualInfo(data->display, &data->vi), data->image->data, data->image->bytes_per_line);
|
|
|
+ SDL_BlitSurfaceScaled(scale_surface, NULL, scale_surface, &rect, SDL_SCALEMODE_LINEAR);
|
|
|
+ X11_XShmPutImage(data->display, data->window, data->ctx, data->image, 0, 0, 0, 0, data->window_width, data->window_height, False);
|
|
|
+ }
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ XImage *image;
|
|
|
+
|
|
|
+ image = X11_XGetImage(data->display, data->drawable, 0, 0 , data->pixmap_width, data->pixmap_height, AllPlanes, ZPixmap);
|
|
|
+ scale_surface = SDL_CreateSurfaceFrom(data->pixmap_width, data->pixmap_height, X11_GetPixelFormatFromVisualInfo(data->display, &data->vi), image->data, image->bytes_per_line);
|
|
|
+ SDL_BlitSurfaceScaled(scale_surface, NULL, scale_surface, &rect, SDL_SCALEMODE_LINEAR);
|
|
|
+ X11_XPutImage(data->display, data->window, data->ctx, image, 0, 0, 0, 0, data->window_width, data->window_height);
|
|
|
+
|
|
|
+ XDestroyImage(image);
|
|
|
+ SDL_DestroySurface(scale_surface);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
X11_XFlush(data->display);
|
|
@@ -1248,7 +1399,62 @@ void X11Toolkit_ResizeWindow(SDL_ToolkitWindowX11 *data, int w, int h) {
|
|
|
data->pixmap_width = w;
|
|
|
data->pixmap_height = h;
|
|
|
X11_XFreePixmap(data->display, data->drawable);
|
|
|
- data->drawable = X11_XCreatePixmap(data->display, data->window, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (!data->shm_pixmap) {
|
|
|
+ data->drawable = X11_XCreatePixmap(data->display, data->window, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+ }
|
|
|
+#else
|
|
|
+ data->drawable = X11_XCreatePixmap(data->display, data->window, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+#endif
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (data->shm) {
|
|
|
+ X11_XShmDetach(data->display, &data->shm_info);
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ shmdt(data->shm_info.shmaddr);
|
|
|
+
|
|
|
+ data->image = X11_XShmCreateImage(data->display, data->visual, data->depth, ZPixmap, NULL, &data->shm_info, data->pixmap_width, data->pixmap_height);
|
|
|
+ if (data->image) {
|
|
|
+ data->shm_bytes_per_line = data->image->bytes_per_line;
|
|
|
+ data->shm_info.shmid = shmget(IPC_PRIVATE, data->image->bytes_per_line * data->image->height, IPC_CREAT | 0777);
|
|
|
+ if (data->shm_info.shmid < 0) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ data->shm_info.readOnly = False;
|
|
|
+ data->shm_info.shmaddr = data->image->data = (char *)shmat(data->shm_info.shmid, 0, 0);
|
|
|
+ if (((signed char *)data->shm_info.shmaddr) == (signed char *)-1) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_shm_error = False;
|
|
|
+ g_old_error_handler = X11_XSetErrorHandler(X11Toolkit_SharedMemoryErrorHandler);
|
|
|
+ X11_XShmAttach(data->display, &data->shm_info);
|
|
|
+ X11_XSync(data->display, False);
|
|
|
+ X11_XSetErrorHandler(g_old_error_handler);
|
|
|
+ if (g_shm_error) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ shmdt(data->shm_info.shmaddr);
|
|
|
+ shmctl(data->shm_info.shmid, IPC_RMID, 0);
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data->shm_pixmap) {
|
|
|
+ data->drawable = X11_XShmCreatePixmap(data->display, data->window, data->shm_info.shmaddr, &data->shm_info, data->pixmap_width, data->pixmap_height, data->depth);
|
|
|
+ if (data->drawable == None) {
|
|
|
+ data->shm_pixmap = False;
|
|
|
+ } else {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ shmctl(data->shm_info.shmid, IPC_RMID, 0);
|
|
|
+ } else {
|
|
|
+ data->shm = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
X11_XResizeWindow(data->display, data->window, data->window_width, data->window_height);
|
|
@@ -1677,6 +1883,16 @@ void X11Toolkit_DestroyWindow(SDL_ToolkitWindowX11 *data) {
|
|
|
if (data->pixmap) {
|
|
|
X11_XFreePixmap(data->display, data->drawable);
|
|
|
}
|
|
|
+
|
|
|
+#ifndef NO_SHARED_MEMORY
|
|
|
+ if (data->pixmap && data->shm) {
|
|
|
+ X11_XShmDetach(data->display, &data->shm_info);
|
|
|
+ if (!data->shm_pixmap) {
|
|
|
+ XDestroyImage(data->image);
|
|
|
+ }
|
|
|
+ shmdt(data->shm_info.shmaddr);
|
|
|
+ }
|
|
|
+#endif
|
|
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
if (data->font_set) {
|