mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 15:25:28 +03:00
Make GraphicBufferProducer use the new nvmap API
This commit is contained in:
parent
c97f5a9315
commit
1149158198
@ -6,13 +6,18 @@
|
|||||||
#include <gpu.h>
|
#include <gpu.h>
|
||||||
#include <gpu/texture/format.h>
|
#include <gpu/texture/format.h>
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
#include <services/nvdrv/driver.h>
|
|
||||||
#include <services/nvdrv/devices/nvmap.h>
|
#include <services/nvdrv/devices/nvmap.h>
|
||||||
#include <services/common/fence.h>
|
#include <services/common/fence.h>
|
||||||
#include "GraphicBufferProducer.h"
|
#include "GraphicBufferProducer.h"
|
||||||
|
|
||||||
namespace skyline::service::hosbinder {
|
namespace skyline::service::hosbinder {
|
||||||
GraphicBufferProducer::GraphicBufferProducer(const DeviceState &state) : state(state), bufferEvent(std::make_shared<kernel::type::KEvent>(state, true)) {}
|
GraphicBufferProducer::GraphicBufferProducer(const DeviceState &state, nvdrv::core::NvMap &nvMap) : state(state), bufferEvent(std::make_shared<kernel::type::KEvent>(state, true)), nvMap(nvMap) {}
|
||||||
|
|
||||||
|
void GraphicBufferProducer::FreeGraphicBufferNvMap(GraphicBuffer &buffer) {
|
||||||
|
auto surface{buffer.graphicHandle.surfaces.at(0)};
|
||||||
|
u32 nvMapHandleId{surface.nvmapHandle ? surface.nvmapHandle : buffer.graphicHandle.nvmapId};
|
||||||
|
nvMap.FreeHandle(nvMapHandleId, true);
|
||||||
|
}
|
||||||
|
|
||||||
u32 GraphicBufferProducer::GetPendingBufferCount() {
|
u32 GraphicBufferProducer::GetPendingBufferCount() {
|
||||||
u32 count{};
|
u32 count{};
|
||||||
@ -64,6 +69,12 @@ namespace skyline::service::hosbinder {
|
|||||||
for (auto &slot : queue) {
|
for (auto &slot : queue) {
|
||||||
slot.state = BufferState::Free;
|
slot.state = BufferState::Free;
|
||||||
slot.frameNumber = std::numeric_limits<u32>::max();
|
slot.frameNumber = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
|
if (slot.texture) {
|
||||||
|
slot.texture = {};
|
||||||
|
FreeGraphicBufferNvMap(*slot.graphicBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
slot.graphicBuffer = nullptr;
|
slot.graphicBuffer = nullptr;
|
||||||
}
|
}
|
||||||
} else if (preallocatedBufferCount < count) {
|
} else if (preallocatedBufferCount < count) {
|
||||||
@ -160,6 +171,12 @@ namespace skyline::service::hosbinder {
|
|||||||
|
|
||||||
bufferSlot.state = BufferState::Free;
|
bufferSlot.state = BufferState::Free;
|
||||||
bufferSlot.frameNumber = std::numeric_limits<u32>::max();
|
bufferSlot.frameNumber = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
|
if (bufferSlot.texture) {
|
||||||
|
bufferSlot.texture = {};
|
||||||
|
FreeGraphicBufferNvMap(*bufferSlot.graphicBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
bufferSlot.graphicBuffer = nullptr;
|
bufferSlot.graphicBuffer = nullptr;
|
||||||
|
|
||||||
bufferEvent->Signal();
|
bufferEvent->Signal();
|
||||||
@ -183,6 +200,12 @@ namespace skyline::service::hosbinder {
|
|||||||
|
|
||||||
bufferSlot->state = BufferState::Free;
|
bufferSlot->state = BufferState::Free;
|
||||||
bufferSlot->frameNumber = std::numeric_limits<u32>::max();
|
bufferSlot->frameNumber = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
|
if (bufferSlot->texture) {
|
||||||
|
bufferSlot->texture = {};
|
||||||
|
FreeGraphicBufferNvMap(*bufferSlot->graphicBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
graphicBuffer = *std::exchange(bufferSlot->graphicBuffer, nullptr);
|
graphicBuffer = *std::exchange(bufferSlot->graphicBuffer, nullptr);
|
||||||
fence = AndroidFence{};
|
fence = AndroidFence{};
|
||||||
|
|
||||||
@ -202,6 +225,11 @@ namespace skyline::service::hosbinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bufferSlot->texture) {
|
||||||
|
bufferSlot->texture = {};
|
||||||
|
FreeGraphicBufferNvMap(*bufferSlot->graphicBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (bufferSlot == queue.end()) {
|
if (bufferSlot == queue.end()) {
|
||||||
state.logger->Warn("Could not find any free slots to attach the graphic buffer to");
|
state.logger->Warn("Could not find any free slots to attach the graphic buffer to");
|
||||||
return AndroidStatus::NoMemory;
|
return AndroidStatus::NoMemory;
|
||||||
@ -304,27 +332,13 @@ namespace skyline::service::hosbinder {
|
|||||||
if (surface.scanFormat != NvDisplayScanFormat::Progressive)
|
if (surface.scanFormat != NvDisplayScanFormat::Progressive)
|
||||||
throw exception("Non-Progressive surfaces are not supported: {}", ToString(surface.scanFormat));
|
throw exception("Non-Progressive surfaces are not supported: {}", ToString(surface.scanFormat));
|
||||||
|
|
||||||
std::shared_ptr<nvdrv::device::NvMap::NvMapObject> nvBuffer{};
|
// Duplicate the handle so it can't be freed by the guest
|
||||||
{
|
auto nvMapHandleObj{nvMap.GetHandle(surface.nvmapHandle ? surface.nvmapHandle : handle.nvmapId)};
|
||||||
auto driver{nvdrv::driver.lock()};
|
if (auto err{nvMapHandleObj->Duplicate(true)}; err != PosixResult::Success)
|
||||||
auto nvmap{driver->nvMap.lock()};
|
throw exception("Failed to duplicate graphic buffer NvMap handle: {}!", static_cast<i32>(err));
|
||||||
if (surface.nvmapHandle) {
|
|
||||||
nvBuffer = nvmap->GetObject(surface.nvmapHandle);
|
|
||||||
} else {
|
|
||||||
std::shared_lock nvmapLock(nvmap->mapMutex);
|
|
||||||
for (const auto &object : nvmap->maps) {
|
|
||||||
if (object->id == handle.nvmapId) {
|
|
||||||
nvBuffer = object;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!nvBuffer)
|
|
||||||
throw exception("A QueueBuffer request has an invalid NvMap Handle ({}) and ID ({})", surface.nvmapHandle, handle.nvmapId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface.size > (nvBuffer->size - surface.offset))
|
if (surface.size > (nvMapHandleObj->origSize - surface.offset))
|
||||||
throw exception("Surface doesn't fit into NvMap mapping of size 0x{:X} when mapped at 0x{:X} -> 0x{:X}", nvBuffer->size, surface.offset, surface.offset + surface.size);
|
throw exception("Surface doesn't fit into NvMap mapping of size 0x{:X} when mapped at 0x{:X} -> 0x{:X}", nvMapHandleObj->origSize, surface.offset, surface.offset + surface.size);
|
||||||
|
|
||||||
gpu::texture::TileMode tileMode;
|
gpu::texture::TileMode tileMode;
|
||||||
gpu::texture::TileConfig tileConfig{};
|
gpu::texture::TileConfig tileConfig{};
|
||||||
@ -344,7 +358,7 @@ namespace skyline::service::hosbinder {
|
|||||||
throw exception("Legacy 16Bx16 tiled surfaces are not supported");
|
throw exception("Legacy 16Bx16 tiled surfaces are not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto guestTexture{std::make_shared<gpu::GuestTexture>(state, nvBuffer->ptr + surface.offset, gpu::texture::Dimensions(surface.width, surface.height), format, tileMode, tileConfig)};
|
auto guestTexture{std::make_shared<gpu::GuestTexture>(state, nvMapHandleObj->GetPointer() + surface.offset, gpu::texture::Dimensions(surface.width, surface.height), format, tileMode, tileConfig)};
|
||||||
buffer.texture = guestTexture->CreateTexture({}, vk::ImageTiling::eLinear);
|
buffer.texture = guestTexture->CreateTexture({}, vk::ImageTiling::eLinear);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,6 +543,12 @@ namespace skyline::service::hosbinder {
|
|||||||
for (auto &slot : queue) {
|
for (auto &slot : queue) {
|
||||||
slot.state = BufferState::Free;
|
slot.state = BufferState::Free;
|
||||||
slot.frameNumber = std::numeric_limits<u32>::max();
|
slot.frameNumber = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
|
if (slot.texture) {
|
||||||
|
slot.texture = {};
|
||||||
|
FreeGraphicBufferNvMap(*slot.graphicBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
slot.graphicBuffer = nullptr;
|
slot.graphicBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,12 +564,16 @@ namespace skyline::service::hosbinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto &buffer{queue[slot]};
|
auto &buffer{queue[slot]};
|
||||||
|
if (buffer.texture) {
|
||||||
|
buffer.texture = {};
|
||||||
|
FreeGraphicBufferNvMap(*buffer.graphicBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
buffer.state = BufferState::Free;
|
buffer.state = BufferState::Free;
|
||||||
buffer.frameNumber = 0;
|
buffer.frameNumber = 0;
|
||||||
buffer.wasBufferRequested = false;
|
buffer.wasBufferRequested = false;
|
||||||
buffer.isPreallocated = graphicBuffer != nullptr;
|
buffer.isPreallocated = graphicBuffer != nullptr;
|
||||||
buffer.graphicBuffer = graphicBuffer ? std::make_unique<GraphicBuffer>(*graphicBuffer) : nullptr;
|
buffer.graphicBuffer = graphicBuffer ? std::make_unique<GraphicBuffer>(*graphicBuffer) : nullptr;
|
||||||
buffer.texture = {};
|
|
||||||
|
|
||||||
if (graphicBuffer) {
|
if (graphicBuffer) {
|
||||||
if (graphicBuffer->magic != GraphicBuffer::Magic)
|
if (graphicBuffer->magic != GraphicBuffer::Magic)
|
||||||
|
@ -14,6 +14,10 @@ namespace skyline::gpu {
|
|||||||
class Texture;
|
class Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace skyline::service::nvdrv::core {
|
||||||
|
class NvMap;
|
||||||
|
}
|
||||||
|
|
||||||
namespace skyline::service::hosbinder {
|
namespace skyline::service::hosbinder {
|
||||||
/**
|
/**
|
||||||
* @url https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferSlot.h;l=52-91
|
* @url https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferSlot.h;l=52-91
|
||||||
@ -66,6 +70,9 @@ namespace skyline::service::hosbinder {
|
|||||||
AndroidPixelFormat defaultFormat{AndroidPixelFormat::RGBA8888}; //!< The assumed format of a buffer if none is supplied in DequeueBuffer
|
AndroidPixelFormat defaultFormat{AndroidPixelFormat::RGBA8888}; //!< The assumed format of a buffer if none is supplied in DequeueBuffer
|
||||||
NativeWindowApi connectedApi{NativeWindowApi::None}; //!< The API that the producer is currently connected to
|
NativeWindowApi connectedApi{NativeWindowApi::None}; //!< The API that the producer is currently connected to
|
||||||
u64 frameNumber{}; //!< The amount of frames that have been presented so far
|
u64 frameNumber{}; //!< The amount of frames that have been presented so far
|
||||||
|
nvdrv::core::NvMap &nvMap;
|
||||||
|
|
||||||
|
void FreeGraphicBufferNvMap(GraphicBuffer &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The amount of buffers which have been queued onto the consumer
|
* @return The amount of buffers which have been queued onto the consumer
|
||||||
@ -180,7 +187,7 @@ namespace skyline::service::hosbinder {
|
|||||||
SetPreallocatedBuffer = 14, //!< A transaction specific to HOS, see the implementation for a description of its functionality
|
SetPreallocatedBuffer = 14, //!< A transaction specific to HOS, see the implementation for a description of its functionality
|
||||||
};
|
};
|
||||||
|
|
||||||
GraphicBufferProducer(const DeviceState &state);
|
GraphicBufferProducer(const DeviceState &state, nvdrv::core::NvMap &nvmap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The handler for Binder IPC transactions with IGraphicBufferProducer
|
* @brief The handler for Binder IPC transactions with IGraphicBufferProducer
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "GraphicBufferProducer.h"
|
#include "GraphicBufferProducer.h"
|
||||||
|
|
||||||
namespace skyline::service::hosbinder {
|
namespace skyline::service::hosbinder {
|
||||||
IHOSBinderDriver::IHOSBinderDriver(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {}
|
IHOSBinderDriver::IHOSBinderDriver(const DeviceState &state, ServiceManager &manager, nvdrv::core::NvMap &nvMap) : BaseService(state, manager), nvMap(nvMap) {}
|
||||||
|
|
||||||
Result IHOSBinderDriver::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result IHOSBinderDriver::TransactParcel(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
// We opted for just supporting a single layer and display as it's what basically all games use and wasting cycles on it is pointless
|
// We opted for just supporting a single layer and display as it's what basically all games use and wasting cycles on it is pointless
|
||||||
@ -122,7 +122,7 @@ namespace skyline::service::hosbinder {
|
|||||||
|
|
||||||
layerStrongReferenceCount = InitialStrongReferenceCount;
|
layerStrongReferenceCount = InitialStrongReferenceCount;
|
||||||
layerWeakReferenceCount = 0;
|
layerWeakReferenceCount = 0;
|
||||||
layer.emplace(state);
|
layer.emplace(state, nvMap);
|
||||||
|
|
||||||
return DefaultLayerId;
|
return DefaultLayerId;
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,10 @@ namespace skyline::service::hosbinder {
|
|||||||
constexpr static u32 DefaultBinderLayerHandle{1}; //!< The handle as assigned by SurfaceFlinger of the default layer
|
constexpr static u32 DefaultBinderLayerHandle{1}; //!< The handle as assigned by SurfaceFlinger of the default layer
|
||||||
std::optional<GraphicBufferProducer> layer; //!< The IGraphicBufferProducer backing the layer (NativeWindow)
|
std::optional<GraphicBufferProducer> layer; //!< The IGraphicBufferProducer backing the layer (NativeWindow)
|
||||||
|
|
||||||
|
nvdrv::core::NvMap &nvMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IHOSBinderDriver(const DeviceState &state, ServiceManager &manager);
|
IHOSBinderDriver(const DeviceState &state, ServiceManager &manager, nvdrv::core::NvMap &nvMap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Emulates the transaction of parcels between a IGraphicBufferProducer and the application
|
* @brief Emulates the transaction of parcels between a IGraphicBufferProducer and the application
|
||||||
|
Loading…
Reference in New Issue
Block a user