X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=libs%2Fgtkutil%2Fglwidget.cpp;h=8581f7a4a4ef779a0840126e070dd40f21286e12;hb=6736a42a923644f539845a04c153fb3caf153b34;hp=3f9b9a00ac1dc9ab1c3387d251734fe0313c1e7a;hpb=c52a4bd4da209e657018e8d799dcb488cd848e4c;p=xonotic%2Fnetradiant.git diff --git a/libs/gtkutil/glwidget.cpp b/libs/gtkutil/glwidget.cpp index 3f9b9a00..8581f7a4 100644 --- a/libs/gtkutil/glwidget.cpp +++ b/libs/gtkutil/glwidget.cpp @@ -19,239 +19,285 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -// OpenGL widget based on GtkGLExt +// OpenGL widget based on GtkGLExt / GtkGLArea #include "glwidget.h" -#include "debugging/debugging.h" - #include "igl.h" -#include -#include +// Function callbacks +static void (*sharedContextCreated)() = nullptr; +static void (*sharedContextDestroyed)() = nullptr; -#include "pointer.h" +unsigned int g_context_count = 0; + +ui::GLArea g_shared{ui::null}; + +static void _glwidget_context_created(ui::GLArea self, void *data) +{ + if (++g_context_count == 1) { + g_shared = self; + g_object_ref(g_shared._handle); -void ( *GLWidget_sharedContextCreated )() = 0; -void ( *GLWidget_sharedContextDestroyed )() = 0; + glwidget_make_current(g_shared); + GlobalOpenGL().contextValid = true; + sharedContextCreated(); + } +} -typedef int* attribs_t; -struct config_t +static void _glwidget_context_destroyed(ui::GLArea self, void *data) { - const char* name; - attribs_t attribs; -}; -typedef const config_t* configs_iterator; + if (--g_context_count == 0) { + GlobalOpenGL().contextValid = false; -int config_rgba32[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 24, - GDK_GL_ATTRIB_LIST_NONE, -}; + sharedContextDestroyed(); -int config_rgba[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 16, - GDK_GL_ATTRIB_LIST_NONE, -}; + g_shared.unref(); + g_shared = ui::GLArea(ui::null); + } +} -const config_t configs[] = { - { - "colour-buffer = 32bpp, depth-buffer = none", - config_rgba32, - }, - { - "colour-buffer = 16bpp, depth-buffer = none", - config_rgba, - } -}; +void glwidget_set_shared_context_constructors( + void created(), void destroyed() ) +{ + sharedContextCreated = created; + sharedContextDestroyed = destroyed; +} -GdkGLConfig* glconfig_new(){ - GdkGLConfig* glconfig = 0; +#if GTK_TARGET == 3 - for ( configs_iterator i = configs, end = configs + 2; i != end; ++i ) - { - glconfig = gdk_gl_config_new( ( *i ).attribs ); - if ( glconfig != 0 ) { - globalOutputStream() << "OpenGL window configuration: " << ( *i ).name << "\n"; - return glconfig; - } - } +#include - globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = none\n"; - return gdk_gl_config_new_by_mode( (GdkGLConfigMode)( GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE ) ); +static GdkGLContext *glwidget_context_created(ui::GLArea self) +{ + _glwidget_context_created(self, nullptr); + return gtk_gl_area_get_context(self); } -int config_rgba32_depth32[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 24, - GDK_GL_DEPTH_SIZE, 32, - GDK_GL_ATTRIB_LIST_NONE, -}; +ui::GLArea glwidget_new(bool zbuffer) +{ + auto self = ui::GLArea::from(GTK_GL_AREA(gtk_gl_area_new())); + gtk_gl_area_set_has_depth_buffer(self, zbuffer); + gtk_gl_area_set_auto_render(self, true); // FIXME -int config_rgba32_depth24[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 24, - GDK_GL_DEPTH_SIZE, 24, - GDK_GL_ATTRIB_LIST_NONE, -}; + self.connect("realize", G_CALLBACK(glwidget_context_created), nullptr); + return self; +} -int config_rgba32_depth16[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 24, - GDK_GL_DEPTH_SIZE, 16, - GDK_GL_ATTRIB_LIST_NONE, +bool glwidget_make_current(ui::GLArea self) +{ +// if (!g_context_count) { +// glwidget_context_created(self); +// } + gtk_gl_area_make_current(self); + return true; +} + +void glwidget_swap_buffers(ui::GLArea self) +{ + g_assert(GTK_IS_GL_AREA(self)); + gtk_gl_area_queue_render(self); +} + +#endif + +#if GTK_TARGET == 2 + +#include +#include + +#include "pointer.h" + +struct config_t { + const char *name; + int *attribs; }; +typedef const config_t *configs_iterator; -int config_rgba32_depth[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 24, - GDK_GL_DEPTH_SIZE, 1, - GDK_GL_ATTRIB_LIST_NONE, +static int config_rgba32[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 24, + GDK_GL_ATTRIB_LIST_NONE, }; -int config_rgba_depth16[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 16, - GDK_GL_DEPTH_SIZE, 16, - GDK_GL_ATTRIB_LIST_NONE, +static int config_rgba[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 16, + GDK_GL_ATTRIB_LIST_NONE, }; -int config_rgba_depth[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 16, - GDK_GL_DEPTH_SIZE, 1, - GDK_GL_ATTRIB_LIST_NONE, +static const config_t configs[] = { + { + "colour-buffer = 32bpp, depth-buffer = none", + config_rgba32, + }, + { + "colour-buffer = 16bpp, depth-buffer = none", + config_rgba, + } }; -const config_t configs_with_depth[] = +static GdkGLConfig *glconfig_new() { - { - "colour-buffer = 32bpp, depth-buffer = 32bpp", - config_rgba32_depth32, - }, - { - "colour-buffer = 32bpp, depth-buffer = 24bpp", - config_rgba32_depth24, - }, - { - "colour-buffer = 32bpp, depth-buffer = 16bpp", - config_rgba32_depth16, - }, - { - "colour-buffer = 32bpp, depth-buffer = auto", - config_rgba32_depth, - }, - { - "colour-buffer = 16bpp, depth-buffer = 16bpp", - config_rgba_depth16, - }, - { - "colour-buffer = auto, depth-buffer = auto", - config_rgba_depth, - }, + for (configs_iterator i = configs, end = configs + 2; i != end; ++i) { + if (auto glconfig = gdk_gl_config_new(i->attribs)) { + globalOutputStream() << "OpenGL window configuration: " << i->name << "\n"; + return glconfig; + } + } + globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = none\n"; + return gdk_gl_config_new_by_mode((GdkGLConfigMode) (GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE)); +} + +static int config_rgba32_depth32[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, + 24, + GDK_GL_DEPTH_SIZE, + 32, + GDK_GL_ATTRIB_LIST_NONE, }; -GdkGLConfig* glconfig_new_with_depth(){ - GdkGLConfig* glconfig = 0; +static int config_rgba32_depth24[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 24, + GDK_GL_DEPTH_SIZE, 24, + GDK_GL_ATTRIB_LIST_NONE, +}; - for ( configs_iterator i = configs_with_depth, end = configs_with_depth + 6; i != end; ++i ) - { - glconfig = gdk_gl_config_new( ( *i ).attribs ); - if ( glconfig != 0 ) { - globalOutputStream() << "OpenGL window configuration: " << ( *i ).name << "\n"; - return glconfig; - } - } +static int config_rgba32_depth16[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 24, + GDK_GL_DEPTH_SIZE, 16, + GDK_GL_ATTRIB_LIST_NONE, +}; - globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = auto (fallback)\n"; - return gdk_gl_config_new_by_mode( (GdkGLConfigMode)( GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE | GDK_GL_MODE_DEPTH ) ); -} +static int config_rgba32_depth[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 24, + GDK_GL_DEPTH_SIZE, 1, + GDK_GL_ATTRIB_LIST_NONE, +}; -unsigned int g_context_count = 0; +static int config_rgba_depth16[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 16, + GDK_GL_DEPTH_SIZE, 16, + GDK_GL_ATTRIB_LIST_NONE, +}; -namespace +static int config_rgba_depth[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 16, + GDK_GL_DEPTH_SIZE, 1, + GDK_GL_ATTRIB_LIST_NONE, +}; + +static const config_t configs_with_depth[] = + { + { + "colour-buffer = 32bpp, depth-buffer = 32bpp", + config_rgba32_depth32, + }, + { + "colour-buffer = 32bpp, depth-buffer = 24bpp", + config_rgba32_depth24, + }, + { + "colour-buffer = 32bpp, depth-buffer = 16bpp", + config_rgba32_depth16, + }, + { + "colour-buffer = 32bpp, depth-buffer = auto", + config_rgba32_depth, + }, + { + "colour-buffer = 16bpp, depth-buffer = 16bpp", + config_rgba_depth16, + }, + { + "colour-buffer = auto, depth-buffer = auto", + config_rgba_depth, + }, + }; + +static GdkGLConfig *glconfig_new_with_depth() { -GtkWidget* g_shared = 0; + for (configs_iterator i = configs_with_depth, end = configs_with_depth + 6; i != end; ++i) { + if (auto glconfig = gdk_gl_config_new(i->attribs)) { + globalOutputStream() << "OpenGL window configuration: " << i->name << "\n"; + return glconfig; + } + } + globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = auto (fallback)\n"; + return gdk_gl_config_new_by_mode((GdkGLConfigMode) (GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE | GDK_GL_MODE_DEPTH)); } -gint glwidget_context_created( GtkWidget* widget, gpointer data ){ - if ( ++g_context_count == 1 ) { - g_shared = widget; - g_object_ref( g_shared ); - - glwidget_make_current( g_shared ); - GlobalOpenGL().contextValid = true; - - GLWidget_sharedContextCreated(); - } - return FALSE; +static int glwidget_context_created(ui::GLArea self, void *data) +{ + _glwidget_context_created(self, data); + return false; } -gint glwidget_context_destroyed( GtkWidget* widget, gpointer data ){ - if ( --g_context_count == 0 ) { - GlobalOpenGL().contextValid = false; - - GLWidget_sharedContextDestroyed(); - - g_object_unref( g_shared ); - g_shared = 0; - } - return FALSE; +int glwidget_context_destroyed(ui::GLArea self, void *data) +{ + _glwidget_context_destroyed(self, data); + return false; } -gboolean glwidget_enable_gl( GtkWidget* widget, GtkWidget* widget2, gpointer data ){ - if ( widget2 == 0 && !gtk_widget_is_gl_capable( widget ) ) { - GdkGLConfig* glconfig = ( g_object_get_data( G_OBJECT( widget ), "zbuffer" ) ) ? glconfig_new_with_depth() : glconfig_new(); - ASSERT_MESSAGE( glconfig != 0, "failed to create OpenGL config" ); - - gtk_widget_set_gl_capability( widget, glconfig, g_shared != 0 ? gtk_widget_get_gl_context( g_shared ) : 0, TRUE, GDK_GL_RGBA_TYPE ); - - gtk_widget_realize( widget ); - if ( g_shared == 0 ) { - g_shared = widget; - } - - // free glconfig? - } - return FALSE; +static bool glwidget_enable_gl(ui::GLArea self, ui::Widget root, gpointer data) +{ + if (!root && !gtk_widget_is_gl_capable(self)) { + const auto zbuffer = g_object_get_data(G_OBJECT(self), "zbuffer"); + GdkGLConfig *glconfig = zbuffer ? glconfig_new_with_depth() : glconfig_new(); + ASSERT_MESSAGE(glconfig, "failed to create OpenGL config"); + + const auto share_list = g_shared ? gtk_widget_get_gl_context(g_shared) : nullptr; + gtk_widget_set_gl_capability(self, glconfig, share_list, true, GDK_GL_RGBA_TYPE); + + gtk_widget_realize(self); + if (!g_shared) { + g_shared = self; + } + // free glconfig? + } + return false; } -GtkWidget* glwidget_new( gboolean zbuffer ){ - GtkWidget* widget = gtk_drawing_area_new(); - - g_object_set_data( G_OBJECT( widget ), "zbuffer", gint_to_pointer( zbuffer ) ); +ui::GLArea glwidget_new(bool zbuffer) +{ + auto self = ui::GLArea::from(gtk_drawing_area_new()); - g_signal_connect( G_OBJECT( widget ), "hierarchy-changed", G_CALLBACK( glwidget_enable_gl ), 0 ); + g_object_set_data(G_OBJECT(self), "zbuffer", gint_to_pointer(zbuffer)); - g_signal_connect( G_OBJECT( widget ), "realize", G_CALLBACK( glwidget_context_created ), 0 ); - g_signal_connect( G_OBJECT( widget ), "unrealize", G_CALLBACK( glwidget_context_destroyed ), 0 ); + self.connect("hierarchy-changed", G_CALLBACK(glwidget_enable_gl), 0); - return widget; -} + self.connect("realize", G_CALLBACK(glwidget_context_created), 0); + self.connect("unrealize", G_CALLBACK(glwidget_context_destroyed), 0); -void glwidget_destroy_context( GtkWidget *widget ){ + return self; } -void glwidget_create_context( GtkWidget *widget ){ +void glwidget_swap_buffers(ui::GLArea self) +{ + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(self); + gdk_gl_drawable_swap_buffers(gldrawable); } -void glwidget_swap_buffers( GtkWidget *widget ){ - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable( widget ); - gdk_gl_drawable_swap_buffers( gldrawable ); +bool glwidget_make_current(ui::GLArea self) +{ + GdkGLContext *glcontext = gtk_widget_get_gl_context(self); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(self); + return gdk_gl_drawable_gl_begin(gldrawable, glcontext); } -gboolean glwidget_make_current( GtkWidget *widget ){ - GdkGLContext *glcontext = gtk_widget_get_gl_context( widget ); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable( widget ); - return gdk_gl_drawable_gl_begin( gldrawable, glcontext ); -} +#endif