In XwindowBuffer get the default visual and depth from the XGServer.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@26961 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2008-10-24 16:42:38 +00:00
parent c6c8160a30
commit 1802f35b22
4 changed files with 312 additions and 283 deletions

View file

@ -1,3 +1,11 @@
2008-10-24 Fred Kiefer <FredKiefer@gmx.de>
* Source/x11/XGServer.m (-visualForScreen:, -depthForScreen:):
New methods that hide RContext details.
* Headers/x11/XGServer.h: Declare these new methods.
* Source/x11/XWindowBuffer.m: Get the default visual and depth
from the XGServer.
2008-10-22 Fred Kiefer <FredKiefer@gmx.de>
* Source/x11/XGServerWindow.m (-_checkStyle:): Correct code

View file

@ -63,6 +63,9 @@ typedef enum {
- (Window) xAppRootWindow;
- (void *) xrContextForScreen: (int)screen_number;
- (Visual *) visualForScreen: (int)screen_number;
- (int) depthForScreen: (int)screen_number;
- (XGDrawMechanism) drawMechanismForScreen: (int)screen_number;
- (void) getForScreen: (int)screen_number pixelFormat: (int *)bpp_number
masks: (int *)red_mask : (int *)green_mask : (int *)blue_mask;

View file

@ -518,6 +518,16 @@ _parse_display_name(NSString *name, int *dn, int *sn)
return [[self _screenContextForScreen: screen_number] context];
}
- (Visual *) visualForScreen: (int)screen_number
{
return [[self _screenContextForScreen: screen_number] context]->visual;
}
- (int) depthForScreen: (int)screen_number
{
return [[self _screenContextForScreen: screen_number] context]->depth;
}
/**
Returns the XGDrawMechanism, which roughly describes the depth of
the screen and how pixels should be drawn to the screen for maximum

View file

@ -12,7 +12,7 @@
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
@ -49,7 +49,7 @@ 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).";
= @"Falling back to normal XImage: s (will be slower).";
static int test_xshm_error_handler(Display *d, XErrorEvent *ev)
{
@ -57,7 +57,7 @@ static int test_xshm_error_handler(Display *d, XErrorEvent *ev)
return 0;
}
static void test_xshm(Display *display, int drawing_depth)
static void test_xshm(Display *display, Visual *visual, int drawing_depth)
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
@ -93,39 +93,38 @@ static void test_xshm(Display *display, int drawing_depth)
old_error_handler = XSetErrorHandler(test_xshm_error_handler);
ximage = XShmCreateImage(display,
DefaultVisual(display, DefaultScreen(display)),
drawing_depth, ZPixmap, NULL, &shminfo,
1, 1);
ximage = XShmCreateImage(display, visual,
drawing_depth, ZPixmap, NULL, &shminfo,
1, 1);
XSync(display, False);
if (!ximage || num_xshm_test_errors)
{
NSLog(@"XShm not supported, XShmCreateImage failed.");
goto no_xshm;
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);
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;
NSLog(@"XShm not supported, shmget() failed: %m.");
XDestroyImage(ximage);
goto no_xshm;
}
shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
if ((intptr_t)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;
NSLog(@"XShm not supported, shmat() failed: %m.");
XDestroyImage(ximage);
shmctl(shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
shminfo.readOnly = 0;
@ -134,11 +133,11 @@ static void test_xshm(Display *display, int drawing_depth)
XSync(display, False);
if (num_xshm_test_errors)
{
NSLog(@"XShm not supported, XShmAttach() failed.");
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
NSLog(@"XShm not supported, XShmAttach() failed.");
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
XShmDetach(display, &shminfo);
@ -154,10 +153,10 @@ static void test_xshm(Display *display, int drawing_depth)
if (num_xshm_test_errors)
{
NSLog(@"XShm not supported.");
NSLog(@"XShm not supported.");
no_xshm:
NSLog(xshm_warning);
use_xshm = 0;
NSLog(xshm_warning);
use_xshm = 0;
}
XSetErrorHandler(old_error_handler);
}
@ -166,16 +165,24 @@ no_xshm:
@implementation XWindowBuffer
+ (void) initialize
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
use_shape_hack = [ud boolForKey: @"XWindowBuffer-shape-hack"];
}
+ windowBufferForWindow: (gswindow_device_t *)awindow
depthInfo: (struct XWindowBuffer_depth_info_s *)aDI
{
int i;
XWindowBuffer *wi;
int drawing_depth;
Visual *visual;
for (i = 0; i < num_window_buffers; i++)
{
if (window_buffers[i]->window == awindow)
break;
break;
}
if (i == num_window_buffers)
{
@ -184,11 +191,11 @@ no_xshm:
window_buffers = realloc(window_buffers,
sizeof(XWindowBuffer *) * (num_window_buffers + 1));
if (!window_buffers)
{
NSLog(@"Out of memory (failed to allocate %i bytes)",
sizeof(XWindowBuffer *) * (num_window_buffers + 1));
exit(1);
}
{
NSLog(@"Out of memory (failed to allocate %i bytes)",
sizeof(XWindowBuffer *) * (num_window_buffers + 1));
exit(1);
}
window_buffers[num_window_buffers++] = wi;
}
else
@ -205,6 +212,15 @@ no_xshm:
wi->window->gdriverProtocol = GDriverHandlesExpose | GDriverHandlesBacking;
wi->window->gdriver = wi;
#if 0
drawing_depth = aDI->drawing_depth;
visual = DefaultVisual(wi->display, DefaultScreen(wi->display));
#else
// Better to get the used visual from the XGServer.
visual = [(XGServer*)GSCurrentServer() visualForScreen: awindow->screen];
drawing_depth = [(XGServer*)GSCurrentServer() depthForScreen: awindow->screen];
#endif
/* TODO: resolve properly.
-x11 is creating buffers before I have a chance to tell it not to, so
I'm freeing them here to reduce memory consumption (and prevent
@ -225,33 +241,32 @@ no_xshm:
wi->sx != awindow->xframe.size.width ||
wi->sy != awindow->xframe.size.height)
{
wi->sx = wi->window->xframe.size.width;
/* printf("%@ updating image for %p (%gx%g)\n", wi, wi->window,
wi->window->xframe.size.width, wi->window->xframe.size.height);*/
/* printf("%@ updating image for %p (%gx%g)\n", wi, wi->window,
wi->window->xframe.size.width, wi->window->xframe.size.height);*/
if (wi->ximage)
{
if (wi->use_shm)
{
XShmDetach(wi->display, &wi->shminfo);
XDestroyImage(wi->ximage);
shmdt(wi->shminfo.shmaddr);
}
else
XDestroyImage(wi->ximage);
}
{
if (wi->use_shm)
{
XShmDetach(wi->display, &wi->shminfo);
XDestroyImage(wi->ximage);
shmdt(wi->shminfo.shmaddr);
}
else
XDestroyImage(wi->ximage);
}
if (wi->pixmap)
{
XFreePixmap(wi->display,wi->pixmap);
XSetWindowBackground(wi->display,wi->window->ident,None);
wi->pixmap=0;
}
{
XFreePixmap(wi->display,wi->pixmap);
XSetWindowBackground(wi->display,wi->window->ident,None);
wi->pixmap=0;
}
wi->has_alpha = 0;
if (wi->alpha)
{
free(wi->alpha);
wi->alpha = NULL;
}
{
free(wi->alpha);
wi->alpha = NULL;
}
wi->pending_put = wi->pending_event = 0;
@ -269,73 +284,72 @@ no_xshm:
goto no_xshm;
if (!did_test_xshm)
test_xshm(wi->display, aDI->drawing_depth);
test_xshm(wi->display, visual, drawing_depth);
if (!use_xshm)
goto no_xshm;
/* Use XShm if possible, else fall back to normal XImage: s */
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);
wi->ximage = XShmCreateImage(wi->display, visual,
drawing_depth, ZPixmap, NULL, &wi->shminfo,
wi->window->xframe.size.width,
wi->window->xframe.size.height);
if (!wi->ximage)
{
NSLog(@"Warning: XShmCreateImage failed!");
NSLog(xshm_warning);
goto no_xshm;
}
{
NSLog(@"Warning: XShmCreateImage failed!");
NSLog(xshm_warning);
goto no_xshm;
}
wi->shminfo.shmid = shmget(IPC_PRIVATE,
wi->ximage->bytes_per_line * wi->ximage->height,
IPC_CREAT | 0700);
wi->ximage->bytes_per_line * wi->ximage->height,
IPC_CREAT | 0700);
if (wi->shminfo.shmid == -1)
{
NSLog(@"Warning: shmget() failed: %m.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
goto no_xshm;
}
{
NSLog(@"Warning: shmget() failed: %m.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
goto no_xshm;
}
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
if ((intptr_t)wi->shminfo.shmaddr == -1)
{
NSLog(@"Warning: shmat() failed: %m.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
{
NSLog(@"Warning: shmat() failed: %m.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
wi->shminfo.readOnly = 0;
if (!XShmAttach(wi->display, &wi->shminfo))
{
NSLog(@"Warning: XShmAttach() failed.");
NSLog(xshm_warning);
XDestroyImage(wi->ximage);
shmdt(wi->shminfo.shmaddr);
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
goto no_xshm;
}
{
NSLog(@"Warning: XShmAttach() failed.");
NSLog(xshm_warning);
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. */
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. */
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->ximage->data, &wi->shminfo,
wi->window->xframe.size.width,
wi->window->xframe.size.height,
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
@ -348,24 +362,25 @@ no_xshm:
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,
wi->window->xframe.size.width, wi->window->xframe.size.height,
8, 0);
wi->use_shm = 0;
wi->ximage = XCreateImage(wi->display, visual, drawing_depth,
ZPixmap, 0, NULL,
wi->window->xframe.size.width,
wi->window->xframe.size.height,
8, 0);
wi->ximage->data = malloc(wi->ximage->height * wi->ximage->bytes_per_line);
if (!wi->ximage->data)
{
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);*/
}
wi->ximage->data = malloc(wi->ximage->height * wi->ximage->bytes_per_line);
if (!wi->ximage->data)
{
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);*/
}
}
if (wi->ximage)
@ -376,7 +391,7 @@ no_xshm:
wi->bytes_per_line = wi->ximage->bytes_per_line;
wi->bits_per_pixel = wi->ximage->bits_per_pixel;
wi->bytes_per_pixel = wi->bits_per_pixel / 8;
// NSLog(@"%@ ximage=%p data=%p\n", wi->ximage, wi->data);
// NSLog(@"%@ ximage=%p data=%p\n", wi->ximage, wi->data);
}
else
{
@ -400,31 +415,31 @@ extern int XShmGetEventBase(Display *d);
{
pending_put = 0;
if (pending_rect.x + pending_rect.w > window->xframe.size.width)
{
pending_rect.w = window->xframe.size.width - pending_rect.x;
if (pending_rect.w <= 0)
return;
}
{
pending_rect.w = window->xframe.size.width - pending_rect.x;
if (pending_rect.w <= 0)
return;
}
if (pending_rect.y + pending_rect.h > window->xframe.size.height)
{
pending_rect.h = window->xframe.size.height - pending_rect.y;
if (pending_rect.h <= 0)
return;
}
{
pending_rect.h = window->xframe.size.height - pending_rect.y;
if (pending_rect.h <= 0)
return;
}
if (!XShmPutImage(display, drawable, gc, ximage,
pending_rect.x, pending_rect.y,
pending_rect.x, pending_rect.y,
pending_rect.w, pending_rect.h,
1))
{
NSLog(@"XShmPutImage failed?");
}
pending_rect.x, pending_rect.y,
pending_rect.x, pending_rect.y,
pending_rect.w, pending_rect.h,
1))
{
NSLog(@"XShmPutImage failed?");
}
else
{
pending_event = 1;
}
{
pending_event = 1;
}
}
// XFlush(window->display);
// XFlush(window->display);
}
- (void) _exposeRect: (NSRect)rect
@ -476,138 +491,138 @@ accuracy, we do the test using int: s.
{
/* HACK: lets try to use shaped windows to get some use out of
destination alpha */
destination alpha */
if (has_alpha && use_shape_hack)
{
{
static int warn = 0;
Pixmap p;
int dsize = ((sx + 7) / 8) * sy;
unsigned char *buf = malloc(dsize);
unsigned char *dst;
int bofs;
unsigned char *a;
int as;
int i, x;
Pixmap p;
int dsize = ((sx + 7) / 8) * sy;
unsigned char *buf = malloc(dsize);
unsigned char *dst;
int bofs;
unsigned char *a;
int as;
int i, x;
if (!warn)
NSLog(@"Warning: activating shaped windows");
warn = 1;
if (!warn)
NSLog(@"Warning: activating shaped windows");
warn = 1;
memset(buf, 0xff, dsize);
memset(buf, 0xff, dsize);
#define CUTOFF 128
if (DI.inline_alpha)
{
a = data + DI.inline_alpha_ofs;
as = DI.bytes_per_pixel;
}
else
{
a = alpha;
as = 1;
}
if (DI.inline_alpha)
{
a = data + DI.inline_alpha_ofs;
as = DI.bytes_per_pixel;
}
else
{
a = alpha;
as = 1;
}
for (bofs = 0, i = sx * sy, x = sx, dst = buf; i; i--, a += as)
{
if (*a < CUTOFF)
{
*dst = *dst & ~(1 << bofs);
}
bofs++;
if (bofs == 8)
{
dst++;
bofs = 0;
}
x--;
if (!x)
{
if (bofs)
{
bofs = 0;
dst++;
}
x = sx;
}
}
for (bofs = 0, i = sx * sy, x = sx, dst = buf; i; i--, a += as)
{
if (*a < CUTOFF)
{
*dst = *dst & ~(1 << bofs);
}
bofs++;
if (bofs == 8)
{
dst++;
bofs = 0;
}
x--;
if (!x)
{
if (bofs)
{
bofs = 0;
dst++;
}
x = sx;
}
}
#undef CUTOFF
//NSLog(@"check shape");
if (old_shape_size == dsize && !memcmp(old_shape, buf, dsize))
{
free(buf);
// NSLog(@" same shape");
}
else
{
// NSLog(@" updating");
p = XCreatePixmapFromBitmapData(display, window->ident,
(char *)buf, sx, sy, 1, 0, 1);
free(old_shape);
old_shape = buf;
old_shape_size = dsize;
XShapeCombineMask(display, window->ident,
ShapeBounding, 0, 0, p, ShapeSet);
XFreePixmap(display, p);
}
}
if (old_shape_size == dsize && !memcmp(old_shape, buf, dsize))
{
free(buf);
// NSLog(@" same shape");
}
else
{
// NSLog(@" updating");
p = XCreatePixmapFromBitmapData(display, window->ident,
(char *)buf, sx, sy, 1, 0, 1);
free(old_shape);
old_shape = buf;
old_shape_size = dsize;
XShapeCombineMask(display, window->ident,
ShapeBounding, 0, 0, p, ShapeSet);
XFreePixmap(display, p);
}
}
if (pending_event)
{
if (!pending_put)
{
pending_put = 1;
pending_rect.x = x;
pending_rect.y = y;
pending_rect.w = w;
pending_rect.h = h;
}
else
{
if (x < pending_rect.x)
{
pending_rect.w += pending_rect.x - x;
pending_rect.x = x;
}
if (x + w > pending_rect.x + pending_rect.w)
{
pending_rect.w = x + w - pending_rect.x;
}
if (y < pending_rect.y)
{
pending_rect.h += pending_rect.y - y;
pending_rect.y = y;
}
if (y + h > pending_rect.y + pending_rect.h)
{
pending_rect.h = y + h - pending_rect.y;
}
}
}
{
if (!pending_put)
{
pending_put = 1;
pending_rect.x = x;
pending_rect.y = y;
pending_rect.w = w;
pending_rect.h = h;
}
else
{
if (x < pending_rect.x)
{
pending_rect.w += pending_rect.x - x;
pending_rect.x = x;
}
if (x + w > pending_rect.x + pending_rect.w)
{
pending_rect.w = x + w - pending_rect.x;
}
if (y < pending_rect.y)
{
pending_rect.h += pending_rect.y - y;
pending_rect.y = y;
}
if (y + h > pending_rect.y + pending_rect.h)
{
pending_rect.h = y + h - pending_rect.y;
}
}
}
else
{
pending_put = 0;
if (!XShmPutImage(display, drawable, gc, ximage,
x, y, x, y, w, h, 1))
{
NSLog(@"XShmPutImage failed?");
}
else
{
pending_event = 1;
}
}
{
pending_put = 0;
if (!XShmPutImage(display, drawable, gc, ximage,
x, y, x, y, w, h, 1))
{
NSLog(@"XShmPutImage failed?");
}
else
{
pending_event = 1;
}
}
/* Performance hack. Check right away for ShmCompletion
events. */
events. */
{
XEvent e;
XEvent e;
while (XCheckTypedEvent(window->display,
XShmGetEventBase(window->display) + ShmCompletion, &e))
{
[isa _gotShmCompletion: ((XShmCompletionEvent *)&e)->drawable];
}
while (XCheckTypedEvent(window->display,
XShmGetEventBase(window->display) + ShmCompletion, &e))
{
[isa _gotShmCompletion: ((XShmCompletionEvent *)&e)->drawable];
}
}
}
else if (ximage)
@ -624,7 +639,7 @@ static int warn = 0;
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)
{
@ -634,8 +649,8 @@ static int warn = 0;
has_alpha = 1;
/* fill the alpha channel */
for (i = 0, s = data + DI.inline_alpha_ofs; i < sx * sy;
i++, s += DI.bytes_per_pixel)
*s = 0xff;
i++, s += DI.bytes_per_pixel)
*s = 0xff;
return;
}
@ -646,7 +661,7 @@ static int warn = 0;
return;
}
// NSLog(@"got buffer at %p", alpha);
// NSLog(@"got buffer at %p", alpha);
has_alpha = 1;
memset(alpha, 0xff, sx * sy);
@ -662,25 +677,25 @@ static int warn = 0;
{
num_window_buffers--;
for (; i < num_window_buffers; i++)
window_buffers[i] = window_buffers[i + 1];
window_buffers[i] = window_buffers[i + 1];
}
if (ximage)
{
if (pixmap)
{
XFreePixmap(display,pixmap);
pixmap=0;
}
{
XFreePixmap(display,pixmap);
pixmap=0;
}
if (use_shm)
{
XShmDetach(display, &shminfo);
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
}
{
XShmDetach(display, &shminfo);
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
}
else
XDestroyImage(ximage);
XDestroyImage(ximage);
}
if (alpha)
free(alpha);
@ -688,23 +703,16 @@ static int warn = 0;
}
+ (void) initialize
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
use_shape_hack = [ud boolForKey: @"XWindowBuffer-shape-hack"];
}
+ (void) _gotShmCompletion: (Drawable)d
{
int i;
for (i = 0; i < num_window_buffers; i++)
{
if (window_buffers[i]->drawable == d)
{
[window_buffers[i] _gotShmCompletion];
return;
}
{
[window_buffers[i] _gotShmCompletion];
return;
}
}
}