X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=libs%2Fgtkutil%2Fglwidget.cpp;h=f463b8b30268f2617a019c62287ba1a54bee8bee;hb=e3af470d9d19e105c9a9c6228931ee2645d09371;hp=746b8f0f9202d34b92a8a0c079ff98591a0ff4e4;hpb=e4287c28bb2dafedc81c66e63951d947cfbeb225;p=xonotic%2Fnetradiant.git diff --git a/libs/gtkutil/glwidget.cpp b/libs/gtkutil/glwidget.cpp index 746b8f0f..f463b8b3 100644 --- a/libs/gtkutil/glwidget.cpp +++ b/libs/gtkutil/glwidget.cpp @@ -23,235 +23,283 @@ #include "glwidget.h" -#include "debugging/debugging.h" - #include "igl.h" -#include -#include +void (*GLWidget_sharedContextCreated)() = 0; -#include "pointer.h" +void (*GLWidget_sharedContextDestroyed)() = 0; -void ( *GLWidget_sharedContextCreated )() = 0; -void ( *GLWidget_sharedContextDestroyed )() = 0; +unsigned int g_context_count = 0; +ui::GLArea g_shared{ui::null}; -typedef int* attribs_t; -struct config_t +static void _glwidget_context_created(ui::GLArea self, void *data) { - const char* name; - attribs_t attribs; -}; -typedef const config_t* configs_iterator; - -int config_rgba32[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 24, - GDK_GL_ATTRIB_LIST_NONE, -}; + if (++g_context_count == 1) { + g_shared = self; + g_object_ref(g_shared._handle); -int config_rgba[] = { - GDK_GL_RGBA, - GDK_GL_DOUBLEBUFFER, - GDK_GL_BUFFER_SIZE, 16, - GDK_GL_ATTRIB_LIST_NONE, -}; + glwidget_make_current(g_shared); + GlobalOpenGL().contextValid = true; -const config_t configs[] = { - { - "colour-buffer = 32bpp, depth-buffer = none", - config_rgba32, - }, - { - "colour-buffer = 16bpp, depth-buffer = none", - config_rgba, - } -}; + GLWidget_sharedContextCreated(); + } +} -GdkGLConfig* glconfig_new(){ - GdkGLConfig* glconfig = 0; +static void _glwidget_context_destroyed(ui::GLArea self, void *data) +{ + if (--g_context_count == 0) { + GlobalOpenGL().contextValid = false; - 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; - } - } + GLWidget_sharedContextDestroyed(); - 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 ) ); + g_shared.unref(); + g_shared = ui::GLArea(ui::null); + } } -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, -}; - -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, -}; - -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, -}; +void glwidget_destroy_context(ui::GLArea self) +{ +} -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, -}; +void glwidget_create_context(ui::GLArea self) +{ +} -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, -}; +#if GTK_TARGET == 3 -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, -}; +#include -const config_t configs_with_depth[] = +static GdkGLContext *glwidget_context_created(ui::GLArea self) { - { - "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, - }, -}; - -GdkGLConfig* glconfig_new_with_depth(){ - GdkGLConfig* glconfig = 0; + _glwidget_context_created(self, nullptr); + return gtk_gl_area_get_context(self); +} - 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; - } - } +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 - 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 ) ); + self.connect("realize", G_CALLBACK(glwidget_context_created), nullptr); + return self; } -unsigned int g_context_count = 0; +bool glwidget_make_current(ui::GLArea self) +{ +// if (!g_context_count) { +// glwidget_context_created(self); +// } + gtk_gl_area_make_current(self); + auto valid = GlobalOpenGL().contextValid; + return true; +} -namespace +void glwidget_swap_buffers(ui::GLArea self) { -GtkWidget* g_shared = 0; + g_assert(GTK_IS_GL_AREA(self)); + gtk_gl_area_queue_render(self); } -gint glwidget_context_created( GtkWidget* widget, gpointer data ){ - if ( ++g_context_count == 1 ) { - g_shared = widget; - gtk_widget_ref( g_shared ); +#endif - glwidget_make_current( g_shared ); - GlobalOpenGL().contextValid = true; +#if GTK_TARGET == 2 - GLWidget_sharedContextCreated(); - } - return FALSE; -} +#include +#include + +#include "pointer.h" + +struct config_t { + const char *name; + int *attribs; +}; +typedef const config_t *configs_iterator; + +static int config_rgba32[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 24, + GDK_GL_ATTRIB_LIST_NONE, +}; -gint glwidget_context_destroyed( GtkWidget* widget, gpointer data ){ - if ( --g_context_count == 0 ) { - GlobalOpenGL().contextValid = false; +static int config_rgba[] = { + GDK_GL_RGBA, + GDK_GL_DOUBLEBUFFER, + GDK_GL_BUFFER_SIZE, 16, + GDK_GL_ATTRIB_LIST_NONE, +}; - GLWidget_sharedContextDestroyed(); +static const config_t configs[] = { + { + "colour-buffer = 32bpp, depth-buffer = none", + config_rgba32, + }, + { + "colour-buffer = 16bpp, depth-buffer = none", + config_rgba, + } +}; - gtk_widget_unref( g_shared ); - g_shared = 0; - } - return FALSE; +static GdkGLConfig *glconfig_new() +{ + 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)); } -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" ); +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, +}; - gtk_widget_set_gl_capability( widget, glconfig, g_shared != 0 ? gtk_widget_get_gl_context( g_shared ) : 0, TRUE, GDK_GL_RGBA_TYPE ); +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, +}; - gtk_widget_realize( widget ); - if ( g_shared == 0 ) { - g_shared = widget; - } +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, +}; - // free glconfig? - } - return FALSE; -} +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, +}; -GtkWidget* glwidget_new( gboolean zbuffer ){ - GtkWidget* widget = gtk_drawing_area_new(); +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, +}; - g_object_set_data( G_OBJECT( widget ), "zbuffer", gint_to_pointer( zbuffer ) ); +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, +}; - g_signal_connect( G_OBJECT( widget ), "hierarchy-changed", G_CALLBACK( glwidget_enable_gl ), 0 ); +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() +{ + 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)); +} - 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 ); +static int glwidget_context_created(ui::GLArea self, void *data) +{ + _glwidget_context_created(self, data); + return false; +} - return widget; +int glwidget_context_destroyed(ui::GLArea self, void *data) +{ + _glwidget_context_destroyed(self, data); + return false; } -void glwidget_destroy_context( GtkWidget *widget ){ +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; } -void glwidget_create_context( GtkWidget *widget ){ +ui::GLArea glwidget_new(bool zbuffer) +{ + auto self = ui::GLArea::from(gtk_drawing_area_new()); + + g_object_set_data(G_OBJECT(self), "zbuffer", gint_to_pointer(zbuffer)); + + self.connect("hierarchy-changed", G_CALLBACK(glwidget_enable_gl), 0); + + self.connect("realize", G_CALLBACK(glwidget_context_created), 0); + self.connect("unrealize", G_CALLBACK(glwidget_context_destroyed), 0); + + return self; } -void glwidget_swap_buffers( GtkWidget *widget ){ - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable( widget ); - gdk_gl_drawable_swap_buffers( gldrawable ); +void glwidget_swap_buffers(ui::GLArea self) +{ + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(self); + gdk_gl_drawable_swap_buffers(gldrawable); } -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 ); +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); } + +#endif