[cairo] memory problem with the X11 - SHM backend
Uli Schlachter
psychon at znc.in
Sun Dec 1 03:11:20 PST 2013
Hi,
On 01.12.2013 11:30, Cedric Roux wrote:
> On 12/01/2013 10:55 AM, Uli Schlachter wrote:
>> On 01.12.2013 01:06, Cedric Roux wrote:
>>> I have a problem running you with X11/Xshm. This is a debian host here.
>>> The following program reports an always increasing "evs" thing.
>>>
>>> The first line it outputs is "1 evs" and the last one is
>>> "7409 evs".
>>
>> It doesn't do so here:
>>
>> $ gcc t.c -lcairo -lX11&& ./a.out | uniq -c
>> 7500 1 evs
>
> I have 1.12.16 here, you are with the git one?
Does not happen with git nor with debian's 1.12.16-2.
> Still no problem if you do the following instead of the translate(0,0) ?
>
> static int z = 2; cairo_matrix_init_translate(&m, z, z);
> z = 2 - z;
Still no problem.
>> (Looks like the first paint() causes a SHM fallback and all the following
>> paint()s don't cause any Xlib calls, but just draw to the already existing SHM
>> image surface)
>>
>> If I do make the change mentioned below, I do get an increasing size of the
>> event queue. Why don't you run any event loop that gets events from Xlib?
>
> There is the XCheckMaskEvent thing, but it never prints "events".
> even with XFlush before.
>
> To figure things out (there are events in the queue, why doesn't
> XCheckMaskEvent return them?) I looked at the first_event field when
> calling XInitExtension and it is 65. I didn't check in the source of
> X11 but I suspect XCheckMaskEvent(-1L) won't look at this number
> because (1<<65) is out of range. Calling XNextEvent indeed removes the
> event from the queue.
XCheckMaskEvent() only handles core events. We are looking at an event coming
from the MIT-SHM extension. It gets generated via XSendEvent() by cairo:
http://cgit.freedesktop.org/cairo/tree/src/cairo-xlib-surface-shm.c?id=31eff5c6eb57ad379689748fd8c60a5ffe0ba481#n433
This is used to implement something like a "non-blocking XSync()". When Xlib
receives the event, LastKnownRequestProcessed(dpy) is updated and cairo can
re-use some shared memory that it was waiting for.
The idea for the main loop is to just discard this event, I guess. Chris would
know more.
> Well, I'm left with a problem here. I cannot use XNextEvent because
> my program uses select and XCheckMaskEvent leaves the event in
> the queue... So I guess I'll have to go with the XEventsQueued thing
> to check if there is something waiting and then use XNextEvent to
> really get it out. Or something...
You might be looking for something like this:
while (XPending(dpy)) {
XNextEvent(dpy, &ev);
/* Handle the event */
}
Cheers,
Uli
> Thanks for your help, Uli, and taking time to test things.
> I guess it was me misunderstanding something in there, probably
> the semantics of XCheckMaskEvent. Or something.
>
> Regards.
>
>>
>>> That means the X event queue is not emptied. (Please don't
>>> look at the style, it's a quick and dirty hack to let the problem pop
>>> up.)
>>>
>>> Oh yes, you need to create a 128x128 mini.png file to run it. Content
>>> does not seem to matter, I have a white image here.
>>>
>>> Am I doing something wrong with you or is the problem on your side?
>>
>> Uhm, so what exactly is the problem here? So far we are just at the symptom
>> "always increasing 'evs' thing". This might cause many actual problems, so which
>> one are you looking at?
>>
>>> If I call XSync(d, True) the queue is emptied and the original program
>>> that exhibited the problem and from which I wrote that little proof of
>>> concept still works pretty reasonably well. (What a terrific sentence
>>> I just wrote...)
>>> Except it smokes my CPU like hell, but that's none of your concern I
>>> suspect.
>>>
>>> In the hope that you can help me here...
>>> Regards cairo, have a nice sunday.
>>>
>>> #include<stdio.h>
>>> #include<cairo/cairo.h>
>>> #include<cairo/cairo-xlib.h>
>>> #include<X11/Xlib.h>
>>> #include<stdlib.h>
>>>
>>> int main(void)
>>> {
>>> cairo_surface_t *image;
>>> cairo_pattern_t *pletters;
>>> cairo_surface_t *cs;
>>> Display *d;
>>> Pixmap p;
>>>
>>> d = XOpenDisplay(0); if (!d) abort();
>>> p = XCreatePixmap(d, DefaultRootWindow(d), 256, 256,
>>> DefaultDepth(d, DefaultScreen(d)));
>>> cs = cairo_xlib_surface_create(d, p, DefaultVisual(d, DefaultScreen(d)),
>>> 256, 256);
>>>
>>> //image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 512, 512);
>>> image = cairo_image_surface_create_from_png("mini.png");
>>> pletters = cairo_pattern_create_for_surface(image);
>>>
>>> int y;
>>> for (y=0; y< 500; y++) {
>>> int i;
>>> cairo_matrix_t m;
>>> cairo_t *c = cairo_create(cs);
>>>
>>> //cairo_scale(c, 0.5, 0.5);
>>> //cairo_translate(c, 1, 1);
>>> for (i = 0; i< 15; i++) {
>>> //static int z = 2; cairo_matrix_init_translate(&m, 0, 0); //z =
>>> 2 - z;
>>> cairo_matrix_init_translate(&m, 0, 0); //z = 2 - z;
>>> cairo_pattern_set_matrix(pletters,&m);
>>> cairo_set_source(c, pletters);
>>> cairo_paint(c);
>>>
>>> //XSync(d, True);
>>> printf("%d evs\n", XEventsQueued(d, QueuedAfterReading));
>>> //XFlush(d);
>>>
>>> XEvent ev; while (XCheckMaskEvent(d, -1L,&ev)) {
>>> printf("event!\n"); }
>>
>> Add here: cairo_surface_flush(cs); and the event queue gets filled with
>> MIT-SHM-Completion events (and the program of course runs a lot slower).
>>
>>> }
>>>
>>> cairo_destroy(c);
>>> }
>>>
>>> return 0;
>>> }
>>>
>>
>> Cheers,
>> Uli
>
--
No matter how much cats fight, there always seem to be plenty of kittens.
More information about the cairo
mailing list