Skip to content

Instantly share code, notes, and snippets.

@thatcosmonaut
Last active July 2, 2024 18:26
Show Gist options
  • Save thatcosmonaut/16c3dc5259f6d5ddb7a685f789fe6f23 to your computer and use it in GitHub Desktop.
Save thatcosmonaut/16c3dc5259f6d5ddb7a685f789fe6f23 to your computer and use it in GitHub Desktop.
Automated backporting from SDL3 -> Refresh
import argparse
sdl_license_text = """/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/"""
refresh_license_text = """/* Refresh - a cross-platform hardware-accelerated graphics library with modern capabilities
*
* Copyright (c) 2020-2024 Evan Hemsley
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
* Evan "cosmonaut" Hemsley <evan@moonside.games>
*
*/
"""
sdl_alternate_license_text = '''/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/'''
sdl_even_more_alternate_license_text = '''/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/'''
include_h_find = '''#define SDL_GPU_H
#include <SDL3/SDL_stdinc.h>
'''
include_h_replace = '''#define REFRESH_H
#include "SDL.h"
#include <SDL_stdinc.h>
#ifdef _WIN32
#define REFRESHAPI __declspec(dllexport)
#define REFRESHCALL __cdecl
#else
#define REFRESHAPI
#define REFRESHCALL
#endif
/* -Wpedantic nameless union/struct silencing */
#ifndef REFRESHNAMELESS
#ifdef __GNUC__
#define REFRESHNAMELESS __extension__
#else
#define REFRESHNAMELESS
#endif /* __GNUC__ */
#endif /* REFRESHNAMELESS */
'''
create_device_find = ''' SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL) {
SDL_SetError("Video subsystem not initialized");
return NULL;
}
selectedBackend = SDL_GpuSelectBackend(_this, preferredBackends);
'''
create_device_replace = '''
selectedBackend = Refresh_SelectBackend(preferredBackends);
'''
vulkan_c_app_info_find = ''' appInfo.pEngineName = "SDLGPU";
appInfo.engineVersion = SDL_VERSION;'''
vulkan_c_app_info_replace = ''' appInfo.pEngineName = "Refresh";
appInfo.engineVersion = ((2 * 100 * 100) + (0 * 100) + (0));'''
vulkan_c_include_find = '''#define VK_NO_PROTOTYPES
#include "../../video/khronos/vulkan/vulkan.h"
#include "SDL_hashtable.h"
#include <SDL3/SDL_vulkan.h>
#include "../SDL_gpu_driver.h"'''
vulkan_c_include_replace = '''#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>
#include <SDL.h>
#include <SDL_video.h>
#include <SDL_vulkan.h>
#include "Refresh_driver.h"'''
vulkan_c_create_surface_find = ''' if (!SDL_Vulkan_CreateSurface(
dummyWindowHandle,
renderer->instance,
NULL, /* FIXME: VAllocationCallbacks */
&surface)) {
'''
vulkan_c_create_surface_replace = ''' if (!SDL_Vulkan_CreateSurface(
dummyWindowHandle,
renderer->instance,
&surface)) {
'''
vulkan_c_create_window_find = ''' dummyWindowHandle = SDL_CreateWindow(
"SDL_Gpu Vulkan",
128,
128,
SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN);'''
vulkan_c_create_window_replace = ''' dummyWindowHandle = SDL_CreateWindow(
"Refresh Vulkan",
0, 0,
128, 128,
SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN);'''
vulkan_c_dummy_surface_find = ''' if (_this->Vulkan_CreateSurface(
_this,
window,
renderer->instance,
NULL,
&surface) < 0) {
return SDL_FALSE;
}'''
vulkan_c_dummy_surface_replace = ''' if (!SDL_Vulkan_CreateSurface(
window,
renderer->instance,
&surface)) {
return SDL_FALSE;
}'''
vulkan_c_destroy_surface_one_indent_find = ''' SDL_Vulkan_DestroySurface(
renderer->instance,
surface,
NULL);'''
vulkan_c_destroy_surface_one_indent_replace = ''' renderer->vkDestroySurfaceKHR(
renderer->instance,
surface,
NULL);'''
vulkan_c_destroy_surface_two_indent_find = ''' SDL_Vulkan_DestroySurface(
renderer->instance,
surface,
NULL);'''
vulkan_c_destroy_surface_two_indent_replace = ''' renderer->vkDestroySurfaceKHR(
renderer->instance,
surface,
NULL);'''
vulkan_c_assert_video_device_find = ''' SDL_assert(_this && _this->Vulkan_CreateSurface);
'''
vulkan_c_assert_video_device_replace = ''
vulkan_c_create_surface_from_video_device_find = ''' if (_this->Vulkan_CreateSurface(
_this,
windowData->window,
renderer->instance,
NULL, /* FIXME: VAllocationCallbacks */
&swapchainData->surface) < 0) {
SDL_free(swapchainData);
SDL_LogError(
SDL_LOG_CATEGORY_APPLICATION,
"Vulkan_CreateSurface failed: %s",
SDL_GetError());
return SDL_FALSE;
}'''
vulkan_c_create_surface_from_video_device_replace = ''' if (!SDL_Vulkan_CreateSurface(
windowData->window,
renderer->instance,
&swapchainData->surface)) {
SDL_free(swapchainData);
SDL_LogError(
SDL_LOG_CATEGORY_APPLICATION,
"Vulkan_CreateSurface failed: %s",
SDL_GetError());
return SDL_FALSE;
}'''
vulkan_c_create_surface_null_check_find = ''' if (_this->Vulkan_CreateSurface == NULL) {
return SDL_FALSE;
}
'''
vulkan_c_create_surface_null_check_replace = ''
vulkan_c_original_extension_names_find = ''' const char *const *originalInstanceExtensionNames;
'''
vulkan_c_original_extension_names_replace = ''
vulkan_c_get_instance_extension_find = ''' originalInstanceExtensionNames = SDL_Vulkan_GetInstanceExtensions(&instanceExtensionCount);
if (!originalInstanceExtensionNames) {
SDL_LogError(
SDL_LOG_CATEGORY_APPLICATION,
"SDL_Vulkan_GetInstanceExtensions(): getExtensionCount: %s",
SDL_GetError());
return 0;
}'''
vulkan_c_get_instance_extension_replace = ''' if (!SDL_Vulkan_GetInstanceExtensions(
(SDL_Window *)deviceWindowHandle,
&instanceExtensionCount,
NULL)) {
SDL_LogError(
SDL_LOG_CATEGORY_APPLICATION,
"SDL_Vulkan_GetInstanceExtensions(): getExtensionCount: %s",
SDL_GetError());
return SDL_FALSE;
}'''
vulkan_c_copy_instance_extension_find = ''' SDL_memcpy(instanceExtensionNames, originalInstanceExtensionNames, instanceExtensionCount * sizeof(const char *));
'''
vulkan_c_copy_instance_extension_replace = '''
if (!SDL_Vulkan_GetInstanceExtensions(
deviceWindowHandle,
&instanceExtensionCount,
instanceExtensionNames)) {
SDL_LogError(
SDL_LOG_CATEGORY_APPLICATION,
"SDL_Vulkan_GetInstanceExtensions(): %s",
SDL_GetError());
}
'''
vulkan_c_create_surface_abi_break_find = ''' if (SDL_Vulkan_CreateSurface(
dummyWindowHandle,
renderer->instance,
NULL, /* FIXME: VAllocationCallbacks */
&surface) < 0) {'''
vulkan_c_create_surface_abi_break_replace = ''' if (!SDL_Vulkan_CreateSurface(
dummyWindowHandle,
renderer->instance,
&surface)) {'''
vulkan_c_fetch_window_data_find = ''' SDL_PropertiesID properties = SDL_GetWindowProperties(window);
return (WindowData *)SDL_GetProperty(properties, WINDOW_PROPERTY_DATA, NULL);
'''
vulkan_c_fetch_window_data_replace = ''' return (WindowData *)SDL_GetWindowData(window, WINDOW_PROPERTY_DATA);
'''
vulkan_c_set_window_data_find = '''SDL_SetProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);'''
vulkan_c_set_window_data_replace = '''SDL_SetWindowData(window, WINDOW_PROPERTY_DATA, windowData);'''
vulkan_c_clear_window_data_find = '''SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);'''
vulkan_c_clear_window_data_replace = '''SDL_SetWindowData(window, WINDOW_PROPERTY_DATA, NULL);'''
vulkan_c_thread_id_find = ''' SDL_ThreadID threadID = SDL_GetCurrentThreadID();
'''
vulkan_c_thread_id_replace = ''' SDL_threadID threadID = SDL_ThreadID();
'''
vulkan_c_sync_window_find = ''' /* Sync now to be sure that our swapchain size is correct */
SDL_SyncWindow(windowData->window);'''
vulkan_c_sync_window_replace = ''' /* Should sync now to be sure that our swapchain size is correct */
/* TODO: how to backport SyncWindow? */
'''
vulkan_c_prepare_driver_find = '''static Uint8 VULKAN_PrepareDriver(SDL_VideoDevice *_this)'''
vulkan_c_prepare_driver_replace = '''static SDL_bool VULKAN_PrepareDriver()'''
d3d11_c_dxgi_find = '''#ifdef _WIN32
dxgiHandle = (HWND)SDL_GetProperty(SDL_GetWindowProperties(windowData->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
#else'''
d3d11_c_dxgi_replace = '''#ifdef _WIN32
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo((SDL_Window *)windowData->window, &info);
dxgiHandle = info.info.win.window;
#else
'''
d3d11_c_include_syswm_find = '''#include <dxgidebug.h>'''
d3d11_c_include_syswm_replace = '''#include <dxgidebug.h>
#ifdef _WIN32
#include <SDL_syswm.h>
#endif'''
d3d11_c_fetch_window_data_find = ''' SDL_PropertiesID properties = SDL_GetWindowProperties(window);
return (D3D11WindowData *)SDL_GetProperty(properties, WINDOW_PROPERTY_DATA, NULL);
'''
d3d11_c_fetch_window_data_replace = ''' return (D3D11WindowData *)SDL_GetWindowData(window, WINDOW_PROPERTY_DATA);
'''
d3d11_c_prepare_driver_find = '''static Uint8 D3D11_PrepareDriver(SDL_VideoDevice *_this)'''
d3d11_c_prepare_driver_replace = '''static SDL_bool D3D11_PrepareDriver()'''
metal_m_fetch_window_data_find = ''' SDL_PropertiesID properties = SDL_GetWindowProperties(window);
return (MetalWindowData *)SDL_GetProperty(properties, WINDOW_PROPERTY_DATA, NULL);
'''
metal_m_fetch_window_data_replace = ''' return (MetalWindowData*) SDL_GetWindowData(window, WINDOW_PROPERTY_DATA);
'''
metal_m_prepare_driver_find = '''static SDL_bool METAL_PrepareDriver(SDL_VideoDevice *_this)
{
/* FIXME: Add a macOS / iOS version check! Maybe support >= 10.14? */
return (_this->Metal_CreateView != NULL);
}'''
metal_m_prepare_driver_replace = '''static SDL_bool METAL_PrepareDriver()
{
/* FIXME: Add a macOS / iOS version check! Maybe support >= 10.14? */
return SDL_TRUE;
}'''
filepaths = [
['include/SDL3/SDL_gpu.h', 'include/Refresh.h'],
['src/gpu/SDL_gpu.c', 'src/Refresh.c'],
['src/gpu/SDL_gpu_driver.h', 'src/Refresh_driver.h'],
['src/gpu/SDL_gpu_spirv_c.h', 'src/Refresh_spirv_c.h'],
['src/gpu/SDL_gpu_spirv.c', 'src/Refresh_spirv.c'],
['src/gpu/vulkan/SDL_gpu_vulkan.c', 'src/vulkan/Refresh_vulkan.c'],
['src/gpu/metal/SDL_gpu_metal.m', 'src/metal/Refresh_metal.m'],
['src/gpu/d3d11/SDL_gpu_d3d11.c', 'src/d3d11/Refresh_d3d11.c'],
]
def backport_to_refresh(sdl_dir, refresh_dir, sdl_filepath, refresh_filepath):
sdl_filepath = sdl_dir + sdl_filepath
refresh_filepath = refresh_dir + refresh_filepath
with open(sdl_filepath, 'r') as file:
filedata = file.read()
# license and include fixups
filedata = filedata.replace(sdl_license_text, refresh_license_text)
filedata = filedata.replace(sdl_alternate_license_text, refresh_license_text)
filedata = filedata.replace(sdl_even_more_alternate_license_text, refresh_license_text)
filedata = filedata.replace('#include "SDL_internal.h"\n', '')
# include .h fixups
filedata = filedata.replace(include_h_find, include_h_replace)
filedata = filedata.replace('\n/**\n * \\file SDL_gpu.h\n *\n * Include file for SDL GPU API functions\n */\n\n', '')
filedata = filedata.replace('extern SDL_DECLSPEC', 'REFRESHAPI')
filedata = filedata.replace('SDLCALL ', '')
filedata = filedata.replace('since SDL 3.x.x', 'since Refresh 2.0.0')
# driver.h fixups
filedata = filedata.replace('Uint8 (*PrepareDriver)(SDL_VideoDevice *_this)', 'SDL_bool (*PrepareDriver)()')
filedata = filedata.replace('#define SDL_GPU_DRIVER_H\n\n', '#define REFRESH_DRIVER_H\n\n#include "Refresh.h"\n\n')
filedata = filedata.replace('#include "../video/SDL_sysvideo.h"\n\n', '')
# Refresh.c fixups
filedata = filedata.replace(create_device_find, create_device_replace)
# vulkan.c fixups
filedata = filedata.replace(vulkan_c_include_find, vulkan_c_include_replace)
filedata = filedata.replace(vulkan_c_app_info_find, vulkan_c_app_info_replace)
filedata = filedata.replace(vulkan_c_create_surface_find, vulkan_c_create_surface_replace)
filedata = filedata.replace(vulkan_c_create_window_find, vulkan_c_create_window_replace)
filedata = filedata.replace(vulkan_c_dummy_surface_find, vulkan_c_dummy_surface_replace)
filedata = filedata.replace(vulkan_c_assert_video_device_find, vulkan_c_assert_video_device_replace)
filedata = filedata.replace(vulkan_c_create_surface_from_video_device_find, vulkan_c_create_surface_from_video_device_replace)
filedata = filedata.replace(vulkan_c_create_surface_null_check_find, vulkan_c_create_surface_null_check_replace)
filedata = filedata.replace(vulkan_c_destroy_surface_one_indent_find, vulkan_c_destroy_surface_one_indent_replace)
filedata = filedata.replace(vulkan_c_destroy_surface_two_indent_find, vulkan_c_destroy_surface_two_indent_replace)
filedata = filedata.replace(vulkan_c_original_extension_names_find, vulkan_c_original_extension_names_replace)
filedata = filedata.replace(vulkan_c_get_instance_extension_find, vulkan_c_get_instance_extension_replace)
filedata = filedata.replace(vulkan_c_copy_instance_extension_find, vulkan_c_copy_instance_extension_replace)
filedata = filedata.replace(vulkan_c_create_surface_abi_break_find, vulkan_c_create_surface_abi_break_replace)
filedata = filedata.replace(vulkan_c_fetch_window_data_find, vulkan_c_fetch_window_data_replace)
filedata = filedata.replace(vulkan_c_set_window_data_find, vulkan_c_set_window_data_replace)
filedata = filedata.replace(vulkan_c_clear_window_data_find, vulkan_c_clear_window_data_replace)
filedata = filedata.replace(vulkan_c_sync_window_find, vulkan_c_sync_window_replace)
filedata = filedata.replace(vulkan_c_thread_id_find, vulkan_c_thread_id_replace)
filedata = filedata.replace(vulkan_c_sync_window_find, vulkan_c_sync_window_replace)
filedata = filedata.replace(vulkan_c_prepare_driver_find, vulkan_c_prepare_driver_replace)
# d3d11.c fixups
filedata = filedata.replace(d3d11_c_include_syswm_find, d3d11_c_include_syswm_replace)
filedata = filedata.replace(d3d11_c_dxgi_find, d3d11_c_dxgi_replace)
filedata = filedata.replace(d3d11_c_fetch_window_data_find, d3d11_c_fetch_window_data_replace)
filedata = filedata.replace(d3d11_c_prepare_driver_find, d3d11_c_prepare_driver_replace)
# metal.m fixups
filedata = filedata.replace(metal_m_fetch_window_data_find, metal_m_fetch_window_data_replace)
filedata = filedata.replace(metal_m_prepare_driver_find, metal_m_prepare_driver_replace)
# namespace fixups
filedata = filedata.replace('SDL_Gpu', 'Refresh_')
filedata = filedata.replace('SDL_gpu_', 'Refresh_')
filedata = filedata.replace('SDL_GPU_', 'REFRESH_')
filedata = filedata.replace('SDLTo', 'RefreshTo')
# video device fixups
filedata = filedata.replace('SDL_VideoDevice *_this = SDL_GetVideoDevice();\n', '')
filedata = filedata.replace('_this = SDL_GetVideoDevice();', '')
filedata = filedata.replace('SDL_VideoDevice *_this, ', '')
filedata = filedata.replace('SDL_VideoDevice *_this;', '')
filedata = filedata.replace('SDL_VideoDevice *_this', '')
filedata = filedata.replace('_this', '')
# hint fixups
filedata = filedata.replace('"SDL_HINT_GPU_BACKEND %s', '"REFRESH_HINT_BACKEND %s')
filedata = filedata.replace('SDL_HINT_GPU_BACKEND', '"REFRESH_HINT_BACKEND"')
# SDL3 -> SDL2 fixups
filedata = filedata.replace('SDL_AtomicInt', 'SDL_atomic_t')
filedata = filedata.replace('SDL_Mutex', 'SDL_mutex')
filedata = filedata.replace('SDL_ThreadID', 'SDL_threadID')
filedata = filedata.replace('SDL_threadID()', 'SDL_ThreadID()') # lol
with open(refresh_filepath, 'w') as file:
file.write(filedata)
parser = argparse.ArgumentParser("refresh_backport")
parser.add_argument("sdl_dir")
parser.add_argument("refresh_dir")
args = parser.parse_args()
for filepath in filepaths:
backport_to_refresh(args.sdl_dir, args.refresh_dir, filepath[0], filepath[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment