File indexing completed on 2024-11-10 04:57:31

0001 /*
0002     SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "presentationtime.h"
0007 #include "display.h"
0008 #include "output.h"
0009 #include "surface.h"
0010 #include "surface_p.h"
0011 
0012 namespace KWin
0013 {
0014 
0015 PresentationTime::PresentationTime(Display *display, QObject *parent)
0016     : QObject(parent)
0017     , QtWaylandServer::wp_presentation(*display, 1)
0018 {
0019 }
0020 
0021 void PresentationTime::wp_presentation_bind_resource(Resource *resource)
0022 {
0023     send_clock_id(resource->handle, CLOCK_MONOTONIC);
0024 }
0025 
0026 void PresentationTime::wp_presentation_destroy(Resource *resource)
0027 {
0028     wl_resource_destroy(resource->handle);
0029 }
0030 
0031 void PresentationTime::wp_presentation_feedback(Resource *resource, wl_resource *surface, uint32_t callback)
0032 {
0033     SurfaceInterface *surf = SurfaceInterface::get(surface);
0034     SurfaceInterfacePrivate *surfPriv = SurfaceInterfacePrivate::get(surf);
0035 
0036     auto &feedback = surfPriv->pending->presentationFeedback;
0037     if (!feedback) {
0038         feedback = std::make_unique<PresentationTimeFeedback>();
0039     }
0040 
0041     wl_resource *feedbackResource = wl_resource_create(resource->client(), &wp_presentation_feedback_interface, resource->version(), callback);
0042     wl_resource_set_implementation(feedbackResource, nullptr, nullptr, [](wl_resource *resource) {
0043         wl_list_remove(wl_resource_get_link(resource));
0044     });
0045 
0046     wl_list_insert(feedback->resources.prev, wl_resource_get_link(feedbackResource));
0047 }
0048 
0049 PresentationTimeFeedback::PresentationTimeFeedback()
0050 {
0051     wl_list_init(&resources);
0052 }
0053 
0054 PresentationTimeFeedback::~PresentationTimeFeedback()
0055 {
0056     wl_resource *resource;
0057     wl_resource *tmp;
0058     wl_resource_for_each_safe (resource, tmp, &resources) {
0059         wp_presentation_feedback_send_discarded(resource);
0060         wl_resource_destroy(resource);
0061     }
0062 }
0063 
0064 void PresentationTimeFeedback::presented(std::chrono::nanoseconds refreshCycleDuration, std::chrono::nanoseconds timestamp, PresentationMode mode)
0065 {
0066     const auto secs = std::chrono::duration_cast<std::chrono::seconds>(timestamp);
0067     const uint32_t tvSecHi = secs.count() >> 32;
0068     const uint32_t tvSecLo = secs.count() & 0xffffffff;
0069     const uint32_t tvNsec = (timestamp - secs).count();
0070 
0071     const bool adaptiveSync = mode == PresentationMode::AdaptiveSync || mode == PresentationMode::AdaptiveAsync;
0072     const uint32_t refreshDuration = adaptiveSync ? 0 : refreshCycleDuration.count();
0073     uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK | WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION;
0074     if (mode == PresentationMode::VSync || mode == PresentationMode::AdaptiveSync) {
0075         flags |= WP_PRESENTATION_FEEDBACK_KIND_VSYNC;
0076     }
0077 
0078     wl_resource *resource;
0079     wl_resource *tmp;
0080     wl_resource_for_each_safe (resource, tmp, &resources) {
0081         wp_presentation_feedback_send_presented(resource, tvSecHi, tvSecLo, tvNsec, refreshDuration, 0, 0, flags);
0082         wl_resource_destroy(resource);
0083     }
0084 }
0085 }