215 lines
6.6 KiB
C++
215 lines
6.6 KiB
C++
#include <cstring>
|
|
#include <mutex>
|
|
#include <stdexcept>
|
|
|
|
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/General.hpp"
|
|
#include "prx/libSceVideoOut/include/VideoOutDriver.hpp"
|
|
|
|
static int validateOutputConfig(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, uint64_t reserved) {
|
|
if (!VideoOutDriver::Get().IsOpen(handle)) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
if (reservedPtr != nullptr || reserved != 0) {
|
|
return VIDEO_OUT_ERROR_INVALID_VALUE;
|
|
}
|
|
if (options != nullptr) {
|
|
for (auto v : options->internalData) {
|
|
if (v != 0) {
|
|
return VIDEO_OUT_ERROR_INVALID_OPTION;
|
|
}
|
|
}
|
|
}
|
|
if (mode != VIDEO_OUT_OUTPUT_MODE_DEFAULT && mode != VIDEO_OUT_OUTPUT_MODE_119_88HZ) {
|
|
return VIDEO_OUT_ERROR_UNSUPPORTED_OUTPUT_MODE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param) {
|
|
(void)param;
|
|
if (userId != 255 && userId != 0) {
|
|
return VIDEO_OUT_ERROR_INVALID_VALUE;
|
|
}
|
|
if (busType != VIDEO_OUT_BUS_TYPE_MAIN && busType != VIDEO_OUT_BUS_TYPE_OVERLAY && busType != VIDEO_OUT_BUS_TYPE_SUB) {
|
|
return VIDEO_OUT_ERROR_INVALID_VALUE;
|
|
}
|
|
if (index != 0) {
|
|
return VIDEO_OUT_ERROR_INVALID_VALUE;
|
|
}
|
|
const int handle = VideoOutDriver::Get().Open(busType);
|
|
if (handle < 0) {
|
|
return VIDEO_OUT_ERROR_RESOURCE_BUSY;
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutClose(int handle) {
|
|
return VideoOutDriver::Get().Close(handle) ? 0 : VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutSetFlipRate(int handle, int rate) {
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
if (rate < 0 || rate > 2) {
|
|
return VIDEO_OUT_ERROR_INVALID_VALUE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
cfg->flipRate = rate;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutGetFlipStatus(int handle, VideoOutFlipStatus* status) {
|
|
if (status == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
|
}
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
*status = cfg->flipStatus;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutGetVblankStatus(int handle, VideoOutVblankStatus* status) {
|
|
if (status == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
|
}
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
*status = cfg->vblankStatus;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutGetOutputStatus(int handle, VideoOutOutputStatus* status) {
|
|
if (status == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
|
}
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
status->resolution = (cfg->width >= 3840 || cfg->height >= 2160) ? 2u : 1u;
|
|
status->dynamicRange = 1;
|
|
status->refreshRate = (cfg->outputMode == VIDEO_OUT_OUTPUT_MODE_119_88HZ) ? VIDEO_OUT_REFRESH_RATE_119_88HZ : VIDEO_OUT_REFRESH_RATE_59_94HZ;
|
|
status->flags = 0;
|
|
status->reserved[0] = 0;
|
|
status->reserved[1] = 0;
|
|
status->reserved[2] = 0;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutIsFlipPending(int handle) {
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
return cfg->flipStatus.flipPendingNum;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutWaitVblank(int handle) {
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
const uint64_t count = cfg->vblankStatus.count;
|
|
while (cfg->opened && cfg->vblankStatus.count == count) {
|
|
cfg->vblankCond.wait(lock);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutInitializeOutputOptions(VideoOutOutputOptions* options) {
|
|
if (options == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
|
}
|
|
std::memset(options, 0, sizeof(VideoOutOutputOptions));
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutIsOutputSupported(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, uint64_t reserved) {
|
|
const int result = validateOutputConfig(handle, mode, options, reservedPtr, reserved);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
return (mode == VIDEO_OUT_OUTPUT_MODE_119_88HZ) ? 0 : 1;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutConfigureOutput(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, uint64_t reserved) {
|
|
const int supported = sceVideoOutIsOutputSupported(handle, mode, options, reservedPtr, reserved);
|
|
if (supported < 0) {
|
|
return supported;
|
|
}
|
|
if (supported == 0 && mode == VIDEO_OUT_OUTPUT_MODE_119_88HZ) {
|
|
return VIDEO_OUT_ERROR_UNAVAILABLE_OUTPUT_MODE;
|
|
}
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
cfg->outputMode = mode;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutSetWindowModeMargins(int handle, int top, int bottom) {
|
|
(void)top;
|
|
(void)bottom;
|
|
if (!VideoOutDriver::Get().IsOpen(handle)) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutLatencyControlWaitBeforeInput(int handle) {
|
|
if (!VideoOutDriver::Get().IsOpen(handle)) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutLatencyMeasureSetStartPoint(int handle, uint32_t point) {
|
|
(void)point;
|
|
if (!VideoOutDriver::Get().IsOpen(handle)) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutColorSettingsSetGamma(VideoOutColorSettings* settings, float gamma) {
|
|
if (settings == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
|
}
|
|
if (gamma < 0.1f || gamma > 2.0f) {
|
|
return VIDEO_OUT_ERROR_INVALID_VALUE;
|
|
}
|
|
settings->gamma = gamma;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceVideoOutAdjustColor(int handle, const VideoOutColorSettings* settings) {
|
|
if (settings == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
|
}
|
|
auto* cfg = VideoOutDriver::Get().GetConfig(handle);
|
|
if (cfg == nullptr) {
|
|
return VIDEO_OUT_ERROR_INVALID_HANDLE;
|
|
}
|
|
std::unique_lock lock(cfg->mutex);
|
|
cfg->gamma = settings->gamma;
|
|
return 0;
|
|
}
|
|
|
|
}
|