buffer_queue.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include "common/assert.h"
  6. #include "common/logging/log.h"
  7. #include "core/core.h"
  8. #include "core/hle/kernel/kernel.h"
  9. #include "core/hle/kernel/readable_event.h"
  10. #include "core/hle/kernel/writable_event.h"
  11. #include "core/hle/service/nvflinger/buffer_queue.h"
  12. namespace Service::NVFlinger {
  13. BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
  14. auto& kernel = Core::System::GetInstance().Kernel();
  15. buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
  16. "BufferQueue NativeHandle");
  17. }
  18. BufferQueue::~BufferQueue() = default;
  19. void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
  20. LOG_WARNING(Service, "Adding graphics buffer {}", slot);
  21. Buffer buffer{};
  22. buffer.slot = slot;
  23. buffer.igbp_buffer = igbp_buffer;
  24. buffer.status = Buffer::Status::Free;
  25. queue.emplace_back(buffer);
  26. buffer_wait_event.writable->Signal();
  27. }
  28. std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
  29. u32 height) {
  30. auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
  31. // Only consider free buffers. Buffers become free once again after they've been Acquired
  32. // and Released by the compositor, see the NVFlinger::Compose method.
  33. if (buffer.status != Buffer::Status::Free) {
  34. return false;
  35. }
  36. // Make sure that the parameters match.
  37. return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
  38. });
  39. if (itr == queue.end()) {
  40. return {};
  41. }
  42. itr->status = Buffer::Status::Dequeued;
  43. return {{itr->slot, &itr->multi_fence}};
  44. }
  45. const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
  46. auto itr = std::find_if(queue.begin(), queue.end(),
  47. [&](const Buffer& buffer) { return buffer.slot == slot; });
  48. ASSERT(itr != queue.end());
  49. ASSERT(itr->status == Buffer::Status::Dequeued);
  50. return itr->igbp_buffer;
  51. }
  52. void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
  53. const Common::Rectangle<int>& crop_rect, u32 swap_interval,
  54. Service::Nvidia::MultiFence& multi_fence) {
  55. auto itr = std::find_if(queue.begin(), queue.end(),
  56. [&](const Buffer& buffer) { return buffer.slot == slot; });
  57. ASSERT(itr != queue.end());
  58. ASSERT(itr->status == Buffer::Status::Dequeued);
  59. itr->status = Buffer::Status::Queued;
  60. itr->transform = transform;
  61. itr->crop_rect = crop_rect;
  62. itr->swap_interval = swap_interval;
  63. itr->multi_fence = multi_fence;
  64. queue_sequence.push_back(slot);
  65. }
  66. std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
  67. std::vector<Buffer>::iterator itr = queue.end();
  68. while (itr == queue.end() && !queue_sequence.empty()) {
  69. u32 slot = queue_sequence.front();
  70. itr = std::find_if(queue.begin(), queue.end(), [&slot](const Buffer& buffer) {
  71. return buffer.status == Buffer::Status::Queued && buffer.slot == slot;
  72. });
  73. queue_sequence.pop_front();
  74. }
  75. if (itr == queue.end())
  76. return {};
  77. itr->status = Buffer::Status::Acquired;
  78. return *itr;
  79. }
  80. void BufferQueue::ReleaseBuffer(u32 slot) {
  81. auto itr = std::find_if(queue.begin(), queue.end(),
  82. [&](const Buffer& buffer) { return buffer.slot == slot; });
  83. ASSERT(itr != queue.end());
  84. ASSERT(itr->status == Buffer::Status::Acquired);
  85. itr->status = Buffer::Status::Free;
  86. buffer_wait_event.writable->Signal();
  87. }
  88. u32 BufferQueue::Query(QueryType type) {
  89. LOG_WARNING(Service, "(STUBBED) called type={}", static_cast<u32>(type));
  90. switch (type) {
  91. case QueryType::NativeWindowFormat:
  92. // TODO(Subv): Use an enum for this
  93. static constexpr u32 FormatABGR8 = 1;
  94. return FormatABGR8;
  95. }
  96. UNIMPLEMENTED();
  97. return 0;
  98. }
  99. Kernel::SharedPtr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
  100. return buffer_wait_event.writable;
  101. }
  102. Kernel::SharedPtr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const {
  103. return buffer_wait_event.readable;
  104. }
  105. } // namespace Service::NVFlinger