summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2014-08-14 11:10:00 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2014-08-14 11:20:37 +0100
commit19a0a6196bc7cc488a95f421bed19fe3f3e800e0 (patch)
treeb8c1babc17f5d24e9a1b8db53921345e508ae1f4
parent3398e2ea873deb13bdbb78f196f0034fad5ad1f2 (diff)
downloadgtk+-19a0a6196bc7cc488a95f421bed19fe3f3e800e0.tar.gz
gl: Rework pixel format validation
Instead of modifying the pixel format in place, we allow separating the pixel format from the effective pixel format we found. This means that caller code can keep a reference to the pixel format it creates, and re-use it to create new contexts on different displays, while the GL context can keep a reference to a valid pixel format to let the use query it. This allows GtkGLArea to keep its own user-supplied pixel format and reuse it without adding additional constraints as a result of a validation on a specific GdkDisplay.
-rw-r--r--gdk/gdkdisplay.c84
-rw-r--r--gdk/gdkdisplay.h9
-rw-r--r--gdk/gdkdisplayprivate.h6
-rw-r--r--gdk/gdkglcontext.c88
-rw-r--r--gdk/gdkglpixelformat.c7
-rw-r--r--gdk/x11/gdkglcontext-x11.c33
-rw-r--r--gdk/x11/gdkglcontext-x11.h1
-rw-r--r--gtk/gtkglarea.c12
8 files changed, 187 insertions, 53 deletions
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 0b564b5aab..71ef3c9608 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -2227,27 +2227,6 @@ gdk_error_trap_pop (void)
}
/*< private >
- * gdk_display_create_gl_context:
- * @display: a #GdkDisplay
- * @format: a #GdkGLPixelFormat
- * @share: (optional): an optional shared #GdkGLContext
- * @error: return location for a #GError
- *
- * Creates a new platform-specific #GdkGLContext for the
- * given @display and @format.
- *
- * Returns: (transfer full): the newly created #GdkGLContext
- */
-GdkGLContext *
-gdk_display_create_gl_context (GdkDisplay *display,
- GdkGLPixelFormat *format,
- GdkGLContext *share,
- GError **error)
-{
- return GDK_DISPLAY_GET_CLASS (display)->create_gl_context (display, format, share, error);
-}
-
-/*< private >
* gdk_display_destroy_gl_context:
* @display: a #GdkDisplay
* @context: a #GdkGLContext
@@ -2313,10 +2292,15 @@ gdk_display_get_current_gl_context (GdkDisplay *display)
* gdk_display_validate_gl_pixel_format:
* @display: a #GdkDisplay
* @format: a #GdkGLPixelFormat
+ * @validated_format: (out callee-allocates) (transfer full) (optional): return location for
+ * the validated #GdkGLPixelFormat
* @error: return location for a #GError
*
* Validates a #GdkGLPixelFormat for the given display.
*
+ * If the pixel format is valid, and @validated_format is not %NULL, the
+ * validated pixel format will be stored into @validated_format.
+ *
* If the pixel format is invalid, @error will be set.
*
* Returns: %TRUE if the pixel format is valid
@@ -2326,23 +2310,57 @@ gdk_display_get_current_gl_context (GdkDisplay *display)
gboolean
gdk_display_validate_gl_pixel_format (GdkDisplay *display,
GdkGLPixelFormat *format,
+ GdkGLPixelFormat **validated_format,
GError **error)
{
- return GDK_DISPLAY_GET_CLASS (display)->validate_gl_pixel_format (display, format, error);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+ g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (format), FALSE);
+ g_return_val_if_fail (validated_format == NULL || *validated_format == NULL, FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->validate_gl_pixel_format (display,
+ format, validated_format,
+ error);
}
/**
- * gdk_display_get_gl_context:
+ * gdk_display_create_gl_context:
* @display: a #GdkDisplay
* @format: a #GdkGLPixelFormat
- * @share: (optional): a shared #GdkGLContext, or %NULL
* @error: return location for a #GError
*
* Creates a new #GdkGLContext for the given display, with the given
* pixel format.
*
- * If @share is not %NULL then the newly created #GdkGLContext will
- * share resources with it.
+ * If the @format is invalid, or in case the creation of the #GdkGLContext
+ * failed, @error will be set.
+ *
+ * Returns: (transfer full): the newly created #GdkGLContext, or
+ * %NULL on error
+ *
+ * Since: 3.14
+ */
+GdkGLContext *
+gdk_display_create_gl_context (GdkDisplay *display,
+ GdkGLPixelFormat *format,
+ GError **error)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+ g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (format), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ return GDK_DISPLAY_GET_CLASS (display)->create_gl_context (display, format, NULL, error);
+}
+
+/**
+ * gdk_display_create_shared_gl_context:
+ * @display: a #GdkDisplay
+ * @format: a #GdkGLPixelFormat
+ * @shared_context: shared #GdkGLContext
+ * @error: return location for a #GError
+ *
+ * Creates a new #GdkGLContext for the given display, with the given
+ * pixel format; the newly created #GdkGLContext will share resources
+ * like the texture namespace and display lists with @shared_context.
*
* If the @format is invalid, or in case the creation of the #GdkGLContext
* failed, @error will be set.
@@ -2353,15 +2371,17 @@ gdk_display_validate_gl_pixel_format (GdkDisplay *display,
* Since: 3.14
*/
GdkGLContext *
-gdk_display_get_gl_context (GdkDisplay *display,
- GdkGLPixelFormat *format,
- GdkGLContext *share,
- GError **error)
+gdk_display_create_shared_gl_context (GdkDisplay *display,
+ GdkGLPixelFormat *format,
+ GdkGLContext *shared_context,
+ GError **error)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (format), NULL);
- g_return_val_if_fail (share == NULL || GDK_IS_GL_CONTEXT (share), NULL);
+ g_return_val_if_fail (GDK_IS_GL_CONTEXT (shared_context), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- return gdk_display_create_gl_context (display, format, share, error);
+ return GDK_DISPLAY_GET_CLASS (display)->create_gl_context (display, format,
+ shared_context,
+ error);
}
diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h
index 290c8811e3..1002b2f7be 100644
--- a/gdk/gdkdisplay.h
+++ b/gdk/gdkdisplay.h
@@ -174,11 +174,16 @@ GdkAppLaunchContext *gdk_display_get_app_launch_context (GdkDisplay *display);
GDK_AVAILABLE_IN_3_14
gboolean gdk_display_validate_gl_pixel_format (GdkDisplay *display,
GdkGLPixelFormat *format,
+ GdkGLPixelFormat **validated_format,
GError **error);
GDK_AVAILABLE_IN_3_14
-GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display,
+GdkGLContext * gdk_display_create_gl_context (GdkDisplay *display,
GdkGLPixelFormat *format,
- GdkGLContext *share,
+ GError **error);
+GDK_AVAILABLE_IN_3_14
+GdkGLContext * gdk_display_create_shared_gl_context (GdkDisplay *display,
+ GdkGLPixelFormat *format,
+ GdkGLContext *shared_context,
GError **error);
G_END_DECLS
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index 01e1f4ad25..81d90660d2 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -236,6 +236,7 @@ struct _GdkDisplayClass
GdkGLContext *context);
gboolean (*validate_gl_pixel_format) (GdkDisplay *display,
GdkGLPixelFormat *format,
+ GdkGLPixelFormat **valid_format,
GError **error);
/* Signals */
@@ -318,10 +319,7 @@ GdkWindow * _gdk_display_create_window (GdkDisplay *display
gboolean gdk_display_validate_gl_pixel_format (GdkDisplay *display,
GdkGLPixelFormat *format,
- GError **error);
-GdkGLContext * gdk_display_create_gl_context (GdkDisplay *display,
- GdkGLPixelFormat *format,
- GdkGLContext *share,
+ GdkGLPixelFormat **validated_format,
GError **error);
void gdk_display_destroy_gl_context (GdkDisplay *display,
GdkGLContext *context);
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 0764344390..cff8c79616 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -35,6 +35,92 @@
*
* A #GdkGLContext has to be associated with a #GdkWindow and
* made "current", otherwise any OpenGL call will be ignored.
+ *
+ * ## Creating a new OpenGL context ##
+ *
+ * In order to create a new #GdkGLContext instance you need a
+ * #GdkGLPixelFormat instance and a #GdkDisplay.
+ *
+ * The #GdkGLPixelFormat class contains configuration option that
+ * you require from the windowing system to be available on the
+ * #GdkGLContext.
+ *
+ * |[<!-- language="C" -->
+ * GdkGLPixelFormat *format;
+ *
+ * format = gdk_gl_pixel_format_new ("double-buffer", TRUE,
+ * "depth-size", 32,
+ * NULL);
+ * ]|
+ *
+ * The example above will create a pixel format with double buffering
+ * and a depth buffer size of 32 bits.
+ *
+ * You can either choose to validate the pixel format, in case you
+ * have the ability to change your drawing code depending on it, or
+ * just ask the #GdkDisplay to create the #GdkGLContext with it, which
+ * will implicitly validate the pixel format and return an error if it
+ * could not find an OpenGL context that satisfied the requirements
+ * of the pixel format:
+ *
+ * |[<!-- language="C" -->
+ * GError *error = NULL;
+ *
+ * // the "display" variable has been set elsewhere
+ * GdkGLContext *context =
+ * gdk_display_create_gl_context (display, format, &error);
+ *
+ * if (error != NULL)
+ * {
+ * // handle error condition
+ * }
+ *
+ * // you can release the reference on the pixel format at
+ * // this point
+ * g_object_unref (format);
+ * ]|
+ *
+ * ## Using a GdkGLContext ##
+ *
+ * In order to use a #GdkGLContext to draw with OpenGL commands
+ * on a #GdkWindow, it's necessary to bind the context to the
+ * window:
+ *
+ * |[<!-- language="C" -->
+ * // associates the window to the context
+ * gdk_gl_context_set_window (context, window);
+ * ]|
+ *
+ * This ensures that the #GdkGLContext can refer to the #GdkWindow,
+ * as well as the #GdkWindow can present the result of the OpenGL
+ * commands.
+ *
+ * You will also need to make the #GdkGLContext the current context
+ * before issuing OpenGL calls; the system sends OpenGL commands to
+ * whichever context is current. It is possible to have multiple
+ * contexts, so you always need to ensure that the one which you
+ * want to draw with is the current one before issuing commands:
+ *
+ * |[<!-- language="C" -->
+ * gdk_gl_context_make_current (context);
+ * ]|
+ *
+ * You can now perform your drawing using OpenGL commands.
+ *
+ * Once you finished drawing your frame, and you want to present the
+ * result on the window bound to the #GdkGLContext, you should call
+ * gdk_gl_context_flush_buffer().
+ *
+ * If the #GdkWindow bound to the #GdkGLContext changes size, you
+ * will need to call gdk_gl_context_update() to ensure that the OpenGL
+ * viewport is kept in sync with the size of the window.
+ *
+ * You can detach the currently bound #GdkWindow from a #GdkGLContext
+ * by using gdk_gl_context_set_window() with a %NULL argument.
+ *
+ * You can check which #GdkGLContext is the current one by using
+ * gdk_gl_context_get_current(); you can also unset any #GdkGLContext
+ * that is currently set by calling gdk_gl_context_clear_current().
*/
#include "config.h"
@@ -229,7 +315,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
/**
* GdkGLContext:visual:
*
- * The #GdkVisual used by the context.
+ * The #GdkVisual matching the #GdkGLPixelFormat used by the context.
*
* Since: 3.14
*/
diff --git a/gdk/gdkglpixelformat.c b/gdk/gdkglpixelformat.c
index 0f57fafd15..2ca08a2776 100644
--- a/gdk/gdkglpixelformat.c
+++ b/gdk/gdkglpixelformat.c
@@ -56,10 +56,11 @@
*
* |[<!-- language="C" -->
* GError *error = NULL;
+ * GdkGLPixelFormat *valid = NULL;
*
* // The "display" variable is set elsewhere.
* // The "format" variable is the one we set previously.
- * if (!gdk_display_validate_gl_pixel_format (display, format, &error))
+ * if (!gdk_display_validate_gl_pixel_format (display, format, &valid, &error))
* {
* // print "error" or create a new pixel format to validate
* }
@@ -72,11 +73,13 @@
* GdkGLContext *context;
* GError *error = NULL;
*
- * context = gdk_display_get_gl_context (display, format, NULL, &error);
+ * context = gdk_display_create_gl_context (display, format, &error);
* if (error != NULL)
* {
* // print error
* }
+ *
+ * g_object_unref (format);
* ]|
*
* Once a #GdkGLContext has been created with a #GdkGLPixelFormat, the
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 86c8d6d02f..9a22c1f65f 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -540,6 +540,7 @@ gdk_x11_display_create_gl_context (GdkDisplay *display,
GdkGLContext *share,
GError **error)
{
+ GdkGLPixelFormat *valid_format;
GdkX11GLContext *context;
GdkVisual *gdk_visual;
GLXFBConfig config;
@@ -553,11 +554,11 @@ gdk_x11_display_create_gl_context (GdkDisplay *display,
unsigned long mask;
Display *dpy;
- if (!gdk_x11_display_validate_gl_pixel_format (display, format, error))
+ if (!gdk_x11_display_validate_gl_pixel_format (display, format, NULL, error))
return NULL;
- /* if validation succeeded, then we don't need to check for the result
- * here
+ /* if validation succeeded, then we don't need to check for the
+ * result here: we know the pixel format has a valid GLXFBConfig
*/
find_fbconfig_for_pixel_format (display, format, &config, &xvisinfo, NULL);
@@ -648,9 +649,17 @@ gdk_x11_display_create_gl_context (GdkDisplay *display,
is_direct ? "direct" : "indirect",
(unsigned long) dummy_xwin));
+ /* the GdkGLContext holds a reference on the pixel format
+ * that is used to create it, not the one that the user
+ * passed; this allows the user to query the pixel format
+ * attributes
+ */
+ valid_format = g_object_new (GDK_TYPE_GL_PIXEL_FORMAT, NULL);
+ update_pixel_format (display, valid_format, config);
+
context = g_object_new (GDK_X11_TYPE_GL_CONTEXT,
"display", display,
- "pixel-format", format,
+ "pixel-format", valid_format,
"visual", gdk_visual,
NULL);
@@ -767,6 +776,7 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display,
gboolean
gdk_x11_display_validate_gl_pixel_format (GdkDisplay *display,
GdkGLPixelFormat *format,
+ GdkGLPixelFormat **validated_format,
GError **error)
{
GLXFBConfig config;
@@ -795,10 +805,17 @@ gdk_x11_display_validate_gl_pixel_format (GdkDisplay *display,
if (!find_fbconfig_for_pixel_format (display, format, &config, NULL, error))
return FALSE;
- /* update the pixel format with the values of the
- * configuration we found
- */
- update_pixel_format (display, format, config);
+ if (validated_format != NULL)
+ {
+ GdkGLPixelFormat *valid = g_object_new (GDK_TYPE_GL_PIXEL_FORMAT, NULL);
+
+ /* update the pixel format with the values of the
+ * configuration we found
+ */
+ update_pixel_format (display, valid, config);
+
+ *validated_format = valid;
+ }
return TRUE;
}
diff --git a/gdk/x11/gdkglcontext-x11.h b/gdk/x11/gdkglcontext-x11.h
index 8b5f2341e1..d17c433c4f 100644
--- a/gdk/x11/gdkglcontext-x11.h
+++ b/gdk/x11/gdkglcontext-x11.h
@@ -61,6 +61,7 @@ struct _GdkX11GLContextClass
gboolean gdk_x11_display_init_gl (GdkDisplay *display);
gboolean gdk_x11_display_validate_gl_pixel_format (GdkDisplay *display,
GdkGLPixelFormat *format,
+ GdkGLPixelFormat **validated_format,
GError **error);
GdkGLContext * gdk_x11_display_create_gl_context (GdkDisplay *display,
GdkGLPixelFormat *format,
diff --git a/gtk/gtkglarea.c b/gtk/gtkglarea.c
index 94cd7e2a2e..c2f9b584a8 100644
--- a/gtk/gtkglarea.c
+++ b/gtk/gtkglarea.c
@@ -143,9 +143,9 @@
*
* // create a GdkGLContext that has shared texture namespace
* // and display lists with a given context
- * return gdk_display_get_gl_context (display, format,
- * shared_context,
- * NULL);
+ * return gdk_display_create_shared_gl_context (display, format,
+ * shared_context,
+ * NULL);
* }
* ]|
*
@@ -375,7 +375,7 @@ gtk_gl_area_real_create_context (GtkGLArea *area,
if (display == NULL)
display = gdk_display_get_default ();
- retval = gdk_display_get_gl_context (display, format, NULL, &error);
+ retval = gdk_display_create_gl_context (display, format, &error);
if (error != NULL)
{
g_critical ("Unable to create a GdkGLContext: %s", error->message);
@@ -420,6 +420,10 @@ gtk_gl_area_class_init (GtkGLAreaClass *klass)
* The #GdkGLPixelFormat used for creating the #GdkGLContext
* to be used by the #GtkGLArea widget.
*
+ * If you want to query the effective pixel format used by
+ * the #GdkGLContext, you should get the #GtkGLArea:context and
+ * call gdk_gl_context_get_pixel_format().
+ *
* Since: 3.14
*/
obj_props[PROP_PIXEL_FORMAT] =