diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/service/am/am_types.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/am/frontend/applet_software_keyboard.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/service/am/frontend/applet_software_keyboard.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/am/library_applet_creator.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/service/am/self_controller.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/service/am/system_buffer_manager.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/am/system_buffer_manager.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | 154 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/fb_share_buffer_manager.h | 24 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/hardware_composer.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/hwc_layer.h | 13 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/vi/layer/vi_layer.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/service/vi/layer/vi_layer.h | 13 | 
16 files changed, 217 insertions, 66 deletions
| diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h index a2b852b12..8c33feb15 100644 --- a/src/core/hle/service/am/am_types.h +++ b/src/core/hle/service/am/am_types.h @@ -130,9 +130,9 @@ enum class AppletProgramId : u64 {  enum class LibraryAppletMode : u32 {      AllForeground = 0, -    Background = 1, -    NoUI = 2, -    BackgroundIndirectDisplay = 3, +    PartialForeground = 1, +    NoUi = 2, +    PartialForegroundIndirectDisplay = 3,      AllForegroundInitiallyHidden = 4,  }; diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp index fbf75d379..034c62f32 100644 --- a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp @@ -68,9 +68,9 @@ void SoftwareKeyboard::Initialize() {      case LibraryAppletMode::AllForeground:          InitializeForeground();          break; -    case LibraryAppletMode::Background: -    case LibraryAppletMode::BackgroundIndirectDisplay: -        InitializeBackground(applet_mode); +    case LibraryAppletMode::PartialForeground: +    case LibraryAppletMode::PartialForegroundIndirectDisplay: +        InitializePartialForeground(applet_mode);          break;      default:          ASSERT_MSG(false, "Invalid LibraryAppletMode={}", applet_mode); @@ -243,7 +243,7 @@ void SoftwareKeyboard::InitializeForeground() {      InitializeFrontendNormalKeyboard();  } -void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mode) { +void SoftwareKeyboard::InitializePartialForeground(LibraryAppletMode library_applet_mode) {      LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet.");      is_background = true; @@ -258,9 +258,9 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mod                  swkbd_inline_initialize_arg.size());      if (swkbd_initialize_arg.library_applet_mode_flag) { -        ASSERT(library_applet_mode == LibraryAppletMode::Background); +        ASSERT(library_applet_mode == LibraryAppletMode::PartialForeground);      } else { -        ASSERT(library_applet_mode == LibraryAppletMode::BackgroundIndirectDisplay); +        ASSERT(library_applet_mode == LibraryAppletMode::PartialForegroundIndirectDisplay);      }  } diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.h b/src/core/hle/service/am/frontend/applet_software_keyboard.h index f464b7e15..2a7d01b96 100644 --- a/src/core/hle/service/am/frontend/applet_software_keyboard.h +++ b/src/core/hle/service/am/frontend/applet_software_keyboard.h @@ -62,7 +62,7 @@ private:      void InitializeForeground();      /// Initializes the inline software keyboard. -    void InitializeBackground(LibraryAppletMode library_applet_mode); +    void InitializePartialForeground(LibraryAppletMode library_applet_mode);      /// Processes the text check sent by the application.      void ProcessTextCheck(); diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp index 47bab7528..ee646bea5 100644 --- a/src/core/hle/service/am/library_applet_creator.cpp +++ b/src/core/hle/service/am/library_applet_creator.cpp @@ -87,7 +87,7 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {      // Set focus state      switch (mode) {      case LibraryAppletMode::AllForeground: -    case LibraryAppletMode::NoUI: +    case LibraryAppletMode::NoUi:          applet->focus_state = FocusState::InFocus;          applet->hid_registration.EnableAppletToGetInput(true);          applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); @@ -99,8 +99,8 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {          applet->hid_registration.EnableAppletToGetInput(false);          applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);          break; -    case LibraryAppletMode::Background: -    case LibraryAppletMode::BackgroundIndirectDisplay: +    case LibraryAppletMode::PartialForeground: +    case LibraryAppletMode::PartialForegroundIndirectDisplay:      default:          applet->focus_state = FocusState::Background;          applet->hid_registration.EnableAppletToGetInput(true); diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp index 0289f5cf1..b92663b2b 100644 --- a/src/core/hle/service/am/self_controller.cpp +++ b/src/core/hle/service/am/self_controller.cpp @@ -288,7 +288,8 @@ void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {  }  Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { -    if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) { +    if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id, +                                                 applet->library_applet_mode)) {          return ResultSuccess;      } diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp index 60a9afc9d..3cccc5388 100644 --- a/src/core/hle/service/am/system_buffer_manager.cpp +++ b/src/core/hle/service/am/system_buffer_manager.cpp @@ -17,11 +17,12 @@ SystemBufferManager::~SystemBufferManager() {      // Clean up shared layers.      if (m_buffer_sharing_enabled) { +        m_nvnflinger->GetSystemBufferManager().Finalize(m_process);      }  }  bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, -                                     AppletId applet_id) { +                                     AppletId applet_id, LibraryAppletMode mode) {      if (m_nvnflinger) {          return m_buffer_sharing_enabled;      } @@ -36,9 +37,14 @@ bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel:          return false;      } +    Nvnflinger::LayerBlending blending = Nvnflinger::LayerBlending::None; +    if (mode == LibraryAppletMode::PartialForeground) { +        blending = Nvnflinger::LayerBlending::Coverage; +    } +      const auto display_id = m_nvnflinger->OpenDisplay("Default").value();      const auto res = m_nvnflinger->GetSystemBufferManager().Initialize( -        &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id); +        m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending);      if (res.IsSuccess()) {          m_buffer_sharing_enabled = true; diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h index 98c3cf055..0690f68b6 100644 --- a/src/core/hle/service/am/system_buffer_manager.h +++ b/src/core/hle/service/am/system_buffer_manager.h @@ -27,7 +27,8 @@ public:      SystemBufferManager();      ~SystemBufferManager(); -    bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id); +    bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id, +                    LibraryAppletMode mode);      void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,                                      u64* out_system_shared_layer_id) { diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index abe95303e..995646e25 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -15,6 +15,22 @@  namespace Service::Nvidia::Devices { +namespace { + +Tegra::BlendMode ConvertBlending(Service::Nvnflinger::LayerBlending blending) { +    switch (blending) { +    case Service::Nvnflinger::LayerBlending::None: +    default: +        return Tegra::BlendMode::Opaque; +    case Service::Nvnflinger::LayerBlending::Premultiplied: +        return Tegra::BlendMode::Premultiplied; +    case Service::Nvnflinger::LayerBlending::Coverage: +        return Tegra::BlendMode::Coverage; +    } +} + +} // namespace +  nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core)      : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {}  nvdisp_disp0::~nvdisp_disp0() = default; @@ -56,6 +72,7 @@ void nvdisp_disp0::Composite(std::span<const Nvnflinger::HwcLayer> sorted_layers              .pixel_format = layer.format,              .transform_flags = layer.transform,              .crop_rect = layer.crop_rect, +            .blending = ConvertBlending(layer.blending),          });          for (size_t i = 0; i < layer.acquire_fence.num_fences; i++) { diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp index e71652cdf..6a7da0cae 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp @@ -14,24 +14,19 @@  #include "core/hle/service/nvnflinger/ui/graphic_buffer.h"  #include "core/hle/service/vi/layer/vi_layer.h"  #include "core/hle/service/vi/vi_results.h" +#include "video_core/gpu.h"  namespace Service::Nvnflinger {  namespace { -Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, -                                        std::unique_ptr<Kernel::KPageGroup>* out_page_group, -                                        Core::System& system, u32 size) { +Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group, +                                  Core::System& system, u32 size) {      using Core::Memory::YUZU_PAGESIZE;      // Allocate memory for the system shared buffer. -    // FIXME: Because the gmmu can only point to cpu addresses, we need -    //        to map this in the application space to allow it to be used. -    // FIXME: Add proper smmu emulation.      // FIXME: This memory belongs to vi's .data section.      auto& kernel = system.Kernel(); -    auto* process = system.ApplicationProcess(); -    auto& page_table = process->GetPageTable();      // Hold a temporary page group reference while we try to map it.      auto pg = std::make_unique<Kernel::KPageGroup>( @@ -43,6 +38,30 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address,          Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,                                               Kernel::KMemoryManager::Direction::FromBack))); +    // Fill the output data with red. +    for (auto& block : *pg) { +        u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress()); +        u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize()); + +        for (; start < end; start++) { +            *start = 0xFF0000FF; +        } +    } + +    // Return the mapped page group. +    *out_page_group = std::move(pg); + +    // We succeeded. +    R_SUCCEED(); +} + +Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address, +                                              std::unique_ptr<Kernel::KPageGroup>& pg, +                                              Kernel::KProcess* process, Core::System& system) { +    using Core::Memory::YUZU_PAGESIZE; + +    auto& page_table = process->GetPageTable(); +      // Get bounds of where mapping is possible.      const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart());      const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE; @@ -64,9 +83,6 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address,      // Return failure, if necessary      R_UNLESS(i < 64, res); -    // Return the mapped page group. -    *out_page_group = std::move(pg); -      // We succeeded.      R_SUCCEED();  } @@ -135,6 +151,13 @@ Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::D      R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd));  } +void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) { +    auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); +    ASSERT(nvmap != nullptr); + +    R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd)); +} +  constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;  constexpr u32 SharedBufferBlockLinearBpp = 4; @@ -186,53 +209,97 @@ FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& fli  FbShareBufferManager::~FbShareBufferManager() = default; -Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u64 display_id) { +Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, +                                        u64* out_layer_handle, u64 display_id, +                                        LayerBlending blending) {      std::scoped_lock lk{m_guard}; -    // Ensure we have not already created a buffer. -    R_UNLESS(m_buffer_id == 0, VI::ResultOperationFailed); +    // Ensure we haven't already created. +    const u64 aruid = owner_process->GetProcessId(); +    R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied); + +    // Allocate memory for the shared buffer if needed. +    if (!m_buffer_page_group) { +        R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system, +                                         SharedBufferSize)); -    // Allocate memory and space for the shared buffer. -    Common::ProcessAddress map_address; -    R_TRY(AllocateIoForProcessAddressSpace(std::addressof(map_address), -                                           std::addressof(m_buffer_page_group), m_system, -                                           SharedBufferSize)); +        // Record buffer id. +        m_buffer_id = m_next_buffer_id++; + +        // Record display id. +        m_display_id = display_id; +    } + +    // Map into process. +    Common::ProcessAddress map_address{}; +    R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group, +                                                 owner_process, m_system)); + +    // Create new session. +    auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{}); +    auto& session = it->second;      auto& container = m_nvdrv->GetContainer(); -    m_session_id = container.OpenSession(m_system.ApplicationProcess()); -    m_nvmap_fd = m_nvdrv->Open("/dev/nvmap", m_session_id); +    session.session_id = container.OpenSession(owner_process); +    session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);      // Create an nvmap handle for the buffer and assign the memory to it. -    R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, m_nvmap_fd, -                                  map_address, SharedBufferSize)); - -    // Record the display id. -    m_display_id = display_id; +    R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv, +                                  session.nvmap_fd, map_address, SharedBufferSize));      // Create and open a layer for the display. -    m_layer_id = m_flinger.CreateLayer(m_display_id).value(); -    m_flinger.OpenLayer(m_layer_id); - -    // Set up the buffer. -    m_buffer_id = m_next_buffer_id++; +    session.layer_id = m_flinger.CreateLayer(m_display_id, blending).value(); +    m_flinger.OpenLayer(session.layer_id);      // Get the layer. -    VI::Layer* layer = m_flinger.FindLayer(m_display_id, m_layer_id); +    VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id);      ASSERT(layer != nullptr);      // Get the producer and set preallocated buffers.      auto& producer = layer->GetBufferQueue(); -    MakeGraphicBuffer(producer, 0, m_buffer_nvmap_handle); -    MakeGraphicBuffer(producer, 1, m_buffer_nvmap_handle); +    MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle); +    MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle);      // Assign outputs.      *out_buffer_id = m_buffer_id; -    *out_layer_id = m_layer_id; +    *out_layer_handle = session.layer_id;      // We succeeded.      R_SUCCEED();  } +void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) { +    std::scoped_lock lk{m_guard}; + +    if (m_buffer_id == 0) { +        return; +    } + +    const u64 aruid = owner_process->GetProcessId(); +    const auto it = m_sessions.find(aruid); +    if (it == m_sessions.end()) { +        return; +    } + +    auto& session = it->second; + +    // Destroy the layer. +    m_flinger.DestroyLayer(session.layer_id); + +    // Close nvmap handle. +    FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); + +    // Close nvmap device. +    m_nvdrv->Close(session.nvmap_fd); + +    // Close session. +    auto& container = m_nvdrv->GetContainer(); +    container.CloseSession(session.session_id); + +    // Erase. +    m_sessions.erase(it); +} +  Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,                                                             s32* out_nvmap_handle,                                                             SharedMemoryPoolLayout* out_pool_layout, @@ -242,17 +309,18 @@ Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,      R_UNLESS(m_buffer_id > 0, VI::ResultNotFound);      R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound); +    R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound);      *out_pool_layout = SharedBufferPoolLayout;      *out_buffer_size = SharedBufferSize; -    *out_nvmap_handle = m_buffer_nvmap_handle; +    *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle;      R_SUCCEED();  }  Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) {      // Ensure the layer id is valid. -    R_UNLESS(m_layer_id > 0 && layer_id == m_layer_id, VI::ResultNotFound); +    R_UNLESS(layer_id > 0, VI::ResultNotFound);      // Get the layer.      VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id); @@ -309,6 +377,10 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,                   android::Status::NoError,               VI::ResultOperationFailed); +    ON_RESULT_FAILURE { +        producer.CancelBuffer(static_cast<s32>(slot), fence); +    }; +      // Queue the buffer to the producer.      android::QueueBufferInput input{};      android::QueueBufferOutput output{}; @@ -342,4 +414,12 @@ Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadab      R_SUCCEED();  } +Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, +                                                      s32* out_layer_index) { +    // TODO +    *out_was_written = true; +    *out_layer_index = 1; +    R_SUCCEED(); +} +  } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h index 033bf4bbe..b79a7d23a 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h @@ -3,9 +3,12 @@  #pragma once +#include <map> +  #include "common/math_util.h"  #include "core/hle/service/nvdrv/core/container.h"  #include "core/hle/service/nvdrv/nvdata.h" +#include "core/hle/service/nvnflinger/hwc_layer.h"  #include "core/hle/service/nvnflinger/nvnflinger.h"  #include "core/hle/service/nvnflinger/ui/fence.h" @@ -29,13 +32,18 @@ struct SharedMemoryPoolLayout {  };  static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); +struct FbShareSession; +  class FbShareBufferManager final {  public:      explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger,                                    std::shared_ptr<Nvidia::Module> nvdrv);      ~FbShareBufferManager(); -    Result Initialize(u64* out_buffer_id, u64* out_layer_handle, u64 display_id); +    Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, +                      u64 display_id, LayerBlending blending); +    void Finalize(Kernel::KProcess* owner_process); +      Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,                                           SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id,                                           u64 applet_resource_user_id); @@ -45,6 +53,8 @@ public:                                      u32 transform, s32 swap_interval, u64 layer_id, s64 slot);      Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); +    Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); +  private:      Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); @@ -52,11 +62,8 @@ private:      u64 m_next_buffer_id = 1;      u64 m_display_id = 0;      u64 m_buffer_id = 0; -    u64 m_layer_id = 0; -    u32 m_buffer_nvmap_handle = 0;      SharedMemoryPoolLayout m_pool_layout = {}; -    Nvidia::DeviceFD m_nvmap_fd = {}; -    Nvidia::NvCore::SessionId m_session_id = {}; +    std::map<u64, FbShareSession> m_sessions;      std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;      std::mutex m_guard; @@ -65,4 +72,11 @@ private:      std::shared_ptr<Nvidia::Module> m_nvdrv;  }; +struct FbShareSession { +    Nvidia::DeviceFD nvmap_fd = {}; +    Nvidia::NvCore::SessionId session_id = {}; +    u64 layer_id = {}; +    u32 buffer_nvmap_handle = 0; +}; +  } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp index ba2b5c28c..be7eb97a3 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.cpp +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp @@ -86,6 +86,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,              .height = igbp_buffer.Height(),              .stride = igbp_buffer.Stride(),              .z_index = 0, +            .blending = layer.GetBlending(),              .transform = static_cast<android::BufferTransformFlags>(item.transform),              .crop_rect = item.crop,              .acquire_fence = item.fence, diff --git a/src/core/hle/service/nvnflinger/hwc_layer.h b/src/core/hle/service/nvnflinger/hwc_layer.h index 3af668a25..f71a5d822 100644 --- a/src/core/hle/service/nvnflinger/hwc_layer.h +++ b/src/core/hle/service/nvnflinger/hwc_layer.h @@ -11,6 +11,18 @@  namespace Service::Nvnflinger { +// hwc_layer_t::blending values +enum class LayerBlending : u32 { +    // No blending +    None = 0x100, + +    // ONE / ONE_MINUS_SRC_ALPHA +    Premultiplied = 0x105, + +    // SRC_ALPHA / ONE_MINUS_SRC_ALPHA +    Coverage = 0x405, +}; +  struct HwcLayer {      u32 buffer_handle;      u32 offset; @@ -19,6 +31,7 @@ struct HwcLayer {      u32 height;      u32 stride;      s32 z_index; +    LayerBlending blending;      android::BufferTransformFlags transform;      Common::Rectangle<int> crop_rect;      android::Fence acquire_fence; diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index d8ba89d43..687ccc9f9 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -157,7 +157,7 @@ bool Nvnflinger::CloseDisplay(u64 display_id) {      return true;  } -std::optional<u64> Nvnflinger::CreateLayer(u64 display_id) { +std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) {      const auto lock_guard = Lock();      auto* const display = FindDisplay(display_id); @@ -166,13 +166,14 @@ std::optional<u64> Nvnflinger::CreateLayer(u64 display_id) {      }      const u64 layer_id = next_layer_id++; -    CreateLayerAtId(*display, layer_id); +    CreateLayerAtId(*display, layer_id, blending);      return layer_id;  } -void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { +void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) {      const auto buffer_id = next_buffer_queue_id++;      display.CreateLayer(layer_id, buffer_id, nvdrv->container); +    display.FindLayer(layer_id)->SetBlending(blending);  }  bool Nvnflinger::OpenLayer(u64 layer_id) { diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index c984d55a0..4cf4f069d 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -15,6 +15,7 @@  #include "common/thread.h"  #include "core/hle/result.h"  #include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nvnflinger/hwc_layer.h"  namespace Common {  class Event; @@ -72,7 +73,8 @@ public:      /// Creates a layer on the specified display and returns the layer ID.      ///      /// If an invalid display ID is specified, then an empty optional is returned. -    [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); +    [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id, +                                                 LayerBlending blending = LayerBlending::None);      /// Opens a layer on all displays for the given layer ID.      bool OpenLayer(u64 layer_id); @@ -128,7 +130,7 @@ private:      [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);      /// Creates a layer with the specified layer ID in the desired display. -    void CreateLayerAtId(VI::Display& display, u64 layer_id); +    void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending);      void SplitVSync(std::stop_token stop_token); diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp index 493bd6e9e..eca35d82a 100644 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ b/src/core/hle/service/vi/layer/vi_layer.cpp @@ -1,6 +1,7 @@  // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/nvnflinger/hwc_layer.h"  #include "core/hle/service/vi/layer/vi_layer.h"  namespace Service::VI { @@ -8,8 +9,9 @@ namespace Service::VI {  Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,               android::BufferQueueProducer& binder_,               std::shared_ptr<android::BufferItemConsumer>&& consumer_) -    : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, -      consumer{std::move(consumer_)}, open{false}, visible{true} {} +    : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move( +                                                                                    consumer_)}, +      blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {}  Layer::~Layer() = default; diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index b4b031ee7..14e229903 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h @@ -14,6 +14,10 @@ class BufferQueueCore;  class BufferQueueProducer;  } // namespace Service::android +namespace Service::Nvnflinger { +enum class LayerBlending : u32; +} +  namespace Service::VI {  /// Represents a single display layer. @@ -92,12 +96,21 @@ public:          return !std::exchange(open, true);      } +    Nvnflinger::LayerBlending GetBlending() { +        return blending; +    } + +    void SetBlending(Nvnflinger::LayerBlending b) { +        blending = b; +    } +  private:      const u64 layer_id;      const u32 binder_id;      android::BufferQueueCore& core;      android::BufferQueueProducer& binder;      std::shared_ptr<android::BufferItemConsumer> consumer; +    Service::Nvnflinger::LayerBlending blending;      bool open;      bool visible;  }; | 
