mirror of
https://github.com/gnustep/libs-back.git
synced 2025-06-01 17:52:33 +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
3ccdce3009
commit
b78ff5291f
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>
|
2002-09-23 19:30 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
* Source/art/ftfont.m (-initWithFontName:matrix:): Retain
|
* 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;
|
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 */
|
/* Use XShm if possible, else fall back to normal XImage:s */
|
||||||
if (XShmQueryExtension(wi->display))
|
if (!XShmQueryExtension(wi->display))
|
||||||
{
|
{
|
||||||
wi->use_shm = 1;
|
static BOOL xshm_warned = NO;
|
||||||
wi->ximage = XShmCreateImage(wi->display,
|
if (!xshm_warned)
|
||||||
DefaultVisual(wi->display, DefaultScreen(wi->display)),
|
NSLog(@"XShm not supported." WARN);
|
||||||
aDI->drawing_depth, ZPixmap, NULL, &wi->shminfo,
|
xshm_warned = YES;
|
||||||
wi->window->xframe.size.width,
|
goto no_xshm;
|
||||||
wi->window->xframe.size.height);
|
|
||||||
}
|
}
|
||||||
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
|
NSLog(@"Warning: XShmCreateImage failed!" WARN);
|
||||||
windows. how can we tell? */
|
goto no_xshm;
|
||||||
wi->shminfo.shmid = shmget(IPC_PRIVATE,
|
}
|
||||||
wi->ximage->bytes_per_line * wi->ximage->height,
|
wi->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||||
IPC_CREAT | 0700);
|
wi->ximage->bytes_per_line * wi->ximage->height,
|
||||||
|
IPC_CREAT | 0700);
|
||||||
|
|
||||||
if (!wi->shminfo.shmid == -1)
|
if (wi->shminfo.shmid == -1)
|
||||||
NSLog(@"shmget() failed"); /* TODO */
|
{
|
||||||
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
|
NSLog(@"Warning: shmget() failed: %m." WARN);
|
||||||
|
XDestroyImage(wi->ximage);
|
||||||
|
goto no_xshm;
|
||||||
|
}
|
||||||
|
|
||||||
wi->shminfo.readOnly = 0;
|
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
|
||||||
if (!XShmAttach(wi->display, &wi->shminfo))
|
if ((int)wi->shminfo.shmaddr == -1)
|
||||||
NSLog(@"XShmAttach() failed");
|
{
|
||||||
|
NSLog(@"Warning: shmat() failed: %m." WARN);
|
||||||
/* We try to create a shared pixmap using the same buffer, and set
|
XDestroyImage(wi->ximage);
|
||||||
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. */
|
|
||||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
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->use_shm = 0;
|
||||||
wi->ximage = XCreateImage(wi->display, DefaultVisual(wi->display,
|
wi->ximage = XCreateImage(wi->display, DefaultVisual(wi->display,
|
||||||
DefaultScreen(wi->display)), aDI->drawing_depth, ZPixmap, 0, NULL,
|
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);
|
XDestroyImage(wi->ximage);
|
||||||
wi->ximage = NULL;
|
wi->ximage = NULL;
|
||||||
}
|
}
|
||||||
/*TODO? wi->ximage = XGetImage(wi->display, wi->drawable,
|
/*TODO? wi->ximage = XGetImage(wi->display, wi->drawable,
|
||||||
0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
|
0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
|
||||||
-1, ZPixmap);*/
|
-1, ZPixmap);*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +257,7 @@ static int use_shape_hack = 0; /* this is an ugly hack :) */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSLog(@"Warning: failed to create image for window");
|
NSLog(@"Warning: failed to create image for window!");
|
||||||
wi->data = NULL;
|
wi->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,6 +456,9 @@ static int warn = 0;
|
||||||
if (has_alpha)
|
if (has_alpha)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
// NSLog(@"needs alpha for %p: %ix%i", self, sx, sy);
|
// NSLog(@"needs alpha for %p: %ix%i", self, sx, sy);
|
||||||
|
|
||||||
if (DI.inline_alpha)
|
if (DI.inline_alpha)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue