forked from AuroraMiddleware/gtk
wayland: Add OpenGL support
This uses EGL to implement GdkGLContext for wayland.
This commit is contained in:
parent
6717242d26
commit
7eae4985e8
@ -427,7 +427,7 @@ fi
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
WAYLAND_DEPENDENCIES="wayland-client >= wayland_required_version xkbcommon >= 0.2.0 wayland-cursor >= wayland_required_version"
|
||||
WAYLAND_DEPENDENCIES="wayland-client >= wayland_required_version xkbcommon >= 0.2.0 wayland-cursor >= wayland_required_version wayland-egl >= wayland_required_version"
|
||||
if test "$enable_wayland_backend" = "maybe" ; then
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
PKG_CHECK_EXISTS($WAYLAND_DEPENDENCIES, [have_wayland_deps=yes], [have_wayland_deps=no])
|
||||
|
@ -39,7 +39,9 @@ libgdk_wayland_la_SOURCES = \
|
||||
gdkdisplay-wayland.h \
|
||||
gdkdnd-wayland.c \
|
||||
gdkeventsource.c \
|
||||
gdkkeys-wayland.c \
|
||||
gdkkeys-wayland.c \
|
||||
gdkglcontext-wayland.c \
|
||||
gdkglcontext-wayland.h \
|
||||
gdkscreen-wayland.c \
|
||||
gdkselection-wayland.c \
|
||||
gdkwindow-wayland.c \
|
||||
@ -54,6 +56,7 @@ libgdkinclude_HEADERS = \
|
||||
libgdkwaylandinclude_HEADERS = \
|
||||
gdkwaylanddevice.h \
|
||||
gdkwaylanddisplay.h \
|
||||
gdkwaylandglcontext.h \
|
||||
gdkwaylandselection.h \
|
||||
gdkwaylandwindow.h
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "gdkdevicemanager.h"
|
||||
#include "gdkkeysprivate.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkglcontext-wayland.h"
|
||||
|
||||
/**
|
||||
* SECTION:wayland_interaction
|
||||
@ -540,6 +541,9 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
|
||||
display_class->convert_selection = _gdk_wayland_display_convert_selection;
|
||||
display_class->text_property_to_utf8_list = _gdk_wayland_display_text_property_to_utf8_list;
|
||||
display_class->utf8_to_string_target = _gdk_wayland_display_utf8_to_string_target;
|
||||
|
||||
display_class->destroy_gl_context = gdk_wayland_display_destroy_gl_context;
|
||||
display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <stdint.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-cursor.h>
|
||||
#include <wayland-egl.h>
|
||||
#include <gdk/wayland/gtk-shell-client-protocol.h>
|
||||
#include <gdk/wayland/xdg-shell-client-protocol.h>
|
||||
|
||||
@ -37,6 +38,8 @@
|
||||
|
||||
#include "gdkdisplayprivate.h"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkWaylandSelection GdkWaylandSelection;
|
||||
@ -76,6 +79,16 @@ struct _GdkWaylandDisplay
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
GdkWaylandSelection *selection;
|
||||
|
||||
/* egl info */
|
||||
EGLDisplay egl_display;
|
||||
int egl_major_version;
|
||||
int egl_minor_version;
|
||||
|
||||
guint have_egl : 1;
|
||||
guint have_egl_khr_create_context : 1;
|
||||
guint have_egl_buffer_age : 1;
|
||||
guint have_egl_swap_buffers_with_damage : 1;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDisplayClass
|
||||
|
414
gdk/wayland/gdkglcontext-wayland.c
Normal file
414
gdk/wayland/gdkglcontext-wayland.c
Normal file
@ -0,0 +1,414 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* gdkglcontext-wayland.c: Wayland specific OpenGL wrappers
|
||||
*
|
||||
* Copyright © 2014 Emmanuele Bassi
|
||||
* Copyright © 2014 Alexander Larsson
|
||||
*
|
||||
* 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-wayland.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
|
||||
#include "gdkwaylanddisplay.h"
|
||||
#include "gdkwaylandglcontext.h"
|
||||
#include "gdkwaylandwindow.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
|
||||
G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_update (GdkGLContext *context)
|
||||
{
|
||||
GdkWindow *window = gdk_gl_context_get_window (context);
|
||||
int width, height;
|
||||
|
||||
if (!gdk_gl_context_make_current (context))
|
||||
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 %p (context: %p)\n",
|
||||
width, height,
|
||||
window, context));
|
||||
|
||||
glViewport (0, 0, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_window_invalidate_for_new_frame (GdkWindow *window,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
cairo_rectangle_int_t window_rect;
|
||||
GdkDisplay *display = gdk_window_get_display (window);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context_wayland;
|
||||
int buffer_age;
|
||||
gboolean invalidate_all;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
/* Minimal update is ok if we're not drawing with gl */
|
||||
if (window->gl_paint_context == NULL)
|
||||
return;
|
||||
|
||||
context_wayland = GDK_WAYLAND_GL_CONTEXT (window->gl_paint_context);
|
||||
buffer_age = 0;
|
||||
|
||||
egl_surface = gdk_wayland_window_get_egl_surface (window->impl_window,
|
||||
context_wayland->egl_config);
|
||||
|
||||
if (display_wayland->have_egl_buffer_age)
|
||||
eglQuerySurface (display_wayland->egl_display, egl_surface,
|
||||
EGL_BUFFER_AGE_EXT, &buffer_age);
|
||||
|
||||
invalidate_all = FALSE;
|
||||
if (buffer_age == 0 || buffer_age >= 4)
|
||||
invalidate_all = TRUE;
|
||||
else
|
||||
{
|
||||
if (buffer_age >= 2)
|
||||
{
|
||||
if (window->old_updated_area[0])
|
||||
cairo_region_union (update_area, window->old_updated_area[0]);
|
||||
else
|
||||
invalidate_all = TRUE;
|
||||
}
|
||||
if (buffer_age >= 3)
|
||||
{
|
||||
if (window->old_updated_area[1])
|
||||
cairo_region_union (update_area, window->old_updated_area[1]);
|
||||
else
|
||||
invalidate_all = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidate_all)
|
||||
{
|
||||
window_rect.x = 0;
|
||||
window_rect.y = 0;
|
||||
window_rect.width = gdk_window_get_width (window);
|
||||
window_rect.height = gdk_window_get_height (window);
|
||||
|
||||
/* If nothing else is known, repaint everything so that the back
|
||||
buffer is fully up-to-date for the swapbuffer */
|
||||
cairo_region_union_rectangle (update_area, &window_rect);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_flush_buffer (GdkGLContext *context,
|
||||
cairo_region_t *painted,
|
||||
cairo_region_t *damage)
|
||||
{
|
||||
GdkWindow *window = gdk_gl_context_get_window (context);
|
||||
GdkDisplay *display = gdk_window_get_display (window);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
EGLSurface egl_surface;
|
||||
|
||||
if (!gdk_gl_context_make_current (context))
|
||||
return;
|
||||
|
||||
egl_surface = gdk_wayland_window_get_egl_surface (window->impl_window,
|
||||
context_wayland->egl_config);
|
||||
|
||||
// TODO: Use eglSwapBuffersWithDamageEXT if available
|
||||
if (display_wayland->have_egl_swap_buffers_with_damage)
|
||||
{
|
||||
int i, j, n_rects = cairo_region_num_rectangles (damage);
|
||||
EGLint *rects = g_new (EGLint, n_rects * 4);
|
||||
cairo_rectangle_int_t rect;
|
||||
int window_height = gdk_window_get_height (window);
|
||||
|
||||
for (i = 0, j = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_region_get_rectangle (damage, i, &rect);
|
||||
rects[j++] = rect.x;
|
||||
rects[j++] = window_height - rect.height - rect.y;
|
||||
rects[j++] = rect.width;
|
||||
rects[j++] = rect.height;
|
||||
}
|
||||
eglSwapBuffersWithDamageEXT (display_wayland->egl_display, egl_surface, rects, n_rects);
|
||||
g_free (rects);
|
||||
}
|
||||
else
|
||||
eglSwapBuffers (display_wayland->egl_display, egl_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
|
||||
{
|
||||
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
|
||||
|
||||
context_class->update = gdk_wayland_gl_context_update;
|
||||
context_class->flush_buffer = gdk_wayland_gl_context_flush_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_init (GdkWaylandGLContext *self)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_display_init_gl (GdkDisplay *display)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLint major, minor;
|
||||
EGLDisplay *dpy;
|
||||
|
||||
if (display_wayland->have_egl)
|
||||
return TRUE;
|
||||
|
||||
dpy = eglGetDisplay ((EGLNativeDisplayType)display_wayland->wl_display);
|
||||
if (dpy == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!eglInitialize (dpy, &major, &minor))
|
||||
return FALSE;
|
||||
|
||||
if (!eglBindAPI (EGL_OPENGL_API))
|
||||
return FALSE;
|
||||
|
||||
display_wayland->egl_display = dpy;
|
||||
display_wayland->egl_major_version = major;
|
||||
display_wayland->egl_minor_version = minor;
|
||||
|
||||
display_wayland->have_egl = TRUE;
|
||||
|
||||
display_wayland->have_egl_khr_create_context =
|
||||
epoxy_has_egl_extension (dpy, "EGL_KHR_create_context");
|
||||
|
||||
display_wayland->have_egl_buffer_age =
|
||||
epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
|
||||
|
||||
display_wayland->have_egl_swap_buffers_with_damage =
|
||||
epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("EGL API version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
" - Version: %s\n"
|
||||
" - Client APIs: %s\n"
|
||||
" - Extensions:\n"
|
||||
"\t%s\n"
|
||||
,
|
||||
display_wayland->egl_major_version,
|
||||
display_wayland->egl_minor_version,
|
||||
eglQueryString (dpy, EGL_VENDOR),
|
||||
eglQueryString(dpy, EGL_VERSION),
|
||||
eglQueryString(dpy, EGL_CLIENT_APIS),
|
||||
eglQueryString(dpy, EGL_EXTENSIONS)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define MAX_EGL_ATTRS 30
|
||||
|
||||
static gboolean
|
||||
find_eglconfig_for_window (GdkWindow *window,
|
||||
EGLConfig *egl_config_out,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = gdk_window_get_display (window);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkVisual *visual = gdk_window_get_visual (window);
|
||||
EGLint attrs[MAX_EGL_ATTRS];
|
||||
EGLint count;
|
||||
EGLConfig *configs;
|
||||
gboolean use_rgba;
|
||||
|
||||
int i = 0;
|
||||
|
||||
attrs[i++] = EGL_SURFACE_TYPE;
|
||||
attrs[i++] = EGL_WINDOW_BIT;
|
||||
|
||||
attrs[i++] = EGL_COLOR_BUFFER_TYPE;
|
||||
attrs[i++] = EGL_RGB_BUFFER;
|
||||
|
||||
attrs[i++] = EGL_RED_SIZE;
|
||||
attrs[i++] = gdk_visual_get_bits_per_rgb (visual);
|
||||
attrs[i++] = EGL_GREEN_SIZE;
|
||||
attrs[i++] = gdk_visual_get_bits_per_rgb (visual);
|
||||
attrs[i++] = EGL_BLUE_SIZE;
|
||||
attrs[i++] = gdk_visual_get_bits_per_rgb (visual);
|
||||
|
||||
use_rgba = (visual == gdk_screen_get_rgba_visual (gdk_display_get_default_screen (display)));
|
||||
|
||||
if (use_rgba)
|
||||
{
|
||||
attrs[i++] = EGL_ALPHA_SIZE;
|
||||
attrs[i++] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
attrs[i++] = EGL_ALPHA_SIZE;
|
||||
attrs[i++] = 0;
|
||||
}
|
||||
|
||||
attrs[i++] = EGL_NONE;
|
||||
g_assert (i < MAX_EGL_ATTRS);
|
||||
|
||||
if (!eglChooseConfig (display_wayland->egl_display, attrs, NULL, 0, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
configs = g_new (EGLConfig, count);
|
||||
|
||||
if (!eglChooseConfig (display_wayland->egl_display, attrs, configs, count, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Pick first valid configuration i guess? */
|
||||
|
||||
if (egl_config_out != NULL)
|
||||
*egl_config_out = configs[0];
|
||||
|
||||
g_free (configs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_wayland_window_create_gl_context (GdkWindow *window,
|
||||
GdkGLProfile profile,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = gdk_window_get_display (window);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
int i;
|
||||
EGLint context_attribs[3];
|
||||
|
||||
if (!gdk_wayland_display_init_gl (display))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (profile == GDK_GL_PROFILE_3_2_CORE &&
|
||||
!display_wayland->have_egl_khr_create_context)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
|
||||
_("3.2 core GL profile is not available on EGL implementation"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!find_eglconfig_for_window (window, &config, error))
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
if (profile == GDK_GL_PROFILE_3_2_CORE)
|
||||
{
|
||||
context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
|
||||
context_attribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
}
|
||||
context_attribs[i++] = EGL_NONE;
|
||||
|
||||
ctx = eglCreateContext (display_wayland->egl_display,
|
||||
config,
|
||||
share ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context : EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
if (ctx == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("Created EGL context[%p]\n", ctx));
|
||||
|
||||
context = g_object_new (GDK_WAYLAND_TYPE_GL_CONTEXT,
|
||||
"window", window,
|
||||
"visual", gdk_window_get_visual (window),
|
||||
NULL);
|
||||
|
||||
context->egl_config = config;
|
||||
context->egl_context = ctx;
|
||||
|
||||
return GDK_GL_CONTEXT (context);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_display_destroy_gl_context (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
|
||||
/* TODO: Unset as current if current? */
|
||||
if (context_wayland->egl_context != NULL)
|
||||
{
|
||||
if (eglGetCurrentContext () == context_wayland->egl_context)
|
||||
eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
|
||||
GDK_NOTE (OPENGL, g_print ("Destroying EGL context\n"));
|
||||
|
||||
eglDestroyContext (display_wayland->egl_display,
|
||||
context_wayland->egl_context);
|
||||
context_wayland->egl_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context_wayland;
|
||||
GdkWindow *window;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
window = gdk_gl_context_get_window (context);
|
||||
|
||||
egl_surface = gdk_wayland_window_get_egl_surface (window->impl_window, context_wayland->egl_config);
|
||||
|
||||
if (!eglMakeCurrent(display_wayland->egl_display, egl_surface,
|
||||
egl_surface, context_wayland->egl_context))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
63
gdk/wayland/gdkglcontext-wayland.h
Normal file
63
gdk/wayland/gdkglcontext-wayland.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* gdkglcontext-wayland.h: Private Wayland specific OpenGL wrappers
|
||||
*
|
||||
* Copyright © 2014 Emmanuele Bassi
|
||||
* Copyright © 2014 Red Hat, Int
|
||||
*
|
||||
* 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_WAYLAND_GL_CONTEXT__
|
||||
#define __GDK_WAYLAND_GL_CONTEXT__
|
||||
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkvisual.h"
|
||||
#include "gdkwindow.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkmain.h"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GdkWaylandGLContext
|
||||
{
|
||||
GdkGLContext parent_instance;
|
||||
|
||||
EGLContext egl_context;
|
||||
EGLConfig egl_config;
|
||||
};
|
||||
|
||||
struct _GdkWaylandGLContextClass
|
||||
{
|
||||
GdkGLContextClass parent_class;
|
||||
};
|
||||
|
||||
gboolean gdk_wayland_display_init_gl (GdkDisplay *display);
|
||||
GdkGLContext * gdk_wayland_window_create_gl_context (GdkWindow *window,
|
||||
GdkGLProfile profile,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
void gdk_wayland_window_invalidate_for_new_frame (GdkWindow *window,
|
||||
cairo_region_t *update_area);
|
||||
void gdk_wayland_display_destroy_gl_context (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
gboolean gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WAYLAND_GL_CONTEXT__ */
|
@ -237,5 +237,7 @@ struct wl_data_source * gdk_wayland_selection_get_data_source (GdkWindow *owner,
|
||||
GdkAtom selection);
|
||||
void gdk_wayland_selection_unset_data_source (GdkAtom selection);
|
||||
|
||||
EGLSurface gdk_wayland_window_get_egl_surface (GdkWindow *window,
|
||||
EGLConfig config);
|
||||
|
||||
#endif /* __GDK_PRIVATE_WAYLAND_H__ */
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <gdk/wayland/gdkwaylanddisplay.h>
|
||||
#include <gdk/wayland/gdkwaylandselection.h>
|
||||
#include <gdk/wayland/gdkwaylandwindow.h>
|
||||
#include <gdk/wayland/gdkwaylandglcontext.h>
|
||||
|
||||
#undef __GDKWAYLAND_H_INSIDE__
|
||||
|
||||
|
45
gdk/wayland/gdkwaylandglcontext.h
Normal file
45
gdk/wayland/gdkwaylandglcontext.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* gdkglcontext-wayland.c: Wayland specific OpenGL wrappers
|
||||
*
|
||||
* Copyright © 2014 Emmanuele Bassi
|
||||
* Copyright © 2014 Red Hat, Inc
|
||||
*
|
||||
* 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_WAYLAND_GL_CONTEXT_H__
|
||||
#define __GDK_WAYLAND_GL_CONTEXT_H__
|
||||
|
||||
#if !defined (__GDKWAYLAND_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdkwayland.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_WAYLAND_TYPE_GL_CONTEXT (gdk_wayland_gl_context_get_type ())
|
||||
#define GDK_WAYLAND_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_WAYLAND_TYPE_GL_CONTEXT, GdkWaylandGLContext))
|
||||
#define GDK_WAYLAND_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_WAYLAND_TYPE_GL_CONTEXT))
|
||||
|
||||
typedef struct _GdkWaylandGLContext GdkWaylandGLContext;
|
||||
typedef struct _GdkWaylandGLContextClass GdkWaylandGLContextClass;
|
||||
|
||||
GDK_AVAILABLE_IN_3_14
|
||||
GType gdk_wayland_gl_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WAYLAND_GL_CONTEXT_H__ */
|
@ -26,6 +26,7 @@
|
||||
#include "gdkwindow.h"
|
||||
#include "gdkwindowimpl.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkglcontext-wayland.h"
|
||||
#include "gdkframeclockprivate.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkinternals.h"
|
||||
@ -97,6 +98,9 @@ struct _GdkWindowImplWayland
|
||||
|
||||
struct wl_subsurface *subsurface;
|
||||
|
||||
struct wl_egl_window *egl_window;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
unsigned int mapped : 1;
|
||||
unsigned int use_custom_surface : 1;
|
||||
unsigned int pending_commit : 1;
|
||||
@ -170,6 +174,9 @@ gdk_wayland_window_update_size (GdkWindow *window,
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
|
||||
if (impl->egl_window)
|
||||
wl_egl_window_resize (impl->egl_window, width, height, 0, 0);
|
||||
|
||||
area.x = 0;
|
||||
area.y = 0;
|
||||
area.width = window->width;
|
||||
@ -582,15 +589,18 @@ gdk_window_impl_wayland_end_paint (GdkWindow *window)
|
||||
cairo_rectangle_int_t rect;
|
||||
int i, n;
|
||||
|
||||
gdk_wayland_window_attach_image (window);
|
||||
|
||||
n = cairo_region_num_rectangles (window->current_paint.region);
|
||||
for (i = 0; i < n; i++)
|
||||
if (!window->current_paint.use_gl)
|
||||
{
|
||||
cairo_region_get_rectangle (window->current_paint.region, i, &rect);
|
||||
wl_surface_damage (impl->surface,
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
impl->pending_commit = TRUE;
|
||||
gdk_wayland_window_attach_image (window);
|
||||
|
||||
n = cairo_region_num_rectangles (window->current_paint.region);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
cairo_region_get_rectangle (window->current_paint.region, i, &rect);
|
||||
wl_surface_damage (impl->surface,
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
impl->pending_commit = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1156,10 +1166,23 @@ gdk_wayland_window_show (GdkWindow *window,
|
||||
static void
|
||||
gdk_wayland_window_hide_surface (GdkWindow *window)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
|
||||
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
|
||||
if (impl->surface)
|
||||
{
|
||||
if (impl->egl_surface)
|
||||
{
|
||||
eglDestroySurface(display_wayland->egl_display, impl->egl_surface);
|
||||
impl->egl_surface = NULL;
|
||||
}
|
||||
|
||||
if (impl->egl_window)
|
||||
{
|
||||
wl_egl_window_destroy (impl->egl_window);
|
||||
impl->egl_window = NULL;
|
||||
}
|
||||
|
||||
if (impl->xdg_surface)
|
||||
{
|
||||
xdg_surface_destroy (impl->xdg_surface);
|
||||
@ -2128,6 +2151,8 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
|
||||
impl_class->set_opaque_region = gdk_wayland_window_set_opaque_region;
|
||||
impl_class->set_shadow_width = gdk_wayland_window_set_shadow_width;
|
||||
impl_class->show_window_menu = gdk_wayland_window_show_window_menu;
|
||||
impl_class->create_gl_context = gdk_wayland_window_create_gl_context;
|
||||
impl_class->invalidate_for_new_frame = gdk_wayland_window_invalidate_for_new_frame;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2169,6 +2194,50 @@ gdk_wayland_window_get_wl_surface (GdkWindow *window)
|
||||
return impl->surface;
|
||||
}
|
||||
|
||||
static struct wl_egl_window *
|
||||
gdk_wayland_window_get_wl_egl_window (GdkWindow *window)
|
||||
{
|
||||
GdkWindowImplWayland *impl;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
|
||||
|
||||
impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
|
||||
if (impl->egl_window == NULL)
|
||||
{
|
||||
impl->egl_window =
|
||||
wl_egl_window_create(impl->surface,
|
||||
impl->wrapper->width,
|
||||
impl->wrapper->height);
|
||||
}
|
||||
|
||||
return impl->egl_window;
|
||||
}
|
||||
|
||||
EGLSurface
|
||||
gdk_wayland_window_get_egl_surface (GdkWindow *window,
|
||||
EGLConfig config)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
|
||||
GdkWindowImplWayland *impl;
|
||||
struct wl_egl_window *egl_window;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
|
||||
|
||||
impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||
|
||||
if (impl->egl_surface == NULL)
|
||||
{
|
||||
egl_window = gdk_wayland_window_get_wl_egl_window (window);
|
||||
|
||||
impl->egl_surface =
|
||||
eglCreateWindowSurface (display_wayland->egl_display,
|
||||
config, egl_window, NULL);
|
||||
}
|
||||
|
||||
return impl->egl_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_window_set_use_custom_surface:
|
||||
* @window: (type GdkWaylandWindow): a #GdkWindow
|
||||
|
Loading…
Reference in New Issue
Block a user