Stub indirect layer VI service functions

Indirect layers are used by the game to render layer on its own, the game allocates a buffer with the size from `GetIndirectLayerImageRequiredMemoryInfo` and uses `GetIndirectLayerImageMap` to draw the applet contents into the buffer. 

As we don't LLE applet implementations nor do our HLE implementations draw equivalent applets, we cannot submit this to the guest. As a result, these functions are stubbed with the framebuffer being cleared to red. 

Stubbing these functions allows titles such as Dark Souls to not crash while initializing indirect layers.
This commit is contained in:
PixelyIon 2023-02-04 22:40:00 +05:30 committed by Mark Collins
parent dba191d2dc
commit 22f8cc5970
3 changed files with 49 additions and 0 deletions

View file

@ -124,4 +124,38 @@ namespace skyline::service::visrv {
return {};
}
Result IApplicationDisplayService::GetIndirectLayerImageMap(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto width{request.Pop<i64>()};
auto height{request.Pop<i64>()};
if (!request.outputBuf.empty()) {
// As we don't support indirect layers, we just fill the output buffer with red
auto imageBuffer{request.outputBuf.at(0)};
std::fill(imageBuffer.begin(), imageBuffer.end(), 0xFF0000FF);
}
response.Push<i64>(width);
response.Push<i64>(height);
return {};
}
Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
i64 width{request.Pop<i64>()}, height{request.Pop<i64>()};
if (width <= 0 || height <= 0)
return result::InvalidDimensions;
constexpr ssize_t A8B8G8R8Size{4}; //!< The size of a pixel in the A8B8G8R8 format, this format is used by indirect layers
i64 layerSize{width * height * A8B8G8R8Size};
constexpr ssize_t BlockSize{0x20000}; //!< The size of an arbitrarily defined block, the layer size must be aligned to a block
response.Push<i64>(util::AlignUpNpot<i64>(layerSize, BlockSize));
constexpr size_t DefaultAlignment{0x1000}; //!< The default alignment of the buffer
response.Push<u64>(DefaultAlignment);
return Result{};
}
}

View file

@ -88,6 +88,18 @@ namespace skyline::service::visrv {
*/
Result SetLayerScalingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Draws an indirect layer into the supplied buffer
* @url https://switchbrew.org/wiki/Display_services#GetIndirectLayerImageMap
*/
Result GetIndirectLayerImageMap(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Gets the amount of memory required for an indirect layer
* @url https://switchbrew.org/wiki/Display_services#GetIndirectLayerImageRequiredMemoryInfo
*/
Result GetIndirectLayerImageRequiredMemoryInfo(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Converts an arbitrary scaling mode to a VI scaling mode
*/
@ -113,6 +125,8 @@ namespace skyline::service::visrv {
SFUNC_BASE(0x7EF, IApplicationDisplayService, IDisplayService, DestroyStrayLayer),
SFUNC(0x835, IApplicationDisplayService, SetLayerScalingMode),
SFUNC(0x836, IApplicationDisplayService, ConvertScalingMode),
SFUNC(0x992, IApplicationDisplayService, GetIndirectLayerImageMap),
SFUNC(0x99C, IApplicationDisplayService, GetIndirectLayerImageRequiredMemoryInfo),
SFUNC(0x1452, IApplicationDisplayService, GetDisplayVsyncEvent)
)
};

View file

@ -7,5 +7,6 @@
namespace skyline::service::visrv::result {
constexpr Result InvalidArgument(114, 1);
constexpr Result InvalidDimensions(114, 4);
constexpr Result IllegalOperation(114, 6);
}