mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-30 15:31:34 +00:00
Merge branch 'wip/master.win.egl' into 'master'
Add an EGL (OpenGL/ES 3) renderer for GTK+-4.x (using Google's ANGLE project) for Windows Closes #105 See merge request GNOME/gtk!215
This commit is contained in:
commit
0ee3370afc
@ -1,7 +1,7 @@
|
||||
precision highp float;
|
||||
|
||||
void main() {
|
||||
float lerpVal = gl_FragCoord.y / 500.0f;
|
||||
float lerpVal = gl_FragCoord.y / 500.0;
|
||||
|
||||
gl_FragColor = mix(vec4(1.0f, 0.85f, 0.35f, 1.0f), vec4(0.2f, 0.2f, 0.2f, 1.0f), lerpVal);
|
||||
gl_FragColor = mix(vec4(1.0, 0.85, 0.35, 1.0), vec4(0.2, 0.2, 0.2, 1.0), lerpVal);
|
||||
}
|
||||
|
@ -334,6 +334,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
cairo_region_t *clip_region;
|
||||
GdkGLContextPaintData *paint_data;
|
||||
int major, minor, version;
|
||||
gboolean es_use_bgra = FALSE;
|
||||
|
||||
paint_context = gdk_surface_get_paint_gl_context (surface, NULL);
|
||||
if (paint_context == NULL)
|
||||
@ -343,6 +344,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
}
|
||||
|
||||
clip_region = gdk_cairo_region_from_clip (cr);
|
||||
es_use_bgra = gdk_gl_context_use_es_bgra (paint_context);
|
||||
|
||||
gdk_gl_context_make_current (paint_context);
|
||||
paint_data = gdk_gl_context_get_paint_data (paint_context);
|
||||
@ -413,7 +415,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_use_bgra ? GL_BGRA : GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
cairo_image_surface_get_data (image));
|
||||
|
||||
glPixelStorei (GL_PACK_ROW_LENGTH, 0);
|
||||
|
@ -92,6 +92,10 @@
|
||||
#include "gdkintl.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
# include "gdk/win32/gdkwin32.h"
|
||||
#endif
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct {
|
||||
@ -993,11 +997,14 @@ 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;
|
||||
priv->has_gl_framebuffer_blit = epoxy_has_gl_extension ("GL_ANGLE_framebuffer_blit");
|
||||
|
||||
/* No OES version */
|
||||
priv->has_frame_terminator = FALSE;
|
||||
@ -1223,3 +1230,19 @@ gdk_gl_context_has_debug (GdkGLContext *self)
|
||||
|
||||
return priv->debug_enabled || priv->use_khr_debug;
|
||||
}
|
||||
|
||||
/* This is currently private! */
|
||||
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
|
||||
gboolean
|
||||
gdk_gl_context_use_es_bgra (GdkGLContext *context)
|
||||
{
|
||||
if (!gdk_gl_context_get_use_es (context))
|
||||
return FALSE;
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_WIN32_IS_GL_CONTEXT (context))
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -107,6 +107,9 @@ void gdk_gl_context_label_object_printf (GdkGLContext
|
||||
...) G_GNUC_PRINTF (4, 5);
|
||||
|
||||
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
|
||||
|
||||
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_GL_CONTEXT_PRIVATE_H__ */
|
||||
|
@ -39,6 +39,13 @@
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include "gdkwin32langnotification.h"
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
# include <epoxy/egl.h>
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_FILE_MACHINE_ARM64
|
||||
# define IMAGE_FILE_MACHINE_ARM64 0xAA64
|
||||
#endif
|
||||
|
||||
static int debug_indent = 0;
|
||||
|
||||
@ -641,6 +648,14 @@ gdk_win32_display_dispose (GObject *object)
|
||||
{
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (object);
|
||||
|
||||
#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);
|
||||
@ -869,6 +884,40 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_win32_check_on_arm64 (GdkWin32Display *display)
|
||||
{
|
||||
static gsize checked = 0;
|
||||
|
||||
if (g_once_init_enter (&checked))
|
||||
{
|
||||
HMODULE kernel32 = LoadLibraryW (L"kernel32.dll");
|
||||
|
||||
if (kernel32 != NULL)
|
||||
{
|
||||
display->cpu_funcs.isWow64Process2 =
|
||||
(funcIsWow64Process2) GetProcAddress (kernel32, "IsWow64Process2");
|
||||
|
||||
if (display->cpu_funcs.isWow64Process2 != NULL)
|
||||
{
|
||||
USHORT proc_cpu = 0;
|
||||
USHORT native_cpu = 0;
|
||||
|
||||
display->cpu_funcs.isWow64Process2 (GetCurrentProcess (),
|
||||
&proc_cpu,
|
||||
&native_cpu);
|
||||
|
||||
if (native_cpu == IMAGE_FILE_MACHINE_ARM64)
|
||||
display->running_on_arm64 = TRUE;
|
||||
}
|
||||
|
||||
FreeLibrary (kernel32);
|
||||
}
|
||||
|
||||
g_once_init_leave (&checked, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_display_init (GdkWin32Display *display)
|
||||
{
|
||||
@ -877,6 +926,7 @@ gdk_win32_display_init (GdkWin32Display *display)
|
||||
display->monitors = G_LIST_MODEL (g_list_store_new (GDK_TYPE_MONITOR));
|
||||
|
||||
_gdk_win32_enable_hidpi (display);
|
||||
_gdk_win32_check_on_arm64 (display);
|
||||
|
||||
/* if we have DPI awareness, set up fixed scale if set */
|
||||
if (display->dpi_aware_type != PROCESS_DPI_UNAWARE &&
|
||||
|
@ -24,6 +24,10 @@
|
||||
|
||||
#include "gdkwin32screen.h"
|
||||
#include "gdkwin32cursor.h"
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
# include <epoxy/egl.h>
|
||||
#endif
|
||||
|
||||
/* Define values used to set DPI-awareness */
|
||||
typedef enum _GdkWin32ProcessDpiAwareness {
|
||||
@ -65,6 +69,13 @@ typedef struct _GdkWin32User32DPIFuncs
|
||||
funcIsProcessDPIAware isDpiAwareFunc;
|
||||
} GdkWin32User32DPIFuncs;
|
||||
|
||||
/* Detect running architecture */
|
||||
typedef BOOL (WINAPI *funcIsWow64Process2) (HANDLE, USHORT *, USHORT *);
|
||||
typedef struct _GdkWin32KernelCPUFuncs
|
||||
{
|
||||
funcIsWow64Process2 isWow64Process2;
|
||||
} GdkWin32KernelCPUFuncs;
|
||||
|
||||
struct _GdkWin32Display
|
||||
{
|
||||
GdkDisplay display;
|
||||
@ -82,6 +93,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
|
||||
|
||||
GListModel *monitors;
|
||||
|
||||
guint hasWglARBCreateContext : 1;
|
||||
@ -90,6 +109,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;
|
||||
@ -113,6 +138,10 @@ struct _GdkWin32Display
|
||||
|
||||
/* Message filters */
|
||||
GList *filters;
|
||||
|
||||
/* Running CPU items */
|
||||
guint running_on_arm64 : 1;
|
||||
GdkWin32KernelCPUFuncs cpu_funcs;
|
||||
};
|
||||
|
||||
struct _GdkWin32DisplayClass
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdkwin32.h"
|
||||
#include "gdkkeysyms.h"
|
||||
#include "gdkglcontext-win32.h"
|
||||
#include "gdkdevicemanager-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
@ -2945,7 +2946,11 @@ gdk_event_translate (MSG *msg,
|
||||
{
|
||||
case SC_MINIMIZE:
|
||||
case SC_RESTORE:
|
||||
do_show_window (window, msg->wParam == SC_MINIMIZE ? TRUE : FALSE);
|
||||
do_show_window (window, msg->wParam == SC_MINIMIZE ? TRUE : FALSE);
|
||||
|
||||
if (msg->wParam == SC_RESTORE)
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (window);
|
||||
|
||||
break;
|
||||
case SC_MAXIMIZE:
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
@ -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
|
||||
@ -51,17 +55,37 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context));
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (context_win32->hglrc != NULL)
|
||||
if (display_win32 != NULL)
|
||||
{
|
||||
if (wglGetCurrentContext () == context_win32->hglrc)
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
if (display_win32->have_wgl)
|
||||
{
|
||||
if (wglGetCurrentContext () == context_win32->hglrc)
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
|
||||
GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
|
||||
GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
|
||||
|
||||
wglDeleteContext (context_win32->hglrc);
|
||||
context_win32->hglrc = NULL;
|
||||
wglDeleteContext (context_win32->hglrc);
|
||||
context_win32->hglrc = NULL;
|
||||
|
||||
ReleaseDC (display_win32->gl_hwnd, context_win32->gl_hdc);
|
||||
ReleaseDC (display_win32->gl_hwnd, context_win32->gl_hdc);
|
||||
}
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
else if (display_win32->have_egl)
|
||||
{
|
||||
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;
|
||||
|
||||
ReleaseDC (display_win32->gl_hwnd, context_win32->gl_hdc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (surface != NULL)
|
||||
@ -77,7 +101,6 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
|
||||
if (impl->suppress_layered == 0)
|
||||
_gdk_win32_surface_update_style_bits (surface);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@ -100,6 +123,33 @@ gdk_gl_blit_region (GdkSurface *surface, cairo_region_t *region)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
static gboolean
|
||||
_get_is_egl_force_redraw (GdkSurface *surface)
|
||||
{
|
||||
/* We only need to call gdk_window_invalidate_rect () if necessary */
|
||||
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
return impl->egl_force_redraw_all;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_reset_egl_force_redraw (GdkSurface *surface)
|
||||
{
|
||||
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
if (impl->egl_force_redraw_all)
|
||||
impl->egl_force_redraw_all = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
@ -108,7 +158,6 @@ gdk_win32_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
GdkWin32GLContext *context_win32 = GDK_WIN32_GL_CONTEXT (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkWin32Display *display = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
|
||||
gboolean can_wait = display->hasWglOMLSyncControl;
|
||||
cairo_rectangle_int_t whole_window;
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_parent_class)->end_frame (draw_context, painted);
|
||||
@ -116,9 +165,12 @@ gdk_win32_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
whole_window = (GdkRectangle) { 0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface) };
|
||||
|
||||
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 ();
|
||||
@ -135,29 +187,54 @@ gdk_win32_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
&ust, &msc, &sbc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
whole_window = (GdkRectangle) { 0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface) };
|
||||
if (cairo_region_contains_rectangle (painted, &whole_window) == CAIRO_REGION_OVERLAP_IN)
|
||||
{
|
||||
SwapBuffers (context_win32->gl_hdc);
|
||||
}
|
||||
else if (gdk_gl_context_has_framebuffer_blit (context))
|
||||
{
|
||||
glDrawBuffer(GL_FRONT);
|
||||
glReadBuffer(GL_BACK);
|
||||
gdk_gl_blit_region (surface, painted);
|
||||
glDrawBuffer(GL_BACK);
|
||||
glFlush();
|
||||
if (cairo_region_contains_rectangle (painted, &whole_window) == CAIRO_REGION_OVERLAP_IN)
|
||||
SwapBuffers (context_win32->gl_hdc);
|
||||
else if (gdk_gl_context_has_framebuffer_blit (context))
|
||||
{
|
||||
glDrawBuffer(GL_FRONT);
|
||||
glReadBuffer(GL_BACK);
|
||||
gdk_gl_blit_region (surface, painted);
|
||||
glDrawBuffer(GL_BACK);
|
||||
glFlush();
|
||||
|
||||
if (gdk_gl_context_has_frame_terminator (context))
|
||||
glFrameTerminatorGREMEDY ();
|
||||
if (gdk_gl_context_has_frame_terminator (context))
|
||||
glFrameTerminatorGREMEDY ();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Need to swap whole buffer even thouigh not everything was redrawn. Expect artifacts.");
|
||||
SwapBuffers (context_win32->gl_hdc);
|
||||
}
|
||||
}
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
else
|
||||
{
|
||||
g_warning ("Need to swap whole buffer even thouigh not everything was redrawn. Expect artifacts.");
|
||||
SwapBuffers (context_win32->gl_hdc);
|
||||
EGLSurface egl_surface = _gdk_win32_surface_get_egl_surface (surface, context_win32->egl_config, FALSE);
|
||||
gboolean force_egl_redraw_all = _get_is_egl_force_redraw (surface);
|
||||
|
||||
if (force_egl_redraw_all)
|
||||
{
|
||||
GdkRectangle rect = {0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface)};
|
||||
|
||||
/* We need to do gdk_window_invalidate_rect() so that we don't get glitches after maximizing or
|
||||
* restoring or using aerosnap
|
||||
*/
|
||||
gdk_surface_invalidate_rect (surface, &rect);
|
||||
_reset_egl_force_redraw (surface);
|
||||
}
|
||||
|
||||
if (cairo_region_contains_rectangle (painted, &whole_window) == CAIRO_REGION_OVERLAP_IN || force_egl_redraw_all)
|
||||
eglSwapBuffers (display->egl_disp, egl_surface);
|
||||
else if (gdk_gl_context_has_framebuffer_blit (context))
|
||||
gdk_gl_blit_region (surface, painted);
|
||||
else
|
||||
{
|
||||
g_warning ("Need to swap whole buffer even thouigh not everything was redrawn. Expect artifacts.");
|
||||
eglSwapBuffers (display->egl_disp, egl_surface);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -415,61 +492,151 @@ _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)
|
||||
{
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
int 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_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
|
||||
display_win32->running_on_arm64;
|
||||
#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)
|
||||
{
|
||||
GdkWGLDummy dummy;
|
||||
memset (&dummy, 0, sizeof (GdkWGLDummy));
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
|
||||
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->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");
|
||||
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"
|
||||
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);
|
||||
_destroy_dummy_gl_context (dummy);
|
||||
}
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
else
|
||||
{
|
||||
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");
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
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"));
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -649,6 +816,122 @@ _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,
|
||||
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;
|
||||
attrs[i++] = EGL_ALPHA_SIZE;
|
||||
attrs[i++] = 1;
|
||||
|
||||
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 */
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_realize (GdkGLContext *context,
|
||||
GError **error)
|
||||
@ -656,39 +939,23 @@ 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 context items that we will want to use later */
|
||||
HGLRC hglrc;
|
||||
int pixel_format;
|
||||
gboolean debug_bit, compat_bit, legacy_bit;
|
||||
gboolean use_es = FALSE;
|
||||
|
||||
/* request flags and specific versions for core (3.2+) WGL context */
|
||||
int flags = 0;
|
||||
int glver_major = 0;
|
||||
int glver_minor = 0;
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
|
||||
|
||||
if (!_set_pixformat_for_hdc (context_win32->gl_hdc,
|
||||
&pixel_format,
|
||||
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);
|
||||
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 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
|
||||
@ -696,42 +963,114 @@ gdk_win32_gl_context_realize (GdkGLContext *context,
|
||||
if (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_LEGACY is set, we default to a legacy context */
|
||||
legacy_bit = g_getenv ("GDK_GL_LEGACY") != NULL;
|
||||
|
||||
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"));
|
||||
use_es = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
|
||||
(share != NULL && gdk_gl_context_get_use_es (share));
|
||||
|
||||
hglrc = _create_gl_context (context_win32->gl_hdc,
|
||||
share,
|
||||
flags,
|
||||
glver_major,
|
||||
glver_minor,
|
||||
&legacy_bit,
|
||||
win32_display->hasWglARBCreateContext);
|
||||
|
||||
if (hglrc == NULL)
|
||||
if (win32_display->have_wgl || !use_es)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return FALSE;
|
||||
/* These are the real WGL context items that we will want to use later */
|
||||
HGLRC hglrc;
|
||||
int pixel_format;
|
||||
|
||||
if (!_set_pixformat_for_hdc (context_win32->gl_hdc,
|
||||
&pixel_format,
|
||||
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() on WGL, use a legacy context */
|
||||
if (!legacy_bit)
|
||||
legacy_bit = !win32_display->hasWglARBCreateContext;
|
||||
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
|
||||
else
|
||||
{
|
||||
EGLContext egl_context;
|
||||
EGLContext ctx;
|
||||
|
||||
context_win32->hglrc = hglrc;
|
||||
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->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
|
||||
@ -781,9 +1120,22 @@ _gdk_win32_surface_create_gl_context (GdkSurface *surface,
|
||||
GdkWin32GLContext *context = NULL;
|
||||
|
||||
/* Acquire and store up the Windows-specific HWND and HDC */
|
||||
HWND hwnd;
|
||||
/* HWND hwnd;*/
|
||||
HDC hdc;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLContext egl_context;
|
||||
EGLConfig config;
|
||||
#endif
|
||||
|
||||
display_win32->gl_hwnd = GDK_SURFACE_HWND (surface);
|
||||
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))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
@ -792,10 +1144,21 @@ _gdk_win32_surface_create_gl_context (GdkSurface *surface,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hwnd = GDK_SURFACE_HWND (surface);
|
||||
hdc = GetDC (hwnd);
|
||||
#if 0
|
||||
if (display_win32->have_wgl)
|
||||
{
|
||||
hwnd = GDK_SURFACE_HWND (surface);
|
||||
hdc = GetDC (hwnd);
|
||||
|
||||
display_win32->gl_hwnd = hwnd;
|
||||
display_win32->gl_hwnd = hwnd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (display_win32->have_egl && !find_eglconfig_for_window (display_win32, &config,
|
||||
&display_win32->egl_min_swap_interval, error))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT,
|
||||
"surface", surface,
|
||||
@ -805,6 +1168,11 @@ _gdk_win32_surface_create_gl_context (GdkSurface *surface,
|
||||
context->gl_hdc = hdc;
|
||||
context->is_attached = attached;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (display_win32->have_egl)
|
||||
context->egl_config = config;
|
||||
#endif
|
||||
|
||||
return GDK_GL_CONTEXT (context);
|
||||
}
|
||||
|
||||
@ -820,41 +1188,86 @@ _gdk_win32_display_make_gl_context_current (GdkDisplay *display,
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (display_win32->egl_disp != EGL_NO_DISPLAY)
|
||||
eglMakeCurrent(display_win32->egl_disp,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
else
|
||||
#endif
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
context_win32 = GDK_WIN32_GL_CONTEXT (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 (context_win32->is_attached && display_win32->hasWglEXTSwapControl)
|
||||
{
|
||||
surface = gdk_gl_context_get_surface (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. */
|
||||
display = gdk_surface_get_display (surface);
|
||||
do_frame_sync = ! gdk_display_is_composited (display);
|
||||
|
||||
if (do_frame_sync != context_win32->do_frame_sync)
|
||||
if (!wglMakeCurrent (context_win32->gl_hdc, context_win32->hglrc))
|
||||
{
|
||||
context_win32->do_frame_sync = do_frame_sync;
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("Making WGL context current failed\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (do_frame_sync)
|
||||
wglSwapIntervalEXT (1);
|
||||
else
|
||||
wglSwapIntervalEXT (0);
|
||||
if (context_win32->is_attached && display_win32->hasWglEXTSwapControl)
|
||||
{
|
||||
surface = gdk_gl_context_get_surface (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. */
|
||||
display = gdk_surface_get_display (surface);
|
||||
do_frame_sync = ! gdk_display_is_composited (display);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
else
|
||||
{
|
||||
EGLSurface egl_surface;
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (context_win32->is_attached)
|
||||
egl_surface = _gdk_win32_surface_get_egl_surface (surface, context_win32->egl_config, FALSE);
|
||||
else
|
||||
{
|
||||
if (display_win32->hasEglSurfacelessContext)
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
else
|
||||
egl_surface = _gdk_win32_surface_get_egl_surface (surface, 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;
|
||||
}
|
||||
|
||||
@ -888,3 +1301,20 @@ gdk_win32_display_get_wgl_version (GdkDisplay *display,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface)
|
||||
{
|
||||
/* If we are using ANGLE, we need to force redraw of the whole Window and its child windows
|
||||
* as we need to re-acquire the EGL surfaces that we rendered to upload to Cairo explicitly,
|
||||
* using gdk_window_invalidate_rect (), when we maximize or restore or use aerosnap
|
||||
*/
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
impl->egl_force_redraw_all = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -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 "gdksurface.h"
|
||||
@ -43,6 +47,12 @@ struct _GdkWin32GLContext
|
||||
/* other items */
|
||||
guint is_attached : 1;
|
||||
guint do_frame_sync : 1;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
/* EGL (Angle) Context Items */
|
||||
EGLContext egl_context;
|
||||
EGLConfig egl_config;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _GdkWin32GLContextClass
|
||||
@ -59,6 +69,8 @@ _gdk_win32_surface_create_gl_context (GdkSurface *window,
|
||||
gboolean
|
||||
_gdk_win32_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
void
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -711,6 +711,22 @@ gdk_win32_surface_destroy (GdkSurface *window,
|
||||
gdk_win32_surface_set_transient_for (child, NULL);
|
||||
}
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
GdkWin32Display *display = GDK_WIN32_DISPLAY (gdk_surface_get_display (window));
|
||||
|
||||
/* Get rid of any EGLSurfaces that we might have created */
|
||||
if (surface->egl_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface (display->egl_disp, surface->egl_surface);
|
||||
surface->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
if (surface->egl_dummy_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface (display->egl_disp, surface->egl_dummy_surface);
|
||||
surface->egl_dummy_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Remove ourself from our transient owner */
|
||||
if (surface->transient_owner != NULL)
|
||||
{
|
||||
@ -1253,14 +1269,16 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (window);
|
||||
|
||||
if (with_move)
|
||||
{
|
||||
{
|
||||
gdk_win32_surface_do_move_resize (window, x, y, width, height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_win32_surface_resize (window, width, height);
|
||||
}
|
||||
{
|
||||
gdk_win32_surface_resize (window, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@ -3809,6 +3827,9 @@ gdk_win32_surface_end_move_resize_drag (GdkSurface *window)
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (window);
|
||||
GdkW32DragMoveResizeContext *context = &impl->drag_move_resize_context;
|
||||
|
||||
if (context->op == GDK_WIN32_DRAGOP_RESIZE)
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (window);
|
||||
|
||||
context->op = GDK_WIN32_DRAGOP_NONE;
|
||||
|
||||
@ -4286,6 +4307,8 @@ gdk_win32_surface_unmaximize (GdkSurface *window)
|
||||
GDK_SURFACE_HWND (window),
|
||||
_gdk_win32_surface_state_to_string (window->state)));
|
||||
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (window);
|
||||
|
||||
if (GDK_SURFACE_IS_MAPPED (window))
|
||||
GtkShowWindow (window, SW_RESTORE);
|
||||
else
|
||||
@ -4362,6 +4385,7 @@ gdk_win32_surface_unfullscreen (GdkSurface *window)
|
||||
|
||||
impl->hint_flags = fi->hint_flags;
|
||||
SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE, fi->style);
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (window);
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_NOTOPMOST,
|
||||
fi->r.left, fi->r.top,
|
||||
fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
|
||||
@ -5140,3 +5164,34 @@ gdk_win32_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
|
||||
{
|
||||
iface->present = gdk_win32_drag_surface_present;
|
||||
}
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLSurface
|
||||
_gdk_win32_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config,
|
||||
gboolean is_dummy)
|
||||
{
|
||||
GdkWin32Display *display = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
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
|
||||
|
@ -34,6 +34,10 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
# include <epoxy/egl.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
@ -351,6 +355,12 @@ struct _GdkWin32Surface
|
||||
int surface_scale;
|
||||
int unscaled_width;
|
||||
int unscaled_height;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLSurface egl_surface;
|
||||
EGLSurface egl_dummy_surface;
|
||||
guint egl_force_redraw_all : 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _GdkWin32SurfaceClass
|
||||
@ -392,6 +402,12 @@ void
|
||||
gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
|
||||
RECT window_rect);
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLSurface _gdk_win32_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config,
|
||||
gboolean is_dummy);
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_SURFACE_WIN32_H__ */
|
||||
|
@ -43,6 +43,12 @@ gdk_win32_public_headers = files([
|
||||
|
||||
install_headers(gdk_win32_public_headers, 'gdkwin32.h', subdir: 'gtk-4.0/gdk/win32/')
|
||||
|
||||
GDK_WIN32_EGL_CFLAGS = []
|
||||
|
||||
if win32_has_egl
|
||||
GDK_WIN32_EGL_CFLAGS = ['-DGDK_WIN32_ENABLE_EGL']
|
||||
endif
|
||||
|
||||
gdk_win32_deps = [ # FIXME
|
||||
pangowin32_dep
|
||||
]
|
||||
@ -50,5 +56,5 @@ gdk_win32_deps = [ # FIXME
|
||||
libgdk_win32 = static_library('gdk-win32',
|
||||
gdk_win32_sources, gdkconfig, gdkenum_h,
|
||||
include_directories: [confinc, gdkinc],
|
||||
c_args: ['-DGTK_COMPILATION', '-DG_LOG_DOMAIN="Gdk"', '-DINSIDE_GDK_WIN32'],
|
||||
c_args: ['-DGTK_COMPILATION', '-DG_LOG_DOMAIN="Gdk"', '-DINSIDE_GDK_WIN32'] + GDK_WIN32_EGL_CFLAGS,
|
||||
dependencies: [gdk_deps, gdk_win32_deps])
|
||||
|
16
meson.build
16
meson.build
@ -607,6 +607,22 @@ if win32_enabled
|
||||
endif
|
||||
pc_gdk_extra_libs += ['-lwinmm', '-ldwmapi', '-lsetupapi', '-lcfgmgr32']
|
||||
backend_immodules += ['ime']
|
||||
|
||||
# Check whether libepoxy is built with EGL support on Windows
|
||||
win32_has_egl = cc.links(
|
||||
'''
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
EGLDisplay disp = EGL_NO_DISPLAY;
|
||||
|
||||
return epoxy_egl_version (disp);
|
||||
}
|
||||
''',
|
||||
dependencies : epoxy_dep,
|
||||
name : 'libepoxy supports EGL on Windows'
|
||||
)
|
||||
endif
|
||||
|
||||
# Check for bind_textdomain_codeset, including -lintl if GLib brings it in by
|
||||
|
Loading…
Reference in New Issue
Block a user