video: Allow selection of 3D stereo resolutions

This commit is contained in:
kd-11 2020-01-07 19:07:09 +03:00 committed by kd-11
parent 19107b2de5
commit 6e3406b3f5
6 changed files with 116 additions and 53 deletions

View File

@ -300,6 +300,14 @@ error_code cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
if (g_cfg.video.enable_3d)
{
// Return Playstation 3D display value
// Some games call this function when 3D is enabled
*screenSize = 24.f;
return CELL_OK;
}
// TODO: Use virtual screen size
#ifdef _WIN32
// HDC screen = GetDC(NULL);

View File

@ -8,6 +8,7 @@
LOG_CHANNEL(cellSysutil);
// NOTE: Unused in this module, but used by gs_frame to determine window size
const extern std::unordered_map<video_resolution, std::pair<int, int>, value_hash<video_resolution>> g_video_out_resolution_map
{
{ video_resolution::_1080, { 1920, 1080 } },
@ -62,6 +63,41 @@ void fmt_class_string<CellVideoOutError>::format(std::string& out, u64 arg)
error_code cellVideoOutGetNumberOfDevice(u32 videoOut);
error_code _IntGetResolutionInfo(u8 resolution_id, CellVideoOutResolution* resolution)
{
// NOTE: Some resolution IDs that return values on hw have unknown resolution enumerants
switch (resolution_id)
{
case CELL_VIDEO_OUT_RESOLUTION_1080: *resolution = { 0x780, 0x438 }; break;
case CELL_VIDEO_OUT_RESOLUTION_720: *resolution = { 0x500, 0x2d0 }; break;
case CELL_VIDEO_OUT_RESOLUTION_480: *resolution = { 0x2d0, 0x1e0 }; break;
case CELL_VIDEO_OUT_RESOLUTION_576: *resolution = { 0x2d0, 0x240 }; break;
case CELL_VIDEO_OUT_RESOLUTION_1600x1080: *resolution = { 0x640, 0x438 }; break;
case CELL_VIDEO_OUT_RESOLUTION_1440x1080: *resolution = { 0x5a0, 0x438 }; break;
case CELL_VIDEO_OUT_RESOLUTION_1280x1080: *resolution = { 0x500, 0x438 }; break;
case CELL_VIDEO_OUT_RESOLUTION_960x1080: *resolution = { 0x3c0, 0x438 }; break;
case 0x64: *resolution = { 0x550, 0x300 }; break;
case CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING: *resolution = { 0x500, 0x5be }; break;
case 0x82: *resolution = { 0x780, 0x438 }; break;
case 0x83: *resolution = { 0x780, 0x89d }; break;
case CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING: *resolution = { 0x280, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING: *resolution = { 0x320, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING: *resolution = { 0x3c0, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING: *resolution = { 0x400, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_720_DUALVIEW_FRAME_PACKING: *resolution = { 0x500, 0x5be }; break;
case 0x92: *resolution = { 0x780, 0x438 }; break;
case CELL_VIDEO_OUT_RESOLUTION_640x720_DUALVIEW_FRAME_PACKING: *resolution = { 0x280, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_800x720_DUALVIEW_FRAME_PACKING: *resolution = { 0x320, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_960x720_DUALVIEW_FRAME_PACKING: *resolution = { 0x3c0, 0x5be }; break;
case CELL_VIDEO_OUT_RESOLUTION_1024x720_DUALVIEW_FRAME_PACKING: *resolution = { 0x400, 0x5be }; break;
case 0xa1: *resolution = { 0x780, 0x438 }; break;
default: return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}
return CELL_OK;
}
error_code cellVideoOutGetState(u32 videoOut, u32 deviceIndex, vm::ptr<CellVideoOutState> state)
{
cellSysutil.trace("cellVideoOutGetState(videoOut=%d, deviceIndex=%d, state=*0x%x)", videoOut, deviceIndex, state);
@ -90,6 +126,7 @@ error_code cellVideoOutGetState(u32 videoOut, u32 deviceIndex, vm::ptr<CellVideo
state->displayMode.conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE;
state->displayMode.aspect = conf->state? conf->aspect : g_video_out_aspect_id.at(g_cfg.video.aspect_ratio);
state->displayMode.refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ;
return CELL_OK;
}
@ -110,36 +147,15 @@ error_code cellVideoOutGetResolution(u32 resolutionId, vm::ptr<CellVideoOutResol
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;
CellVideoOutResolution res;
error_code result;
default: return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
if (result = _IntGetResolutionInfo(resolutionId, &res); result == CELL_OK)
{
*resolution = res;
}
return CELL_OK;
return result;
}
error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option, u32 waitForEvent)
@ -161,34 +177,23 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration
return CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
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)
CellVideoOutResolution res;
if (_IntGetResolutionInfo(config->resolutionId, &res) != CELL_OK ||
(config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING && !g_cfg.video.enable_3d))
{
// Resolution not supported
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);
auto conf = g_fxo->get<rsx::avconf>();
conf->resolution_id = config->resolutionId;
conf->_3d = config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING;
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);
conf->resolution_x = res.width;
conf->resolution_y = res.height;
conf->state = 1;
if (conf->aspect == CELL_VIDEO_OUT_ASPECT_AUTO)
@ -197,6 +202,8 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration
conf->aspect = g_video_out_aspect_id.at(g_cfg.video.aspect_ratio);
}
cellSysutil.notice("Selected video resolution 0x%x", config->resolutionId);
return CELL_OK;
}
@ -215,7 +222,8 @@ error_code cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfig
switch (videoOut)
{
case CELL_VIDEO_OUT_PRIMARY:
if (const auto conf = g_fxo->get<rsx::avconf>(); conf->state)
{
if (auto conf = g_fxo->get<rsx::avconf>(); conf->state)
{
config->resolutionId = conf->resolution_id;
config->format = conf->format;
@ -227,10 +235,15 @@ error_code cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfig
config->resolutionId = g_video_out_resolution_id.at(g_cfg.video.resolution);
config->format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8;
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;
CellVideoOutResolution res;
verify("Invalid video configuration" HERE), _IntGetResolutionInfo(config->resolutionId, &res) == CELL_OK;
config->pitch = 4 * res.width;
}
return CELL_OK;
}
case CELL_VIDEO_OUT_SECONDARY:
@ -277,6 +290,16 @@ error_code cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr<Cell
info->availableModes[0].refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_60HZ | CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ;
info->availableModes[0].resolutionId = g_video_out_resolution_id.at(g_cfg.video.resolution);
info->availableModes[0].scanMode = CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE;
if (g_cfg.video.enable_3d && g_cfg.video.resolution == video_resolution::_720)
{
// Register 3D-capable display mode
info->availableModes[1] = info->availableModes[0];
info->availableModes[1].conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_TO_720_3D_FRAME_PACKING;
info->availableModes[1].resolutionId = CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING;
info->availableModeCount++;
}
return CELL_OK;
}
@ -299,10 +322,38 @@ error_code cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId,
switch (videoOut)
{
case CELL_VIDEO_OUT_PRIMARY: return not_an_error(
resolutionId == g_video_out_resolution_id.at(g_cfg.video.resolution) + 0u
&& (aspect == CELL_VIDEO_OUT_ASPECT_AUTO || aspect == g_video_out_aspect_id.at(g_cfg.video.aspect_ratio) + 0u)
);
case CELL_VIDEO_OUT_PRIMARY:
{
// NOTE: Result is boolean
if (aspect != CELL_VIDEO_OUT_ASPECT_AUTO && aspect != static_cast<u32>(g_video_out_aspect_id.at(g_cfg.video.aspect_ratio)))
{
return not_an_error(0);
}
if (resolutionId == static_cast<u32>(g_video_out_resolution_id.at(g_cfg.video.resolution)))
{
// Perfect match
return not_an_error(1);
}
if (g_cfg.video.enable_3d && g_cfg.video.resolution == video_resolution::_720)
{
switch (resolutionId)
{
case CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING:
case CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING:
case CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING:
case CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING:
case CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING:
return not_an_error(1);
default:
break;
}
}
return not_an_error(0);
}
case CELL_VIDEO_OUT_SECONDARY: return not_an_error(0);
}

View File

@ -104,8 +104,9 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
if (!buffer_pitch)
buffer_pitch = buffer_width * avconfig->get_bpp();
const u32 video_frame_height = (!avconfig->_3d? avconfig->resolution_y : (avconfig->resolution_y - 30) / 2);
buffer_width = std::min(buffer_width, avconfig->resolution_x);
buffer_height = std::min(buffer_height, avconfig->resolution_y);
buffer_height = std::min(buffer_height, video_frame_height);
}
else
{

View File

@ -419,8 +419,9 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
if (!buffer_pitch)
buffer_pitch = buffer_width * avconfig->get_bpp();
const u32 video_frame_height = (!avconfig->_3d? avconfig->resolution_y : (avconfig->resolution_y - 30) / 2);
buffer_width = std::min(buffer_width, avconfig->resolution_x);
buffer_height = std::min(buffer_height, avconfig->resolution_y);
buffer_height = std::min(buffer_height, video_frame_height);
}
else
{

View File

@ -142,6 +142,7 @@ namespace rsx
struct avconf
{
bool _3d = false; // Stereo 3D off
u8 format = 0; // XRGB
u8 aspect = 0; // AUTO
u8 resolution_id = 2; // 720p

View File

@ -125,6 +125,7 @@ struct cfg_root : cfg::node
cfg::_bool disable_native_float16{ this, "Disable native float16 support", false };
cfg::_bool multithreaded_rsx{ this, "Multithreaded RSX", false };
cfg::_bool relaxed_zcull_sync{ this, "Relaxed ZCULL Sync", false };
cfg::_bool enable_3d{ this, "Enable 3D", false };
cfg::_int<1, 8> consequtive_frames_to_draw{ this, "Consecutive Frames To Draw", 1 };
cfg::_int<1, 8> consequtive_frames_to_skip{ this, "Consecutive Frames To Skip", 1 };
cfg::_int<50, 800> resolution_scale_percent{ this, "Resolution Scale", 100 };