nvflinger: Implement swap intervals
This commit is contained in:
parent
772c86a260
commit
ceb5f5079c
|
@ -63,7 +63,7 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
|
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(),
|
auto itr = std::find_if(queue.begin(), queue.end(),
|
||||||
[&](const Buffer& buffer) { return buffer.slot == slot; });
|
[&](const Buffer& buffer) { return buffer.slot == slot; });
|
||||||
ASSERT(itr != queue.end());
|
ASSERT(itr != queue.end());
|
||||||
|
@ -71,6 +71,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
|
||||||
itr->status = Buffer::Status::Queued;
|
itr->status = Buffer::Status::Queued;
|
||||||
itr->transform = transform;
|
itr->transform = transform;
|
||||||
itr->crop_rect = crop_rect;
|
itr->crop_rect = crop_rect;
|
||||||
|
itr->swap_interval = swap_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
|
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
|
||||||
|
|
|
@ -68,13 +68,14 @@ public:
|
||||||
IGBPBuffer igbp_buffer;
|
IGBPBuffer igbp_buffer;
|
||||||
BufferTransformFlags transform;
|
BufferTransformFlags transform;
|
||||||
Common::Rectangle<int> crop_rect;
|
Common::Rectangle<int> crop_rect;
|
||||||
|
u32 swap_interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
|
void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
|
||||||
std::optional<u32> DequeueBuffer(u32 width, u32 height);
|
std::optional<u32> DequeueBuffer(u32 width, u32 height);
|
||||||
const IGBPBuffer& RequestBuffer(u32 slot) const;
|
const IGBPBuffer& RequestBuffer(u32 slot) const;
|
||||||
void QueueBuffer(u32 slot, BufferTransformFlags transform,
|
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();
|
std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
|
||||||
void ReleaseBuffer(u32 slot);
|
void ReleaseBuffer(u32 slot);
|
||||||
u32 Query(QueryType type);
|
u32 Query(QueryType type);
|
||||||
|
|
|
@ -37,15 +37,16 @@ NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_t
|
||||||
displays.emplace_back(4, "Null");
|
displays.emplace_back(4, "Null");
|
||||||
|
|
||||||
// Schedule the screen composition events
|
// 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(
|
composition_event = core_timing.RegisterEvent(
|
||||||
"ScreenComposition", [this, ticks](u64 userdata, s64 cycles_late) {
|
"ScreenComposition", [this](u64 userdata, s64 cycles_late) {
|
||||||
Compose();
|
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() {
|
NVFlinger::~NVFlinger() {
|
||||||
|
@ -206,8 +207,13 @@ void NVFlinger::Compose() {
|
||||||
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride,
|
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride,
|
||||||
buffer->get().transform, buffer->get().crop_rect);
|
buffer->get().transform, buffer->get().crop_rect);
|
||||||
|
|
||||||
|
swap_interval = buffer->get().swap_interval;
|
||||||
buffer_queue.ReleaseBuffer(buffer->get().slot);
|
buffer_queue.ReleaseBuffer(buffer->get().slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s64 NVFlinger::GetNextTicks() {
|
||||||
|
return (Core::Timing::BASE_CLOCK_RATE * (1LL << swap_interval)) / 120;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::NVFlinger
|
} // namespace Service::NVFlinger
|
||||||
|
|
|
@ -74,6 +74,8 @@ public:
|
||||||
/// finished.
|
/// finished.
|
||||||
void Compose();
|
void Compose();
|
||||||
|
|
||||||
|
s64 GetNextTicks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Finds the display identified by the specified ID.
|
/// Finds the display identified by the specified ID.
|
||||||
VI::Display* FindDisplay(u64 display_id);
|
VI::Display* FindDisplay(u64 display_id);
|
||||||
|
@ -98,6 +100,8 @@ private:
|
||||||
/// layers.
|
/// layers.
|
||||||
u32 next_buffer_queue_id = 1;
|
u32 next_buffer_queue_id = 1;
|
||||||
|
|
||||||
|
u32 swap_interval = 1;
|
||||||
|
|
||||||
/// Event that handles screen composition.
|
/// Event that handles screen composition.
|
||||||
Core::Timing::EventType* composition_event;
|
Core::Timing::EventType* composition_event;
|
||||||
|
|
||||||
|
|
|
@ -418,7 +418,8 @@ public:
|
||||||
s32_le scaling_mode;
|
s32_le scaling_mode;
|
||||||
NVFlinger::BufferQueue::BufferTransformFlags transform;
|
NVFlinger::BufferQueue::BufferTransformFlags transform;
|
||||||
u32_le sticky_transform;
|
u32_le sticky_transform;
|
||||||
INSERT_PADDING_WORDS(2);
|
INSERT_PADDING_WORDS(1);
|
||||||
|
u32_le swap_interval;
|
||||||
u32_le fence_is_valid;
|
u32_le fence_is_valid;
|
||||||
std::array<Fence, 2> fences;
|
std::array<Fence, 2> fences;
|
||||||
|
|
||||||
|
@ -582,7 +583,7 @@ private:
|
||||||
IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
|
IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
|
||||||
|
|
||||||
buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
|
buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
|
||||||
request.data.GetCropRect());
|
request.data.GetCropRect(), request.data.swap_interval);
|
||||||
|
|
||||||
IGBPQueueBufferResponseParcel response{1280, 720};
|
IGBPQueueBufferResponseParcel response{1280, 720};
|
||||||
ctx.WriteBuffer(response.Serialize());
|
ctx.WriteBuffer(response.Serialize());
|
||||||
|
|
Reference in New Issue