mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
ps3: add a PS3 display server, switch resolutions through it
Screen resolution on PS3 lived in the ps3 context driver: a list of resolution ids it probed for at init (leaked on every reinit - the malloc'd list was never freed), stepped through with left/right on the menu entry and applied with OK by reinitialising the driver. On PSL1GHT that did nothing at all: the RSX driver configures the video output itself, from the mode the system menu has it in, and never looked at the chosen id. dispserv_ps3 is now the display server for __PS3__. It lists the modes the connected display takes (480, 576, 960x1080, 720, the 1080-line scalers, 1080), marks the one in use, and switches between them. The menu entry now opens the same resolution dropdown the desktop platforms use, and Start resets to the system menu's mode as it does elsewhere. A choice is stored in current_resolution_id - the video output resolution id, as before, so existing configs keep their modes - and the video driver is reinitialised to configure the output in it; picking the mode already in use reinitialises nothing. A refresh-rate-only set_resolution (the autoswitch) is refused. ps3_display_server_resolution() is what configures the output: the chosen mode when the display takes it, otherwise the system menu's. The RSX driver's rsx_init_screen now uses it in place of the system mode, which makes the setting work on PSL1GHT; the PSGL context uses it for its device size in place of the unchecked stored id, so a choice the current display cannot show (a config moved to another TV) falls back instead of failing. The mode table and those rules are in dispserv_ps3_modes.c, which takes the display's answers through a callback and so has no SDK dependency. The context driver loses its list and its output size/prev/next callbacks, and global_t loses the list, count, check, idx and initial fields nothing reads any more. Test: samples/gfx/dispserv_ps3 links the real server and mode rules against stubbed PSL1GHT video output queries (declared in the tree's PS3 stub <sysutil/video.h>, now carrying PSL1GHT's layouts) for displays taking different sets of modes with the system menu in each: the list is exactly what the display takes with the mode in use marked; each entry, through the label the menu prints and the parse the menu does, selects its mode, stores its id, reinitialises once (never for the mode in use) and reports its rate and size; the mode the driver configures follows the choice and falls back to the system mode for one the display lacks or an unknown id; refresh-only and unavailable modes are refused without touching anything. Wired into Linux-samples-gfx (ASan + UBSan); compile-matrix gains a PSL1GHT syntax lane for the server.
This commit is contained in:
1 parent
8e386c7642
commit
ffa4ec336a
18 files changed
+858
-173
No files matched your search
@@ -660,6 +660,28 @@ jobs:
|
||||
timeout 60 ./dispserv_gx_test
|
||||
make clean
|
||||
|
||||
- name: Build and run dispserv_ps3_test (ASan + UBSan)
|
||||
shell: bash
|
||||
working-directory: samples/gfx/dispserv_ps3
|
||||
run: |
|
||||
set -eu
|
||||
# The PS3 display server (dispserv_ps3.c and the mode rules in
|
||||
# dispserv_ps3_modes.c), linked as they ship against stubbed
|
||||
# PSL1GHT video output queries, for displays taking different
|
||||
# sets of modes with the system menu in each: the list holds
|
||||
# exactly what the display takes with the mode in use marked,
|
||||
# each entry - through the menu's label and parse - selects
|
||||
# that mode and reinitialises the driver once, and
|
||||
# ps3_display_server_resolution(), which the RSX driver
|
||||
# configures the output from, follows the choice (before, the
|
||||
# RSX driver ignored the setting and kept the system menu's
|
||||
# mode) and falls back to the system mode when the display
|
||||
# does not take it.
|
||||
make clean all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
timeout 60 ./dispserv_ps3_test
|
||||
make clean
|
||||
|
||||
- name: X11 window poll sends no requests (Xvfb, ASan + UBSan)
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -515,6 +515,7 @@ check "gekko: mem2_manager" "$HOSTOFF $GEKKO_INC -DGEKKO -DHW_RVL -DRARCH_CON
|
||||
check "gekko: dispserv_gx" "$HOSTOFF $GEKKO_INC -DGEKKO -DHW_RVL -DRARCH_CONSOLE $CDECL" gfx/display_servers/dispserv_gx.c
|
||||
check "gamecube: dispserv_gx" "$HOSTOFF $GEKKO_INC -DGEKKO -DRARCH_CONSOLE $CDECL" gfx/display_servers/dispserv_gx.c
|
||||
check "gekko: dispserv_gx_modes" "$HOSTOFF $GEKKO_INC -DGEKKO -DHW_RVL -DRARCH_CONSOLE $CDECL" gfx/display_servers/dispserv_gx_modes.c
|
||||
check "psl1ght: dispserv_ps3" "$HOSTOFF -Itools/platform_stubs/ps3 -D__PS3__ -D__PSL1GHT__ -DRARCH_CONSOLE $CDECL" gfx/display_servers/dispserv_ps3.c gfx/display_servers/dispserv_ps3_modes.c
|
||||
check "3ds: ctr_input" "$HOSTOFF -Itools/platform_stubs/ctr -D_3DS -D__3DS__ -DARM11 -DRARCH_CONSOLE $CDECL" input/drivers/ctr_input.c
|
||||
PSP_DEFS="$HOSTOFF -Itools/platform_stubs/psp -DPSP -D_POSIX_C_SOURCE=199309L -DRARCH_CONSOLE"
|
||||
check "psp: psp_input" "$PSP_DEFS $CDECL" input/drivers/psp_input.c
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Display server for the PS3. It lists the video output modes the
|
||||
* connected display takes (dispserv_ps3_modes.c), marks the one in
|
||||
* use, and switches between them. The output itself is configured by
|
||||
* whoever owns the frame buffers - the RSX driver on PSL1GHT, the PSGL
|
||||
* context on the Cell SDK - at init, from
|
||||
* ps3_display_server_resolution(); so a switch stores the choice in
|
||||
* current_resolution_id and reinitialises the video driver, which
|
||||
* comes back up in it.
|
||||
*
|
||||
* Only whole modes can be switched: a set_resolution without dims
|
||||
* (the refresh rate autoswitch) fails. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sysutil/video.h>
|
||||
typedef videoState ps3_video_state_t;
|
||||
#define PS3_VIDEO_GET_STATE(s) videoGetState(0, 0, (s))
|
||||
#define PS3_VIDEO_AVAILABLE(id) videoGetResolutionAvailability( \
|
||||
VIDEO_PRIMARY, (id), VIDEO_ASPECT_AUTO, 0)
|
||||
#else
|
||||
#include <sysutil/sysutil_sysparam.h>
|
||||
typedef CellVideoOutState ps3_video_state_t;
|
||||
#define PS3_VIDEO_GET_STATE(s) cellVideoOutGetState( \
|
||||
CELL_VIDEO_OUT_PRIMARY, 0, (s))
|
||||
#define PS3_VIDEO_AVAILABLE(id) cellVideoOutGetResolutionAvailability( \
|
||||
CELL_VIDEO_OUT_PRIMARY, (id), CELL_VIDEO_OUT_ASPECT_AUTO, 0)
|
||||
#endif
|
||||
|
||||
#include "dispserv_ps3.h"
|
||||
#include "../../command.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
/* Nothing to keep; any non-NULL pointer marks the server as up */
|
||||
static char ps3_display_server_state;
|
||||
|
||||
static bool ps3_display_server_available(void *user, unsigned id)
|
||||
{
|
||||
return PS3_VIDEO_AVAILABLE(id) ? true : false;
|
||||
}
|
||||
|
||||
/* The mode the system menu has the output in, 0 when unreadable */
|
||||
static unsigned ps3_display_server_system_id(void)
|
||||
{
|
||||
ps3_video_state_t state;
|
||||
if (PS3_VIDEO_GET_STATE(&state) != 0)
|
||||
return PS3_MODE_ID_SYSTEM;
|
||||
return state.displayMode.resolution;
|
||||
}
|
||||
|
||||
unsigned ps3_display_server_resolution(unsigned system_id)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
return ps3_modes_effective(ps3_display_server_available, NULL,
|
||||
global->console.screen.resolutions.current.id, system_id);
|
||||
}
|
||||
|
||||
static unsigned ps3_display_server_in_use(void)
|
||||
{
|
||||
return ps3_display_server_resolution(ps3_display_server_system_id());
|
||||
}
|
||||
|
||||
static void *ps3_display_server_init(void)
|
||||
{
|
||||
return &ps3_display_server_state;
|
||||
}
|
||||
|
||||
static void ps3_display_server_destroy(void *data) { }
|
||||
|
||||
static void *ps3_display_server_get_resolution_list(void *data,
|
||||
unsigned *len)
|
||||
{
|
||||
unsigned count;
|
||||
video_display_config_t *list;
|
||||
global_t *global = global_get_ptr();
|
||||
unsigned current = global->console.screen.resolutions.current.id;
|
||||
unsigned system = ps3_display_server_system_id();
|
||||
|
||||
count = ps3_modes_list(ps3_display_server_available, NULL,
|
||||
current, system, NULL, 0);
|
||||
if (!count || !(list = (video_display_config_t*)
|
||||
malloc(count * sizeof(*list))))
|
||||
{
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*len = ps3_modes_list(ps3_display_server_available, NULL,
|
||||
current, system, list, count);
|
||||
return list;
|
||||
}
|
||||
|
||||
static bool ps3_display_server_set_resolution(void *data,
|
||||
unsigned dims, int int_hz, float hz, int center,
|
||||
int monitor_index, int xoffset, int padjust)
|
||||
{
|
||||
int id;
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
/* No dims is a refresh rate change on its own, which the video
|
||||
* output cannot make without changing the mode */
|
||||
if (!VIDEO_SCALE_W(dims) || !VIDEO_SCALE_H(dims))
|
||||
return false;
|
||||
|
||||
if ((id = ps3_modes_find(ps3_display_server_available, NULL, dims)) < 0)
|
||||
{
|
||||
RARCH_WARN("[PS3] The display does not take %ux%u.\n",
|
||||
VIDEO_SCALE_W(dims), VIDEO_SCALE_H(dims));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((unsigned)id == ps3_display_server_in_use())
|
||||
{
|
||||
/* Already there; store it so the choice outlives a change to
|
||||
* the system menu's mode */
|
||||
global->console.screen.resolutions.current.id = (unsigned)id;
|
||||
return true;
|
||||
}
|
||||
|
||||
global->console.screen.resolutions.current.id = (unsigned)id;
|
||||
/* PAL60 temporal conversion only applies to 576 (PSGL) */
|
||||
if (dims != VIDEO_SCALE_PACK(720, 576))
|
||||
{
|
||||
global->console.screen.pal_enable = false;
|
||||
global->console.screen.pal60_enable = false;
|
||||
}
|
||||
|
||||
/* The output is configured at video init, with the frame buffers
|
||||
* sized for it */
|
||||
command_event(CMD_EVENT_REINIT, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static float ps3_display_server_get_refresh_rate(void *data)
|
||||
{
|
||||
return ps3_modes_hz(ps3_display_server_in_use());
|
||||
}
|
||||
|
||||
static void ps3_display_server_get_video_output_size(void *data,
|
||||
unsigned *dims, char *s, size_t len)
|
||||
{
|
||||
*dims = ps3_modes_dims(ps3_display_server_in_use());
|
||||
}
|
||||
|
||||
const video_display_server_t dispserv_ps3 = {
|
||||
ps3_display_server_init,
|
||||
ps3_display_server_destroy,
|
||||
NULL, /* set_window_opacity */
|
||||
NULL, /* set_window_progress */
|
||||
NULL, /* set_window_decorations */
|
||||
ps3_display_server_set_resolution,
|
||||
ps3_display_server_get_resolution_list,
|
||||
NULL, /* get_output_options */
|
||||
NULL, /* set_screen_orientation */
|
||||
NULL, /* get_screen_orientation */
|
||||
ps3_display_server_get_refresh_rate,
|
||||
ps3_display_server_get_video_output_size,
|
||||
NULL, /* get_video_output_prev */
|
||||
NULL, /* get_video_output_next */
|
||||
NULL, /* get_metrics */
|
||||
NULL, /* get_flags */
|
||||
NULL, /* get_scanline */
|
||||
NULL, /* wait_vblank */
|
||||
NULL, /* modeline_list_outputs */
|
||||
NULL, /* modeline_open */
|
||||
NULL, /* modeline_close */
|
||||
NULL, /* modeline_caps */
|
||||
NULL, /* modeline_enum */
|
||||
NULL, /* modeline_add */
|
||||
NULL, /* modeline_update */
|
||||
NULL, /* modeline_delete */
|
||||
NULL, /* modeline_set */
|
||||
NULL, /* modeline_flush */
|
||||
NULL, /* get_edid */
|
||||
NULL, /* idle_wait */
|
||||
"ps3"
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DISPSERV_PS3_H
|
||||
#define __DISPSERV_PS3_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include "dispserv_ps3_modes.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* The video output resolution id to configure: the one chosen in the
|
||||
* menu (current_resolution_id) when the display takes it, otherwise
|
||||
* system_id - the mode the system menu has the output in, which the
|
||||
* caller reads from the output state (0 when it has none). Shared by
|
||||
* the RSX driver and the PSGL context, which configure the output. */
|
||||
unsigned ps3_display_server_resolution(unsigned system_id);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "dispserv_ps3_modes.h"
|
||||
|
||||
typedef struct ps3_mode
|
||||
{
|
||||
unsigned char id;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
} ps3_mode_t;
|
||||
|
||||
/* The order the list shows them in, as the old context-driver list
|
||||
* did: SD, the 1080-line horizontal scalers under 720p, then 1080 */
|
||||
static const ps3_mode_t ps3_mode_table[] = {
|
||||
{ 4, 720, 480 }, /* 480 */
|
||||
{ 5, 720, 576 }, /* 576 */
|
||||
{ 13, 960, 1080 },
|
||||
{ 2, 1280, 720 }, /* 720 */
|
||||
{ 12, 1280, 1080 },
|
||||
{ 11, 1440, 1080 },
|
||||
{ 10, 1600, 1080 },
|
||||
{ 1, 1920, 1080 } /* 1080 */
|
||||
};
|
||||
|
||||
#define PS3_MODE_COUNT (sizeof(ps3_mode_table) / sizeof(ps3_mode_table[0]))
|
||||
#define PS3_MODE_ID_576 5
|
||||
|
||||
static const ps3_mode_t *ps3_modes_lookup(unsigned id)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < PS3_MODE_COUNT; i++)
|
||||
if (ps3_mode_table[i].id == id)
|
||||
return &ps3_mode_table[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned ps3_modes_dims(unsigned id)
|
||||
{
|
||||
const ps3_mode_t *m = ps3_modes_lookup(id);
|
||||
if (!m)
|
||||
return 0;
|
||||
return VIDEO_SCALE_PACK(m->width, m->height);
|
||||
}
|
||||
|
||||
float ps3_modes_hz(unsigned id)
|
||||
{
|
||||
return (id == PS3_MODE_ID_576) ? 50.0f : 59.94f;
|
||||
}
|
||||
|
||||
unsigned ps3_modes_effective(ps3_mode_available_t avail, void *user,
|
||||
unsigned current_id, unsigned system_id)
|
||||
{
|
||||
if ( current_id != PS3_MODE_ID_SYSTEM
|
||||
&& ps3_modes_lookup(current_id)
|
||||
&& avail(user, current_id))
|
||||
return current_id;
|
||||
return ps3_modes_lookup(system_id) ? system_id : PS3_MODE_ID_SYSTEM;
|
||||
}
|
||||
|
||||
int ps3_modes_find(ps3_mode_available_t avail, void *user, unsigned dims)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < PS3_MODE_COUNT; i++)
|
||||
if ( VIDEO_SCALE_PACK(ps3_mode_table[i].width,
|
||||
ps3_mode_table[i].height) == dims
|
||||
&& avail(user, ps3_mode_table[i].id))
|
||||
return ps3_mode_table[i].id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned ps3_modes_list(ps3_mode_available_t avail, void *user,
|
||||
unsigned current_id, unsigned system_id,
|
||||
video_display_config_t *out, unsigned max)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned count = 0;
|
||||
unsigned in_use = ps3_modes_effective(avail, user, current_id, system_id);
|
||||
|
||||
for (i = 0; i < PS3_MODE_COUNT; i++)
|
||||
{
|
||||
const ps3_mode_t *m = &ps3_mode_table[i];
|
||||
if (!avail(user, m->id))
|
||||
continue;
|
||||
if (out && count < max)
|
||||
{
|
||||
video_display_config_t *cfg = &out[count];
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
cfg->dims = VIDEO_SCALE_PACK(m->width, m->height);
|
||||
cfg->bpp = 32;
|
||||
cfg->refreshrate_float = ps3_modes_hz(m->id);
|
||||
cfg->refreshrate = (unsigned)cfg->refreshrate_float;
|
||||
cfg->idx = m->id;
|
||||
cfg->current = (m->id == in_use);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* The PS3 video output modes RetroArch offers and the rules for which
|
||||
* one is in use. Nothing here touches an SDK: whether the display
|
||||
* takes a mode comes in through a callback (dispserv_ps3.c asks the
|
||||
* video output), so the Cell SDK and PSL1GHT builds share it and a
|
||||
* host build can test it.
|
||||
*
|
||||
* A mode is named by its video output resolution id, the value both
|
||||
* SDKs use (CELL_VIDEO_OUT_RESOLUTION_* / VIDEO_RESOLUTION_*: 1080 is
|
||||
* 1, 720 is 2, 480 is 4, 576 is 5, 1600x1080 to 960x1080 are 10 to
|
||||
* 13). That id is what current_resolution_id stores in the config;
|
||||
* 0 there means "whatever the system menu is set to". */
|
||||
|
||||
#ifndef __DISPSERV_PS3_MODES_H
|
||||
#define __DISPSERV_PS3_MODES_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#include "../video_display_server.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define PS3_MODE_ID_SYSTEM 0
|
||||
|
||||
/* Whether the display takes the mode with this resolution id */
|
||||
typedef bool (*ps3_mode_available_t)(void *user, unsigned id);
|
||||
|
||||
/* The mode's size as VIDEO_SCALE_PACKed dims, 0 for an unknown id. */
|
||||
unsigned ps3_modes_dims(unsigned id);
|
||||
|
||||
/* The field rate the video output runs the mode at. */
|
||||
float ps3_modes_hz(unsigned id);
|
||||
|
||||
/* The id in use: the stored one when it is a known mode the display
|
||||
* takes, otherwise system_id (the system menu's mode; 0 if unknown). */
|
||||
unsigned ps3_modes_effective(ps3_mode_available_t avail, void *user,
|
||||
unsigned current_id, unsigned system_id);
|
||||
|
||||
/* The id of an available mode of exactly these dims, or -1. */
|
||||
int ps3_modes_find(ps3_mode_available_t avail, void *user, unsigned dims);
|
||||
|
||||
/* The available modes, smallest first, with the one in use marked
|
||||
* current. Writes at most max entries to out and returns how many
|
||||
* there are in total; out may be NULL to count. */
|
||||
unsigned ps3_modes_list(ps3_mode_available_t avail, void *user,
|
||||
unsigned current_id, unsigned system_id,
|
||||
video_display_config_t *out, unsigned max);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "../../retroarch.h"
|
||||
#ifdef HAVE_THREADS
|
||||
#include "../video_thread_wrapper.h"
|
||||
#include "../display_servers/dispserv_ps3.h"
|
||||
#endif
|
||||
|
||||
#define RSX_MAX_BUFFERS 2
|
||||
@@ -1319,6 +1320,7 @@ static gcmContextData *rsx_init_screen(rsx_t* gcm)
|
||||
videoState state;
|
||||
videoConfiguration vconfig;
|
||||
videoResolution res; /* Screen Resolution */
|
||||
unsigned resolution;
|
||||
/* Context to keep track of the RSX buffer. */
|
||||
gcmContextData *context = NULL;
|
||||
static gcmContextData *saved_context = NULL;
|
||||
@@ -1356,13 +1358,16 @@ static gcmContextData *rsx_init_screen(rsx_t* gcm)
|
||||
if (state.state != 0)
|
||||
goto error;
|
||||
|
||||
/* Get the current resolution */
|
||||
if (videoGetResolution(state.displayMode.resolution, &res) != 0)
|
||||
/* The mode chosen through the display server when the display
|
||||
* takes it, otherwise the one the system menu has it in */
|
||||
resolution = ps3_display_server_resolution(state.displayMode.resolution);
|
||||
|
||||
if (videoGetResolution(resolution, &res) != 0)
|
||||
goto error;
|
||||
|
||||
/* Configure the buffer format to xRGB */
|
||||
memset(&vconfig, 0, sizeof(videoConfiguration));
|
||||
vconfig.resolution = state.displayMode.resolution;
|
||||
vconfig.resolution = resolution;
|
||||
vconfig.format = VIDEO_BUFFER_FORMAT_XRGB;
|
||||
vconfig.pitch = res.width * sizeof(u32);
|
||||
vconfig.aspect = state.displayMode.aspect;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <rsx/rsx.h>
|
||||
#endif
|
||||
#include "../../frontend/frontend_driver.h"
|
||||
#include "../display_servers/dispserv_ps3.h"
|
||||
#if defined(HAVE_PSGL)
|
||||
#include "../common/gl_common.h"
|
||||
#include "../common/gl2_common.h"
|
||||
@@ -56,88 +57,6 @@ static enum gfx_ctx_api ps3_api = GFX_CTX_RSX_API;
|
||||
static enum gfx_ctx_api ps3_api = GFX_CTX_NONE;
|
||||
#endif
|
||||
|
||||
static unsigned gfx_ctx_ps3_get_resolution(unsigned idx)
|
||||
{
|
||||
CellVideoOutResolution resolution;
|
||||
cellVideoOutGetResolution(idx, &resolution);
|
||||
return VIDEO_SCALE_PACK(resolution.width, resolution.height);
|
||||
}
|
||||
|
||||
static void gfx_ctx_ps3_get_available_resolutions(void)
|
||||
{
|
||||
unsigned i;
|
||||
uint32_t videomode[] = {
|
||||
CELL_VIDEO_OUT_RESOLUTION_480,
|
||||
CELL_VIDEO_OUT_RESOLUTION_576,
|
||||
CELL_VIDEO_OUT_RESOLUTION_960x1080,
|
||||
CELL_VIDEO_OUT_RESOLUTION_720,
|
||||
CELL_VIDEO_OUT_RESOLUTION_1280x1080,
|
||||
CELL_VIDEO_OUT_RESOLUTION_1440x1080,
|
||||
CELL_VIDEO_OUT_RESOLUTION_1600x1080,
|
||||
CELL_VIDEO_OUT_RESOLUTION_1080
|
||||
};
|
||||
uint32_t resolution_count = 0;
|
||||
bool defaultresolution = true;
|
||||
uint16_t num_videomodes = sizeof(videomode) / sizeof(uint32_t);
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (global->console.screen.resolutions.check)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_videomodes; i++)
|
||||
{
|
||||
if (cellVideoOutGetResolutionAvailability(
|
||||
CELL_VIDEO_OUT_PRIMARY, videomode[i],
|
||||
CELL_VIDEO_OUT_ASPECT_AUTO, 0))
|
||||
resolution_count++;
|
||||
}
|
||||
|
||||
global->console.screen.resolutions.count = 0;
|
||||
global->console.screen.resolutions.list =
|
||||
malloc(resolution_count * sizeof(uint32_t));
|
||||
|
||||
/* NULL-check: the resolutions.list[...] writes in the loop
|
||||
* below and the '...list[...current.idx]' read at line ~138
|
||||
* would NULL-deref on OOM. Void-returning function; leaving
|
||||
* resolutions.check == false means the next call will retry
|
||||
* (which is desired - an OOM here is transient and we want
|
||||
* to populate the list once memory is available). */
|
||||
if (!global->console.screen.resolutions.list)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_videomodes; i++)
|
||||
{
|
||||
if (cellVideoOutGetResolutionAvailability(
|
||||
CELL_VIDEO_OUT_PRIMARY,
|
||||
videomode[i],
|
||||
CELL_VIDEO_OUT_ASPECT_AUTO, 0))
|
||||
{
|
||||
global->console.screen.resolutions.list[
|
||||
global->console.screen.resolutions.count++] = videomode[i];
|
||||
global->console.screen.resolutions.initial.id = videomode[i];
|
||||
|
||||
if (global->console.screen.resolutions.current.id == videomode[i])
|
||||
{
|
||||
defaultresolution = false;
|
||||
global->console.screen.resolutions.current.idx =
|
||||
global->console.screen.resolutions.count-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In case we didn't specify a resolution -
|
||||
* make the last resolution
|
||||
that was added to the list (the highest resolution)
|
||||
the default resolution */
|
||||
if (global->console.screen.resolutions.current.id > num_videomodes || defaultresolution)
|
||||
{
|
||||
global->console.screen.resolutions.current.idx = resolution_count - 1;
|
||||
global->console.screen.resolutions.current.id = global->console.screen.resolutions.list[global->console.screen.resolutions.current.idx];
|
||||
}
|
||||
|
||||
global->console.screen.resolutions.check = true;
|
||||
}
|
||||
|
||||
static void gfx_ctx_ps3_set_swap_interval(void *data, int interval)
|
||||
{
|
||||
#if defined(HAVE_PSGL)
|
||||
@@ -199,6 +118,7 @@ static void *gfx_ctx_ps3_init(void *video_driver)
|
||||
#ifdef HAVE_PSGL
|
||||
PSGLdeviceParameters params;
|
||||
PSGLinitOptions options;
|
||||
unsigned dims;
|
||||
#endif
|
||||
global_t *global = global_get_ptr();
|
||||
gfx_ctx_ps3_data_t *ps3 = (gfx_ctx_ps3_data_t*)
|
||||
@@ -224,10 +144,10 @@ static void *gfx_ctx_ps3_init(void *video_driver)
|
||||
params.depthFormat = GL_NONE;
|
||||
params.multisamplingMode = GL_MULTISAMPLING_NONE_SCE;
|
||||
|
||||
if (global->console.screen.resolutions.current.id)
|
||||
/* The mode the display server has chosen, if the display takes
|
||||
* it; without one PSGL keeps the system menu's mode */
|
||||
if ((dims = ps3_modes_dims(ps3_display_server_resolution(0))))
|
||||
{
|
||||
unsigned dims = gfx_ctx_ps3_get_resolution(
|
||||
global->console.screen.resolutions.current.id);
|
||||
params.enable |= PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT;
|
||||
params.width = VIDEO_SCALE_W(dims);
|
||||
params.height = VIDEO_SCALE_H(dims);
|
||||
@@ -261,8 +181,6 @@ static void *gfx_ctx_ps3_init(void *video_driver)
|
||||
CELL_VIDEO_OUT_PRIMARY, CELL_VIDEO_OUT_RESOLUTION_576,
|
||||
CELL_VIDEO_OUT_ASPECT_AUTO, 0);
|
||||
|
||||
gfx_ctx_ps3_get_available_resolutions();
|
||||
|
||||
return ps3;
|
||||
}
|
||||
|
||||
@@ -321,62 +239,6 @@ static bool gfx_ctx_ps3_bind_api(void *data,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_ps3_get_video_output_size(void *data,
|
||||
unsigned *dims, char *desc, size_t desc_len)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return;
|
||||
|
||||
*dims = gfx_ctx_ps3_get_resolution(
|
||||
global->console.screen.resolutions.current.id);
|
||||
|
||||
if (*dims == VIDEO_SCALE_PACK(720, 576))
|
||||
{
|
||||
if (global->console.screen.pal_enable)
|
||||
global->console.screen.pal60_enable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
global->console.screen.pal_enable = false;
|
||||
global->console.screen.pal60_enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_ctx_ps3_get_video_output_prev(void *data)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return;
|
||||
|
||||
if (global->console.screen.resolutions.current.idx)
|
||||
{
|
||||
global->console.screen.resolutions.current.idx--;
|
||||
global->console.screen.resolutions.current.id =
|
||||
global->console.screen.resolutions.list
|
||||
[global->console.screen.resolutions.current.idx];
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_ctx_ps3_get_video_output_next(void *data)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return;
|
||||
|
||||
if (global->console.screen.resolutions.current.idx + 1 <
|
||||
global->console.screen.resolutions.count)
|
||||
{
|
||||
global->console.screen.resolutions.current.idx++;
|
||||
global->console.screen.resolutions.current.id =
|
||||
global->console.screen.resolutions.list
|
||||
[global->console.screen.resolutions.current.idx];
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t gfx_ctx_ps3_get_flags(void *data)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
@@ -399,9 +261,9 @@ const gfx_ctx_driver_t gfx_ctx_ps3 = {
|
||||
gfx_ctx_ps3_set_video_mode,
|
||||
gfx_ctx_ps3_get_video_size,
|
||||
NULL, /* get_refresh_rate */
|
||||
gfx_ctx_ps3_get_video_output_size,
|
||||
gfx_ctx_ps3_get_video_output_prev,
|
||||
gfx_ctx_ps3_get_video_output_next,
|
||||
NULL, /* get_video_output_size: dispserv_ps3 */
|
||||
NULL, /* get_video_output_prev */
|
||||
NULL, /* get_video_output_next */
|
||||
NULL, /* get_metrics */
|
||||
NULL,
|
||||
NULL, /* update_title */
|
||||
|
||||
@@ -253,6 +253,7 @@ extern const video_display_server_t dispserv_apple;
|
||||
extern const video_display_server_t dispserv_sdl2;
|
||||
extern const video_display_server_t dispserv_sdl3;
|
||||
extern const video_display_server_t dispserv_gx;
|
||||
extern const video_display_server_t dispserv_ps3;
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
|
||||
@@ -1774,6 +1774,8 @@ void* video_display_server_init(enum rarch_display_type type)
|
||||
current_display_server = &dispserv_apple;
|
||||
#elif defined(GEKKO)
|
||||
current_display_server = &dispserv_gx;
|
||||
#elif defined(__PS3__)
|
||||
current_display_server = &dispserv_ps3;
|
||||
#else
|
||||
current_display_server = &dispserv_null;
|
||||
#endif
|
||||
|
||||
@@ -324,6 +324,8 @@ VIDEO CONTEXT
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include "../gfx/drivers_context/emscriptenegl_ctx.c"
|
||||
#elif defined(__PS3__)
|
||||
#include "../gfx/display_servers/dispserv_ps3_modes.c"
|
||||
#include "../gfx/display_servers/dispserv_ps3.c"
|
||||
#include "../gfx/drivers_context/ps3_ctx.c"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8603,7 +8603,7 @@ static int generic_dropdown_box_list(size_t idx, unsigned lbl)
|
||||
static int action_ok_video_resolution(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
#if defined(PS2) || defined(__PS3__)
|
||||
#if defined(PS2)
|
||||
unsigned dims = 0;
|
||||
char desc[64] = {0};
|
||||
|
||||
@@ -8613,9 +8613,6 @@ static int action_ok_video_resolution(const char *path,
|
||||
char msg[128];
|
||||
msg[0] = '\0';
|
||||
|
||||
#if defined(_WIN32) || defined(__PS3__)
|
||||
generic_action_ok_command(CMD_EVENT_REINIT);
|
||||
#endif
|
||||
video_driver_set_video_mode(dims, true);
|
||||
{
|
||||
if (*desc)
|
||||
|
||||
@@ -628,7 +628,6 @@ static int action_start_video_resolution(
|
||||
const char *path, const char *label,
|
||||
unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
#if defined(GEKKO) || defined(PS2) || !defined(__PSL1GHT__) && !defined(__PS3__)
|
||||
unsigned dims = 0;
|
||||
char desc[64] = {0};
|
||||
global_t *global = global_get_ptr();
|
||||
@@ -640,7 +639,7 @@ static int action_start_video_resolution(
|
||||
{
|
||||
size_t _len;
|
||||
char msg[128];
|
||||
#if defined(GEKKO) || defined(PS2)
|
||||
#if defined(GEKKO) || defined(PS2) || defined(__PS3__)
|
||||
bool fullscreen = true;
|
||||
#else
|
||||
/* The window state the frontend is in, as driver init reads it */
|
||||
@@ -649,9 +648,8 @@ static int action_start_video_resolution(
|
||||
#endif
|
||||
msg[0] = '\0';
|
||||
|
||||
#if defined(_WIN32) || !defined(__PSL1GHT__) && !defined(__PS3__)
|
||||
/* PS3: the video output is configured at video init */
|
||||
generic_action_ok_command(CMD_EVENT_REINIT);
|
||||
#endif
|
||||
video_driver_set_video_mode(dims, fullscreen);
|
||||
#ifdef GEKKO
|
||||
if (!VIDEO_SCALE_W(dims) || !VIDEO_SCALE_H(dims))
|
||||
@@ -670,7 +668,6 @@ static int action_start_video_resolution(
|
||||
runloop_msg_queue_push(msg, _len, 1, 100, true, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11552,7 +11552,7 @@ unsigned menu_displaylist_build_list(
|
||||
PARSE_ONLY_UINT, false) == 0)
|
||||
count++;
|
||||
|
||||
#if defined(PS2) || defined(__PS3__)
|
||||
#if defined(PS2)
|
||||
if (true)
|
||||
#else
|
||||
if (video_display_server_has_resolution_list())
|
||||
|
||||
+1
-10
@@ -279,19 +279,10 @@ typedef struct global
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t *list;
|
||||
unsigned count;
|
||||
struct
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned id;
|
||||
unsigned id; /* current_resolution_id */
|
||||
} current;
|
||||
struct
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned id;
|
||||
} initial;
|
||||
bool check;
|
||||
} resolutions;
|
||||
unsigned gamma_correction;
|
||||
unsigned int flicker_filter_index;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
TARGET := dispserv_ps3_test
|
||||
|
||||
# Links the real display server and its mode rules. dispserv_ps3.c
|
||||
# reaches PSL1GHT for two video output queries; the tree's PS3 stub
|
||||
# <sysutil/video.h> declares them in PSL1GHT's layouts and the test
|
||||
# defines them, to plug the console into a display taking any modes.
|
||||
REPO_ROOT := ../../..
|
||||
|
||||
SOURCES := dispserv_ps3_test.c \
|
||||
$(REPO_ROOT)/gfx/display_servers/dispserv_ps3.c \
|
||||
$(REPO_ROOT)/gfx/display_servers/dispserv_ps3_modes.c
|
||||
|
||||
CFLAGS += -Wall -std=gnu99 -g -O0 \
|
||||
-D__PS3__ -D__PSL1GHT__ \
|
||||
-I$(REPO_ROOT)/tools/platform_stubs/ps3 \
|
||||
-I$(REPO_ROOT) \
|
||||
-I$(REPO_ROOT)/libretro-common/include
|
||||
|
||||
# Objects stay here: the tree's own gfx/display_servers/*.o belong
|
||||
# to the console build (griffin for PSL1GHT).
|
||||
OBJS := $(notdir $(SOURCES:.c=.o))
|
||||
vpath %.c $(sort $(dir $(SOURCES)))
|
||||
|
||||
ifneq ($(SANITIZER),)
|
||||
CFLAGS := -fsanitize=$(SANITIZER) -fno-omit-frame-pointer $(CFLAGS)
|
||||
LDFLAGS := -fsanitize=$(SANITIZER) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
LDFLAGS += -lm
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) -o $@ $(OBJS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJS)
|
||||
|
||||
.PHONY: all clean
|
||||
@@ -0,0 +1,322 @@
|
||||
/* Copyright (C) 2010-2026 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (dispserv_ps3_test.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Contract test for the PS3 display server
|
||||
* (gfx/display_servers/dispserv_ps3.c + dispserv_ps3_modes.c), linked
|
||||
* as they ship against stubbed PSL1GHT video output queries.
|
||||
*
|
||||
* For displays taking different sets of modes (SD only, a 720p set, a
|
||||
* full 1080 set, a PAL SD set), with the system menu in each mode, it
|
||||
* checks that:
|
||||
* - the resolution list offers exactly the modes the display takes,
|
||||
* with the one in use marked current: the stored choice when the
|
||||
* display takes it, otherwise the system menu's mode;
|
||||
* - each entry, taken through the menu's own round trip - the label
|
||||
* menu_displaylist.c prints, parsed back the way
|
||||
* action_cb_push_dropdown_item_resolution does - selects exactly
|
||||
* that mode: current_resolution_id becomes its resolution id, the
|
||||
* video driver is reinitialised once (not at all when the mode is
|
||||
* already the one in use), and the refresh rate and output size
|
||||
* reported are the ones listed;
|
||||
* - ps3_display_server_resolution(), which the RSX driver and the
|
||||
* PSGL context configure the output from, gives the choice when
|
||||
* the display takes it and the system menu's mode otherwise -
|
||||
* before this the RSX driver ignored the setting entirely;
|
||||
* - a set_resolution with no dims (the refresh rate autoswitch) and
|
||||
* one naming a mode the display does not take both fail without
|
||||
* touching the stored id or reinitialising anything;
|
||||
* - the ids the config stores keep meaning the modes they did. */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sysutil/video.h>
|
||||
|
||||
#include "gfx/display_servers/dispserv_ps3.h"
|
||||
#include "command.h"
|
||||
#include "retroarch.h"
|
||||
|
||||
static int failures;
|
||||
|
||||
#define CHECK(cond, ...) do { \
|
||||
if (!(cond)) { \
|
||||
failures++; \
|
||||
printf("FAIL %s:%d: ", __FILE__, __LINE__); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* ---- stubbed video output ---- */
|
||||
|
||||
static unsigned available_mask; /* bit n: resolution id n */
|
||||
static unsigned system_id;
|
||||
static int state_fails;
|
||||
|
||||
int32_t videoGetState(int32_t videoOut, int32_t deviceIndex, videoState *state)
|
||||
{
|
||||
memset(state, 0, sizeof(*state));
|
||||
if (state_fails)
|
||||
return -1;
|
||||
state->displayMode.resolution = (uint8_t)system_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t videoGetResolutionAvailability(uint32_t videoOut, uint32_t resolutionId,
|
||||
uint32_t aspect, uint32_t option)
|
||||
{
|
||||
return (resolutionId < 32 && (available_mask & (1u << resolutionId)))
|
||||
? 1 : 0;
|
||||
}
|
||||
|
||||
/* ---- stubbed RetroArch ---- */
|
||||
|
||||
static global_t g_global;
|
||||
static unsigned reinits;
|
||||
|
||||
global_t *global_get_ptr(void) { return &g_global; }
|
||||
|
||||
bool command_event(enum event_command action, void *data)
|
||||
{
|
||||
if (action == CMD_EVENT_REINIT)
|
||||
reinits++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RARCH_WARN(const char *fmt, ...) { (void)fmt; }
|
||||
|
||||
/* ---- the menu's round trip ---- */
|
||||
|
||||
/* menu_displaylist.c, DISPLAYLIST_DROPDOWN_LIST_RESOLUTION */
|
||||
static void menu_label(char *s, size_t len, const video_display_config_t *c)
|
||||
{
|
||||
snprintf(s, len, "%dx%d (%.3f Hz)%s%s",
|
||||
VIDEO_SCALE_W(c->dims), VIDEO_SCALE_H(c->dims),
|
||||
c->refreshrate_float,
|
||||
c->interlaced ? "[i]" : "",
|
||||
c->dblscan ? "[d]" : "");
|
||||
}
|
||||
|
||||
/* menu_cbs_ok.c, action_cb_push_dropdown_item_resolution */
|
||||
static bool menu_parse(const char *path, unsigned *dims, float *hz)
|
||||
{
|
||||
char *end = NULL;
|
||||
unsigned width, height;
|
||||
width = (unsigned)strtoul(path, &end, 0);
|
||||
if (end == path || *end != 'x')
|
||||
return false;
|
||||
++end;
|
||||
height = (unsigned)strtoul(end, &end, 0);
|
||||
*dims = VIDEO_SCALE_PACK(width, height);
|
||||
while (*end == ' ' || *end == '(')
|
||||
++end;
|
||||
*hz = (float)strtod(end, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ---- tests ---- */
|
||||
|
||||
#define BIT(id) (1u << (id))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
unsigned mask;
|
||||
unsigned count;
|
||||
} display_t;
|
||||
|
||||
static const display_t displays[] = {
|
||||
{ "SD 480", BIT(4), 1 },
|
||||
{ "PAL SD", BIT(4) | BIT(5), 2 },
|
||||
{ "HD 720", BIT(4) | BIT(2), 2 },
|
||||
{ "Full HD", BIT(4) | BIT(5) | BIT(2) | BIT(1)
|
||||
| BIT(10) | BIT(11) | BIT(12) | BIT(13), 8 },
|
||||
};
|
||||
|
||||
static const unsigned all_ids[] = { 4, 5, 13, 2, 12, 11, 10, 1 };
|
||||
|
||||
static video_display_config_t *get_list(void *data, unsigned *n)
|
||||
{
|
||||
*n = 0;
|
||||
return (video_display_config_t*)dispserv_ps3.get_resolution_list(data, n);
|
||||
}
|
||||
|
||||
static void test_table_ids(void)
|
||||
{
|
||||
CHECK(ps3_modes_dims(1) == VIDEO_SCALE_PACK(1920, 1080), "id 1");
|
||||
CHECK(ps3_modes_dims(2) == VIDEO_SCALE_PACK(1280, 720), "id 2");
|
||||
CHECK(ps3_modes_dims(4) == VIDEO_SCALE_PACK( 720, 480), "id 4");
|
||||
CHECK(ps3_modes_dims(5) == VIDEO_SCALE_PACK( 720, 576), "id 5");
|
||||
CHECK(ps3_modes_dims(10) == VIDEO_SCALE_PACK(1600, 1080), "id 10");
|
||||
CHECK(ps3_modes_dims(11) == VIDEO_SCALE_PACK(1440, 1080), "id 11");
|
||||
CHECK(ps3_modes_dims(12) == VIDEO_SCALE_PACK(1280, 1080), "id 12");
|
||||
CHECK(ps3_modes_dims(13) == VIDEO_SCALE_PACK( 960, 1080), "id 13");
|
||||
CHECK(ps3_modes_dims(0) == 0 && ps3_modes_dims(3) == 0
|
||||
&& ps3_modes_dims(0x81) == 0, "unknown ids have dims");
|
||||
CHECK(ps3_modes_hz(5) == 50.0f && fabsf(ps3_modes_hz(1) - 59.94f) < 0.001f,
|
||||
"rates");
|
||||
}
|
||||
|
||||
static void test_display(void *data, const display_t *d)
|
||||
{
|
||||
unsigned s, i, n;
|
||||
|
||||
available_mask = d->mask;
|
||||
|
||||
/* The system menu in each mode the display takes */
|
||||
for (s = 0; s < sizeof(all_ids) / sizeof(all_ids[0]); s++)
|
||||
{
|
||||
video_display_config_t *list;
|
||||
if (!(d->mask & BIT(all_ids[s])))
|
||||
continue;
|
||||
system_id = all_ids[s];
|
||||
g_global.console.screen.resolutions.current.id = 0;
|
||||
|
||||
CHECK(ps3_display_server_resolution(system_id) == system_id,
|
||||
"%s: no choice does not give the system mode", d->name);
|
||||
|
||||
list = get_list(data, &n);
|
||||
CHECK(list && n == d->count, "%s: %u entries, want %u",
|
||||
d->name, n, d->count);
|
||||
if (!list)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
CHECK(d->mask & BIT(list[i].idx), "%s: lists id %u it lacks",
|
||||
d->name, list[i].idx);
|
||||
CHECK(list[i].current == (list[i].idx == system_id),
|
||||
"%s: id %u current=%d with system %u", d->name,
|
||||
list[i].idx, list[i].current, system_id);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
char label[64];
|
||||
unsigned dims, m, j, out = 0;
|
||||
float hz;
|
||||
bool in_use = (list[i].idx
|
||||
== ps3_display_server_resolution(system_id));
|
||||
video_display_config_t *after;
|
||||
|
||||
menu_label(label, sizeof(label), &list[i]);
|
||||
CHECK(menu_parse(label, &dims, &hz), "unparsable '%s'", label);
|
||||
|
||||
reinits = 0;
|
||||
CHECK(dispserv_ps3.set_resolution(data, dims, (int)floor(hz), hz,
|
||||
0, 0, 0, 0), "%s: '%s' refused", d->name, label);
|
||||
CHECK(g_global.console.screen.resolutions.current.id
|
||||
== list[i].idx, "%s: '%s' stored %u, want %u", d->name,
|
||||
label, g_global.console.screen.resolutions.current.id,
|
||||
list[i].idx);
|
||||
CHECK(reinits == (in_use ? 0u : 1u),
|
||||
"%s: '%s' reinitialised %u times", d->name, label, reinits);
|
||||
CHECK(ps3_display_server_resolution(system_id) == list[i].idx,
|
||||
"%s: '%s' is not what the driver configures", d->name,
|
||||
label);
|
||||
CHECK(fabsf(dispserv_ps3.get_refresh_rate(data)
|
||||
- list[i].refreshrate_float) < 0.0001f,
|
||||
"%s: '%s' reports another rate", d->name, label);
|
||||
dispserv_ps3.get_video_output_size(data, &out, NULL, 0);
|
||||
CHECK(out == list[i].dims, "%s: '%s' reports %ux%u", d->name,
|
||||
label, VIDEO_SCALE_W(out), VIDEO_SCALE_H(out));
|
||||
|
||||
after = get_list(data, &m);
|
||||
if (after)
|
||||
{
|
||||
unsigned cur = 0;
|
||||
for (j = 0; j < m; j++)
|
||||
if (after[j].current)
|
||||
cur++;
|
||||
CHECK(cur == 1 && after[i].current,
|
||||
"%s: after '%s' the wrong entry is current",
|
||||
d->name, label);
|
||||
free(after);
|
||||
}
|
||||
}
|
||||
|
||||
free(list);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_fallbacks(void *data)
|
||||
{
|
||||
unsigned dims = 0;
|
||||
available_mask = BIT(4) | BIT(2);
|
||||
system_id = 2;
|
||||
|
||||
/* A stored choice the display does not take (moved to another TV) */
|
||||
g_global.console.screen.resolutions.current.id = 1;
|
||||
CHECK(ps3_display_server_resolution(system_id) == 2,
|
||||
"unavailable choice not replaced by the system mode");
|
||||
dispserv_ps3.get_video_output_size(data, &dims, NULL, 0);
|
||||
CHECK(dims == VIDEO_SCALE_PACK(1280, 720), "reports the lost choice");
|
||||
|
||||
/* A stored id that names no mode */
|
||||
g_global.console.screen.resolutions.current.id = 0x81;
|
||||
CHECK(ps3_display_server_resolution(system_id) == 2, "id 0x81 used");
|
||||
|
||||
/* Output state unreadable: the list still marks nothing wrongly */
|
||||
g_global.console.screen.resolutions.current.id = 0;
|
||||
state_fails = 1;
|
||||
CHECK(ps3_display_server_resolution(0) == 0, "invented a mode");
|
||||
state_fails = 0;
|
||||
|
||||
g_global.console.screen.resolutions.current.id = 4;
|
||||
reinits = 0;
|
||||
CHECK(!dispserv_ps3.set_resolution(data, 0, 50, 50.0f, 0, 0, 0, 0),
|
||||
"refresh-rate-only switch accepted");
|
||||
CHECK(!dispserv_ps3.set_resolution(data, VIDEO_SCALE_PACK(1920, 1080),
|
||||
59, 59.94f, 0, 0, 0, 0), "1080 accepted on a 720 display");
|
||||
CHECK(!dispserv_ps3.set_resolution(data, VIDEO_SCALE_PACK(640, 480),
|
||||
59, 59.94f, 0, 0, 0, 0), "640x480 accepted");
|
||||
CHECK(reinits == 0, "a refused switch reinitialised");
|
||||
CHECK(g_global.console.screen.resolutions.current.id == 4,
|
||||
"a refused switch changed the stored id");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned i;
|
||||
void *data = dispserv_ps3.init();
|
||||
|
||||
CHECK(data != NULL, "init returned NULL");
|
||||
CHECK(dispserv_ps3.ident && !strcmp(dispserv_ps3.ident, "ps3"), "ident");
|
||||
|
||||
test_table_ids();
|
||||
for (i = 0; i < sizeof(displays) / sizeof(displays[0]); i++)
|
||||
test_display(data, &displays[i]);
|
||||
test_fallbacks(data);
|
||||
|
||||
dispserv_ps3.destroy(data);
|
||||
|
||||
if (failures)
|
||||
{
|
||||
printf("%d failure(s)\n", failures);
|
||||
return 1;
|
||||
}
|
||||
printf("[pass] dispserv_ps3_test\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,10 +1,46 @@
|
||||
/* Empty on purpose. defines/ps3_defines.h includes <sysutil/video.h>
|
||||
* unconditionally, so it has to exist for anything to parse against
|
||||
* these stubs; nothing compiled against them uses it yet. Declare what
|
||||
* a file needs as one arrives. */
|
||||
/* PSL1GHT <sysutil/video.h>, the part of it compiled against here:
|
||||
* the video output queries gfx/display_servers/dispserv_ps3.c makes,
|
||||
* in PSL1GHT's layouts and values (stdint types for its u8/u16/s32).
|
||||
* defines/ps3_defines.h includes this unconditionally. Declare what a
|
||||
* file needs as one arrives. */
|
||||
#ifndef PS3STUB_SYSUTIL_VIDEO_H
|
||||
#define PS3STUB_SYSUTIL_VIDEO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define VIDEO_PRIMARY 0
|
||||
#define VIDEO_ASPECT_AUTO 0
|
||||
|
||||
#define VIDEO_RESOLUTION_1080 1
|
||||
#define VIDEO_RESOLUTION_720 2
|
||||
#define VIDEO_RESOLUTION_480 4
|
||||
#define VIDEO_RESOLUTION_576 5
|
||||
#define VIDEO_RESOLUTION_1600x1080 10
|
||||
#define VIDEO_RESOLUTION_1440x1080 11
|
||||
#define VIDEO_RESOLUTION_1280x1080 12
|
||||
#define VIDEO_RESOLUTION_960x1080 13
|
||||
|
||||
typedef struct _videodisplaymode
|
||||
{
|
||||
uint8_t resolution;
|
||||
uint8_t scanMode;
|
||||
uint8_t conversion;
|
||||
uint8_t aspect;
|
||||
uint8_t padding[2];
|
||||
uint16_t refreshRates;
|
||||
} videoDisplayMode;
|
||||
|
||||
typedef struct _videostate
|
||||
{
|
||||
uint8_t state;
|
||||
uint8_t colorSpace;
|
||||
uint8_t padding[6];
|
||||
videoDisplayMode displayMode;
|
||||
} videoState;
|
||||
|
||||
int32_t videoGetState(int32_t videoOut, int32_t deviceIndex,
|
||||
videoState *state);
|
||||
int32_t videoGetResolutionAvailability(uint32_t videoOut,
|
||||
uint32_t resolutionId, uint32_t aspect, uint32_t option);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user