container.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "core/core.h"
  4. #include "core/hle/service/nvdrv/nvdrv_interface.h"
  5. #include "core/hle/service/nvnflinger/buffer_queue_producer.h"
  6. #include "core/hle/service/nvnflinger/hos_binder_driver.h"
  7. #include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
  8. #include "core/hle/service/nvnflinger/surface_flinger.h"
  9. #include "core/hle/service/sm/sm.h"
  10. #include "core/hle/service/vi/container.h"
  11. #include "core/hle/service/vi/vi_results.h"
  12. namespace Service::VI {
  13. Container::Container(Core::System& system) {
  14. m_displays.CreateDisplay(DisplayName{"Default"});
  15. m_displays.CreateDisplay(DisplayName{"External"});
  16. m_displays.CreateDisplay(DisplayName{"Edid"});
  17. m_displays.CreateDisplay(DisplayName{"Internal"});
  18. m_displays.CreateDisplay(DisplayName{"Null"});
  19. m_binder_driver =
  20. system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true);
  21. m_surface_flinger = m_binder_driver->GetSurfaceFlinger();
  22. const auto nvdrv =
  23. system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule();
  24. m_shared_buffer_manager.emplace(system, *this, nvdrv);
  25. m_displays.ForEachDisplay(
  26. [&](auto& display) { m_surface_flinger->AddDisplay(display.GetId()); });
  27. m_conductor.emplace(system, *this, m_displays);
  28. }
  29. Container::~Container() {
  30. this->OnTerminate();
  31. }
  32. void Container::OnTerminate() {
  33. std::scoped_lock lk{m_lock};
  34. m_is_shut_down = true;
  35. m_layers.ForEachLayer([&](auto& layer) {
  36. if (layer.IsOpen()) {
  37. this->DestroyBufferQueueLocked(&layer);
  38. }
  39. });
  40. m_displays.ForEachDisplay(
  41. [&](auto& display) { m_surface_flinger->RemoveDisplay(display.GetId()); });
  42. }
  43. SharedBufferManager* Container::GetSharedBufferManager() {
  44. return std::addressof(*m_shared_buffer_manager);
  45. }
  46. Result Container::GetBinderDriver(
  47. std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver) {
  48. *out_binder_driver = m_binder_driver;
  49. R_SUCCEED();
  50. }
  51. Result Container::GetLayerProducerHandle(
  52. std::shared_ptr<android::BufferQueueProducer>* out_producer, u64 layer_id) {
  53. std::scoped_lock lk{m_lock};
  54. auto* const layer = m_layers.GetLayerById(layer_id);
  55. R_UNLESS(layer != nullptr, VI::ResultNotFound);
  56. const auto binder = m_binder_driver->GetServer()->TryGetBinder(layer->GetProducerBinderId());
  57. R_UNLESS(binder != nullptr, VI::ResultNotFound);
  58. *out_producer = std::static_pointer_cast<android::BufferQueueProducer>(binder);
  59. R_SUCCEED();
  60. }
  61. Result Container::OpenDisplay(u64* out_display_id, const DisplayName& display_name) {
  62. auto* const display = m_displays.GetDisplayByName(display_name);
  63. R_UNLESS(display != nullptr, VI::ResultNotFound);
  64. *out_display_id = display->GetId();
  65. R_SUCCEED();
  66. }
  67. Result Container::CloseDisplay(u64 display_id) {
  68. R_SUCCEED();
  69. }
  70. Result Container::CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid) {
  71. std::scoped_lock lk{m_lock};
  72. R_RETURN(this->CreateLayerLocked(out_layer_id, display_id, owner_aruid));
  73. }
  74. Result Container::DestroyManagedLayer(u64 layer_id) {
  75. std::scoped_lock lk{m_lock};
  76. // Try to close, if open, but don't fail if not.
  77. this->CloseLayerLocked(layer_id);
  78. R_RETURN(this->DestroyLayerLocked(layer_id));
  79. }
  80. Result Container::OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid) {
  81. std::scoped_lock lk{m_lock};
  82. R_RETURN(this->OpenLayerLocked(out_producer_binder_id, layer_id, aruid));
  83. }
  84. Result Container::CloseLayer(u64 layer_id) {
  85. std::scoped_lock lk{m_lock};
  86. R_RETURN(this->CloseLayerLocked(layer_id));
  87. }
  88. Result Container::SetLayerVisibility(u64 layer_id, bool visible) {
  89. std::scoped_lock lk{m_lock};
  90. auto* const layer = m_layers.GetLayerById(layer_id);
  91. R_UNLESS(layer != nullptr, VI::ResultNotFound);
  92. m_surface_flinger->SetLayerVisibility(layer->GetConsumerBinderId(), visible);
  93. R_SUCCEED();
  94. }
  95. Result Container::SetLayerBlending(u64 layer_id, bool enabled) {
  96. std::scoped_lock lk{m_lock};
  97. auto* const layer = m_layers.GetLayerById(layer_id);
  98. R_UNLESS(layer != nullptr, VI::ResultNotFound);
  99. m_surface_flinger->SetLayerBlending(layer->GetConsumerBinderId(),
  100. enabled ? Nvnflinger::LayerBlending::Coverage
  101. : Nvnflinger::LayerBlending::None);
  102. R_SUCCEED();
  103. }
  104. void Container::LinkVsyncEvent(u64 display_id, Event* event) {
  105. std::scoped_lock lk{m_lock};
  106. m_conductor->LinkVsyncEvent(display_id, event);
  107. }
  108. void Container::UnlinkVsyncEvent(u64 display_id, Event* event) {
  109. std::scoped_lock lk{m_lock};
  110. m_conductor->UnlinkVsyncEvent(display_id, event);
  111. }
  112. Result Container::CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id) {
  113. std::scoped_lock lk{m_lock};
  114. R_TRY(this->CreateLayerLocked(out_layer_id, display_id, {}));
  115. R_RETURN(this->OpenLayerLocked(out_producer_binder_id, *out_layer_id, {}));
  116. }
  117. Result Container::DestroyStrayLayer(u64 layer_id) {
  118. std::scoped_lock lk{m_lock};
  119. R_TRY(this->CloseLayerLocked(layer_id));
  120. R_RETURN(this->DestroyLayerLocked(layer_id));
  121. }
  122. Result Container::CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid) {
  123. auto* const display = m_displays.GetDisplayById(display_id);
  124. R_UNLESS(display != nullptr, VI::ResultNotFound);
  125. auto* const layer = m_layers.CreateLayer(owner_aruid, display);
  126. R_UNLESS(layer != nullptr, VI::ResultNotFound);
  127. *out_layer_id = layer->GetId();
  128. R_SUCCEED();
  129. }
  130. Result Container::DestroyLayerLocked(u64 layer_id) {
  131. R_SUCCEED_IF(m_layers.DestroyLayer(layer_id));
  132. R_THROW(VI::ResultNotFound);
  133. }
  134. Result Container::OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid) {
  135. R_UNLESS(!m_is_shut_down, VI::ResultOperationFailed);
  136. auto* const layer = m_layers.GetLayerById(layer_id);
  137. R_UNLESS(layer != nullptr, VI::ResultNotFound);
  138. R_UNLESS(!layer->IsOpen(), VI::ResultOperationFailed);
  139. R_UNLESS(layer->GetOwnerAruid() == aruid, VI::ResultPermissionDenied);
  140. this->CreateBufferQueueLocked(layer);
  141. *out_producer_binder_id = layer->GetProducerBinderId();
  142. R_SUCCEED();
  143. }
  144. Result Container::CloseLayerLocked(u64 layer_id) {
  145. auto* const layer = m_layers.GetLayerById(layer_id);
  146. R_UNLESS(layer != nullptr, VI::ResultNotFound);
  147. R_UNLESS(layer->IsOpen(), VI::ResultOperationFailed);
  148. this->DestroyBufferQueueLocked(layer);
  149. R_SUCCEED();
  150. }
  151. void Container::CreateBufferQueueLocked(Layer* layer) {
  152. s32 consumer_binder_id, producer_binder_id;
  153. m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id);
  154. layer->Open(consumer_binder_id, producer_binder_id);
  155. if (auto* display = layer->GetDisplay(); display != nullptr) {
  156. m_surface_flinger->AddLayerToDisplayStack(display->GetId(), consumer_binder_id);
  157. }
  158. }
  159. void Container::DestroyBufferQueueLocked(Layer* layer) {
  160. if (auto* display = layer->GetDisplay(); display != nullptr) {
  161. m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(),
  162. layer->GetConsumerBinderId());
  163. }
  164. layer->Close();
  165. m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(),
  166. layer->GetProducerBinderId());
  167. }
  168. void Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale,
  169. u64 display_id) {
  170. std::scoped_lock lk{m_lock};
  171. m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale, display_id);
  172. }
  173. } // namespace Service::VI