buffer_queue.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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/alignment.h"
  6. #include "common/scope_exit.h"
  7. #include "core/core_timing.h"
  8. #include "core/hle/service/nvflinger/buffer_queue.h"
  9. namespace Service {
  10. namespace NVFlinger {
  11. BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
  12. native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle");
  13. native_handle->Signal();
  14. }
  15. void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
  16. Buffer buffer{};
  17. buffer.slot = slot;
  18. buffer.igbp_buffer = igbp_buffer;
  19. buffer.status = Buffer::Status::Free;
  20. LOG_WARNING(Service, "Adding graphics buffer %u", slot);
  21. queue.emplace_back(buffer);
  22. }
  23. u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) {
  24. auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
  25. // Only consider free buffers. Buffers become free once again after they've been Acquired
  26. // and Released by the compositor, see the NVFlinger::Compose method.
  27. if (buffer.status != Buffer::Status::Free)
  28. return false;
  29. // Make sure that the parameters match.
  30. auto& igbp_buffer = buffer.igbp_buffer;
  31. return igbp_buffer.format == pixel_format && igbp_buffer.width == width &&
  32. igbp_buffer.height == height;
  33. });
  34. if (itr == queue.end()) {
  35. LOG_CRITICAL(Service_NVDRV, "no free buffers for pixel_format=%d, width=%d, height=%d",
  36. pixel_format, width, height);
  37. itr = queue.begin();
  38. }
  39. itr->status = Buffer::Status::Dequeued;
  40. return itr->slot;
  41. }
  42. const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
  43. auto itr = std::find_if(queue.begin(), queue.end(),
  44. [&](const Buffer& buffer) { return buffer.slot == slot; });
  45. ASSERT(itr != queue.end());
  46. ASSERT(itr->status == Buffer::Status::Dequeued);
  47. return itr->igbp_buffer;
  48. }
  49. void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform) {
  50. auto itr = std::find_if(queue.begin(), queue.end(),
  51. [&](const Buffer& buffer) { return buffer.slot == slot; });
  52. ASSERT(itr != queue.end());
  53. ASSERT(itr->status == Buffer::Status::Dequeued);
  54. itr->status = Buffer::Status::Queued;
  55. itr->transform = transform;
  56. }
  57. boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() {
  58. auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) {
  59. return buffer.status == Buffer::Status::Queued;
  60. });
  61. if (itr == queue.end())
  62. return boost::none;
  63. itr->status = Buffer::Status::Acquired;
  64. return *itr;
  65. }
  66. void BufferQueue::ReleaseBuffer(u32 slot) {
  67. auto itr = std::find_if(queue.begin(), queue.end(),
  68. [&](const Buffer& buffer) { return buffer.slot == slot; });
  69. ASSERT(itr != queue.end());
  70. ASSERT(itr->status == Buffer::Status::Acquired);
  71. itr->status = Buffer::Status::Free;
  72. }
  73. u32 BufferQueue::Query(QueryType type) {
  74. LOG_WARNING(Service, "(STUBBED) called type=%u", static_cast<u32>(type));
  75. switch (type) {
  76. case QueryType::NativeWindowFormat:
  77. // TODO(Subv): Use an enum for this
  78. static constexpr u32 FormatABGR8 = 1;
  79. return FormatABGR8;
  80. }
  81. UNIMPLEMENTED();
  82. return 0;
  83. }
  84. } // namespace NVFlinger
  85. } // namespace Service