summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2018-04-27 23:30:32 +0800
committerChun-wei Fan <fanc999@yahoo.com.tw>2018-06-08 15:11:11 +0800
commit82c700c5c3561bcd35b15acbfa07a93557c07b66 (patch)
treecd2b7b697b0140e2f681f4b76d984ac4197e7ed1
parent9ac7f906aae7f9f252988a5a7f294123b622c8c1 (diff)
downloadgtk+-82c700c5c3561bcd35b15acbfa07a93557c07b66.tar.gz
Add a EGL renderer (via ANGLE) for Windows
This is for adding a EGL-based renderer which is done via the ANGLE project, which translate EGL calls to Direct3D 9/11. This is done as a possible solution to issue #105, especially for cases where the needed full GL extensions to map OpenGL to Direc3D is unavailable or unreliable, or when the OpenGL implementation from the graphics drivers are problematic. To enable this, do the following: -Build ANGLE and ensure the ANGLE libEGL.dll and libGLESv2.dll are available. A sufficiently-recent ANGLE is needed for things to work correctly--note that the copy of ANGLE that is included in qtbase-5.10.1 is sufficient. ANGLE is licensed under a BSD 3-clause license. Note also that Visual Studio 2013 or later is required to build ANGLE from QT-5.10.1, but the 2013-built ANGLE DLLs can work without without problems for GTK+ that is built with Visual Studio 2008 or later. -Build libepoxy on Windows with EGL support enabled. -Define GDK_WIN32_ENABLE_EGL when building gdk-win32.lib when building with Visual Studio, or pass in --enable-win32-gles during configure when building with MinGW/mingw-w64. -Prior to running GTK+ programs, the GDK_GL envvar needs to contain gles. Known issues: -Only OpenGL ES 3 is supported, ANGLE's ES 2 does not support the needed extensions, notably GL_OES_vertex_array_object, but its ES 3 support is sufficient. -There is no autodetection or fallback mechanism to enable using EGL/Angle automatically yet. There is no plans to do this in this commit. Thanks to LRN for pointing out that we should #include "win32/gdkwin32.h" instead of #include "gdkwin32.h" for gdkgl.c. LRN also did the autotools portion of this patch. Further notes about the autotools --enable-win32-gles option, fom LRN: This adds --enable-win32-gles option, which enables the code for GLES renderer. This commit also adds tests for WGL and EGL in epoxy. The absence of WGL is highly unlikely (it's enabled by default), but checking for EGL when GLES is enabled is necessary, as EGL is disabled in Windows builds of epoxy by default.
-rw-r--r--build/win32/Makefile.am1
-rw-r--r--build/win32/README_EGL_MSVC.txt29
-rw-r--r--configure.ac37
-rw-r--r--gdk/gdkgl.c13
-rw-r--r--gdk/gdkglcontext.c10
-rw-r--r--gdk/win32/Makefile.am4
-rw-r--r--gdk/win32/gdkdisplay-win32.c12
-rw-r--r--gdk/win32/gdkdisplay-win32.h18
-rw-r--r--gdk/win32/gdkglcontext-win32.c673
-rw-r--r--gdk/win32/gdkglcontext-win32.h10
-rw-r--r--gdk/win32/gdkwindow-win32.c49
-rw-r--r--gdk/win32/gdkwindow-win32.h15
12 files changed, 728 insertions, 143 deletions
diff --git a/build/win32/Makefile.am b/build/win32/Makefile.am
index 39fed6fe69..e47c8c411e 100644
--- a/build/win32/Makefile.am
+++ b/build/win32/Makefile.am
@@ -42,6 +42,7 @@ EXTRA_DIST += \
replace.py \
pc_base.py \
gtkpc.py \
+ README_EGL_MSVC.txt \
$(GENERATED_ITEMS)
-include $(top_srcdir)/git.mk
diff --git a/build/win32/README_EGL_MSVC.txt b/build/win32/README_EGL_MSVC.txt
new file mode 100644
index 0000000000..f32b9a62fd
--- /dev/null
+++ b/build/win32/README_EGL_MSVC.txt
@@ -0,0 +1,29 @@
+Notes on enabling EGL (ANGLE/D3D support) for Windows/Visual Studio builds
+==========================================================================
+There is now support in the GL context creation code for Windows in GDK for
+creating and using EGL (OpenGL ES 3) contexts, which can be used instead of
+the existing OpenGL (Desktop) support, especially when the graphics drivers
+do not support OpenGL adequately.
+
+This support is not enabled by default in the project files. In order to do
+so, please do the following:
+
+-Obtain or compile a build of recent version of ANGLE. The one that comes
+ with QT 5.10.x is sufficiently recent, but not the one that comes with QT-
+ 5.6.x. Note that Visual Studio 2013 or later is required for building
+ ANGLE from QT-5.10.x, but the Visual Studio 2013-built ANGLE DLLs does work
+ without problems with GTK+ built with Visual Studio 2008~2013. You may
+ need to obtain D3Dcompiler_[47|43|42].dll if it does not come with the
+ system (which is part of the DirectX runtimes). Its headers and .lib
+ needs to be set to be found by the compiler and linker respectively before
+ building libepoxy.
+-Build libepoxy with EGL support, which has to be enabled explicitly on
+ Windows builds. Pass in -Degl=yes when building libepoxy using Meson.
+ Build and install, making sure the headers and .lib can be located by the
+ compiler and linker respectively.
+-Open the vsX/gtk+.sln, and open the project properties in the "gdk3-win32"
+ project. Under "C/C++", add GDK_WIN32_ENABLE_EGL in the "Preprocessor
+ Definitions" to the existing definitions in there for the configuration
+ that is being built. Then build the solution.
+-To force the use of the EGL code, set the envvar GDK_GL=(...,)gles , where (...,)
+ are the other GDK_GL options desired.
diff --git a/configure.ac b/configure.ac
index 05843eda14..f07279db87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1434,6 +1434,43 @@ else
X11_PREFIX="$ac_default_prefix"
fi
+AC_ARG_ENABLE(win32-gles,
+ [AS_HELP_STRING([--enable-win32-gles],
+ [enable OpenGL ES rendering in Win32 backend, disabled by default])],
+ [win32_gles=yes],
+ [win32_gles=no])
+
+if test x"$enable_win32_backend" = xyes; then
+ AC_MSG_CHECKING(WGL support in epoxy)
+ WGL_SUPPORT="`$PKG_CONFIG --variable=epoxy_has_wgl epoxy`"
+ if test x"$WGL_SUPPORT" = x1; then
+ AC_MSG_RESULT([supported])
+ else
+ AC_MSG_ERROR([
+*** epoxy was not built with WGL support or epoxy version is too old.
+*** WGL support in epoxy is enabled by default for all Windows builds,
+*** and is used by GTK+ uncondititonally. If it is not there, then
+*** something is very wrong.
+])
+ fi
+ if test x"$win32_gles" = xyes; then
+ AC_MSG_CHECKING(EGL support in epoxy)
+ EGL_SUPPORT="`$PKG_CONFIG --variable=epoxy_has_egl epoxy`"
+ if test x"$EGL_SUPPORT" = x1; then
+ AC_MSG_RESULT([supported])
+ else
+ AC_MSG_ERROR([
+*** epoxy was not built with EGL support or epoxy version is too old.
+*** EGL support in epoxy is disabled by default in Windows builds,
+*** you might need to rebuild epoxy with explicit --enable-egl=yes.
+*** EGL support is needed for OpenGL ES rendering.
+])
+ fi
+ fi
+fi
+
+AM_CONDITIONAL(WIN32_GLES, test x"$platform_win32" = xyes -a x"$win32_gles" = xyes)
+
GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
ATK_PREFIX="`$PKG_CONFIG --variable=prefix atk`"
PANGO_PREFIX="`$PKG_CONFIG --variable=prefix pango`"
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index 8e7b8c2310..933e204439 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -22,6 +22,10 @@
#include "gdkinternals.h"
+#ifdef GDK_WINDOWING_WIN32
+# include "win32/gdkwin32.h"
+#endif
+
#include <epoxy/gl.h>
#include <math.h>
#include <string.h>
@@ -641,6 +645,13 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
{
/* Software fallback */
int major, minor, version;
+ gboolean es_read_bgra = FALSE;
+
+#ifdef GDK_WINDOWING_WIN32
+ /* on ANGLE GLES, we need to set the glReadPixel() format as GL_BGRA instead */
+ if (GDK_WIN32_IS_GL_CONTEXT(paint_context))
+ es_read_bgra = TRUE;
+#endif
gdk_gl_context_get_version (paint_context, &major, &minor);
version = major * 100 + minor;
@@ -683,7 +694,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
cairo_image_surface_get_data (image));
else
- glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
+ glReadPixels (x, y, width, height, es_read_bgra ? GL_BGRA : GL_RGBA, GL_UNSIGNED_BYTE,
cairo_image_surface_get_data (image));
glPixelStorei (GL_PACK_ROW_LENGTH, 0);
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index df538b0c77..dfbed63ca5 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -793,11 +793,17 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
has_npot = priv->gl_version >= 20;
has_texture_rectangle = FALSE;
- /* This should check for GL_NV_framebuffer_blit - see extension at:
+ /* This should check for GL_NV_framebuffer_blit as well - see extension at:
*
* https://www.khronos.org/registry/gles/extensions/NV/NV_framebuffer_blit.txt
+ *
+ * for ANGLE, we can enable bit blitting if we have the
+ * GL_ANGLE_framebuffer_blit extension
*/
- priv->has_gl_framebuffer_blit = FALSE;
+ if (epoxy_has_gl_extension ("GL_ANGLE_framebuffer_blit"))
+ priv->has_gl_framebuffer_blit = TRUE;
+ else
+ priv->has_gl_framebuffer_blit = FALSE;
/* No OES version */
priv->has_frame_terminator = FALSE;
diff --git a/gdk/win32/Makefile.am b/gdk/win32/Makefile.am
index 7c37427f07..0504428580 100644
--- a/gdk/win32/Makefile.am
+++ b/gdk/win32/Makefile.am
@@ -17,6 +17,10 @@ AM_CPPFLAGS = \
$(GDK_WIN32_EXTRA_CFLAGS) \
-DGDK_COMPILATION
+if WIN32_GLES
+AM_CPPFLAGS += "-DGDK_WIN32_ENABLE_EGL=1"
+endif #WIN32_GLES
+
LDADDS = $(GDK_DEP_LIBS)
noinst_LTLIBRARIES = libgdk-win32.la
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index de3fab2bef..4f095019b7 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -31,6 +31,10 @@
#include "gdkmonitor-win32.h"
#include "gdkwin32.h"
+#ifdef GDK_WIN32_ENABLE_EGL
+# include <epoxy/egl.h>
+#endif
+
static int debug_indent = 0;
static GdkMonitor *
@@ -825,6 +829,14 @@ gdk_win32_display_dispose (GObject *object)
_gdk_screen_close (display_win32->screen);
+#ifdef GDK_WIN32_ENABLE_EGL
+ if (display_win32->egl_disp != EGL_NO_DISPLAY)
+ {
+ eglTerminate (display_win32->egl_disp);
+ display_win32->egl_disp = EGL_NO_DISPLAY;
+ }
+#endif
+
if (display_win32->hwnd != NULL)
{
DestroyWindow (display_win32->hwnd);
diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h
index 99981af5ee..ad8db96f0f 100644
--- a/gdk/win32/gdkdisplay-win32.h
+++ b/gdk/win32/gdkdisplay-win32.h
@@ -19,6 +19,10 @@
#include "gdkdisplayprivate.h"
+#ifdef GDK_WIN32_ENABLE_EGL
+# include <epoxy/egl.h>
+#endif
+
#ifndef __GDK_DISPLAY__WIN32_H__
#define __GDK_DISPLAY__WIN32_H__
@@ -75,6 +79,14 @@ struct _GdkWin32Display
guint gl_version;
HWND gl_hwnd;
+#ifdef GDK_WIN32_ENABLE_EGL
+ /* EGL (Angle) Items */
+ guint have_egl : 1;
+ guint egl_version;
+ EGLDisplay egl_disp;
+ HDC hdc_egl_temp;
+#endif
+
GPtrArray *monitors;
guint hasWglARBCreateContext : 1;
@@ -83,6 +95,12 @@ struct _GdkWin32Display
guint hasWglARBPixelFormat : 1;
guint hasWglARBmultisample : 1;
+#ifdef GDK_WIN32_ENABLE_EGL
+ guint hasEglKHRCreateContext : 1;
+ guint hasEglSurfacelessContext : 1;
+ EGLint egl_min_swap_interval;
+#endif
+
/* HiDPI Items */
guint have_at_least_win81 : 1;
GdkWin32ProcessDpiAwareness dpi_aware_type;
diff --git a/gdk/win32/gdkglcontext-win32.c b/gdk/win32/gdkglcontext-win32.c
index 593a991f31..7a6ff8ee5a 100644
--- a/gdk/win32/gdkglcontext-win32.c
+++ b/gdk/win32/gdkglcontext-win32.c
@@ -41,6 +41,10 @@
#include <cairo.h>
#include <epoxy/wgl.h>
+#ifdef GDK_WIN32_ENABLE_EGL
+# include <epoxy/egl.h>
+#endif
+
G_DEFINE_TYPE (GdkWin32GLContext, gdk_win32_gl_context, GDK_TYPE_GL_CONTEXT)
static void
@@ -50,6 +54,7 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
GdkWin32GLContext *context_win32 = GDK_WIN32_GL_CONTEXT (gobject);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context));
GdkWindow *window = gdk_gl_context_get_window (context);
+ GdkWindowImplWin32 *impl = NULL;
if (context_win32->hglrc != NULL)
{
@@ -64,9 +69,28 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
ReleaseDC (display_win32->gl_hwnd, context_win32->gl_hdc);
}
+#ifdef GDK_WIN32_ENABLE_EGL
+ if (context_win32->egl_context != EGL_NO_CONTEXT)
+ {
+ if (eglGetCurrentContext () == context_win32->egl_context)
+ eglMakeCurrent(display_win32->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+
+ GDK_NOTE (OPENGL, g_message ("Destroying EGL (ANGLE) context"));
+
+ eglDestroyContext (display_win32->egl_disp,
+ context_win32->egl_context);
+ context_win32->egl_context = EGL_NO_CONTEXT;
+
+ impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+ ReleaseDC (display_win32->gl_hwnd, context_win32->gl_hdc);
+ }
+#endif
+
if (window != NULL && window->impl != NULL)
{
- GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+ impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (impl->suppress_layered > 0)
impl->suppress_layered--;
@@ -126,11 +150,12 @@ _gdk_win32_gl_context_end_frame (GdkGLContext *context,
GdkWindow *window = gdk_gl_context_get_window (context);
GdkWin32Display *display = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
- gboolean can_wait = display->hasWglOMLSyncControl;
gdk_gl_context_make_current (context);
- if (context_win32->do_frame_sync)
+ if (!gdk_gl_context_get_use_es (context))
{
+ gboolean can_wait = display->hasWglOMLSyncControl;
+
if (context_win32->do_frame_sync)
{
glFinish ();
@@ -147,21 +172,30 @@ _gdk_win32_gl_context_end_frame (GdkGLContext *context,
&ust, &msc, &sbc);
}
}
+
+ /* EGL does not have do_blit_swap */
+ if (context_win32->do_blit_swap)
+ {
+ glDrawBuffer(GL_FRONT);
+ glReadBuffer(GL_BACK);
+ gdk_gl_blit_region (window, painted);
+ glDrawBuffer(GL_BACK);
+ glFlush();
+
+ if (gdk_gl_context_has_frame_terminator (context))
+ glFrameTerminatorGREMEDY ();
+ }
+ else
+ SwapBuffers (context_win32->gl_hdc);
}
- if (context_win32->do_blit_swap)
+#ifdef GDK_WIN32_ENABLE_EGL
+ else
{
- glDrawBuffer(GL_FRONT);
- glReadBuffer(GL_BACK);
- gdk_gl_blit_region (window, painted);
- glDrawBuffer(GL_BACK);
- glFlush();
-
- if (gdk_gl_context_has_frame_terminator (context))
- glFrameTerminatorGREMEDY ();
+ EGLSurface egl_surface = _gdk_win32_window_get_egl_surface (window, context_win32->egl_config, FALSE);
+ eglSwapBuffers (display->egl_disp, egl_surface);
}
- else
- SwapBuffers (context_win32->gl_hdc);
+#endif
}
void
@@ -180,6 +214,7 @@ _gdk_win32_window_invalidate_for_new_frame (GdkWindow *window,
context_win32 = GDK_WIN32_GL_CONTEXT (window->gl_paint_context);
context_win32->do_blit_swap = FALSE;
+ /* gdk_gl_context_has_framebuffer_blit() is for Desktop GL only ! */
if (gdk_gl_context_has_framebuffer_blit (window->gl_paint_context) &&
cairo_region_contains_rectangle (update_area, &whole_window) != CAIRO_REGION_OVERLAP_IN)
{
@@ -453,64 +488,152 @@ _gdk_init_dummy_context (GdkWGLDummy *dummy,
return best_idx;
}
+#ifdef GDK_WIN32_ENABLE_EGL
+
+#ifndef EGL_PLATFORM_ANGLE_ANGLE
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#endif
+
+#ifndef EGL_PLATFORM_ANGLE_TYPE_ANGLE
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#endif
+
+#ifndef EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#endif
+
+static EGLDisplay
+_gdk_win32_get_egl_display (GdkWin32Display *display)
+{
+ EGLDisplay disp;
+ gboolean success = FALSE;
+
+ if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
+ {
+ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
+ if (getPlatformDisplay)
+ {
+ EGLint disp_attr[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE};
+
+ disp = getPlatformDisplay (EGL_PLATFORM_ANGLE_ANGLE, display->hdc_egl_temp, disp_attr);
+
+ if (disp != EGL_NO_DISPLAY)
+ return disp;
+ }
+ }
+ return eglGetDisplay (display->hdc_egl_temp);
+}
+#endif
+
static gboolean
_gdk_win32_display_init_gl (GdkDisplay *display,
const gboolean need_alpha_bits)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
gint best_idx = 0;
- GdkWGLDummy dummy;
-
- if (display_win32->have_wgl)
+ gboolean disable_wgl = FALSE;
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ EGLDisplay egl_disp;
+ disable_wgl = (_gdk_gl_flags & GDK_GL_GLES) != 0;
+#endif
+
+ if (display_win32->have_wgl
+#ifdef GDK_WIN32_ENABLE_EGL
+ || display_win32->have_egl
+#endif
+ )
return TRUE;
- memset (&dummy, 0, sizeof (GdkWGLDummy));
+ if (!disable_wgl)
+ {
+ /* acquire and cache dummy Window (HWND & HDC) and
+ * dummy GL Context, it is used to query functions
+ * and used for other stuff as well
+ */
+ GdkWGLDummy dummy;
+ memset (&dummy, 0, sizeof (GdkWGLDummy));
+
+ best_idx = _gdk_init_dummy_context (&dummy, need_alpha_bits);
- /* acquire and cache dummy Window (HWND & HDC) and
- * dummy GL Context, it is used to query functions
- * and used for other stuff as well
- */
- best_idx = _gdk_init_dummy_context (&dummy, need_alpha_bits);
+ if (best_idx == 0 || !wglMakeCurrent (dummy.hdc, dummy.hglrc))
+ return FALSE;
- if (best_idx == 0 || !wglMakeCurrent (dummy.hdc, dummy.hglrc))
- return FALSE;
+ display_win32->have_wgl = TRUE;
+ display_win32->gl_version = epoxy_gl_version ();
+
+ display_win32->hasWglARBCreateContext =
+ epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_create_context");
+ display_win32->hasWglEXTSwapControl =
+ epoxy_has_wgl_extension (dummy.hdc, "WGL_EXT_swap_control");
+ display_win32->hasWglOMLSyncControl =
+ epoxy_has_wgl_extension (dummy.hdc, "WGL_OML_sync_control");
+ display_win32->hasWglARBPixelFormat =
+ epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_pixel_format");
+ display_win32->hasWglARBmultisample =
+ epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_multisample");
+
+ GDK_NOTE (OPENGL,
+ g_print ("WGL API version %d.%d found\n"
+ " - Vendor: %s\n"
+ " - Checked extensions:\n"
+ "\t* WGL_ARB_pixel_format: %s\n"
+ "\t* WGL_ARB_create_context: %s\n"
+ "\t* WGL_EXT_swap_control: %s\n"
+ "\t* WGL_OML_sync_control: %s\n"
+ "\t* WGL_ARB_multisample: %s\n",
+ display_win32->gl_version / 10,
+ display_win32->gl_version % 10,
+ glGetString (GL_VENDOR),
+ display_win32->hasWglARBPixelFormat ? "yes" : "no",
+ display_win32->hasWglARBCreateContext ? "yes" : "no",
+ display_win32->hasWglEXTSwapControl ? "yes" : "no",
+ display_win32->hasWglOMLSyncControl ? "yes" : "no",
+ display_win32->hasWglARBmultisample ? "yes" : "no"));
+
+ wglMakeCurrent (NULL, NULL);
- display_win32->have_wgl = TRUE;
- display_win32->gl_version = epoxy_gl_version ();
+ _destroy_dummy_gl_context (dummy);
+ return TRUE;
+ }
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ egl_disp = _gdk_win32_get_egl_display (display_win32);
+
+ if (egl_disp == EGL_NO_DISPLAY ||
+ !eglInitialize (egl_disp, NULL, NULL))
+ {
+ if (egl_disp != EGL_NO_DISPLAY)
+ {
+ eglTerminate (egl_disp);
+ egl_disp = EGL_NO_DISPLAY;
+ }
+
+ return FALSE;
+ }
+
+ display_win32->egl_disp = egl_disp;
+ display_win32->have_egl = TRUE;
+ display_win32->egl_version = epoxy_egl_version (egl_disp);
+
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ display_win32->hasEglSurfacelessContext =
+ epoxy_has_egl_extension (egl_disp, "EGL_KHR_surfaceless_context");
- display_win32->hasWglARBCreateContext =
- epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_create_context");
- display_win32->hasWglEXTSwapControl =
- epoxy_has_wgl_extension (dummy.hdc, "WGL_EXT_swap_control");
- display_win32->hasWglOMLSyncControl =
- epoxy_has_wgl_extension (dummy.hdc, "WGL_OML_sync_control");
- display_win32->hasWglARBPixelFormat =
- epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_pixel_format");
- display_win32->hasWglARBmultisample =
- epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_multisample");
GDK_NOTE (OPENGL,
- g_print ("WGL API version %d.%d found\n"
+ g_print ("EGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Checked extensions:\n"
- "\t* WGL_ARB_pixel_format: %s\n"
- "\t* WGL_ARB_create_context: %s\n"
- "\t* WGL_EXT_swap_control: %s\n"
- "\t* WGL_OML_sync_control: %s\n"
- "\t* WGL_ARB_multisample: %s\n",
- display_win32->gl_version / 10,
- display_win32->gl_version % 10,
- glGetString (GL_VENDOR),
- display_win32->hasWglARBPixelFormat ? "yes" : "no",
- display_win32->hasWglARBCreateContext ? "yes" : "no",
- display_win32->hasWglEXTSwapControl ? "yes" : "no",
- display_win32->hasWglOMLSyncControl ? "yes" : "no",
- display_win32->hasWglARBmultisample ? "yes" : "no"));
-
- wglMakeCurrent (NULL, NULL);
- _destroy_dummy_gl_context (dummy);
+ "\t* EGL_KHR_surfaceless_context: %s\n",
+ display_win32->egl_version / 10,
+ display_win32->egl_version % 10,
+ eglQueryString (display_win32->egl_disp, EGL_VENDOR),
+ display_win32->hasEglSurfacelessContext ? "yes" : "no"));
return TRUE;
+#endif
}
/* Setup the legacy context after creating it */
@@ -688,6 +811,132 @@ _set_pixformat_for_hdc (HDC hdc,
return TRUE;
}
+#ifdef GDK_WIN32_ENABLE_EGL
+
+#define MAX_EGL_ATTRS 30
+
+static gboolean
+find_eglconfig_for_window (GdkWin32Display *display,
+ EGLConfig *egl_config_out,
+ EGLint *min_swap_interval_out,
+ gboolean need_alpha_bits,
+ GError **error)
+{
+ EGLint attrs[MAX_EGL_ATTRS];
+ EGLint count;
+ EGLConfig *configs, chosen_config;
+
+ int i = 0;
+
+ EGLDisplay egl_disp = display->egl_disp;
+
+ attrs[i++] = EGL_CONFORMANT;
+ attrs[i++] = EGL_OPENGL_ES2_BIT;
+ 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;
+
+ if (need_alpha_bits)
+ {
+ attrs[i++] = EGL_ALPHA_SIZE;
+ attrs[i++] = 1;
+ }
+ else
+ {
+ attrs[i++] = EGL_ALPHA_SIZE;
+ attrs[i++] = EGL_DONT_CARE;
+ }
+
+ attrs[i++] = EGL_NONE;
+ g_assert (i < MAX_EGL_ATTRS);
+
+ if (!eglChooseConfig (display->egl_disp, 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->egl_disp, 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? */
+ chosen_config = configs[0];
+
+ if (!eglGetConfigAttrib (display->egl_disp, chosen_config,
+ EGL_MIN_SWAP_INTERVAL, min_swap_interval_out))
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ "Could not retrieve the minimum swap interval");
+ g_free (configs);
+ return FALSE;
+ }
+
+ if (egl_config_out != NULL)
+ *egl_config_out = chosen_config;
+
+ g_free (configs);
+
+ return TRUE;
+}
+
+#define N_EGL_ATTRS 16
+
+static EGLContext
+_create_egl_context (EGLDisplay display,
+ EGLConfig config,
+ GdkGLContext *share,
+ int flags,
+ int major,
+ int minor,
+ gboolean *is_legacy)
+{
+ EGLContext ctx;
+ EGLint context_attribs[N_EGL_ATTRS];
+ int i = 0;
+
+ /* ANGLE does not support the GL_OES_vertex_array_object extension, so we need to use ES3 directly */
+ context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
+ context_attribs[i++] = 3;
+
+ /* Specify the flags */
+ context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
+ context_attribs[i++] = flags;
+
+ context_attribs[i++] = EGL_NONE;
+ g_assert (i < N_EGL_ATTRS);
+
+ ctx = eglCreateContext (display,
+ config,
+ share != NULL ? GDK_WIN32_GL_CONTEXT (share)->egl_context
+ : EGL_NO_CONTEXT,
+ context_attribs);
+
+ if (ctx != EGL_NO_CONTEXT)
+ GDK_NOTE (OPENGL, g_message ("Created EGL context[%p]", ctx));
+
+ return ctx;
+}
+#endif /* GDK_WIN32_ENABLE_EGL */
+
gboolean
_gdk_win32_gl_context_realize (GdkGLContext *context,
GError **error)
@@ -695,83 +944,143 @@ _gdk_win32_gl_context_realize (GdkGLContext *context,
GdkGLContext *share = gdk_gl_context_get_shared_context (context);
GdkWin32GLContext *context_win32 = GDK_WIN32_GL_CONTEXT (context);
+ /* These are the real WGL/EGL context items that we will want to use later */
+ gboolean debug_bit, compat_bit, legacy_bit;
+
/* These are the real WGL context items that we will want to use later */
HGLRC hglrc;
gint pixel_format;
- gboolean debug_bit, compat_bit, legacy_bit;
+ gboolean use_es = FALSE;
/* request flags and specific versions for core (3.2+) WGL context */
gint flags = 0;
- gint glver_major = 0;
- gint glver_minor = 0;
+ gint major = 0;
+ gint minor = 0;
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ EGLContext egl_context;
+#endif
GdkWindow *window = gdk_gl_context_get_window (context);
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (gdk_window_get_display (window));
- if (!_set_pixformat_for_hdc (context_win32->gl_hdc,
- &pixel_format,
- context_win32->need_alpha_bits,
- win32_display))
- {
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_UNSUPPORTED_FORMAT,
- _("No available configurations for the given pixel format"));
-
- return FALSE;
- }
-
- gdk_gl_context_get_required_version (context, &glver_major, &glver_minor);
- debug_bit = gdk_gl_context_get_debug_enabled (context);
- compat_bit = gdk_gl_context_get_forward_compatible (context);
-
- /* if there isn't wglCreateContextAttribsARB(), or if GDK_GL_LEGACY is set, we default to a legacy context */
- legacy_bit = !win32_display->hasWglARBCreateContext ||
- g_getenv ("GDK_GL_LEGACY") != NULL;
-
/*
* A legacy context cannot be shared with core profile ones, so this means we
* must stick to a legacy context if the shared context is a legacy context
*/
- if (share != NULL && gdk_gl_context_is_legacy (share))
+ if ((_gdk_gl_flags & GDK_GL_LEGACY) != 0 ||
+ share != NULL && gdk_gl_context_is_legacy (share))
legacy_bit = TRUE;
- if (debug_bit)
- flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
- if (compat_bit)
- flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ if ((_gdk_gl_flags & GDK_GL_GLES) != 0 ||
+ (share != NULL && gdk_gl_context_get_use_es (share)))
+ use_es = TRUE;
- GDK_NOTE (OPENGL,
- g_print ("Creating %s WGL context (version:%d.%d, debug:%s, forward:%s, legacy: %s)\n",
- compat_bit ? "core" : "compat",
- glver_major,
- glver_minor,
- debug_bit ? "yes" : "no",
- compat_bit ? "yes" : "no",
- legacy_bit ? "yes" : "no"));
-
- hglrc = _create_gl_context (context_win32->gl_hdc,
- share,
- flags,
- glver_major,
- glver_minor,
- &legacy_bit,
- win32_display->hasWglARBCreateContext);
-
- if (hglrc == NULL)
+ gdk_gl_context_get_required_version (context, &major, &minor);
+ debug_bit = gdk_gl_context_get_debug_enabled (context);
+ compat_bit = gdk_gl_context_get_forward_compatible (context);
+
+ if (win32_display->have_wgl)
{
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("Unable to create a GL context"));
- return FALSE;
+ if (!_set_pixformat_for_hdc (context_win32->gl_hdc,
+ &pixel_format,
+ context_win32->need_alpha_bits,
+ win32_display))
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_UNSUPPORTED_FORMAT,
+ _("No available configurations for the given pixel format"));
+
+ return FALSE;
+ }
+
+ /* if there isn't wglCreateContextAttribsARB(), or if GDK_GL_LEGACY is set, we default to a legacy context */
+ legacy_bit = !win32_display->hasWglARBCreateContext ||
+ g_getenv ("GDK_GL_LEGACY") != NULL;
+
+ if (debug_bit)
+ flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
+ if (compat_bit)
+ flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+
+ GDK_NOTE (OPENGL,
+ g_print ("Creating %s WGL context (version:%d.%d, debug:%s, forward:%s, legacy: %s)\n",
+ compat_bit ? "core" : "compat",
+ major,
+ minor,
+ debug_bit ? "yes" : "no",
+ compat_bit ? "yes" : "no",
+ legacy_bit ? "yes" : "no"));
+
+ hglrc = _create_gl_context (context_win32->gl_hdc,
+ share,
+ flags,
+ major,
+ minor,
+ &legacy_bit,
+ win32_display->hasWglARBCreateContext);
+
+ if (hglrc == NULL)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL context"));
+ return FALSE;
+ }
+
+ GDK_NOTE (OPENGL,
+ g_print ("Created WGL context[%p], pixel_format=%d\n",
+ hglrc,
+ pixel_format));
+
+ context_win32->hglrc = hglrc;
}
- GDK_NOTE (OPENGL,
- g_print ("Created WGL context[%p], pixel_format=%d\n",
- hglrc,
- pixel_format));
+#ifdef GDK_WIN32_ENABLE_EGL
+ if (win32_display->have_egl)
+ {
+ EGLContext ctx;
+
+ if (debug_bit)
+ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+ if (compat_bit)
+ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+
+ GDK_NOTE (OPENGL, g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s)",
+ major, minor,
+ debug_bit ? "yes" : "no",
+ compat_bit ? "yes" : "no",
+ legacy_bit ? "yes" : "no"));
+
+ ctx = _create_egl_context (win32_display->egl_disp,
+ context_win32->egl_config,
+ share,
+ flags,
+ major,
+ minor,
+ &legacy_bit);
+
+ if (ctx == EGL_NO_CONTEXT)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL context"));
+
+ return FALSE;
+ }
+
+ GDK_NOTE (OPENGL,
+ g_print ("Created EGL context[%p]\n",
+ ctx));
- context_win32->hglrc = hglrc;
+ context_win32->egl_context = ctx;
+ use_es = TRUE;
+ }
+#endif
+
+ /* set whether we are using GLES */
+ gdk_gl_context_set_use_es(context, use_es);
/* OpenGL does not work with WS_EX_LAYERED enabled, so we need to
* disable WS_EX_LAYERED when we acquire a valid HGLRC
@@ -804,9 +1113,21 @@ _gdk_win32_window_create_gl_context (GdkWindow *window,
gboolean need_alpha_bits = (visual == gdk_screen_get_rgba_visual (gdk_display_get_default_screen (display)));
/* Acquire and store up the Windows-specific HWND and HDC */
- HWND hwnd;
HDC hdc;
+#ifdef GDK_WIN32_ENABLE_EGL
+ EGLContext egl_context;
+ EGLConfig config;
+#endif
+
+ display_win32->gl_hwnd = GDK_WINDOW_HWND (window);
+ hdc = GetDC (display_win32->gl_hwnd);
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ /* display_win32->hdc_egl_temp should *not* be destroyed here! It is destroyed at dispose()! */
+ display_win32->hdc_egl_temp = hdc;
+#endif
+
if (!_gdk_win32_display_init_gl (display, need_alpha_bits))
{
g_set_error_literal (error, GDK_GL_ERROR,
@@ -815,10 +1136,12 @@ _gdk_win32_window_create_gl_context (GdkWindow *window,
return NULL;
}
- hwnd = GDK_WINDOW_HWND (window);
- hdc = GetDC (hwnd);
-
- display_win32->gl_hwnd = hwnd;
+#ifdef GDK_WIN32_ENABLE_EGL
+ if (display_win32->have_egl && !find_eglconfig_for_window (display_win32, &config,
+ &display_win32->egl_min_swap_interval, need_alpha_bits,
+ error))
+ return NULL;
+#endif
context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT,
"display", display,
@@ -828,6 +1151,12 @@ _gdk_win32_window_create_gl_context (GdkWindow *window,
context->need_alpha_bits = need_alpha_bits;
context->gl_hdc = hdc;
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ if (display_win32->have_egl)
+ context->egl_config = config;
+#endif
+
context->is_attached = attached;
return GDK_GL_CONTEXT (context);
@@ -842,44 +1171,88 @@ _gdk_win32_display_make_gl_context_current (GdkDisplay *display,
GdkWindow *window;
GdkScreen *screen;
+#if GDK_WIN32_ENABLE_EGL
+ EGLSurface egl_surface;
+#endif
+
gboolean do_frame_sync = FALSE;
if (context == NULL)
{
- wglMakeCurrent(NULL, NULL);
+ if (display_win32->have_wgl)
+ wglMakeCurrent(NULL, NULL);
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ else if (display_win32->have_egl)
+ eglMakeCurrent (display_win32->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+#endif
return TRUE;
}
context_win32 = GDK_WIN32_GL_CONTEXT (context);
+ window = gdk_gl_context_get_window (context);
- if (!wglMakeCurrent (context_win32->gl_hdc, context_win32->hglrc))
+ if (!gdk_gl_context_get_use_es (context))
{
- GDK_NOTE (OPENGL,
- g_print ("Making WGL context current failed\n"));
- return FALSE;
+ if (!wglMakeCurrent (context_win32->gl_hdc, context_win32->hglrc))
+ {
+ GDK_NOTE (OPENGL,
+ g_print ("Making WGL context current failed\n"));
+ return FALSE;
+ }
+
+ if (context_win32->is_attached)
+ {
+ if (display_win32->hasWglEXTSwapControl)
+ {
+ /* If there is compositing there is no particular need to delay
+ * the swap when drawing on the offscreen, rendering to the screen
+ * happens later anyway, and its up to the compositor to sync that
+ * to the vblank. */
+ screen = gdk_window_get_screen (window);
+ do_frame_sync = ! gdk_screen_is_composited (screen);
+
+ if (do_frame_sync != context_win32->do_frame_sync)
+ {
+ context_win32->do_frame_sync = do_frame_sync;
+
+ if (do_frame_sync)
+ wglSwapIntervalEXT (1);
+ else
+ wglSwapIntervalEXT (0);
+ }
+ }
+ }
}
- if (context_win32->is_attached && display_win32->hasWglEXTSwapControl)
+#ifdef GDK_WIN32_ENABLE_EGL
+ else
{
- window = gdk_gl_context_get_window (context);
-
- /* If there is compositing there is no particular need to delay
- * the swap when drawing on the offscreen, rendering to the screen
- * happens later anyway, and its up to the compositor to sync that
- * to the vblank. */
- screen = gdk_window_get_screen (window);
- do_frame_sync = ! gdk_screen_is_composited (screen);
-
- if (do_frame_sync != context_win32->do_frame_sync)
+ if (context_win32->is_attached)
+ egl_surface = _gdk_win32_window_get_egl_surface (window, context_win32->egl_config, FALSE);
+ else
{
- context_win32->do_frame_sync = do_frame_sync;
-
- if (do_frame_sync)
- wglSwapIntervalEXT (1);
+ if (display_win32->hasEglSurfacelessContext)
+ egl_surface = EGL_NO_SURFACE;
else
- wglSwapIntervalEXT (0);
+ egl_surface = _gdk_win32_window_get_egl_surface (window, context_win32->egl_config, TRUE);
}
+
+ if (!eglMakeCurrent (display_win32->egl_disp,
+ egl_surface,
+ egl_surface,
+ context_win32->egl_context))
+ {
+ g_warning ("eglMakeCurrent failed");
+ return FALSE;
+ }
+
+ if (display_win32->egl_min_swap_interval == 0)
+ eglSwapInterval (display_win32->egl_disp, 0);
+ else
+ g_debug ("Can't disable GL swap interval");
}
+#endif
return TRUE;
}
@@ -901,18 +1274,38 @@ gdk_win32_display_get_wgl_version (GdkDisplay *display,
gint *major,
gint *minor)
{
+ GdkWin32Display *display_win32 = NULL;
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
if (!GDK_IS_WIN32_DISPLAY (display))
return FALSE;
- if (!_gdk_win32_display_init_gl (display, FALSE))
+ display_win32 = GDK_WIN32_DISPLAY (display);
+
+ if (!_gdk_win32_display_init_gl (display, FALSE) || !display_win32->have_wgl
+#ifdef GDK_WIN32_ENABLE_EGL
+ || !display_win32->have_egl
+#endif
+ )
return FALSE;
- if (major != NULL)
- *major = GDK_WIN32_DISPLAY (display)->gl_version / 10;
- if (minor != NULL)
- *minor = GDK_WIN32_DISPLAY (display)->gl_version % 10;
+ if (display_win32->have_wgl)
+ {
+ if (major != NULL)
+ *major = GDK_WIN32_DISPLAY (display)->gl_version / 10;
+ if (minor != NULL)
+ *minor = GDK_WIN32_DISPLAY (display)->gl_version % 10;
+ }
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ else if (display_win32->have_egl)
+ {
+ if (major != NULL)
+ *major = GDK_WIN32_DISPLAY (display)->egl_version / 10;
+ if (minor != NULL)
+ *minor = GDK_WIN32_DISPLAY (display)->egl_version % 10;
+ }
+#endif
return TRUE;
}
diff --git a/gdk/win32/gdkglcontext-win32.h b/gdk/win32/gdkglcontext-win32.h
index b42cb9e220..f5535823f2 100644
--- a/gdk/win32/gdkglcontext-win32.h
+++ b/gdk/win32/gdkglcontext-win32.h
@@ -24,6 +24,10 @@
#include <epoxy/gl.h>
#include <epoxy/wgl.h>
+#ifdef GDK_WIN32_ENABLE_EGL
+# include <epoxy/egl.h>
+#endif
+
#include "gdkglcontextprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkvisual.h"
@@ -46,6 +50,12 @@ struct _GdkWin32GLContext
guint is_attached : 1;
guint do_frame_sync : 1;
guint do_blit_swap : 1;
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ /* EGL (Angle) Context Items */
+ EGLContext egl_context;
+ EGLConfig egl_config;
+#endif
};
struct _GdkWin32GLContextClass
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index ea510e4bd4..2fd6ef2c5c 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -1074,6 +1074,7 @@ gdk_win32_window_destroy (GdkWindow *window,
{
GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GSList *tmp;
+ GdkWin32Display *display = NULL;
g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1096,6 +1097,22 @@ gdk_win32_window_destroy (GdkWindow *window,
g_slist_free (window_impl->transient_children);
window_impl->transient_children = NULL;
+#ifdef GDK_WIN32_ENABLE_EGL
+ display = GDK_WIN32_DISPLAY (gdk_window_get_display (window));
+
+ /* Get rid of any EGLSurfaces that we might have created */
+ if (window_impl->egl_surface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface (display->egl_disp, window_impl->egl_surface);
+ window_impl->egl_surface = EGL_NO_SURFACE;
+ }
+ if (window_impl->egl_dummy_surface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface (display->egl_disp, window_impl->egl_dummy_surface);
+ window_impl->egl_dummy_surface = EGL_NO_SURFACE;
+ }
+#endif
+
/* Remove ourself from our transient owner */
if (window_impl->transient_owner != NULL)
{
@@ -6276,3 +6293,35 @@ gdk_win32_window_get_handle (GdkWindow *window)
return GDK_WINDOW_HWND (window);
}
+
+#ifdef GDK_WIN32_ENABLE_EGL
+EGLSurface
+_gdk_win32_window_get_egl_surface (GdkWindow *window,
+ EGLConfig config,
+ gboolean is_dummy)
+{
+ EGLSurface surface;
+ GdkWin32Display *display = GDK_WIN32_DISPLAY (gdk_window_get_display (window));
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+ if (is_dummy)
+ {
+ if (impl->egl_dummy_surface == EGL_NO_SURFACE)
+ {
+ EGLint attribs[] = {EGL_WIDTH, 1, EGL_WIDTH, 1, EGL_NONE};
+ impl->egl_dummy_surface = eglCreatePbufferSurface (display->egl_disp,
+ config,
+ attribs);
+ }
+ return impl->egl_dummy_surface;
+ }
+ else
+ {
+ if (impl->egl_surface == EGL_NO_SURFACE)
+ impl->egl_surface = eglCreateWindowSurface (display->egl_disp, config, display->gl_hwnd, NULL);
+
+ return impl->egl_surface;
+ }
+
+}
+#endif
diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h
index 59b9a42c39..a5e837ec8d 100644
--- a/gdk/win32/gdkwindow-win32.h
+++ b/gdk/win32/gdkwindow-win32.h
@@ -31,6 +31,10 @@
#include <windows.h>
+#ifdef GDK_WIN32_ENABLE_EGL
+#include <epoxy/egl.h>
+#endif
+
G_BEGIN_DECLS
/* Window implementation for Win32
@@ -352,6 +356,11 @@ struct _GdkWindowImplWin32
gint window_scale;
gint unscaled_width;
gint unscaled_height;
+
+#ifdef GDK_WIN32_ENABLE_EGL
+ EGLSurface egl_surface;
+ EGLSurface egl_dummy_surface;
+#endif
};
struct _GdkWindowImplWin32Class
@@ -373,6 +382,12 @@ void _gdk_win32_window_update_style_bits (GdkWindow *window);
gint _gdk_win32_window_get_scale_factor (GdkWindow *window);
+#ifdef GDK_WIN32_ENABLE_EGL
+EGLSurface _gdk_win32_window_get_egl_surface (GdkWindow *window,
+ EGLConfig config,
+ gboolean is_dummy);
+#endif
+
G_END_DECLS
#endif /* __GDK_WINDOW_WIN32_H__ */