diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 4c9df099e..fab7a12e4 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/alignment.h" +#include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_m.h" @@ -10,6 +11,9 @@ namespace Service { namespace VI { +constexpr size_t SCREEN_REFRESH_RATE = 60; +constexpr u64 frame_ticks = static_cast(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); + class Parcel { public: // This default size was chosen arbitrarily. @@ -637,6 +641,19 @@ NVFlinger::NVFlinger() { displays.emplace_back(external); displays.emplace_back(edid); displays.emplace_back(internal); + + // Schedule the screen composition events + composition_event = + CoreTiming::RegisterEvent("ScreenCompositioin", [this](u64 userdata, int cycles_late) { + Compose(); + CoreTiming::ScheduleEvent(frame_ticks - cycles_late, composition_event); + }); + + CoreTiming::ScheduleEvent(frame_ticks, composition_event); +} + +NVFlinger::~NVFlinger() { + CoreTiming::UnscheduleEvent(composition_event, 0); } u64 NVFlinger::OpenDisplay(const std::string& name) { @@ -702,6 +719,13 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) { return *itr; } +void NVFlinger::Compose() { + for (auto& display : displays) { + // TODO(Subv): Gather the surfaces and forward them to the GPU for drawing. + display.vsync_event->Signal(); + } +} + BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {} void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 029bd6831..1bd8f7472 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -80,7 +80,7 @@ struct Display { class NVFlinger { public: NVFlinger(); - ~NVFlinger() = default; + ~NVFlinger(); /// Opens the specified display and returns the id. u64 OpenDisplay(const std::string& name); @@ -97,6 +97,10 @@ public: /// Obtains a buffer queue identified by the id. std::shared_ptr GetBufferQueue(u32 id) const; + /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when + /// finished. + void Compose(); + private: /// Returns the display identified by the specified id. Display& GetDisplay(u64 display_id); @@ -112,6 +116,9 @@ private: /// Id to use for the next buffer queue that is created, this counter is shared among all /// layers. u32 next_buffer_queue_id = 1; + + /// CoreTiming event that handles screen composition. + int composition_event; }; class IApplicationDisplayService final : public ServiceFramework {