consumer_base.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-FileCopyrightText: Copyright 2010 The Android Open Source Project
  3. // SPDX-License-Identifier: GPL-3.0-or-later
  4. // Parts of this implementation were based on:
  5. // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/ConsumerBase.cpp
  6. #include "common/assert.h"
  7. #include "common/logging/log.h"
  8. #include "core/hle/service/nvnflinger/buffer_item.h"
  9. #include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
  10. #include "core/hle/service/nvnflinger/buffer_queue_core.h"
  11. #include "core/hle/service/nvnflinger/consumer_base.h"
  12. #include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
  13. namespace Service::android {
  14. ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_)
  15. : consumer{std::move(consumer_)} {}
  16. ConsumerBase::~ConsumerBase() {
  17. std::scoped_lock lock{mutex};
  18. ASSERT_MSG(is_abandoned, "consumer is not abandoned!");
  19. }
  20. void ConsumerBase::Connect(bool controlled_by_app) {
  21. consumer->Connect(shared_from_this(), controlled_by_app);
  22. }
  23. void ConsumerBase::Abandon() {
  24. LOG_DEBUG(Service_Nvnflinger, "called");
  25. std::scoped_lock lock{mutex};
  26. if (!is_abandoned) {
  27. this->AbandonLocked();
  28. is_abandoned = true;
  29. }
  30. }
  31. void ConsumerBase::AbandonLocked() {
  32. for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
  33. this->FreeBufferLocked(i);
  34. }
  35. // disconnect from the BufferQueue
  36. consumer->Disconnect();
  37. consumer = nullptr;
  38. }
  39. void ConsumerBase::FreeBufferLocked(s32 slot_index) {
  40. LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index);
  41. slots[slot_index].graphic_buffer = nullptr;
  42. slots[slot_index].fence = Fence::NoFence();
  43. slots[slot_index].frame_number = 0;
  44. }
  45. void ConsumerBase::OnFrameAvailable(const BufferItem& item) {
  46. LOG_DEBUG(Service_Nvnflinger, "called");
  47. }
  48. void ConsumerBase::OnFrameReplaced(const BufferItem& item) {
  49. LOG_DEBUG(Service_Nvnflinger, "called");
  50. }
  51. void ConsumerBase::OnBuffersReleased() {
  52. std::scoped_lock lock{mutex};
  53. LOG_DEBUG(Service_Nvnflinger, "called");
  54. if (is_abandoned) {
  55. // Nothing to do if we're already abandoned.
  56. return;
  57. }
  58. u64 mask = 0;
  59. consumer->GetReleasedBuffers(&mask);
  60. for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
  61. if (mask & (1ULL << i)) {
  62. FreeBufferLocked(i);
  63. }
  64. }
  65. }
  66. void ConsumerBase::OnSidebandStreamChanged() {}
  67. Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when) {
  68. Status err = consumer->AcquireBuffer(item, present_when);
  69. if (err != Status::NoError) {
  70. return err;
  71. }
  72. if (item->graphic_buffer != nullptr) {
  73. slots[item->slot].graphic_buffer = item->graphic_buffer;
  74. }
  75. slots[item->slot].frame_number = item->frame_number;
  76. slots[item->slot].fence = item->fence;
  77. LOG_DEBUG(Service_Nvnflinger, "slot={}", item->slot);
  78. return Status::NoError;
  79. }
  80. Status ConsumerBase::AddReleaseFenceLocked(s32 slot,
  81. const std::shared_ptr<GraphicBuffer>& graphic_buffer,
  82. const Fence& fence) {
  83. LOG_DEBUG(Service_Nvnflinger, "slot={}", slot);
  84. // If consumer no longer tracks this graphic_buffer, we can safely
  85. // drop this fence, as it will never be received by the producer.
  86. if (!StillTracking(slot, graphic_buffer)) {
  87. return Status::NoError;
  88. }
  89. slots[slot].fence = fence;
  90. return Status::NoError;
  91. }
  92. Status ConsumerBase::ReleaseBufferLocked(s32 slot,
  93. const std::shared_ptr<GraphicBuffer>& graphic_buffer) {
  94. // If consumer no longer tracks this graphic_buffer (we received a new
  95. // buffer on the same slot), the buffer producer is definitely no longer
  96. // tracking it.
  97. if (!StillTracking(slot, graphic_buffer)) {
  98. return Status::NoError;
  99. }
  100. LOG_DEBUG(Service_Nvnflinger, "slot={}", slot);
  101. Status err = consumer->ReleaseBuffer(slot, slots[slot].frame_number, slots[slot].fence);
  102. if (err == Status::StaleBufferSlot) {
  103. FreeBufferLocked(slot);
  104. }
  105. slots[slot].fence = Fence::NoFence();
  106. return err;
  107. }
  108. bool ConsumerBase::StillTracking(s32 slot,
  109. const std::shared_ptr<GraphicBuffer>& graphic_buffer) const {
  110. if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
  111. return false;
  112. }
  113. return (slots[slot].graphic_buffer != nullptr &&
  114. slots[slot].graphic_buffer->Handle() == graphic_buffer->Handle());
  115. }
  116. } // namespace Service::android