diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 813b5286e..23d7ca476 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -181,6 +181,44 @@ int VideoOutDriver::UnregisterBuffers(VideoOutPort* port, s32 attributeIndex) { return ORBIS_OK; } +int VideoOutDriver::ChangeBufferAttribute(VideoOutPort* port, s32 attributeIndex, + const BufferAttribute* attribute) { + if (attributeIndex >= MaxDisplayBufferGroups || !port->groups[attributeIndex].is_occupied) { + LOG_ERROR(Lib_VideoOut, "Invalid attribute index {}", attributeIndex); + return ORBIS_VIDEO_OUT_ERROR_INVALID_VALUE; + } + + if (attribute->reserved0 != 0 || attribute->reserved1 != 0) { + LOG_ERROR(Lib_VideoOut, "Invalid reserved members"); + return ORBIS_VIDEO_OUT_ERROR_INVALID_VALUE; + } + if (attribute->aspect_ratio != 0) { + LOG_ERROR(Lib_VideoOut, "Invalid aspect ratio = {}", attribute->aspect_ratio); + return ORBIS_VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO; + } + if (attribute->width > attribute->pitch_in_pixel) { + LOG_ERROR(Lib_VideoOut, "Buffer width {} is larger than pitch {}", attribute->width, + attribute->pitch_in_pixel); + return ORBIS_VIDEO_OUT_ERROR_INVALID_PITCH; + } + if (attribute->tiling_mode < TilingMode::Tile || attribute->tiling_mode > TilingMode::Linear) { + LOG_ERROR(Lib_VideoOut, "Invalid tilingMode = {}", + static_cast(attribute->tiling_mode)); + return ORBIS_VIDEO_OUT_ERROR_INVALID_TILING_MODE; + } + + LOG_INFO(Lib_VideoOut, + "attributeIndex = {}, pixelFormat = {}, aspectRatio = {}, " + "tilingMode = {}, width = {}, height = {}, pitchInPixel = {}, option = {:#x}", + attributeIndex, GetPixelFormatString(attribute->pixel_format), attribute->aspect_ratio, + static_cast(attribute->tiling_mode), attribute->width, attribute->height, + attribute->pitch_in_pixel, attribute->option); + + std::unique_lock lock{port->port_mutex}; + std::memcpy(&port->groups[attributeIndex].attrib, attribute, sizeof(BufferAttribute)); + return 0; +} + void VideoOutDriver::Flip(const Request& req) { // Update HDR status before presenting. presenter->SetHDR(req.port->is_hdr); diff --git a/src/core/libraries/videoout/driver.h b/src/core/libraries/videoout/driver.h index 96bd58500..253ec0958 100644 --- a/src/core/libraries/videoout/driver.h +++ b/src/core/libraries/videoout/driver.h @@ -87,6 +87,8 @@ public: int RegisterBuffers(VideoOutPort* port, s32 startIndex, void* const* addresses, s32 bufferNum, const BufferAttribute* attribute); int UnregisterBuffers(VideoOutPort* port, s32 attributeIndex); + int ChangeBufferAttribute(VideoOutPort* port, s32 bufferIndex, + const BufferAttribute* attribute); bool SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false); diff --git a/src/core/libraries/videoout/video_out.cpp b/src/core/libraries/videoout/video_out.cpp index 7714eb2b5..1c0310972 100644 --- a/src/core/libraries/videoout/video_out.cpp +++ b/src/core/libraries/videoout/video_out.cpp @@ -449,6 +449,16 @@ s32 PS4_SYSV_ABI sceVideoOutConfigureOutputMode_(s32 handle, u32 reserved, const return ORBIS_OK; } +s32 PS4_SYSV_ABI sceVideoOutSubmitChangeBufferAttribute(s32 handle, s32 attributeIndex, + const BufferAttribute* attribute) { + auto* port = driver->GetPort(handle); + if (!port || !port->is_open) { + return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE; + } + + return driver->ChangeBufferAttribute(port, attributeIndex, attribute); +} + s32 PS4_SYSV_ABI sceVideoOutSetWindowModeMargins(s32 handle, s32 top, s32 bottom) { LOG_ERROR(Lib_VideoOut, "(STUBBED) called top = {}, bottom = {}", top, bottom); return ORBIS_OK; @@ -493,6 +503,8 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { sceVideoOutConfigureOutputMode_); LIB_FUNCTION("MTxxrOCeSig", "libSceVideoOut", 1, "libSceVideoOut", sceVideoOutSetWindowModeMargins); + LIB_FUNCTION("IOdgHlCGU-k", "libSceVideoOut", 1, "libSceVideoOut", + sceVideoOutSubmitChangeBufferAttribute); } } // namespace Libraries::VideoOut