summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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__ */