Просмотр исходного кода

nvflinger: Implement swap intervals

Fernando Sahmkow 7 лет назад
Родитель
Сommit
ceb5f5079c

+ 2 - 1
src/core/hle/service/nvflinger/buffer_queue.cpp

@@ -63,7 +63,7 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
 }
 
 void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
-                              const Common::Rectangle<int>& crop_rect) {
+                              const Common::Rectangle<int>& crop_rect, u32 swap_interval) {
     auto itr = std::find_if(queue.begin(), queue.end(),
                             [&](const Buffer& buffer) { return buffer.slot == slot; });
     ASSERT(itr != queue.end());
@@ -71,6 +71,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
     itr->status = Buffer::Status::Queued;
     itr->transform = transform;
     itr->crop_rect = crop_rect;
+    itr->swap_interval = swap_interval;
 }
 
 std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {

+ 2 - 1
src/core/hle/service/nvflinger/buffer_queue.h

@@ -68,13 +68,14 @@ public:
         IGBPBuffer igbp_buffer;
         BufferTransformFlags transform;
         Common::Rectangle<int> crop_rect;
+        u32 swap_interval;
     };
 
     void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
     std::optional<u32> DequeueBuffer(u32 width, u32 height);
     const IGBPBuffer& RequestBuffer(u32 slot) const;
     void QueueBuffer(u32 slot, BufferTransformFlags transform,
-                     const Common::Rectangle<int>& crop_rect);
+                     const Common::Rectangle<int>& crop_rect, u32 swap_interval);
     std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
     void ReleaseBuffer(u32 slot);
     u32 Query(QueryType type);

+ 10 - 4
src/core/hle/service/nvflinger/nvflinger.cpp

@@ -37,15 +37,16 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t
     displays.emplace_back(4, "Null");
 
     // Schedule the screen composition events
-    const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks;
+    //const auto ticks = Settings::values.force_30fps_mode ? frame_ticks_30fps : frame_ticks;
 
     composition_event = core_timing.RegisterEvent(
-        "ScreenComposition", [this, ticks](u64 userdata, s64 cycles_late) {
+        "ScreenComposition", [this](u64 userdata, s64 cycles_late) {
             Compose();
-            this->core_timing.ScheduleEvent(ticks - cycles_late, composition_event);
+            const auto ticks = GetNextTicks();
+            this->core_timing.ScheduleEvent(std::max(0LL,ticks - cycles_late), composition_event);
         });
 
-    core_timing.ScheduleEvent(ticks, composition_event);
+    core_timing.ScheduleEvent(frame_ticks, composition_event);
 }
 
 NVFlinger::~NVFlinger() {
@@ -206,8 +207,13 @@ void NVFlinger::Compose() {
                      igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride,
                      buffer->get().transform, buffer->get().crop_rect);
 
+        swap_interval = buffer->get().swap_interval;
         buffer_queue.ReleaseBuffer(buffer->get().slot);
     }
 }
 
+s64 NVFlinger::GetNextTicks() {
+    return (Core::Timing::BASE_CLOCK_RATE * (1LL << swap_interval)) / 120;
+}
+
 } // namespace Service::NVFlinger

+ 4 - 0
src/core/hle/service/nvflinger/nvflinger.h

@@ -74,6 +74,8 @@ public:
     /// finished.
     void Compose();
 
+    s64 GetNextTicks();
+
 private:
     /// Finds the display identified by the specified ID.
     VI::Display* FindDisplay(u64 display_id);
@@ -98,6 +100,8 @@ private:
     /// layers.
     u32 next_buffer_queue_id = 1;
 
+    u32 swap_interval = 1;
+
     /// Event that handles screen composition.
     Core::Timing::EventType* composition_event;
 

+ 3 - 2
src/core/hle/service/vi/vi.cpp

@@ -418,7 +418,8 @@ public:
         s32_le scaling_mode;
         NVFlinger::BufferQueue::BufferTransformFlags transform;
         u32_le sticky_transform;
-        INSERT_PADDING_WORDS(2);
+        INSERT_PADDING_WORDS(1);
+        u32_le swap_interval;
         u32_le fence_is_valid;
         std::array<Fence, 2> fences;
 
@@ -582,7 +583,7 @@ private:
             IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
 
             buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
-                                     request.data.GetCropRect());
+                                     request.data.GetCropRect(), request.data.swap_interval);
 
             IGBPQueueBufferResponseParcel response{1280, 720};
             ctx.WriteBuffer(response.Serialize());