Skip to content

Commit

Permalink
video: Allow selection of 3D stereo resolutions
Browse files Browse the repository at this point in the history
  • Loading branch information
kd-11 committed Mar 7, 2020
1 parent 19107b2 commit 6e3406b
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 53 deletions.
8 changes: 8 additions & 0 deletions rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
153 changes: 102 additions & 51 deletions rpcs3/Emu/Cell/Modules/cellVideoOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 } },
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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;
}

Expand All @@ -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;
Expand All @@ -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:

Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
}

Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Emu/RSX/GL/GLPresent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Emu/RSX/VK/VKPresent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/RSX/rsx_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/system_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down

0 comments on commit 6e3406b

Please sign in to comment.