mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 15:31:14 +00:00
Improve error handling when creating shared memory buffers. Don't use shared memory for windows that are (probably) image caches. Don't crash in -needsAlpha if we don't have valid data.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@14536 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
dd75dce3bd
commit
bec53bc686
2 changed files with 98 additions and 51 deletions
|
@ -1,3 +1,11 @@
|
|||
2002-09-24 13:22 Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
* Source/x11/XWindowBuffer.m (+windowBufferForWindow:depthInfo:):
|
||||
Detect and handle errors properly. Only use shared memory for
|
||||
reasonably large windows.
|
||||
|
||||
(-needsAlpha): Make data isn't NULL before trying to do anything.
|
||||
|
||||
2002-09-23 19:30 Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
* Source/art/ftfont.m (-initWithFontName:matrix:): Retain
|
||||
|
|
|
@ -135,62 +135,98 @@ static int use_shape_hack = 0; /* this is an ugly hack :) */
|
|||
|
||||
wi->ximage = NULL;
|
||||
|
||||
/* TODO: only use shared memory for 'real' on-screen windows. how can
|
||||
we tell? don't create shared buffer until first expose? */
|
||||
/* The primary problems seems to be the system limit on the _number_
|
||||
of shared memory segments, not their total size, so we only create
|
||||
shared buffers for reasonably large buffers and assume that the small
|
||||
ones are just caches of images and will never be displayed, anyway
|
||||
(and if they are displayed, it won't cost much, since they're small).
|
||||
*/
|
||||
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)."
|
||||
/* Use XShm if possible, else fall back to normal XImage:s */
|
||||
if (XShmQueryExtension(wi->display))
|
||||
if (!XShmQueryExtension(wi->display))
|
||||
{
|
||||
wi->use_shm = 1;
|
||||
wi->ximage = XShmCreateImage(wi->display,
|
||||
DefaultVisual(wi->display, DefaultScreen(wi->display)),
|
||||
aDI->drawing_depth, ZPixmap, NULL, &wi->shminfo,
|
||||
wi->window->xframe.size.width,
|
||||
wi->window->xframe.size.height);
|
||||
static BOOL xshm_warned = NO;
|
||||
if (!xshm_warned)
|
||||
NSLog(@"XShm not supported." WARN);
|
||||
xshm_warned = YES;
|
||||
goto no_xshm;
|
||||
}
|
||||
if (wi->ximage)
|
||||
|
||||
wi->use_shm = 1;
|
||||
wi->ximage = XShmCreateImage(wi->display,
|
||||
DefaultVisual(wi->display, DefaultScreen(wi->display)),
|
||||
aDI->drawing_depth, ZPixmap, NULL, &wi->shminfo,
|
||||
wi->window->xframe.size.width,
|
||||
wi->window->xframe.size.height);
|
||||
if (!wi->ximage)
|
||||
{
|
||||
/* TODO: only use shared memory for 'real' on-screen
|
||||
windows. how can we tell? */
|
||||
wi->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
wi->ximage->bytes_per_line * wi->ximage->height,
|
||||
IPC_CREAT | 0700);
|
||||
NSLog(@"Warning: XShmCreateImage failed!" WARN);
|
||||
goto no_xshm;
|
||||
}
|
||||
wi->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
wi->ximage->bytes_per_line * wi->ximage->height,
|
||||
IPC_CREAT | 0700);
|
||||
|
||||
if (!wi->shminfo.shmid == -1)
|
||||
NSLog(@"shmget() failed"); /* TODO */
|
||||
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
|
||||
if (wi->shminfo.shmid == -1)
|
||||
{
|
||||
NSLog(@"Warning: shmget() failed: %m." WARN);
|
||||
XDestroyImage(wi->ximage);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
wi->shminfo.readOnly = 0;
|
||||
if (!XShmAttach(wi->display, &wi->shminfo))
|
||||
NSLog(@"XShmAttach() failed");
|
||||
|
||||
/* We try to create a shared pixmap using the same buffer, and set
|
||||
it as the background of the window. This allows X to handle expose
|
||||
events all by itself, which avoids white flashing when things are
|
||||
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);
|
||||
if (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);
|
||||
|
||||
/* 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 be destroyed
|
||||
despite nobody being attached anymore. */
|
||||
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
|
||||
if ((int)wi->shminfo.shmaddr == -1)
|
||||
{
|
||||
NSLog(@"Warning: shmat() failed: %m." WARN);
|
||||
XDestroyImage(wi->ximage);
|
||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
||||
goto no_xshm;
|
||||
}
|
||||
else
|
||||
|
||||
wi->shminfo.readOnly = 0;
|
||||
if (!XShmAttach(wi->display, &wi->shminfo))
|
||||
{
|
||||
NSLog(@"failed to create shared memory image, using normal XImage:s");
|
||||
NSLog(@"Warning: XShmAttach() failed." WARN);
|
||||
XDestroyImage(wi->ximage);
|
||||
shmdt(wi->shminfo.shmaddr);
|
||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
/* We try to create a shared pixmap using the same buffer, and set
|
||||
it as the background of the window. This allows X to handle expose
|
||||
events all by itself, which avoids white flashing when things are
|
||||
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);
|
||||
if (wi->pixmap) /* TODO: this doesn't work */
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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
|
||||
be destroyed despite nobody being attached anymore. */
|
||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
||||
|
||||
if (!wi->ximage)
|
||||
{
|
||||
no_xshm:
|
||||
wi->use_shm = 0;
|
||||
wi->ximage = XCreateImage(wi->display, DefaultVisual(wi->display,
|
||||
DefaultScreen(wi->display)), aDI->drawing_depth, ZPixmap, 0, NULL,
|
||||
|
@ -203,9 +239,9 @@ static int use_shape_hack = 0; /* this is an ugly hack :) */
|
|||
XDestroyImage(wi->ximage);
|
||||
wi->ximage = NULL;
|
||||
}
|
||||
/*TODO? wi->ximage = XGetImage(wi->display, wi->drawable,
|
||||
0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
|
||||
-1, ZPixmap);*/
|
||||
/*TODO? wi->ximage = XGetImage(wi->display, wi->drawable,
|
||||
0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
|
||||
-1, ZPixmap);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,7 +257,7 @@ static int use_shape_hack = 0; /* this is an ugly hack :) */
|
|||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Warning: failed to create image for window");
|
||||
NSLog(@"Warning: failed to create image for window!");
|
||||
wi->data = NULL;
|
||||
}
|
||||
|
||||
|
@ -420,6 +456,9 @@ static int warn = 0;
|
|||
if (has_alpha)
|
||||
return;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
// NSLog(@"needs alpha for %p: %ix%i", self, sx, sy);
|
||||
|
||||
if (DI.inline_alpha)
|
||||
|
|
Loading…
Reference in a new issue