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 }