rpcsx/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp

345 lines
11 KiB
C++
Raw Normal View History

#include "stdafx.h"
2016-03-21 20:43:03 +01:00
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/IdManager.h"
#include "Emu/RSX/rsx_utils.h"
2016-03-21 20:43:03 +01:00
#include "cellVideoOut.h"
2016-05-13 15:55:34 +02:00
extern logs::channel cellSysutil;
2016-03-21 20:43:03 +01:00
2017-05-20 13:45:02 +02:00
const extern std::unordered_map<video_resolution, std::pair<int, int>, value_hash<video_resolution>> g_video_out_resolution_map
2016-03-21 20:43:03 +01:00
{
2017-05-20 13:45:02 +02:00
{ video_resolution::_1080, { 1920, 1080 } },
{ video_resolution::_720, { 1280, 720 } },
{ video_resolution::_480, { 720, 480 } },
{ video_resolution::_576, { 720, 576 } },
{ video_resolution::_1600x1080, { 1600, 1080 } },
{ video_resolution::_1440x1080, { 1440, 1080 } },
{ video_resolution::_1280x1080, { 1280, 1080 } },
{ video_resolution::_960x1080, { 960, 1080 } },
};
const extern std::unordered_map<video_resolution, CellVideoOutResolutionId, value_hash<video_resolution>> g_video_out_resolution_id
2016-03-21 20:43:03 +01:00
{
2017-05-20 13:45:02 +02:00
{ video_resolution::_1080, CELL_VIDEO_OUT_RESOLUTION_1080 },
{ video_resolution::_720, CELL_VIDEO_OUT_RESOLUTION_720 },
{ video_resolution::_480, CELL_VIDEO_OUT_RESOLUTION_480 },
{ video_resolution::_576, CELL_VIDEO_OUT_RESOLUTION_576 },
{ video_resolution::_1600x1080, CELL_VIDEO_OUT_RESOLUTION_1600x1080 },
{ video_resolution::_1440x1080, CELL_VIDEO_OUT_RESOLUTION_1440x1080 },
{ video_resolution::_1280x1080, CELL_VIDEO_OUT_RESOLUTION_1280x1080 },
{ video_resolution::_960x1080, CELL_VIDEO_OUT_RESOLUTION_960x1080 },
};
2016-03-21 20:43:03 +01:00
2017-05-20 13:45:02 +02:00
const extern std::unordered_map<video_aspect, CellVideoOutDisplayAspect, value_hash<video_aspect>> g_video_out_aspect_id
2016-03-21 20:43:03 +01:00
{
2017-05-20 13:45:02 +02:00
{ video_aspect::_16_9, CELL_VIDEO_OUT_ASPECT_16_9 },
{ video_aspect::_4_3, CELL_VIDEO_OUT_ASPECT_4_3 },
2016-03-21 20:43:03 +01:00
};
template<>
void fmt_class_string<CellVideoOutError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(CELL_VIDEO_OUT_ERROR_NOT_IMPLEMENTED);
STR_CASE(CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION);
STR_CASE(CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER);
STR_CASE(CELL_VIDEO_OUT_ERROR_PARAMETER_OUT_OF_RANGE);
STR_CASE(CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND);
STR_CASE(CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT);
STR_CASE(CELL_VIDEO_OUT_ERROR_UNSUPPORTED_DISPLAY_MODE);
STR_CASE(CELL_VIDEO_OUT_ERROR_CONDITION_BUSY);
STR_CASE(CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET);
}
return unknown;
});
}
error_code cellVideoOutGetNumberOfDevice(u32 videoOut);
error_code cellVideoOutGetState(u32 videoOut, u32 deviceIndex, vm::ptr<CellVideoOutState> state)
2016-03-21 20:43:03 +01:00
{
cellSysutil.trace("cellVideoOutGetState(videoOut=%d, deviceIndex=%d, state=*0x%x)", videoOut, deviceIndex, state);
if (!state)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
2020-01-19 14:46:28 +01:00
const auto device_count = cellVideoOutGetNumberOfDevice(videoOut);
if (device_count < 0 || deviceIndex >= static_cast<u32>(device_count))
{
return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND;
}
2016-03-21 20:43:03 +01:00
switch (videoOut)
{
case CELL_VIDEO_OUT_PRIMARY:
state->state = CELL_VIDEO_OUT_OUTPUT_STATE_ENABLED;
state->colorSpace = CELL_VIDEO_OUT_COLOR_SPACE_RGB;
2017-05-20 13:45:02 +02:00
state->displayMode.resolutionId = g_video_out_resolution_id.at(g_cfg.video.resolution); // TODO
2016-03-21 20:43:03 +01:00
state->displayMode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE;
state->displayMode.conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE;
2017-05-20 13:45:02 +02:00
state->displayMode.aspect = g_video_out_aspect_id.at(g_cfg.video.aspect_ratio); // TODO
2016-03-21 20:43:03 +01:00
state->displayMode.refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ;
return CELL_OK;
case CELL_VIDEO_OUT_SECONDARY:
*state = { CELL_VIDEO_OUT_OUTPUT_STATE_DISABLED }; // ???
return CELL_OK;
}
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
error_code cellVideoOutGetResolution(u32 resolutionId, vm::ptr<CellVideoOutResolution> resolution)
2016-03-21 20:43:03 +01:00
{
cellSysutil.trace("cellVideoOutGetResolution(resolutionId=0x%x, resolution=*0x%x)", resolutionId, resolution);
if (!resolution)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
switch (resolutionId)
{
case 0x01: *resolution = { 0x780, 0x438 }; break;
case 0x02: *resolution = { 0x500, 0x2d0 }; break;
case 0x04: *resolution = { 0x2d0, 0x1e0 }; break;
case 0x05: *resolution = { 0x2d0, 0x240 }; break;
case 0x0a: *resolution = { 0x640, 0x438 }; break;
case 0x0b: *resolution = { 0x5a0, 0x438 }; break;
case 0x0c: *resolution = { 0x500, 0x438 }; break;
case 0x0d: *resolution = { 0x3c0, 0x438 }; break;
case 0x64: *resolution = { 0x550, 0x300 }; break;
case 0x81: *resolution = { 0x500, 0x5be }; break;
case 0x82: *resolution = { 0x780, 0x438 }; break;
case 0x83: *resolution = { 0x780, 0x89d }; break;
case 0x8b: *resolution = { 0x280, 0x5be }; break;
case 0x8a: *resolution = { 0x320, 0x5be }; break;
case 0x89: *resolution = { 0x3c0, 0x5be }; break;
case 0x88: *resolution = { 0x400, 0x5be }; break;
case 0x91: *resolution = { 0x500, 0x5be }; break;
case 0x92: *resolution = { 0x780, 0x438 }; break;
case 0x9b: *resolution = { 0x280, 0x5be }; break;
case 0x9a: *resolution = { 0x320, 0x5be }; break;
case 0x99: *resolution = { 0x3c0, 0x5be }; break;
case 0x98: *resolution = { 0x400, 0x5be }; break;
case 0xa1: *resolution = { 0x780, 0x438 }; break;
2019-08-25 14:04:20 +02:00
2016-03-21 20:43:03 +01:00
default: return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
return CELL_OK;
}
error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option, u32 waitForEvent)
2016-03-21 20:43:03 +01:00
{
2017-08-18 22:44:07 +02:00
cellSysutil.todo("cellVideoOutConfigure(videoOut=%d, config=*0x%x, option=*0x%x, waitForEvent=%d)", videoOut, config, option, waitForEvent);
2016-03-21 20:43:03 +01:00
2017-08-18 22:44:07 +02:00
if (!config)
2016-03-21 20:43:03 +01:00
{
2017-08-18 22:44:07 +02:00
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
2016-03-21 20:43:03 +01:00
2017-08-18 22:44:07 +02:00
if (!config->pitch)
{
return CELL_VIDEO_OUT_ERROR_PARAMETER_OUT_OF_RANGE;
2016-03-21 20:43:03 +01:00
}
2017-08-18 22:44:07 +02:00
if (config->resolutionId == 0x92 || config->resolutionId == 0xa1)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
2018-12-26 02:38:20 +01:00
bool found = false;
video_resolution res;
for (const auto& ares : g_video_out_resolution_id)
{
if (ares.second == config->resolutionId)
{
found = true;
res = ares.first;
break;
}
}
if (!found)
{
cellSysutil.error("Unusual resolution requested: 0x%x", config->resolutionId);
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_DISPLAY_MODE;
}
auto& res_info = g_video_out_resolution_map.at(res);
2019-08-25 14:04:20 +02:00
auto conf = g_fxo->get<rsx::avconf>();
conf->aspect = config->aspect;
conf->format = config->format;
conf->scanline_pitch = config->pitch;
conf->resolution_x = u32(res_info.first);
conf->resolution_y = u32(res_info.second);
2019-08-25 14:04:20 +02:00
conf->state = 1;
2017-08-18 22:44:07 +02:00
return CELL_OK;
2016-03-21 20:43:03 +01:00
}
error_code cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option)
2016-03-21 20:43:03 +01:00
{
cellSysutil.warning("cellVideoOutGetConfiguration(videoOut=%d, config=*0x%x, option=*0x%x)", videoOut, config, option);
if (!config)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
2016-03-21 20:43:03 +01:00
if (option) *option = {};
*config = {};
switch (videoOut)
{
case CELL_VIDEO_OUT_PRIMARY:
2017-05-20 13:45:02 +02:00
config->resolutionId = g_video_out_resolution_id.at(g_cfg.video.resolution);
2016-03-21 20:43:03 +01:00
config->format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8;
2017-05-20 13:45:02 +02:00
config->aspect = g_video_out_aspect_id.at(g_cfg.video.aspect_ratio);
config->pitch = 4 * g_video_out_resolution_map.at(g_cfg.video.resolution).first;
2016-03-21 20:43:03 +01:00
return CELL_OK;
case CELL_VIDEO_OUT_SECONDARY:
return CELL_OK;
}
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
error_code cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr<CellVideoOutDeviceInfo> info)
2016-03-21 20:43:03 +01:00
{
cellSysutil.warning("cellVideoOutGetDeviceInfo(videoOut=%d, deviceIndex=%d, info=*0x%x)", videoOut, deviceIndex, info);
if (!info)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
2020-01-19 14:46:28 +01:00
const auto device_count = cellVideoOutGetNumberOfDevice(videoOut);
if (device_count < 0 || deviceIndex >= static_cast<u32>(device_count))
{
return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND;
}
2016-03-21 20:43:03 +01:00
// Use standard dummy values for now.
info->portType = CELL_VIDEO_OUT_PORT_HDMI;
info->colorSpace = CELL_VIDEO_OUT_COLOR_SPACE_RGB;
2016-12-05 18:35:05 +01:00
info->latency = 100;
2016-03-21 20:43:03 +01:00
info->availableModeCount = 1;
info->state = CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE;
info->rgbOutputRange = 1;
info->colorInfo.blueX = 0xFFFF;
info->colorInfo.blueY = 0xFFFF;
info->colorInfo.greenX = 0xFFFF;
info->colorInfo.greenY = 0xFFFF;
info->colorInfo.redX = 0xFFFF;
info->colorInfo.redY = 0xFFFF;
info->colorInfo.whiteX = 0xFFFF;
info->colorInfo.whiteY = 0xFFFF;
info->colorInfo.gamma = 100;
2017-05-20 13:45:02 +02:00
info->availableModes[0].aspect = g_video_out_aspect_id.at(g_cfg.video.aspect_ratio);
2016-12-05 18:35:05 +01:00
info->availableModes[0].conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE;
info->availableModes[0].refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_60HZ | CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ;
2017-05-20 13:45:02 +02:00
info->availableModes[0].resolutionId = g_video_out_resolution_id.at(g_cfg.video.resolution);
2016-12-05 18:35:05 +01:00
info->availableModes[0].scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE;
2016-03-21 20:43:03 +01:00
return CELL_OK;
}
error_code cellVideoOutGetNumberOfDevice(u32 videoOut)
2016-03-21 20:43:03 +01:00
{
cellSysutil.warning("cellVideoOutGetNumberOfDevice(videoOut=%d)", videoOut);
switch (videoOut)
{
2016-08-15 17:30:33 +02:00
case CELL_VIDEO_OUT_PRIMARY: return not_an_error(1);
case CELL_VIDEO_OUT_SECONDARY: return not_an_error(0);
2016-03-21 20:43:03 +01:00
}
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
error_code cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option)
2016-03-21 20:43:03 +01:00
{
cellSysutil.warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, aspect=%d, option=%d)", videoOut, resolutionId, aspect, option);
switch (videoOut)
{
2016-12-05 18:35:05 +01:00
case CELL_VIDEO_OUT_PRIMARY: return not_an_error(
2017-05-20 13:45:02 +02:00
resolutionId == g_video_out_resolution_id.at(g_cfg.video.resolution)
&& (aspect == CELL_VIDEO_OUT_ASPECT_AUTO || aspect == g_video_out_aspect_id.at(g_cfg.video.aspect_ratio))
2016-12-05 18:35:05 +01:00
);
2016-08-15 17:30:33 +02:00
case CELL_VIDEO_OUT_SECONDARY: return not_an_error(0);
2016-03-21 20:43:03 +01:00
}
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
2019-11-15 20:15:00 +01:00
error_code cellVideoOutConfigure2()
2019-04-05 20:14:01 +02:00
{
cellSysutil.todo("cellVideoOutConfigure2()");
return CELL_OK;
2019-04-05 20:14:01 +02:00
}
2019-11-15 20:15:00 +01:00
error_code cellVideoOutGetResolutionAvailability2()
2019-04-05 20:14:01 +02:00
{
cellSysutil.todo("cellVideoOutGetResolutionAvailability2()");
return CELL_OK;
2019-04-05 20:14:01 +02:00
}
2019-11-15 20:15:00 +01:00
error_code cellVideoOutGetConvertCursorColorInfo(vm::ptr<u8> rgbOutputRange)
2016-03-21 20:43:03 +01:00
{
cellSysutil.todo("cellVideoOutGetConvertCursorColorInfo()");
return CELL_OK;
2016-03-21 20:43:03 +01:00
}
2019-11-15 20:15:00 +01:00
error_code cellVideoOutDebugSetMonitorType(u32 videoOut, u32 monitorType)
2016-03-21 20:43:03 +01:00
{
cellSysutil.todo("cellVideoOutDebugSetMonitorType()");
return CELL_OK;
2016-03-21 20:43:03 +01:00
}
2019-11-15 20:15:00 +01:00
error_code cellVideoOutRegisterCallback(u32 slot, vm::ptr<CellVideoOutCallback> function, vm::ptr<void> userData)
2016-03-21 20:43:03 +01:00
{
cellSysutil.todo("cellVideoOutRegisterCallback()");
return CELL_OK;
2016-03-21 20:43:03 +01:00
}
2019-11-15 20:15:00 +01:00
error_code cellVideoOutUnregisterCallback(u32 slot)
2016-03-21 20:43:03 +01:00
{
cellSysutil.todo("cellVideoOutUnregisterCallback()");
return CELL_OK;
2016-03-21 20:43:03 +01:00
}
void cellSysutil_VideoOut_init()
{
REG_FUNC(cellSysutil, cellVideoOutGetState);
REG_FUNC(cellSysutil, cellVideoOutGetResolution).flag(MFF_PERFECT);
2016-03-21 20:43:03 +01:00
REG_FUNC(cellSysutil, cellVideoOutConfigure);
2019-04-05 20:14:01 +02:00
REG_FUNC(cellSysutil, cellVideoOutConfigure2);
2016-03-21 20:43:03 +01:00
REG_FUNC(cellSysutil, cellVideoOutGetConfiguration);
REG_FUNC(cellSysutil, cellVideoOutGetDeviceInfo);
REG_FUNC(cellSysutil, cellVideoOutGetNumberOfDevice);
REG_FUNC(cellSysutil, cellVideoOutGetResolutionAvailability);
2019-04-05 20:14:01 +02:00
REG_FUNC(cellSysutil, cellVideoOutGetResolutionAvailability2);
2016-03-21 20:43:03 +01:00
REG_FUNC(cellSysutil, cellVideoOutGetConvertCursorColorInfo);
REG_FUNC(cellSysutil, cellVideoOutDebugSetMonitorType);
REG_FUNC(cellSysutil, cellVideoOutRegisterCallback);
REG_FUNC(cellSysutil, cellVideoOutUnregisterCallback);
}