Compare commits
40 Commits
font-rende
...
wip/gdk-gl
Author | SHA1 | Date | |
---|---|---|---|
|
6d22f2a46a | ||
|
4d07a9ad3a | ||
|
a8b172b803 | ||
|
78f84f42c5 | ||
|
06d48d0e9a | ||
|
a7f3f94985 | ||
|
06bd4aba2b | ||
|
5cba7de332 | ||
|
be97c75a01 | ||
|
a98d8fd8df | ||
|
7622a36c7d | ||
|
fb996eec50 | ||
|
cf0b1771da | ||
|
19a0a6196b | ||
|
3398e2ea87 | ||
|
9082c07b91 | ||
|
fd24c996df | ||
|
4e84bf5263 | ||
|
0f47f8bcae | ||
|
4b5f540f11 | ||
|
b7a5369f01 | ||
|
30548946ee | ||
|
63130913ca | ||
|
3d2237865c | ||
|
54edcca4d5 | ||
|
ca380707e3 | ||
|
a71cec0119 | ||
|
d713ae6321 | ||
|
e18136f16b | ||
|
686f9b4607 | ||
|
90cc7743d0 | ||
|
eb0e790a21 | ||
|
0500963db9 | ||
|
bc9180d610 | ||
|
6b0fc7c4d8 | ||
|
6d71c440e9 | ||
|
ffcd7983aa | ||
|
a5da2eff7d | ||
|
5052aa4a9a | ||
|
a6ee04781f |
@@ -48,6 +48,7 @@ m4_define([cairo_required_version], [1.12.0])
|
|||||||
m4_define([gdk_pixbuf_required_version], [2.27.1])
|
m4_define([gdk_pixbuf_required_version], [2.27.1])
|
||||||
m4_define([introspection_required_version], [1.39.0])
|
m4_define([introspection_required_version], [1.39.0])
|
||||||
m4_define([wayland_required_version], [1.3.90])
|
m4_define([wayland_required_version], [1.3.90])
|
||||||
|
m4_define([epoxy_required_version], [1.0])
|
||||||
GLIB_REQUIRED_VERSION=glib_required_version
|
GLIB_REQUIRED_VERSION=glib_required_version
|
||||||
PANGO_REQUIRED_VERSION=pango_required_version
|
PANGO_REQUIRED_VERSION=pango_required_version
|
||||||
ATK_REQUIRED_VERSION=atk_required_version
|
ATK_REQUIRED_VERSION=atk_required_version
|
||||||
@@ -1325,7 +1326,7 @@ CFLAGS="$saved_cflags"
|
|||||||
LDFLAGS="$saved_ldflags"
|
LDFLAGS="$saved_ldflags"
|
||||||
|
|
||||||
GDK_PACKAGES="$PANGO_PACKAGES gdk-pixbuf-2.0 >= gdk_pixbuf_required_version cairo >= cairo_required_version cairo-gobject >= cairo_required_version"
|
GDK_PACKAGES="$PANGO_PACKAGES gdk-pixbuf-2.0 >= gdk_pixbuf_required_version cairo >= cairo_required_version cairo-gobject >= cairo_required_version"
|
||||||
GDK_PRIVATE_PACKAGES="$GDK_GIO_PACKAGE $X_PACKAGES $WAYLAND_PACKAGES $cairo_backends"
|
GDK_PRIVATE_PACKAGES="$GDK_GIO_PACKAGE $X_PACKAGES $WAYLAND_PACKAGES $cairo_backends epoxy >= epoxy_required_version"
|
||||||
if test "x$enable_x11_backend" = xyes; then
|
if test "x$enable_x11_backend" = xyes; then
|
||||||
GDK_PRIVATE_PACKAGES="$GDK_PRIVATE_PACKAGES pangoft2"
|
GDK_PRIVATE_PACKAGES="$GDK_PRIVATE_PACKAGES pangoft2"
|
||||||
fi
|
fi
|
||||||
|
@@ -25,6 +25,7 @@ demos = \
|
|||||||
event_axes.c \
|
event_axes.c \
|
||||||
expander.c \
|
expander.c \
|
||||||
gestures.c \
|
gestures.c \
|
||||||
|
glarea.c \
|
||||||
headerbar.c \
|
headerbar.c \
|
||||||
hypertext.c \
|
hypertext.c \
|
||||||
iconview.c \
|
iconview.c \
|
||||||
|
@@ -95,6 +95,7 @@
|
|||||||
<file>expander.c</file>
|
<file>expander.c</file>
|
||||||
<file>flowbox.c</file>
|
<file>flowbox.c</file>
|
||||||
<file>gestures.c</file>
|
<file>gestures.c</file>
|
||||||
|
<file>glarea.c</file>
|
||||||
<file>headerbar.c</file>
|
<file>headerbar.c</file>
|
||||||
<file>hypertext.c</file>
|
<file>hypertext.c</file>
|
||||||
<file>iconview.c</file>
|
<file>iconview.c</file>
|
||||||
|
230
demos/gtk-demo/glarea.c
Normal file
230
demos/gtk-demo/glarea.c
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/* OpenGL Area
|
||||||
|
*
|
||||||
|
* GtkGLArea is a widget that allows custom drawing using OpenGL calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <epoxy/gl.h>
|
||||||
|
|
||||||
|
static GtkWidget *demo_window = NULL;
|
||||||
|
|
||||||
|
/* the GtkGLArea widget */
|
||||||
|
static GtkWidget *gl_area = NULL;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
X_AXIS,
|
||||||
|
Y_AXIS,
|
||||||
|
Z_AXIS,
|
||||||
|
|
||||||
|
N_AXIS
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Rotation angles on each axis */
|
||||||
|
static float rotation_angles[N_AXIS] = { 0.0 };
|
||||||
|
|
||||||
|
/* The object we are drawing */
|
||||||
|
static void
|
||||||
|
draw_triangle (void)
|
||||||
|
{
|
||||||
|
glColor3f (1.0f, 0.85f, 0.35f);
|
||||||
|
glBegin (GL_TRIANGLES);
|
||||||
|
{
|
||||||
|
glVertex3f ( 0.0, 0.6, 0.0);
|
||||||
|
glVertex3f (-0.2, -0.3, 0.0);
|
||||||
|
glVertex3f ( 0.2, -0.3, 0.0);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The main rendering callback */
|
||||||
|
static gboolean
|
||||||
|
render (GtkGLArea *area,
|
||||||
|
GdkGLContext *context)
|
||||||
|
{
|
||||||
|
glClearColor (0.5, 0.5, 0.5, 1.0);
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glRotatef (rotation_angles[X_AXIS], 1, 0, 0);
|
||||||
|
glRotatef (rotation_angles[Y_AXIS], 0, 1, 0);
|
||||||
|
glRotatef (rotation_angles[Z_AXIS], 0, 0, 1);
|
||||||
|
|
||||||
|
draw_triangle ();
|
||||||
|
|
||||||
|
glFlush ();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the GL state */
|
||||||
|
static void
|
||||||
|
init_gl_state (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GdkGLContext *context = gtk_gl_area_get_context (GTK_GL_AREA (widget));
|
||||||
|
GdkGLPixelFormat *format = gdk_gl_context_get_pixel_format (context);
|
||||||
|
|
||||||
|
g_print ("GL Pixel format:\n"
|
||||||
|
" - double-buffer: %s\n"
|
||||||
|
" - multi-sample: %s\n"
|
||||||
|
" - stereo: %s\n"
|
||||||
|
" - color-size: %d, alpha-size: %d\n"
|
||||||
|
" - depth-size: %d\n"
|
||||||
|
" - stencil-size: %d\n"
|
||||||
|
" - aux-buffers: %d\n"
|
||||||
|
" - accum-size: %d\n"
|
||||||
|
" - sample-buffers: %d\n"
|
||||||
|
" - samples: %d\n\n",
|
||||||
|
gdk_gl_pixel_format_get_double_buffer (format) ? "yes" : "no",
|
||||||
|
gdk_gl_pixel_format_get_multi_sample (format) ? "yes" : "no",
|
||||||
|
gdk_gl_pixel_format_get_stereo (format) ? "yes" : "no",
|
||||||
|
gdk_gl_pixel_format_get_color_size (format),
|
||||||
|
gdk_gl_pixel_format_get_alpha_size (format),
|
||||||
|
gdk_gl_pixel_format_get_depth_size (format),
|
||||||
|
gdk_gl_pixel_format_get_stencil_size (format),
|
||||||
|
gdk_gl_pixel_format_get_aux_buffers (format),
|
||||||
|
gdk_gl_pixel_format_get_accum_size (format),
|
||||||
|
gdk_gl_pixel_format_get_sample_buffers (format),
|
||||||
|
gdk_gl_pixel_format_get_samples (format));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_axis_value_change (GtkAdjustment *adjustment,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
int axis = GPOINTER_TO_INT (data);
|
||||||
|
|
||||||
|
g_assert (axis >= 0 && axis < N_AXIS);
|
||||||
|
|
||||||
|
/* Update the rotation angle */
|
||||||
|
rotation_angles[axis] = gtk_adjustment_get_value (adjustment);
|
||||||
|
|
||||||
|
/* Update the contents of the GL drawing area */
|
||||||
|
gtk_widget_queue_draw (gl_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget *
|
||||||
|
create_axis_slider (int axis)
|
||||||
|
{
|
||||||
|
GtkWidget *box, *label, *slider;
|
||||||
|
GtkAdjustment *adj;
|
||||||
|
const char *text;
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
|
||||||
|
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case X_AXIS:
|
||||||
|
text = "X axis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Y_AXIS:
|
||||||
|
text = "Y axis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Z_AXIS:
|
||||||
|
text = "Z axis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
label = gtk_label_new (text);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), label);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
|
||||||
|
adj = gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 12.0, 0.0);
|
||||||
|
g_signal_connect (adj, "value-changed",
|
||||||
|
G_CALLBACK (on_axis_value_change),
|
||||||
|
GINT_TO_POINTER (axis));
|
||||||
|
slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adj);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), slider);
|
||||||
|
gtk_widget_set_hexpand (slider, TRUE);
|
||||||
|
gtk_widget_show (slider);
|
||||||
|
|
||||||
|
gtk_widget_show (box);
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_window (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
/* Reset the state */
|
||||||
|
demo_window = NULL;
|
||||||
|
gl_area = NULL;
|
||||||
|
|
||||||
|
rotation_angles[X_AXIS] = 0.0;
|
||||||
|
rotation_angles[Y_AXIS] = 0.0;
|
||||||
|
rotation_angles[Z_AXIS] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
create_glarea_window (GtkWidget *do_widget)
|
||||||
|
{
|
||||||
|
GtkWidget *window, *box, *button, *controls;
|
||||||
|
GdkGLPixelFormat *pixel_format;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||||
|
gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (do_widget));
|
||||||
|
gtk_window_set_title (GTK_WINDOW (window), "GtkGLArea - Golden Triangle");
|
||||||
|
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (window), 12);
|
||||||
|
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||||
|
gtk_box_set_spacing (GTK_BOX (box), 6);
|
||||||
|
gtk_container_add (GTK_CONTAINER (window), box);
|
||||||
|
|
||||||
|
/* Create a new pixel format; we use this to configure the
|
||||||
|
* GL context, and to check for features.
|
||||||
|
*
|
||||||
|
* We only need it to be double-buffered.
|
||||||
|
*/
|
||||||
|
pixel_format = gdk_gl_pixel_format_new ("double-buffer", TRUE, NULL);
|
||||||
|
|
||||||
|
gl_area = gtk_gl_area_new (pixel_format);
|
||||||
|
gtk_widget_set_hexpand (gl_area, TRUE);
|
||||||
|
gtk_widget_set_vexpand (gl_area, TRUE);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), gl_area);
|
||||||
|
|
||||||
|
/* we use ::realize to initialize our GL state, because at that
|
||||||
|
* point we know that the GtkGLArea is associated with windowing
|
||||||
|
* system resources like a display, window, and GL context.
|
||||||
|
*/
|
||||||
|
g_signal_connect (gl_area, "realize", G_CALLBACK (init_gl_state), NULL);
|
||||||
|
|
||||||
|
/* the main "draw" call for GtkGLArea */
|
||||||
|
g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
|
||||||
|
g_object_unref (pixel_format);
|
||||||
|
|
||||||
|
controls = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), controls);
|
||||||
|
gtk_widget_set_hexpand (controls, TRUE);
|
||||||
|
|
||||||
|
for (i = 0; i < N_AXIS; i++)
|
||||||
|
gtk_container_add (GTK_CONTAINER (controls), create_axis_slider (i));
|
||||||
|
|
||||||
|
button = gtk_button_new_with_label ("Quit");
|
||||||
|
gtk_widget_set_hexpand (button, TRUE);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), button);
|
||||||
|
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
do_glarea (GtkWidget *do_widget)
|
||||||
|
{
|
||||||
|
if (demo_window == NULL)
|
||||||
|
demo_window = create_glarea_window (do_widget);
|
||||||
|
|
||||||
|
if (!gtk_widget_get_visible (demo_window))
|
||||||
|
gtk_widget_show_all (demo_window);
|
||||||
|
else
|
||||||
|
gtk_widget_destroy (demo_window);
|
||||||
|
|
||||||
|
return demo_window;
|
||||||
|
}
|
@@ -32,6 +32,8 @@
|
|||||||
<xi:include href="xml/windows.xml" />
|
<xi:include href="xml/windows.xml" />
|
||||||
<xi:include href="xml/gdkframeclock.xml" />
|
<xi:include href="xml/gdkframeclock.xml" />
|
||||||
<xi:include href="xml/gdkframetimings.xml" />
|
<xi:include href="xml/gdkframetimings.xml" />
|
||||||
|
<xi:include href="xml/gdkglcontext.xml" />
|
||||||
|
<xi:include href="xml/gdkglpixelformat.xml" />
|
||||||
<xi:include href="xml/events.xml" />
|
<xi:include href="xml/events.xml" />
|
||||||
<xi:include href="xml/event_structs.xml" />
|
<xi:include href="xml/event_structs.xml" />
|
||||||
<xi:include href="xml/keys.xml" />
|
<xi:include href="xml/keys.xml" />
|
||||||
|
@@ -156,6 +156,8 @@ gdk_display_supports_input_shapes
|
|||||||
gdk_display_supports_composite
|
gdk_display_supports_composite
|
||||||
gdk_display_get_app_launch_context
|
gdk_display_get_app_launch_context
|
||||||
gdk_display_notify_startup_complete
|
gdk_display_notify_startup_complete
|
||||||
|
gdk_display_validate_gl_pixel_format
|
||||||
|
gdk_display_get_gl_context
|
||||||
|
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GDK_DISPLAY
|
GDK_DISPLAY
|
||||||
@@ -1004,6 +1006,7 @@ gdk_x11_display_error_trap_pop
|
|||||||
gdk_x11_display_error_trap_pop_ignored
|
gdk_x11_display_error_trap_pop_ignored
|
||||||
gdk_x11_display_set_cursor_theme
|
gdk_x11_display_set_cursor_theme
|
||||||
gdk_x11_display_set_window_scale
|
gdk_x11_display_set_window_scale
|
||||||
|
gdk_x11_display_get_glx_version
|
||||||
gdk_x11_register_standard_event_type
|
gdk_x11_register_standard_event_type
|
||||||
gdk_x11_screen_get_screen_number
|
gdk_x11_screen_get_screen_number
|
||||||
gdk_x11_screen_get_xscreen
|
gdk_x11_screen_get_xscreen
|
||||||
@@ -1123,6 +1126,11 @@ GDK_X11_KEYMAP_CLASS
|
|||||||
GDK_IS_X11_KEYMAP
|
GDK_IS_X11_KEYMAP
|
||||||
GDK_IS_X11_KEYMAP_CLASS
|
GDK_IS_X11_KEYMAP_CLASS
|
||||||
GDK_X11_KEYMAP_GET_CLASS
|
GDK_X11_KEYMAP_GET_CLASS
|
||||||
|
GDK_TYPE_X11_GL_CONTEXT
|
||||||
|
GDK_X11_GL_CONTEXT
|
||||||
|
GDK_X11_GL_CONTEXT_CLASS
|
||||||
|
GDK_IS_X11_GL_CONTEXT
|
||||||
|
GDK_IS_X11_GL_CONTEXT_CLASS
|
||||||
GDK_TYPE_X11_SCREEN
|
GDK_TYPE_X11_SCREEN
|
||||||
GDK_X11_SCREEN
|
GDK_X11_SCREEN
|
||||||
GDK_X11_SCREEN_CLASS
|
GDK_X11_SCREEN_CLASS
|
||||||
@@ -1273,3 +1281,50 @@ gdk_frame_timings_get_predicted_presentation_time
|
|||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
gdk_frame_get_type
|
gdk_frame_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>gdkglcontext</FILE>
|
||||||
|
GdkGLContext
|
||||||
|
gdk_gl_context_get_display
|
||||||
|
gdk_gl_context_get_pixel_format
|
||||||
|
gdk_gl_context_get_visual
|
||||||
|
gdk_gl_context_set_window
|
||||||
|
gdk_gl_context_get_window
|
||||||
|
gdk_gl_context_make_current
|
||||||
|
gdk_gl_context_flush_buffer
|
||||||
|
gdk_gl_context_update
|
||||||
|
gdk_gl_context_clear_current
|
||||||
|
gdk_gl_context_get_current
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
GDK_GL_CONTEXT
|
||||||
|
GDK_IS_GL_CONTEXT
|
||||||
|
GDK_TYPE_GL_CONTEXT
|
||||||
|
gdk_gl_context_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>gdkglpixelformat</FILE>
|
||||||
|
GdkGLPixelFormat
|
||||||
|
GdkGLPixelFormatProfile
|
||||||
|
gdk_gl_pixel_format_new
|
||||||
|
<SUBSECTION>
|
||||||
|
gdk_gl_pixel_format_get_double_buffer
|
||||||
|
gdk_gl_pixel_format_get_multi_sample
|
||||||
|
gdk_gl_pixel_format_get_color_size
|
||||||
|
gdk_gl_pixel_format_get_alpha_size
|
||||||
|
gdk_gl_pixel_format_get_depth_size
|
||||||
|
gdk_gl_pixel_format_get_stencil_size
|
||||||
|
gdk_gl_pixel_format_get_accum_size
|
||||||
|
gdk_gl_pixel_format_get_aux_buffers
|
||||||
|
gdk_gl_pixel_format_get_sample_buffers
|
||||||
|
gdk_gl_pixel_format_get_samples
|
||||||
|
<SUBSECTION>
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR
|
||||||
|
GdkGLPixelFormatError
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
GDK_GL_PIXEL_FORMAT
|
||||||
|
GDK_IS_GL_PIXEL_FORMAT
|
||||||
|
GDK_TYPE_GL_PIXEL_FORMAT
|
||||||
|
gdk_gl_pixel_format_error_quark
|
||||||
|
gdk_gl_pixel_format_get_type
|
||||||
|
</SECTION>
|
||||||
|
@@ -8,6 +8,8 @@ gdk_display_get_type
|
|||||||
gdk_display_manager_get_type
|
gdk_display_manager_get_type
|
||||||
gdk_drag_context_get_type
|
gdk_drag_context_get_type
|
||||||
gdk_frame_clock_get_type
|
gdk_frame_clock_get_type
|
||||||
|
gdk_gl_context_get_type
|
||||||
|
gdk_gl_pixel_format_get_type
|
||||||
gdk_keymap_get_type
|
gdk_keymap_get_type
|
||||||
gdk_screen_get_type
|
gdk_screen_get_type
|
||||||
gdk_visual_get_type
|
gdk_visual_get_type
|
||||||
|
@@ -243,6 +243,7 @@
|
|||||||
<xi:include href="xml/gtkadjustment.xml" />
|
<xi:include href="xml/gtkadjustment.xml" />
|
||||||
<xi:include href="xml/gtkcalendar.xml" />
|
<xi:include href="xml/gtkcalendar.xml" />
|
||||||
<xi:include href="xml/gtkdrawingarea.xml" />
|
<xi:include href="xml/gtkdrawingarea.xml" />
|
||||||
|
<xi:include href="xml/gtkglarea.xml" />
|
||||||
<xi:include href="xml/gtkeventbox.xml" />
|
<xi:include href="xml/gtkeventbox.xml" />
|
||||||
<xi:include href="xml/gtkhandlebox.xml" />
|
<xi:include href="xml/gtkhandlebox.xml" />
|
||||||
<xi:include href="xml/gtkimcontextsimple.xml" />
|
<xi:include href="xml/gtkimcontextsimple.xml" />
|
||||||
|
@@ -8153,3 +8153,22 @@ GTK_GESTURE_ZOOM_GET_CLASS
|
|||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
gtk_gesture_zoom_get_type
|
gtk_gesture_zoom_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>gtkglarea</FILE>
|
||||||
|
GtkGLArea
|
||||||
|
GtkGLAreaClass
|
||||||
|
gtk_gl_area_new
|
||||||
|
gtk_gl_area_get_context
|
||||||
|
<SUBSECTION>
|
||||||
|
gtk_gl_area_make_current
|
||||||
|
gtk_gl_area_flush_buffer
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
GTK_TYPE_GL_AREA
|
||||||
|
GTK_GL_AREA
|
||||||
|
GTK_GL_AREA_CLASS
|
||||||
|
GTK_IS_GL_AREA
|
||||||
|
GTK_IS_GL_AREA_CLASS
|
||||||
|
<SUBSECTION Private>
|
||||||
|
gtk_gl_area_get_type
|
||||||
|
</SECTION>
|
||||||
|
@@ -75,6 +75,8 @@ gdk_public_h_sources = \
|
|||||||
gdkdnd.h \
|
gdkdnd.h \
|
||||||
gdkevents.h \
|
gdkevents.h \
|
||||||
gdkframetimings.h \
|
gdkframetimings.h \
|
||||||
|
gdkglcontext.h \
|
||||||
|
gdkglpixelformat.h \
|
||||||
gdkkeys.h \
|
gdkkeys.h \
|
||||||
gdkkeysyms.h \
|
gdkkeysyms.h \
|
||||||
gdkkeysyms-compat.h \
|
gdkkeysyms-compat.h \
|
||||||
@@ -111,6 +113,8 @@ gdk_private_headers = \
|
|||||||
gdkdndprivate.h \
|
gdkdndprivate.h \
|
||||||
gdkframeclockidle.h \
|
gdkframeclockidle.h \
|
||||||
gdkframeclockprivate.h \
|
gdkframeclockprivate.h \
|
||||||
|
gdkglcontextprivate.h \
|
||||||
|
gdkglpixelformatprivate.h \
|
||||||
gdkscreenprivate.h \
|
gdkscreenprivate.h \
|
||||||
gdkinternals.h \
|
gdkinternals.h \
|
||||||
gdkintl.h \
|
gdkintl.h \
|
||||||
@@ -135,6 +139,8 @@ gdk_c_sources = \
|
|||||||
gdkdnd.c \
|
gdkdnd.c \
|
||||||
gdkevents.c \
|
gdkevents.c \
|
||||||
gdkframetimings.c \
|
gdkframetimings.c \
|
||||||
|
gdkglcontext.c \
|
||||||
|
gdkglpixelformat.c \
|
||||||
gdkglobals.c \
|
gdkglobals.c \
|
||||||
gdkkeys.c \
|
gdkkeys.c \
|
||||||
gdkkeyuni.c \
|
gdkkeyuni.c \
|
||||||
|
@@ -148,7 +148,8 @@ static const GDebugKey gdk_debug_keys[] = {
|
|||||||
{"draw", GDK_DEBUG_DRAW},
|
{"draw", GDK_DEBUG_DRAW},
|
||||||
{"eventloop", GDK_DEBUG_EVENTLOOP},
|
{"eventloop", GDK_DEBUG_EVENTLOOP},
|
||||||
{"frames", GDK_DEBUG_FRAMES},
|
{"frames", GDK_DEBUG_FRAMES},
|
||||||
{"settings", GDK_DEBUG_SETTINGS}
|
{"settings", GDK_DEBUG_SETTINGS},
|
||||||
|
{"opengl", GDK_DEBUG_OPENGL},
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@@ -41,6 +41,8 @@
|
|||||||
#include <gdk/gdkevents.h>
|
#include <gdk/gdkevents.h>
|
||||||
#include <gdk/gdkframeclock.h>
|
#include <gdk/gdkframeclock.h>
|
||||||
#include <gdk/gdkframetimings.h>
|
#include <gdk/gdkframetimings.h>
|
||||||
|
#include <gdk/gdkglpixelformat.h>
|
||||||
|
#include <gdk/gdkglcontext.h>
|
||||||
#include <gdk/gdkkeys.h>
|
#include <gdk/gdkkeys.h>
|
||||||
#include <gdk/gdkkeysyms.h>
|
#include <gdk/gdkkeysyms.h>
|
||||||
#include <gdk/gdkmain.h>
|
#include <gdk/gdkmain.h>
|
||||||
|
160
gdk/gdkdisplay.c
160
gdk/gdkdisplay.c
@@ -2225,3 +2225,163 @@ gdk_error_trap_pop (void)
|
|||||||
{
|
{
|
||||||
return gdk_error_trap_pop_internal (TRUE);
|
return gdk_error_trap_pop_internal (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_display_destroy_gl_context:
|
||||||
|
* @display: a #GdkDisplay
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Destroys the platform-specific parts of the @context.
|
||||||
|
*
|
||||||
|
* The @context instance is still valid, though inert, after
|
||||||
|
* this functionr returns.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_display_destroy_gl_context (GdkDisplay *display,
|
||||||
|
GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GDK_DISPLAY_GET_CLASS (display)->destroy_gl_context (display, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_display_make_gl_context_current:
|
||||||
|
* @display: a #GdkDisplay
|
||||||
|
* @context: (optional): a #GdkGLContext, or %NULL
|
||||||
|
* @window: (optional): a #GdkWindow, or %NULL
|
||||||
|
*
|
||||||
|
* Makes the given @context the current GL context, or unsets
|
||||||
|
* the current GL context if @context is %NULL.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||||
|
GdkGLContext *context,
|
||||||
|
GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkGLContext *current = gdk_display_get_current_gl_context (display);
|
||||||
|
|
||||||
|
if (current == context)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (context == NULL)
|
||||||
|
g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
|
||||||
|
else
|
||||||
|
g_object_set_data_full (G_OBJECT (display), "-gdk-gl-current-context",
|
||||||
|
g_object_ref (context),
|
||||||
|
(GDestroyNotify) g_object_unref);
|
||||||
|
|
||||||
|
return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_display_get_current_gl_context:
|
||||||
|
* @display: a #GdkDisplay
|
||||||
|
*
|
||||||
|
* Retrieves the current #GdkGLContext associated with @display.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the current #GdkGLContext or %NULL
|
||||||
|
*/
|
||||||
|
GdkGLContext *
|
||||||
|
gdk_display_get_current_gl_context (GdkDisplay *display)
|
||||||
|
{
|
||||||
|
return g_object_get_data (G_OBJECT (display), "-gdk-gl-current-context");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdk_display_validate_gl_pixel_format (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GdkGLPixelFormat **validated_format,
|
||||||
|
GError **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_create_gl_context:
|
||||||
|
* @display: a #GdkDisplay
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
* @error: return location for a #GError
|
||||||
|
*
|
||||||
|
* Creates a new #GdkGLContext for the given display, with the given
|
||||||
|
* pixel format.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the newly created #GdkGLContext, or
|
||||||
|
* %NULL on error
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkGLContext *
|
||||||
|
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 (GDK_IS_GL_CONTEXT (shared_context), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
return GDK_DISPLAY_GET_CLASS (display)->create_gl_context (display, format,
|
||||||
|
shared_context,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
@@ -171,6 +171,21 @@ GdkDeviceManager * gdk_display_get_device_manager (GdkDisplay *display);
|
|||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
GdkAppLaunchContext *gdk_display_get_app_launch_context (GdkDisplay *display);
|
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_create_gl_context (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GDK_DISPLAY_H__ */
|
#endif /* __GDK_DISPLAY_H__ */
|
||||||
|
@@ -225,6 +225,20 @@ struct _GdkDisplayClass
|
|||||||
gchar * (*utf8_to_string_target) (GdkDisplay *display,
|
gchar * (*utf8_to_string_target) (GdkDisplay *display,
|
||||||
const gchar *text);
|
const gchar *text);
|
||||||
|
|
||||||
|
GdkGLContext * (*create_gl_context) (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GdkGLContext *share,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*make_gl_context_current) (GdkDisplay *display,
|
||||||
|
GdkGLContext *context,
|
||||||
|
GdkWindow *drawable);
|
||||||
|
void (*destroy_gl_context) (GdkDisplay *display,
|
||||||
|
GdkGLContext *context);
|
||||||
|
gboolean (*validate_gl_pixel_format) (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GdkGLPixelFormat **valid_format,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
/* Signals */
|
/* Signals */
|
||||||
void (*opened) (GdkDisplay *display);
|
void (*opened) (GdkDisplay *display);
|
||||||
void (*closed) (GdkDisplay *display,
|
void (*closed) (GdkDisplay *display,
|
||||||
@@ -303,6 +317,17 @@ void _gdk_display_create_window_impl (GdkDisplay *display
|
|||||||
gint attributes_mask);
|
gint attributes_mask);
|
||||||
GdkWindow * _gdk_display_create_window (GdkDisplay *display);
|
GdkWindow * _gdk_display_create_window (GdkDisplay *display);
|
||||||
|
|
||||||
|
gboolean gdk_display_validate_gl_pixel_format (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GdkGLPixelFormat **validated_format,
|
||||||
|
GError **error);
|
||||||
|
void gdk_display_destroy_gl_context (GdkDisplay *display,
|
||||||
|
GdkGLContext *context);
|
||||||
|
gboolean gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||||
|
GdkGLContext *context,
|
||||||
|
GdkWindow *window);
|
||||||
|
GdkGLContext * gdk_display_get_current_gl_context (GdkDisplay *display);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GDK_DISPLAY_PRIVATE_H__ */
|
#endif /* __GDK_DISPLAY_PRIVATE_H__ */
|
||||||
|
648
gdk/gdkglcontext.c
Normal file
648
gdk/gdkglcontext.c
Normal file
@@ -0,0 +1,648 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglcontext.c: GL context abstraction
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:gdkglcontext
|
||||||
|
* @Title: GdkGLContext
|
||||||
|
* @Short_description: OpenGL context
|
||||||
|
*
|
||||||
|
* #GdkGLContext is an object representing the platform-specific
|
||||||
|
* OpenGL drawing context.
|
||||||
|
*
|
||||||
|
* #GdkGLContexts are created via a #GdkDisplay by specifying a
|
||||||
|
* #GdkGLPixelFormat to be used by the OpenGL context.
|
||||||
|
*
|
||||||
|
* Support for #GdkGLContext is platform specific; in order to
|
||||||
|
* discover if the platform supports OpenGL, you should use the
|
||||||
|
* #GdkGLPixelFormat class.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#include "gdkglcontextprivate.h"
|
||||||
|
#include "gdkdisplayprivate.h"
|
||||||
|
#include "gdkglpixelformat.h"
|
||||||
|
#include "gdkvisual.h"
|
||||||
|
#include "gdkinternals.h"
|
||||||
|
|
||||||
|
#include "gdkintl.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdkDisplay *display;
|
||||||
|
GdkGLPixelFormat *pixel_format;
|
||||||
|
GdkWindow *window;
|
||||||
|
GdkVisual *visual;
|
||||||
|
|
||||||
|
gboolean swap_interval;
|
||||||
|
} GdkGLContextPrivate;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_DISPLAY,
|
||||||
|
PROP_PIXEL_FORMAT,
|
||||||
|
PROP_WINDOW,
|
||||||
|
PROP_VISUAL,
|
||||||
|
|
||||||
|
PROP_SWAP_INTERVAL,
|
||||||
|
|
||||||
|
LAST_PROP
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *obj_pspecs[LAST_PROP] = { NULL, };
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_context_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
gdk_display_destroy_gl_context (priv->display, context);
|
||||||
|
|
||||||
|
g_clear_object (&priv->display);
|
||||||
|
g_clear_object (&priv->pixel_format);
|
||||||
|
g_clear_object (&priv->window);
|
||||||
|
g_clear_object (&priv->visual);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdk_gl_context_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_context_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DISPLAY:
|
||||||
|
priv->display = g_object_ref (g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PIXEL_FORMAT:
|
||||||
|
priv->pixel_format = g_object_ref (g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_WINDOW:
|
||||||
|
{
|
||||||
|
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||||
|
GdkWindow *window = g_value_get_object (value);
|
||||||
|
|
||||||
|
gdk_gl_context_set_window (context, window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_VISUAL:
|
||||||
|
{
|
||||||
|
GdkVisual *visual = g_value_get_object (value);
|
||||||
|
|
||||||
|
if (visual != NULL)
|
||||||
|
priv->visual = g_object_ref (visual);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SWAP_INTERVAL:
|
||||||
|
priv->swap_interval = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_context_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DISPLAY:
|
||||||
|
g_value_set_object (value, priv->display);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PIXEL_FORMAT:
|
||||||
|
g_value_set_object (value, priv->pixel_format);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_WINDOW:
|
||||||
|
g_value_set_object (value, priv->window);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_VISUAL:
|
||||||
|
g_value_set_object (value, priv->visual);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SWAP_INTERVAL:
|
||||||
|
g_value_set_boolean (value, priv->swap_interval);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLContext:display:
|
||||||
|
*
|
||||||
|
* The #GdkDisplay used by the context.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_pspecs[PROP_DISPLAY] =
|
||||||
|
g_param_spec_object ("display",
|
||||||
|
"Display",
|
||||||
|
"The GDK display used by the GL context",
|
||||||
|
GDK_TYPE_DISPLAY,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLContext:pixel-format:
|
||||||
|
*
|
||||||
|
* The #GdkGLPixelFormat used to create the context.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_pspecs[PROP_PIXEL_FORMAT] =
|
||||||
|
g_param_spec_object ("pixel-format",
|
||||||
|
"Pixel Format",
|
||||||
|
"The GDK pixel format used by the GL context",
|
||||||
|
GDK_TYPE_GL_PIXEL_FORMAT,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLContext:window:
|
||||||
|
*
|
||||||
|
* The #GdkWindow currently bound to the context.
|
||||||
|
*
|
||||||
|
* You typically need to bind a #GdkWindow to a #GdkGLContext prior
|
||||||
|
* to calling gdk_gl_context_make_current().
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_pspecs[PROP_WINDOW] =
|
||||||
|
g_param_spec_object ("window",
|
||||||
|
P_("Window"),
|
||||||
|
P_("The GDK window currently bound to the GL context"),
|
||||||
|
GDK_TYPE_WINDOW,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLContext:visual:
|
||||||
|
*
|
||||||
|
* The #GdkVisual matching the #GdkGLPixelFormat used by the context.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_pspecs[PROP_VISUAL] =
|
||||||
|
g_param_spec_object ("visual",
|
||||||
|
P_("Visual"),
|
||||||
|
P_("The GDK visual used by the GL context"),
|
||||||
|
GDK_TYPE_VISUAL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLContext:swap-interval:
|
||||||
|
*
|
||||||
|
* The swap interval of the context.
|
||||||
|
*
|
||||||
|
* If set to %TRUE (the default), buffers will be flushed only during
|
||||||
|
* the vertical refresh of the display.
|
||||||
|
*
|
||||||
|
* If set to %FALSE, gdk_gl_context_flush_buffer() will execute
|
||||||
|
* the buffer flush as soon as possible.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_pspecs[PROP_SWAP_INTERVAL] =
|
||||||
|
g_param_spec_boolean ("swap-interval",
|
||||||
|
P_("Swap Interval"),
|
||||||
|
P_("The swap interval of the GL context"),
|
||||||
|
TRUE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
gobject_class->set_property = gdk_gl_context_set_property;
|
||||||
|
gobject_class->get_property = gdk_gl_context_get_property;
|
||||||
|
gobject_class->dispose = gdk_gl_context_dispose;
|
||||||
|
|
||||||
|
g_object_class_install_properties (gobject_class, LAST_PROP, obj_pspecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_context_init (GdkGLContext *self)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||||
|
|
||||||
|
priv->swap_interval = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_get_display:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkDisplay associated with the @context.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #GdkDisplay
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkDisplay *
|
||||||
|
gdk_gl_context_get_display (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||||
|
|
||||||
|
return priv->display;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_get_pixel_format:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkGLPixelFormat associated with the @context.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #GdkDisplay
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkGLPixelFormat *
|
||||||
|
gdk_gl_context_get_pixel_format (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||||
|
|
||||||
|
return priv->pixel_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_get_visual:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkVisual associated with the @context.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #GdkVisual
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkVisual *
|
||||||
|
gdk_gl_context_get_visual (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||||
|
|
||||||
|
return priv->visual;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_flush_buffer:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Copies the back buffer to the front buffer.
|
||||||
|
*
|
||||||
|
* If the #GdkGLContext is not double buffered, this function does not
|
||||||
|
* do anything.
|
||||||
|
*
|
||||||
|
* Depending on the value of the #GdkGLContext:swap-interval property,
|
||||||
|
* the copy may take place during the vertical refresh of the display
|
||||||
|
* rather than immediately.
|
||||||
|
*
|
||||||
|
* This function may call `glFlush()` implicitly before returning; it
|
||||||
|
* is not recommended to call `glFlush()` explicitly before calling
|
||||||
|
* this function.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_gl_context_flush_buffer (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||||
|
|
||||||
|
GDK_GL_CONTEXT_GET_CLASS (context)->flush_buffer (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_make_current:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Makes the @context the current one.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the context is current
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdk_gl_context_make_current (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE);
|
||||||
|
|
||||||
|
return gdk_display_make_gl_context_current (priv->display, context, priv->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_set_window:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
* @window: (optional): a #GdkWindow, or %NULL
|
||||||
|
*
|
||||||
|
* Sets the #GdkWindow used to display the draw commands.
|
||||||
|
*
|
||||||
|
* If @window is %NULL, the @context is detached from the window.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_gl_context_set_window (GdkGLContext *context,
|
||||||
|
GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||||
|
g_return_if_fail (window == NULL || (GDK_IS_WINDOW (window) && !GDK_WINDOW_DESTROYED (window)));
|
||||||
|
|
||||||
|
if (priv->window == window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->window != NULL)
|
||||||
|
gdk_window_set_gl_context (priv->window, NULL);
|
||||||
|
|
||||||
|
g_clear_object (&priv->window);
|
||||||
|
|
||||||
|
if (window != NULL)
|
||||||
|
{
|
||||||
|
priv->window = g_object_ref (window);
|
||||||
|
gdk_window_set_gl_context (window, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
GDK_GL_CONTEXT_GET_CLASS (context)->set_window (context, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_get_window:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkWindow used by the @context.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): a #GdkWindow or %NULL
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkWindow *
|
||||||
|
gdk_gl_context_get_window (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||||
|
|
||||||
|
return priv->window;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_update:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Updates the @context when the #GdkWindow used to display the
|
||||||
|
* rendering changes size or position.
|
||||||
|
*
|
||||||
|
* Typically, you will call this function after calling
|
||||||
|
* gdk_window_resize() or gdk_window_move_resize().
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_gl_context_update (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||||
|
|
||||||
|
if (priv->window == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GDK_GL_CONTEXT_GET_CLASS (context)->update (context, priv->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_clear_current:
|
||||||
|
*
|
||||||
|
* Clears the current #GdkGLContext.
|
||||||
|
*
|
||||||
|
* Any OpenGL call after this function returns will be ignored
|
||||||
|
* until gdk_gl_context_make_current() is called.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_gl_context_clear_current (void)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gdk_display_get_default ();
|
||||||
|
|
||||||
|
gdk_display_make_gl_context_current (display, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_context_get_current:
|
||||||
|
*
|
||||||
|
* Retrieves the current #GdkGLContext.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the current #GdkGLContext, or %NULL
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkGLContext *
|
||||||
|
gdk_gl_context_get_current (void)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gdk_display_get_default ();
|
||||||
|
|
||||||
|
return gdk_display_get_current_gl_context (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_gl_context_get_swap_interval:
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Retrieves the swap interval of the context.
|
||||||
|
*
|
||||||
|
* Returns: the swap interval
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdk_gl_context_get_swap_interval (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||||
|
|
||||||
|
return priv->swap_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_window_has_gl_context:
|
||||||
|
* @window: a #GdkWindow
|
||||||
|
*
|
||||||
|
* Checks whether a #GdkWindow has a #GdkGLContext associated to it.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the window has a GL context
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdk_window_has_gl_context (GdkWindow *window)
|
||||||
|
{
|
||||||
|
return g_object_get_data (G_OBJECT (window), "-gdk-gl-context") != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_window_set_gl_context:
|
||||||
|
* @window: a #GdkWindow
|
||||||
|
* @context: a #GdkGLContext
|
||||||
|
*
|
||||||
|
* Sets a back pointer to a #GdkGLContext on @window.
|
||||||
|
*
|
||||||
|
* This function should only be called by gdk_gl_context_set_window().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_window_set_gl_context (GdkWindow *window,
|
||||||
|
GdkGLContext *context)
|
||||||
|
{
|
||||||
|
g_object_set_data (G_OBJECT (window), "-gdk-gl-context", context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_window_get_gl_context:
|
||||||
|
* @window: a #GdkWindow
|
||||||
|
*
|
||||||
|
* Retrieves a pointer to the #GdkGLContext associated to
|
||||||
|
* the @window.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): a #GdkGLContext, or %NULL
|
||||||
|
*/
|
||||||
|
GdkGLContext *
|
||||||
|
gdk_window_get_gl_context (GdkWindow *window)
|
||||||
|
{
|
||||||
|
return g_object_get_data (G_OBJECT (window), "-gdk-gl-context");
|
||||||
|
}
|
66
gdk/gdkglcontext.h
Normal file
66
gdk/gdkglcontext.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglcontext.h: GL context abstraction
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_GL_CONTEXT_H__
|
||||||
|
#define __GDK_GL_CONTEXT_H__
|
||||||
|
|
||||||
|
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||||
|
#error "Only <gdk/gdk.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gdk/gdkversionmacros.h>
|
||||||
|
#include <gdk/gdktypes.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_TYPE_GL_CONTEXT (gdk_gl_context_get_type ())
|
||||||
|
#define GDK_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContext))
|
||||||
|
#define GDK_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_CONTEXT))
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GType gdk_gl_context_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkGLPixelFormat * gdk_gl_context_get_pixel_format (GdkGLContext *context);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkVisual * gdk_gl_context_get_visual (GdkGLContext *context);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
void gdk_gl_context_flush_buffer (GdkGLContext *context);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gboolean gdk_gl_context_make_current (GdkGLContext *context);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
void gdk_gl_context_set_window (GdkGLContext *context,
|
||||||
|
GdkWindow *window);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkWindow * gdk_gl_context_get_window (GdkGLContext *context);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
void gdk_gl_context_update (GdkGLContext *context);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
void gdk_gl_context_clear_current (void);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkGLContext * gdk_gl_context_get_current (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_GL_CONTEXT_H__ */
|
54
gdk/gdkglcontextprivate.h
Normal file
54
gdk/gdkglcontextprivate.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglcontextprivate.h: GL context abstraction
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_GL_CONTEXT_PRIVATE_H__
|
||||||
|
#define __GDK_GL_CONTEXT_PRIVATE_H__
|
||||||
|
|
||||||
|
#include "gdkglcontext.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||||
|
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
|
||||||
|
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||||
|
|
||||||
|
typedef struct _GdkGLContextClass GdkGLContextClass;
|
||||||
|
|
||||||
|
struct _GdkGLContext
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GdkGLContextClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* set_window) (GdkGLContext *context,
|
||||||
|
GdkWindow *window);
|
||||||
|
void (* update) (GdkGLContext *context,
|
||||||
|
GdkWindow *window);
|
||||||
|
void (* flush_buffer) (GdkGLContext *context);
|
||||||
|
};
|
||||||
|
|
||||||
|
gboolean gdk_gl_context_get_swap_interval (GdkGLContext *context);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_GL_CONTEXT_PRIVATE_H__ */
|
664
gdk/gdkglpixelformat.c
Normal file
664
gdk/gdkglpixelformat.c
Normal file
@@ -0,0 +1,664 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglpixelformat.c: GL pixel formats
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:gdkglpixelformat
|
||||||
|
* @Title: GdkGLPixelFormat
|
||||||
|
* @Short_description: Specify the pixel format for GL contexts
|
||||||
|
*
|
||||||
|
* The #GdkGLPixelFormat class is used to specify the types and sizes of
|
||||||
|
* buffers to be used by a #GdkGLContext, as well as other configuration
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* Once created, a #GdkGLPixelFormat is immutable, and can only be used
|
||||||
|
* to create a #GdkGLContext, or for validation.
|
||||||
|
*
|
||||||
|
* Once a #GdkGLPixelFormat has been validated, either directly through
|
||||||
|
* gdk_display_validate_gl_pixel_format() or indirectly through the
|
||||||
|
* creation of a #GdkGLContext, it is possible to query its properties
|
||||||
|
* for the values found during validation.
|
||||||
|
*
|
||||||
|
* ## Using GdkGLPixelFormat ##
|
||||||
|
*
|
||||||
|
* Typically, you will create a new #GdkGLPixelFormat using the given
|
||||||
|
* constructor and properties:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* GdkGLPixelFormat *format;
|
||||||
|
*
|
||||||
|
* // Ask for a pixel format with double buffering and
|
||||||
|
* // a depth buffer with a size of 32 bits
|
||||||
|
* format = gdk_gl_pixel_format_new ("double-buffer", TRUE,
|
||||||
|
* "depth-size", 32,
|
||||||
|
* NULL);
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* After creating a pixel format, you can validate it using a #GdkDisplay
|
||||||
|
* and use the result of gdk_display_validate_gl_pixel_format() to provide
|
||||||
|
* an alternative pixel format:
|
||||||
|
*
|
||||||
|
* |[<!-- 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, &valid, &error))
|
||||||
|
* {
|
||||||
|
* // print "error" or create a new pixel format to validate
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* You can also create a #GdkGLContext for the given display and
|
||||||
|
* pixel format:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* GdkGLContext *context;
|
||||||
|
* GError *error = NULL;
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* context will acquire a reference on the pixel format, so it's safe to
|
||||||
|
* release the reference created at construction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gdkglpixelformatprivate.h"
|
||||||
|
|
||||||
|
#include "gdkdisplayprivate.h"
|
||||||
|
#include "gdkenumtypes.h"
|
||||||
|
|
||||||
|
#include "gdkintl.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
/* bool */
|
||||||
|
PROP_DOUBLE_BUFFER,
|
||||||
|
PROP_MULTI_SAMPLE,
|
||||||
|
PROP_STEREO,
|
||||||
|
|
||||||
|
/* uint */
|
||||||
|
PROP_AUX_BUFFERS,
|
||||||
|
PROP_COLOR_SIZE,
|
||||||
|
PROP_ALPHA_SIZE,
|
||||||
|
PROP_DEPTH_SIZE,
|
||||||
|
PROP_STENCIL_SIZE,
|
||||||
|
PROP_ACCUM_SIZE,
|
||||||
|
PROP_SAMPLE_BUFFERS,
|
||||||
|
PROP_SAMPLES,
|
||||||
|
|
||||||
|
/* enum */
|
||||||
|
PROP_PROFILE,
|
||||||
|
|
||||||
|
LAST_PROP
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *obj_props[LAST_PROP] = { NULL, };
|
||||||
|
|
||||||
|
G_DEFINE_QUARK (gdk-gl-pixel-format-error-quark, gdk_gl_pixel_format_error)
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdkGLPixelFormat, gdk_gl_pixel_format, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_pixel_format_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdkGLPixelFormat *self = GDK_GL_PIXEL_FORMAT (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DOUBLE_BUFFER:
|
||||||
|
self->double_buffer = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_MULTI_SAMPLE:
|
||||||
|
self->multi_sample = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_STEREO:
|
||||||
|
self->stereo = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_AUX_BUFFERS:
|
||||||
|
self->aux_buffers = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_COLOR_SIZE:
|
||||||
|
self->color_size = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_ALPHA_SIZE:
|
||||||
|
self->alpha_size = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DEPTH_SIZE:
|
||||||
|
self->depth_size = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_STENCIL_SIZE:
|
||||||
|
self->stencil_size = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_ACCUM_SIZE:
|
||||||
|
self->accum_size = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SAMPLE_BUFFERS:
|
||||||
|
self->sample_buffers = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SAMPLES:
|
||||||
|
self->samples = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PROFILE:
|
||||||
|
self->profile = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_pixel_format_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdkGLPixelFormat *self = GDK_GL_PIXEL_FORMAT (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DOUBLE_BUFFER:
|
||||||
|
g_value_set_boolean (value, self->double_buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_MULTI_SAMPLE:
|
||||||
|
g_value_set_boolean (value, self->multi_sample);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_STEREO:
|
||||||
|
g_value_set_boolean (value, self->stereo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_AUX_BUFFERS:
|
||||||
|
g_value_set_int (value, self->aux_buffers);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_COLOR_SIZE:
|
||||||
|
g_value_set_int (value, self->color_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_ALPHA_SIZE:
|
||||||
|
g_value_set_int (value, self->alpha_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DEPTH_SIZE:
|
||||||
|
g_value_set_int (value, self->depth_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_STENCIL_SIZE:
|
||||||
|
g_value_set_int (value, self->stencil_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_ACCUM_SIZE:
|
||||||
|
g_value_set_int (value, self->accum_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SAMPLE_BUFFERS:
|
||||||
|
g_value_set_int (value, self->sample_buffers);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SAMPLES:
|
||||||
|
g_value_set_int (value, self->samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PROFILE:
|
||||||
|
g_value_set_enum (value, self->profile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_pixel_format_class_init (GdkGLPixelFormatClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->set_property = gdk_gl_pixel_format_set_property;
|
||||||
|
gobject_class->get_property = gdk_gl_pixel_format_get_property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:double-buffer:
|
||||||
|
*
|
||||||
|
* Whether the pixel format should enable double buffering.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_DOUBLE_BUFFER] =
|
||||||
|
g_param_spec_boolean ("double-buffer",
|
||||||
|
P_("Double Buffer"),
|
||||||
|
P_("Whether the pixel format should ask for double buffering"),
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:multi-sample:
|
||||||
|
*
|
||||||
|
* Whether the pixel format should enable multi-sampling.
|
||||||
|
*
|
||||||
|
* See also the #GdkGLPixelFormat:sample-buffers and
|
||||||
|
* #GdkGLPixelFormat:samples properties.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_MULTI_SAMPLE] =
|
||||||
|
g_param_spec_boolean ("multi-sample",
|
||||||
|
P_("Multi Sample"),
|
||||||
|
P_("Whether the pixel format should enable multi-sampling"),
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:stereo:
|
||||||
|
*
|
||||||
|
* Whether the pixel format should support stereoscopic buffers.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_STEREO] =
|
||||||
|
g_param_spec_boolean ("stereo",
|
||||||
|
P_("Stereo"),
|
||||||
|
P_("Whether the pixel format should support stereoscopic buffers"),
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:aux-buffers:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the number of auxiliary buffers
|
||||||
|
* for the pixel format.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_AUX_BUFFERS] =
|
||||||
|
g_param_spec_int ("aux-buffers",
|
||||||
|
P_("Auxiliary Buffers"),
|
||||||
|
P_("The number of auxiliary buffers"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:color-size:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the size of each color buffer.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_COLOR_SIZE] =
|
||||||
|
g_param_spec_int ("color-size",
|
||||||
|
P_("Color Size"),
|
||||||
|
P_("The size of each color buffer"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:alpha-size:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the size of the alpha buffer.
|
||||||
|
*
|
||||||
|
* If set to 0, the alpha channel will be ignored.
|
||||||
|
*
|
||||||
|
* If set the -1, the default will be used.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_ALPHA_SIZE] =
|
||||||
|
g_param_spec_int ("alpha-size",
|
||||||
|
P_("Alpha Size"),
|
||||||
|
P_("The size of the alpha buffer"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:depth-size:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the size of the depth buffer.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_DEPTH_SIZE] =
|
||||||
|
g_param_spec_int ("depth-size",
|
||||||
|
P_("Depth Size"),
|
||||||
|
P_("The size of the depth buffer"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:stencil-size:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the size of the stencil buffer.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_STENCIL_SIZE] =
|
||||||
|
g_param_spec_int ("stencil-size",
|
||||||
|
P_("Stencil Size"),
|
||||||
|
P_("The size of the stencil buffer"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:accum-size:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the size of the accumulation buffer.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_ACCUM_SIZE] =
|
||||||
|
g_param_spec_int ("accum-size",
|
||||||
|
P_("Accumulation Size"),
|
||||||
|
P_("The size of the accumulation buffer"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:sample-buffers:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the number of multi-sample buffers.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* This property is only used if #GdkGLPixelFormat:multi-sample is set
|
||||||
|
* to %TRUE.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_SAMPLE_BUFFERS] =
|
||||||
|
g_param_spec_int ("sample-buffers",
|
||||||
|
P_("Sample Buffers"),
|
||||||
|
P_("The number of multi-sample buffers"),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:samples:
|
||||||
|
*
|
||||||
|
* A positive integer indicating the number of samples for each
|
||||||
|
* multi-sample buffer.
|
||||||
|
*
|
||||||
|
* If set to -1, the default will be used.
|
||||||
|
*
|
||||||
|
* This property is only used if #GdkGLPixelFormat:multi-sample is set
|
||||||
|
* to %TRUE.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_SAMPLES] =
|
||||||
|
g_param_spec_int ("samples",
|
||||||
|
P_("Samples"),
|
||||||
|
P_(""),
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormat:profile:
|
||||||
|
*
|
||||||
|
* The GL profile to be used when creating a #GdkGLContext.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_PROFILE] =
|
||||||
|
g_param_spec_enum ("profile",
|
||||||
|
P_("Profile"),
|
||||||
|
P_(""),
|
||||||
|
GDK_TYPE_GL_PIXEL_FORMAT_PROFILE,
|
||||||
|
GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
g_object_class_install_properties (gobject_class, LAST_PROP, obj_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_gl_pixel_format_init (GdkGLPixelFormat *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_new:
|
||||||
|
* @first_property: the first property to set
|
||||||
|
* @...: the value of the @first_property, followed by a %NULL terminated
|
||||||
|
* set of property, value pairs
|
||||||
|
*
|
||||||
|
* Creates a new #GdkGLPixelFormat with the given list of properties.
|
||||||
|
*
|
||||||
|
* Returns: the newly created #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkGLPixelFormat *
|
||||||
|
gdk_gl_pixel_format_new (const char *first_property,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
GdkGLPixelFormat *res;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, first_property);
|
||||||
|
|
||||||
|
res = (GdkGLPixelFormat *) g_object_new_valist (GDK_TYPE_GL_PIXEL_FORMAT, first_property, args);
|
||||||
|
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GDK_GL_PIXEL_FORMAT_GET(CType,FieldName,DefaultValue) \
|
||||||
|
CType \
|
||||||
|
gdk_gl_pixel_format_get_ ## FieldName (GdkGLPixelFormat *format) \
|
||||||
|
{ \
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (format), DefaultValue); \
|
||||||
|
\
|
||||||
|
return format->FieldName; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_double_buffer:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:double-buffer property.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the pixel format is double buffered
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gboolean, double_buffer, FALSE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_multi_sample:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:multi-sample property.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the pixel format supports multi-sampling
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gboolean, multi_sample, FALSE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_stereo:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:stereo property.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the pixel format supports stereoscopic buffers
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gboolean, stereo, FALSE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_color_size:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:color-size property.
|
||||||
|
*
|
||||||
|
* Returns: the size of the RGB components of the color buffer
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, color_size, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_alpha_size:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:alpha-size property.
|
||||||
|
*
|
||||||
|
* Returns: the size of the alpha component of the color buffer
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, alpha_size, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_depth_size:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:depth-size property.
|
||||||
|
*
|
||||||
|
* Returns: the size of the depth buffer
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, depth_size, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_stencil_size:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:stencil-size property.
|
||||||
|
*
|
||||||
|
* Returns: the size of the stencil buffer
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, stencil_size, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_aux_buffers:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:aux-buffers property.
|
||||||
|
*
|
||||||
|
* Returns: the number of auxiliary buffers.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, aux_buffers, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_accum_size:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:accum-size property.
|
||||||
|
*
|
||||||
|
* Returns: the size of the accumulation buffers
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, accum_size, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_sample_buffers:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:sample-buffers property.
|
||||||
|
*
|
||||||
|
* Returns: the number of multi-sample buffers
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, sample_buffers, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_gl_pixel_format_get_samples:
|
||||||
|
* @format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Retrieves the value of the #GdkGLPixelFormat:samples property.
|
||||||
|
*
|
||||||
|
* Returns: the number of samples for each multi-sample buffer
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GDK_GL_PIXEL_FORMAT_GET (gint, samples, 0)
|
||||||
|
|
||||||
|
#undef GDK_GL_PIXEL_FORMAT_GET
|
75
gdk/gdkglpixelformat.h
Normal file
75
gdk/gdkglpixelformat.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglpixelformat.h: GL pixel formats
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_GL_PIXEL_FORMAT_H__
|
||||||
|
#define __GDK_GL_PIXEL_FORMAT_H__
|
||||||
|
|
||||||
|
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||||
|
#error "Only <gdk/gdk.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gdk/gdkversionmacros.h>
|
||||||
|
#include <gdk/gdktypes.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_TYPE_GL_PIXEL_FORMAT (gdk_gl_pixel_format_get_type ())
|
||||||
|
#define GDK_GL_PIXEL_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_PIXEL_FORMAT, GdkGLPixelFormat))
|
||||||
|
#define GDK_IS_GL_PIXEL_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_PIXEL_FORMAT))
|
||||||
|
|
||||||
|
#define GDK_GL_PIXEL_FORMAT_ERROR (gdk_gl_pixel_format_error_quark ())
|
||||||
|
|
||||||
|
typedef struct _GdkGLPixelFormatClass GdkGLPixelFormatClass;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GType gdk_gl_pixel_format_get_type (void) G_GNUC_CONST;
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GQuark gdk_gl_pixel_format_error_quark (void);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkGLPixelFormat * gdk_gl_pixel_format_new (const char *first_property,
|
||||||
|
...);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gboolean gdk_gl_pixel_format_get_double_buffer (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gboolean gdk_gl_pixel_format_get_multi_sample (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gboolean gdk_gl_pixel_format_get_stereo (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_color_size (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_alpha_size (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_depth_size (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_stencil_size (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_accum_size (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_aux_buffers (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_sample_buffers (GdkGLPixelFormat *format);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gint gdk_gl_pixel_format_get_samples (GdkGLPixelFormat *format);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_GL_PIXEL_FORMAT_H__ */
|
59
gdk/gdkglpixelformatprivate.h
Normal file
59
gdk/gdkglpixelformatprivate.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglpixelformatprivate.h: GL pixel formats private API
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_GL_PIXEL_FORMAT_PRIVATE_H__
|
||||||
|
#define __GDK_GL_PIXEL_FORMAT_PRIVATE_H__
|
||||||
|
|
||||||
|
#include "gdkglpixelformat.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_GL_PIXEL_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_PIXEL_FORMAT, GdkGLPixelFormatClass))
|
||||||
|
#define GDK_IS_GL_PIXEL_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_PIXEL_FORMAT))
|
||||||
|
#define GDK_GL_PIXEL_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_PIXEL_FORMAT, GdkGLPixelFormatClass))
|
||||||
|
|
||||||
|
struct _GdkGLPixelFormat
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
gboolean double_buffer;
|
||||||
|
gboolean multi_sample;
|
||||||
|
gboolean stereo;
|
||||||
|
|
||||||
|
int aux_buffers;
|
||||||
|
int color_size;
|
||||||
|
int alpha_size;
|
||||||
|
int depth_size;
|
||||||
|
int stencil_size;
|
||||||
|
int accum_size;
|
||||||
|
int sample_buffers;
|
||||||
|
int samples;
|
||||||
|
|
||||||
|
GdkGLPixelFormatProfile profile;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GdkGLPixelFormatClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_GL_PIXEL_FORMAT_PRIVATE_H__ */
|
@@ -84,7 +84,8 @@ typedef enum {
|
|||||||
GDK_DEBUG_DRAW = 1 << 9,
|
GDK_DEBUG_DRAW = 1 << 9,
|
||||||
GDK_DEBUG_EVENTLOOP = 1 << 10,
|
GDK_DEBUG_EVENTLOOP = 1 << 10,
|
||||||
GDK_DEBUG_FRAMES = 1 << 11,
|
GDK_DEBUG_FRAMES = 1 << 11,
|
||||||
GDK_DEBUG_SETTINGS = 1 << 12
|
GDK_DEBUG_SETTINGS = 1 << 12,
|
||||||
|
GDK_DEBUG_OPENGL = 1 << 13
|
||||||
} GdkDebugFlag;
|
} GdkDebugFlag;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -406,6 +407,11 @@ void _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_win
|
|||||||
gboolean _gdk_window_has_impl (GdkWindow *window);
|
gboolean _gdk_window_has_impl (GdkWindow *window);
|
||||||
GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
|
GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
|
||||||
|
|
||||||
|
gboolean gdk_window_has_gl_context (GdkWindow *window);
|
||||||
|
void gdk_window_set_gl_context (GdkWindow *window,
|
||||||
|
GdkGLContext *context);
|
||||||
|
GdkGLContext * gdk_window_get_gl_context (GdkWindow *window);
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
* offscreen window routines *
|
* offscreen window routines *
|
||||||
*****************************/
|
*****************************/
|
||||||
|
@@ -128,6 +128,9 @@ typedef struct _GdkWindow GdkWindow;
|
|||||||
typedef struct _GdkKeymap GdkKeymap;
|
typedef struct _GdkKeymap GdkKeymap;
|
||||||
typedef struct _GdkAppLaunchContext GdkAppLaunchContext;
|
typedef struct _GdkAppLaunchContext GdkAppLaunchContext;
|
||||||
|
|
||||||
|
typedef struct _GdkGLPixelFormat GdkGLPixelFormat;
|
||||||
|
typedef struct _GdkGLContext GdkGLContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GdkByteOrder:
|
* GdkByteOrder:
|
||||||
* @GDK_LSB_FIRST: The values are stored with the least-significant byte
|
* @GDK_LSB_FIRST: The values are stored with the least-significant byte
|
||||||
@@ -429,8 +432,25 @@ struct _GdkPoint
|
|||||||
gint y;
|
gint y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkGLPixelFormatProfile:
|
||||||
|
* @GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT: ...
|
||||||
|
* @GDK_GL_PIXEL_FORMAT_PROFILE_LEGACY: ...
|
||||||
|
* @GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE: ...
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT,
|
||||||
|
GDK_GL_PIXEL_FORMAT_PROFILE_LEGACY,
|
||||||
|
GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE
|
||||||
|
} GdkGLPixelFormatProfile;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_INVALID_FORMAT,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE
|
||||||
|
} GdkGLPixelFormatError;
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GDK_TYPES_H__ */
|
#endif /* __GDK_TYPES_H__ */
|
||||||
|
@@ -39,6 +39,8 @@ libgdk_x11_la_SOURCES = \
|
|||||||
gdkeventtranslator.c \
|
gdkeventtranslator.c \
|
||||||
gdkeventtranslator.h \
|
gdkeventtranslator.h \
|
||||||
gdkgeometry-x11.c \
|
gdkgeometry-x11.c \
|
||||||
|
gdkglcontext-x11.c \
|
||||||
|
gdkglcontext-x11.h \
|
||||||
gdkkeys-x11.c \
|
gdkkeys-x11.c \
|
||||||
gdkmain-x11.c \
|
gdkmain-x11.c \
|
||||||
gdkproperty-x11.c \
|
gdkproperty-x11.c \
|
||||||
@@ -71,6 +73,7 @@ libgdkx11include_HEADERS = \
|
|||||||
gdkx11display.h \
|
gdkx11display.h \
|
||||||
gdkx11displaymanager.h \
|
gdkx11displaymanager.h \
|
||||||
gdkx11dnd.h \
|
gdkx11dnd.h \
|
||||||
|
gdkx11glcontext.h \
|
||||||
gdkx11keys.h \
|
gdkx11keys.h \
|
||||||
gdkx11property.h \
|
gdkx11property.h \
|
||||||
gdkx11screen.h \
|
gdkx11screen.h \
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "gdkdisplay-x11.h"
|
#include "gdkdisplay-x11.h"
|
||||||
#include "gdkprivate-x11.h"
|
#include "gdkprivate-x11.h"
|
||||||
#include "gdkscreen-x11.h"
|
#include "gdkscreen-x11.h"
|
||||||
|
#include "gdkglcontext-x11.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib/gprintf.h>
|
#include <glib/gprintf.h>
|
||||||
@@ -781,11 +782,13 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!window ||
|
if (!window ||
|
||||||
xevent->xconfigure.event != xevent->xconfigure.window ||
|
xevent->xconfigure.event != xevent->xconfigure.window ||
|
||||||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
|
GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
|
||||||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
|
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
|
||||||
return_val = FALSE;
|
{
|
||||||
|
return_val = FALSE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
event->configure.type = GDK_CONFIGURE;
|
event->configure.type = GDK_CONFIGURE;
|
||||||
@@ -2903,5 +2906,10 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
|
|||||||
display_class->text_property_to_utf8_list = _gdk_x11_display_text_property_to_utf8_list;
|
display_class->text_property_to_utf8_list = _gdk_x11_display_text_property_to_utf8_list;
|
||||||
display_class->utf8_to_string_target = _gdk_x11_display_utf8_to_string_target;
|
display_class->utf8_to_string_target = _gdk_x11_display_utf8_to_string_target;
|
||||||
|
|
||||||
|
display_class->validate_gl_pixel_format = gdk_x11_display_validate_gl_pixel_format;
|
||||||
|
display_class->create_gl_context = gdk_x11_display_create_gl_context;
|
||||||
|
display_class->destroy_gl_context = gdk_x11_display_destroy_gl_context;
|
||||||
|
display_class->make_gl_context_current = gdk_x11_display_make_gl_context_current;
|
||||||
|
|
||||||
_gdk_x11_windowing_init ();
|
_gdk_x11_windowing_init ();
|
||||||
}
|
}
|
||||||
|
@@ -124,6 +124,20 @@ struct _GdkX11Display
|
|||||||
GSList *error_traps;
|
GSList *error_traps;
|
||||||
|
|
||||||
gint wm_moveresize_button;
|
gint wm_moveresize_button;
|
||||||
|
|
||||||
|
/* GLX information */
|
||||||
|
guint have_glx : 1;
|
||||||
|
gint glx_version;
|
||||||
|
gint glx_error_base;
|
||||||
|
gint glx_event_base;
|
||||||
|
|
||||||
|
/* GLX extensions we check */
|
||||||
|
guint has_glx_swap_interval : 1;
|
||||||
|
guint has_glx_create_context : 1;
|
||||||
|
guint has_glx_texture_from_pixmap : 1;
|
||||||
|
guint has_glx_video_sync : 1;
|
||||||
|
guint has_glx_buffer_age : 1;
|
||||||
|
guint has_glx_sync_control : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GdkX11DisplayClass
|
struct _GdkX11DisplayClass
|
||||||
|
920
gdk/x11/gdkglcontext-x11.c
Normal file
920
gdk/x11/gdkglcontext-x11.c
Normal file
@@ -0,0 +1,920 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglcontext-x11.c: X11 specific OpenGL wrappers
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gdkglcontext-x11.h"
|
||||||
|
#include "gdkdisplay-x11.h"
|
||||||
|
#include "gdkscreen-x11.h"
|
||||||
|
|
||||||
|
#include "gdkx11display.h"
|
||||||
|
#include "gdkx11glcontext.h"
|
||||||
|
#include "gdkx11screen.h"
|
||||||
|
#include "gdkx11window.h"
|
||||||
|
#include "gdkx11visual.h"
|
||||||
|
|
||||||
|
#include "gdkinternals.h"
|
||||||
|
|
||||||
|
#include "gdkintl.h"
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLXDrawable drawable;
|
||||||
|
|
||||||
|
GdkDisplay *display;
|
||||||
|
GdkGLContext *context;
|
||||||
|
GdkWindow *window;
|
||||||
|
|
||||||
|
guint32 last_frame_counter;
|
||||||
|
} DrawableInfo;
|
||||||
|
|
||||||
|
static void
|
||||||
|
drawable_info_free (gpointer data_)
|
||||||
|
{
|
||||||
|
DrawableInfo *data = data_;
|
||||||
|
|
||||||
|
gdk_x11_display_error_trap_push (data->display);
|
||||||
|
|
||||||
|
if (data->drawable)
|
||||||
|
glXDestroyWindow (gdk_x11_display_get_xdisplay (data->display), data->drawable);
|
||||||
|
|
||||||
|
gdk_x11_display_error_trap_pop_ignored (data->display);
|
||||||
|
|
||||||
|
g_slice_free (DrawableInfo, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DrawableInfo *
|
||||||
|
get_glx_drawable_info (GdkWindow *window)
|
||||||
|
{
|
||||||
|
return g_object_get_data (G_OBJECT (window), "-gdk-x11-window-glx-info");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_glx_drawable_info (GdkWindow *window,
|
||||||
|
DrawableInfo *info)
|
||||||
|
{
|
||||||
|
g_object_set_data_full (G_OBJECT (window), "-gdk-x11-window-glx-info",
|
||||||
|
info,
|
||||||
|
drawable_info_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_gl_context_set_window (GdkGLContext *context,
|
||||||
|
GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||||
|
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||||
|
DrawableInfo *info;
|
||||||
|
|
||||||
|
if (window == NULL)
|
||||||
|
{
|
||||||
|
gdk_x11_display_make_gl_context_current (display, context, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we need to make sure that the GdkWindow is backed by
|
||||||
|
* an actual native surface
|
||||||
|
*/
|
||||||
|
gdk_window_ensure_native (window);
|
||||||
|
|
||||||
|
/* GLX < 1.3 accepts X11 drawables, so there's no need to
|
||||||
|
* go through the creation of a GLX drawable
|
||||||
|
*/
|
||||||
|
if (GDK_X11_DISPLAY (display)->glx_version < 13)
|
||||||
|
return;
|
||||||
|
|
||||||
|
info = get_glx_drawable_info (window);
|
||||||
|
if (info != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_x11_display_error_trap_push (display);
|
||||||
|
|
||||||
|
info = g_slice_new (DrawableInfo);
|
||||||
|
info->window = window;
|
||||||
|
info->context = context;
|
||||||
|
info->display = display;
|
||||||
|
info->drawable = glXCreateWindow (gdk_x11_display_get_xdisplay (display),
|
||||||
|
context_x11->glx_config,
|
||||||
|
gdk_x11_window_get_xid (window),
|
||||||
|
NULL);
|
||||||
|
info->last_frame_counter = 0;
|
||||||
|
|
||||||
|
gdk_x11_display_error_trap_pop_ignored (display);
|
||||||
|
|
||||||
|
set_glx_drawable_info (window, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_gl_context_update (GdkGLContext *context,
|
||||||
|
GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
if (!gdk_x11_display_make_gl_context_current (display, context, window))
|
||||||
|
return;
|
||||||
|
|
||||||
|
width = gdk_window_get_width (window);
|
||||||
|
height = gdk_window_get_height (window);
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL, g_print ("Updating GL viewport size to { %d, %d } for window %lu (context: %p)\n",
|
||||||
|
width, height,
|
||||||
|
(unsigned long) gdk_x11_window_get_xid (window),
|
||||||
|
context));
|
||||||
|
|
||||||
|
glViewport (0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_wait_for_vblank (GdkDisplay *display,
|
||||||
|
GLXDrawable drawable)
|
||||||
|
{
|
||||||
|
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||||
|
Display *dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
|
||||||
|
if (display_x11->has_glx_sync_control)
|
||||||
|
{
|
||||||
|
gint64 ust, msc, sbc;
|
||||||
|
|
||||||
|
glXGetSyncValuesOML (dpy, drawable, &ust, &msc, &sbc);
|
||||||
|
glXWaitForMscOML (dpy, drawable,
|
||||||
|
0, 2, (msc + 1) % 2,
|
||||||
|
&ust, &msc, &sbc);
|
||||||
|
}
|
||||||
|
else if (display_x11->has_glx_video_sync)
|
||||||
|
{
|
||||||
|
guint32 current_count;
|
||||||
|
|
||||||
|
glXGetVideoSyncSGI (¤t_count);
|
||||||
|
glXWaitVideoSyncSGI (2, (current_count + 1) % 2, ¤t_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_gl_context_flush_buffer (GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||||
|
GdkWindow *window = gdk_gl_context_get_window (context);
|
||||||
|
Display *dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||||
|
DrawableInfo *info;
|
||||||
|
GLXDrawable drawable;
|
||||||
|
|
||||||
|
if (window == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_x11_display_make_gl_context_current (display, context, window);
|
||||||
|
|
||||||
|
info = get_glx_drawable_info (window);
|
||||||
|
if (info != NULL && info->drawable != None)
|
||||||
|
drawable = info->drawable;
|
||||||
|
else
|
||||||
|
drawable = gdk_x11_window_get_xid (window);
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL,
|
||||||
|
g_print ("Flushing GLX buffers for %s drawable %lu (window: %lu)\n",
|
||||||
|
drawable == info->drawable ? "GLX" : "X11",
|
||||||
|
(unsigned long) drawable,
|
||||||
|
(unsigned long) gdk_x11_window_get_xid (window)));
|
||||||
|
|
||||||
|
/* if we are going to wait for the vertical refresh manually
|
||||||
|
* we need to flush pending redraws, and we also need to wait
|
||||||
|
* for that to finish, otherwise we are going to tear.
|
||||||
|
*
|
||||||
|
* obviously, this condition should not be hit if we have
|
||||||
|
* GLX_SGI_swap_control, and we ask the driver to do the right
|
||||||
|
* thing.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
guint32 end_frame_counter = 0;
|
||||||
|
gboolean has_counter = display_x11->has_glx_video_sync;
|
||||||
|
gboolean can_wait = display_x11->has_glx_video_sync ||
|
||||||
|
display_x11->has_glx_sync_control;
|
||||||
|
|
||||||
|
if (display_x11->has_glx_video_sync)
|
||||||
|
glXGetVideoSyncSGI (&end_frame_counter);
|
||||||
|
|
||||||
|
if (!display_x11->has_glx_swap_interval)
|
||||||
|
{
|
||||||
|
glFinish ();
|
||||||
|
|
||||||
|
if (has_counter && can_wait)
|
||||||
|
{
|
||||||
|
guint32 last_counter = info != NULL ? info->last_frame_counter : 0;
|
||||||
|
|
||||||
|
if (last_counter == end_frame_counter)
|
||||||
|
maybe_wait_for_vblank (display, drawable);
|
||||||
|
}
|
||||||
|
else if (can_wait)
|
||||||
|
maybe_wait_for_vblank (display, drawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glXSwapBuffers (dpy, drawable);
|
||||||
|
|
||||||
|
if (info != NULL && display_x11->has_glx_video_sync)
|
||||||
|
glXGetVideoSyncSGI (&info->last_frame_counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
|
||||||
|
{
|
||||||
|
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
|
||||||
|
|
||||||
|
context_class->set_window = gdk_x11_gl_context_set_window;
|
||||||
|
context_class->update = gdk_x11_gl_context_update;
|
||||||
|
context_class->flush_buffer = gdk_x11_gl_context_flush_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_gl_context_init (GdkX11GLContext *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdk_x11_display_init_gl (GdkDisplay *display)
|
||||||
|
{
|
||||||
|
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||||
|
GdkScreen *screen;
|
||||||
|
Display *dpy;
|
||||||
|
int error_base, event_base;
|
||||||
|
int screen_num;
|
||||||
|
|
||||||
|
if (display_x11->have_glx)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
|
||||||
|
if (!glXQueryExtension (dpy, &error_base, &event_base))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
screen = gdk_display_get_default_screen (display);
|
||||||
|
screen_num = GDK_X11_SCREEN (screen)->screen_num;
|
||||||
|
|
||||||
|
display_x11->have_glx = TRUE;
|
||||||
|
|
||||||
|
display_x11->glx_version = epoxy_glx_version (dpy, screen_num);
|
||||||
|
display_x11->glx_error_base = error_base;
|
||||||
|
display_x11->glx_event_base = event_base;
|
||||||
|
|
||||||
|
display_x11->has_glx_create_context =
|
||||||
|
epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_create_context_profile");
|
||||||
|
display_x11->has_glx_swap_interval =
|
||||||
|
epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_swap_control");
|
||||||
|
display_x11->has_glx_texture_from_pixmap =
|
||||||
|
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap");
|
||||||
|
display_x11->has_glx_video_sync =
|
||||||
|
epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_video_sync");
|
||||||
|
display_x11->has_glx_buffer_age =
|
||||||
|
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_buffer_age");
|
||||||
|
display_x11->has_glx_sync_control =
|
||||||
|
epoxy_has_glx_extension (dpy, screen_num, "GLX_OML_sync_control");
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL,
|
||||||
|
g_print ("GLX version %d.%d found\n"
|
||||||
|
" - Vendor: %s\n"
|
||||||
|
" - Checked extensions:\n"
|
||||||
|
"\t* GLX_ARB_create_context_profile: %s\n"
|
||||||
|
"\t* GLX_SGI_swap_control: %s\n"
|
||||||
|
"\t* GLX_EXT_texture_from_pixmap: %s\n"
|
||||||
|
"\t* GLX_SGI_video_sync: %s\n"
|
||||||
|
"\t* GLX_EXT_buffer_age: %s\n"
|
||||||
|
"\t* GLX_OML_sync_control: %s\n",
|
||||||
|
display_x11->glx_version / 10,
|
||||||
|
display_x11->glx_version % 10,
|
||||||
|
glXGetClientString (dpy, GLX_VENDOR),
|
||||||
|
display_x11->has_glx_create_context ? "yes" : "no",
|
||||||
|
display_x11->has_glx_swap_interval ? "yes" : "no",
|
||||||
|
display_x11->has_glx_texture_from_pixmap ? "yes" : "no",
|
||||||
|
display_x11->has_glx_video_sync ? "yes" : "no",
|
||||||
|
display_x11->has_glx_buffer_age ? "yes" : "no",
|
||||||
|
display_x11->has_glx_sync_control ? "yes" : "no"));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_GLX_ATTRS 30
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_glx_attributes_for_pixel_format (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
int *attrs)
|
||||||
|
{
|
||||||
|
GdkX11Display *display_x11;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
attrs[i++] = GLX_DRAWABLE_TYPE;
|
||||||
|
attrs[i++] = GLX_WINDOW_BIT;
|
||||||
|
|
||||||
|
attrs[i++] = GLX_RENDER_TYPE;
|
||||||
|
attrs[i++] = GLX_RGBA_BIT;
|
||||||
|
|
||||||
|
if (format->double_buffer)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_DOUBLEBUFFER;
|
||||||
|
attrs[i++] = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->stereo)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_STEREO;
|
||||||
|
attrs[i++] = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->color_size < 0)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_RED_SIZE;
|
||||||
|
attrs[i++] = 1;
|
||||||
|
attrs[i++] = GLX_GREEN_SIZE;
|
||||||
|
attrs[i++] = 1;
|
||||||
|
attrs[i++] = GLX_BLUE_SIZE;
|
||||||
|
attrs[i++] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_RED_SIZE;
|
||||||
|
attrs[i++] = format->color_size;
|
||||||
|
attrs[i++] = GLX_GREEN_SIZE;
|
||||||
|
attrs[i++] = format->color_size;
|
||||||
|
attrs[i++] = GLX_BLUE_SIZE;
|
||||||
|
attrs[i++] = format->color_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->alpha_size < 0)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_ALPHA_SIZE;
|
||||||
|
attrs[i++] = 1;
|
||||||
|
}
|
||||||
|
else if (format->alpha_size == 0)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_ALPHA_SIZE;
|
||||||
|
attrs[i++] = GLX_DONT_CARE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_ALPHA_SIZE;
|
||||||
|
attrs[i++] = format->alpha_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->depth_size < 0)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_DEPTH_SIZE;
|
||||||
|
attrs[i++] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_DEPTH_SIZE;
|
||||||
|
attrs[i++] = format->depth_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->stencil_size < 0)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_STENCIL_SIZE;
|
||||||
|
attrs[i++] = GLX_DONT_CARE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_STENCIL_SIZE;
|
||||||
|
attrs[i++] = format->stencil_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->accum_size > 0)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_ACCUM_RED_SIZE;
|
||||||
|
attrs[i++] = format->accum_size;
|
||||||
|
attrs[i++] = GLX_ACCUM_GREEN_SIZE;
|
||||||
|
attrs[i++] = format->accum_size;
|
||||||
|
attrs[i++] = GLX_ACCUM_BLUE_SIZE;
|
||||||
|
attrs[i++] = format->accum_size;
|
||||||
|
attrs[i++] = GLX_ACCUM_ALPHA_SIZE;
|
||||||
|
attrs[i++] = format->accum_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_x11 = GDK_X11_DISPLAY (display);
|
||||||
|
if (display_x11->glx_version >= 14 && format->multi_sample)
|
||||||
|
{
|
||||||
|
attrs[i++] = GLX_SAMPLE_BUFFERS;
|
||||||
|
attrs[i++] = format->sample_buffers > 0 ? format->sample_buffers : 1;
|
||||||
|
|
||||||
|
attrs[i++] = GLX_SAMPLES;
|
||||||
|
attrs[i++] = format->samples > 0 ? format->samples : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs[i++] = None;
|
||||||
|
|
||||||
|
g_assert (i < MAX_GLX_ATTRS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
find_fbconfig_for_pixel_format (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GLXFBConfig *fb_config_out,
|
||||||
|
XVisualInfo **visinfo_out,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
static int attrs[MAX_GLX_ATTRS];
|
||||||
|
|
||||||
|
Display *dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
GLXFBConfig *configs;
|
||||||
|
int n_configs, i;
|
||||||
|
gboolean use_rgba;
|
||||||
|
gboolean retval = FALSE;
|
||||||
|
|
||||||
|
get_glx_attributes_for_pixel_format (display, format, attrs);
|
||||||
|
|
||||||
|
use_rgba = format->alpha_size != 0;
|
||||||
|
|
||||||
|
configs = glXChooseFBConfig (dpy, DefaultScreen (dpy), attrs, &n_configs);
|
||||||
|
if (configs == NULL || n_configs == 0)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE,
|
||||||
|
_("No available configurations for the given pixel format"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we don't care about an alpha channel, then the first
|
||||||
|
* valid configuration is the one we give back
|
||||||
|
*/
|
||||||
|
if (!use_rgba)
|
||||||
|
{
|
||||||
|
if (fb_config_out != NULL)
|
||||||
|
*fb_config_out = configs[0];
|
||||||
|
|
||||||
|
if (visinfo_out != NULL)
|
||||||
|
*visinfo_out = glXGetVisualFromFBConfig (dpy, configs[0]);
|
||||||
|
|
||||||
|
retval = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n_configs; i++)
|
||||||
|
{
|
||||||
|
XVisualInfo *visinfo;
|
||||||
|
unsigned long mask;
|
||||||
|
|
||||||
|
visinfo = glXGetVisualFromFBConfig (dpy, configs[i]);
|
||||||
|
if (visinfo == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mask = visinfo->red_mask | visinfo->green_mask | visinfo->blue_mask;
|
||||||
|
if (visinfo->depth == 32 && mask != 0xffffffff)
|
||||||
|
{
|
||||||
|
if (fb_config_out != NULL)
|
||||||
|
*fb_config_out = configs[i];
|
||||||
|
|
||||||
|
if (visinfo_out != NULL)
|
||||||
|
*visinfo_out = visinfo;
|
||||||
|
|
||||||
|
retval = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree (visinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_set_error (error, GDK_GL_PIXEL_FORMAT_ERROR,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE,
|
||||||
|
_("No available configurations for the given RGBA pixel format"));
|
||||||
|
|
||||||
|
out:
|
||||||
|
XFree (configs);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_pixel_format (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GLXFBConfig config)
|
||||||
|
{
|
||||||
|
Display *dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_DOUBLEBUFFER, &format->double_buffer);
|
||||||
|
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_RED_SIZE, &value);
|
||||||
|
format->color_size = value;
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_GREEN_SIZE, &value);
|
||||||
|
format->color_size = MIN (format->color_size, value);
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_BLUE_SIZE, &value);
|
||||||
|
format->color_size = MIN (format->color_size, value);
|
||||||
|
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_ALPHA_SIZE, &format->alpha_size);
|
||||||
|
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_AUX_BUFFERS, &format->aux_buffers);
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_DEPTH_SIZE, &format->depth_size);
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_STENCIL_SIZE, &format->stencil_size);
|
||||||
|
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_ACCUM_RED_SIZE, &value);
|
||||||
|
format->accum_size = value;
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_ACCUM_GREEN_SIZE, &value);
|
||||||
|
format->accum_size = MIN (format->accum_size, value);
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_ACCUM_BLUE_SIZE, &value);
|
||||||
|
format->accum_size = MIN (format->accum_size, value);
|
||||||
|
glXGetFBConfigAttrib (dpy, config, GLX_ACCUM_ALPHA_SIZE, &value);
|
||||||
|
format->accum_size = MIN (format->accum_size, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLXContext
|
||||||
|
create_gl3_context (GdkDisplay *display,
|
||||||
|
GLXFBConfig config,
|
||||||
|
GdkGLContext *share)
|
||||||
|
{
|
||||||
|
static const int attrib_list[] = {
|
||||||
|
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||||
|
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||||
|
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
|
||||||
|
None,
|
||||||
|
};
|
||||||
|
|
||||||
|
GdkX11GLContext *context_x11 = NULL;
|
||||||
|
|
||||||
|
if (share != NULL)
|
||||||
|
context_x11 = GDK_X11_GL_CONTEXT (share);
|
||||||
|
|
||||||
|
return glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display),
|
||||||
|
config,
|
||||||
|
context_x11 != NULL ? context_x11->glx_context : NULL,
|
||||||
|
True,
|
||||||
|
attrib_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLXContext
|
||||||
|
create_gl_context (GdkDisplay *display,
|
||||||
|
GLXFBConfig config,
|
||||||
|
GdkGLContext *share)
|
||||||
|
{
|
||||||
|
GdkX11GLContext *context_x11 = NULL;
|
||||||
|
|
||||||
|
if (share != NULL)
|
||||||
|
context_x11 = GDK_X11_GL_CONTEXT (share);
|
||||||
|
|
||||||
|
return glXCreateNewContext (gdk_x11_display_get_xdisplay (display),
|
||||||
|
config,
|
||||||
|
GLX_RGBA_TYPE,
|
||||||
|
context_x11 != NULL ? context_x11->glx_context : NULL,
|
||||||
|
True);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkGLContext *
|
||||||
|
gdk_x11_display_create_gl_context (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GdkGLContext *share,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GdkGLPixelFormat *valid_format;
|
||||||
|
GdkX11GLContext *context;
|
||||||
|
GdkVisual *gdk_visual;
|
||||||
|
GLXFBConfig config;
|
||||||
|
GLXContext glx_context;
|
||||||
|
Window dummy_xwin;
|
||||||
|
GLXWindow dummy_glx;
|
||||||
|
GLXWindow dummy_drawable;
|
||||||
|
gboolean is_direct;
|
||||||
|
XVisualInfo *xvisinfo;
|
||||||
|
XSetWindowAttributes attrs;
|
||||||
|
unsigned long mask;
|
||||||
|
Display *dpy;
|
||||||
|
|
||||||
|
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: we know the pixel format has a valid GLXFBConfig
|
||||||
|
*/
|
||||||
|
find_fbconfig_for_pixel_format (display, format, &config, &xvisinfo, NULL);
|
||||||
|
|
||||||
|
dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
|
||||||
|
/* we check for the GLX_ARB_create_context_profile extension
|
||||||
|
* while validating the PixelFormat.
|
||||||
|
*/
|
||||||
|
if (format->profile == GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE)
|
||||||
|
glx_context = create_gl3_context (display, config, share);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT is currently
|
||||||
|
* equivalent to the LEGACY profile
|
||||||
|
*/
|
||||||
|
glx_context = create_gl_context (display, config, share);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glx_context == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE,
|
||||||
|
_("Unable to create a GL context"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_direct = glXIsDirect (dpy, glx_context);
|
||||||
|
|
||||||
|
gdk_x11_display_error_trap_push (display);
|
||||||
|
|
||||||
|
/* create a dummy window; this is needed because GLX does not allow
|
||||||
|
* us to query the context until it's bound to a drawable; we simply
|
||||||
|
* create a small OR window, put it off screen, and never map it. in
|
||||||
|
* order to keep the GL machinery in a sane state, we always make
|
||||||
|
* the dummy window the current drawable if the user unsets the
|
||||||
|
* GdkWindow bound to the GdkGLContext.
|
||||||
|
*/
|
||||||
|
attrs.override_redirect = True;
|
||||||
|
attrs.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), xvisinfo->visual, AllocNone);
|
||||||
|
attrs.border_pixel = 0;
|
||||||
|
mask = CWOverrideRedirect | CWColormap | CWBorderPixel;
|
||||||
|
|
||||||
|
dummy_xwin = XCreateWindow (dpy, DefaultRootWindow (dpy),
|
||||||
|
-100, -100, 1, 1,
|
||||||
|
0,
|
||||||
|
xvisinfo->depth,
|
||||||
|
CopyFromParent,
|
||||||
|
xvisinfo->visual,
|
||||||
|
mask,
|
||||||
|
&attrs);
|
||||||
|
|
||||||
|
/* GLX API introduced in 1.3 expects GLX drawables */
|
||||||
|
if (GDK_X11_DISPLAY (display)->glx_version >= 13)
|
||||||
|
dummy_glx = glXCreateWindow (dpy, config, dummy_xwin, NULL);
|
||||||
|
else
|
||||||
|
dummy_glx = None;
|
||||||
|
|
||||||
|
dummy_drawable = dummy_glx != None
|
||||||
|
? dummy_glx
|
||||||
|
: dummy_xwin;
|
||||||
|
|
||||||
|
glXMakeContextCurrent (dpy, dummy_drawable, dummy_drawable, glx_context);
|
||||||
|
|
||||||
|
gdk_visual = gdk_x11_screen_lookup_visual (gdk_display_get_default_screen (display),
|
||||||
|
xvisinfo->visualid);
|
||||||
|
|
||||||
|
XFree (xvisinfo);
|
||||||
|
|
||||||
|
if (gdk_x11_display_error_trap_pop (display))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE,
|
||||||
|
_("Unable to create a GL context"));
|
||||||
|
|
||||||
|
glXDestroyContext (dpy, glx_context);
|
||||||
|
|
||||||
|
if (dummy_xwin)
|
||||||
|
XDestroyWindow (dpy, dummy_xwin);
|
||||||
|
if (dummy_glx)
|
||||||
|
glXDestroyWindow (dpy, dummy_glx);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL,
|
||||||
|
g_print ("Created GLX context[%p], %s, dummy drawable: %lu\n",
|
||||||
|
glx_context,
|
||||||
|
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", valid_format,
|
||||||
|
"visual", gdk_visual,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
context->glx_config = config;
|
||||||
|
context->glx_context = glx_context;
|
||||||
|
context->dummy_drawable = dummy_xwin;
|
||||||
|
context->dummy_glx_drawable = dummy_glx;
|
||||||
|
context->current_drawable = dummy_drawable;
|
||||||
|
context->is_direct = is_direct;
|
||||||
|
|
||||||
|
g_object_unref (valid_format);
|
||||||
|
|
||||||
|
return GDK_GL_CONTEXT (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdk_x11_display_destroy_gl_context (GdkDisplay *display,
|
||||||
|
GdkGLContext *context)
|
||||||
|
{
|
||||||
|
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||||
|
Display *dpy = gdk_x11_display_get_xdisplay (display);
|
||||||
|
|
||||||
|
if (context_x11->glx_context != NULL)
|
||||||
|
{
|
||||||
|
if (glXGetCurrentContext () == context_x11->glx_context)
|
||||||
|
glXMakeContextCurrent (dpy, None, None, NULL);
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
|
||||||
|
glXDestroyContext (dpy, context_x11->glx_context);
|
||||||
|
context_x11->glx_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context_x11->dummy_glx_drawable)
|
||||||
|
{
|
||||||
|
GDK_NOTE (OPENGL, g_print ("Destroying dummy GLX drawable\n"));
|
||||||
|
glXDestroyWindow (dpy, context_x11->dummy_glx_drawable);
|
||||||
|
context_x11->dummy_glx_drawable = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context_x11->dummy_drawable)
|
||||||
|
{
|
||||||
|
GDK_NOTE (OPENGL, g_print ("Destroying dummy drawable\n"));
|
||||||
|
XDestroyWindow (dpy, context_x11->dummy_drawable);
|
||||||
|
context_x11->dummy_drawable = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdk_x11_display_make_gl_context_current (GdkDisplay *display,
|
||||||
|
GdkGLContext *context,
|
||||||
|
GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||||
|
GLXDrawable drawable = None;
|
||||||
|
|
||||||
|
if (context_x11->glx_context == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (window == NULL)
|
||||||
|
{
|
||||||
|
/* we re-bind our dummy drawable, so that the context
|
||||||
|
* can still be used for queries
|
||||||
|
*/
|
||||||
|
drawable = context_x11->dummy_glx_drawable != None
|
||||||
|
? context_x11->dummy_glx_drawable
|
||||||
|
: context_x11->dummy_drawable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawableInfo *info = get_glx_drawable_info (window);
|
||||||
|
|
||||||
|
if (info != NULL && info->drawable != None)
|
||||||
|
drawable = info->drawable;
|
||||||
|
else
|
||||||
|
drawable = gdk_x11_window_get_xid (window);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (drawable == None))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (drawable == context_x11->current_drawable)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL,
|
||||||
|
g_print ("Making GLX context current to drawable %lu (dummy: %s)\n",
|
||||||
|
(unsigned long) drawable,
|
||||||
|
drawable == context_x11->dummy_drawable ? "yes" : "no"));
|
||||||
|
|
||||||
|
gdk_x11_display_error_trap_push (display);
|
||||||
|
|
||||||
|
glXMakeContextCurrent (gdk_x11_display_get_xdisplay (display),
|
||||||
|
drawable, drawable,
|
||||||
|
context_x11->glx_context);
|
||||||
|
|
||||||
|
if (GDK_X11_DISPLAY (display)->has_glx_swap_interval)
|
||||||
|
{
|
||||||
|
if (gdk_gl_context_get_swap_interval (context))
|
||||||
|
glXSwapIntervalSGI (1);
|
||||||
|
else
|
||||||
|
glXSwapIntervalSGI (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSync (gdk_x11_display_get_xdisplay (display), False);
|
||||||
|
|
||||||
|
if (gdk_x11_display_error_trap_pop (display))
|
||||||
|
{
|
||||||
|
g_critical ("X Error received while calling glXMakeContextCurrent()");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
context_x11->current_drawable = drawable;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdk_x11_display_validate_gl_pixel_format (GdkDisplay *display,
|
||||||
|
GdkGLPixelFormat *format,
|
||||||
|
GdkGLPixelFormat **validated_format,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GLXFBConfig config;
|
||||||
|
|
||||||
|
if (!gdk_x11_display_init_gl (display))
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE,
|
||||||
|
_("No GL implementation is available"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->profile == GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE)
|
||||||
|
{
|
||||||
|
if (!GDK_X11_DISPLAY (display)->has_glx_create_context)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR,
|
||||||
|
GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE,
|
||||||
|
_("The GLX_ARB_create_context_profile extension "
|
||||||
|
"needed to create 3.2 core profiles is not "
|
||||||
|
"available"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!find_fbconfig_for_pixel_format (display, format, &config, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
GDK_NOTE (OPENGL,
|
||||||
|
g_print ("Found GLX config for requested pixel format:\n"
|
||||||
|
" - double-buffer: %s\n"
|
||||||
|
" - multi-sample: %s\n"
|
||||||
|
" - stereo: %s\n"
|
||||||
|
" - color-size: %d, alpha-size: %d\n"
|
||||||
|
" - depth-size: %d\n"
|
||||||
|
" - stencil-size: %d\n"
|
||||||
|
" - aux-buffers: %d\n"
|
||||||
|
" - accum-size: %d\n"
|
||||||
|
" - sample-buffers: %d, samples: %d\n",
|
||||||
|
format->double_buffer ? "yes" : "no",
|
||||||
|
format->multi_sample ? "yes" : "no",
|
||||||
|
format->stereo ? "yes" : "no",
|
||||||
|
format->color_size, format->alpha_size,
|
||||||
|
format->depth_size,
|
||||||
|
format->stencil_size,
|
||||||
|
format->aux_buffers,
|
||||||
|
format->accum_size,
|
||||||
|
format->sample_buffers, format->samples));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_x11_display_get_glx_version:
|
||||||
|
* @display: a #GdkDisplay
|
||||||
|
* @major: (out): return location for the GLX major version
|
||||||
|
* @minor: (out): return location for the GLX minor version
|
||||||
|
*
|
||||||
|
* Retrieves the version of the GLX implementation.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if GLX is available
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdk_x11_display_get_glx_version (GdkDisplay *display,
|
||||||
|
int *major,
|
||||||
|
int *minor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||||
|
|
||||||
|
if (!GDK_IS_X11_DISPLAY (display))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!gdk_x11_display_init_gl (display))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (major != NULL)
|
||||||
|
*major = GDK_X11_DISPLAY (display)->glx_version / 10;
|
||||||
|
if (minor != NULL)
|
||||||
|
*minor = GDK_X11_DISPLAY (display)->glx_version % 10;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
78
gdk/x11/gdkglcontext-x11.h
Normal file
78
gdk/x11/gdkglcontext-x11.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglcontext-x11.h: Private X11 specific OpenGL wrappers
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_X11_GL_CONTEXT__
|
||||||
|
#define __GDK_X11_GL_CONTEXT__
|
||||||
|
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#include <epoxy/gl.h>
|
||||||
|
#include <epoxy/glx.h>
|
||||||
|
|
||||||
|
#include "gdkglcontextprivate.h"
|
||||||
|
#include "gdkglpixelformatprivate.h"
|
||||||
|
#include "gdkdisplayprivate.h"
|
||||||
|
#include "gdkglpixelformat.h"
|
||||||
|
#include "gdkvisual.h"
|
||||||
|
#include "gdkwindow.h"
|
||||||
|
#include "gdkinternals.h"
|
||||||
|
#include "gdkmain.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
struct _GdkX11GLContext
|
||||||
|
{
|
||||||
|
GdkGLContext parent_instance;
|
||||||
|
|
||||||
|
GLXContext glx_context;
|
||||||
|
GLXFBConfig glx_config;
|
||||||
|
|
||||||
|
GLXDrawable current_drawable;
|
||||||
|
|
||||||
|
Window dummy_drawable;
|
||||||
|
GLXWindow dummy_glx_drawable;
|
||||||
|
|
||||||
|
guint is_direct : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GdkX11GLContextClass
|
||||||
|
{
|
||||||
|
GdkGLContextClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
GdkGLContext *share,
|
||||||
|
GError **error);
|
||||||
|
void gdk_x11_display_destroy_gl_context (GdkDisplay *display,
|
||||||
|
GdkGLContext *context);
|
||||||
|
gboolean gdk_x11_display_make_gl_context_current (GdkDisplay *display,
|
||||||
|
GdkGLContext *context,
|
||||||
|
GdkWindow *window);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_X11_GL_CONTEXT__ */
|
@@ -43,6 +43,7 @@
|
|||||||
#include <gdk/x11/gdkx11display.h>
|
#include <gdk/x11/gdkx11display.h>
|
||||||
#include <gdk/x11/gdkx11displaymanager.h>
|
#include <gdk/x11/gdkx11displaymanager.h>
|
||||||
#include <gdk/x11/gdkx11dnd.h>
|
#include <gdk/x11/gdkx11dnd.h>
|
||||||
|
#include <gdk/x11/gdkx11glcontext.h>
|
||||||
#include <gdk/x11/gdkx11keys.h>
|
#include <gdk/x11/gdkx11keys.h>
|
||||||
#include <gdk/x11/gdkx11property.h>
|
#include <gdk/x11/gdkx11property.h>
|
||||||
#include <gdk/x11/gdkx11screen.h>
|
#include <gdk/x11/gdkx11screen.h>
|
||||||
|
49
gdk/x11/gdkx11glcontext.h
Normal file
49
gdk/x11/gdkx11glcontext.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
*
|
||||||
|
* gdkglcontext-x11.c: X11 specific OpenGL wrappers
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_X11_GL_CONTEXT_H__
|
||||||
|
#define __GDK_X11_GL_CONTEXT_H__
|
||||||
|
|
||||||
|
#if !defined (__GDKX_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||||
|
#error "Only <gdk/gdkx.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_X11_TYPE_GL_CONTEXT (gdk_x11_gl_context_get_type ())
|
||||||
|
#define GDK_X11_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_X11_TYPE_GL_CONTEXT, GdkX11GLContext))
|
||||||
|
#define GDK_X11_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_X11_TYPE_GL_CONTEXT))
|
||||||
|
|
||||||
|
typedef struct _GdkX11GLContext GdkX11GLContext;
|
||||||
|
typedef struct _GdkX11GLContextClass GdkX11GLContextClass;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GType gdk_x11_gl_context_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gboolean gdk_x11_display_get_glx_version (GdkDisplay *display,
|
||||||
|
int *major,
|
||||||
|
int *minor);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_X11_GL_CONTEXT_H__ */
|
@@ -365,6 +365,7 @@ gtk_public_h_sources = \
|
|||||||
gtkgesturesingle.h \
|
gtkgesturesingle.h \
|
||||||
gtkgestureswipe.h \
|
gtkgestureswipe.h \
|
||||||
gtkgesturezoom.h \
|
gtkgesturezoom.h \
|
||||||
|
gtkglarea.h \
|
||||||
gtkgrid.h \
|
gtkgrid.h \
|
||||||
gtkheaderbar.h \
|
gtkheaderbar.h \
|
||||||
gtkicontheme.h \
|
gtkicontheme.h \
|
||||||
@@ -937,6 +938,7 @@ gtk_base_c_sources = \
|
|||||||
gtkgesturesingle.c \
|
gtkgesturesingle.c \
|
||||||
gtkgestureswipe.c \
|
gtkgestureswipe.c \
|
||||||
gtkgesturezoom.c \
|
gtkgesturezoom.c \
|
||||||
|
gtkglarea.c \
|
||||||
gtkgrid.c \
|
gtkgrid.c \
|
||||||
gtkheaderbar.c \
|
gtkheaderbar.c \
|
||||||
gtkhsla.c \
|
gtkhsla.c \
|
||||||
|
@@ -114,6 +114,7 @@
|
|||||||
#include <gtk/gtkgesturesingle.h>
|
#include <gtk/gtkgesturesingle.h>
|
||||||
#include <gtk/gtkgestureswipe.h>
|
#include <gtk/gtkgestureswipe.h>
|
||||||
#include <gtk/gtkgesturezoom.h>
|
#include <gtk/gtkgesturezoom.h>
|
||||||
|
#include <gtk/gtkglarea.h>
|
||||||
#include <gtk/gtkgrid.h>
|
#include <gtk/gtkgrid.h>
|
||||||
#include <gtk/gtkheaderbar.h>
|
#include <gtk/gtkheaderbar.h>
|
||||||
#include <gtk/gtkicontheme.h>
|
#include <gtk/gtkicontheme.h>
|
||||||
|
667
gtk/gtkglarea.c
Normal file
667
gtk/gtkglarea.c
Normal file
@@ -0,0 +1,667 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
*
|
||||||
|
* gtkglarea.c: A GL drawing area
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "gtkglarea.h"
|
||||||
|
#include "gtkintl.h"
|
||||||
|
#include "gtkstylecontext.h"
|
||||||
|
#include "gtkmarshalers.h"
|
||||||
|
#include "gtkprivate.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:gtkglarea
|
||||||
|
* @Title: GtkGLArea
|
||||||
|
* @Short_description: A widget for custom drawing with OpenGL
|
||||||
|
*
|
||||||
|
* #GtkGLArea is a widget that allows drawing with OpenGL.
|
||||||
|
*
|
||||||
|
* #GtkGLArea can set up its own #GdkGLContext using a provided
|
||||||
|
* #GdkGLPixelFormat, or can use a given #GdkGLContext.
|
||||||
|
*
|
||||||
|
* In order to draw, you have to connect to the #GtkGLArea::render signal,
|
||||||
|
* or subclass #GtkGLArea and override the @GtkGLAreaClass.render() virtual
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* The #GtkGLArea widget ensures that the #GdkGLContext is associated with
|
||||||
|
* the widget's drawing area, and it is kept updated when the size and
|
||||||
|
* position of the drawing area changes.
|
||||||
|
*
|
||||||
|
* ## Drawing with GtkGLArea ##
|
||||||
|
*
|
||||||
|
* The simplest way to draw using OpenGL commands in a #GtkGLArea is to
|
||||||
|
* create a widget instance and connect to the #GtkGLArea::render signal:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* // create a double buffered pixel format
|
||||||
|
* GdkGLPixelFormat *format =
|
||||||
|
* gdk_gl_pixel_format_new ("double-buffer", TRUE);
|
||||||
|
*
|
||||||
|
* // create a GtkGLArea instance
|
||||||
|
* GtkWidget *gl_area = gtk_gl_area_new (format);
|
||||||
|
*
|
||||||
|
* // the GtkGLArea now owns the GdkGLPixelFormat
|
||||||
|
* g_object_unref (format);
|
||||||
|
*
|
||||||
|
* // connect to the "render" signal
|
||||||
|
* g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* The `render()` function will be called when the #GtkGLArea is ready
|
||||||
|
* for you to draw its content:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* static gboolean
|
||||||
|
* render (GtkGLArea *area, GdkGLContext *context)
|
||||||
|
* {
|
||||||
|
* // inside this function it's safe to use GL; the given
|
||||||
|
* // #GdkGLContext has been made current to the drawable
|
||||||
|
* // surface used by the #GtkGLArea and the viewport has
|
||||||
|
* // already been set to be the size of the allocation
|
||||||
|
*
|
||||||
|
* // we can start by clearing the buffer
|
||||||
|
* glClearColor (0, 0, 0, 0);
|
||||||
|
* glClear (GL_COLOR_BUFFER_BIT);
|
||||||
|
*
|
||||||
|
* // draw your object
|
||||||
|
* draw_an_object ();
|
||||||
|
*
|
||||||
|
* // we completed our drawing; the draw commands will be
|
||||||
|
* // flushed at the end of the signal emission chain, and
|
||||||
|
* // the buffers swapped if needed
|
||||||
|
* return TRUE;
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* The `draw_an_object()` function draws a 2D, gold-colored
|
||||||
|
* triangle:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* static void
|
||||||
|
* draw_an_object (void)
|
||||||
|
* {
|
||||||
|
* // set the color
|
||||||
|
* glColor3f (1.0f, 0.85f, 0.35f);
|
||||||
|
*
|
||||||
|
* // draw our triangle
|
||||||
|
* glBegin (GL_TRIANGLES);
|
||||||
|
* {
|
||||||
|
* glVertex3f ( 0.0f, 0.6f, 0.0f);
|
||||||
|
* glVertex3f (-0.2f, -0.3f, 0.0f);
|
||||||
|
* glVertex3f ( 0.2f, -0.3f, 0.0f);
|
||||||
|
* }
|
||||||
|
* glEnd ();
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* This is an extremely simple example; in a real-world application you
|
||||||
|
* would probably replace the immediate mode drawing with persistent
|
||||||
|
* geometry primitives, like a Vertex Buffer Object, and only redraw what
|
||||||
|
* changed in your scene.
|
||||||
|
*
|
||||||
|
* ## Using different OpenGL contexts with GtkGLArea ##
|
||||||
|
*
|
||||||
|
* The #GtkGLArea widget will create a #GdkGLContext for the given
|
||||||
|
* pixel format passed on creation. It is possible, however, to change
|
||||||
|
* this default behavior by connecting to the #GtkGLArea::create-context
|
||||||
|
* signal, or by overriding the #GtkGLAreaClass.create_context() virtual
|
||||||
|
* function on a #GtkGLArea subclass.
|
||||||
|
*
|
||||||
|
* If you need to let a #GtkGLArea create a #GdkGLContext with shared
|
||||||
|
* data with another context you can use the #GtkGLArea::create-context
|
||||||
|
* to override the creation of the widget-specific OpenGL context:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* static GdkGLContext *
|
||||||
|
* create_shared_context (GtkGLArea *area,
|
||||||
|
* GdkGLPixelFormat *format,
|
||||||
|
* GdkGLContext *shared_context)
|
||||||
|
* {
|
||||||
|
* GdkDisplay *display;
|
||||||
|
*
|
||||||
|
* display = gtk_widget_get_display (GTK_WIDGET (area));
|
||||||
|
* if (display == NULL)
|
||||||
|
* display = gdk_display_get_default ();
|
||||||
|
*
|
||||||
|
* // create a GdkGLContext that has shared texture namespace
|
||||||
|
* // and display lists with a given context
|
||||||
|
* return gdk_display_create_shared_gl_context (display, format,
|
||||||
|
* shared_context,
|
||||||
|
* NULL);
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* The #GtkGLArea will take ownership of the #GdkGLContext returned
|
||||||
|
* by the #GtkGLArea::create-context signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdkGLPixelFormat *pixel_format;
|
||||||
|
GdkGLContext *context;
|
||||||
|
} GtkGLAreaPrivate;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_PIXEL_FORMAT,
|
||||||
|
PROP_CONTEXT,
|
||||||
|
|
||||||
|
LAST_PROP
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *obj_props[LAST_PROP] = { NULL, };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RENDER,
|
||||||
|
CREATE_CONTEXT,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint area_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (GtkGLArea, gtk_gl_area, GTK_TYPE_WIDGET)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
GtkGLArea *self = GTK_GL_AREA (gobject);
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (self);
|
||||||
|
|
||||||
|
g_clear_object (&priv->pixel_format);
|
||||||
|
g_clear_object (&priv->context);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gtk_gl_area_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkGLArea *self = GTK_GL_AREA (gobject);
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (self);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_PIXEL_FORMAT:
|
||||||
|
priv->pixel_format = g_value_dup_object (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (GTK_GL_AREA (gobject));
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_PIXEL_FORMAT:
|
||||||
|
g_value_set_object (value, priv->pixel_format);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_CONTEXT:
|
||||||
|
g_value_set_object (value, priv->context);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkGLContext *
|
||||||
|
gtk_gl_area_create_context (GtkGLArea *area)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (area);
|
||||||
|
GdkGLContext *context;
|
||||||
|
|
||||||
|
if (priv->context != NULL)
|
||||||
|
return priv->context;
|
||||||
|
|
||||||
|
context = NULL;
|
||||||
|
g_signal_emit (area, area_signals[CREATE_CONTEXT], 0,
|
||||||
|
priv->pixel_format,
|
||||||
|
&context);
|
||||||
|
|
||||||
|
if (context == NULL)
|
||||||
|
{
|
||||||
|
g_critical ("No GL context was created for the widget");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_set_visual (GTK_WIDGET (area), gdk_gl_context_get_visual (context));
|
||||||
|
|
||||||
|
priv->context = context;
|
||||||
|
|
||||||
|
return priv->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GdkGLContext *context;
|
||||||
|
GtkAllocation allocation;
|
||||||
|
GdkWindow *window;
|
||||||
|
GdkWindowAttr attributes;
|
||||||
|
gint attributes_mask;
|
||||||
|
|
||||||
|
context = gtk_gl_area_create_context (GTK_GL_AREA (widget));
|
||||||
|
|
||||||
|
gtk_widget_set_realized (widget, TRUE);
|
||||||
|
gtk_widget_get_allocation (widget, &allocation);
|
||||||
|
|
||||||
|
attributes.window_type = GDK_WINDOW_CHILD;
|
||||||
|
attributes.x = allocation.x;
|
||||||
|
attributes.y = allocation.y;
|
||||||
|
attributes.width = allocation.width;
|
||||||
|
attributes.height = allocation.height;
|
||||||
|
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||||
|
attributes.visual = gtk_widget_get_visual (widget);
|
||||||
|
attributes.event_mask = gtk_widget_get_events (widget) |
|
||||||
|
GDK_EXPOSURE_MASK |
|
||||||
|
GDK_STRUCTURE_MASK;
|
||||||
|
|
||||||
|
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
|
||||||
|
|
||||||
|
window = gdk_window_new (gtk_widget_get_parent_window (widget),
|
||||||
|
&attributes,
|
||||||
|
attributes_mask);
|
||||||
|
gtk_widget_register_window (widget, window);
|
||||||
|
gtk_widget_set_window (widget, window);
|
||||||
|
|
||||||
|
if (context != NULL)
|
||||||
|
{
|
||||||
|
gdk_gl_context_set_window (context, window);
|
||||||
|
gdk_gl_context_update (context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_unrealize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private ((GtkGLArea *) widget);
|
||||||
|
|
||||||
|
if (priv->context != NULL)
|
||||||
|
gdk_gl_context_set_window (priv->context, NULL);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_gl_area_parent_class)->unrealize (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private ((GtkGLArea *) widget);
|
||||||
|
|
||||||
|
gtk_widget_set_allocation (widget, allocation);
|
||||||
|
|
||||||
|
if (!gtk_widget_get_realized (widget))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_window_move_resize (gtk_widget_get_window (widget),
|
||||||
|
allocation->x,
|
||||||
|
allocation->y,
|
||||||
|
allocation->width,
|
||||||
|
allocation->height);
|
||||||
|
|
||||||
|
if (priv->context != NULL)
|
||||||
|
gdk_gl_context_update (priv->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_gl_area_draw (GtkWidget *widget,
|
||||||
|
cairo_t *cr)
|
||||||
|
{
|
||||||
|
GtkGLArea *self = GTK_GL_AREA (widget);
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (self);
|
||||||
|
gboolean unused;
|
||||||
|
|
||||||
|
if (priv->context == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!gtk_gl_area_make_current (self))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_signal_emit (self, area_signals[RENDER], 0, priv->context, &unused);
|
||||||
|
|
||||||
|
/* XXX: this will go away once gdk_window_end_paint() knows about
|
||||||
|
* GdkGLContext and calls it implicitly when needed
|
||||||
|
*/
|
||||||
|
gtk_gl_area_flush_buffer (self);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_screen_changed (GtkWidget *widget,
|
||||||
|
GdkScreen *old_screen)
|
||||||
|
{
|
||||||
|
GtkGLArea *self = GTK_GL_AREA (widget);
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (self);
|
||||||
|
|
||||||
|
/* this will cause the context to be recreated on realize */
|
||||||
|
g_clear_object (&priv->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkGLContext *
|
||||||
|
gtk_gl_area_real_create_context (GtkGLArea *area,
|
||||||
|
GdkGLPixelFormat *format)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (area));
|
||||||
|
GdkGLContext *retval;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (display == NULL)
|
||||||
|
display = gdk_display_get_default ();
|
||||||
|
|
||||||
|
retval = gdk_display_create_gl_context (display, format, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to create a GdkGLContext: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
create_context_accumulator (GSignalInvocationHint *ihint,
|
||||||
|
GValue *return_accu,
|
||||||
|
const GValue *handler_return,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
g_value_copy (handler_return, return_accu);
|
||||||
|
|
||||||
|
/* stop after the first handler returning a valid object */
|
||||||
|
return g_value_get_object (handler_return) == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_class_init (GtkGLAreaClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
|
klass->create_context = gtk_gl_area_real_create_context;
|
||||||
|
|
||||||
|
widget_class->screen_changed = gtk_gl_area_screen_changed;
|
||||||
|
widget_class->realize = gtk_gl_area_realize;
|
||||||
|
widget_class->unrealize = gtk_gl_area_unrealize;
|
||||||
|
widget_class->size_allocate = gtk_gl_area_size_allocate;
|
||||||
|
widget_class->draw = gtk_gl_area_draw;
|
||||||
|
|
||||||
|
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_DRAWING_AREA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkGLArea:pixel-format:
|
||||||
|
*
|
||||||
|
* 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] =
|
||||||
|
g_param_spec_object ("pixel-format",
|
||||||
|
P_("Pixel Format"),
|
||||||
|
P_("The GDK pixel format for creating the GL context"),
|
||||||
|
GDK_TYPE_GL_PIXEL_FORMAT,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkGLArea:context:
|
||||||
|
*
|
||||||
|
* The #GdkGLContext used by the #GtkGLArea widget.
|
||||||
|
*
|
||||||
|
* The #GtkGLArea widget is responsible for creating the #GdkGLContext
|
||||||
|
* instance. See the #GtkGLArea::create-context signal on how to
|
||||||
|
* override the default behavior.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
obj_props[PROP_CONTEXT] =
|
||||||
|
g_param_spec_object ("context",
|
||||||
|
P_("Context"),
|
||||||
|
P_("The GL context"),
|
||||||
|
GDK_TYPE_GL_CONTEXT,
|
||||||
|
G_PARAM_READABLE |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
gobject_class->set_property = gtk_gl_area_set_property;
|
||||||
|
gobject_class->get_property = gtk_gl_area_get_property;
|
||||||
|
gobject_class->dispose = gtk_gl_area_dispose;
|
||||||
|
|
||||||
|
g_object_class_install_properties (gobject_class, LAST_PROP, obj_props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkGLArea::create-context:
|
||||||
|
* @area: the #GtkGLArea that emitted the signal
|
||||||
|
* @format: the #GdkGLPixelFormat for the OpenGL context
|
||||||
|
*
|
||||||
|
* The ::create-context signal is emitted each time a #GtkGLArea needs
|
||||||
|
* to create a #GdkGLContext for the given pixel format.
|
||||||
|
*
|
||||||
|
* Widgets can change #GdkDisplay, #GdkScreen, or #GdkVisual; this
|
||||||
|
* implies that a valid pixel format for a specific #GdkDisplay may
|
||||||
|
* not be valid any more after a change in those objects.
|
||||||
|
*
|
||||||
|
* The #GtkGLArea widget will presently emit the ::create-context
|
||||||
|
* signal when:
|
||||||
|
*
|
||||||
|
* - the #GtkWidget::screen-changed signal is emitted
|
||||||
|
* - the #GtkWidget::realize signal is emitted
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a newly created #GdkGLContext; the
|
||||||
|
* #GtkGLArea widget will take ownership of the returned value.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
area_signals[CREATE_CONTEXT] =
|
||||||
|
g_signal_new (I_("create-context"),
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GtkGLAreaClass, create_context),
|
||||||
|
create_context_accumulator, NULL,
|
||||||
|
_gtk_marshal_OBJECT__OBJECT,
|
||||||
|
GDK_TYPE_GL_CONTEXT, 1,
|
||||||
|
GDK_TYPE_GL_PIXEL_FORMAT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkGLArea::render:
|
||||||
|
* @area: the #GtkGLArea that emitted the signal
|
||||||
|
* @context: the #GdkGLContext used by @area
|
||||||
|
*
|
||||||
|
* The ::render signal is emitted every time the contents
|
||||||
|
* of the #GtkGLArea should be redrawn.
|
||||||
|
*
|
||||||
|
* The @context is bound to the @area prior to emitting this function,
|
||||||
|
* and the buffers are flushed once the emission terminates.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE to stop other handlers from being invoked for the event.
|
||||||
|
* %FALSE to propagate the event further.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
area_signals[RENDER] =
|
||||||
|
g_signal_new (I_("render"),
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GtkGLAreaClass, render),
|
||||||
|
_gtk_boolean_handled_accumulator, NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_BOOLEAN, 1,
|
||||||
|
GDK_TYPE_GL_CONTEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_gl_area_init (GtkGLArea *self)
|
||||||
|
{
|
||||||
|
gtk_widget_set_has_window (GTK_WIDGET (self), TRUE);
|
||||||
|
gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE);
|
||||||
|
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||||
|
/* FIXME: we need this because double buffering inside GDK will
|
||||||
|
* clear the GL drawable we use, which means flickering. the
|
||||||
|
* proper way to fix this is to make GDK understand that a GDK
|
||||||
|
* window backed by a native window with a GL context will draw
|
||||||
|
* on the window itself, and that all the other drawing should
|
||||||
|
* happen on a seperate surface, which will then get blended via
|
||||||
|
* GL.
|
||||||
|
*/
|
||||||
|
gtk_widget_set_double_buffered (GTK_WIDGET (self), FALSE);
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_gl_area_new:
|
||||||
|
* @pixel_format: a #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Creates a new #GtkGLArea widget using the given @pixel_format to
|
||||||
|
* configure a #GdkGLContext.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the newly created #GtkGLArea
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GtkWidget *
|
||||||
|
gtk_gl_area_new (GdkGLPixelFormat *pixel_format)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (pixel_format), NULL);
|
||||||
|
|
||||||
|
return g_object_new (GTK_TYPE_GL_AREA,
|
||||||
|
"pixel-format", pixel_format,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_gl_area_get_pixel_format:
|
||||||
|
* @area: a #GtkGLArea
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkGLPixelFormat used by @area.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #GdkGLPixelFormat
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkGLPixelFormat *
|
||||||
|
gtk_gl_area_get_pixel_format (GtkGLArea *area)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (area);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_GL_AREA (area), NULL);
|
||||||
|
|
||||||
|
return priv->pixel_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_gl_area_get_context:
|
||||||
|
* @area: a #GtkGLArea
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkGLContext used by @area.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #GdkGLContext
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
GdkGLContext *
|
||||||
|
gtk_gl_area_get_context (GtkGLArea *area)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (area);
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_GL_AREA (area), NULL);
|
||||||
|
|
||||||
|
return priv->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_gl_area_make_current:
|
||||||
|
* @area: a #GtkGLArea
|
||||||
|
*
|
||||||
|
* Ensures that the #GdkGLContext used by @area is associated with
|
||||||
|
* the #GtkGLArea.
|
||||||
|
*
|
||||||
|
* This function is automatically called before emitting the
|
||||||
|
* #GtkGLArea::render signal, and should not be called by
|
||||||
|
* application code.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the context was associated successfully with
|
||||||
|
* the widget
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gtk_gl_area_make_current (GtkGLArea *area)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (area);
|
||||||
|
GtkWidget *widget;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_GL_AREA (area), FALSE);
|
||||||
|
|
||||||
|
widget = GTK_WIDGET (area);
|
||||||
|
g_return_val_if_fail (gtk_widget_get_realized (widget), FALSE);
|
||||||
|
|
||||||
|
if (priv->context == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
gdk_gl_context_set_window (priv->context, gtk_widget_get_window (widget));
|
||||||
|
|
||||||
|
return gdk_gl_context_make_current (priv->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_gl_area_flush_buffer:
|
||||||
|
* @area: a #GtkGLArea
|
||||||
|
*
|
||||||
|
* Flushes the buffer associated with @area.
|
||||||
|
*
|
||||||
|
* This function is automatically called after emitting
|
||||||
|
* the #GtkGLArea::render signal, and should not be called
|
||||||
|
* by application code.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_gl_area_flush_buffer (GtkGLArea *area)
|
||||||
|
{
|
||||||
|
GtkGLAreaPrivate *priv = gtk_gl_area_get_instance_private (area);
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_GL_AREA (area));
|
||||||
|
g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (area)));
|
||||||
|
|
||||||
|
if (priv->context == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_gl_context_flush_buffer (priv->context);
|
||||||
|
}
|
96
gtk/gtkglarea.h
Normal file
96
gtk/gtkglarea.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
*
|
||||||
|
* gtkglarea.h: A GL drawing area
|
||||||
|
*
|
||||||
|
* Copyright © 2014 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_GL_AREA_H__
|
||||||
|
#define __GTK_GL_AREA_H__
|
||||||
|
|
||||||
|
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||||
|
#error "Only <gtk/gtk.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gtk/gtkwidget.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GTK_TYPE_GL_AREA (gtk_gl_area_get_type ())
|
||||||
|
#define GTK_GL_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GL_AREA, GtkGLArea))
|
||||||
|
#define GTK_IS_GL_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GL_AREA))
|
||||||
|
#define GTK_GL_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GL_AREA, GtkGLAreaClass))
|
||||||
|
#define GTK_IS_GL_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GL_AREA))
|
||||||
|
#define GTK_GL_AREA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GL_AREA, GtkGLAreaClass))
|
||||||
|
|
||||||
|
typedef struct _GtkGLArea GtkGLArea;
|
||||||
|
typedef struct _GtkGLAreaClass GtkGLAreaClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkGLArea:
|
||||||
|
*
|
||||||
|
* A #GtkWidget used for drawing with OpenGL.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
struct _GtkGLArea
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GtkWidget parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkGLAreaClass:
|
||||||
|
* @create_context: class closure for the #GtkGLArea::create-context signal
|
||||||
|
* @render: class closure for the #GtkGLArea::render signal
|
||||||
|
*
|
||||||
|
* The `GtkGLAreaClass` structure contains only private data.
|
||||||
|
*
|
||||||
|
* Since: 3.14
|
||||||
|
*/
|
||||||
|
struct _GtkGLAreaClass
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GtkWidgetClass parent_class;
|
||||||
|
|
||||||
|
/*< public >*/
|
||||||
|
GdkGLContext * (* create_context) (GtkGLArea *area,
|
||||||
|
GdkGLPixelFormat *format);
|
||||||
|
|
||||||
|
gboolean (* render) (GtkGLArea *area,
|
||||||
|
GdkGLContext *context);
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
gpointer _padding[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GType gtk_gl_area_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GtkWidget * gtk_gl_area_new (GdkGLPixelFormat *format);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
GdkGLContext * gtk_gl_area_get_context (GtkGLArea *area);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
gboolean gtk_gl_area_make_current (GtkGLArea *area);
|
||||||
|
GDK_AVAILABLE_IN_3_14
|
||||||
|
void gtk_gl_area_flush_buffer (GtkGLArea *area);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_GL_AREA_H__ */
|
@@ -124,6 +124,7 @@ VOID:UINT,STRING,UINT
|
|||||||
VOID:UINT,UINT
|
VOID:UINT,UINT
|
||||||
VOID:VOID
|
VOID:VOID
|
||||||
OBJECT:OBJECT,INT,INT
|
OBJECT:OBJECT,INT,INT
|
||||||
|
OBJECT:OBJECT
|
||||||
VOID:POINTER,POINTER,POINTER,POINTER,STRING
|
VOID:POINTER,POINTER,POINTER,POINTER,STRING
|
||||||
VOID:OBJECT,STRING,POINTER,POINTER
|
VOID:OBJECT,STRING,POINTER,POINTER
|
||||||
INT:INT
|
INT:INT
|
||||||
|
@@ -66,6 +66,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
|||||||
testfullscreen \
|
testfullscreen \
|
||||||
testgeometry \
|
testgeometry \
|
||||||
testgiconpixbuf \
|
testgiconpixbuf \
|
||||||
|
testglarea \
|
||||||
testgrid \
|
testgrid \
|
||||||
testgtk \
|
testgtk \
|
||||||
testheaderbar \
|
testheaderbar \
|
||||||
|
193
tests/testglarea.c
Normal file
193
tests/testglarea.c
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <epoxy/gl.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
X_AXIS,
|
||||||
|
Y_AXIS,
|
||||||
|
Z_AXIS,
|
||||||
|
|
||||||
|
N_AXIS
|
||||||
|
};
|
||||||
|
|
||||||
|
static float rotation_angles[N_AXIS] = { 0.0 };
|
||||||
|
|
||||||
|
static GtkWidget *gl_area;
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_triangle (void)
|
||||||
|
{
|
||||||
|
glColor3f (1.0f, 0.85f, 0.35f);
|
||||||
|
glBegin (GL_TRIANGLES);
|
||||||
|
{
|
||||||
|
glVertex3f ( 0.0, 0.6, 0.0);
|
||||||
|
glVertex3f (-0.2, -0.3, 0.0);
|
||||||
|
glVertex3f ( 0.2, -0.3, 0.0);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
render (GtkGLArea *area,
|
||||||
|
GdkGLContext *context)
|
||||||
|
{
|
||||||
|
glClearColor (0.5, 0.5, 0.5, 1.0);
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glRotatef (rotation_angles[X_AXIS], 1, 0, 0);
|
||||||
|
glRotatef (rotation_angles[Y_AXIS], 0, 1, 0);
|
||||||
|
glRotatef (rotation_angles[Z_AXIS], 0, 0, 1);
|
||||||
|
|
||||||
|
draw_triangle ();
|
||||||
|
|
||||||
|
glFlush ();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GdkGLContext *context = gtk_gl_area_get_context (GTK_GL_AREA (widget));
|
||||||
|
GdkGLPixelFormat *format = gdk_gl_context_get_pixel_format (context);
|
||||||
|
|
||||||
|
g_print ("GL Pixel format:\n"
|
||||||
|
" - double-buffer: %s\n"
|
||||||
|
" - multi-sample: %s\n"
|
||||||
|
" - stereo: %s\n"
|
||||||
|
" - color-size: %d, alpha-size: %d\n"
|
||||||
|
" - depth-size: %d\n"
|
||||||
|
" - stencil-size: %d\n"
|
||||||
|
" - aux-buffers: %d\n"
|
||||||
|
" - accum-size: %d\n"
|
||||||
|
" - sample-buffers: %d\n"
|
||||||
|
" - samples: %d\n\n",
|
||||||
|
gdk_gl_pixel_format_get_double_buffer (format) ? "yes" : "no",
|
||||||
|
gdk_gl_pixel_format_get_multi_sample (format) ? "yes" : "no",
|
||||||
|
gdk_gl_pixel_format_get_stereo (format) ? "yes" : "no",
|
||||||
|
gdk_gl_pixel_format_get_color_size (format),
|
||||||
|
gdk_gl_pixel_format_get_alpha_size (format),
|
||||||
|
gdk_gl_pixel_format_get_depth_size (format),
|
||||||
|
gdk_gl_pixel_format_get_stencil_size (format),
|
||||||
|
gdk_gl_pixel_format_get_aux_buffers (format),
|
||||||
|
gdk_gl_pixel_format_get_accum_size (format),
|
||||||
|
gdk_gl_pixel_format_get_sample_buffers (format),
|
||||||
|
gdk_gl_pixel_format_get_samples (format));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_axis_value_change (GtkAdjustment *adjustment,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
int axis = GPOINTER_TO_INT (data);
|
||||||
|
|
||||||
|
if (axis < 0 || axis >= N_AXIS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rotation_angles[axis] = gtk_adjustment_get_value (adjustment);
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (gl_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget *
|
||||||
|
create_axis_slider (int axis)
|
||||||
|
{
|
||||||
|
GtkWidget *box, *label, *slider;
|
||||||
|
GtkAdjustment *adj;
|
||||||
|
const char *text;
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
|
||||||
|
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case X_AXIS:
|
||||||
|
text = "X axis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Y_AXIS:
|
||||||
|
text = "Y axis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Z_AXIS:
|
||||||
|
text = "Z axis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
label = gtk_label_new (text);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), label);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
|
||||||
|
adj = gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 12.0, 0.0);
|
||||||
|
g_signal_connect (adj, "value-changed",
|
||||||
|
G_CALLBACK (on_axis_value_change),
|
||||||
|
GINT_TO_POINTER (axis));
|
||||||
|
slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adj);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), slider);
|
||||||
|
gtk_widget_set_hexpand (slider, TRUE);
|
||||||
|
gtk_widget_show (slider);
|
||||||
|
|
||||||
|
gtk_widget_show (box);
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GtkWidget *window, *box, *button, *controls;
|
||||||
|
GdkGLPixelFormat *pixel_format;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
|
/* create a new pixel format; we use this to configure the
|
||||||
|
* GL context, and to check for features
|
||||||
|
*/
|
||||||
|
pixel_format = gdk_gl_pixel_format_new ("double-buffer", TRUE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||||
|
gtk_window_set_title (GTK_WINDOW (window), "GtkGLArea - Golden Triangle");
|
||||||
|
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (window), 12);
|
||||||
|
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
|
||||||
|
gtk_widget_show (window);
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||||
|
gtk_box_set_spacing (GTK_BOX (box), 6);
|
||||||
|
gtk_container_add (GTK_CONTAINER (window), box);
|
||||||
|
gtk_widget_show (box);
|
||||||
|
|
||||||
|
gl_area = gtk_gl_area_new (pixel_format);
|
||||||
|
gtk_widget_set_hexpand (gl_area, TRUE);
|
||||||
|
gtk_widget_set_vexpand (gl_area, TRUE);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), gl_area);
|
||||||
|
g_signal_connect (gl_area, "realize", G_CALLBACK (init), NULL);
|
||||||
|
g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
|
||||||
|
gtk_widget_show (gl_area);
|
||||||
|
g_object_unref (pixel_format);
|
||||||
|
|
||||||
|
controls = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), controls);
|
||||||
|
gtk_widget_set_hexpand (controls, TRUE);
|
||||||
|
gtk_widget_show (controls);
|
||||||
|
|
||||||
|
for (i = 0; i < N_AXIS; i++)
|
||||||
|
gtk_container_add (GTK_CONTAINER (controls), create_axis_slider (i));
|
||||||
|
|
||||||
|
button = gtk_button_new_with_label ("Quit");
|
||||||
|
gtk_widget_set_hexpand (button, TRUE);
|
||||||
|
gtk_container_add (GTK_CONTAINER (box), button);
|
||||||
|
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
|
||||||
|
gtk_widget_show (button);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Reference in New Issue
Block a user