Closed FreeSlave closed 9 years ago
I think X11 is freeing the memory for the internal buffer. Meaning it is using it live (I thought it didn't). This is a little worrisome. As it means that it needs a full new reallocation when the size of the buffer changes. And keep around the XImage until then. I'm not really in a position to test, to make sure it even compiles (thanks Travis/dub failing even though code is fine). I'll push to ~master a fix. But you'll need to confirm.
I don't think that resizing caused the problem in first place (though it could cause problems after). It crashes on the first call to swapBuffers. I pulled the latest version and txImage is still null after XCreateImage. I've changed XYBitmap to XYPixmap and it seems to work (including resizing). Though window does not react to closing, only to sigterm.
Unfortunately x11 docs are awful for this argument. So I'm changing as per your suggestion as it seems to be correct.
Found out it receives close event, but it takes some time. Still could not find what causes such hanging. Also the application itself eats near 40% CPU.
The run loop that I used in example, was designed for 3d games. Where they want 100% resource usage. For GUI's and such it doesn't need it. There it needs to go down to a point of a percentage when not doing anything.
What needs to happen is a new function like messageLoopIteration who's sole job is to wait for a new message, instead of saying if it got one or not optionally. This will dramatically decrease CPU usage. It will also drop the FPS down ridiculously.
Here is my newish event loop which I'm using for GUI purposes. Differences:
It dropped cpu usage by about 20% when being displayed on Windows.
void showAndRun(ushort tickSleep = 100) {
import devisualization.window.window;
import core.time : dur;
self.show;
auto sleepTick = dur!"msecs"(tickSleep);
while(true) {
import core.thread : Thread;
bool sleep = Window.messageLoopIteration(1, 1);
IContext context = self.context;
if (self.hasBeenClosed)
break;
else if (context !is null) {
self.onDraw;
}
if (sleep)
Thread.sleep(sleepTick);
}
}
If you remove the self.onDraw call in the event loop it can be dropped by another percentage. Which should be about 4% on your system. The only platform that does need that in still is OSX.
void showAndRun(ushort tickSleep = 100) {
import devisualization.window.window;
import core.time : dur;
self.show;
auto sleepTick = dur!"msecs"(tickSleep);
while(true) {
import core.thread : Thread;
version(OSX) {
IContext context = self.context;
if (self.hasBeenClosed)
break;
else if (context !is null) {
self.onDraw;
}
} else {
if (self.hasBeenClosed)
break;
}
if (Window.messageLoopIteration(1, 1))
Thread.sleep(sleepTick);
}
}
It's still hanging at 8% on my system. Which is wayy to high even when it isn't foreground. I think the next task is a blocking wait until program has a window that is focussed aka has keyboard input. This is going to be a lot more difficult.
The test program looks the same. Should I replace test loop by this manually? What is self variable?
Well, self seems to be window object. Ok, I modified code, the second snippet seems to work on X11 without hanging. But the window is white.
Can you explain logic behind not doing sleep when there're no pending events left?
Wow, I thought I answered you @MyLittleRobo. My apologies!
self is the instance of Window.
In that code, it was whatever worked the best on my machine.
I've done some work to make it more round 5% cpu usage:
void showAndRun(ushort framerate=25) {
import devisualization.window.window;
import std.datetime : StopWatch, TickDuration;
import core.time : dur;
self.show;
StopWatch stopWatch;
auto expectTickDuration = 1000 / framerate;
version(Windows) {
TIMECAPS caps;
timeGetDevCaps(&caps, caps.sizeof);
timeBeginPeriod(caps.wPeriodMin);
}
while(true) {
import core.thread : Thread;
stopWatch.start;
version(OSX) {
IContext context = self.context;
if (self.hasBeenClosed)
break;
else if (context !is null) {
self.onDraw;
}
} else {
IContext context = self.context;
if (self.hasBeenClosed)
break;
}
stopWatch.stop();
auto timeTaken = stopWatch.peek().hnsecs;
stopWatch.reset();
Window.messageLoopIteration(1, 0);
if (timeTaken < expectTickDuration)
Thread.sleep(dur!"msecs"(expectTickDuration - timeTaken));
}
TLDR: FPS limiter At least on Windows I've been unable to make the event loop sleep for messages. It's making me rather curious. Something isn't right. I wonder if e.g. phobos is doing something nasty here.
Is this bug fixed or not?
I believe so, but @MyLittleRobo should confirm.
I use de_window 0.1.2 and have the following:
(gdb) r
Starting program: /home/drug/.dub/packages/de_window-0.1.2/de_window_test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
has context
type: Buffer2D
toolkit version:
shading language version:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78c7028 in XPutImage () from /usr/lib/x86_64-linux-gnu/libX11.so.6
(gdb) bt
#0 0x00007ffff78c7028 in XPutImage () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#1 0x000000000040791c in devisualization.window.context.buffer2d.Buffer2DContext.swapBuffers() (this=...)
at platforms/linux/devisualization/window/context/buffer2d.d:75
#2 0x0000000000406a26 in D main () at test/main.d:191
#3 0x00000000004a3e5f in __lambda1 (this=0x7fffffffdff0) at /home/build/tmp/build/.build/src/gcc-4.9.2/libphobos/libdruntime/rt/dmain2.d:411
#4 0x00000000004a3f8f in rt.dmain2._d_run_main() (this=this@entry=0x7fffffffdff0, dg=...)
at /home/build/tmp/build/.build/src/gcc-4.9.2/libphobos/libdruntime/rt/dmain2.d:386
#5 0x00000000004a4339 in runAll (this=0x7fffffffdff0) at /home/build/tmp/build/.build/src/gcc-4.9.2/libphobos/libdruntime/rt/dmain2.d:411
#6 0x00000000004a3f8f in rt.dmain2._d_run_main() (this=this@entry=0x7fffffffdff0, dg=...)
at /home/build/tmp/build/.build/src/gcc-4.9.2/libphobos/libdruntime/rt/dmain2.d:386
#7 0x00000000004a4116 in _d_run_main (argc=1, argv=0x7fffffffe158, mainFunc=<optimized out>)
at /home/build/tmp/build/.build/src/gcc-4.9.2/libphobos/libdruntime/rt/dmain2.d:419
#8 0x0000000000406338 in main (argc=1, argv=0x7fffffffe158)
at /home/drug/bin/x86_64-gdcproject-linux-gnu/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/include/d/__entrypoint.di:62
Opengl context works fine.
I'm not really in a position to debug this, so. Can you please output the values for: (from https://github.com/Devisualization/window/blob/master/platforms/linux/devisualization/window/context/buffer2d.d#L75)
pixmap, bufferdata
Something is probably null or invalid.
Ah, I see, this bug is fixed in master. Could you tag it I can use version, no master?
Tagged 0.1.3
When running the test program. Eventually theImage become null.
The weird thing it goes to xlib.XCreateImage twice, but does not call xlib.XSetWindowBackgroundPixmap and xutil.XDestroyImage.
My system info: X.Org X Server 1.16.2.901 (1.16.3 RC 1) Release Date: 2014-12-09 X Protocol Version 11, Revision 0 Build Operating System: Linux 3.2.0-4-amd64 i686 Debian Current Operating System: Linux debian 3.10-3-686-pae #1 SMP Debian 3.10.11-1 (2013-09-10) i686