Core: Fix get nvmap object random crash
This commit is contained in:
parent
fe24c65153
commit
9982cff98b
|
@ -207,6 +207,19 @@ void NvMap::UnpinHandle(Handle::Id handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NvMap::DuplicateHandle(Handle::Id handle) {
|
||||||
|
auto handle_description{GetHandle(handle)};
|
||||||
|
if (!handle_description) {
|
||||||
|
LOG_CRITICAL(Service_NVDRV, "Unregistered handle!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = handle_description->Duplicate(false);
|
||||||
|
if (result != NvResult::Success) {
|
||||||
|
LOG_CRITICAL(Service_NVDRV, "Could not duplicate handle!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
|
std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
|
||||||
std::weak_ptr<Handle> hWeak{GetHandle(handle)};
|
std::weak_ptr<Handle> hWeak{GetHandle(handle)};
|
||||||
FreeInfo freeInfo;
|
FreeInfo freeInfo;
|
||||||
|
@ -254,7 +267,7 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
|
||||||
|
|
||||||
// Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed
|
// Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed
|
||||||
if (!hWeak.expired()) {
|
if (!hWeak.expired()) {
|
||||||
LOG_ERROR(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
|
LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
|
||||||
freeInfo.address = 0;
|
freeInfo.address = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void UnpinHandle(Handle::Id handle);
|
void UnpinHandle(Handle::Id handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tries to duplicate a handle
|
||||||
|
*/
|
||||||
|
void DuplicateHandle(Handle::Id handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Tries to free a handle and remove a single dupe
|
* @brief Tries to free a handle and remove a single dupe
|
||||||
* @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned
|
* @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned
|
||||||
|
|
|
@ -69,18 +69,6 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
void nvmap::OnOpen(DeviceFD fd) {}
|
void nvmap::OnOpen(DeviceFD fd) {}
|
||||||
void nvmap::OnClose(DeviceFD fd) {}
|
void nvmap::OnClose(DeviceFD fd) {}
|
||||||
|
|
||||||
VAddr nvmap::GetObjectAddress(u32 handle) const {
|
|
||||||
auto obj = file.GetHandle(handle);
|
|
||||||
if (obj) {
|
|
||||||
return obj->address;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<NvCore::NvMap::Handle> nvmap::GetObject(u32 handle) const {
|
|
||||||
return file.GetHandle(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
IocCreateParams params;
|
IocCreateParams params;
|
||||||
std::memcpy(¶ms, input.data(), sizeof(params));
|
std::memcpy(¶ms, input.data(), sizeof(params));
|
||||||
|
|
|
@ -36,11 +36,6 @@ public:
|
||||||
void OnOpen(DeviceFD fd) override;
|
void OnOpen(DeviceFD fd) override;
|
||||||
void OnClose(DeviceFD fd) override;
|
void OnClose(DeviceFD fd) override;
|
||||||
|
|
||||||
/// Returns the allocated address of an nvmap object given its handle.
|
|
||||||
VAddr GetObjectAddress(u32 handle) const;
|
|
||||||
|
|
||||||
std::shared_ptr<NvCore::NvMap::Handle> GetObject(u32 handle) const;
|
|
||||||
|
|
||||||
enum class HandleParameterType : u32_le {
|
enum class HandleParameterType : u32_le {
|
||||||
Size = 1,
|
Size = 1,
|
||||||
Alignment = 2,
|
Alignment = 2,
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class EventInterface;
|
friend class EventInterface;
|
||||||
|
friend class Service::NVFlinger::NVFlinger;
|
||||||
|
|
||||||
/// Id to use for the next open file descriptor.
|
/// Id to use for the next open file descriptor.
|
||||||
DeviceFD next_fd = 1;
|
DeviceFD next_fd = 1;
|
||||||
|
@ -111,8 +112,6 @@ private:
|
||||||
/// Manages syncpoints on the host
|
/// Manages syncpoints on the host
|
||||||
NvCore::Container container;
|
NvCore::Container container;
|
||||||
|
|
||||||
void CreateEvent(u32 event_id);
|
|
||||||
void FreeEvent(u32 event_id);
|
|
||||||
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
|
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,18 @@
|
||||||
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
|
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/nvmap.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_item.h"
|
#include "core/hle/service/nvflinger/buffer_item.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
|
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
||||||
#include "core/hle/service/nvflinger/producer_listener.h"
|
#include "core/hle/service/nvflinger/producer_listener.h"
|
||||||
|
#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
|
||||||
|
|
||||||
namespace Service::android {
|
namespace Service::android {
|
||||||
|
|
||||||
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
|
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
|
||||||
: core{std::move(core_)}, slots{core->slots} {}
|
Service::Nvidia::NvCore::NvMap& nvmap_)
|
||||||
|
: core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
|
||||||
|
|
||||||
BufferQueueConsumer::~BufferQueueConsumer() = default;
|
BufferQueueConsumer::~BufferQueueConsumer() = default;
|
||||||
|
|
||||||
|
@ -133,6 +136,8 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
|
||||||
|
|
||||||
slots[slot].buffer_state = BufferState::Free;
|
slots[slot].buffer_state = BufferState::Free;
|
||||||
|
|
||||||
|
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), false);
|
||||||
|
|
||||||
listener = core->connected_producer_listener;
|
listener = core->connected_producer_listener;
|
||||||
|
|
||||||
LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);
|
LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_defs.h"
|
#include "core/hle/service/nvflinger/buffer_queue_defs.h"
|
||||||
#include "core/hle/service/nvflinger/status.h"
|
#include "core/hle/service/nvflinger/status.h"
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
class NvMap;
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
||||||
|
|
||||||
namespace Service::android {
|
namespace Service::android {
|
||||||
|
|
||||||
class BufferItem;
|
class BufferItem;
|
||||||
|
@ -21,7 +25,8 @@ class IConsumerListener;
|
||||||
|
|
||||||
class BufferQueueConsumer final {
|
class BufferQueueConsumer final {
|
||||||
public:
|
public:
|
||||||
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
|
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
|
||||||
|
Service::Nvidia::NvCore::NvMap& nvmap_);
|
||||||
~BufferQueueConsumer();
|
~BufferQueueConsumer();
|
||||||
|
|
||||||
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
|
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
|
||||||
|
@ -32,6 +37,7 @@ public:
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<BufferQueueCore> core;
|
std::shared_ptr<BufferQueueCore> core;
|
||||||
BufferQueueDefs::SlotsType& slots;
|
BufferQueueDefs::SlotsType& slots;
|
||||||
|
Service::Nvidia::NvCore::NvMap& nvmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::android
|
} // namespace Service::android
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "core/hle/kernel/k_writable_event.h"
|
#include "core/hle/kernel/k_writable_event.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
#include "core/hle/service/nvdrv/core/nvmap.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_producer.h"
|
#include "core/hle/service/nvflinger/buffer_queue_producer.h"
|
||||||
#include "core/hle/service/nvflinger/consumer_listener.h"
|
#include "core/hle/service/nvflinger/consumer_listener.h"
|
||||||
|
@ -26,8 +26,10 @@
|
||||||
namespace Service::android {
|
namespace Service::android {
|
||||||
|
|
||||||
BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
|
BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
|
||||||
std::shared_ptr<BufferQueueCore> buffer_queue_core_)
|
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
|
||||||
: service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots) {
|
Service::Nvidia::NvCore::NvMap& nvmap_)
|
||||||
|
: service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots),
|
||||||
|
nvmap(nvmap_) {
|
||||||
buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
|
buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,6 +532,8 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
|
||||||
item.is_droppable = core->dequeue_buffer_cannot_block || async;
|
item.is_droppable = core->dequeue_buffer_cannot_block || async;
|
||||||
item.swap_interval = swap_interval;
|
item.swap_interval = swap_interval;
|
||||||
|
|
||||||
|
nvmap.DuplicateHandle(item.graphic_buffer->BufferId());
|
||||||
|
|
||||||
sticky_transform = sticky_transform_;
|
sticky_transform = sticky_transform_;
|
||||||
|
|
||||||
if (core->queue.empty()) {
|
if (core->queue.empty()) {
|
||||||
|
|
|
@ -31,6 +31,10 @@ namespace Service::KernelHelpers {
|
||||||
class ServiceContext;
|
class ServiceContext;
|
||||||
} // namespace Service::KernelHelpers
|
} // namespace Service::KernelHelpers
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
class NvMap;
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
||||||
|
|
||||||
namespace Service::android {
|
namespace Service::android {
|
||||||
|
|
||||||
class BufferQueueCore;
|
class BufferQueueCore;
|
||||||
|
@ -39,7 +43,8 @@ class IProducerListener;
|
||||||
class BufferQueueProducer final : public IBinder {
|
class BufferQueueProducer final : public IBinder {
|
||||||
public:
|
public:
|
||||||
explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
|
explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
|
||||||
std::shared_ptr<BufferQueueCore> buffer_queue_core_);
|
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
|
||||||
|
Service::Nvidia::NvCore::NvMap& nvmap_);
|
||||||
~BufferQueueProducer();
|
~BufferQueueProducer();
|
||||||
|
|
||||||
void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override;
|
void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override;
|
||||||
|
@ -78,6 +83,8 @@ private:
|
||||||
s32 next_callback_ticket{};
|
s32 next_callback_ticket{};
|
||||||
s32 current_callback_ticket{};
|
s32 current_callback_ticket{};
|
||||||
std::condition_variable_any callback_condition;
|
std::condition_variable_any callback_condition;
|
||||||
|
|
||||||
|
Service::Nvidia::NvCore::NvMap& nvmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::android
|
} // namespace Service::android
|
||||||
|
|
|
@ -149,7 +149,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
|
||||||
|
|
||||||
void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
|
void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
|
||||||
const auto buffer_id = next_buffer_queue_id++;
|
const auto buffer_id = next_buffer_queue_id++;
|
||||||
display.CreateLayer(layer_id, buffer_id);
|
display.CreateLayer(layer_id, buffer_id, nvdrv->container);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NVFlinger::CloseLayer(u64 layer_id) {
|
void NVFlinger::CloseLayer(u64 layer_id) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/k_writable_event.h"
|
#include "core/hle/kernel/k_writable_event.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_item_consumer.h"
|
#include "core/hle/service/nvflinger/buffer_item_consumer.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
|
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
||||||
|
@ -29,11 +30,13 @@ struct BufferQueue {
|
||||||
std::unique_ptr<android::BufferQueueConsumer> consumer;
|
std::unique_ptr<android::BufferQueueConsumer> consumer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context) {
|
static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context,
|
||||||
|
Service::Nvidia::NvCore::NvMap& nvmap) {
|
||||||
auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
|
auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
|
||||||
return {buffer_queue_core,
|
return {
|
||||||
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core),
|
buffer_queue_core,
|
||||||
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
|
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
|
||||||
|
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)};
|
||||||
}
|
}
|
||||||
|
|
||||||
Display::Display(u64 id, std::string name_,
|
Display::Display(u64 id, std::string name_,
|
||||||
|
@ -74,10 +77,11 @@ void Display::SignalVSyncEvent() {
|
||||||
vsync_event->GetWritableEvent().Signal();
|
vsync_event->GetWritableEvent().Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::CreateLayer(u64 layer_id, u32 binder_id) {
|
void Display::CreateLayer(u64 layer_id, u32 binder_id,
|
||||||
|
Service::Nvidia::NvCore::Container& nv_core) {
|
||||||
ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
|
ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
|
||||||
|
|
||||||
auto [core, producer, consumer] = CreateBufferQueue(service_context);
|
auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile());
|
||||||
|
|
||||||
auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
|
auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
|
||||||
buffer_item_consumer->Connect(false);
|
buffer_item_consumer->Connect(false);
|
||||||
|
|
|
@ -27,6 +27,11 @@ namespace Service::NVFlinger {
|
||||||
class HosBinderDriverServer;
|
class HosBinderDriverServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
class Container;
|
||||||
|
class NvMap;
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
||||||
|
|
||||||
namespace Service::VI {
|
namespace Service::VI {
|
||||||
|
|
||||||
class Layer;
|
class Layer;
|
||||||
|
@ -93,7 +98,7 @@ public:
|
||||||
/// @param layer_id The ID to assign to the created layer.
|
/// @param layer_id The ID to assign to the created layer.
|
||||||
/// @param binder_id The ID assigned to the buffer queue.
|
/// @param binder_id The ID assigned to the buffer queue.
|
||||||
///
|
///
|
||||||
void CreateLayer(u64 layer_id, u32 binder_id);
|
void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
|
||||||
|
|
||||||
/// Closes and removes a layer from this display with the given ID.
|
/// Closes and removes a layer from this display with the given ID.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue