2004-11-10 18:41 Alexander Malmberg <alexander@malmberg.org>

* Source/x11/XWindowBuffer.m (test_xshm): New function.
	(test_xshm_error_handler): New function.
	(+windowBufferForWindow:depthInfo:): Move XShm detection code
	to test_xshm and use it to decide whether to use XShm or not.
	(+initialize): Move use_xshm setting code to test_xshm.
	(+_gotShmCompletion:): Don't warn if we can't find an XWindowBuffer
	for the event.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@20338 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Alexander Malmberg 2004-11-10 17:47:38 +00:00
parent e71ab02698
commit 34d406f5d9
2 changed files with 143 additions and 26 deletions

View file

@ -1,3 +1,13 @@
2004-11-10 18:41 Alexander Malmberg <alexander@malmberg.org>
* Source/x11/XWindowBuffer.m (test_xshm): New function.
(test_xshm_error_handler): New function.
(+windowBufferForWindow:depthInfo:): Move XShm detection code
to test_xshm and use it to decide whether to use XShm or not.
(+initialize): Move use_xshm setting code to test_xshm.
(+_gotShmCompletion:): Don't warn if we can't find an XWindowBuffer
for the event.
2004-11-10 Matt Rice <ratmice@yahoo.com>
* Source/x11/XGServerWindow.m (-iconSize): Implement new method.

View file

@ -41,8 +41,121 @@ static int num_window_buffers;
static int use_shape_hack = 0; /* this is an ugly hack :) */
static int use_xshm = 1;
static int did_test_xshm = 0;
static int use_xshm = 1;
static int num_xshm_test_errors = 0;
static NSString *xshm_warning
= @"Falling back to normal XImage:s (will be slower).";
static int test_xshm_error_handler(Display *d, XErrorEvent *ev)
{
num_xshm_test_errors++;
return 0;
}
static void test_xshm(Display *display, int drawing_depth)
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
did_test_xshm = 1;
if ([ud objectForKey: @"XWindowBufferUseXShm"])
use_xshm = [ud boolForKey: @"XWindowBufferUseXShm"];
/* If the user doesn't want XShm, there's no point in doing any further
testing. */
if (!use_xshm)
return;
/* This seems to return success if the X server understands the XShm
protocol, regardless of whether XShm can actually be used or not... */
if (!XShmQueryExtension(display))
{
NSLog(@"XShm not supported by X server.");
NSLog(xshm_warning);
use_xshm = 0;
return;
}
/* ... so we check that it actually works here. To do this, we need to
set up our own error handler (because the xlib calls never fail, they
just cause error events to be sent to us), explicitly synchronize
(or we wouldn't get to handle, and thus detect, the errors until much
later), and try actually creating a XShm image. Yuck. */
{
XImage *ximage;
XShmSegmentInfo shminfo;
int (*old_error_handler)();
old_error_handler = XSetErrorHandler(test_xshm_error_handler);
ximage = XShmCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
drawing_depth, ZPixmap, NULL, &shminfo,
1, 1);
if (!ximage || num_xshm_test_errors)
{
NSLog(@"XShm not supported, XShmCreateImage failed.");
goto no_xshm;
}
shminfo.shmid = shmget(IPC_PRIVATE,
64, /* We don't have exact bytes per row values here, but this
should be safe, and we'll probably get a full page anyway.
(And if it turns out not to be enough, the X server will notice
and give us errors, causing us to think that XShm isn't
supported.) */
IPC_CREAT | 0700);
if (shminfo.shmid == -1 || num_xshm_test_errors)
{
NSLog(@"XShm not supported, shmget() failed: %m.");
XDestroyImage(ximage);
goto no_xshm;
}
shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
if ((int)shminfo.shmaddr == -1 || num_xshm_test_errors)
{
NSLog(@"XShm not supported, shmat() failed: %m.");
XDestroyImage(ximage);
shmctl(shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
shminfo.readOnly = 0;
if (!XShmAttach(display, &shminfo) || num_xshm_test_errors)
{
NSLog(@"XShm not supported, XShmAttach() failed.");
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
XShmDetach(display, &shminfo);
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
/* Most of the time, all the above calls will return success despite
actually failing. To catch all errors generated by the calls before
returning, we synchronize here. */
XSync(display, False);
shmctl(shminfo.shmid, IPC_RMID, 0);
if (num_xshm_test_errors)
{
NSLog(@"XShm not supported.");
no_xshm:
NSLog(xshm_warning);
use_xshm = 0;
}
XSetErrorHandler(old_error_handler);
}
}
@implementation XWindowBuffer
@ -149,20 +262,13 @@ static int use_xshm = 1;
if (wi->window->xframe.size.width * wi->window->xframe.size.height < 4096)
goto no_xshm;
#define WARN @" Falling back to normal XImage:s (will be slower)."
if (!did_test_xshm)
test_xshm(wi->display, aDI->drawing_depth);
if (!use_xshm)
goto no_xshm;
/* Use XShm if possible, else fall back to normal XImage:s */
if (!XShmQueryExtension(wi->display))
{
static BOOL xshm_warned = NO;
if (!xshm_warned)
NSLog(@"XShm not supported." WARN);
xshm_warned = YES;
goto no_xshm;
}
wi->use_shm = 1;
wi->ximage = XShmCreateImage(wi->display,
DefaultVisual(wi->display, DefaultScreen(wi->display)),
@ -171,7 +277,8 @@ static BOOL xshm_warned = NO;
wi->window->xframe.size.height);
if (!wi->ximage)
{
NSLog(@"Warning: XShmCreateImage failed!" WARN);
NSLog(@"Warning: XShmCreateImage failed!");
NSLog(xshm_warning);
goto no_xshm;
}
wi->shminfo.shmid = shmget(IPC_PRIVATE,
@ -180,7 +287,8 @@ static BOOL xshm_warned = NO;
if (wi->shminfo.shmid == -1)
{
NSLog(@"Warning: shmget() failed: %m." WARN);
NSLog(@"Warning: shmget() failed: %m.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
goto no_xshm;
}
@ -188,7 +296,8 @@ static BOOL xshm_warned = NO;
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
if ((int)wi->shminfo.shmaddr == -1)
{
NSLog(@"Warning: shmat() failed: %m." WARN);
NSLog(@"Warning: shmat() failed: %m.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
@ -197,7 +306,8 @@ static BOOL xshm_warned = NO;
wi->shminfo.readOnly = 0;
if (!XShmAttach(wi->display, &wi->shminfo))
{
NSLog(@"Warning: XShmAttach() failed." WARN);
NSLog(@"Warning: XShmAttach() failed.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
shmdt(wi->shminfo.shmaddr);
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
@ -210,20 +320,21 @@ static BOOL xshm_warned = NO;
dragged across a window. */
/* TODO: we still get and handle expose events, although we don't
need to. */
wi->pixmap=XShmCreatePixmap(wi->display,wi->drawable,
wi->ximage->data,&wi->shminfo,
wi->window->xframe.size.width,
wi->window->xframe.size.height,
aDI->drawing_depth);
wi->pixmap = XShmCreatePixmap(wi->display, wi->drawable,
wi->ximage->data, &wi->shminfo,
wi->window->xframe.size.width,
wi->window->xframe.size.height,
aDI->drawing_depth);
if (wi->pixmap) /* TODO: this doesn't work */
{
XSetWindowBackgroundPixmap(wi->display,wi->window->ident,wi->pixmap);
XSetWindowBackgroundPixmap(wi->display, wi->window->ident,
wi->pixmap);
}
/* On some systems (eg. freebsd), X can't attach to the shared segment
if it's marked for destruction, so we make sure it's attached before
marking it. */
XSync(wi->display,False);
XSync(wi->display, False);
/* Mark the segment as destroyed now. Since we're attached, it won't
actually be destroyed, but if we crashed before doing this, it wouldn't
@ -541,9 +652,6 @@ static int warn = 0;
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
use_shape_hack = [ud boolForKey: @"XWindowBuffer-shape-hack"];
if ([ud objectForKey: @"XWindowBufferUseXShm"])
use_xshm = [ud boolForKey: @"XWindowBufferUseXShm"];
}
@ -558,7 +666,6 @@ static int warn = 0;
return;
}
}
NSLog(@"Warning: gotShmCompletion: couldn't find XWindowBuffer for drawable");
}
@end