This commit is contained in:
ewtoombs 2019-12-09 19:03:20 -08:00 committed by GitHub
commit ee341ee061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 144 additions and 0 deletions

View File

@ -413,6 +413,31 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
* @ingroup native * @ingroup native
*/ */
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
/*! @brief Check to see if the Wayland server supports the presentation-time
* protocol.
*
* @return GLFW_TRUE iff presentation-time is supported.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwWaylandPresSupported(void);
/*! @brief Swap the buffers, then use the Wayland presentation-time protocol to
* wait for the new frame to be presented. GLFW window events are processed for
* the whole time this function waits for the frame to be presented.
*
* @return The presentation time of the frame, with respect to the same time
* measure glfwGetTime() uses, or 0.0 if the frame was not shown due to a
* vblank miss.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI double glfwWaylandSwapPres(GLFWwindow* window);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_EGL) #if defined(GLFW_EXPOSE_NATIVE_EGL)

View File

@ -55,6 +55,10 @@ elseif (_GLFW_WAYLAND)
PROTOCOL PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" "${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
BASENAME idle-inhibit-unstable-v1) BASENAME idle-inhibit-unstable-v1)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/presentation-time/presentation-time.xml"
BASENAME presentation-time)
elseif (_GLFW_OSMESA) elseif (_GLFW_OSMESA)
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
posix_time.h posix_thread.h osmesa_context.h) posix_time.h posix_thread.h osmesa_context.h)

View File

@ -777,12 +777,28 @@ static const struct xdg_wm_base_listener wmBaseListener = {
wmBaseHandlePing wmBaseHandlePing
}; };
static void
presSetClockId(void *data, struct wp_presentation *pres, uint32_t clockId)
{
if (clockId == CLOCK_MONOTONIC)
{
// TODO: support for clocks other than CLOCK_MONOTONIC.
_glfw.wl.pres = pres;
}
}
static const struct wp_presentation_listener presListener = {
presSetClockId
};
static void registryHandleGlobal(void* data, static void registryHandleGlobal(void* data,
struct wl_registry* registry, struct wl_registry* registry,
uint32_t name, uint32_t name,
const char* interface, const char* interface,
uint32_t version) uint32_t version)
{ {
struct wp_presentation* pres;
if (strcmp(interface, "wl_compositor") == 0) if (strcmp(interface, "wl_compositor") == 0)
{ {
_glfw.wl.compositorVersion = min(3, version); _glfw.wl.compositorVersion = min(3, version);
@ -863,6 +879,13 @@ static void registryHandleGlobal(void* data,
&zwp_idle_inhibit_manager_v1_interface, &zwp_idle_inhibit_manager_v1_interface,
1); 1);
} }
else if (strcmp(interface, wp_presentation_interface.name) == 0)
{
pres = wl_registry_bind(registry, name,
&wp_presentation_interface,
1);
wp_presentation_add_listener(pres, &presListener, NULL);
}
} }
static void registryHandleGlobalRemove(void *data, static void registryHandleGlobalRemove(void *data,

View File

@ -62,6 +62,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" #include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
#include "wayland-presentation-time-client-protocol.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
@ -216,6 +217,9 @@ typedef struct _GLFWwindowWayland
int focus; int focus;
} decorations; } decorations;
GLFWbool presWaiting;
double presTime;
} _GLFWwindowWayland; } _GLFWwindowWayland;
// Wayland-specific global data // Wayland-specific global data
@ -324,6 +328,8 @@ typedef struct _GLFWlibraryWayland
PFN_wl_egl_window_resize window_resize; PFN_wl_egl_window_resize window_resize;
} egl; } egl;
struct wp_presentation* pres;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data

View File

@ -39,6 +39,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <poll.h> #include <poll.h>
#include <assert.h>
static int createTmpfileCloexec(char* tmpname) static int createTmpfileCloexec(char* tmpname)
@ -826,6 +827,13 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
window->wl.monitorsCount = 0; window->wl.monitorsCount = 0;
window->wl.monitorsSize = 1; window->wl.monitorsSize = 1;
if (_glfw.wl.pres)
{
window->wl.presWaiting = GLFW_FALSE;
// Tell the user we missed the first vblank.
window->wl.presTime = 0.;
}
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -1752,3 +1760,81 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)
return window->wl.surface; return window->wl.surface;
} }
static void feedbackSyncOutput(void* data,
struct wp_presentation_feedback* fback,
struct wl_output* output)
{
}
static void feedbackPresented(void* data,
struct wp_presentation_feedback* fback,
uint32_t tvSecHi,
uint32_t tvSecLo,
uint32_t tvNsec,
uint32_t refreshNsec,
uint32_t seqHi,
uint32_t seqLo,
uint32_t flags)
{
_GLFWwindow* window;
uint64_t sec;
uint64_t nsec;
window = (_GLFWwindow*) data;
window->wl.presWaiting = GLFW_FALSE;
sec = (uint64_t) tvSecLo + ((uint64_t) tvSecHi << 32);
nsec = sec * 1000000000 + (uint64_t) tvNsec;
window->wl.presTime = (double) (nsec - _glfw.timer.offset) * 1e-9;
wp_presentation_feedback_destroy(fback);
}
static void feedbackDiscarded(void* data,
struct wp_presentation_feedback* fback)
{
_GLFWwindow* window = (_GLFWwindow*) data;
window->wl.presWaiting = GLFW_FALSE;
window->wl.presTime = 0.;
wp_presentation_feedback_destroy(fback);
}
static const struct wp_presentation_feedback_listener feedbackListener = {
feedbackSyncOutput,
feedbackPresented,
feedbackDiscarded
};
GLFWAPI int glfwWaylandPresSupported(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
return _glfw.wl.pres != NULL;
}
GLFWAPI double glfwWaylandSwapPres(GLFWwindow* handle)
{
_GLFWwindow* window;
struct wp_presentation_feedback* fback;
_GLFW_REQUIRE_INIT_OR_RETURN(0.);
assert(handle);
assert(_glfw.wl.pres);
window = (_GLFWwindow*) handle;
glfwSwapBuffers(handle);
while (window->wl.presWaiting)
{
handleEvents(-1);
}
window->wl.presWaiting = GLFW_TRUE;
fback = wp_presentation_feedback(_glfw.wl.pres, window->wl.surface);
wp_presentation_feedback_add_listener(fback, &feedbackListener, window);
return window->wl.presTime;
}