mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Merge branch 'master' of https://github.com/FIX94/RetroArch
This commit is contained in:
commit
1ed54b8683
@ -361,8 +361,19 @@ ifeq ($(HAVE_NEON),1)
|
||||
OBJ += audio/audio_utils_neon.o
|
||||
endif
|
||||
|
||||
HW_CONTEXT_MENU_DRIVERS=$(HAVE_RGUI)
|
||||
|
||||
ifeq ($(HW_CONTEXT_MENU_DRIVERS),0)
|
||||
ifeq ($(HAVE_GL_CONTEXT),1)
|
||||
HW_CONTEXT_MENU_DRIVERS=1
|
||||
endif
|
||||
ifeq ($(HAVE_VULKAN),1)
|
||||
HW_CONTEXT_MENU_DRIVERS=1
|
||||
endif
|
||||
endif
|
||||
|
||||
# XMB and MaterialUI are always enabled if supported and not explicitly disabled
|
||||
ifeq ($(HAVE_RGUI)$(HAVE_GL_CONTEXT), 11)
|
||||
ifeq ($(HW_CONTEXT_MENU_DRIVERS), 1)
|
||||
ifeq ($(HAVE_ZARCH),)
|
||||
HAVE_ZARCH = 1
|
||||
endif
|
||||
@ -586,6 +597,13 @@ OBJ += gfx/video_context_driver.o \
|
||||
libretro-common/gfx/math/matrix_4x4.o \
|
||||
libretro-common/gfx/math/matrix_3x3.o
|
||||
|
||||
ifeq ($(HAVE_KMS), 1)
|
||||
HAVE_AND_WILL_USE_DRM = 1
|
||||
OBJ += gfx/drivers_context/drm_ctx.o
|
||||
DEFINES += $(GBM_CFLAGS) $(DRM_CFLAGS) $(EGL_CFLAGS)
|
||||
LIBS += $(GBM_LIBS) $(DRM_LIBS) $(EGL_LIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GL_CONTEXT), 1)
|
||||
DEFINES += -DHAVE_OPENGL -DHAVE_GLSL
|
||||
OBJ += gfx/drivers/gl.o \
|
||||
@ -597,13 +615,6 @@ ifeq ($(HAVE_GL_CONTEXT), 1)
|
||||
OBJ += menu/drivers_display/menu_display_gl.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_KMS), 1)
|
||||
HAVE_AND_WILL_USE_DRM = 1
|
||||
OBJ += gfx/drivers_context/drm_egl_ctx.o
|
||||
DEFINES += $(GBM_CFLAGS) $(DRM_CFLAGS) $(EGL_CFLAGS)
|
||||
LIBS += $(GBM_LIBS) $(DRM_LIBS) $(EGL_LIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VIDEOCORE), 1)
|
||||
OBJ += gfx/drivers_context/vc_egl_ctx.o
|
||||
DEFINES += $(EGL_CFLAGS)
|
||||
|
@ -638,18 +638,6 @@ static bool event_save_auto_state(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void event_init_remapping(void)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *path = settings->input.remapping_path;
|
||||
config_file_t *conf = config_file_new(path);
|
||||
|
||||
if (!settings->input.remap_binds_enable || !conf)
|
||||
return;
|
||||
|
||||
input_remapping_load_file(conf, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* event_save_core_config:
|
||||
*
|
||||
@ -684,7 +672,6 @@ static bool event_save_core_config(void)
|
||||
RARCH_ERR("%s\n", msg_hash_to_str(MSG_CONFIG_DIRECTORY_NOT_SET));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Infer file name based on libretro core. */
|
||||
if (*settings->libretro && path_file_exists(settings->libretro))
|
||||
{
|
||||
@ -700,14 +687,12 @@ static bool event_save_core_config(void)
|
||||
path_remove_extension(config_name);
|
||||
fill_pathname_join(config_path, config_dir, config_name,
|
||||
sizeof(config_path));
|
||||
|
||||
if (i)
|
||||
snprintf(tmp, sizeof(tmp), "-%u.cfg", i);
|
||||
else
|
||||
strlcpy(tmp, ".cfg", sizeof(tmp));
|
||||
|
||||
fill_string_join(config_path, tmp, sizeof(config_path));
|
||||
|
||||
snprintf(config_path, sizeof(config_path), "%s%s", config_path, tmp);
|
||||
if (!path_file_exists(config_path))
|
||||
{
|
||||
found_path = true;
|
||||
@ -765,8 +750,10 @@ static bool event_save_core_config(void)
|
||||
**/
|
||||
void event_save_current_config(void)
|
||||
{
|
||||
char msg[128];
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
bool ret = false;
|
||||
|
||||
if (settings->config_save_on_exit && *global->path.config)
|
||||
{
|
||||
@ -774,15 +761,29 @@ void event_save_current_config(void)
|
||||
* needed on consoles for core switching and reusing last good
|
||||
* config for new cores.
|
||||
*/
|
||||
config_save_file(global->path.config);
|
||||
|
||||
/* Flush out the core specific config. */
|
||||
if (*global->path.core_specific_config &&
|
||||
settings->core_specific_config)
|
||||
config_save_file(global->path.core_specific_config);
|
||||
ret = config_save_file(global->path.core_specific_config);
|
||||
else
|
||||
ret = config_save_file(global->path.config);
|
||||
}
|
||||
|
||||
event_cmd_ctl(EVENT_CMD_AUTOSAVE_STATE, NULL);
|
||||
if (ret)
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "Saved new config to \"%s\".",
|
||||
global->path.config);
|
||||
RARCH_LOG("%s\n", msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "Failed saving config to \"%s\".",
|
||||
global->path.config);
|
||||
RARCH_ERR("%s\n", msg);
|
||||
}
|
||||
|
||||
runloop_msg_queue_push(msg, 1, 180, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1133,12 +1134,6 @@ bool event_cmd_ctl(enum event_command cmd, void *data)
|
||||
case EVENT_CMD_CHEATS_APPLY:
|
||||
cheat_manager_apply_cheats();
|
||||
break;
|
||||
case EVENT_CMD_REMAPPING_DEINIT:
|
||||
break;
|
||||
case EVENT_CMD_REMAPPING_INIT:
|
||||
event_cmd_ctl(EVENT_CMD_REMAPPING_DEINIT, NULL);
|
||||
event_init_remapping();
|
||||
break;
|
||||
case EVENT_CMD_REWIND_DEINIT:
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
|
||||
|
@ -201,8 +201,6 @@ enum event_command
|
||||
/* Toggles fullscreen mode. */
|
||||
EVENT_CMD_FULLSCREEN_TOGGLE,
|
||||
EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG,
|
||||
EVENT_CMD_REMAPPING_INIT,
|
||||
EVENT_CMD_REMAPPING_DEINIT,
|
||||
EVENT_CMD_VOLUME_UP,
|
||||
EVENT_CMD_VOLUME_DOWN,
|
||||
EVENT_CMD_EXEC
|
||||
|
@ -1564,8 +1564,6 @@ static bool config_load_file(const char *path, bool set_defaults)
|
||||
}
|
||||
}
|
||||
|
||||
config_get_path(conf, "input_remapping_path", settings->input.remapping_path,
|
||||
sizeof(settings->input.remapping_path));
|
||||
config_get_path(conf, "resampler_directory", settings->resampler_directory,
|
||||
sizeof(settings->resampler_directory));
|
||||
config_get_path(conf, "cache_directory", settings->cache_directory,
|
||||
@ -2167,7 +2165,6 @@ bool config_load_remap(void)
|
||||
else
|
||||
{
|
||||
RARCH_LOG("Remaps: no game-specific remap found at %s\n", game_path);
|
||||
*settings->input.remapping_path= '\0';
|
||||
input_remapping_set_defaults();
|
||||
}
|
||||
|
||||
@ -2187,7 +2184,6 @@ bool config_load_remap(void)
|
||||
else
|
||||
{
|
||||
RARCH_LOG("Remaps: no core-specific remap found at %s\n", core_path);
|
||||
*settings->input.remapping_path= '\0';
|
||||
input_remapping_set_defaults();
|
||||
}
|
||||
|
||||
@ -2695,8 +2691,6 @@ bool config_save_file(const char *path)
|
||||
settings->cache_directory);
|
||||
config_set_path(conf, "input_remapping_directory",
|
||||
settings->input_remapping_directory);
|
||||
config_set_path(conf, "input_remapping_path",
|
||||
settings->input.remapping_path);
|
||||
config_set_path(conf, "resampler_directory",
|
||||
settings->resampler_directory);
|
||||
config_set_string(conf, "audio_resampler", settings->audio.resampler);
|
||||
|
@ -256,8 +256,6 @@ typedef struct settings
|
||||
bool input_descriptor_label_show;
|
||||
bool input_descriptor_hide_unbound;
|
||||
|
||||
char remapping_path[PATH_MAX_LENGTH];
|
||||
|
||||
unsigned menu_toggle_gamepad_combo;
|
||||
bool back_as_menu_toggle_enable;
|
||||
|
||||
|
@ -9,10 +9,6 @@
|
||||
#include <file/file_path.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <rthreads/async_job.h>
|
||||
#endif
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
@ -42,6 +38,7 @@ static retro_input_state_t IMAGE_CORE_PREFIX(input_state_cb);
|
||||
static retro_audio_sample_batch_t IMAGE_CORE_PREFIX(audio_batch_cb);
|
||||
static retro_environment_t IMAGE_CORE_PREFIX(environ_cb);
|
||||
|
||||
static bool process_new_image;
|
||||
static uint32_t* image_buffer;
|
||||
static int image_width;
|
||||
static int image_height;
|
||||
@ -49,17 +46,6 @@ static bool image_uploaded;
|
||||
static bool slideshow_enable;
|
||||
struct string_list *file_list;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static async_job_t *imageviewer_jobs;
|
||||
|
||||
#if 0
|
||||
static int imageviewer_async_job_add(async_task_t task, void *payload)
|
||||
{
|
||||
return async_job_add(imageviewer_jobs, task, payload);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define DUPE_TEST
|
||||
#endif
|
||||
@ -103,9 +89,6 @@ void IMAGE_CORE_PREFIX(retro_init)(void)
|
||||
image_width = 0;
|
||||
image_height = 0;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
imageviewer_jobs = async_job_new();
|
||||
#endif
|
||||
}
|
||||
|
||||
void IMAGE_CORE_PREFIX(retro_deinit)(void)
|
||||
@ -115,11 +98,6 @@ void IMAGE_CORE_PREFIX(retro_deinit)(void)
|
||||
image_buffer = NULL;
|
||||
image_width = 0;
|
||||
image_height = 0;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
async_job_free(imageviewer_jobs);
|
||||
imageviewer_jobs = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void IMAGE_CORE_PREFIX(retro_set_environment)(retro_environment_t cb)
|
||||
@ -193,12 +171,11 @@ void IMAGE_CORE_PREFIX(retro_cheat_set)(unsigned a, bool b, const char * c)
|
||||
{
|
||||
}
|
||||
|
||||
static bool imageviewer_load(const char *path, uint32_t *buf, int image_index)
|
||||
static bool imageviewer_load(const char *path, int image_index)
|
||||
{
|
||||
int comp;
|
||||
struct retro_system_av_info info;
|
||||
uint32_t *end = NULL;
|
||||
if (image_buffer) free(image_buffer);
|
||||
if (image_buffer)
|
||||
free(image_buffer);
|
||||
|
||||
image_buffer = (uint32_t*)stbi_load(
|
||||
path,
|
||||
@ -207,30 +184,17 @@ static bool imageviewer_load(const char *path, uint32_t *buf, int image_index)
|
||||
&comp,
|
||||
4);
|
||||
|
||||
/* RGBA > XRGB8888 */
|
||||
buf = &image_buffer[0];
|
||||
|
||||
if (!buf)
|
||||
if (!image_buffer)
|
||||
return false;
|
||||
end = buf + (image_width*image_height*sizeof(uint32_t))/4;
|
||||
|
||||
while(buf < end)
|
||||
{
|
||||
uint32_t pixel = *buf;
|
||||
*buf = (pixel & 0xff00ff00) | ((pixel << 16) & 0x00ff0000) | ((pixel >> 16) & 0xff);
|
||||
buf++;
|
||||
}
|
||||
process_new_image = true;
|
||||
|
||||
IMAGE_CORE_PREFIX(retro_get_system_av_info)(&info);
|
||||
|
||||
IMAGE_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_GEOMETRY, &info.geometry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IMAGE_CORE_PREFIX(retro_load_game)(const struct retro_game_info *info)
|
||||
{
|
||||
uint32_t *buf = NULL;
|
||||
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
|
||||
char *dir = strdup(info->path);
|
||||
|
||||
@ -251,7 +215,7 @@ bool IMAGE_CORE_PREFIX(retro_load_game)(const struct retro_game_info *info)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!imageviewer_load(info->path, buf, 0))
|
||||
if (!imageviewer_load(info->path, 0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -289,7 +253,6 @@ size_t IMAGE_CORE_PREFIX(retro_get_memory_size)(unsigned id)
|
||||
|
||||
void IMAGE_CORE_PREFIX(retro_run)(void)
|
||||
{
|
||||
uint32_t *buf = NULL;
|
||||
bool first_image = false;
|
||||
bool last_image = false;
|
||||
bool backwards_image = false;
|
||||
@ -387,12 +350,33 @@ void IMAGE_CORE_PREFIX(retro_run)(void)
|
||||
|
||||
if (load_image)
|
||||
{
|
||||
if (!imageviewer_load(file_list->elems[image_index].data, buf, image_index))
|
||||
if (!imageviewer_load(file_list->elems[image_index].data, image_index))
|
||||
{
|
||||
IMAGE_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (process_new_image)
|
||||
{
|
||||
/* RGBA > XRGB8888 */
|
||||
struct retro_system_av_info info;
|
||||
uint32_t *buf = &image_buffer[0];
|
||||
uint32_t *end = buf + (image_width*image_height*sizeof(uint32_t))/4;
|
||||
|
||||
while(buf < end)
|
||||
{
|
||||
uint32_t pixel = *buf;
|
||||
*buf = (pixel & 0xff00ff00) | ((pixel << 16) & 0x00ff0000) | ((pixel >> 16) & 0xff);
|
||||
buf++;
|
||||
}
|
||||
|
||||
IMAGE_CORE_PREFIX(retro_get_system_av_info)(&info);
|
||||
|
||||
IMAGE_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_GEOMETRY, &info.geometry);
|
||||
|
||||
process_new_image = false;
|
||||
}
|
||||
|
||||
#ifdef DUPE_TEST
|
||||
if (!image_uploaded)
|
||||
{
|
||||
|
@ -178,10 +178,10 @@ static void vulkan_test_render(void)
|
||||
update_ubo();
|
||||
|
||||
VkCommandBuffer cmd = vk.cmd[vk.index];
|
||||
vkResetCommandPool(vulkan->device, vk.cmd_pool[vk.index], 0);
|
||||
|
||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkResetCommandBuffer(cmd, 0);
|
||||
vkBeginCommandBuffer(cmd, &begin_info);
|
||||
|
||||
VkImageMemoryBarrier prepare_rendering = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
@ -548,6 +548,7 @@ static void init_swapchain(void)
|
||||
vkAllocateMemory(device, &alloc, NULL, &vk.image_memory[i]);
|
||||
vkBindImageMemory(device, vk.images[i].create_info.image, vk.image_memory[i], 0);
|
||||
|
||||
vk.images[i].create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
vk.images[i].create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
vk.images[i].create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
vk.images[i].create_info.subresourceRange.baseMipLevel = 0;
|
||||
@ -582,6 +583,7 @@ static void init_command(void)
|
||||
VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
|
||||
pool_info.queueFamilyIndex = vulkan->queue_index;
|
||||
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
|
||||
for (unsigned i = 0; i < vk.num_swapchain_images; i++)
|
||||
{
|
||||
|
@ -104,7 +104,9 @@ int rarch_main(int argc, char *argv[], void *data)
|
||||
char *fullpath = NULL;
|
||||
rarch_system_info_t *system = NULL;
|
||||
void *args = (void*)data;
|
||||
#ifndef HAVE_MAIN
|
||||
int ret = 0;
|
||||
#endif
|
||||
|
||||
rarch_ctl(RARCH_CTL_PREINIT, NULL);
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
volatile sig_atomic_t g_egl_quit;
|
||||
bool g_egl_inited;
|
||||
|
||||
enum gfx_ctx_api g_egl_api;
|
||||
unsigned g_egl_major = 0;
|
||||
unsigned g_egl_minor = 0;
|
||||
|
||||
@ -102,7 +101,6 @@ void egl_destroy(void *data)
|
||||
egl->dpy = EGL_NO_DISPLAY;
|
||||
egl->config = 0;
|
||||
g_egl_quit = 0;
|
||||
egl->api = GFX_CTX_NONE;
|
||||
g_egl_inited = false;
|
||||
}
|
||||
|
||||
@ -209,7 +207,6 @@ bool egl_init_context(void *data, NativeDisplayType display,
|
||||
if (!eglChooseConfig(egl->dpy, attrib_ptr, &egl->config, 1, n) || *n != 1)
|
||||
return false;
|
||||
|
||||
egl->api = g_egl_api;
|
||||
egl->major = g_egl_major;
|
||||
egl->minor = g_egl_minor;
|
||||
|
||||
|
@ -53,7 +53,6 @@ typedef struct
|
||||
|
||||
unsigned major;
|
||||
unsigned minor;
|
||||
enum gfx_ctx_api api;
|
||||
|
||||
/* egl "private" */
|
||||
bool use_hw_ctx;
|
||||
@ -64,7 +63,6 @@ extern bool g_egl_inited;
|
||||
|
||||
/* bind_api is called before init so we need these, please
|
||||
* try no to use them outside of bind_api() and init() */
|
||||
extern enum gfx_ctx_api g_egl_api;
|
||||
extern unsigned g_egl_major;
|
||||
extern unsigned g_egl_minor;
|
||||
|
||||
|
@ -86,6 +86,48 @@ void vulkan_map_persistent_texture(VkDevice device, struct vk_texture *texture)
|
||||
vkMapMemory(device, texture->memory, texture->offset, texture->size, 0, &texture->mapped);
|
||||
}
|
||||
|
||||
void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd,
|
||||
struct vk_texture *dynamic,
|
||||
struct vk_texture *staging)
|
||||
{
|
||||
VkImageCopy region;
|
||||
retro_assert(dynamic->type == VULKAN_TEXTURE_DYNAMIC);
|
||||
retro_assert(staging->type == VULKAN_TEXTURE_STAGING);
|
||||
|
||||
vulkan_transition_texture(vk, staging);
|
||||
|
||||
/* We don't have to sync against previous TRANSFER, since we observed the completion
|
||||
* by fences. If we have a single texture_optimal, we would need to sync against
|
||||
* previous transfers to avoid races.
|
||||
*
|
||||
* We would also need to optionally maintain extra textures due to changes in resolution,
|
||||
* so this seems like the sanest and simplest solution. */
|
||||
vulkan_image_layout_transition(vk, vk->cmd, dynamic->image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||
|
||||
memset(®ion, 0, sizeof(region));
|
||||
region.extent.width = dynamic->width;
|
||||
region.extent.height = dynamic->height;
|
||||
region.extent.depth = 1;
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.dstSubresource = region.srcSubresource;
|
||||
|
||||
vkCmdCopyImage(vk->cmd,
|
||||
staging->image, VK_IMAGE_LAYOUT_GENERAL,
|
||||
dynamic->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
vulkan_image_layout_transition(vk, vk->cmd, dynamic->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
#ifdef VULKAN_DEBUG_TEXTURE_ALLOC
|
||||
static VkImage vk_images[4 * 1024];
|
||||
static unsigned vk_count;
|
||||
@ -131,70 +173,126 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
VkFormat format,
|
||||
const void *initial, const VkComponentMapping *swizzle, enum vk_texture_type type)
|
||||
{
|
||||
/* TODO: Evaluate how we should do texture uploads on discrete cards optimally.
|
||||
* For integrated GPUs, using linear texture is highly desirable to avoid extra copies, but
|
||||
* we might need to take a DMA transfer with block interleave on desktop GPUs.
|
||||
*
|
||||
* Also, Vulkan drivers are not required to support sampling from linear textures
|
||||
* (only TRANSFER), but seems to work fine on GPUs I've tested so far. */
|
||||
|
||||
VkDevice device = vk->context->device;
|
||||
struct vk_texture tex;
|
||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
|
||||
VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
VkImageSubresource subresource = { VK_IMAGE_ASPECT_COLOR_BIT };
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkSubresourceLayout layout;
|
||||
|
||||
if (type == VULKAN_TEXTURE_STATIC && !initial)
|
||||
retro_assert(0 && "Static textures must have initial data.\n");
|
||||
VkDevice device = vk->context->device;
|
||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
VkImageSubresource subresource = { VK_IMAGE_ASPECT_COLOR_BIT };
|
||||
VkCommandBufferAllocateInfo cmd_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
|
||||
memset(&tex, 0, sizeof(tex));
|
||||
|
||||
info.imageType = VK_IMAGE_TYPE_2D;
|
||||
info.format = format;
|
||||
info.extent.width = width;
|
||||
info.imageType = VK_IMAGE_TYPE_2D;
|
||||
info.format = format;
|
||||
info.extent.width = width;
|
||||
info.extent.height = height;
|
||||
info.extent.depth = 1;
|
||||
info.mipLevels = 1;
|
||||
info.arrayLayers = 1;
|
||||
info.extent.depth = 1;
|
||||
info.mipLevels = 1;
|
||||
info.arrayLayers = 1;
|
||||
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
info.tiling = type != VULKAN_TEXTURE_STATIC ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
if (type == VULKAN_TEXTURE_STATIC)
|
||||
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
if (type == VULKAN_TEXTURE_READBACK)
|
||||
info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
/* We'll transition this on first use for streamed textures. */
|
||||
info.initialLayout = type == VULKAN_TEXTURE_STREAMED ?
|
||||
VK_IMAGE_LAYOUT_PREINITIALIZED :
|
||||
VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
if (type == VULKAN_TEXTURE_STREAMED)
|
||||
{
|
||||
VkFormatProperties format_properties;
|
||||
VkFormatFeatureFlags required = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
||||
vkGetPhysicalDeviceFormatProperties(vk->context->gpu, format, &format_properties);
|
||||
|
||||
if ((format_properties.linearTilingFeatures & required) != required)
|
||||
{
|
||||
RARCH_LOG("[Vulkan]: GPU does not support using linear images as textures. Falling back to copy path.\n");
|
||||
type = VULKAN_TEXTURE_STAGING;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case VULKAN_TEXTURE_STATIC:
|
||||
retro_assert(initial && "Static textures must have initial data.\n");
|
||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
break;
|
||||
|
||||
case VULKAN_TEXTURE_DYNAMIC:
|
||||
retro_assert(!initial && "Dynamic textures must not have initial data.\n");
|
||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
break;
|
||||
|
||||
case VULKAN_TEXTURE_STREAMED:
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
|
||||
break;
|
||||
|
||||
case VULKAN_TEXTURE_STAGING:
|
||||
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
|
||||
break;
|
||||
|
||||
case VULKAN_TEXTURE_READBACK:
|
||||
info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
|
||||
vkCreateImage(device, &info, NULL, &tex.image);
|
||||
#if 0
|
||||
vulkan_track_alloc(tex.image);
|
||||
#endif
|
||||
|
||||
vkGetImageMemoryRequirements(device, tex.image, &mem_reqs);
|
||||
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
|
||||
if (type == VULKAN_TEXTURE_STATIC)
|
||||
switch (type)
|
||||
{
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(&vk->context->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
|
||||
case VULKAN_TEXTURE_STATIC:
|
||||
case VULKAN_TEXTURE_DYNAMIC:
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(&vk->context->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(&vk->context->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
/* If the texture is STREAMED and it's not DEVICE_LOCAL, we expect to hit a slower path,
|
||||
* so fallback to copy path. */
|
||||
if (type == VULKAN_TEXTURE_STREAMED &&
|
||||
(vk->context->memory_properties.memoryTypes[alloc.memoryTypeIndex].propertyFlags &
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0)
|
||||
{
|
||||
/* Recreate texture but for STAGING this time ... */
|
||||
RARCH_LOG("[Vulkan]: GPU supports linear images as textures, but not DEVICE_LOCAL. Falling back to copy path.\n");
|
||||
type = VULKAN_TEXTURE_STAGING;
|
||||
vkDestroyImage(device, tex.image, NULL);
|
||||
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
vkCreateImage(device, &info, NULL, &tex.image);
|
||||
vkGetImageMemoryRequirements(device, tex.image, &mem_reqs);
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(&vk->context->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
}
|
||||
|
||||
/* We're not reusing the objects themselves. */
|
||||
@ -213,7 +311,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
old->memory_size >= mem_reqs.size &&
|
||||
old->memory_type == alloc.memoryTypeIndex)
|
||||
{
|
||||
tex.memory = old->memory;
|
||||
tex.memory = old->memory;
|
||||
tex.memory_size = old->memory_size;
|
||||
tex.memory_type = old->memory_type;
|
||||
|
||||
@ -237,17 +335,17 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
|
||||
vkBindImageMemory(device, tex.image, tex.memory, 0);
|
||||
|
||||
view.image = tex.image;
|
||||
view.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
view.format = format;
|
||||
view.image = tex.image;
|
||||
view.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
view.format = format;
|
||||
if (swizzle)
|
||||
view.components = *swizzle;
|
||||
view.components = *swizzle;
|
||||
else
|
||||
{
|
||||
view.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
view.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
view.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
view.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
view.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
view.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
view.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
view.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
}
|
||||
view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
view.subresourceRange.levelCount = 1;
|
||||
@ -258,26 +356,27 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
vkGetImageSubresourceLayout(device, tex.image, &subresource, &layout);
|
||||
tex.stride = layout.rowPitch;
|
||||
tex.offset = layout.offset;
|
||||
tex.size = layout.size;
|
||||
tex.size = layout.size;
|
||||
tex.layout = info.initialLayout;
|
||||
|
||||
tex.width = width;
|
||||
tex.width = width;
|
||||
tex.height = height;
|
||||
tex.format = format;
|
||||
tex.type = type;
|
||||
|
||||
if (initial && type == VULKAN_TEXTURE_STREAMED)
|
||||
if (initial && (type == VULKAN_TEXTURE_STREAMED || type == VULKAN_TEXTURE_STAGING))
|
||||
{
|
||||
unsigned bpp = vulkan_format_to_bpp(tex.format);
|
||||
unsigned stride = tex.width * bpp;
|
||||
unsigned x, y;
|
||||
uint8_t *dst;
|
||||
const uint8_t *src;
|
||||
void *ptr;
|
||||
uint8_t *dst = NULL;
|
||||
const uint8_t *src = NULL;
|
||||
void *ptr = NULL;
|
||||
unsigned bpp = vulkan_format_to_bpp(tex.format);
|
||||
unsigned stride = tex.width * bpp;
|
||||
|
||||
vkMapMemory(device, tex.memory, tex.offset, tex.size, 0, &ptr);
|
||||
|
||||
dst = (uint8_t*)ptr;
|
||||
src = (const uint8_t*)initial;
|
||||
dst = (uint8_t*)ptr;
|
||||
src = (const uint8_t*)initial;
|
||||
for (y = 0; y < tex.height; y++, dst += tex.stride, src += stride)
|
||||
memcpy(dst, src, width * bpp);
|
||||
|
||||
@ -285,22 +384,18 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
}
|
||||
else if (initial && type == VULKAN_TEXTURE_STATIC)
|
||||
{
|
||||
VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
VkImageCopy region;
|
||||
|
||||
VkCommandBuffer staging;
|
||||
unsigned bpp = vulkan_format_to_bpp(tex.format);
|
||||
struct vk_texture tmp = vulkan_create_texture(vk, NULL,
|
||||
width, height, format, initial, NULL, VULKAN_TEXTURE_STREAMED);
|
||||
width, height, format, initial, NULL, VULKAN_TEXTURE_STAGING);
|
||||
|
||||
info.commandPool = vk->staging_pool;
|
||||
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
info.commandBufferCount = 1;
|
||||
vkAllocateCommandBuffers(vk->context->device, &info, &staging);
|
||||
cmd_info.commandPool = vk->staging_pool;
|
||||
cmd_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cmd_info.commandBufferCount = 1;
|
||||
vkAllocateCommandBuffers(vk->context->device, &cmd_info, &staging);
|
||||
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkBeginCommandBuffer(staging, &begin_info);
|
||||
|
||||
vulkan_image_layout_transition(vk, staging, tmp.image,
|
||||
@ -316,12 +411,12 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||
|
||||
memset(®ion, 0, sizeof(region));
|
||||
region.extent.width = width;
|
||||
region.extent.height = height;
|
||||
region.extent.depth = 1;
|
||||
region.extent.width = width;
|
||||
region.extent.height = height;
|
||||
region.extent.depth = 1;
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.dstSubresource = region.srcSubresource;
|
||||
region.dstSubresource = region.srcSubresource;
|
||||
|
||||
vkCmdCopyImage(staging,
|
||||
tmp.image, VK_IMAGE_LAYOUT_GENERAL,
|
||||
@ -329,19 +424,23 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
||||
1, ®ion);
|
||||
|
||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||
|
||||
vkEndCommandBuffer(staging);
|
||||
submit_info.commandBufferCount = 1;
|
||||
submit_info.pCommandBuffers = &staging;
|
||||
submit_info.pCommandBuffers = &staging;
|
||||
|
||||
slock_lock(vk->context->queue_lock);
|
||||
vkQueueSubmit(vk->context->queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
/* TODO: Very crude, but texture uploads only happen during init,
|
||||
* so waiting for GPU to complete transfer and blocking isn't a big deal. */
|
||||
|
||||
/* TODO: Very crude, but texture uploads only happen
|
||||
* during init, so waiting for GPU to complete transfer
|
||||
* and blocking isn't a big deal. */
|
||||
vkQueueWaitIdle(vk->context->queue);
|
||||
slock_unlock(vk->context->queue_lock);
|
||||
|
||||
@ -377,33 +476,34 @@ static void vulkan_write_quad_descriptors(VkDevice device,
|
||||
VkDescriptorImageInfo image_info;
|
||||
VkDescriptorBufferInfo buffer_info;
|
||||
|
||||
image_info.sampler = sampler;
|
||||
image_info.imageView = texture->view;
|
||||
image_info.sampler = sampler;
|
||||
image_info.imageView = texture->view;
|
||||
image_info.imageLayout = texture->layout;
|
||||
|
||||
buffer_info.buffer = buffer;
|
||||
buffer_info.offset = offset;
|
||||
buffer_info.range = range;
|
||||
buffer_info.buffer = buffer;
|
||||
buffer_info.offset = offset;
|
||||
buffer_info.range = range;
|
||||
|
||||
write.dstSet = set;
|
||||
write.dstBinding = 0;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
write.pBufferInfo = &buffer_info;
|
||||
write.dstSet = set;
|
||||
write.dstBinding = 0;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
write.pBufferInfo = &buffer_info;
|
||||
vkUpdateDescriptorSets(device, 1, &write, 0, NULL);
|
||||
|
||||
write.dstSet = set;
|
||||
write.dstBinding = 1;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write.pImageInfo = &image_info;
|
||||
write.dstSet = set;
|
||||
write.dstBinding = 1;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write.pImageInfo = &image_info;
|
||||
vkUpdateDescriptorSets(device, 1, &write, 0, NULL);
|
||||
}
|
||||
|
||||
void vulkan_transition_texture(vk_t *vk, struct vk_texture *texture)
|
||||
{
|
||||
/* Transition to GENERAL layout for linear streamed textures.
|
||||
* We're using linear textures here, so only GENERAL layout is supported.
|
||||
* We're using linear textures here, so only
|
||||
* GENERAL layout is supported.
|
||||
*/
|
||||
if (texture->layout == VK_IMAGE_LAYOUT_PREINITIALIZED)
|
||||
{
|
||||
@ -420,7 +520,9 @@ static void vulkan_check_dynamic_state(vk_t *vk)
|
||||
{
|
||||
if (vk->tracker.dirty & VULKAN_DIRTY_DYNAMIC_BIT)
|
||||
{
|
||||
const VkRect2D sci = {{ vk->vp.x, vk->vp.y }, { vk->vp.width, vk->vp.height }};
|
||||
const VkRect2D sci = {
|
||||
{ vk->vp.x, vk->vp.y },
|
||||
{ vk->vp.width, vk->vp.height }};
|
||||
vkCmdSetViewport(vk->cmd, 0, 1, &vk->vk_vp);
|
||||
vkCmdSetScissor(vk->cmd, 0, 1, &sci);
|
||||
|
||||
@ -434,7 +536,8 @@ void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call)
|
||||
|
||||
if (call->pipeline != vk->tracker.pipeline)
|
||||
{
|
||||
vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, call->pipeline);
|
||||
vkCmdBindPipeline(vk->cmd,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, call->pipeline);
|
||||
vk->tracker.pipeline = call->pipeline;
|
||||
|
||||
/* Changing pipeline invalidates dynamic state. */
|
||||
@ -447,9 +550,9 @@ void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call)
|
||||
{
|
||||
VkDescriptorSet set;
|
||||
|
||||
if (memcmp(call->mvp, &vk->tracker.mvp, sizeof(*call->mvp)) ||
|
||||
call->texture->view != vk->tracker.view ||
|
||||
call->sampler != vk->tracker.sampler)
|
||||
if (memcmp(call->mvp, &vk->tracker.mvp, sizeof(*call->mvp))
|
||||
|| (call->texture->view != vk->tracker.view)
|
||||
|| (call->sampler != vk->tracker.sampler))
|
||||
{
|
||||
/* Upload UBO */
|
||||
struct vk_buffer_range range;
|
||||
@ -458,7 +561,8 @@ void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call)
|
||||
return;
|
||||
memcpy(range.data, call->mvp, sizeof(*call->mvp));
|
||||
|
||||
set = vulkan_descriptor_manager_alloc(vk->context->device, &vk->chain->descriptor_manager);
|
||||
set = vulkan_descriptor_manager_alloc(
|
||||
vk->context->device, &vk->chain->descriptor_manager);
|
||||
vulkan_write_quad_descriptors(vk->context->device,
|
||||
set,
|
||||
range.buffer,
|
||||
@ -491,11 +595,12 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
|
||||
if (quad->pipeline != vk->tracker.pipeline)
|
||||
{
|
||||
vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, quad->pipeline);
|
||||
vkCmdBindPipeline(vk->cmd,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, quad->pipeline);
|
||||
vk->tracker.pipeline = quad->pipeline;
|
||||
|
||||
/* Changing pipeline invalidates dynamic state. */
|
||||
vk->tracker.dirty |= VULKAN_DIRTY_DYNAMIC_BIT;
|
||||
vk->tracker.dirty |= VULKAN_DIRTY_DYNAMIC_BIT;
|
||||
}
|
||||
|
||||
vulkan_check_dynamic_state(vk);
|
||||
@ -508,9 +613,9 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
sizeof(*quad->mvp), &range))
|
||||
return;
|
||||
|
||||
if (memcmp(quad->mvp, &vk->tracker.mvp, sizeof(*quad->mvp)) ||
|
||||
quad->texture->view != vk->tracker.view ||
|
||||
quad->sampler != vk->tracker.sampler)
|
||||
if (memcmp(quad->mvp, &vk->tracker.mvp, sizeof(*quad->mvp))
|
||||
|| quad->texture->view != vk->tracker.view
|
||||
|| quad->sampler != vk->tracker.sampler)
|
||||
{
|
||||
/* Upload UBO */
|
||||
struct vk_buffer_range range;
|
||||
@ -519,7 +624,9 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
return;
|
||||
memcpy(range.data, quad->mvp, sizeof(*quad->mvp));
|
||||
|
||||
set = vulkan_descriptor_manager_alloc(vk->context->device, &vk->chain->descriptor_manager);
|
||||
set = vulkan_descriptor_manager_alloc(vk->context->device,
|
||||
&vk->chain->descriptor_manager);
|
||||
|
||||
vulkan_write_quad_descriptors(vk->context->device,
|
||||
set,
|
||||
range.buffer,
|
||||
@ -532,9 +639,9 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
vk->pipelines.layout, 0,
|
||||
1, &set, 0, NULL);
|
||||
|
||||
vk->tracker.view = quad->texture->view;
|
||||
vk->tracker.view = quad->texture->view;
|
||||
vk->tracker.sampler = quad->sampler;
|
||||
vk->tracker.mvp = *quad->mvp;
|
||||
vk->tracker.mvp = *quad->mvp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,20 +665,25 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad)
|
||||
vkCmdDraw(vk->cmd, 6, 1, 0, 0);
|
||||
}
|
||||
|
||||
void vulkan_image_layout_transition(vk_t *vk, VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
||||
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages)
|
||||
void vulkan_image_layout_transition(
|
||||
vk_t *vk,
|
||||
VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout,
|
||||
VkImageLayout new_layout,
|
||||
VkAccessFlags srcAccess,
|
||||
VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags srcStages,
|
||||
VkPipelineStageFlags dstStages)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
|
||||
barrier.srcAccessMask = srcAccess;
|
||||
barrier.dstAccessMask = dstAccess;
|
||||
barrier.oldLayout = old_layout;
|
||||
barrier.newLayout = new_layout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.srcAccessMask = srcAccess;
|
||||
barrier.dstAccessMask = dstAccess;
|
||||
barrier.oldLayout = old_layout;
|
||||
barrier.newLayout = new_layout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
@ -591,25 +703,28 @@ struct vk_buffer vulkan_create_buffer(const struct vulkan_context *context,
|
||||
struct vk_buffer buffer;
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
|
||||
info.size = size;
|
||||
info.usage = usage;
|
||||
info.size = size;
|
||||
info.usage = usage;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
vkCreateBuffer(context->device, &info, NULL, &buffer.buffer);
|
||||
|
||||
vkGetBufferMemoryRequirements(context->device, buffer.buffer, &mem_reqs);
|
||||
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type(&context->memory_properties,
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type(
|
||||
&context->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
vkAllocateMemory(context->device, &alloc, NULL, &buffer.memory);
|
||||
vkBindBufferMemory(context->device, buffer.buffer, buffer.memory, 0);
|
||||
|
||||
buffer.size = alloc.allocationSize;
|
||||
|
||||
vkMapMemory(context->device, buffer.memory, 0, buffer.size, 0, &buffer.mapped);
|
||||
vkMapMemory(context->device,
|
||||
buffer.memory, 0, buffer.size, 0, &buffer.mapped);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -621,14 +736,18 @@ void vulkan_destroy_buffer(VkDevice device, struct vk_buffer *buffer)
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
}
|
||||
|
||||
static struct vk_descriptor_pool *vulkan_alloc_descriptor_pool(VkDevice device,
|
||||
static struct vk_descriptor_pool *vulkan_alloc_descriptor_pool(
|
||||
VkDevice device,
|
||||
const struct vk_descriptor_manager *manager)
|
||||
{
|
||||
unsigned i;
|
||||
VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
VkDescriptorSetAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
VkDescriptorSetAllocateInfo alloc_info = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||
|
||||
struct vk_descriptor_pool *pool = (struct vk_descriptor_pool*)calloc(1, sizeof(*pool));
|
||||
struct vk_descriptor_pool *pool =
|
||||
(struct vk_descriptor_pool*)calloc(1, sizeof(*pool));
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
@ -648,7 +767,8 @@ static struct vk_descriptor_pool *vulkan_alloc_descriptor_pool(VkDevice device,
|
||||
return pool;
|
||||
}
|
||||
|
||||
VkDescriptorSet vulkan_descriptor_manager_alloc(VkDevice device, struct vk_descriptor_manager *manager)
|
||||
VkDescriptorSet vulkan_descriptor_manager_alloc(
|
||||
VkDevice device, struct vk_descriptor_manager *manager)
|
||||
{
|
||||
if (manager->count < VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS)
|
||||
return manager->current->sets[manager->count++];
|
||||
@ -656,7 +776,7 @@ VkDescriptorSet vulkan_descriptor_manager_alloc(VkDevice device, struct vk_descr
|
||||
while (manager->current->next)
|
||||
{
|
||||
manager->current = manager->current->next;
|
||||
manager->count = 0;
|
||||
manager->count = 0;
|
||||
return manager->current->sets[manager->count++];
|
||||
}
|
||||
|
||||
@ -664,7 +784,7 @@ VkDescriptorSet vulkan_descriptor_manager_alloc(VkDevice device, struct vk_descr
|
||||
retro_assert(manager->current->next);
|
||||
|
||||
manager->current = manager->current->next;
|
||||
manager->count = 0;
|
||||
manager->count = 0;
|
||||
return manager->current->sets[manager->count++];
|
||||
}
|
||||
|
||||
@ -674,22 +794,26 @@ void vulkan_descriptor_manager_restart(struct vk_descriptor_manager *manager)
|
||||
manager->count = 0;
|
||||
}
|
||||
|
||||
struct vk_descriptor_manager vulkan_create_descriptor_manager(VkDevice device,
|
||||
const VkDescriptorPoolSize *sizes, unsigned num_sizes, VkDescriptorSetLayout set_layout)
|
||||
struct vk_descriptor_manager vulkan_create_descriptor_manager(
|
||||
VkDevice device,
|
||||
const VkDescriptorPoolSize *sizes,
|
||||
unsigned num_sizes,
|
||||
VkDescriptorSetLayout set_layout)
|
||||
{
|
||||
struct vk_descriptor_manager manager;
|
||||
memset(&manager, 0, sizeof(manager));
|
||||
retro_assert(num_sizes <= VULKAN_MAX_DESCRIPTOR_POOL_SIZES);
|
||||
memcpy(manager.sizes, sizes, num_sizes * sizeof(*sizes));
|
||||
manager.num_sizes = num_sizes;
|
||||
manager.num_sizes = num_sizes;
|
||||
manager.set_layout = set_layout;
|
||||
|
||||
manager.head = vulkan_alloc_descriptor_pool(device, &manager);
|
||||
manager.head = vulkan_alloc_descriptor_pool(device, &manager);
|
||||
retro_assert(manager.head);
|
||||
return manager;
|
||||
}
|
||||
|
||||
void vulkan_destroy_descriptor_manager(VkDevice device, struct vk_descriptor_manager *manager)
|
||||
void vulkan_destroy_descriptor_manager(VkDevice device,
|
||||
struct vk_descriptor_manager *manager)
|
||||
{
|
||||
struct vk_descriptor_pool *node = manager->head;
|
||||
|
||||
@ -697,7 +821,8 @@ void vulkan_destroy_descriptor_manager(VkDevice device, struct vk_descriptor_man
|
||||
{
|
||||
struct vk_descriptor_pool *next = node->next;
|
||||
|
||||
vkFreeDescriptorSets(device, node->pool, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS, node->sets);
|
||||
vkFreeDescriptorSets(device, node->pool,
|
||||
VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS, node->sets);
|
||||
vkDestroyDescriptorPool(device, node->pool, NULL);
|
||||
|
||||
free(node);
|
||||
@ -713,26 +838,30 @@ static void vulkan_buffer_chain_step(struct vk_buffer_chain *chain)
|
||||
chain->offset = 0;
|
||||
}
|
||||
|
||||
static bool vulkan_buffer_chain_suballoc(struct vk_buffer_chain *chain, size_t size, struct vk_buffer_range *range)
|
||||
static bool vulkan_buffer_chain_suballoc(struct vk_buffer_chain *chain,
|
||||
size_t size, struct vk_buffer_range *range)
|
||||
{
|
||||
VkDeviceSize next_offset = chain->offset + size;
|
||||
if (next_offset <= chain->current->buffer.size)
|
||||
{
|
||||
range->data = (uint8_t*)chain->current->buffer.mapped + chain->offset;
|
||||
range->data = (uint8_t*)chain->current->buffer.mapped + chain->offset;
|
||||
range->buffer = chain->current->buffer.buffer;
|
||||
range->offset = chain->offset;
|
||||
chain->offset = (next_offset + chain->alignment - 1) & ~(chain->alignment - 1);
|
||||
chain->offset = (next_offset + chain->alignment - 1)
|
||||
& ~(chain->alignment - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct vk_buffer_node *vulkan_buffer_chain_alloc_node(
|
||||
const struct vulkan_context *context,
|
||||
size_t size, VkBufferUsageFlags usage)
|
||||
{
|
||||
struct vk_buffer_node *node = (struct vk_buffer_node*)calloc(1, sizeof(*node));
|
||||
struct vk_buffer_node *node = (struct vk_buffer_node*)
|
||||
calloc(1, sizeof(*node));
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
@ -744,7 +873,8 @@ struct vk_buffer_chain vulkan_buffer_chain_init(VkDeviceSize block_size,
|
||||
VkDeviceSize alignment,
|
||||
VkBufferUsageFlags usage)
|
||||
{
|
||||
struct vk_buffer_chain chain = { block_size, alignment, 0, usage, NULL, NULL };
|
||||
struct vk_buffer_chain chain = {
|
||||
block_size, alignment, 0, usage, NULL, NULL };
|
||||
return chain;
|
||||
}
|
||||
|
||||
@ -755,7 +885,8 @@ void vulkan_buffer_chain_discard(struct vk_buffer_chain *chain)
|
||||
}
|
||||
|
||||
bool vulkan_buffer_chain_alloc(const struct vulkan_context *context,
|
||||
struct vk_buffer_chain *chain, size_t size, struct vk_buffer_range *range)
|
||||
struct vk_buffer_chain *chain,
|
||||
size_t size, struct vk_buffer_range *range)
|
||||
{
|
||||
if (!chain->head)
|
||||
{
|
||||
@ -781,7 +912,8 @@ bool vulkan_buffer_chain_alloc(const struct vulkan_context *context,
|
||||
}
|
||||
|
||||
/* We have to allocate a new node, might allocate larger
|
||||
* buffer here than block_size in case we have a very large allocation. */
|
||||
* buffer here than block_size in case we have
|
||||
* a very large allocation. */
|
||||
if (size < chain->block_size)
|
||||
size = chain->block_size;
|
||||
|
||||
@ -1224,7 +1356,7 @@ void vulkan_acquire_next_image(gfx_ctx_vulkan_data_t *vk)
|
||||
VkFence *next_fence;
|
||||
VkSemaphoreCreateInfo sem_info =
|
||||
{ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
|
||||
VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
|
||||
VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
|
||||
|
||||
vkCreateFence(vk->context.device, &info, NULL, &fence);
|
||||
|
||||
@ -1287,7 +1419,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
|
||||
if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
format = formats[0];
|
||||
format = formats[0];
|
||||
format.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
else
|
||||
@ -1314,6 +1446,8 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
/* Limit latency. */
|
||||
if (desired_swapchain_images > 3)
|
||||
desired_swapchain_images = 3;
|
||||
if (desired_swapchain_images < surface_properties.minImageCount)
|
||||
desired_swapchain_images = surface_properties.minImageCount;
|
||||
|
||||
if ((surface_properties.maxImageCount > 0)
|
||||
&& (desired_swapchain_images > surface_properties.maxImageCount))
|
||||
|
@ -52,11 +52,39 @@
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <gfx/math/matrix_4x4.h>
|
||||
#include <formats/image.h>
|
||||
#ifndef VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL
|
||||
#define VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL 1024
|
||||
#endif
|
||||
|
||||
typedef struct VkDmaBufImageCreateInfo_
|
||||
{
|
||||
VkStructureType sType; /* Must be VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL */
|
||||
const void* pNext; /* Pointer to next structure. */
|
||||
int fd;
|
||||
VkFormat format;
|
||||
VkExtent3D extent; /* Depth must be 1 */
|
||||
uint32_t strideInBytes;
|
||||
} VkDmaBufImageCreateInfo;
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateDmaBufImageINTEL)(VkDevice device,
|
||||
const VkDmaBufImageCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMem, VkImage* pImage);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDmaBufImageINTEL(
|
||||
VkDevice _device,
|
||||
const VkDmaBufImageCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDeviceMemory* pMem,
|
||||
VkImage* pImage);
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_inline.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include "boolean.h"
|
||||
#include <gfx/math/matrix_4x4.h>
|
||||
#include <gfx/scaler/scaler.h>
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <formats/image.h>
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../../performance.h"
|
||||
#include "../../libretro.h"
|
||||
@ -66,13 +94,25 @@
|
||||
#include "../video_context_driver.h"
|
||||
#include "libretro_vulkan.h"
|
||||
#include "../drivers_shader/shader_vulkan.h"
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <gfx/scaler/scaler.h>
|
||||
|
||||
enum vk_texture_type
|
||||
{
|
||||
/* We will use the texture as a sampled linear texture. */
|
||||
VULKAN_TEXTURE_STREAMED = 0,
|
||||
|
||||
/* We will use the texture as a linear texture, but only
|
||||
* for copying to a DYNAMIC texture. */
|
||||
VULKAN_TEXTURE_STAGING,
|
||||
|
||||
/* We will use the texture as an optimally tiled texture,
|
||||
* and we will update the texture by copying from STAGING
|
||||
* textures. */
|
||||
VULKAN_TEXTURE_DYNAMIC,
|
||||
|
||||
/* We will upload content once. */
|
||||
VULKAN_TEXTURE_STATIC,
|
||||
|
||||
/* We will use the texture for reading back transfers from GPU. */
|
||||
VULKAN_TEXTURE_READBACK
|
||||
};
|
||||
|
||||
@ -118,10 +158,14 @@ typedef struct gfx_ctx_vulkan_data
|
||||
{
|
||||
vulkan_context_t context;
|
||||
|
||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR
|
||||
fpGetPhysicalDeviceSurfaceSupportKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
|
||||
fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
|
||||
fpGetPhysicalDeviceSurfaceFormatsKHR;
|
||||
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
|
||||
fpGetPhysicalDeviceSurfacePresentModesKHR;
|
||||
PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
|
||||
PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
|
||||
PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
|
||||
@ -188,6 +232,7 @@ struct vk_texture
|
||||
uint32_t memory_type;
|
||||
|
||||
VkImageLayout layout;
|
||||
enum vk_texture_type type;
|
||||
bool default_smooth;
|
||||
};
|
||||
|
||||
@ -259,6 +304,7 @@ struct vk_per_frame
|
||||
{
|
||||
struct vk_image backbuffer;
|
||||
struct vk_texture texture;
|
||||
struct vk_texture texture_optimal;
|
||||
struct vk_buffer_chain vbo;
|
||||
struct vk_buffer_chain ubo;
|
||||
struct vk_descriptor_manager descriptor_manager;
|
||||
@ -336,6 +382,7 @@ typedef struct vk
|
||||
struct
|
||||
{
|
||||
VkPipeline alpha_blend;
|
||||
VkPipeline font;
|
||||
VkDescriptorSetLayout set_layout;
|
||||
VkPipelineLayout layout;
|
||||
VkPipelineCache cache;
|
||||
@ -351,6 +398,9 @@ typedef struct vk
|
||||
struct
|
||||
{
|
||||
struct vk_texture textures[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
||||
struct vk_texture textures_optimal[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
||||
bool dirty[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
||||
|
||||
float alpha;
|
||||
unsigned last_index;
|
||||
bool enable;
|
||||
@ -420,6 +470,10 @@ void vulkan_transition_texture(vk_t *vk, struct vk_texture *texture);
|
||||
void vulkan_map_persistent_texture(VkDevice device, struct vk_texture *tex);
|
||||
void vulkan_destroy_texture(VkDevice device, struct vk_texture *tex);
|
||||
|
||||
void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd,
|
||||
struct vk_texture *dynamic,
|
||||
struct vk_texture *staging);
|
||||
|
||||
/* VBO will be written to here. */
|
||||
void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad);
|
||||
|
||||
@ -428,7 +482,8 @@ void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad);
|
||||
*/
|
||||
void vulkan_draw_triangles(vk_t *vk, const struct vk_draw_triangles *call);
|
||||
|
||||
void vulkan_image_layout_transition(vk_t *vk, VkCommandBuffer cmd, VkImage image,
|
||||
void vulkan_image_layout_transition(vk_t *vk,
|
||||
VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
||||
VkAccessFlags srcAccess, VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags srcStages, VkPipelineStageFlags dstStages);
|
||||
@ -470,8 +525,8 @@ static INLINE void vulkan_write_quad_vbo(struct vk_vertex *pv,
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
pv[i].x = x + strip[2 * i + 0] * width;
|
||||
pv[i].y = y + strip[2 * i + 1] * height;
|
||||
pv[i].x = x + strip[2 * i + 0] * width;
|
||||
pv[i].y = y + strip[2 * i + 1] * height;
|
||||
pv[i].tex_x = tex_x + strip[2 * i + 0] * tex_width;
|
||||
pv[i].tex_y = tex_y + strip[2 * i + 1] * tex_height;
|
||||
pv[i].color = *color;
|
||||
|
@ -2804,11 +2804,12 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
}
|
||||
|
||||
{
|
||||
unsigned minimum;
|
||||
video_shader_ctx_texture_t texture_info;
|
||||
|
||||
video_shader_driver_ctl(SHADER_CTL_GET_PREV_TEXTURES, &texture_info);
|
||||
|
||||
unsigned minimum = texture_info.id;
|
||||
minimum = texture_info.id;
|
||||
gl->textures = max(minimum + 1, gl->textures);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "../common/vulkan_common.h"
|
||||
#include "vulkan_shaders/alpha_blend.vert.inc"
|
||||
#include "vulkan_shaders/alpha_blend.frag.inc"
|
||||
#include "vulkan_shaders/font.frag.inc"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@ -301,7 +302,6 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
pipe.renderPass = vk->render_pass;
|
||||
pipe.layout = vk->pipelines.layout;
|
||||
|
||||
/* Alpha-blended pipeline. */
|
||||
module_info.codeSize = alpha_blend_vert_spv_len;
|
||||
module_info.pCode = (const uint32_t*)alpha_blend_vert_spv;
|
||||
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
@ -309,13 +309,6 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[0].module);
|
||||
|
||||
module_info.codeSize = alpha_blend_frag_spv_len;
|
||||
module_info.pCode = (const uint32_t*)alpha_blend_frag_spv;
|
||||
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shader_stages[1].pName = "main";
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
blend_attachment.blendEnable = true;
|
||||
blend_attachment.colorWriteMask = 0xf;
|
||||
blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
@ -323,7 +316,27 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
|
||||
/* Glyph pipeline */
|
||||
module_info.codeSize = font_frag_spv_len;
|
||||
module_info.pCode = (const uint32_t*)font_frag_spv;
|
||||
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shader_stages[1].pName = "main";
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->pipelines.font);
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL);
|
||||
|
||||
/* Alpha-blended pipeline. */
|
||||
module_info.codeSize = alpha_blend_frag_spv_len;
|
||||
module_info.pCode = (const uint32_t*)alpha_blend_frag_spv;
|
||||
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shader_stages[1].pName = "main";
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->pipelines.alpha_blend);
|
||||
@ -461,6 +474,13 @@ static void vulkan_init_textures(vk_t *vk)
|
||||
NULL, NULL, VULKAN_TEXTURE_STREAMED);
|
||||
vulkan_map_persistent_texture(vk->context->device,
|
||||
&vk->swapchain[i].texture);
|
||||
|
||||
if (vk->swapchain[i].texture.type == VULKAN_TEXTURE_STAGING)
|
||||
{
|
||||
vk->swapchain[i].texture_optimal = vulkan_create_texture(vk, NULL,
|
||||
vk->tex_w, vk->tex_h, vk->tex_fmt,
|
||||
NULL, NULL, VULKAN_TEXTURE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -471,9 +491,12 @@ static void vulkan_deinit_textures(vk_t *vk)
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < vk->num_swapchain_images; i++)
|
||||
{
|
||||
if (vk->swapchain[i].texture.memory != VK_NULL_HANDLE)
|
||||
vulkan_destroy_texture(vk->context->device,
|
||||
&vk->swapchain[i].texture);
|
||||
vulkan_destroy_texture(vk->context->device, &vk->swapchain[i].texture);
|
||||
if (vk->swapchain[i].texture_optimal.memory != VK_NULL_HANDLE)
|
||||
vulkan_destroy_texture(vk->context->device, &vk->swapchain[i].texture_optimal);
|
||||
}
|
||||
}
|
||||
|
||||
static void vulkan_deinit_command_buffers(vk_t *vk)
|
||||
@ -503,6 +526,7 @@ static void vulkan_deinit_pipelines(vk_t *vk)
|
||||
unsigned i;
|
||||
vulkan_deinit_pipeline_layout(vk);
|
||||
vkDestroyPipeline(vk->context->device, vk->pipelines.alpha_blend, NULL);
|
||||
vkDestroyPipeline(vk->context->device, vk->pipelines.font, NULL);
|
||||
for (i = 0; i < 4; i++)
|
||||
vkDestroyPipeline(vk->context->device, vk->display.pipelines[i], NULL);
|
||||
}
|
||||
@ -671,9 +695,12 @@ static void vulkan_deinit_menu(vk_t *vk)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++)
|
||||
{
|
||||
if (vk->menu.textures[i].memory)
|
||||
vulkan_destroy_texture(vk->context->device,
|
||||
&vk->menu.textures[i]);
|
||||
vulkan_destroy_texture(vk->context->device, &vk->menu.textures[i]);
|
||||
if (vk->menu.textures_optimal[i].memory)
|
||||
vulkan_destroy_texture(vk->context->device, &vk->menu.textures_optimal[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void vulkan_free(void *data)
|
||||
@ -1323,6 +1350,13 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
vulkan_buffer_chain_discard(&chain->vbo);
|
||||
vulkan_buffer_chain_discard(&chain->ubo);
|
||||
|
||||
/* Start recording the command buffer. */
|
||||
vk->cmd = chain->cmd;
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkResetCommandBuffer(vk->cmd, 0);
|
||||
vkBeginCommandBuffer(vk->cmd, &begin_info);
|
||||
memset(&vk->tracker, 0, sizeof(vk->tracker));
|
||||
|
||||
/* Upload texture */
|
||||
retro_perf_start(©_frame);
|
||||
if (frame && !vk->hw.enable)
|
||||
@ -1336,9 +1370,16 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
|| chain->texture.height != frame_height)
|
||||
{
|
||||
chain->texture = vulkan_create_texture(vk, &chain->texture,
|
||||
frame_width, frame_height, chain->texture.format,
|
||||
NULL, NULL, VULKAN_TEXTURE_STREAMED);
|
||||
frame_width, frame_height, chain->texture.format, NULL, NULL,
|
||||
chain->texture_optimal.memory ? VULKAN_TEXTURE_STAGING : VULKAN_TEXTURE_STREAMED);
|
||||
vulkan_map_persistent_texture(vk->context->device, &chain->texture);
|
||||
|
||||
if (chain->texture.type == VULKAN_TEXTURE_STAGING)
|
||||
{
|
||||
chain->texture_optimal = vulkan_create_texture(vk, &chain->texture_optimal,
|
||||
frame_width, frame_height, chain->texture_optimal.format,
|
||||
NULL, NULL, VULKAN_TEXTURE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
if (frame != chain->texture.mapped)
|
||||
@ -1352,17 +1393,17 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
memcpy(dst, src, frame_width * bpp);
|
||||
}
|
||||
|
||||
/* If we have an optimal texture, copy to that now. */
|
||||
if (chain->texture_optimal.memory != VK_NULL_HANDLE)
|
||||
{
|
||||
vulkan_copy_staging_to_dynamic(vk, vk->cmd,
|
||||
&chain->texture_optimal, &chain->texture);
|
||||
}
|
||||
|
||||
vk->last_valid_index = frame_index;
|
||||
}
|
||||
retro_perf_stop(©_frame);
|
||||
|
||||
/* Start recording the command buffer. */
|
||||
vk->cmd = chain->cmd;
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkResetCommandBuffer(vk->cmd, 0);
|
||||
vkBeginCommandBuffer(vk->cmd, &begin_info);
|
||||
memset(&vk->tracker, 0, sizeof(vk->tracker));
|
||||
|
||||
/* Notify filter chain about the new sync index. */
|
||||
vulkan_filter_chain_notify_sync_index(vk->filter_chain, frame_index);
|
||||
|
||||
@ -1399,9 +1440,11 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
}
|
||||
else
|
||||
{
|
||||
struct vk_texture *tex = &
|
||||
vk->swapchain[vk->last_valid_index].texture;
|
||||
vulkan_transition_texture(vk, tex);
|
||||
struct vk_texture *tex = &vk->swapchain[vk->last_valid_index].texture;
|
||||
if (vk->swapchain[vk->last_valid_index].texture_optimal.memory != VK_NULL_HANDLE)
|
||||
tex = &vk->swapchain[vk->last_valid_index].texture_optimal;
|
||||
else
|
||||
vulkan_transition_texture(vk, tex);
|
||||
|
||||
input.view = tex->view;
|
||||
input.layout = tex->layout;
|
||||
@ -1450,16 +1493,30 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
if (vk->menu.textures[vk->menu.last_index].image != VK_NULL_HANDLE)
|
||||
{
|
||||
struct vk_draw_quad quad;
|
||||
struct vk_texture *optimal = &vk->menu.textures_optimal[vk->menu.last_index];
|
||||
vulkan_set_viewport(vk, width, height, vk->menu.full_screen, false);
|
||||
|
||||
quad.pipeline = vk->pipelines.alpha_blend;
|
||||
quad.texture = &vk->menu.textures[vk->menu.last_index];
|
||||
quad.sampler = vk->samplers.linear;
|
||||
quad.mvp = &vk->mvp_no_rot;
|
||||
quad.color.r = 1.0f;
|
||||
quad.color.g = 1.0f;
|
||||
quad.color.b = 1.0f;
|
||||
quad.color.a = vk->menu.alpha;
|
||||
quad.texture = &vk->menu.textures[vk->menu.last_index];
|
||||
|
||||
if (optimal->memory != VK_NULL_HANDLE)
|
||||
{
|
||||
if (vk->menu.dirty[vk->menu.last_index])
|
||||
{
|
||||
vulkan_copy_staging_to_dynamic(vk, vk->cmd,
|
||||
optimal,
|
||||
quad.texture);
|
||||
vk->menu.dirty[vk->menu.last_index] = false;
|
||||
}
|
||||
quad.texture = optimal;
|
||||
}
|
||||
|
||||
quad.sampler = vk->samplers.linear;
|
||||
quad.mvp = &vk->mvp_no_rot;
|
||||
quad.color.r = 1.0f;
|
||||
quad.color.g = 1.0f;
|
||||
quad.color.b = 1.0f;
|
||||
quad.color.a = vk->menu.alpha;
|
||||
vulkan_draw_quad(vk, &quad);
|
||||
}
|
||||
}
|
||||
@ -1657,6 +1714,13 @@ static bool vulkan_get_current_sw_framebuffer(void *data,
|
||||
framebuffer->width, framebuffer->height, chain->texture.format,
|
||||
NULL, NULL, VULKAN_TEXTURE_STREAMED);
|
||||
vulkan_map_persistent_texture(vk->context->device, &chain->texture);
|
||||
|
||||
if (chain->texture.type == VULKAN_TEXTURE_STAGING)
|
||||
{
|
||||
chain->texture_optimal = vulkan_create_texture(vk, &chain->texture_optimal,
|
||||
framebuffer->width, framebuffer->height, chain->texture_optimal.format,
|
||||
NULL, NULL, VULKAN_TEXTURE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
framebuffer->data = chain->texture.mapped;
|
||||
@ -1690,9 +1754,10 @@ static void vulkan_set_texture_frame(void *data,
|
||||
{
|
||||
uint8_t *ptr;
|
||||
unsigned x, y;
|
||||
vk_t *vk = (vk_t*)data;
|
||||
unsigned index = vk->context->current_swapchain_index;
|
||||
struct vk_texture *texture = &vk->menu.textures[index];
|
||||
vk_t *vk = (vk_t*)data;
|
||||
unsigned index = vk->context->current_swapchain_index;
|
||||
struct vk_texture *texture = &vk->menu.textures[index];
|
||||
struct vk_texture *texture_optimal = &vk->menu.textures_optimal[index];
|
||||
const VkComponentMapping br_swizzle = {
|
||||
VK_COMPONENT_SWIZZLE_B,
|
||||
VK_COMPONENT_SWIZZLE_G,
|
||||
@ -1709,7 +1774,8 @@ static void vulkan_set_texture_frame(void *data,
|
||||
texture->memory ? texture : NULL,
|
||||
width, height,
|
||||
rgb32 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_B4G4R4A4_UNORM_PACK16,
|
||||
NULL, rgb32 ? NULL : &br_swizzle, VULKAN_TEXTURE_STREAMED);
|
||||
NULL, rgb32 ? NULL : &br_swizzle,
|
||||
texture_optimal->memory ? VULKAN_TEXTURE_STAGING : VULKAN_TEXTURE_STREAMED);
|
||||
|
||||
vkMapMemory(vk->context->device, texture->memory,
|
||||
texture->offset, texture->size, 0, (void**)&ptr);
|
||||
@ -1723,6 +1789,18 @@ static void vulkan_set_texture_frame(void *data,
|
||||
vkUnmapMemory(vk->context->device, texture->memory);
|
||||
vk->menu.alpha = alpha;
|
||||
vk->menu.last_index = index;
|
||||
|
||||
if (texture->type == VULKAN_TEXTURE_STAGING)
|
||||
{
|
||||
*texture_optimal = vulkan_create_texture(vk,
|
||||
texture_optimal->memory ? texture_optimal : NULL,
|
||||
width, height,
|
||||
rgb32 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_B4G4R4A4_UNORM_PACK16,
|
||||
NULL, rgb32 ? NULL : &br_swizzle,
|
||||
VULKAN_TEXTURE_DYNAMIC);
|
||||
}
|
||||
|
||||
vk->menu.dirty[index] = true;
|
||||
}
|
||||
|
||||
static void vulkan_set_texture_enable(void *data, bool state, bool full_screen)
|
||||
|
12
gfx/drivers/vulkan_shaders/font.frag
Normal file
12
gfx/drivers/vulkan_shaders/font.frag
Normal file
@ -0,0 +1,12 @@
|
||||
#version 310 es
|
||||
precision highp float;
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 1) in vec4 vColor;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 1) uniform highp sampler2D uTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Workaround for early drivers which fail to apply swizzle in VkImageView.
|
||||
FragColor = vec4(vColor.rgb, vColor.a * texture(uTex, vTexCoord).x);
|
||||
}
|
80
gfx/drivers/vulkan_shaders/font.frag.inc
Normal file
80
gfx/drivers/vulkan_shaders/font.frag.inc
Normal file
@ -0,0 +1,80 @@
|
||||
unsigned char font_frag_spv[] = {
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
|
||||
0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
|
||||
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||
0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x76, 0x43, 0x6f, 0x6c,
|
||||
0x6f, 0x72, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0x75, 0x54, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
|
||||
0x1b, 0x00, 0x00, 0x00, 0x76, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72,
|
||||
0x64, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||
0x1b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2b, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
|
||||
0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||
0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||
0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x3b, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||
0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x3d, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x1f, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x22, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
|
||||
};
|
||||
unsigned int font_frag_spv_len = 920;
|
@ -315,8 +315,6 @@ static bool gfx_ctx_qnx_bind_api(void *data,
|
||||
(void)major;
|
||||
(void)minor;
|
||||
|
||||
g_egl_api = api;
|
||||
|
||||
return api == GFX_CTX_OPENGL_ES_API;
|
||||
}
|
||||
|
||||
|
@ -35,21 +35,35 @@
|
||||
#include <file/dir_list.h>
|
||||
#include <retro_file.h>
|
||||
|
||||
|
||||
#include "../../verbosity.h"
|
||||
#include "../../driver.h"
|
||||
#include "../../runloop.h"
|
||||
#include "../common/drm_common.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include "../common/egl_common.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
|
||||
#include "../common/gl_common.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENGLES
|
||||
|
||||
#ifndef EGL_OPENGL_ES3_BIT_KHR
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x0040
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static volatile sig_atomic_t drm_quit = 0;
|
||||
|
||||
static enum gfx_ctx_api drm_api;
|
||||
|
||||
static struct gbm_bo *g_bo;
|
||||
static struct gbm_bo *g_next_bo;
|
||||
static struct gbm_surface *g_gbm_surface;
|
||||
@ -57,13 +71,16 @@ static struct gbm_device *g_gbm_dev;
|
||||
|
||||
static bool waiting_for_flip;
|
||||
|
||||
typedef struct gfx_ctx_drm_egl_data
|
||||
typedef struct gfx_ctx_drm_data
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
egl_ctx_data_t egl;
|
||||
RFILE *g_drm;
|
||||
unsigned g_fb_width;
|
||||
unsigned g_fb_height;
|
||||
} gfx_ctx_drm_egl_data_t;
|
||||
#endif
|
||||
RFILE *drm;
|
||||
unsigned interval;
|
||||
unsigned fb_width;
|
||||
unsigned fb_height;
|
||||
} gfx_ctx_drm_data_t;
|
||||
|
||||
struct drm_fb
|
||||
{
|
||||
@ -71,6 +88,24 @@ struct drm_fb
|
||||
uint32_t fb_id;
|
||||
};
|
||||
|
||||
static void drm_sighandler(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
drm_quit = 1;
|
||||
}
|
||||
|
||||
static void drm_install_sighandler(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_sigaction = NULL;
|
||||
sa.sa_handler = drm_sighandler;
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
}
|
||||
|
||||
static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
|
||||
{
|
||||
struct drm_fb *fb = (struct drm_fb*)data;
|
||||
@ -97,7 +132,7 @@ static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo)
|
||||
stride = gbm_bo_get_stride(bo);
|
||||
handle = gbm_bo_get_handle(bo).u32;
|
||||
|
||||
RARCH_LOG("[KMS/EGL]: New FB: %ux%u (stride: %u).\n",
|
||||
RARCH_LOG("[KMS]: New FB: %ux%u (stride: %u).\n",
|
||||
width, height, stride);
|
||||
|
||||
ret = drmModeAddFB(g_drm_fd, width, height, 24, 32,
|
||||
@ -109,20 +144,21 @@ static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo)
|
||||
return fb;
|
||||
|
||||
error:
|
||||
RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno));
|
||||
RARCH_ERR("[KMS]: Failed to create FB: %s\n", strerror(errno));
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_swap_interval(void *data, unsigned interval)
|
||||
static void gfx_ctx_drm_swap_interval(void *data, unsigned interval)
|
||||
{
|
||||
gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)data;
|
||||
drm->egl.interval = interval;
|
||||
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
|
||||
drm->interval = interval;
|
||||
|
||||
if (interval > 1)
|
||||
RARCH_WARN("[KMS/EGL]: Swap intervals > 1 currently not supported. Will use swap interval of 1.\n");
|
||||
RARCH_WARN("[KMS]: Swap intervals > 1 currently not supported. Will use swap interval of 1.\n");
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_check_window(void *data, bool *quit,
|
||||
static void gfx_ctx_drm_check_window(void *data, bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
|
||||
{
|
||||
(void)data;
|
||||
@ -131,11 +167,11 @@ static void gfx_ctx_drm_egl_check_window(void *data, bool *quit,
|
||||
(void)height;
|
||||
|
||||
*resize = false;
|
||||
*quit = g_egl_quit;
|
||||
*quit = drm_quit;
|
||||
}
|
||||
|
||||
|
||||
static void drm_egl_flip_handler(int fd, unsigned frame,
|
||||
static void drm_flip_handler(int fd, unsigned frame,
|
||||
unsigned sec, unsigned usec, void *data)
|
||||
{
|
||||
static unsigned first_page_flip;
|
||||
@ -152,7 +188,7 @@ static void drm_egl_flip_handler(int fd, unsigned frame,
|
||||
{
|
||||
unsigned missed = frame - last_page_flip - 1;
|
||||
if (missed)
|
||||
RARCH_LOG("[KMS/EGL]: Missed %u VBlank(s) (Frame: %u, DRM frame: %u).\n",
|
||||
RARCH_LOG("[KMS]: Missed %u VBlank(s) (Frame: %u, DRM frame: %u).\n",
|
||||
missed, frame - first_page_flip, frame);
|
||||
}
|
||||
|
||||
@ -160,7 +196,7 @@ static void drm_egl_flip_handler(int fd, unsigned frame,
|
||||
*(bool*)data = false;
|
||||
}
|
||||
|
||||
static bool wait_flip(bool block)
|
||||
static bool gfx_ctx_drm_wait_flip(bool block)
|
||||
{
|
||||
int timeout = 0;
|
||||
|
||||
@ -189,12 +225,11 @@ static bool wait_flip(bool block)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool queue_flip(void)
|
||||
static bool gfx_ctx_drm_queue_flip(void)
|
||||
{
|
||||
struct drm_fb *fb = NULL;
|
||||
|
||||
g_next_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
|
||||
fb = (struct drm_fb*)drm_fb_get_from_bo(g_next_bo);
|
||||
g_next_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
|
||||
fb = (struct drm_fb*)drm_fb_get_from_bo(g_next_bo);
|
||||
|
||||
if (drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id,
|
||||
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip) == 0)
|
||||
@ -204,31 +239,43 @@ static bool queue_flip(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_swap_buffers(void *data)
|
||||
static void gfx_ctx_drm_swap_buffers(void *data)
|
||||
{
|
||||
gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)data;
|
||||
egl_swap_buffers(data);
|
||||
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
|
||||
|
||||
switch (drm_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
egl_swap_buffers(drm);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* I guess we have to wait for flip to have taken
|
||||
* place before another flip can be queued up.
|
||||
*
|
||||
* If true, we are still waiting for a flip
|
||||
* (nonblocking mode, so just drop the frame). */
|
||||
if (wait_flip(drm->egl.interval))
|
||||
if (gfx_ctx_drm_wait_flip(drm->interval))
|
||||
return;
|
||||
|
||||
waiting_for_flip = queue_flip();
|
||||
waiting_for_flip = gfx_ctx_drm_queue_flip();
|
||||
|
||||
if (gbm_surface_has_free_buffers(g_gbm_surface))
|
||||
return;
|
||||
|
||||
/* We have to wait for this flip to finish.
|
||||
* This shouldn't happen as we have triple buffered page-flips. */
|
||||
RARCH_WARN("[KMS/EGL]: Triple buffering is not working correctly ...\n");
|
||||
wait_flip(true);
|
||||
RARCH_WARN("[KMS]: Triple buffering is not working correctly ...\n");
|
||||
gfx_ctx_drm_wait_flip(true);
|
||||
}
|
||||
|
||||
static bool gfx_ctx_drm_egl_set_resize(void *data,
|
||||
static bool gfx_ctx_drm_set_resize(void *data,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
(void)data;
|
||||
@ -238,10 +285,10 @@ static bool gfx_ctx_drm_egl_set_resize(void *data,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_update_window_title(void *data)
|
||||
static void gfx_ctx_drm_update_window_title(void *data)
|
||||
{
|
||||
char buf[128] = {0};
|
||||
char buf_fps[128] = {0};
|
||||
char buf[128];
|
||||
char buf_fps[128];
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
video_monitor_get_fps(buf, sizeof(buf),
|
||||
@ -250,20 +297,19 @@ static void gfx_ctx_drm_egl_update_window_title(void *data)
|
||||
runloop_msg_queue_push( buf_fps, 1, 1, false);
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_get_video_size(void *data,
|
||||
static void gfx_ctx_drm_get_video_size(void *data,
|
||||
unsigned *width, unsigned *height)
|
||||
{
|
||||
gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)data;
|
||||
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
|
||||
|
||||
if (!drm)
|
||||
return;
|
||||
|
||||
(void)data;
|
||||
*width = drm->g_fb_width;
|
||||
*height = drm->g_fb_height;
|
||||
*width = drm->fb_width;
|
||||
*height = drm->fb_height;
|
||||
}
|
||||
|
||||
static void free_drm_resources(gfx_ctx_drm_egl_data_t *drm)
|
||||
static void free_drm_resources(gfx_ctx_drm_data_t *drm)
|
||||
{
|
||||
if (!drm)
|
||||
return;
|
||||
@ -277,22 +323,34 @@ static void free_drm_resources(gfx_ctx_drm_egl_data_t *drm)
|
||||
drm_free();
|
||||
|
||||
if (g_drm_fd >= 0)
|
||||
retro_fclose(drm->g_drm);
|
||||
retro_fclose(drm->drm);
|
||||
|
||||
g_gbm_surface = NULL;
|
||||
g_gbm_dev = NULL;
|
||||
g_drm_fd = -1;
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_destroy_resources(gfx_ctx_drm_egl_data_t *drm)
|
||||
static void gfx_ctx_drm_destroy_resources(gfx_ctx_drm_data_t *drm)
|
||||
{
|
||||
if (!drm)
|
||||
return;
|
||||
|
||||
/* Make sure we acknowledge all page-flips. */
|
||||
wait_flip(true);
|
||||
gfx_ctx_drm_wait_flip(true);
|
||||
|
||||
egl_destroy(drm);
|
||||
switch (drm_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
egl_destroy(drm);
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Restore original CRTC. */
|
||||
drm_restore_crtc();
|
||||
@ -302,22 +360,22 @@ static void gfx_ctx_drm_egl_destroy_resources(gfx_ctx_drm_egl_data_t *drm)
|
||||
g_crtc_id = 0;
|
||||
g_connector_id = 0;
|
||||
|
||||
drm->g_fb_width = 0;
|
||||
drm->g_fb_height = 0;
|
||||
drm->fb_width = 0;
|
||||
drm->fb_height = 0;
|
||||
|
||||
g_bo = NULL;
|
||||
g_next_bo = NULL;
|
||||
g_bo = NULL;
|
||||
g_next_bo = NULL;
|
||||
}
|
||||
|
||||
static void *gfx_ctx_drm_egl_init(void *video_driver)
|
||||
static void *gfx_ctx_drm_init(void *video_driver)
|
||||
{
|
||||
int fd, i;
|
||||
unsigned monitor_index;
|
||||
unsigned gpu_index = 0;
|
||||
const char *gpu = NULL;
|
||||
struct string_list *gpu_descriptors = NULL;
|
||||
gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)
|
||||
calloc(1, sizeof(gfx_ctx_drm_egl_data_t));
|
||||
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)
|
||||
calloc(1, sizeof(gfx_ctx_drm_data_t));
|
||||
|
||||
if (!drm)
|
||||
return NULL;
|
||||
@ -331,19 +389,19 @@ nextgpu:
|
||||
|
||||
if (!gpu_descriptors || gpu_index == gpu_descriptors->size)
|
||||
{
|
||||
RARCH_ERR("[KMS/EGL]: Couldn't find a suitable DRM device.\n");
|
||||
RARCH_ERR("[KMS]: Couldn't find a suitable DRM device.\n");
|
||||
goto error;
|
||||
}
|
||||
gpu = gpu_descriptors->elems[gpu_index++].data;
|
||||
|
||||
drm->g_drm = retro_fopen(gpu, RFILE_MODE_READ_WRITE, -1);
|
||||
if (!drm->g_drm)
|
||||
drm->drm = retro_fopen(gpu, RFILE_MODE_READ_WRITE, -1);
|
||||
if (!drm->drm)
|
||||
{
|
||||
RARCH_WARN("[KMS/EGL]: Couldn't open DRM device.\n");
|
||||
RARCH_WARN("[KMS]: Couldn't open DRM device.\n");
|
||||
goto nextgpu;
|
||||
}
|
||||
|
||||
fd = retro_get_fd(drm->g_drm);
|
||||
fd = retro_get_fd(drm->drm);
|
||||
|
||||
if (!drm_get_resources(fd))
|
||||
goto nextgpu;
|
||||
@ -358,33 +416,33 @@ nextgpu:
|
||||
|
||||
/* First mode is assumed to be the "optimal"
|
||||
* one for get_video_size() purposes. */
|
||||
drm->g_fb_width = g_drm_connector->modes[0].hdisplay;
|
||||
drm->g_fb_height = g_drm_connector->modes[0].vdisplay;
|
||||
drm->fb_width = g_drm_connector->modes[0].hdisplay;
|
||||
drm->fb_height = g_drm_connector->modes[0].vdisplay;
|
||||
|
||||
g_gbm_dev = gbm_create_device(fd);
|
||||
|
||||
if (!g_gbm_dev)
|
||||
{
|
||||
RARCH_WARN("[KMS/EGL]: Couldn't create GBM device.\n");
|
||||
RARCH_WARN("[KMS]: Couldn't create GBM device.\n");
|
||||
goto nextgpu;
|
||||
}
|
||||
|
||||
dir_list_free(gpu_descriptors);
|
||||
|
||||
/* Setup the flip handler. */
|
||||
g_drm_fds.fd = fd;
|
||||
g_drm_fds.events = POLLIN;
|
||||
g_drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
||||
g_drm_evctx.page_flip_handler = drm_egl_flip_handler;
|
||||
g_drm_fds.fd = fd;
|
||||
g_drm_fds.events = POLLIN;
|
||||
g_drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
||||
g_drm_evctx.page_flip_handler = drm_flip_handler;
|
||||
|
||||
g_drm_fd = fd;
|
||||
g_drm_fd = fd;
|
||||
|
||||
return drm;
|
||||
|
||||
error:
|
||||
dir_list_free(gpu_descriptors);
|
||||
|
||||
gfx_ctx_drm_egl_destroy_resources(drm);
|
||||
gfx_ctx_drm_destroy_resources(drm);
|
||||
|
||||
if (drm)
|
||||
free(drm);
|
||||
@ -392,13 +450,15 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static EGLint *egl_fill_attribs(gfx_ctx_drm_egl_data_t *drm, EGLint *attr)
|
||||
static EGLint *gfx_ctx_drm_egl_fill_attribs(
|
||||
gfx_ctx_drm_data_t *drm, EGLint *attr)
|
||||
{
|
||||
switch (drm->egl.api)
|
||||
switch (drm_api)
|
||||
{
|
||||
#ifdef EGL_KHR_create_context
|
||||
case GFX_CTX_OPENGL_API:
|
||||
{
|
||||
#ifdef HAVE_OPENGL
|
||||
unsigned version = drm->egl.major * 1000 + drm->egl.minor;
|
||||
bool core = version >= 3001;
|
||||
#ifdef GL_DEBUG
|
||||
@ -431,23 +491,26 @@ static EGLint *egl_fill_attribs(gfx_ctx_drm_egl_data_t *drm, EGLint *attr)
|
||||
*attr++ = EGL_CONTEXT_FLAGS_KHR;
|
||||
*attr++ = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
#ifdef HAVE_OPENGLES
|
||||
*attr++ = EGL_CONTEXT_CLIENT_VERSION;
|
||||
*attr++ = drm->egl.major ? (EGLint)drm->egl.major : 2;
|
||||
*attr++ = drm->egl.major
|
||||
? (EGLint)drm->egl.major : 2;
|
||||
#ifdef EGL_KHR_create_context
|
||||
if (drm->egl.minor > 0)
|
||||
{
|
||||
*attr++ = EGL_CONTEXT_MINOR_VERSION_KHR;
|
||||
*attr++ = drm->egl.minor;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -456,6 +519,7 @@ static EGLint *egl_fill_attribs(gfx_ctx_drm_egl_data_t *drm, EGLint *attr)
|
||||
return attr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#define DRM_EGL_ATTRIBS_BASE \
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \
|
||||
EGL_RED_SIZE, 1, \
|
||||
@ -464,10 +528,9 @@ static EGLint *egl_fill_attribs(gfx_ctx_drm_egl_data_t *drm, EGLint *attr)
|
||||
EGL_ALPHA_SIZE, 0, \
|
||||
EGL_DEPTH_SIZE, 0
|
||||
|
||||
static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
unsigned width, unsigned height,
|
||||
bool fullscreen)
|
||||
static bool gfx_ctx_drm_egl_set_video_mode(gfx_ctx_drm_data_t *drm)
|
||||
{
|
||||
const EGLint *attrib_ptr = NULL;
|
||||
static const EGLint egl_attribs_gl[] = {
|
||||
DRM_EGL_ATTRIBS_BASE,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
@ -488,28 +551,24 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VG
|
||||
static const EGLint egl_attribs_vg[] = {
|
||||
DRM_EGL_ATTRIBS_BASE,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
|
||||
EGL_NONE,
|
||||
};
|
||||
EGLint *egl_attribs_ptr = NULL;
|
||||
const EGLint *attrib_ptr;
|
||||
EGLint major, minor, n, egl_attribs[16], *attr;
|
||||
float refresh_mod;
|
||||
int i, ret = 0;
|
||||
struct drm_fb *fb = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)data;
|
||||
#endif
|
||||
EGLint major;
|
||||
EGLint minor;
|
||||
EGLint n;
|
||||
EGLint egl_attribs[16];
|
||||
EGLint *egl_attribs_ptr = NULL;
|
||||
EGLint *attr = NULL;
|
||||
|
||||
if (!drm)
|
||||
return false;
|
||||
|
||||
egl_install_sighandlers();
|
||||
|
||||
switch (g_egl_api)
|
||||
switch (drm_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
#ifdef HAVE_OPENGL
|
||||
attrib_ptr = egl_attribs_gl;
|
||||
break;
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -519,17 +578,77 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
else
|
||||
#endif
|
||||
attrib_ptr = egl_attribs_gles;
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_VG
|
||||
attrib_ptr = egl_attribs_vg;
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
attrib_ptr = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (drm_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
if (!egl_init_context(drm, (EGLNativeDisplayType)g_gbm_dev, &major,
|
||||
&minor, &n, attrib_ptr))
|
||||
goto error;
|
||||
|
||||
attr = gfx_ctx_drm_egl_fill_attribs(drm, egl_attribs);
|
||||
egl_attribs_ptr = &egl_attribs[0];
|
||||
|
||||
if (!egl_create_context(drm, (attr != egl_attribs_ptr)
|
||||
? egl_attribs_ptr : NULL))
|
||||
goto error;
|
||||
|
||||
if (!egl_create_surface(drm, (EGLNativeWindowType)g_gbm_surface))
|
||||
return false;
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
egl_swap_buffers(drm);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
egl_report_error();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool gfx_ctx_drm_set_video_mode(void *data,
|
||||
unsigned width, unsigned height,
|
||||
bool fullscreen)
|
||||
{
|
||||
float refresh_mod;
|
||||
int i, ret = 0;
|
||||
struct drm_fb *fb = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
|
||||
|
||||
if (!drm)
|
||||
return false;
|
||||
|
||||
drm_install_sighandler();
|
||||
|
||||
/* If we use black frame insertion,
|
||||
* we fake a 60 Hz monitor for 120 Hz one, etc, so try to match that. */
|
||||
refresh_mod = settings->video.black_frame_insertion ? 0.5f : 1.0f;
|
||||
* we fake a 60 Hz monitor for 120 Hz one,
|
||||
* etc, so try to match that. */
|
||||
refresh_mod = settings->video.black_frame_insertion
|
||||
? 0.5f : 1.0f;
|
||||
|
||||
/* Find desired video mode, and use that.
|
||||
* If not fullscreen, we get desired windowed size,
|
||||
@ -538,7 +657,9 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
g_drm_mode = &g_drm_connector->modes[0];
|
||||
else
|
||||
{
|
||||
/* Try to match settings->video.refresh_rate as closely as possible.
|
||||
/* Try to match settings->video.refresh_rate
|
||||
* as closely as possible.
|
||||
*
|
||||
* Lower resolutions tend to have multiple supported
|
||||
* refresh rates as well.
|
||||
*/
|
||||
@ -570,14 +691,14 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
goto error;
|
||||
}
|
||||
|
||||
drm->g_fb_width = g_drm_mode->hdisplay;
|
||||
drm->g_fb_height = g_drm_mode->vdisplay;
|
||||
drm->fb_width = g_drm_mode->hdisplay;
|
||||
drm->fb_height = g_drm_mode->vdisplay;
|
||||
|
||||
/* Create GBM surface. */
|
||||
g_gbm_surface = gbm_surface_create(
|
||||
g_gbm_dev,
|
||||
drm->g_fb_width,
|
||||
drm->g_fb_height,
|
||||
drm->fb_width,
|
||||
drm->fb_height,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
||||
|
||||
@ -588,33 +709,25 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
}
|
||||
|
||||
|
||||
if (!egl_init_context(drm, (EGLNativeDisplayType)g_gbm_dev, &major,
|
||||
&minor, &n, attrib_ptr))
|
||||
switch (drm_api)
|
||||
{
|
||||
egl_report_error();
|
||||
goto error;
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
if (!gfx_ctx_drm_egl_set_video_mode(drm))
|
||||
goto error;
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
attr = egl_fill_attribs(drm, egl_attribs);
|
||||
egl_attribs_ptr = &egl_attribs[0];
|
||||
|
||||
if (!egl_create_context(drm, (attr != egl_attribs_ptr)
|
||||
? egl_attribs_ptr : NULL))
|
||||
{
|
||||
egl_report_error();
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!egl_create_surface(drm, (EGLNativeWindowType)g_gbm_surface))
|
||||
goto error;
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
egl_swap_buffers(drm);
|
||||
|
||||
g_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
|
||||
fb = drm_fb_get_from_bo(g_bo);
|
||||
fb = drm_fb_get_from_bo(g_bo);
|
||||
|
||||
ret = drmModeSetCrtc(g_drm_fd,
|
||||
ret = drmModeSetCrtc(g_drm_fd,
|
||||
g_crtc_id, fb->fb_id, 0, 0, &g_connector_id, 1, g_drm_mode);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
@ -622,7 +735,7 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
|
||||
return true;
|
||||
|
||||
error:
|
||||
gfx_ctx_drm_egl_destroy_resources(drm);
|
||||
gfx_ctx_drm_destroy_resources(drm);
|
||||
|
||||
if (drm)
|
||||
free(drm);
|
||||
@ -631,18 +744,18 @@ error:
|
||||
}
|
||||
|
||||
|
||||
static void gfx_ctx_drm_egl_destroy(void *data)
|
||||
static void gfx_ctx_drm_destroy(void *data)
|
||||
{
|
||||
gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)data;
|
||||
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
|
||||
|
||||
if (!drm)
|
||||
return;
|
||||
|
||||
gfx_ctx_drm_egl_destroy_resources(drm);
|
||||
gfx_ctx_drm_destroy_resources(drm);
|
||||
free(drm);
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_egl_input_driver(void *data,
|
||||
static void gfx_ctx_drm_input_driver(void *data,
|
||||
const input_driver_t **input, void **input_data)
|
||||
{
|
||||
(void)data;
|
||||
@ -650,49 +763,64 @@ static void gfx_ctx_drm_egl_input_driver(void *data,
|
||||
*input_data = NULL;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_drm_egl_has_focus(void *data)
|
||||
static bool gfx_ctx_drm_has_focus(void *data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_drm_egl_suppress_screensaver(void *data, bool enable)
|
||||
static bool gfx_ctx_drm_suppress_screensaver(void *data, bool enable)
|
||||
{
|
||||
(void)data;
|
||||
(void)enable;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_drm_egl_has_windowed(void *data)
|
||||
static bool gfx_ctx_drm_has_windowed(void *data)
|
||||
{
|
||||
(void)data;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_drm_egl_bind_api(void *video_driver,
|
||||
static bool gfx_ctx_drm_bind_api(void *video_driver,
|
||||
enum gfx_ctx_api api, unsigned major, unsigned minor)
|
||||
{
|
||||
(void)video_driver;
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
g_egl_major = major;
|
||||
g_egl_minor = minor;
|
||||
g_egl_api = api;
|
||||
#endif
|
||||
drm_api = api;
|
||||
|
||||
switch (api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
#if defined(HAVE_EGL) && defined(HAVE_OPENGL)
|
||||
|
||||
#ifndef EGL_KHR_create_context
|
||||
if ((major * 1000 + minor) >= 3001)
|
||||
return false;
|
||||
#endif
|
||||
return eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
#if defined(HAVE_EGL) && defined(HAVE_OPENGLES)
|
||||
|
||||
#ifndef EGL_KHR_create_context
|
||||
if (major >= 3)
|
||||
return false;
|
||||
#endif
|
||||
return eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#if defined(HAVE_EGL) && defined(HAVE_VG)
|
||||
return eglBindAPI(EGL_OPENVG_API);
|
||||
#endif
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -700,31 +828,67 @@ static bool gfx_ctx_drm_egl_bind_api(void *video_driver,
|
||||
return false;
|
||||
}
|
||||
|
||||
static gfx_ctx_proc_t gfx_ctx_drm_get_proc_address(const char *symbol)
|
||||
{
|
||||
switch (drm_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
return egl_get_proc_address(symbol);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_drm_egl = {
|
||||
gfx_ctx_drm_egl_init,
|
||||
gfx_ctx_drm_egl_destroy,
|
||||
gfx_ctx_drm_egl_bind_api,
|
||||
gfx_ctx_drm_egl_swap_interval,
|
||||
gfx_ctx_drm_egl_set_video_mode,
|
||||
gfx_ctx_drm_egl_get_video_size,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gfx_ctx_drm_bind_hw_render(void *data, bool enable)
|
||||
{
|
||||
switch (drm_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
egl_bind_hw_render(data, enable);
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_drm = {
|
||||
gfx_ctx_drm_init,
|
||||
gfx_ctx_drm_destroy,
|
||||
gfx_ctx_drm_bind_api,
|
||||
gfx_ctx_drm_swap_interval,
|
||||
gfx_ctx_drm_set_video_mode,
|
||||
gfx_ctx_drm_get_video_size,
|
||||
NULL, /* get_video_output_size */
|
||||
NULL, /* get_video_output_prev */
|
||||
NULL, /* get_video_output_next */
|
||||
NULL, /* get_metrics */
|
||||
NULL,
|
||||
gfx_ctx_drm_egl_update_window_title,
|
||||
gfx_ctx_drm_egl_check_window,
|
||||
gfx_ctx_drm_egl_set_resize,
|
||||
gfx_ctx_drm_egl_has_focus,
|
||||
gfx_ctx_drm_egl_suppress_screensaver,
|
||||
gfx_ctx_drm_egl_has_windowed,
|
||||
gfx_ctx_drm_egl_swap_buffers,
|
||||
gfx_ctx_drm_egl_input_driver,
|
||||
egl_get_proc_address,
|
||||
gfx_ctx_drm_update_window_title,
|
||||
gfx_ctx_drm_check_window,
|
||||
gfx_ctx_drm_set_resize,
|
||||
gfx_ctx_drm_has_focus,
|
||||
gfx_ctx_drm_suppress_screensaver,
|
||||
gfx_ctx_drm_has_windowed,
|
||||
gfx_ctx_drm_swap_buffers,
|
||||
gfx_ctx_drm_input_driver,
|
||||
gfx_ctx_drm_get_proc_address,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"kms-egl",
|
||||
egl_bind_hw_render,
|
||||
"kms",
|
||||
gfx_ctx_drm_bind_hw_render,
|
||||
};
|
@ -20,7 +20,7 @@
|
||||
#include "../../runloop.h"
|
||||
#include "../common/gl_common.h"
|
||||
|
||||
static enum gfx_ctx_api g_api = GFX_CTX_OPENGL_API;
|
||||
static enum gfx_ctx_api sdl_api = GFX_CTX_OPENGL_API;
|
||||
static unsigned g_major = 2;
|
||||
static unsigned g_minor = 1;
|
||||
|
||||
@ -132,7 +132,7 @@ static bool sdl_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned major,
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
|
||||
#endif
|
||||
g_api = api;
|
||||
sdl_api = api;
|
||||
g_major = major;
|
||||
g_minor = minor;
|
||||
|
||||
|
@ -51,6 +51,7 @@ typedef struct {
|
||||
unsigned res;
|
||||
} vc_ctx_data_t;
|
||||
|
||||
static enum gfx_ctx_api vc_api;
|
||||
static PFNEGLCREATEIMAGEKHRPROC peglCreateImageKHR;
|
||||
static PFNEGLDESTROYIMAGEKHRPROC peglDestroyImageKHR;
|
||||
|
||||
@ -186,7 +187,7 @@ static void *gfx_ctx_vc_init(void *video_driver)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!egl_create_context(vc, (g_egl_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL))
|
||||
if (!egl_create_context(vc, (vc_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL))
|
||||
{
|
||||
egl_report_error();
|
||||
goto error;
|
||||
@ -303,7 +304,7 @@ static bool gfx_ctx_vc_bind_api(void *data,
|
||||
(void)major;
|
||||
(void)minor;
|
||||
|
||||
g_egl_api = api;
|
||||
vc_api = api;
|
||||
|
||||
switch (api)
|
||||
{
|
||||
@ -354,7 +355,7 @@ static void gfx_ctx_vc_destroy(void *data)
|
||||
|
||||
if (vc->egl.ctx)
|
||||
{
|
||||
gfx_ctx_vc_bind_api(data, vc->egl.api, 0, 0);
|
||||
gfx_ctx_vc_bind_api(data, vc_api, 0, 0);
|
||||
eglMakeCurrent(vc->egl.dpy,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(vc->egl.dpy, vc->egl.ctx);
|
||||
@ -373,7 +374,7 @@ static void gfx_ctx_vc_destroy(void *data)
|
||||
|
||||
if (vc->egl.surf)
|
||||
{
|
||||
gfx_ctx_vc_bind_api(data, g_egl_api, 0, 0);
|
||||
gfx_ctx_vc_bind_api(data, vc_api, 0, 0);
|
||||
eglDestroySurface(vc->egl.dpy, vc->egl.surf);
|
||||
}
|
||||
|
||||
@ -386,7 +387,7 @@ static void gfx_ctx_vc_destroy(void *data)
|
||||
eglBindAPI(EGL_OPENVG_API);
|
||||
eglMakeCurrent(vc->egl.dpy,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
gfx_ctx_vc_bind_api(data, vc->egl.api, 0, 0);
|
||||
gfx_ctx_vc_bind_api(data, vc_api, 0, 0);
|
||||
eglMakeCurrent(vc->egl.dpy,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglTerminate(vc->egl.dpy);
|
||||
@ -459,7 +460,7 @@ static bool gfx_ctx_vc_image_buffer_init(void *data,
|
||||
};
|
||||
|
||||
/* Don't bother, we just use VGImages for our EGLImage anyway. */
|
||||
if (vc->egl.api == GFX_CTX_OPENVG_API)
|
||||
if (vc_api == GFX_CTX_OPENVG_API)
|
||||
return false;
|
||||
|
||||
peglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)
|
||||
@ -496,7 +497,7 @@ static bool gfx_ctx_vc_image_buffer_init(void *data,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gfx_ctx_vc_bind_api(NULL, vc->egl.api, 0, 0);
|
||||
gfx_ctx_vc_bind_api(NULL, vc_api, 0, 0);
|
||||
eglMakeCurrent(vc->egl.dpy, vc->egl.surf, vc->egl.surf, vc->egl.ctx);
|
||||
|
||||
vc->smooth = video->smooth;
|
||||
@ -515,7 +516,7 @@ fail:
|
||||
vc->pbuff_surf = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
gfx_ctx_vc_bind_api(NULL, g_egl_api, 0, 0);
|
||||
gfx_ctx_vc_bind_api(NULL, vc_api, 0, 0);
|
||||
eglMakeCurrent(vc->egl.dpy, vc->egl.surf, vc->egl.surf, vc->egl.ctx);
|
||||
|
||||
return false;
|
||||
@ -559,7 +560,7 @@ static bool gfx_ctx_vc_image_buffer_write(void *data, const void *frame, unsigne
|
||||
height);
|
||||
*image_handle = vc->eglBuffer[index];
|
||||
|
||||
gfx_ctx_vc_bind_api(NULL, vc->egl.api, 0, 0);
|
||||
gfx_ctx_vc_bind_api(NULL, vc_api, 0, 0);
|
||||
eglMakeCurrent(vc->egl.dpy, vc->egl.surf, vc->egl.surf, vc->egl.ctx);
|
||||
|
||||
return ret;
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "../common/gl_common.h"
|
||||
#endif
|
||||
|
||||
static volatile sig_atomic_t g_quit = 0;
|
||||
static volatile sig_atomic_t wl_quit = 0;
|
||||
|
||||
typedef struct gfx_ctx_wayland_data
|
||||
{
|
||||
@ -55,6 +55,8 @@ typedef struct gfx_ctx_wayland_data
|
||||
int fd;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned physical_width;
|
||||
unsigned physical_height;
|
||||
struct wl_display *dpy;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
@ -78,18 +80,18 @@ static enum gfx_ctx_api wl_api;
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x0040
|
||||
#endif
|
||||
|
||||
static void sighandler(int sig)
|
||||
static void wl_sighandler(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
g_quit = 1;
|
||||
wl_quit = 1;
|
||||
}
|
||||
|
||||
static void install_sighandlers(void)
|
||||
static void wl_install_sighandler(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_sigaction = NULL;
|
||||
sa.sa_handler = sighandler;
|
||||
sa.sa_handler = wl_sighandler;
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
@ -117,7 +119,7 @@ static void shell_surface_handle_configure(void *data,
|
||||
wl->width = wl->buffer_scale * width;
|
||||
wl->height = wl->buffer_scale * height;
|
||||
|
||||
RARCH_LOG("[Wayland/EGL]: Surface configure: %u x %u.\n",
|
||||
RARCH_LOG("[Wayland]: Surface configure: %u x %u.\n",
|
||||
wl->width, wl->height);
|
||||
}
|
||||
|
||||
@ -134,17 +136,92 @@ static const struct wl_shell_surface_listener shell_surface_listener = {
|
||||
shell_surface_handle_popup_done,
|
||||
};
|
||||
|
||||
static void display_handle_geometry(void *data,
|
||||
struct wl_output *output,
|
||||
int x, int y,
|
||||
int physical_width, int physical_height,
|
||||
int subpixel,
|
||||
const char *make,
|
||||
const char *model,
|
||||
int transform)
|
||||
{
|
||||
(void)data;
|
||||
(void)output;
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)subpixel;
|
||||
(void)make;
|
||||
(void)model;
|
||||
(void)transform;
|
||||
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
wl->physical_width = physical_width;
|
||||
wl->physical_height = physical_height;
|
||||
RARCH_LOG("[Wayland]: Physical width: %d mm x %d mm.\n",
|
||||
physical_width, physical_height);
|
||||
}
|
||||
|
||||
static void display_handle_mode(void *data,
|
||||
struct wl_output *output,
|
||||
uint32_t flags,
|
||||
int width,
|
||||
int height,
|
||||
int refresh)
|
||||
{
|
||||
(void)output;
|
||||
(void)flags;
|
||||
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
wl->width = width;
|
||||
wl->height = height;
|
||||
|
||||
RARCH_LOG("[Wayland]: Video mode: %d x %d @ %d Hz.\n",
|
||||
width, height, refresh);
|
||||
}
|
||||
|
||||
static void display_handle_done(void *data,
|
||||
struct wl_output *output)
|
||||
{
|
||||
(void)data;
|
||||
(void)output;
|
||||
}
|
||||
|
||||
static void display_handle_scale(void *data,
|
||||
struct wl_output *output,
|
||||
int32_t factor)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
|
||||
RARCH_LOG("[Wayland]: Setting buffer scale factor to %d.\n", factor);
|
||||
wl->buffer_scale = factor;
|
||||
}
|
||||
|
||||
static const struct wl_output_listener output_listener = {
|
||||
display_handle_geometry,
|
||||
display_handle_mode,
|
||||
display_handle_done,
|
||||
display_handle_scale,
|
||||
};
|
||||
|
||||
/* Registry callbacks. */
|
||||
static void registry_handle_global(void *data, struct wl_registry *reg,
|
||||
uint32_t id, const char *interface, uint32_t version)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
struct wl_output *output;
|
||||
|
||||
(void)version;
|
||||
|
||||
if (string_is_equal(interface, "wl_compositor"))
|
||||
wl->compositor = (struct wl_compositor*)wl_registry_bind(reg,
|
||||
id, &wl_compositor_interface, 3);
|
||||
else if (string_is_equal(interface, "wl_output"))
|
||||
{
|
||||
output = (struct wl_output*)wl_registry_bind(reg,
|
||||
id, &wl_output_interface, 2);
|
||||
wl_output_add_listener(output, &output_listener, wl);
|
||||
wl_display_roundtrip(wl->dpy);
|
||||
}
|
||||
else if (string_is_equal(interface, "wl_shell"))
|
||||
wl->shell = (struct wl_shell*)
|
||||
wl_registry_bind(reg, id, &wl_shell_interface, 1);
|
||||
@ -242,7 +319,7 @@ static void flush_wayland_fd(gfx_ctx_wayland_data_t *wl)
|
||||
if (fd.revents & (POLLERR | POLLHUP))
|
||||
{
|
||||
close(wl->fd);
|
||||
g_quit = true;
|
||||
wl_quit = true;
|
||||
}
|
||||
|
||||
if (fd.revents & POLLIN)
|
||||
@ -289,7 +366,7 @@ static void gfx_ctx_wl_check_window(void *data, bool *quit,
|
||||
*height = new_height;
|
||||
}
|
||||
|
||||
*quit = g_quit;
|
||||
*quit = wl_quit;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
|
||||
@ -353,6 +430,35 @@ static void gfx_ctx_wl_get_video_size(void *data,
|
||||
*height = wl->height;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_wl_get_metrics(void *data,
|
||||
enum display_metric_types type, float *value)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
if (wl->physical_width == 0 || wl->physical_height == 0)
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DISPLAY_METRIC_MM_WIDTH:
|
||||
*value = (float)wl->physical_width;
|
||||
break;
|
||||
|
||||
case DISPLAY_METRIC_MM_HEIGHT:
|
||||
*value = (float)wl->physical_height;
|
||||
break;
|
||||
|
||||
case DISPLAY_METRIC_DPI:
|
||||
*value = (float)wl->width * 25.4f / (float)wl->physical_width;
|
||||
break;
|
||||
|
||||
default:
|
||||
*value = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DEFAULT_WINDOWED_WIDTH 640
|
||||
#define DEFAULT_WINDOWED_HEIGHT 480
|
||||
|
||||
@ -368,7 +474,6 @@ static void gfx_ctx_wl_get_video_size(void *data,
|
||||
|
||||
static void *gfx_ctx_wl_init(void *video_driver)
|
||||
{
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
static const EGLint egl_attribs_gl[] = {
|
||||
WL_EGL_ATTRIBS_BASE,
|
||||
@ -418,7 +523,7 @@ static void *gfx_ctx_wl_init(void *video_driver)
|
||||
(void)video_driver;
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
switch (wl->egl.api)
|
||||
switch (wl_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
#ifdef HAVE_OPENGL
|
||||
@ -448,34 +553,21 @@ static void *gfx_ctx_wl_init(void *video_driver)
|
||||
}
|
||||
#endif
|
||||
|
||||
g_quit = 0;
|
||||
wl_quit = 0;
|
||||
|
||||
wl->dpy = wl_display_connect(NULL);
|
||||
wl->buffer_scale = 1;
|
||||
|
||||
if (!wl->dpy)
|
||||
{
|
||||
RARCH_ERR("Failed to connect to Wayland server.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
install_sighandlers();
|
||||
wl_install_sighandler();
|
||||
|
||||
wl->registry = wl_display_get_registry(wl->dpy);
|
||||
wl_registry_add_listener(wl->registry, ®istry_listener, wl);
|
||||
|
||||
switch (wl_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
case GFX_CTX_OPENVG_API:
|
||||
#ifdef HAVE_EGL
|
||||
wl_display_dispatch(wl->dpy);
|
||||
#endif
|
||||
break;
|
||||
case GFX_CTX_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wl_display_roundtrip(wl->dpy);
|
||||
|
||||
if (!wl->compositor)
|
||||
@ -534,7 +626,7 @@ error:
|
||||
#ifdef HAVE_EGL
|
||||
static EGLint *egl_fill_attribs(gfx_ctx_wayland_data_t *wl, EGLint *attr)
|
||||
{
|
||||
switch (wl->egl.api)
|
||||
switch (wl_api)
|
||||
{
|
||||
#ifdef EGL_KHR_create_context
|
||||
case GFX_CTX_OPENGL_API:
|
||||
@ -668,10 +760,8 @@ static bool gfx_ctx_wl_set_video_mode(void *data,
|
||||
wl->width = width ? width : DEFAULT_WINDOWED_WIDTH;
|
||||
wl->height = height ? height : DEFAULT_WINDOWED_HEIGHT;
|
||||
|
||||
/* TODO: Use wl_output::scale to obtain correct value. */
|
||||
wl->buffer_scale = 1;
|
||||
|
||||
wl->surface = wl_compositor_create_surface(wl->compositor);
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
|
||||
switch (wl_api)
|
||||
{
|
||||
@ -784,7 +874,6 @@ static bool gfx_ctx_wl_bind_api(void *video_driver,
|
||||
#ifdef HAVE_EGL
|
||||
g_egl_major = major;
|
||||
g_egl_minor = minor;
|
||||
g_egl_api = api;
|
||||
#endif
|
||||
|
||||
switch (api)
|
||||
@ -1056,7 +1145,7 @@ const gfx_ctx_driver_t gfx_ctx_wayland = {
|
||||
NULL, /* get_video_output_size */
|
||||
NULL, /* get_video_output_prev */
|
||||
NULL, /* get_video_output_next */
|
||||
NULL, /* get_metrics */
|
||||
gfx_ctx_wl_get_metrics,
|
||||
NULL,
|
||||
gfx_ctx_wl_update_window_title,
|
||||
gfx_ctx_wl_check_window,
|
||||
|
@ -61,7 +61,7 @@ typedef struct gfx_ctx_x_data
|
||||
|
||||
static unsigned g_major;
|
||||
static unsigned g_minor;
|
||||
static enum gfx_ctx_api g_api;
|
||||
static enum gfx_ctx_api x_api;
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
static PFNGLXCREATECONTEXTATTRIBSARBPROC glx_create_context_attribs;
|
||||
@ -83,7 +83,7 @@ static void gfx_ctx_x_destroy_resources(gfx_ctx_x_data_t *x)
|
||||
|
||||
if (g_x11_dpy)
|
||||
{
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -164,7 +164,7 @@ static void gfx_ctx_x_destroy(void *data)
|
||||
|
||||
gfx_ctx_x_destroy_resources(x);
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_VULKAN_API:
|
||||
#ifdef HAVE_VULKAN
|
||||
@ -184,7 +184,7 @@ static void gfx_ctx_x_swap_interval(void *data, unsigned interval)
|
||||
{
|
||||
gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data;
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -232,7 +232,7 @@ static void gfx_ctx_x_swap_buffers(void *data)
|
||||
{
|
||||
gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data;
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -264,7 +264,7 @@ static void gfx_ctx_x_check_window(void *data, bool *quit,
|
||||
|
||||
x11_check_window(data, quit, resize, width, height, frame_count);
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_VULKAN_API:
|
||||
#ifdef HAVE_VULKAN
|
||||
@ -289,7 +289,7 @@ static bool gfx_ctx_x_set_resize(void *data,
|
||||
(void)width;
|
||||
(void)height;
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_VULKAN_API:
|
||||
#ifdef HAVE_VULKAN
|
||||
@ -346,7 +346,7 @@ static void *gfx_ctx_x_init(void *data)
|
||||
goto error;
|
||||
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -440,7 +440,7 @@ static bool gfx_ctx_x_set_video_mode(void *data,
|
||||
windowed_full = settings->video.windowed_fullscreen;
|
||||
true_full = false;
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -516,7 +516,7 @@ static bool gfx_ctx_x_set_video_mode(void *data,
|
||||
(true_full ? CWOverrideRedirect : 0), &swa);
|
||||
XSetWindowBackground(g_x11_dpy, g_x11_win, 0);
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -568,7 +568,7 @@ static bool gfx_ctx_x_set_video_mode(void *data,
|
||||
|
||||
x11_event_queue_check(&event);
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -678,7 +678,7 @@ static bool gfx_ctx_x_set_video_mode(void *data,
|
||||
|
||||
x11_install_quit_atom();
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -777,7 +777,7 @@ static bool gfx_ctx_x_has_windowed(void *data)
|
||||
|
||||
static gfx_ctx_proc_t gfx_ctx_x_get_proc_address(const char *symbol)
|
||||
{
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
@ -806,7 +806,7 @@ static bool gfx_ctx_x_bind_api(void *data, enum gfx_ctx_api api,
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
#ifdef HAVE_OPENGL
|
||||
g_api = GFX_CTX_OPENGL_API;
|
||||
x_api = GFX_CTX_OPENGL_API;
|
||||
return true;
|
||||
#else
|
||||
break;
|
||||
@ -824,7 +824,7 @@ static bool gfx_ctx_x_bind_api(void *data, enum gfx_ctx_api api,
|
||||
g_major = 2; /* ES 2.0. */
|
||||
g_minor = 0;
|
||||
}
|
||||
g_api = GFX_CTX_OPENGL_ES_API;
|
||||
x_api = GFX_CTX_OPENGL_ES_API;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
@ -832,7 +832,7 @@ static bool gfx_ctx_x_bind_api(void *data, enum gfx_ctx_api api,
|
||||
#endif
|
||||
case GFX_CTX_VULKAN_API:
|
||||
#ifdef HAVE_VULKAN
|
||||
g_api = api;
|
||||
x_api = api;
|
||||
return true;
|
||||
#else
|
||||
break;
|
||||
@ -857,7 +857,7 @@ static void gfx_ctx_x_bind_hw_render(void *data, bool enable)
|
||||
if (!x)
|
||||
return;
|
||||
|
||||
switch (g_api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
case GFX_CTX_OPENGL_ES_API:
|
||||
|
@ -33,7 +33,9 @@ typedef struct {
|
||||
bool should_reset_mode;
|
||||
} xegl_ctx_data_t;
|
||||
|
||||
static int egl_nul_handler(Display *dpy, XErrorEvent *event)
|
||||
static enum gfx_ctx_api x_api;
|
||||
|
||||
static int x_nul_handler(Display *dpy, XErrorEvent *event)
|
||||
{
|
||||
(void)dpy;
|
||||
(void)event;
|
||||
@ -130,7 +132,7 @@ static void *gfx_ctx_xegl_init(void *video_driver)
|
||||
if (!xegl)
|
||||
return NULL;
|
||||
|
||||
switch (xegl->egl.api)
|
||||
switch (x_api)
|
||||
{
|
||||
case GFX_CTX_OPENGL_API:
|
||||
attrib_ptr = egl_attribs_gl;
|
||||
@ -172,7 +174,7 @@ error:
|
||||
|
||||
static EGLint *xegl_fill_attribs(xegl_ctx_data_t *xegl, EGLint *attr)
|
||||
{
|
||||
switch (xegl->egl.api)
|
||||
switch (x_api)
|
||||
{
|
||||
#ifdef EGL_KHR_create_context
|
||||
case GFX_CTX_OPENGL_API:
|
||||
@ -378,7 +380,7 @@ static bool gfx_ctx_xegl_set_video_mode(void *data,
|
||||
/* This can blow up on some drivers. It's not fatal,
|
||||
* so override errors for this call.
|
||||
*/
|
||||
old_handler = XSetErrorHandler(egl_nul_handler);
|
||||
old_handler = XSetErrorHandler(x_nul_handler);
|
||||
XSetInputFocus(g_x11_dpy, g_x11_win, RevertToNone, CurrentTime);
|
||||
XSync(g_x11_dpy, False);
|
||||
XSetErrorHandler(old_handler);
|
||||
@ -445,7 +447,7 @@ static bool gfx_ctx_xegl_bind_api(void *video_driver,
|
||||
{
|
||||
g_egl_major = major;
|
||||
g_egl_minor = minor;
|
||||
g_egl_api = api;
|
||||
x_api = api;
|
||||
|
||||
switch (api)
|
||||
{
|
||||
|
@ -36,12 +36,14 @@ static void *vulkan_raster_font_init_font(void *data,
|
||||
const struct font_atlas *atlas = NULL;
|
||||
vulkan_raster_t *font = (vulkan_raster_t*)calloc(1, sizeof(*font));
|
||||
|
||||
#if 0
|
||||
VkComponentMapping swizzle = {
|
||||
VK_COMPONENT_SWIZZLE_ONE,
|
||||
VK_COMPONENT_SWIZZLE_ONE,
|
||||
VK_COMPONENT_SWIZZLE_ONE,
|
||||
VK_COMPONENT_SWIZZLE_R,
|
||||
};
|
||||
#endif
|
||||
|
||||
if (!font)
|
||||
return NULL;
|
||||
@ -58,7 +60,8 @@ static void *vulkan_raster_font_init_font(void *data,
|
||||
|
||||
atlas = font->font_driver->get_atlas(font->font_data);
|
||||
font->texture = vulkan_create_texture(font->vk, NULL,
|
||||
atlas->width, atlas->height, VK_FORMAT_R8_UNORM, atlas->buffer, &swizzle, VULKAN_TEXTURE_STATIC);
|
||||
atlas->width, atlas->height, VK_FORMAT_R8_UNORM, atlas->buffer,
|
||||
NULL /*&swizzle*/, VULKAN_TEXTURE_STATIC);
|
||||
|
||||
return font;
|
||||
}
|
||||
@ -224,7 +227,7 @@ static void vulkan_raster_font_setup_viewport(vulkan_raster_t *font, bool full_s
|
||||
static void vulkan_raster_font_flush(vulkan_raster_t *font)
|
||||
{
|
||||
const struct vk_draw_triangles call = {
|
||||
font->vk->pipelines.alpha_blend,
|
||||
font->vk->pipelines.font,
|
||||
&font->texture,
|
||||
font->vk->samplers.nearest,
|
||||
&font->vk->mvp,
|
||||
|
@ -58,7 +58,7 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
|
||||
&gfx_ctx_x_egl,
|
||||
#endif
|
||||
#if defined(HAVE_KMS)
|
||||
&gfx_ctx_drm_egl,
|
||||
&gfx_ctx_drm,
|
||||
#endif
|
||||
#if defined(ANDROID)
|
||||
&gfx_ctx_android,
|
||||
|
@ -252,7 +252,7 @@ extern const gfx_ctx_driver_t gfx_ctx_x_egl;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_wayland;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_x;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_d3d;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_drm_egl;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_drm;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_mali_fbdev;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_vivante_fbdev;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_android;
|
||||
|
@ -242,14 +242,11 @@ const char* config_get_video_driver_options(void)
|
||||
return char_list_new_special(STRING_LIST_VIDEO_DRIVERS, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_VULKAN
|
||||
static bool hw_render_context_is_vulkan(enum retro_hw_context_type type)
|
||||
{
|
||||
return type == RETRO_HW_CONTEXT_VULKAN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL) && defined(HAVE_FBO)
|
||||
static bool hw_render_context_is_gl(enum retro_hw_context_type type)
|
||||
{
|
||||
switch (type)
|
||||
@ -266,7 +263,6 @@ static bool hw_render_context_is_gl(enum retro_hw_context_type type)
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool find_video_driver(void)
|
||||
{
|
||||
@ -276,27 +272,27 @@ static bool find_video_driver(void)
|
||||
|
||||
if (video_driver_ctl(RARCH_DISPLAY_CTL_IS_HW_CONTEXT, NULL))
|
||||
{
|
||||
current_video = NULL;
|
||||
struct retro_hw_render_callback *hwr =
|
||||
video_driver_callback();
|
||||
current_video = NULL;
|
||||
|
||||
(void)hwr;
|
||||
|
||||
#if defined(HAVE_VULKAN)
|
||||
if (hwr && hw_render_context_is_vulkan(hwr->context_type))
|
||||
{
|
||||
#if defined(HAVE_VULKAN)
|
||||
RARCH_LOG("Using HW render, Vulkan driver forced.\n");
|
||||
current_video = &video_vulkan;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_OPENGL) && defined(HAVE_FBO)
|
||||
if (hwr && hw_render_context_is_gl(hwr->context_type))
|
||||
{
|
||||
#if defined(HAVE_OPENGL) && defined(HAVE_FBO)
|
||||
RARCH_LOG("Using HW render, OpenGL driver forced.\n");
|
||||
current_video = &video_gl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (current_video)
|
||||
return true;
|
||||
|
@ -141,19 +141,17 @@ VIDEO CONTEXT
|
||||
#include "../gfx/common/vulkan_common.c"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL)
|
||||
|
||||
#if defined(HAVE_KMS)
|
||||
#include "../gfx/drivers_context/drm_egl_ctx.c"
|
||||
#endif
|
||||
#if defined(HAVE_VIDEOCORE)
|
||||
#include "../gfx/drivers_context/vc_egl_ctx.c"
|
||||
#endif
|
||||
|
||||
#include "../gfx/drivers_context/drm_ctx.c"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EGL)
|
||||
#include "../gfx/common/egl_common.c"
|
||||
|
||||
#if defined(HAVE_VIDEOCORE)
|
||||
#include "../gfx/drivers_context/vc_egl_ctx.c"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_X11)
|
||||
|
@ -39,8 +39,8 @@ bool input_remapping_load_file(void *data, const char *path)
|
||||
if (!conf || string_is_empty(path))
|
||||
return false;
|
||||
|
||||
strlcpy(settings->input.remapping_path, path,
|
||||
sizeof(settings->input.remapping_path));
|
||||
strlcpy(global->name.remapfile, path,
|
||||
sizeof(global->name.remapfile));
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
|
@ -68,12 +68,12 @@ static void menu_action_setting_disp_set_label_remap_file_load(
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
*w = 19;
|
||||
strlcpy(s2, path, len2);
|
||||
if (settings)
|
||||
fill_pathname_base(s, settings->input.remapping_path,
|
||||
if (global)
|
||||
fill_pathname_base(s, global->name.remapfile,
|
||||
len);
|
||||
}
|
||||
|
||||
@ -379,13 +379,17 @@ static void menu_action_setting_disp_set_label_input_desc(
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned inp_desc_index_offset = type - MENU_SETTINGS_INPUT_DESC_BEGIN;
|
||||
unsigned inp_desc_user = inp_desc_index_offset /
|
||||
char descriptor[PATH_MAX_LENGTH];
|
||||
const struct retro_keybind *auto_bind = NULL;
|
||||
const struct retro_keybind *keybind = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned inp_desc_index_offset =
|
||||
type - MENU_SETTINGS_INPUT_DESC_BEGIN;
|
||||
unsigned inp_desc_user = inp_desc_index_offset /
|
||||
(RARCH_FIRST_CUSTOM_BIND + 4);
|
||||
unsigned inp_desc_button_index_offset = inp_desc_index_offset -
|
||||
(inp_desc_user * (RARCH_FIRST_CUSTOM_BIND + 4));
|
||||
unsigned remap_id = 0;
|
||||
unsigned remap_id = 0;
|
||||
|
||||
if (!settings)
|
||||
return;
|
||||
@ -393,14 +397,11 @@ static void menu_action_setting_disp_set_label_input_desc(
|
||||
remap_id = settings->input.remap_ids
|
||||
[inp_desc_user][inp_desc_button_index_offset];
|
||||
|
||||
const struct retro_keybind *keybind =
|
||||
(const struct retro_keybind*)
|
||||
keybind = (const struct retro_keybind*)
|
||||
&settings->input.binds[inp_desc_user][remap_id];
|
||||
const struct retro_keybind *auto_bind =
|
||||
(const struct retro_keybind*)
|
||||
auto_bind = (const struct retro_keybind*)
|
||||
input_get_auto_bind(inp_desc_user, remap_id);
|
||||
|
||||
char descriptor[PATH_MAX_LENGTH];
|
||||
input_config_get_bind_string(descriptor,
|
||||
keybind, auto_bind, sizeof(descriptor));
|
||||
|
||||
|
@ -42,12 +42,12 @@
|
||||
|
||||
static int action_start_remap_file_load(unsigned type, const char *label)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!settings)
|
||||
if (!global)
|
||||
return -1;
|
||||
|
||||
settings->input.remapping_path[0] = '\0';
|
||||
global->name.remapfile[0] = '\0';
|
||||
input_remapping_set_defaults();
|
||||
return 0;
|
||||
}
|
||||
|
@ -336,11 +336,11 @@ int generic_menu_iterate(void *data, void *userdata, enum menu_action action)
|
||||
BIT64_SET(menu->state, MENU_STATE_POP_STACK);
|
||||
break;
|
||||
case ITERATE_TYPE_DEFAULT:
|
||||
/* FIXME: Crappy hack, needed for mouse controls to not be completely broken
|
||||
* in case we press back.
|
||||
/* FIXME: Crappy hack, needed for mouse controls
|
||||
* to not be completely broken in case we press back.
|
||||
*
|
||||
* We need to fix this entire mess, mouse controls should not rely on a
|
||||
* hack like this in order to work. */
|
||||
* We need to fix this entire mess, mouse controls
|
||||
* should not rely on a hack like this in order to work. */
|
||||
selection = max(min(selection, (menu_entries_get_size() - 1)), 0);
|
||||
|
||||
menu_entry_get(&entry, 0, selection, NULL, false);
|
||||
|
@ -243,13 +243,13 @@ HRESULT XuiTextureLoader(IXuiDevice *pDevice, LPCWSTR szFileName,
|
||||
|
||||
if(hr != D3DXERR_INVALIDDATA )
|
||||
{
|
||||
pImageInfo->Depth = pSrc.Depth;
|
||||
pImageInfo->Format = pSrc.Format;
|
||||
pImageInfo->Height = pSrc.Height;
|
||||
pImageInfo->Depth = pSrc.Depth;
|
||||
pImageInfo->Format = pSrc.Format;
|
||||
pImageInfo->Height = pSrc.Height;
|
||||
pImageInfo->ImageFileFormat = pSrc.ImageFileFormat;
|
||||
pImageInfo->MipLevels = pSrc.MipLevels;
|
||||
pImageInfo->ResourceType = pSrc.ResourceType;
|
||||
pImageInfo->Width = pSrc.Width;
|
||||
pImageInfo->MipLevels = pSrc.MipLevels;
|
||||
pImageInfo->ResourceType = pSrc.ResourceType;
|
||||
pImageInfo->Width = pSrc.Width;
|
||||
}
|
||||
else
|
||||
RARCH_ERR("D3DXERR_INVALIDDATA Encountered\n");
|
||||
@ -293,7 +293,8 @@ static void* xui_init(void **userdata)
|
||||
|
||||
d3d_make_d3dpp(d3d, &video_info, &d3dpp);
|
||||
|
||||
hr = app.InitShared(d3d->dev, &d3dpp, (PFN_XUITEXTURELOADER)XuiTextureLoader);
|
||||
hr = app.InitShared(d3d->dev, &d3dpp,
|
||||
(PFN_XUITEXTURELOADER)XuiTextureLoader);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@ -387,8 +388,8 @@ static void xui_render_message(const char *msg)
|
||||
float msg_height = 120;
|
||||
float msg_offset = 32;
|
||||
|
||||
font_parms.x = msg_width;
|
||||
font_parms.y = msg_height + (msg_offset * j);
|
||||
font_parms.x = msg_width;
|
||||
font_parms.y = msg_height + (msg_offset * j);
|
||||
font_parms.scale = 21;
|
||||
|
||||
video_driver_set_osd_msg(msg, &font_parms, NULL);
|
||||
@ -404,7 +405,7 @@ static void xui_frame(void *data)
|
||||
XUIMessageRender msgRender;
|
||||
D3DXMATRIX matOrigView;
|
||||
LPDIRECT3DDEVICE d3dr;
|
||||
const char *message;
|
||||
const char *message = NULL;
|
||||
D3DVIEWPORT vp_full = {0};
|
||||
d3d_video_t *d3d = (d3d_video_t*)video_driver_get_ptr(false);
|
||||
|
||||
@ -424,7 +425,8 @@ static void xui_frame(void *data)
|
||||
|
||||
XuiRenderGetViewTransform( app.GetDC(), &matOrigView );
|
||||
|
||||
XuiMessageRender( &msg, &msgRender, app.GetDC(), 0xffffffff, XUI_BLEND_NORMAL );
|
||||
XuiMessageRender( &msg, &msgRender,
|
||||
app.GetDC(), 0xffffffff, XUI_BLEND_NORMAL );
|
||||
XuiSendMessage( app.GetRootObj(), &msg );
|
||||
|
||||
XuiRenderSetViewTransform( app.GetDC(), &matOrigView );
|
||||
@ -452,9 +454,7 @@ static void blit_line(int x, int y, const char *message, bool green)
|
||||
|
||||
static void xui_render_background(void)
|
||||
{
|
||||
bool libretro_running = menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL);
|
||||
|
||||
if (libretro_running)
|
||||
if (menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL))
|
||||
XuiElementSetShow(m_background, FALSE);
|
||||
else
|
||||
XuiElementSetShow(m_background, TRUE);
|
||||
@ -666,13 +666,15 @@ static void xui_list_free(file_list_t *list, size_t idx,
|
||||
|
||||
static void xui_list_clear(file_list_t *list)
|
||||
{
|
||||
XuiListDeleteItems(m_menulist, 0, XuiListGetItemCount(m_menulist));
|
||||
XuiListDeleteItems(m_menulist,
|
||||
0, XuiListGetItemCount(m_menulist));
|
||||
}
|
||||
|
||||
static void xui_list_set_selection(void *data, file_list_t *list)
|
||||
{
|
||||
if (list)
|
||||
XuiListSetCurSel(m_menulist, file_list_get_directory_ptr(list));
|
||||
XuiListSetCurSel(m_menulist,
|
||||
file_list_get_directory_ptr(list));
|
||||
}
|
||||
|
||||
static int xui_environ(menu_environ_cb_t type, void *data)
|
||||
|
@ -213,8 +213,10 @@ static void zarch_zui_font(void)
|
||||
|
||||
menu_display_ctl(MENU_DISPLAY_CTL_FONT_SIZE, &font_size);
|
||||
|
||||
fill_pathname_join(mediapath, settings->assets_directory, "zarch", sizeof(mediapath));
|
||||
fill_pathname_join(fontpath, mediapath, "Roboto-Condensed.ttf", sizeof(fontpath));
|
||||
fill_pathname_join(mediapath,
|
||||
settings->assets_directory, "zarch", sizeof(mediapath));
|
||||
fill_pathname_join(fontpath,
|
||||
mediapath, "Roboto-Condensed.ttf", sizeof(fontpath));
|
||||
|
||||
font_info.path = fontpath;
|
||||
font_info.size = font_size;
|
||||
@ -250,7 +252,8 @@ static int16_t zarch_zui_input_state(zui_t *zui, enum zarch_zui_input_state stat
|
||||
case MENU_POINTER_ZARCH_Y:
|
||||
return menu_input_pointer_state(MENU_POINTER_Y_AXIS);
|
||||
case MENU_ZARCH_PRESSED:
|
||||
if (menu_input_mouse_state(MENU_MOUSE_LEFT_BUTTON) || menu_input_pointer_state(MENU_POINTER_PRESSED))
|
||||
if ( menu_input_mouse_state(MENU_MOUSE_LEFT_BUTTON)
|
||||
|| menu_input_pointer_state(MENU_POINTER_PRESSED))
|
||||
return 1;
|
||||
if (zui->action == MENU_ACTION_OK)
|
||||
return 1;
|
||||
@ -260,7 +263,8 @@ static int16_t zarch_zui_input_state(zui_t *zui, enum zarch_zui_input_state stat
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool zarch_zui_check_button_down(zui_t *zui, unsigned id, int x1, int y1, int x2, int y2)
|
||||
static bool zarch_zui_check_button_down(zui_t *zui,
|
||||
unsigned id, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
bool result = false;
|
||||
bool inside = menu_input_mouse_check_hitbox(x1, y1, x2, y2);
|
||||
@ -268,7 +272,8 @@ static bool zarch_zui_check_button_down(zui_t *zui, unsigned id, int x1, int y1,
|
||||
if (inside)
|
||||
zui->item.hot = id;
|
||||
|
||||
if (zui->item.hot == id && zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
if ( zui->item.hot == id
|
||||
&& zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
{
|
||||
result = true;
|
||||
zui->item.active = id;
|
||||
@ -277,7 +282,8 @@ static bool zarch_zui_check_button_down(zui_t *zui, unsigned id, int x1, int y1,
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool zarch_zui_check_button_up(zui_t *zui, unsigned id, int x1, int y1, int x2, int y2)
|
||||
static bool zarch_zui_check_button_up(zui_t *zui,
|
||||
unsigned id, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
bool result = false;
|
||||
bool inside = menu_input_mouse_check_hitbox(x1, y1, x2, y2);
|
||||
@ -285,7 +291,8 @@ static bool zarch_zui_check_button_up(zui_t *zui, unsigned id, int x1, int y1, i
|
||||
if (inside)
|
||||
zui->item.hot = id;
|
||||
|
||||
if (zui->item.active == id && !zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
if ( zui->item.active == id
|
||||
&& !zarch_zui_input_state(zui, MENU_ZARCH_PRESSED))
|
||||
{
|
||||
if (zui->item.hot == id)
|
||||
result = true;
|
||||
@ -314,7 +321,8 @@ static unsigned zarch_zui_hash(zui_t *zui, const char *s)
|
||||
return zui->hash = hval;
|
||||
}
|
||||
|
||||
static void zarch_zui_draw_text(zui_t *zui, uint32_t color, int x, int y, const char *text)
|
||||
static void zarch_zui_draw_text(zui_t *zui,
|
||||
uint32_t color, int x, int y, const char *text)
|
||||
{
|
||||
struct font_params params;
|
||||
|
||||
@ -375,19 +383,21 @@ static float zarch_zui_randf(float min, float max)
|
||||
return (rand() * ((max - min) / RAND_MAX)) + min;
|
||||
}
|
||||
|
||||
static float zarch_zui_scalef(float val, float oldmin, float oldmax, float newmin, float newmax)
|
||||
static float zarch_zui_scalef(float val,
|
||||
float oldmin, float oldmax, float newmin, float newmax)
|
||||
{
|
||||
return (((val - oldmin) * (newmax - newmin)) / (oldmax - oldmin)) + newmin;
|
||||
}
|
||||
|
||||
#define NPARTICLES 100
|
||||
|
||||
static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca, int width, int height)
|
||||
static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca,
|
||||
int width, int height)
|
||||
{
|
||||
static part_t particles[NPARTICLES];
|
||||
static bool initialized = false;
|
||||
static int timeout = 0;
|
||||
unsigned i, max_gen = 2;
|
||||
unsigned i, max_gen = 2;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
@ -404,11 +414,11 @@ static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca, int width, int hei
|
||||
int16_t mouse_x = zarch_zui_input_state(zui, MENU_ZARCH_MOUSE_X);
|
||||
|
||||
p->y += p->yspeed;
|
||||
p->x += zarch_zui_scalef(mouse_x, 0, width, -0.3, 0.3) + p->xspeed;
|
||||
|
||||
p->alive = p->y >= 0 && p->y < height && p->x >= 0 && p->x < width;
|
||||
|
||||
p->x += zarch_zui_scalef(mouse_x, 0, width, -0.3, 0.3);
|
||||
p->x += p->xspeed;
|
||||
|
||||
p->alive = p->y >= 0 && p->y < height
|
||||
&& p->x >= 0 && p->x < width;
|
||||
}
|
||||
else if (max_gen > 0 && timeout <= 0)
|
||||
{
|
||||
@ -447,13 +457,15 @@ static void zarch_zui_snow(zui_t *zui, gfx_coord_array_t *ca, int width, int hei
|
||||
colors[j] = alpha;
|
||||
}
|
||||
|
||||
zarch_zui_push_quad(width, height, colors, ca, p->x-2, p->y-2, p->x+2, p->y+2);
|
||||
zarch_zui_push_quad(width, height,
|
||||
colors, ca, p->x-2, p->y-2, p->x+2, p->y+2);
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool zarch_zui_button_full(zui_t *zui, int x1, int y1, int x2, int y2, const char *label)
|
||||
static bool zarch_zui_button_full(zui_t *zui,
|
||||
int x1, int y1, int x2, int y2, const char *label)
|
||||
{
|
||||
unsigned id = zarch_zui_hash(zui, label);
|
||||
bool active = zarch_zui_check_button_up(zui, id, x1, y1, x2, y2);
|
||||
@ -470,7 +482,8 @@ static bool zarch_zui_button_full(zui_t *zui, int x1, int y1, int x2, int y2, co
|
||||
|
||||
static bool zarch_zui_button(zui_t *zui, int x1, int y1, const char *label)
|
||||
{
|
||||
return zarch_zui_button_full(zui, x1, y1, x1 + zarch_zui_strwidth(zui->fb_buf, label, 1.0) + 24, y1 + 64, label);
|
||||
return zarch_zui_button_full(zui, x1, y1, x1
|
||||
+ zarch_zui_strwidth(zui->fb_buf, label, 1.0) + 24, y1 + 64, label);
|
||||
}
|
||||
|
||||
static bool zarch_zui_list_item(zui_t *zui, zui_tabbed_t *tab, int x1, int y1,
|
||||
@ -506,7 +519,8 @@ static bool zarch_zui_list_item(zui_t *zui, zui_tabbed_t *tab, int x1, int y1,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zui->active_id != item_id && zui->pending_selection == item_id)
|
||||
if ( zui->active_id != item_id
|
||||
&& zui->pending_selection == item_id)
|
||||
set_active_id = true;
|
||||
}
|
||||
|
||||
@ -542,7 +556,8 @@ static void zarch_zui_tabbed_begin(zui_t *zui, zui_tabbed_t *tab, int x, int y)
|
||||
tab->tabline_size = 60 + 4;
|
||||
}
|
||||
|
||||
static bool zarch_zui_tab(zui_t *zui, zui_tabbed_t *tab, const char *label, unsigned tab_id)
|
||||
static bool zarch_zui_tab(zui_t *zui, zui_tabbed_t *tab,
|
||||
const char *label, unsigned tab_id)
|
||||
{
|
||||
bool active;
|
||||
int x1, y1, x2, y2;
|
||||
@ -656,7 +671,8 @@ static void zarch_zui_render_lay_root_load_free(zui_t *zui)
|
||||
zui->load_dlist = NULL;
|
||||
}
|
||||
|
||||
static void zarch_zui_render_lay_root_load_set_new_path(zui_t *zui, const char *newpath)
|
||||
static void zarch_zui_render_lay_root_load_set_new_path(zui_t *zui,
|
||||
const char *newpath)
|
||||
{
|
||||
if (!zui)
|
||||
return;
|
||||
@ -685,23 +701,29 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
core_info_t *core_info = NULL;
|
||||
core_info_ctl(CORE_INFO_CTL_CURRENT_CORE_GET, &core_info);
|
||||
|
||||
zui->load_dlist = dir_list_new(zui->load_cwd, core_info->supported_extensions, true, true);
|
||||
zui->load_dlist = dir_list_new(zui->load_cwd,
|
||||
core_info->supported_extensions, true, true);
|
||||
dir_list_sort(zui->load_dlist, true);
|
||||
zui->load_dlist_first = 0;
|
||||
}
|
||||
|
||||
cwd_offset = min(strlen(zui->load_cwd), 60);
|
||||
|
||||
zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15, tabbed->tabline_size + 5 + 41, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]);
|
||||
zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15,
|
||||
tabbed->tabline_size + 5 + 41,
|
||||
&zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]);
|
||||
|
||||
if (zarch_zui_button(zui, zui->width - 290 - 129, tabbed->tabline_size + 5, "Home"))
|
||||
if (zarch_zui_button(zui, zui->width - 290 - 129,
|
||||
tabbed->tabline_size + 5, "Home"))
|
||||
zarch_zui_render_lay_root_load_free(zui);
|
||||
|
||||
if (zui->load_dlist)
|
||||
{
|
||||
fill_pathname_parent_dir(parent_dir, zui->load_cwd, sizeof(parent_dir));
|
||||
fill_pathname_parent_dir(parent_dir,
|
||||
zui->load_cwd, sizeof(parent_dir));
|
||||
if (!string_is_empty(parent_dir) &&
|
||||
zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73, " ..", 0, NULL /* TODO/FIXME */))
|
||||
zarch_zui_list_item(zui, tabbed, 0,
|
||||
tabbed->tabline_size + 73, " ..", 0, NULL /* TODO/FIXME */))
|
||||
{
|
||||
zarch_zui_render_lay_root_load_set_new_path(zui, parent_dir);
|
||||
}
|
||||
@ -713,7 +735,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
const char *basename = path_basename(zui->load_dlist->elems[i].data);
|
||||
const char *basename =
|
||||
path_basename(zui->load_dlist->elems[i].data);
|
||||
if (basename[0] != '.')
|
||||
break;
|
||||
skip++;
|
||||
@ -726,7 +749,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
else if (zui->load_dlist_first > (int)size - 5)
|
||||
zui->load_dlist_first = size - 5;
|
||||
|
||||
zui->load_dlist_first = min(max(zui->load_dlist_first, 0), size - 5 - skip);
|
||||
zui->load_dlist_first = min(max(zui->load_dlist_first, 0),
|
||||
size - 5 - skip);
|
||||
|
||||
for (i = skip + zui->load_dlist_first; i < size; ++i)
|
||||
{
|
||||
@ -747,7 +771,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
if (path_is_directory(path))
|
||||
strncat(label, "/", sizeof(label)-1);
|
||||
|
||||
if (zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73 + j * 54,
|
||||
if (zarch_zui_list_item(zui, tabbed, 0,
|
||||
tabbed->tabline_size + 73 + j * 54,
|
||||
label, i, NULL))
|
||||
{
|
||||
if (path_is_directory(path))
|
||||
@ -758,7 +783,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
|
||||
zui->pick_cores = NULL;
|
||||
zui->pick_supported = 0;
|
||||
strncpy(zui->pick_content, path, sizeof(zui->pick_content)-1);
|
||||
strncpy(zui->pick_content,
|
||||
path, sizeof(zui->pick_content)-1);
|
||||
|
||||
core_info_ctl(CORE_INFO_CTL_LIST_GET, &list);
|
||||
|
||||
@ -781,7 +807,8 @@ static int zarch_zui_render_lay_root_load(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zarch_zui_render_lay_root_collections(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
static int zarch_zui_render_lay_root_collections(
|
||||
zui_t *zui, zui_tabbed_t *tabbed)
|
||||
{
|
||||
if (zarch_zui_tab(zui, tabbed, "Collections", 2))
|
||||
{
|
||||
@ -791,7 +818,8 @@ static int zarch_zui_render_lay_root_collections(zui_t *zui, zui_tabbed_t *tabbe
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zarch_zui_render_lay_root_downloads(zui_t *zui, zui_tabbed_t *tabbed)
|
||||
static int zarch_zui_render_lay_root_downloads(
|
||||
zui_t *zui, zui_tabbed_t *tabbed)
|
||||
{
|
||||
if (zarch_zui_tab(zui, tabbed, "Download", 3))
|
||||
{
|
||||
@ -855,7 +883,8 @@ static int zarch_zui_render_lay_root(zui_t *zui)
|
||||
else
|
||||
zui->pending_selection = -1;
|
||||
|
||||
zarch_zui_push_quad(zui->width, zui->height, ZUI_BG_HILITE, &zui->ca, 0, 60, zui->width - 290 - 40, 60+4);
|
||||
zarch_zui_push_quad(zui->width, zui->height,
|
||||
ZUI_BG_HILITE, &zui->ca, 0, 60, zui->width - 290 - 40, 60+4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -923,7 +952,8 @@ static int zarch_zui_render_pick_core(zui_t *zui)
|
||||
|
||||
if (!zui->pick_supported)
|
||||
{
|
||||
zarch_zui_list_item(zui, &tabbed, 0, 54, "Content unsupported", 0, NULL /* TODO/FIXME */);
|
||||
zarch_zui_list_item(zui, &tabbed, 0, 54,
|
||||
"Content unsupported", 0, NULL /* TODO/FIXME */);
|
||||
zui->active_id = 0;
|
||||
return 1;
|
||||
}
|
||||
@ -999,7 +1029,8 @@ static void zarch_frame(void *data)
|
||||
|
||||
menu_display_ctl(MENU_DISPLAY_CTL_FONT_BIND_BLOCK, &zui->tmp_block);
|
||||
|
||||
zarch_zui_push_quad(zui->width, zui->height, ZUI_BG_SCREEN, &zui->ca, 0, 0, zui->width, zui->height);
|
||||
zarch_zui_push_quad(zui->width, zui->height, ZUI_BG_SCREEN,
|
||||
&zui->ca, 0, 0, zui->width, zui->height);
|
||||
zarch_zui_snow(zui, &zui->ca, zui->width, zui->height);
|
||||
|
||||
switch (layout)
|
||||
@ -1078,7 +1109,8 @@ static void *zarch_init(void **userdata)
|
||||
int unused;
|
||||
zui_t *zui = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
menu_handle_t *menu = (menu_handle_t*)calloc(1, sizeof(*menu));
|
||||
menu_handle_t *menu = (menu_handle_t*)
|
||||
calloc(1, sizeof(*menu));
|
||||
|
||||
if (!menu)
|
||||
goto error;
|
||||
@ -1112,7 +1144,8 @@ static void *zarch_init(void **userdata)
|
||||
|
||||
if (!string_is_empty(settings->menu.wallpaper))
|
||||
rarch_task_push_image_load(settings->menu.wallpaper,
|
||||
"cb_menu_wallpaper", menu_display_handle_wallpaper_upload, NULL);
|
||||
"cb_menu_wallpaper",
|
||||
menu_display_handle_wallpaper_upload, NULL);
|
||||
|
||||
zui->ca.allocated = 0;
|
||||
|
||||
@ -1276,18 +1309,22 @@ static bool zarch_menu_init_list(void *data)
|
||||
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
|
||||
|
||||
|
||||
strlcpy(info.label, menu_hash_to_str(MENU_VALUE_HISTORY_TAB), sizeof(info.label));
|
||||
strlcpy(info.label,
|
||||
menu_hash_to_str(MENU_VALUE_HISTORY_TAB), sizeof(info.label));
|
||||
|
||||
menu_entries_push(menu_stack, info.path, info.label, info.type, info.flags, 0);
|
||||
menu_entries_push(menu_stack,
|
||||
info.path, info.label, info.type, info.flags, 0);
|
||||
|
||||
#if 0
|
||||
menu_entries_increment_menu_stack();
|
||||
|
||||
strlcpy(info.label, menu_hash_to_str(MENU_VALUE_MAIN_MENU), sizeof(info.label));
|
||||
strlcpy(info.label,
|
||||
menu_hash_to_str(MENU_VALUE_MAIN_MENU), sizeof(info.label));
|
||||
|
||||
menu_stack = menu_entries_get_menu_stack_ptr(1);
|
||||
|
||||
menu_entries_push(menu_stack, info.path, info.label, info.type, info.flags, 0);
|
||||
menu_entries_push(menu_stack,
|
||||
info.path, info.label, info.type, info.flags, 0);
|
||||
#endif
|
||||
|
||||
event_cmd_ctl(EVENT_CMD_HISTORY_INIT, NULL);
|
||||
|
@ -126,11 +126,12 @@ static void menu_display_d3d_draw(void *data)
|
||||
draw->height = 1;
|
||||
|
||||
if (!mat)
|
||||
mat = (math_matrix_4x4*)menu_display_d3d_get_default_mvp();
|
||||
mat = (math_matrix_4x4*)
|
||||
menu_display_d3d_get_default_mvp();
|
||||
if (!draw->coords->vertex)
|
||||
draw->coords->vertex = &d3d_vertexes[0];
|
||||
draw->coords->vertex = &d3d_vertexes[0];
|
||||
if (!draw->coords->tex_coord)
|
||||
draw->coords->tex_coord = &d3d_tex_coords[0];
|
||||
draw->coords->tex_coord = &d3d_tex_coords[0];
|
||||
if (!draw->coords->lut_tex_coord)
|
||||
draw->coords->lut_tex_coord = &d3d_tex_coords[0];
|
||||
|
||||
|
@ -53,22 +53,24 @@ static void *menu_display_vk_get_default_mvp(void)
|
||||
return &vk->mvp_no_rot;
|
||||
}
|
||||
|
||||
static unsigned to_display_pipeline(enum menu_display_prim_type prim_type, bool blend)
|
||||
static unsigned to_display_pipeline(
|
||||
enum menu_display_prim_type prim_type, bool blend)
|
||||
{
|
||||
return ((prim_type == MENU_DISPLAY_PRIM_TRIANGLESTRIP) << 1) | (blend << 0);
|
||||
}
|
||||
|
||||
static void menu_display_vk_draw(void *data)
|
||||
{
|
||||
menu_display_ctx_draw_t *draw = (menu_display_ctx_draw_t*)data;
|
||||
struct vk_texture *texture;
|
||||
const float *vertex, *tex_coord, *color;
|
||||
math_matrix_4x4 *mat;
|
||||
struct vk_buffer_range range;
|
||||
struct vk_vertex *pv;
|
||||
unsigned i;
|
||||
|
||||
vk_t *vk = vk_get_ptr();
|
||||
struct vk_buffer_range range;
|
||||
struct vk_texture *texture = NULL;
|
||||
const float *vertex = NULL;
|
||||
const float *tex_coord = NULL;
|
||||
const float *color = NULL;
|
||||
math_matrix_4x4 *mat = NULL;
|
||||
struct vk_vertex *pv = NULL;
|
||||
menu_display_ctx_draw_t *draw = (menu_display_ctx_draw_t*)data;
|
||||
vk_t *vk = vk_get_ptr();
|
||||
if (!vk)
|
||||
return;
|
||||
|
||||
@ -120,7 +122,8 @@ static void menu_display_vk_draw(void *data)
|
||||
|
||||
{
|
||||
const struct vk_draw_triangles call = {
|
||||
vk->display.pipelines[to_display_pipeline(draw->prim_type, vk->display.blend)],
|
||||
vk->display.pipelines[
|
||||
to_display_pipeline(draw->prim_type, vk->display.blend)],
|
||||
texture,
|
||||
texture->default_smooth ? vk->samplers.linear : vk->samplers.nearest,
|
||||
mat,
|
||||
@ -179,14 +182,30 @@ static void menu_display_vk_draw_bg(void *data)
|
||||
|
||||
static void menu_display_vk_restore_clear_color(void)
|
||||
{
|
||||
//glClearColor(0.0f, 0.0f, 0.0f, 0.00f);
|
||||
}
|
||||
|
||||
static void menu_display_vk_clear_color(void *data)
|
||||
{
|
||||
(void)data;
|
||||
/* FIXME: This makes little sense in Vulkan.
|
||||
* We shouldn't be clearing mid-screen nilly willy. */
|
||||
VkClearRect rect;
|
||||
VkClearAttachment attachment = { VK_IMAGE_ASPECT_COLOR_BIT };
|
||||
menu_display_ctx_clearcolor_t *clearcolor =
|
||||
(menu_display_ctx_clearcolor_t*)data;
|
||||
|
||||
vk_t *vk = vk_get_ptr();
|
||||
if (!vk || !clearcolor)
|
||||
return;
|
||||
|
||||
attachment.clearValue.color.float32[0] = clearcolor->r;
|
||||
attachment.clearValue.color.float32[1] = clearcolor->g;
|
||||
attachment.clearValue.color.float32[2] = clearcolor->b;
|
||||
attachment.clearValue.color.float32[3] = clearcolor->a;
|
||||
|
||||
memset(&rect, 0, sizeof(rect));
|
||||
rect.rect.extent.width = vk->context->swapchain_width;
|
||||
rect.rect.extent.height = vk->context->swapchain_height;
|
||||
rect.layerCount = 1;
|
||||
|
||||
vkCmdClearAttachments(vk->cmd, 1, &attachment, 1, &rect);
|
||||
}
|
||||
|
||||
static const float *menu_display_vk_get_tex_coords(void)
|
||||
|
@ -628,7 +628,7 @@ static int menu_displaylist_parse_system_info(menu_displaylist_info_t *info)
|
||||
if (gfx_ctx_ctl(GFX_CTL_GET_METRICS, &metrics))
|
||||
{
|
||||
snprintf(tmp, sizeof(tmp), "%s: %.2f",
|
||||
menu_hash_to_str(MENU_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_WIDTH), val);
|
||||
menu_hash_to_str(MENU_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_HEIGHT), val);
|
||||
menu_entries_push(info->list, tmp, "",
|
||||
MENU_SETTINGS_CORE_INFO_NONE, 0, 0);
|
||||
}
|
||||
|
@ -71,3 +71,4 @@ HAVE_QT=no # QT companion support
|
||||
HAVE_XSHM=no # XShm video driver support (disabled because it's just a dummied out stub)
|
||||
HAVE_CHEEVOS=yes # Disable Retro Achievements
|
||||
HAVE_VULKAN=auto # Enable Vulkan support
|
||||
C89_VULKAN=no
|
||||
|
@ -1262,7 +1262,6 @@ static int rarch_main_init(int argc, char *argv[])
|
||||
event_cmd_ctl(EVENT_CMD_CONTROLLERS_INIT, NULL);
|
||||
event_cmd_ctl(EVENT_CMD_RECORD_INIT, NULL);
|
||||
event_cmd_ctl(EVENT_CMD_CHEATS_INIT, NULL);
|
||||
event_cmd_ctl(EVENT_CMD_REMAPPING_INIT, NULL);
|
||||
event_cmd_ctl(EVENT_CMD_SAVEFILES_INIT, NULL);
|
||||
event_cmd_ctl(EVENT_CMD_SET_PER_GAME_RESOLUTION, NULL);
|
||||
|
||||
|
@ -1446,11 +1446,11 @@ int runloop_iterate(unsigned *sleep_ms)
|
||||
unlock_autosave();
|
||||
#endif
|
||||
|
||||
if (!settings->fastforward_ratio)
|
||||
return 0;
|
||||
#ifdef HAVE_MENU
|
||||
end:
|
||||
#endif
|
||||
if (!settings->fastforward_ratio)
|
||||
return 0;
|
||||
|
||||
current = retro_get_time_usec();
|
||||
target = frame_limit_last_time +
|
||||
|
Loading…
x
Reference in New Issue
Block a user