GtkWidget: Alternative for deprecated "double-buffered" property? - c

I've derived my own widget type from GtkWidget in order to use it as a drawing surface for OpenGL. To give OpenGL control over the underlying X11 Window, I need to disable the widget's double buffering - else the whole rendering result will be drawn over by GTK's buffer swap.
However, gtk_widget_set_double_buffered and the "double-buffered" property have been deprecated in the current version of GTK+3 for being too platform-dependent.
Is there a way to disable double buffering on the GDK or X11 level instead?

This is a rather old question, but I'll give it a shot.
In any even slightly more recent context (i.e. with GTK+ >= 3.16, which is over 6 years old by now), I guess the best solution would be to avoid rolling your own OpenGL widget and just use Gtk.GLArea instead: https://docs.gtk.org/gtk3/class.GLArea.html
Alternatively, if you happen to be stuck with an ancient GTK+ version, maybe on an embedded device, then there aren't many options besides gtk_widget_set_double_buffered (see also https://people.gnome.org/~shaunm/girdoc/C/Gtk.Widget.set_double_buffered.html): this does not set any X11/Xorg window flags or similar, but just changes the internal event handling of GTK+ to either send draw calls to an offscreen buffer, or directly to the visible surface.
Note that this offscreen buffer is completely separate from anything involving X or OpenGL.

Related

ncurses blit / buffer

I am looking for a way to create a "buffer" which I can directly copy, or blit, onto a WINDOW* using ncurses. I know there are subwindows, but since the only way to move/ resize them is to create a whole new subwindow, they are not a great fit. I'm looking for something like Microsoft's WriteConsoleOutput.
Would be nice if I could also copy regions, in a reverse-blit fashion (take rect of stdscr and store a copy in a buffer)
windows can in fact be moved or resized without re-creating them:
mvwin
Calling mvwin moves the window so that the upper left-hand corner is at
position (x, y). If the move would cause the window to be off the
is allowed, but should be avoided.
wresize
This is an extension to the curses library. It reallocates storage for
an ncurses window to adjust its dimensions to the specified values. If
either dimension is larger than the current values, the window's data
is filled with blanks that have the current background rendition (as
set by wbkgdset) merged into them.
This extension of ncurses was introduced in mid-1995. It was adopted
in NetBSD curses (2001) and PDCurses (2003).
Regarding the question, updates to a window are based on lines (see waddchnstr for instance).

How to render to multiple windows using a single OpenGL context?

I created two windows using GLFW. The first window has an OpenGL context and the second one doesn't. What I want to do is render the same scene to both windows using a single OpenGL context. Something like this.
glBindVertexArray(vaoId);
// ... tell OpenGL to draw on first window
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(...);
// ... swap first window buffers
// ... tell OpenGL to draw on second window
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(...);
// ... swap second window buffers
glBindVertexArray(0);
The problem is I don't know how to tell OpenGL to draw on a specific window. And I also don't know how to swap buffers for a specific window. If it's necessary, I can use Win32 API.
As far as I'm aware, GLFW does not directly support that in it's API. It generally considers a Window and a GL context as a unit. However, with the native APIs, you can do what you want. For windows 32 in partiuclar, have a look at wglMakeCurrent(). In GLFW, you can get the required context and window handles via GLFW's native access API. Note that you will only get a HWND that way, you will have to manually use GetDC() to get the device context of the window.
Be aware that switching contexts will imply flushing the GL command queue, which can have negative effects on the performance. See GL_KHR_context_flush_control for more details.

Precision timing of GDK3/GTK3 window update

I have an application written in C using GTK (although the language is probably unimportant for this question).
This application has a fullscreengtk_window with a single gtk_drawing_area. For the drawing area, I have registered a tick callback via gtk_widget_add_tick_callback which just calls gtk_widget_queue_draw every tick. Inside the drawing area draw callback, I change the color of the entire window at regular intervals (e.g., from black to white at 1Hz).
Say that in this call to the draw callback I want to change the window from black to white. I would like to know the precise time (down to the nearest ms) that the change is actually drawn on the screen (ideally in the same units as CLOCK_MONOTONIC). I don't think this is the same thing as the GdkFrameClock available in the tick callback, which, as I understand it, is about the time of the frame, not the time when the frame is actually displayed on the screen.
If I just measure the CLOCK_MONOTONIC time in the drawing callback, and then use a photo-diode to measure when the actual change is via an attached A2D, the actual change is the display is understandably delayed by a number of refresh intervals (in my case, 3 screen refreshes).
Just as a summary: if I am in a GTK widget draw callback, is there any way to know the time when the display will actually be shown on the monitor in the units of CLOCK_MONOTONIC? Or alternatively, is there a way that I can block a separate thread until a specific redraw that I care about is actually displayed on the screen (a function I can write like wait_for_screen_flip())?
Update: Ideally, the same solution would work for any Linux compositor (X11 or Wayland), which is why I am hoping for a GTK/GDK solution, where the compositor is abstracted away.
Similarly to Uli's answer of the Present extension and PresentCompleteNotify for X11, Wayland has a similar protocol called wp_presentation_feedback:
https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/presentation-time/presentation-time.xml
This protocol allows the Wayland compositor to inform clients when their content was actually displayed (turned to light). It is independent of the actual buffer mechanism used (EGL/SHM/etc). To use it, you call wp_presentation_get_feedback before wl_surface_commit; when the commit has completed, a presented event will be sent to the client from the new wp_presentation_feedback object, or discarded if it was never shown.
Presentation feedback is currently implemented in Weston; it is not yet implemented in Mutter, and I don't believe it's implemented in KWin either. GTK+ plans to support it when it becomes available in Mutter, but I don't have any great insight as to how it would be exposed through the GTK+ API.
That being said, if you can get access to the Wayland display, it's possible that you could use the interface directly yourself.
I just came across https://developer.gnome.org/gdk3/stable/gdk3-GdkFrameTimings.html#gdk-frame-timings-get-presentation-time which seems to do just like what you want and is part of Gdk. I do not know how to use it nor have I seen some example of it, but https://developer.gnome.org/gdk3/stable/gdk3-GdkFrameTimings.html#gdk3-GdkFrameTimings.description says
The information in GdkFrameTimings is useful for precise synchronization of video with the event or audio streams, and for measuring quality metrics for the application’s display, such as latency and jitter.
Take a look at https://cgit.freedesktop.org/xorg/proto/presentproto/tree/presentproto.txt. Specifically, you want PresentCompleteNotify events. Note that these can only tell you later when presentation actually happened, so (I think) you will not know ahead of time when this is (but you could perhaps guess based on recent notifies?).
Note that this is
a relatively new X11 extension, so might not actually be supported everywhere
depends on the driver used (and likely lots of other factors) for the quality of data
cannot be used from GTK since it requires a different way to display to the screen (you draw to a Pixmap and then use PresentPixmap to make it visible and ask for a notify)
Also note that this extension provides lots of other things. You can for example say "please display at time ". Just read the protocol specification from start to end. :-)

Why this BitBlt example doesn't work anymore?

I'm currently getting back to some Windows Programming using Petzold's book (5th edition).
I compiled the following example using BitBlt and it doesn't work as it is supposed to.
It should copy the Window's icon of (CxSource, CySource) size and replicate it on the whole window's surface.
What happens, in reality, using Windows 7 is that the bitmap below the window gets sourced and copied into the drawing surface i.e. hdcClient.
I don't understand why it behaves like this knowing that it's clear the DC passed to BitBlt is hdcWindow, which refers to a device context obtained via a GetWindowDC(hwnd) of the current application.
I first thought it was due to the fact the transparency mode is enabled by default, but deactivating it doesn't change anything. BitBlt seems to always take the surface below the application Window!
I don't get it! :)
Anyone knows why it works that way and how to fix it?
Making screenshots with BitBlt() did not exactly get any easier since the addition of the DWM (Desktop Window Manager, aka Aero). Petzold's sample code suffers from a subtle timing issue, it is making the screenshot too soon. It does so while Aero is still busy animating the frame, fading it into view. So you see what is behind the window, possibly already partly faded depending on how quickly the first WM_PAINT message is generated.
You can easily fix it by disabling the effect:
#include <windows.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
And after the CreateWindow() call:
BOOL disabled = TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &disabled, sizeof(disabled));
Another tricky detail is that the first BitBlt matters, the DWM returns a cached copy afterwards that is not correctly invalidated by the animation.
This gets grittier when you need a screenshot of a window that belongs to another process. But that was already an issue before Aero, you had to wait long enough to ensure that the window was fully painted. Notable perhaps is the perf of BitBlt(), it gets bogged-down noticeably by having to do job of composing the final image from the window back-buffers. Lots of questions about that at SO, without happy answers.
It is not supposed to copy the windows icon, it is supposed to copy the windows titlebar part where the icon is located.
There are some issues with this (now 20 year old code):
GetSystemMetrics values cannot be used for window related dimensions anymore since GetSystemMetrics returns the classic sizes, not the Visual Style sizes.
Depending on the Windows version, the DWM might define the window size as something larger than your window (where it draws the window shadow and other effects).
Your example works OK on XP:
(There is a small problem because the titlebar is not square (unlike Windows 98/2000 that this example was designed for) so you see a issue in the top left where it is just white. I also modified the example slightly so it varies the HDC source location)
On a modern version of Windows it seems like the DWM or something is not able to properly emulate a simple window DC and parts of the shadow/border/effects area is part of the DC:
I don't know how to fix this but the example is pretty useless anyway, if you want to draw the window icon you should draw the HICON with DrawIconEx. If you want to draw custom non-client area stuff then you need to find more recent examples, not something that only supports the classic theme.

How do I determine non-rectangular drawing regions in Gtk+ 3 with cairo?

The Gtk+ 3 migration guide shows how the GdkEventExpose.region field can be used to provide a fine-grained area for re-rendering widgets. We already do something like this in Inkscape to avoid rendering excessive amounts of complicated stuff on our drawing canvas.
However, the example in the guide shows how to do this for the old Gtk+ 2 expose_event handler.
How do I do the equivalent in a new Gtk+ 3 draw handler, which receives a "ready-clipped" Cairo context as a parameter, rather than a GdkEventExpose?
I guess one possibility is to use cairo_copy_clip_rectangle_list on the "ready-clipped" cairo context to obtain a list of rectangles that make up the region to draw. Does anyone have any experience of using this? Does it seem like a sensible approach?
Yes, you should use cairo_copy_clip_rectangle_list() on the cairo_t that you get in your widget's ::draw() signal handler. See this commit for an example:
http://git.gnome.org/browse/vte/commit/?id=21a064ac8b5925108b0ab9bd6516664c8cd3e268
Since I have not much clue, I decided to check the source code. GDK emits a GDK_EXPOSE event on a window and creates the GdkEventExpose instance for this.
This event is then handled in gtk/gtkmain.c via gtk_widget_send_expose():
http://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?id=eecb9607a5c0ee38eadb446545beccd0922cb0b8#n6104
This function clips the cairo_t to GdkEventExpose.region, as you already learned in the docs.
This then calls _gtk_widget_draw_internal() which emits the actual draw signal:
http://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?id=eecb9607a5c0ee38eadb446545beccd0922cb0b8#n5726
As far as I can see, nothing here let's you access the clip region directly. In gtk_widget_send_expose() the GdkEvent is added as userdata to the cairo context. However, this is not accessible, because all the involved functions and variables are static. So you'll have to use cairo_copy_clip_rectangle_list().
However, this sounds quite inefficent. First gdk_cairo_region transforms the region into a number of calls to cairo_rectangle and then cairo transforms this from its internal representation into a cairo_rectangle_list_t (which may fail if the clip is, for some reason, not a region). If you see this being slow, it might make sense to have some shortcut for this added to gtk directly.

Resources