Implement RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER - faster blitting for video driver backends that support it, i.e. Vulkan

This commit is contained in:
twinaphex 2016-02-19 05:17:47 +01:00
parent d1edfad75f
commit 592e315c3c
2 changed files with 198 additions and 45 deletions

View File

@ -780,6 +780,12 @@ void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
static void retro_run_blit(uint8_t *gfx)
{
unsigned x, y;
#ifdef PSP
static unsigned int __attribute__((aligned(16))) d_list[32];
void* const texture_vram_p = NULL;
#endif
uint16_t *fceu_video_out_ptr = NULL;
struct retro_framebuffer fb = {0};
unsigned incr = 0;
unsigned width = 256;
unsigned height = 240;
@ -798,8 +804,7 @@ static void retro_run_blit(uint8_t *gfx)
}
#ifdef PSP
static unsigned int __attribute__((aligned(16))) d_list[32];
void* const texture_vram_p = (void*) (0x44200000 - (256 * 256)); // max VRAM address - frame size
texture_vram_p = (void*) (0x44200000 - (256 * 256)); // max VRAM address - frame size
sceKernelDcacheWritebackRange(retro_palette,256 * 2);
sceKernelDcacheWritebackRange(XBuf, 256*240 );
@ -827,23 +832,34 @@ static void retro_run_blit(uint8_t *gfx)
video_cb(texture_vram_p, width, height, 256);
#else
fb.width = width;
fb.height = height;
fb.access_flags = RETRO_MEMORY_ACCESS_WRITE;
fceu_video_out_ptr = fceu_video_out;
if (environ_cb(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &fb) && fb.format == RETRO_PIXEL_FORMAT_RGB565)
{
fceu_video_out_ptr = (uint16_t*)fb.data;
pitch = fb.pitch >> 1;
}
if (use_raw_palette)
{
extern uint8 PPU[4];
int deemp = (PPU[1] >> 5) << 2;
for (y = 0; y < height; y++, gfx += incr)
for ( x = 0; x < width; x++, gfx++)
fceu_video_out[y * width + x] = retro_palette[*gfx & 0x3F] | deemp;
fceu_video_out_ptr[y * width + x] = retro_palette[*gfx & 0x3F] | deemp;
}
else
{
for (y = 0; y < height; y++, gfx += incr)
for ( x = 0; x < width; x++, gfx++)
fceu_video_out[y * width + x] = retro_palette[*gfx];
fceu_video_out_ptr[y * width + x] = retro_palette[*gfx];
}
video_cb(fceu_video_out, width, height, pitch);
video_cb(fceu_video_out_ptr, width, height, pitch);
#endif
}

215
src/drivers/libretro/libretro.h Executable file → Normal file
View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2014 The RetroArch team
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro.h).
@ -43,6 +43,40 @@ extern "C" {
#endif
#endif
#ifndef RETRO_CALLCONV
# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__)
# define RETRO_CALLCONV __attribute__((cdecl))
# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64)
# define RETRO_CALLCONV __cdecl
# else
# define RETRO_CALLCONV /* all other platforms only have one calling convention each */
# endif
#endif
#ifndef RETRO_API
# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
# ifdef RETRO_IMPORT_SYMBOLS
# ifdef __GNUC__
# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__))
# else
# define RETRO_API RETRO_CALLCONV __declspec(dllimport)
# endif
# else
# ifdef __GNUC__
# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__))
# else
# define RETRO_API RETRO_CALLCONV __declspec(dllexport)
# endif
# endif
# else
# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__)
# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
# else
# define RETRO_API RETRO_CALLCONV
# endif
# endif
#endif
/* Used for checking API/ABI mismatches that can break libretro
* implementations.
* It is not incremented for compatible changes to the API.
@ -165,13 +199,15 @@ extern "C" {
#define RETRO_DEVICE_ID_ANALOG_Y 1
/* Id values for MOUSE. */
#define RETRO_DEVICE_ID_MOUSE_X 0
#define RETRO_DEVICE_ID_MOUSE_Y 1
#define RETRO_DEVICE_ID_MOUSE_LEFT 2
#define RETRO_DEVICE_ID_MOUSE_RIGHT 3
#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4
#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5
#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6
#define RETRO_DEVICE_ID_MOUSE_X 0
#define RETRO_DEVICE_ID_MOUSE_Y 1
#define RETRO_DEVICE_ID_MOUSE_LEFT 2
#define RETRO_DEVICE_ID_MOUSE_RIGHT 3
#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4
#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5
#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6
#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7
#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8
/* Id values for LIGHTGUN types. */
#define RETRO_DEVICE_ID_LIGHTGUN_X 0
@ -206,6 +242,8 @@ enum retro_language
RETRO_LANGUAGE_KOREAN = 9,
RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10,
RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11,
RETRO_LANGUAGE_ESPERANTO = 12,
RETRO_LANGUAGE_POLISH = 13,
RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */
@ -693,9 +731,10 @@ enum retro_mod
* location-based information from the host device,
* such as current latitude / longitude.
*/
#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30
#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */
#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30
/* const char ** --
* Returns the "content" directory of the frontend.
* Returns the "core assets" directory of the frontend.
* This directory can be used to store specific assets that the
* core relies upon, such as art assets,
* input data, etc etc.
@ -851,6 +890,61 @@ enum retro_mod
* Returns the specified language of the frontend, if specified by the user.
* It can be used by the core for localization purposes.
*/
#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_framebuffer * --
* Returns a preallocated framebuffer which the core can use for rendering
* the frame into when not using SET_HW_RENDER.
* The framebuffer returned from this call must not be used
* after the current call to retro_run() returns.
*
* The goal of this call is to allow zero-copy behavior where a core
* can render directly into video memory, avoiding extra bandwidth cost by copying
* memory from core to video memory.
*
* If this call succeeds and the core renders into it,
* the framebuffer pointer and pitch can be passed to retro_video_refresh_t.
* If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used,
* the core must pass the exact
* same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER;
* i.e. passing a pointer which is offset from the
* buffer is undefined. The width, height and pitch parameters
* must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER.
*
* It is possible for a frontend to return a different pixel format
* than the one used in SET_PIXEL_FORMAT. This can happen if the frontend
* needs to perform conversion.
*
* It is still valid for a core to render to a different buffer
* even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds.
*
* A frontend must make sure that the pointer obtained from this function is
* writeable (and readable).
*/
enum retro_hw_render_interface_type
{
RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
};
/* Base struct. All retro_hw_render_interface_* types
* contain at least these fields. */
struct retro_hw_render_interface
{
enum retro_hw_render_interface_type interface_type;
unsigned interface_version;
};
#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* const struct retro_hw_render_interface ** --
* Returns an API specific rendering interface for accessing API specific data.
* Not all HW rendering APIs support or need this.
* The contents of the returned pointer is specific to the rendering API
* being used. See the various headers like libretro_vulkan.h, etc.
*
* GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
* Similarly, after context_destroyed callback returns,
* the contents of the HW_RENDER_INTERFACE are invalidated.
*/
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
@ -1125,6 +1219,10 @@ struct retro_log_callback
#define RETRO_SIMD_VFPU (1 << 13)
#define RETRO_SIMD_PS (1 << 14)
#define RETRO_SIMD_AES (1 << 15)
#define RETRO_SIMD_VFPV3 (1 << 16)
#define RETRO_SIMD_VFPV4 (1 << 17)
#define RETRO_SIMD_POPCNT (1 << 18)
#define RETRO_SIMD_MOVBE (1 << 19)
typedef uint64_t retro_perf_tick_t;
typedef int64_t retro_time_t;
@ -1464,6 +1562,9 @@ enum retro_hw_context_type
* use the corresponding enums directly. */
RETRO_HW_CONTEXT_OPENGLES_VERSION = 5,
/* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
RETRO_HW_CONTEXT_VULKAN = 6,
RETRO_HW_CONTEXT_DUMMY = INT_MAX
};
@ -1486,23 +1587,28 @@ struct retro_hw_render_callback
*/
retro_hw_context_reset_t context_reset;
/* Set by frontend. */
/* Set by frontend.
* TODO: This is rather obsolete. The frontend should not
* be providing preallocated framebuffers. */
retro_hw_get_current_framebuffer_t get_current_framebuffer;
/* Set by frontend. */
retro_hw_get_proc_address_t get_proc_address;
/* Set if render buffers should have depth component attached. */
/* Set if render buffers should have depth component attached.
* TODO: Obsolete. */
bool depth;
/* Set if stencil buffers should be attached. */
/* Set if stencil buffers should be attached.
* TODO: Obsolete. */
bool stencil;
/* If depth and stencil are true, a packed 24/8 buffer will be added.
* Only attaching stencil is invalid and will be ignored. */
/* Use conventional bottom-left origin convention. If false,
* standard libretro top-left origin semantics are used. */
* standard libretro top-left origin semantics are used.
* TODO: Move to GL specific interface. */
bool bottom_left_origin;
/* Major version number for core GL context or GLES 3.1+. */
@ -1513,6 +1619,7 @@ struct retro_hw_render_callback
/* If this is true, the frontend will go very far to avoid
* resetting context in scenarios like toggling fullscreen, etc.
* TODO: Obsolete? Maybe frontend should just always assume this ...
*/
bool cache_context;
@ -1779,6 +1886,36 @@ struct retro_game_info
const char *meta; /* String of implementation specific meta-data. */
};
#define RETRO_MEMORY_ACCESS_WRITE (1 << 0)
/* The core will write to the buffer provided by retro_framebuffer::data. */
#define RETRO_MEMORY_ACCESS_READ (1 << 1)
/* The core will read from retro_framebuffer::data. */
#define RETRO_MEMORY_TYPE_CACHED (1 << 0)
/* The memory in data is cached.
* If not cached, random writes and/or reading from the buffer is expected to be very slow. */
struct retro_framebuffer
{
void *data; /* The framebuffer which the core can render into.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER.
The initial contents of data are unspecified. */
unsigned width; /* The framebuffer width used by the core. Set by core. */
unsigned height; /* The framebuffer height used by the core. Set by core. */
size_t pitch; /* The number of bytes between the beginning of a scanline,
and beginning of the next scanline.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
enum retro_pixel_format format; /* The pixel format the core must use to render into data.
This format could differ from the format used in
SET_PIXEL_FORMAT.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
unsigned access_flags; /* How the core will access the memory in the framebuffer.
RETRO_MEMORY_ACCESS_* flags.
Set by core. */
unsigned memory_flags; /* Flags telling core how the memory has been mapped.
RETRO_MEMORY_TYPE_* flags.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
};
/* Callbacks */
/* Environment callback. Gives implementations a way of performing
@ -1832,25 +1969,25 @@ typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device,
*
* The rest of the set_* functions are guaranteed to have been called
* before the first call to retro_run() is made. */
void retro_set_environment(retro_environment_t);
void retro_set_video_refresh(retro_video_refresh_t);
void retro_set_audio_sample(retro_audio_sample_t);
void retro_set_audio_sample_batch(retro_audio_sample_batch_t);
void retro_set_input_poll(retro_input_poll_t);
void retro_set_input_state(retro_input_state_t);
RETRO_API void retro_set_environment(retro_environment_t);
RETRO_API void retro_set_video_refresh(retro_video_refresh_t);
RETRO_API void retro_set_audio_sample(retro_audio_sample_t);
RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t);
RETRO_API void retro_set_input_poll(retro_input_poll_t);
RETRO_API void retro_set_input_state(retro_input_state_t);
/* Library global initialization/deinitialization. */
void retro_init(void);
void retro_deinit(void);
RETRO_API void retro_init(void);
RETRO_API void retro_deinit(void);
/* Must return RETRO_API_VERSION. Used to validate ABI compatibility
* when the API is revised. */
unsigned retro_api_version(void);
RETRO_API unsigned retro_api_version(void);
/* Gets statically known system info. Pointers provided in *info
* must be statically allocated.
* Can be called at any time, even before retro_init(). */
void retro_get_system_info(struct retro_system_info *info);
RETRO_API void retro_get_system_info(struct retro_system_info *info);
/* Gets information about system audio/video timings and geometry.
* Can be called only after retro_load_game() has successfully completed.
@ -1858,7 +1995,7 @@ void retro_get_system_info(struct retro_system_info *info);
* variable if needed.
* E.g. geom.aspect_ratio might not be initialized if core doesn't
* desire a particular aspect ratio. */
void retro_get_system_av_info(struct retro_system_av_info *info);
RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info);
/* Sets device to be used for player 'port'.
* By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all
@ -1868,10 +2005,10 @@ void retro_get_system_av_info(struct retro_system_av_info *info);
* hint to the libretro core when a core cannot automatically detect the
* appropriate input device type on its own. It is also relevant when a
* core can change its behavior depending on device type. */
void retro_set_controller_port_device(unsigned port, unsigned device);
RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device);
/* Resets the current game. */
void retro_reset(void);
RETRO_API void retro_reset(void);
/* Runs the game for one video frame.
* During retro_run(), input_poll callback must be called at least once.
@ -1881,7 +2018,7 @@ void retro_reset(void);
* a frame if GET_CAN_DUPE returns true.
* In this case, the video callback can take a NULL argument for data.
*/
void retro_run(void);
RETRO_API void retro_run(void);
/* Returns the amount of data the implementation requires to serialize
* internal state (save states).
@ -1889,35 +2026,35 @@ void retro_run(void);
* returned size is never allowed to be larger than a previous returned
* value, to ensure that the frontend can allocate a save state buffer once.
*/
size_t retro_serialize_size(void);
RETRO_API size_t retro_serialize_size(void);
/* Serializes internal state. If failed, or size is lower than
* retro_serialize_size(), it should return false, true otherwise. */
bool retro_serialize(void *data, size_t size);
bool retro_unserialize(const void *data, size_t size);
RETRO_API bool retro_serialize(void *data, size_t size);
RETRO_API bool retro_unserialize(const void *data, size_t size);
void retro_cheat_reset(void);
void retro_cheat_set(unsigned index, bool enabled, const char *code);
RETRO_API void retro_cheat_reset(void);
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
/* Loads a game. */
bool retro_load_game(const struct retro_game_info *game);
RETRO_API bool retro_load_game(const struct retro_game_info *game);
/* Loads a "special" kind of game. Should not be used,
* except in extreme cases. */
bool retro_load_game_special(
RETRO_API bool retro_load_game_special(
unsigned game_type,
const struct retro_game_info *info, size_t num_info
);
/* Unloads a currently loaded game. */
void retro_unload_game(void);
RETRO_API void retro_unload_game(void);
/* Gets region of game. */
unsigned retro_get_region(void);
RETRO_API unsigned retro_get_region(void);
/* Gets region of memory. */
void *retro_get_memory_data(unsigned id);
size_t retro_get_memory_size(unsigned id);
RETRO_API void *retro_get_memory_data(unsigned id);
RETRO_API size_t retro_get_memory_size(unsigned id);
#ifdef __cplusplus
}