I am creating a GTK+ 3 application which draws an animation using Cairo in a GtkDrawingArea widget. I get visual glitches, such as the ones observed in the images below. These appear only for a single frame, there may be none, or one, or more than one per frame. I am asking for help in identifying the possible issue. Here are the details of my code:
In my main method before starting the gtk_main() loop I hook up a timeout.
g_timeout_add(50, queue_draw, gtk_builder_get_object(builder, "window"));
"window" is the id of my GtkWindow. The queue_draw function is as follows:
gboolean queue_draw(gpointer user_data)
{
gtk_widget_queue_draw(GTK_WIDGET(user_data));
return TRUE;
}
I would think that I could pass the GtkDrawingArea object to this function rather than my whole GtkWindow, but the animation disappears in that case. I am also interested comments on this behavior but it is not my main question.
The draw signal of my GtkDrawingArea is hooked to a function gboolean drawing_area_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data). Inside this method I draw my 3D bar chart by a lazy painter's algorithm, each bar being made of three parallelograms, and the bars being drawn in z order.
It is not a problem with my computer failing to keep up with the frame rendering, somehow corrupting a frame buffer. I set the timeout to 1000ms to capture the images below.
I have not made any calls to gtk_widget_set_double_buffered().
I was not able to observe the issue on Windows Subsystem for Linux (WSL) using XMing as the X server, which makes me think it might be a library issue, or some poorly defined behavior.
The first image is of the visual glitch during my program in normal operation. In the second, I modified the code and fixed the height of the bars to a gentle gradient. This gives a much better view of the issue, but it still very puzzling.
development library package details:
$ dpkg --list | egrep 'lib(cairo|gtk).*-dev'
ii libcairo2-dev:amd64 1.15.10-2ubuntu0.1 amd64 Development files for the Cairo 2D graphics library
ii libgtk-3-dev:amd64 3.22.30-1ubuntu3 amd64 development files for the GTK+ library
library metainformation details:
$ pkg-config --modversion gtk+-3.0 glib-2.0 gdk-pixbuf-2.0 cairo
3.22.30
2.58.1
2.36.11
1.15.10
x11 details:
$ xdpyinfo | head -n 5
name of display: :0
version number: 11.0
vendor string: The X.Org Foundation
vendor release number: 12001000
X.Org version: 1.20.1
Linux details (actually Zorin OS 15 not Ubuntu 18.04):
$ uname -a
Linux <hostname> 4.18.0-25-generic #26~18.04.1-Ubuntu SMP Thu Jun 27 07:28:31 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
edit: Here is another very interesting screenshot of the issue.
Fist, calling gtk_widget_queue_draw on the main window makes no sense as only the GtkDrawingArea need to be updated at a high frequency. Redrawing controls you didn't interact with adds overhead for no value.
Next, I see nothing in your UI that wants to have the drawing area redrawn constantly. You should redraw in reaction to events: a parameter value that has changed in your left panel, or the user clicking in the drawing area to change the viewpoint (if that's something you support). You may event fire up a timeout in reaction to control changes and reinitialize that when another one is changed, so that it lets half a second to the user to change all the settings they want and then display the final result instead of the intermediate changes. This can be useful when you have controls with a value that can change fast like the GtkSpinButtons you use.
From your testing, if calling the drawing code every second instead of every 50ms gives you that result, then the problem is most probably in your drawing code, not on the way GTK+ draws it. To make sure that's the case, you can disable the timeout source that redraws, and add a button that when clicked triggers a single redraw. This way the whole frequency thing is out of the equation, and you should still have those rendering bugs.
The next step is to show us the code in the draw signal handler, as the bug probably lays there. If you want to debug it, you probably can split the drawing so that you save the cairo surface you're drawing to in a file after each histogram bar is painted. Then seeing the changes image by image with an image editor, you will see on which image the problem happens. With some logging, you will see which values trigger the problem.
Related
I'm using LWJGL 2.9.3 to create a window and retrieve mouse coordinates via LWJGLs Mouse.getX(),getY() methods. The results by those methods and by events via getEventX() are equal.
The coordinates I get back are correct using linux (ubuntu gnome, dm: i3) but aren't when using windows 8. (I considered wrong monitor settings due to second monitor but couldn't achieve anything by disconnecting/resetting/changing them)
Here are 2 images with estimations of the coordinates I get on both operating systems.
Correct, linux:
Incorrect, windows:
When activating fullscreen, I get data for both variables, the X coordinate seems to fit, the Y coordinate is somewhat off and changes for multiple clicks on the same location.
Here is the entire code I'm using for this example:
https://gist.github.com/Geosearchef/5889a13edd6b983959e837a8506170af
Does anyone have any idea what could be causing this? A bug with LWJGL? I was already using that exact version on Windows and was able to do it. A problem with my installation?
UPDATE: ((WindowsDisplay) Mouse.implementation).mouse.last_x has the correct value, ((WindowsDisplay) Mouse.implementation).mouse.last_y is correct if you set its origin at 1/3rd from the top. Below that it get's negative --> getting clamped. I don't know though why x gets set to -1.
UPDATE: The mouse implementation fails due to the Display class returning 0, 100 as width and height. This is ignored in the case of fullscreen. Width and height are set correctly in the beginning but are later overriden by an update (resize) call from the underlying implementation.
I've now figured out the problem. I used the natives of and old LWJGL implementation (2.9.1) which were stored in my project files.
I've been looking through the Xlib docs attempting to create a simple XWindows application. I'm able to get a window up and running, modify its background colour using pixel colours, etc.
Unfortunately, when I try and create a graphics content and render some of the primitives (Rectangles/Arcs etc) nothing is rendered.
I then built and ran the example here to make sure I wasn't missing something and it also just rendered the background with none of the primitives.
Can anyone explain what I may be missing here?
If it matters I'm running Fedora 23 on kernel 4.4.1 using Gnome shell.
You need to add event loop and move your drawing to occur after you receive expose event ( also make sure you set event mask when you create window or with XSelectInput call ). Likely the result of your drawing is disposed at some point and because you don't react to "window are is damaged, need to re-paint" notification all you see is window background
Take a look at this example
First of all after 4 hours of debugging I have no problem with my code. But I'm curious why I had issue that I had.
I created fullscreen window with d3d11 rendering. Problem occurred when I tried to alt-tab window and didn't have Present() in my loop (I simply found this issue before implementing rendering function). In that case after minimizing window Red and Blue channels on my screen were swapped (yes, literally).
It took me long time to find because I suspected my swap chain or window itself (sdl). Can you help me find the reason of this bug- for educational purposes?
This usually is due to a graphics driver bug with RGBA swap chains. You can try updating your driver (run Windows Update). But to improve compatibility you can change your swap chain surface format to BGRA (specifically, B8G8R8A8_UNORM). As long as you are just doing normal rendering (and not doing anything fancy like UpdateSubresource directly to the back buffer), you should be able to leave everything else as-is and it will render correctly.
How can I capture the screen with Haskell on Mac OS X?
I've read Screen capture in Haskell?. But I'm working on a Mac Mini. So, the Windows solution is not applicable and the GTK solution does not work because it only captures a black screen. GTK in Macs only captures black screens.
How can I capture the screen with … and OpenGL?
Only with some luck. OpenGL is primarily a drawing API and the contents of the main framebuffer are undefined unless it's drawn to by OpenGL functions themself. That OpenGL could be abused was due to the way graphics system did manage their on-screen windows' framebuffers: After a window without predefined background color/brush was created, its initial framebuffer content was simply everything that was on the screen right before the window's creation. If a OpenGL context is created on top of this, the framebuffer could be read out using glReadPixels, that way creating a screenshot.
Today window compositing has become the norm which makes abusing OpenGL for taking screenshots almost impossible. With compositing each window has its own off-screen framebuffer and the screen's contents are composited only at the end. If you used that method outlined above, which relies on uninitialized memory containing the desired content, on a compositing window system, the results will vary wildly, between solid clear color, over wildly distorted junk fragments, to data noise.
Since taking a screenshot reliably must take into account a lot of idiosyncrasy of the system this is to happen on, it's virtually impossible to write a truly portable screenshot program.
And OpenGL is definitely the wrong tool for it, no matter that people (including myself) were able to abuse it for such in the past.
I programmed this C code to capture the screen of Macs and to show it in an OpenGL window through the function glDrawPixels:
opengl-capture.c
http://pastebin.com/pMH2rDNH
Coding the FFI for Haskell is quite trivial. I'll do it soon.
This might be useful to find the solution in C:
NeHe Productions - Using gluUnProject
http://nehe.gamedev.net/article/using_gluunproject/16013/
Apple Mailing Lists - Re: Screen snapshot example code posted
http://lists.apple.com/archives/cocoa-dev/2005/Aug/msg00901.html
Compiling OpenGL programs on Windows, Linux and OS X
http://goanna.cs.rmit.edu.au/~gl/teaching/Interactive3D/2012/compiling.html
Grab Mac OS Screen using GL_RGB format
I just hit something particularly hard to debug when doing some pretty intensive rendering with Canvas2D. I use all kinds of things, from globalCompositeOperation to multiple off-screen canvases, with some drawImage magic in-between.
It works perfectly fine and smooth on :
Chrome (26) [OSX 10.7.5]
Safari (6.0.2) [OSX 10.7.5]
Firefox (Both 18 and 20 Aurora) [OSX 10.7.5]
Chrome (24) [Windows 7]
Firefox (12) [Windows 7]
Chromium (24) [Archlinux, Gnome 3]
EDIT: Added tests for Windows 7. Strangely enough, it works for FF12 (I had an old version on my dual boot) but there's a definite performance hit after upgrading to FF18. It's not as bad on Windows as it is on Linux though, and the same version on OSX works flawlessly. Regression maybe?
For some reason, on Firefox and Linux (I tried both 18 and 20 Aurora), I have bad rendering performances when dragging and rendering at the same time.
If I fire-and-forget an animation, it is on par with Chrome/Safari, but if I drag and render, I often end up only seeing the end frame after I release the drag.
Neither requestAnimationFrame nor a direct rendering on the mouse event handler work.
After profiling, the reported timings for the rendering parts are well within the range of acceptable (up to 100ms at the absolute worst), and definitely do not correspond to what I see on the screen.
I tried reducing the load by removing some stuff, ending up with reported render times under 15ms, but what I saw didn't change.
What baffles me is that it works almost everywhere else except with Firefox on Linux. Any idea as to where I should look, a bug report or a solution to my problem?
I have fully switched to Chrome on linux because of this issue. It stems from the old 2d rendering engine they are using called Cairo, which is old and out-dated. Azure was to replace this engine and they have it done basically all the platforms except linux.
http://blog.mozilla.org/joe/2011/04/26/introducing-the-azure-project/
https://bugzilla.mozilla.org/show_bug.cgi?id=781731
I think I know where you should look based on this:
If I fire-and-forget an animation, it is on par with Chrome/Safari, but if I drag and render, I often end up only seeing the end frame after I release the drag.
This is probably a double-buffering bug with Firefox on linux.
Canvas implementations have double-buffering built in. You can see it in action on any browser in a simple example like this one: http://jsfiddle.net/simonsarris/XzAjv/ (which uses a setTimeout vs extra work to illustrate that clearing does not happen right away)
The implementations try to delay all rendering by rendering it to an internal bitmap, and then all at once (at the next pause) render it to the canvas. This stops the "flickering" effect when clearing a canvas before redrawing a scene, which is good.
But it seems there's a plain old bug in the Linux Firefox. During your drag and render it seems to not be updating the canvas, probably in an attempt to buffer, but seems to be doing so when it should not be. This would explain why it works in fire-and-forget scenarios.
So I think a bug report is in order. I haven't got any linux machines lying around so I can't reproduce it and submit something myself to be certain though, sorry.
This is in reply to a comment: You could, during the mouse move, dispatch the drawing portion to a tiny timer.
For instance:
// The old way
theCanvas.addEventListener('mousemove', function() {
// if we're dragging and are redrawing
drawingCode();
}, false);
// The new way
theCanvas.addEventListener('mousemove', function() {
// if we're dragging and are redrawing
// in 1 millisecond, fire off drawing code
setTimeout(function() { drawingCode(); }, 1);
}, false);
There isn't such a method, its totally hidden. What you could do is, during mouse move, dispatch