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.
Related
I'm currently making a project in my IT School and I work with SDL (The project is image processing and stuff like that), and currently I just display the image with SDL without interface (buttons etc...). I know a little bit about GTK so I want to know if I can display an image (here a SDL_Surface) into a GTK window
I made some research but nothing was very clear...
Thank you !
Drawing widgets using SDL
Drawing widgets(menu, buttons etc) using SDL drawing functions and handling actions by tracking the cursor position during the occurrence of event(on which item the cursor was while the event was performed).
This becomes very complicated and would be better to use an existing GUI library with some simple hacks. You can find code example for drawing a button here.
Copying SDL surface into target GUI widget
This involves copying pixel by pixel(predefined functions might be available to do the same, gdk_draw_rgb_image in case of gtk) of the sdl surface into target gui widget(can be a drawingArea in case of GTK).
Merging SDL window into a GUI widget
In X11 and win32 systems each windows are given with a window id and by default sdl and gtk would have separate window id resulting two different windows, we can exploit SDL_CreateWindowFrom function to use single window for sdl and gtk in which we will force both the libraries to use a single window id.
You can find similar question here.
GTK Plug and Socket
Plug and Socket enables embeeding widget from one process to another. GTK will create a socket and pass the socket id to SDL and SDL would create window from that socket ID.
Event loop handling:
After merging SDL with GTK you might find gtk and sdl have their own event loops hence handling events might not be as expected. To solve that issue you can handle
events in GTK and propagate the event to SDL using SDL_PushEvent function and vice versa in case you are using user defined events.
.
.
static SDL_Event SDLevent;
switch(event->keyval)
{
case GDK_KEY_m:
SDLevent.type = SDL_KEYUP;
SDLevent.key.keysym.sym = SDLK_m;
SDL_PushEvent(&SDLevent);
break;
.
.
.
This link has a nice explanation for above methods.
I need to get the OpenGL Context (an HGLRC) from a window (or device context). The function wglGetCurrentContext cannot be used since I do not know whether or not the context is bound to the current thread. How can this be done?
I need to get the OpenGL Context (an HGLRC) from a window (or device context).
You can't!
OpenGL render contexts are in no way tied to windows, at all.
Windows can have an arbitrary number of device contexts. There's at least one primary context, but additional contexts can be created at any time.
OpenGL render contexts can be made active on any device context (DC) that is compatible, but there is – again – no strict tie between a DC and a OpenGL context. As long as any given window's device context is compatible to a certain OpenGL context the OpenGL context can be made current on the device context. Later, if one desires so, that connection can be undone and the same OpenGL context can be made current on a different DC of a different window (as long as they're compatible).
Oh, and it also works the other way round: You can have an arbitrary number of threads, each having a different OpenGL context active on the same window/device context simultanously.
There simply is no bijective mapping between windows and OpenGL contexts.
You can use wglGetCurrentContext() to check if there's a context currently bound. But there isn't any function that can be used to check whether a HDC is associated with a HGLRC.
These are the only functions in relation to getting each other:
HDC GetDC(HWND hWnd)
HWND WindowFromDC(HDC hdc)
// Depends on wglMakeCurrent()
HDC wglGetCurrentDC()
HGLRC wglGetCurrentContext()
So you'd need to keep track of the HGLRC after creating it.
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.
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.
How to set the position of the stage or window using clutter1.0? Just like in opengl glutInitWindowPosition(0, 500). Thanks...
Clutter does not provide a wrapper around windowing system specific API: the Stage, as a scene graph element, is defined to always be at (0, 0), so you cannot use the ClutterActor set_position() method on it.
if you're on X11, you can use the X11 API to move a stage Window, e.g.:
Display *xdpy = clutter_x11_get_default_display ();
Window xwin = clutter_x11_stage_get_window (stage);
XMoveWindow (xdpy, xwin, 0, 500);
obviously, there's the whole thorny issue of manual window placement in X11: you should not really do that, and you should defer to the window manager to actually position your windows.
on Windows, you can get the WHND of the Stage window using clutter_win32_get_stage_window() and use SetWindowPos() similarly to how it works on X11.
on OS X is a bit trickier, as Clutter does not expose the NSWindow nor the NSView used by the Stage, as of yet, so you'll have to hack a bit inside Clutter.