diff options
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 52 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.h | 19 | 
2 files changed, 58 insertions, 13 deletions
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index fab7a12e4..67d82c2bf 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 "common/scope_exit.h"  #include "core/core_timing.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/service/vi/vi.h" @@ -721,8 +722,30 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) {  void NVFlinger::Compose() {      for (auto& display : displays) { -        // TODO(Subv): Gather the surfaces and forward them to the GPU for drawing. -        display.vsync_event->Signal(); +        // Trigger vsync for this display at the end of drawing +        SCOPE_EXIT({ display.vsync_event->Signal(); }); + +        // Don't do anything for displays without layers. +        if (display.layers.empty()) +            continue; + +        // TODO(Subv): Support more than 1 layer. +        ASSERT_MSG(display.layers.size() == 1, "Max 1 layer per display is supported"); + +        Layer& layer = display.layers[0]; +        auto& buffer_queue = layer.buffer_queue; + +        // Search for a queued buffer and acquire it +        auto buffer = buffer_queue->AcquireBuffer(); + +        if (buffer == boost::none) { +            // There was no queued buffer to draw. +            continue; +        } + +        // TODO(Subv): Send the buffer to the GPU for drawing. + +        buffer_queue->ReleaseBuffer(buffer->slot);      }  } @@ -732,7 +755,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {      Buffer buffer{};      buffer.slot = slot;      buffer.igbp_buffer = igbp_buffer; -    buffer.status = Buffer::Status::Queued; +    buffer.status = Buffer::Status::Free;      LOG_WARNING(Service, "Adding graphics buffer %u", slot); @@ -741,8 +764,9 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {  u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) {      auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { -        // Only consider enqueued buffers -        if (buffer.status != Buffer::Status::Queued) +        // Only consider free buffers. Buffers become free once again after they've been Acquired +        // and Released by the compositor, see the NVFlinger::Compose method. +        if (buffer.status != Buffer::Status::Free)              return false;          // Make sure that the parameters match. @@ -772,6 +796,24 @@ void BufferQueue::QueueBuffer(u32 slot) {      itr->status = Buffer::Status::Queued;  } +boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() { +    auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) { +        return buffer.status == Buffer::Status::Queued; +    }); +    if (itr == queue.end()) +        return boost::none; +    itr->status = Buffer::Status::Acquired; +    return *itr; +} + +void BufferQueue::ReleaseBuffer(u32 slot) { +    auto itr = std::find_if(queue.begin(), queue.end(), +                            [&](const Buffer& buffer) { return buffer.slot == slot; }); +    ASSERT(itr != queue.end()); +    ASSERT(itr->status == Buffer::Status::Acquired); +    itr->status = Buffer::Status::Free; +} +  Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {}  Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 1bd8f7472..576c4ce32 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -5,6 +5,7 @@  #pragma once  #include <memory> +#include <boost/optional.hpp>  #include "core/hle/kernel/event.h"  #include "core/hle/service/service.h" @@ -34,10 +35,20 @@ public:      BufferQueue(u32 id, u64 layer_id);      ~BufferQueue() = default; +    struct Buffer { +        enum class Status { Free = 0, Queued = 1, Dequeued = 2, Acquired = 3 }; + +        u32 slot; +        Status status = Status::Free; +        IGBPBuffer igbp_buffer; +    }; +      void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);      u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height);      const IGBPBuffer& RequestBuffer(u32 slot) const;      void QueueBuffer(u32 slot); +    boost::optional<const Buffer&> AcquireBuffer(); +    void ReleaseBuffer(u32 slot);      u32 GetId() const {          return id; @@ -47,14 +58,6 @@ private:      u32 id;      u64 layer_id; -    struct Buffer { -        enum class Status { None = 0, Queued = 1, Dequeued = 2 }; - -        u32 slot; -        Status status = Status::None; -        IGBPBuffer igbp_buffer; -    }; -      std::vector<Buffer> queue;  };  | 
