mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-24 22:37:19 +00:00
128 lines
3.4 KiB
C
128 lines
3.4 KiB
C
/**
|
|
* Looking Glass
|
|
* Copyright © 2017-2023 The Looking Glass Authors
|
|
* https://looking-glass.io
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include "wayland.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <wayland-client.h>
|
|
|
|
#include "common/debug.h"
|
|
#include "common/time.h"
|
|
|
|
struct FrameData
|
|
{
|
|
struct timespec sent;
|
|
};
|
|
|
|
static void presentationClockId(void * data,
|
|
struct wp_presentation * presentation, uint32_t clkId)
|
|
{
|
|
wlWm.clkId = clkId;
|
|
}
|
|
|
|
static const struct wp_presentation_listener presentationListener = {
|
|
.clock_id = presentationClockId,
|
|
};
|
|
|
|
static void presentationFeedbackSyncOutput(void * data,
|
|
struct wp_presentation_feedback * feedback, struct wl_output * output)
|
|
{
|
|
// Do nothing.
|
|
}
|
|
|
|
static void presentationFeedbackPresented(void * opaque,
|
|
struct wp_presentation_feedback * feedback, uint32_t tvSecHi, uint32_t tvSecLo,
|
|
uint32_t tvNsec, uint32_t refresh, uint32_t seqHi, uint32_t seqLo, uint32_t flags)
|
|
{
|
|
struct FrameData * data = opaque;
|
|
struct timespec present = {
|
|
.tv_sec = (uint64_t) tvSecHi << 32 | tvSecLo,
|
|
.tv_nsec = tvNsec,
|
|
};
|
|
struct timespec delta;
|
|
|
|
tsDiff(&delta, &present, &data->sent);
|
|
ringbuffer_push(wlWm.photonTimings, &(float){ delta.tv_sec + delta.tv_nsec * 1e-6f });
|
|
free(data);
|
|
wp_presentation_feedback_destroy(feedback);
|
|
}
|
|
|
|
static void presentationFeedbackDiscarded(void * data,
|
|
struct wp_presentation_feedback * feedback)
|
|
{
|
|
free(data);
|
|
wp_presentation_feedback_destroy(feedback);
|
|
}
|
|
|
|
static const struct wp_presentation_feedback_listener presentationFeedbackListener = {
|
|
.sync_output = presentationFeedbackSyncOutput,
|
|
.presented = presentationFeedbackPresented,
|
|
.discarded = presentationFeedbackDiscarded,
|
|
};
|
|
|
|
bool waylandPresentationInit(void)
|
|
{
|
|
if (wlWm.presentation)
|
|
{
|
|
wlWm.photonTimings = ringbuffer_new(256, sizeof(float));
|
|
wlWm.photonGraph = app_registerGraph("PHOTON", wlWm.photonTimings,
|
|
0.0f, 30.0f, NULL);
|
|
wp_presentation_add_listener(wlWm.presentation, &presentationListener, NULL);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void waylandPresentationFree(void)
|
|
{
|
|
if (!wlWm.presentation)
|
|
return;
|
|
|
|
wp_presentation_destroy(wlWm.presentation);
|
|
app_unregisterGraph(wlWm.photonGraph);
|
|
ringbuffer_free(&wlWm.photonTimings);
|
|
}
|
|
|
|
void waylandPresentationFrame(void)
|
|
{
|
|
if (!wlWm.presentation)
|
|
return;
|
|
|
|
struct FrameData * data = malloc(sizeof(*data));
|
|
if (!data)
|
|
{
|
|
DEBUG_ERROR("out of memory");
|
|
return;
|
|
}
|
|
|
|
if (clock_gettime(wlWm.clkId, &data->sent))
|
|
{
|
|
DEBUG_ERROR("clock_gettime failed: %s\n", strerror(errno));
|
|
free(data);
|
|
return;
|
|
}
|
|
|
|
struct wp_presentation_feedback * feedback = wp_presentation_feedback(wlWm.presentation, wlWm.surface);
|
|
wp_presentation_feedback_add_listener(feedback, &presentationFeedbackListener, data);
|
|
}
|