mir: add OpenGL support
Implement GdkGLContext using EGL and use hardware mir surfaces when a GdkWindow uses gl rendering. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=740346
This commit is contained in:
		@ -24,6 +24,7 @@ libgdk_mir_la_SOURCES =	\
 | 
			
		||||
	gdkmirdevicemanager.c \
 | 
			
		||||
	gdkmirdisplay.c \
 | 
			
		||||
	gdkmireventsource.c	\
 | 
			
		||||
	gdkmirglcontext.c \
 | 
			
		||||
	gdkmirkeyboard.c \
 | 
			
		||||
	gdkmirkeymap.c \
 | 
			
		||||
	gdkmirpointer.c \
 | 
			
		||||
 | 
			
		||||
@ -18,10 +18,13 @@
 | 
			
		||||
#ifndef __GDK_PRIVATE_MIR_H__
 | 
			
		||||
#define __GDK_PRIVATE_MIR_H__
 | 
			
		||||
 | 
			
		||||
#include <epoxy/egl.h>
 | 
			
		||||
 | 
			
		||||
#include "gdkmir.h"
 | 
			
		||||
#include "gdkdisplay.h"
 | 
			
		||||
#include "gdkscreen.h"
 | 
			
		||||
#include "gdkdevicemanager.h"
 | 
			
		||||
#include "gdkglcontextprivate.h"
 | 
			
		||||
#include "gdkkeys.h"
 | 
			
		||||
#include "gdkwindowimpl.h"
 | 
			
		||||
 | 
			
		||||
@ -35,6 +38,27 @@ typedef struct _GdkMirEventSource GdkMirEventSource;
 | 
			
		||||
 | 
			
		||||
GType gdk_mir_window_impl_get_type (void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct _GdkMirGLContext
 | 
			
		||||
{
 | 
			
		||||
  GdkGLContext parent_instance;
 | 
			
		||||
 | 
			
		||||
  EGLContext egl_context;
 | 
			
		||||
  EGLConfig egl_config;
 | 
			
		||||
  gboolean is_attached;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _GdkMirGLContextClass
 | 
			
		||||
{
 | 
			
		||||
  GdkGLContextClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _GdkMirGLContext GdkMirGLContext;
 | 
			
		||||
typedef struct _GdkMirGLContextClass GdkMirGLContextClass;
 | 
			
		||||
 | 
			
		||||
#define GDK_MIR_GL_CONTEXT(obj)   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MIR_GL_CONTEXT, GdkMirGLContext))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GdkDisplay *_gdk_mir_display_open (const gchar *display_name);
 | 
			
		||||
 | 
			
		||||
GdkScreen *_gdk_mir_screen_new (GdkDisplay *display);
 | 
			
		||||
@ -77,6 +101,24 @@ void _gdk_mir_window_reference_unref (GdkMirWindowReference *ref);
 | 
			
		||||
 | 
			
		||||
void _gdk_mir_event_source_queue (GdkMirWindowReference *window_ref, const MirEvent *event);
 | 
			
		||||
 | 
			
		||||
MirPixelFormat _gdk_mir_display_get_pixel_format (GdkDisplay *display, MirBufferUsage usage);
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_init_egl_display (GdkDisplay *display);
 | 
			
		||||
 | 
			
		||||
EGLDisplay _gdk_mir_display_get_egl_display (GdkDisplay *display);
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_khr_create_context (GdkDisplay *display);
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_buffer_age (GdkDisplay *display);
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_swap_buffers_with_damage (GdkDisplay *display);
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_surfaceless_context (GdkDisplay *display);
 | 
			
		||||
 | 
			
		||||
EGLSurface _gdk_mir_window_get_egl_surface (GdkWindow *window, EGLConfig config);
 | 
			
		||||
 | 
			
		||||
EGLSurface _gdk_mir_window_get_dummy_egl_surface (GdkWindow *window, EGLConfig config);
 | 
			
		||||
 | 
			
		||||
void _gdk_mir_print_modifiers (unsigned int modifiers);
 | 
			
		||||
 | 
			
		||||
void _gdk_mir_print_key_event (const MirKeyEvent *event);
 | 
			
		||||
 | 
			
		||||
@ -24,8 +24,11 @@
 | 
			
		||||
#define GDK_TYPE_MIR_DISPLAY              (gdk_mir_display_get_type ())
 | 
			
		||||
#define GDK_IS_MIR_DISPLAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_DISPLAY))
 | 
			
		||||
 | 
			
		||||
#define GDK_TYPE_MIR_WINDOW              (gdk_mir_window_get_type ())
 | 
			
		||||
#define GDK_IS_WINDOW_MIR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_WINDOW))
 | 
			
		||||
#define GDK_TYPE_MIR_GL_CONTEXT           (gdk_mir_gl_context_get_type ())
 | 
			
		||||
#define GDK_MIR_IS_GL_CONTEXT(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MIR_GL_CONTEXT))
 | 
			
		||||
 | 
			
		||||
#define GDK_TYPE_MIR_WINDOW               (gdk_mir_window_get_type ())
 | 
			
		||||
#define GDK_IS_WINDOW_MIR(object)         (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_WINDOW))
 | 
			
		||||
 | 
			
		||||
GDK_AVAILABLE_IN_3_10
 | 
			
		||||
GType gdk_mir_display_get_type (void);
 | 
			
		||||
@ -36,4 +39,7 @@ struct MirConnection *gdk_mir_display_get_mir_connection (GdkDisplay *display);
 | 
			
		||||
GDK_AVAILABLE_IN_3_10
 | 
			
		||||
GType gdk_mir_window_get_type (void);
 | 
			
		||||
 | 
			
		||||
GDK_AVAILABLE_IN_3_16
 | 
			
		||||
GType gdk_mir_gl_context_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
#endif /* __GDK_MIR_H__ */
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,15 @@ typedef struct GdkMirDisplay
 | 
			
		||||
  GdkScreen *screen;
 | 
			
		||||
 | 
			
		||||
  GdkKeymap *keymap;
 | 
			
		||||
 | 
			
		||||
  MirPixelFormat sw_pixel_format;
 | 
			
		||||
  MirPixelFormat hw_pixel_format;
 | 
			
		||||
 | 
			
		||||
  EGLDisplay egl_display;
 | 
			
		||||
  guint have_egl_khr_create_context : 1;
 | 
			
		||||
  guint have_egl_buffer_age : 1;
 | 
			
		||||
  guint have_egl_swap_buffers_with_damage : 1;
 | 
			
		||||
  guint have_egl_surfaceless_context : 1;
 | 
			
		||||
} GdkMirDisplay;
 | 
			
		||||
 | 
			
		||||
typedef struct GdkMirDisplayClass
 | 
			
		||||
@ -53,6 +62,8 @@ typedef struct GdkMirDisplayClass
 | 
			
		||||
  GdkDisplayClass parent_class;
 | 
			
		||||
} GdkMirDisplayClass;
 | 
			
		||||
 | 
			
		||||
static void initialize_pixel_formats (GdkMirDisplay *display);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:mir_interaction
 | 
			
		||||
 * @Short_description: Mir backend-specific functions
 | 
			
		||||
@ -112,6 +123,7 @@ _gdk_mir_display_open (const gchar *display_name)
 | 
			
		||||
  display->connection = connection;
 | 
			
		||||
  GDK_DISPLAY (display)->device_manager = _gdk_mir_device_manager_new (GDK_DISPLAY (display));
 | 
			
		||||
  display->screen = _gdk_mir_screen_new (GDK_DISPLAY (display));
 | 
			
		||||
  initialize_pixel_formats (display);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit_by_name (display, "opened");
 | 
			
		||||
 | 
			
		||||
@ -487,6 +499,180 @@ gdk_mir_display_utf8_to_string_target (GdkDisplay  *display,
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
initialize_pixel_formats (GdkMirDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  MirPixelFormat formats[mir_pixel_formats];
 | 
			
		||||
  unsigned int n_formats, i;
 | 
			
		||||
 | 
			
		||||
  mir_connection_get_available_surface_formats (display->connection, formats,
 | 
			
		||||
                                                mir_pixel_formats, &n_formats);
 | 
			
		||||
 | 
			
		||||
  display->sw_pixel_format = mir_pixel_format_invalid;
 | 
			
		||||
  display->hw_pixel_format = mir_pixel_format_invalid;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_formats; i++)
 | 
			
		||||
    {
 | 
			
		||||
      switch (formats[i])
 | 
			
		||||
      {
 | 
			
		||||
        case mir_pixel_format_abgr_8888:
 | 
			
		||||
        case mir_pixel_format_xbgr_8888:
 | 
			
		||||
        case mir_pixel_format_argb_8888:
 | 
			
		||||
        case mir_pixel_format_xrgb_8888:
 | 
			
		||||
          display->hw_pixel_format = formats[i];
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (display->hw_pixel_format != mir_pixel_format_invalid)
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_formats; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (formats[i] == mir_pixel_format_argb_8888)
 | 
			
		||||
        {
 | 
			
		||||
          display->sw_pixel_format = formats[i];
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MirPixelFormat
 | 
			
		||||
_gdk_mir_display_get_pixel_format (GdkDisplay *display,
 | 
			
		||||
                                   MirBufferUsage usage)
 | 
			
		||||
{
 | 
			
		||||
  GdkMirDisplay *mir_dpy = GDK_MIR_DISPLAY (display);
 | 
			
		||||
 | 
			
		||||
  if (usage == mir_buffer_usage_hardware)
 | 
			
		||||
    return mir_dpy->hw_pixel_format;
 | 
			
		||||
 | 
			
		||||
  return mir_dpy->sw_pixel_format;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
_gdk_mir_display_init_egl_display (GdkDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  GdkMirDisplay *mir_dpy = GDK_MIR_DISPLAY (display);
 | 
			
		||||
  EGLint major_version, minor_version;
 | 
			
		||||
  EGLDisplay *dpy;
 | 
			
		||||
 | 
			
		||||
  if (mir_dpy->egl_display)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  dpy = eglGetDisplay (mir_connection_get_egl_native_display (mir_dpy->connection));
 | 
			
		||||
  if (dpy == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!eglInitialize (dpy, &major_version, &minor_version))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!eglBindAPI (EGL_OPENGL_API))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  mir_dpy->egl_display = dpy;
 | 
			
		||||
 | 
			
		||||
  mir_dpy->have_egl_khr_create_context =
 | 
			
		||||
    epoxy_has_egl_extension (dpy, "EGL_KHR_create_context");
 | 
			
		||||
 | 
			
		||||
  mir_dpy->have_egl_buffer_age =
 | 
			
		||||
    epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
 | 
			
		||||
 | 
			
		||||
  mir_dpy->have_egl_swap_buffers_with_damage =
 | 
			
		||||
    epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
 | 
			
		||||
 | 
			
		||||
  mir_dpy->have_egl_surfaceless_context =
 | 
			
		||||
    epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context");
 | 
			
		||||
 | 
			
		||||
  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",
 | 
			
		||||
                     major_version,
 | 
			
		||||
                     minor_version,
 | 
			
		||||
                     eglQueryString (dpy, EGL_VENDOR),
 | 
			
		||||
                     eglQueryString (dpy, EGL_VERSION),
 | 
			
		||||
                     eglQueryString (dpy, EGL_CLIENT_APIS),
 | 
			
		||||
                     eglQueryString (dpy, EGL_EXTENSIONS)));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
gdk_mir_display_make_gl_context_current (GdkDisplay   *display,
 | 
			
		||||
                                         GdkGLContext *context)
 | 
			
		||||
{
 | 
			
		||||
  EGLDisplay egl_display = _gdk_mir_display_get_egl_display (display);
 | 
			
		||||
  GdkMirGLContext *mir_context;
 | 
			
		||||
  GdkWindow *window;
 | 
			
		||||
  EGLSurface egl_surface;
 | 
			
		||||
 | 
			
		||||
  if (context == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  mir_context = GDK_MIR_GL_CONTEXT (context);
 | 
			
		||||
  window = gdk_gl_context_get_window (context);
 | 
			
		||||
 | 
			
		||||
  if (mir_context->is_attached)
 | 
			
		||||
    {
 | 
			
		||||
      egl_surface = _gdk_mir_window_get_egl_surface (window,
 | 
			
		||||
                                                     mir_context->egl_config);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (_gdk_mir_display_have_egl_surfaceless_context (display))
 | 
			
		||||
        egl_surface = EGL_NO_SURFACE;
 | 
			
		||||
      else
 | 
			
		||||
        egl_surface = _gdk_mir_window_get_dummy_egl_surface (window,
 | 
			
		||||
                                                             mir_context->egl_config);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!eglMakeCurrent (egl_display, egl_surface, egl_surface, mir_context->egl_context))
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("eglMakeCurrent failed");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EGLDisplay _gdk_mir_display_get_egl_display (GdkDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return GDK_MIR_DISPLAY (display)->egl_display;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_khr_create_context (GdkDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return GDK_MIR_DISPLAY (display)->have_egl_khr_create_context;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_buffer_age (GdkDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: this is not really supported by mir yet (despite is advertised) */
 | 
			
		||||
  // return GDK_MIR_DISPLAY (display)->have_egl_buffer_age;
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_swap_buffers_with_damage (GdkDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: this is not really supported by mir yet (despite is advertised) */
 | 
			
		||||
  // return GDK_MIR_DISPLAY (display)->have_egl_swap_buffers_with_damage;
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean _gdk_mir_display_have_egl_surfaceless_context (GdkDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return GDK_MIR_DISPLAY (display)->have_egl_surfaceless_context;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_display_init (GdkMirDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
@ -545,4 +731,5 @@ gdk_mir_display_class_init (GdkMirDisplayClass *klass)
 | 
			
		||||
  display_class->convert_selection = gdk_mir_display_convert_selection;
 | 
			
		||||
  display_class->text_property_to_utf8_list = gdk_mir_display_text_property_to_utf8_list;
 | 
			
		||||
  display_class->utf8_to_string_target = gdk_mir_display_utf8_to_string_target;
 | 
			
		||||
  display_class->make_gl_context_current = gdk_mir_display_make_gl_context_current;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										125
									
								
								gdk/mir/gdkmirglcontext.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								gdk/mir/gdkmirglcontext.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
/* GDK - The GIMP Drawing Kit
 | 
			
		||||
 *
 | 
			
		||||
 * gdkmirglcontext.c: Mir specific OpenGL wrappers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright © 2014 Canonical Ltd
 | 
			
		||||
 *
 | 
			
		||||
 * 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 "gdkmir-private.h"
 | 
			
		||||
#include "gdkinternals.h"
 | 
			
		||||
#include "gdkintl.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (GdkMirGLContext, gdk_mir_gl_context, GDK_TYPE_GL_CONTEXT)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_gl_context_update (GdkGLContext *context)
 | 
			
		||||
{
 | 
			
		||||
  GdkWindow *window = gdk_gl_context_get_window (context);
 | 
			
		||||
  int width, height;
 | 
			
		||||
 | 
			
		||||
  gdk_gl_context_make_current (context);
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_gl_context_end_frame (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);
 | 
			
		||||
  GdkMirGLContext *context_mir = GDK_MIR_GL_CONTEXT (context);
 | 
			
		||||
  EGLDisplay egl_display = _gdk_mir_display_get_egl_display (display);
 | 
			
		||||
  EGLSurface egl_surface;
 | 
			
		||||
 | 
			
		||||
  gdk_gl_context_make_current (context);
 | 
			
		||||
 | 
			
		||||
  egl_surface = _gdk_mir_window_get_egl_surface (window,
 | 
			
		||||
                                                 context_mir->egl_config);
 | 
			
		||||
 | 
			
		||||
  if (_gdk_mir_display_have_egl_swap_buffers_with_damage (display))
 | 
			
		||||
    {
 | 
			
		||||
      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 (egl_display, egl_surface, rects, n_rects);
 | 
			
		||||
      g_free (rects);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      eglSwapBuffers (egl_display, egl_surface);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_gl_context_dispose (GObject *gobject)
 | 
			
		||||
{
 | 
			
		||||
  GdkMirGLContext *context_mir = GDK_MIR_GL_CONTEXT (gobject);
 | 
			
		||||
 | 
			
		||||
  if (context_mir->egl_context != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      GdkGLContext *context = GDK_GL_CONTEXT (gobject);
 | 
			
		||||
      GdkWindow *window = gdk_gl_context_get_window (context);
 | 
			
		||||
      GdkDisplay *display = gdk_window_get_display (window);
 | 
			
		||||
      EGLDisplay egl_display = _gdk_mir_display_get_egl_display (display);
 | 
			
		||||
 | 
			
		||||
      if (eglGetCurrentContext () == context_mir->egl_context)
 | 
			
		||||
        eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | 
			
		||||
 | 
			
		||||
      GDK_NOTE (OPENGL, g_print ("Destroying EGL context\n"));
 | 
			
		||||
 | 
			
		||||
      eglDestroyContext (egl_display, context_mir->egl_context);
 | 
			
		||||
      context_mir->egl_context = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (gdk_mir_gl_context_parent_class)->dispose (gobject);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_gl_context_class_init (GdkMirGLContextClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
 | 
			
		||||
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  context_class->update = gdk_mir_gl_context_update;
 | 
			
		||||
  context_class->end_frame = gdk_mir_gl_context_end_frame;
 | 
			
		||||
  gobject_class->dispose = gdk_mir_gl_context_dispose;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_gl_context_init (GdkMirGLContext *self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@ -25,6 +25,7 @@
 | 
			
		||||
 | 
			
		||||
#include "gdkwindowimpl.h"
 | 
			
		||||
#include "gdkinternals.h"
 | 
			
		||||
#include "gdkintl.h"
 | 
			
		||||
#include "gdkdisplayprivate.h"
 | 
			
		||||
#include "gdkdeviceprivate.h"
 | 
			
		||||
 | 
			
		||||
@ -32,6 +33,8 @@
 | 
			
		||||
#define GDK_IS_WINDOW_IMPL_MIR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_MIR))
 | 
			
		||||
#define GDK_MIR_WINDOW_IMPL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_MIR, GdkMirWindowImplClass))
 | 
			
		||||
 | 
			
		||||
#define MAX_EGL_ATTRS 30
 | 
			
		||||
 | 
			
		||||
typedef struct _GdkMirWindowImplClass GdkMirWindowImplClass;
 | 
			
		||||
 | 
			
		||||
struct _GdkMirWindowImpl
 | 
			
		||||
@ -64,6 +67,13 @@ struct _GdkMirWindowImpl
 | 
			
		||||
  /* Cairo context for current frame */
 | 
			
		||||
  cairo_surface_t *cairo_surface;
 | 
			
		||||
 | 
			
		||||
  /* Egl surface for the current mir surface */
 | 
			
		||||
  EGLSurface egl_surface;
 | 
			
		||||
 | 
			
		||||
  /* Dummy MIR and EGL surfaces */
 | 
			
		||||
  MirSurface *dummy_surface;
 | 
			
		||||
  EGLSurface dummy_egl_surface;
 | 
			
		||||
 | 
			
		||||
  /* TRUE if the window can be seen */
 | 
			
		||||
  gboolean visible;
 | 
			
		||||
 | 
			
		||||
@ -135,12 +145,6 @@ gdk_mir_window_impl_init (GdkMirWindowImpl *impl)
 | 
			
		||||
  impl->surface_state = mir_surface_state_unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MirConnection *
 | 
			
		||||
get_connection (GdkWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  return gdk_mir_display_get_mir_connection (gdk_window_get_display (window));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_surface_state (GdkMirWindowImpl *impl,
 | 
			
		||||
                   MirSurfaceState state)
 | 
			
		||||
@ -173,13 +177,32 @@ event_cb (MirSurface     *surface,
 | 
			
		||||
  _gdk_mir_event_source_queue (context, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MirSurface *
 | 
			
		||||
create_mir_surface (GdkDisplay *display,
 | 
			
		||||
                    gint width,
 | 
			
		||||
                    gint height,
 | 
			
		||||
                    MirBufferUsage buffer_usage)
 | 
			
		||||
{
 | 
			
		||||
  MirSurfaceParameters parameters;
 | 
			
		||||
  MirConnection *connection;
 | 
			
		||||
 | 
			
		||||
  parameters.name = "GTK+ Mir";
 | 
			
		||||
  parameters.width = width;
 | 
			
		||||
  parameters.height = height;
 | 
			
		||||
  parameters.pixel_format = _gdk_mir_display_get_pixel_format (display, buffer_usage);
 | 
			
		||||
  parameters.buffer_usage = buffer_usage;
 | 
			
		||||
  parameters.output_id = mir_display_output_id_invalid;
 | 
			
		||||
 | 
			
		||||
  connection = gdk_mir_display_get_mir_connection (display);
 | 
			
		||||
 | 
			
		||||
  return mir_connection_create_surface_sync (connection, ¶meters);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_surface (GdkWindow *window)
 | 
			
		||||
ensure_surface_full (GdkWindow *window,
 | 
			
		||||
                     MirBufferUsage buffer_usage)
 | 
			
		||||
{
 | 
			
		||||
  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 | 
			
		||||
  MirPixelFormat formats[mir_pixel_formats], pixel_format = mir_pixel_format_invalid;
 | 
			
		||||
  unsigned int n_formats, i;
 | 
			
		||||
  MirSurfaceParameters parameters;
 | 
			
		||||
  MirEventDelegate event_delegate = { event_cb, NULL };
 | 
			
		||||
  GdkMirWindowReference *window_ref;
 | 
			
		||||
 | 
			
		||||
@ -193,34 +216,17 @@ ensure_surface (GdkWindow *window)
 | 
			
		||||
 | 
			
		||||
  event_delegate.context = window_ref;
 | 
			
		||||
 | 
			
		||||
  // Should probably calculate this once?
 | 
			
		||||
  // Should prefer certain formats over others
 | 
			
		||||
  mir_connection_get_available_surface_formats (get_connection (window), formats, mir_pixel_formats, &n_formats);
 | 
			
		||||
  for (i = 0; i < n_formats; i++)
 | 
			
		||||
    if (formats[i] == mir_pixel_format_argb_8888)
 | 
			
		||||
      {
 | 
			
		||||
        pixel_format = formats[i];
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
  impl->surface = create_mir_surface (gdk_window_get_display (window),
 | 
			
		||||
                                      window->width, window->height,
 | 
			
		||||
                                      buffer_usage);
 | 
			
		||||
 | 
			
		||||
  parameters.name = "GTK+ Mir";
 | 
			
		||||
  parameters.width = window->width;
 | 
			
		||||
  parameters.height = window->height;
 | 
			
		||||
  parameters.pixel_format = pixel_format;
 | 
			
		||||
  parameters.buffer_usage = mir_buffer_usage_software;
 | 
			
		||||
  parameters.output_id = mir_display_output_id_invalid;
 | 
			
		||||
  impl->surface = mir_connection_create_surface_sync (get_connection (window), ¶meters);
 | 
			
		||||
 | 
			
		||||
  MirGraphicsRegion region;
 | 
			
		||||
  MirEvent resize_event;
 | 
			
		||||
 | 
			
		||||
  mir_surface_get_graphics_region (impl->surface, ®ion);
 | 
			
		||||
 | 
			
		||||
  /* Send the initial configure with the size the server gave... */
 | 
			
		||||
  resize_event.resize.type = mir_event_type_resize;
 | 
			
		||||
  resize_event.resize.surface_id = 0;
 | 
			
		||||
  resize_event.resize.width = region.width;
 | 
			
		||||
  resize_event.resize.height = region.height;
 | 
			
		||||
  resize_event.resize.width = window->width;
 | 
			
		||||
  resize_event.resize.height = window->height;
 | 
			
		||||
 | 
			
		||||
  _gdk_mir_event_source_queue (window_ref, &resize_event);
 | 
			
		||||
 | 
			
		||||
@ -229,6 +235,14 @@ ensure_surface (GdkWindow *window)
 | 
			
		||||
  set_surface_state (impl, impl->surface_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_surface (GdkWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  ensure_surface_full (window, window->gl_paint_context ?
 | 
			
		||||
                                 mir_buffer_usage_hardware :
 | 
			
		||||
                                 mir_buffer_usage_software);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_no_surface (GdkWindow *window)
 | 
			
		||||
{
 | 
			
		||||
@ -237,15 +251,30 @@ ensure_no_surface (GdkWindow *window)
 | 
			
		||||
  if (impl->cairo_surface)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_surface_finish (impl->cairo_surface);
 | 
			
		||||
      cairo_surface_destroy (impl->cairo_surface);
 | 
			
		||||
      impl->cairo_surface = NULL;
 | 
			
		||||
      g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (impl->surface)
 | 
			
		||||
  if (window->gl_paint_context)
 | 
			
		||||
    {
 | 
			
		||||
      mir_surface_release_sync (impl->surface);
 | 
			
		||||
      impl->surface = NULL;
 | 
			
		||||
      GdkDisplay *display = gdk_window_get_display (window);
 | 
			
		||||
      EGLDisplay egl_display = _gdk_mir_display_get_egl_display (display);
 | 
			
		||||
 | 
			
		||||
      if (impl->egl_surface)
 | 
			
		||||
        {
 | 
			
		||||
          eglDestroySurface (egl_display, impl->egl_surface);
 | 
			
		||||
          impl->egl_surface = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (impl->dummy_egl_surface)
 | 
			
		||||
        {
 | 
			
		||||
          eglDestroySurface (egl_display, impl->dummy_egl_surface);
 | 
			
		||||
          impl->dummy_egl_surface = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      g_clear_pointer (&impl->dummy_surface, mir_surface_release_sync);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer(&impl->surface, mir_surface_release_sync);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -303,11 +332,7 @@ send_buffer (GdkWindow *window)
 | 
			
		||||
  mir_surface_swap_buffers_sync (impl->surface);
 | 
			
		||||
 | 
			
		||||
  /* The Cairo context is no longer valid */
 | 
			
		||||
  if (impl->cairo_surface)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_surface_destroy (impl->cairo_surface);
 | 
			
		||||
      impl->cairo_surface = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_surface_t *
 | 
			
		||||
@ -316,7 +341,7 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
 | 
			
		||||
  //g_printerr ("gdk_mir_window_impl_ref_cairo_surface window=%p\n", window);
 | 
			
		||||
  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 | 
			
		||||
  MirGraphicsRegion region;
 | 
			
		||||
  cairo_format_t pixel_format = CAIRO_FORMAT_INVALID;
 | 
			
		||||
  cairo_format_t pixel_format = CAIRO_FORMAT_ARGB32;
 | 
			
		||||
  cairo_surface_t *cairo_surface;
 | 
			
		||||
  cairo_t *c;
 | 
			
		||||
 | 
			
		||||
@ -327,31 +352,16 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Transient windows get rendered into a buffer and copied onto their parent */
 | 
			
		||||
  if (impl->transient_for)
 | 
			
		||||
  if (impl->transient_for || window->gl_paint_context)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, window->width, window->height);
 | 
			
		||||
      cairo_surface = cairo_image_surface_create (pixel_format, window->width, window->height);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_surface (window);
 | 
			
		||||
 | 
			
		||||
      mir_surface_get_graphics_region (impl->surface, ®ion);
 | 
			
		||||
 | 
			
		||||
      // FIXME: Should calculate this once
 | 
			
		||||
      switch (region.pixel_format)
 | 
			
		||||
        {
 | 
			
		||||
        case mir_pixel_format_argb_8888:
 | 
			
		||||
          pixel_format = CAIRO_FORMAT_ARGB32;
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
        case mir_pixel_format_abgr_8888:
 | 
			
		||||
        case mir_pixel_format_xbgr_8888:
 | 
			
		||||
        case mir_pixel_format_xrgb_8888:
 | 
			
		||||
        case mir_pixel_format_bgr_888:
 | 
			
		||||
          // uh-oh...
 | 
			
		||||
          g_printerr ("Unsupported pixel format %d\n", region.pixel_format);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      g_assert (region.pixel_format == mir_pixel_format_argb_8888);
 | 
			
		||||
 | 
			
		||||
      cairo_surface = cairo_image_surface_create_for_data ((unsigned char *) region.vaddr,
 | 
			
		||||
                                                           pixel_format,
 | 
			
		||||
@ -421,10 +431,13 @@ gdk_mir_window_impl_show (GdkWindow *window,
 | 
			
		||||
  /* Make sure there's a surface to see */
 | 
			
		||||
  ensure_surface (window);
 | 
			
		||||
 | 
			
		||||
  /* Make sure something is rendered and then show first frame */
 | 
			
		||||
  s = gdk_mir_window_impl_ref_cairo_surface (window);
 | 
			
		||||
  send_buffer (window);
 | 
			
		||||
  cairo_surface_destroy (s);
 | 
			
		||||
  if (!window->gl_paint_context)
 | 
			
		||||
  {
 | 
			
		||||
    /* Make sure something is rendered and then show first frame */
 | 
			
		||||
    s = gdk_mir_window_impl_ref_cairo_surface (window);
 | 
			
		||||
    send_buffer (window);
 | 
			
		||||
    cairo_surface_destroy (s);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -666,7 +679,7 @@ gdk_mir_window_impl_end_paint (GdkWindow *window)
 | 
			
		||||
  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 | 
			
		||||
 | 
			
		||||
  //g_printerr ("gdk_mir_window_impl_end_paint window=%p\n", window);
 | 
			
		||||
  if (impl->visible)
 | 
			
		||||
  if (impl->visible && !window->current_paint.use_gl)
 | 
			
		||||
    send_buffer (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1245,6 +1258,267 @@ gdk_mir_window_impl_set_shadow_width (GdkWindow *window,
 | 
			
		||||
  g_printerr ("gdk_mir_window_impl_set_shadow_width window=%p\n", window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
find_eglconfig_for_window (GdkWindow  *window,
 | 
			
		||||
                           EGLConfig  *egl_config_out,
 | 
			
		||||
                           GError    **error)
 | 
			
		||||
{
 | 
			
		||||
  GdkDisplay *display = gdk_window_get_display (window);
 | 
			
		||||
  EGLDisplay *egl_display = _gdk_mir_display_get_egl_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++] = 1;
 | 
			
		||||
  attrs[i++] = EGL_GREEN_SIZE;
 | 
			
		||||
  attrs[i++] = 1;
 | 
			
		||||
  attrs[i++] = EGL_BLUE_SIZE;
 | 
			
		||||
  attrs[i++] = 1;
 | 
			
		||||
 | 
			
		||||
  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 (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 (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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GdkGLContext *
 | 
			
		||||
gdk_mir_window_impl_create_gl_context (GdkWindow     *window,
 | 
			
		||||
                                       gboolean       attached,
 | 
			
		||||
                                       GdkGLProfile   profile,
 | 
			
		||||
                                       GdkGLContext  *share,
 | 
			
		||||
                                       GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  GdkDisplay *display = gdk_window_get_display (window);
 | 
			
		||||
  GdkMirGLContext *context;
 | 
			
		||||
  EGLContext ctx;
 | 
			
		||||
  EGLConfig config;
 | 
			
		||||
  int i;
 | 
			
		||||
  EGLint context_attribs[3];
 | 
			
		||||
 | 
			
		||||
  if (!_gdk_mir_display_init_egl_display (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_DEFAULT)
 | 
			
		||||
    profile = GDK_GL_PROFILE_LEGACY;
 | 
			
		||||
 | 
			
		||||
  if (profile == GDK_GL_PROFILE_3_2_CORE &&
 | 
			
		||||
      !_gdk_mir_display_have_egl_khr_create_context (display))
 | 
			
		||||
    {
 | 
			
		||||
      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 (_gdk_mir_display_get_egl_display (display),
 | 
			
		||||
                          config,
 | 
			
		||||
                          share ? GDK_MIR_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_TYPE_MIR_GL_CONTEXT,
 | 
			
		||||
                          "display", display,
 | 
			
		||||
                          "window", window,
 | 
			
		||||
                          "profile", profile,
 | 
			
		||||
                          "shared-context", share,
 | 
			
		||||
                          NULL);
 | 
			
		||||
 | 
			
		||||
  context->egl_config = config;
 | 
			
		||||
  context->egl_context = ctx;
 | 
			
		||||
  context->is_attached = attached;
 | 
			
		||||
 | 
			
		||||
  return GDK_GL_CONTEXT (context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_window_impl_invalidate_for_new_frame (GdkWindow *window,
 | 
			
		||||
                                              cairo_region_t *update_area)
 | 
			
		||||
{
 | 
			
		||||
  cairo_rectangle_int_t window_rect;
 | 
			
		||||
  GdkDisplay *display = gdk_window_get_display (window);
 | 
			
		||||
  GdkMirGLContext *context_mir;
 | 
			
		||||
  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_mir = GDK_MIR_GL_CONTEXT (window->gl_paint_context);
 | 
			
		||||
  buffer_age = 0;
 | 
			
		||||
 | 
			
		||||
  egl_surface = _gdk_mir_window_get_egl_surface (window, context_mir->egl_config);
 | 
			
		||||
 | 
			
		||||
  if (_gdk_mir_display_have_egl_buffer_age (display))
 | 
			
		||||
    {
 | 
			
		||||
      gdk_gl_context_make_current (window->gl_paint_context);
 | 
			
		||||
      eglQuerySurface (_gdk_mir_display_get_egl_display (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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EGLSurface
 | 
			
		||||
_gdk_mir_window_get_egl_surface (GdkWindow *window,
 | 
			
		||||
                                 EGLConfig config)
 | 
			
		||||
{
 | 
			
		||||
  GdkMirWindowImpl *impl;
 | 
			
		||||
 | 
			
		||||
  impl = GDK_MIR_WINDOW_IMPL (window->impl);
 | 
			
		||||
 | 
			
		||||
  if (!impl->egl_surface)
 | 
			
		||||
    {
 | 
			
		||||
      EGLDisplay egl_display;
 | 
			
		||||
      EGLNativeWindowType egl_window;
 | 
			
		||||
 | 
			
		||||
      ensure_no_surface (window);
 | 
			
		||||
      ensure_surface_full (window, mir_buffer_usage_hardware);
 | 
			
		||||
 | 
			
		||||
      egl_display = _gdk_mir_display_get_egl_display (gdk_window_get_display (window));
 | 
			
		||||
      egl_window = (EGLNativeWindowType) mir_surface_get_egl_native_window (impl->surface);
 | 
			
		||||
 | 
			
		||||
      impl->egl_surface =
 | 
			
		||||
        eglCreateWindowSurface (egl_display, config, egl_window, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return impl->egl_surface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EGLSurface
 | 
			
		||||
_gdk_mir_window_get_dummy_egl_surface (GdkWindow *window,
 | 
			
		||||
                                       EGLConfig config)
 | 
			
		||||
{
 | 
			
		||||
  GdkMirWindowImpl *impl;
 | 
			
		||||
 | 
			
		||||
  impl = GDK_MIR_WINDOW_IMPL (window->impl);
 | 
			
		||||
 | 
			
		||||
  if (!impl->dummy_egl_surface)
 | 
			
		||||
    {
 | 
			
		||||
      GdkDisplay *display;
 | 
			
		||||
      EGLDisplay egl_display;
 | 
			
		||||
      EGLNativeWindowType egl_window;
 | 
			
		||||
 | 
			
		||||
      display = gdk_window_get_display (window);
 | 
			
		||||
      impl->dummy_surface = create_mir_surface (display, 1, 1,
 | 
			
		||||
                                                mir_buffer_usage_hardware);
 | 
			
		||||
 | 
			
		||||
      egl_display = _gdk_mir_display_get_egl_display (display);
 | 
			
		||||
      egl_window = (EGLNativeWindowType) mir_surface_get_egl_native_window (impl->surface);
 | 
			
		||||
 | 
			
		||||
      impl->dummy_egl_surface =
 | 
			
		||||
        eglCreateWindowSurface (egl_display, config, egl_window, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return impl->dummy_egl_surface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@ -1333,4 +1607,6 @@ gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
 | 
			
		||||
  impl_class->get_scale_factor = gdk_mir_window_impl_get_scale_factor;
 | 
			
		||||
  impl_class->set_opaque_region = gdk_mir_window_impl_set_opaque_region;
 | 
			
		||||
  impl_class->set_shadow_width = gdk_mir_window_impl_set_shadow_width;
 | 
			
		||||
  impl_class->create_gl_context = gdk_mir_window_impl_create_gl_context;
 | 
			
		||||
  impl_class->invalidate_for_new_frame = gdk_mir_window_impl_invalidate_for_new_frame;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user