Compare commits

...

70 Commits

Author SHA1 Message Date
Coder2 cbf1f2529c
Merge 973260a851 into 9ed83e71f6 2025-06-23 10:30:58 +02:00
Sam Lantinga 9ed83e71f6 Fixed memory leaks in KMSDRM property handling
Also cleaned up the code for consistency so it's easy to see memory leaks here.
2025-06-22 21:33:52 -07:00
SDL Wiki Bot 603118c340 Sync SDL3 wiki -> header
[ci skip]
2025-06-23 04:18:24 +00:00
Sam Lantinga aa4f916b71 Renamed SDL_PROP_AUDIOSTREAM_KEEP_ON_SHUTDOWN_BOOLEAN to SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN 2025-06-22 21:17:06 -07:00
SDL Wiki Bot 6cfe211142 Sync SDL3 wiki -> header
[ci skip]
2025-06-23 04:07:09 +00:00
Ryan C. Gordon 274aa0242e
audio: Let apps save an audio stream from destruction during SDL_Quit(). (#13244)
This is a special-case piece of functionality, generally these are expected
to go away during shutdown, but maybe someone is switching between audio
subsystems or something...
2025-06-22 21:06:15 -07:00
Ozkan Sezer af8bee2dd1 alsa: change an SDL_LogError into SDL_LogDebug.
it is informational only and seeing ERROR on the terminal was confusing
2025-06-22 21:04:44 -07:00
Marcin Serwin bbc674b9e7 test: Fix resource paths in testtray
Signed-off-by: Marcin Serwin <marcin@serwin.dev>
2025-06-22 21:03:37 -07:00
mitchellcairns 796961acec
Resolve bug for calibration Nintendo Switch Pro Controller (#13260)
Resolves a bug which prevents the stored calibration data from loading, only allowing loading of factory-installed calibration data
2025-06-22 20:59:15 -07:00
Mitch Cairns 3a6f9e01f8 Fixed Nintendo Switch thumbstick calibration 2025-06-22 15:26:49 -07:00
Coder2 973260a851 OpenHarmony Port (renderer) 2025-06-22 06:10:31 +08:00
Jack253-png e7fdb9c19d
Harmony port: workflow
[sdl-ci-filter harmony-*]
2025-06-08 08:19:59 +08:00
Jack253-png e7e0bd2768
Harmony port: workflow fix [sdl-ci-filter harmony-*] 2025-06-08 08:14:10 +08:00
Jack253-png 38a7790ae9
Harmony port: workflow fix [sdl-ci-filter harmony-*] 2025-06-08 08:01:32 +08:00
Jack253-png b8f497f720
Harmony port: workflow fix [sdl-ci-filter harmony] 2025-06-08 08:00:34 +08:00
Jack253-png d7a01e6778
Harmony port: workflow fix [sdl-ci-filter harmony] 2025-06-08 07:57:03 +08:00
Jack253-png e7bcd9a9ae
Harmony port: workflow fix [sdl-ci-filter harmony] 2025-06-08 07:52:03 +08:00
Jack253-png a649753853
Harmony port: format 2025-06-08 07:15:06 +08:00
Coder2 29c6d182e2
Update create-test-plan.py 2025-06-08 07:03:05 +08:00
Coder2 376aa5dfd7
Update create-test-plan.py 2025-06-08 06:57:05 +08:00
Coder2 2b5815ad72
Update CMakeLists.txt 2025-06-08 06:50:03 +08:00
Coder2 f6147e0a81
Update SDL_ohos.c 2025-06-08 06:46:45 +08:00
Coder2 0f4c8f597f
Update create-test-plan.py 2025-06-08 06:38:39 +08:00
Coder2 56cea28cbd
Update CMakeLists.txt 2025-06-08 06:32:18 +08:00
Coder2 4781c60983
Update generic.yml 2025-06-08 06:30:03 +08:00
Coder2 cf696785e8
Update create-test-plan.py 2025-06-08 06:29:31 +08:00
Jack253-png 9c3e5f2925
Harmony port: pthread enable 2025-06-07 06:19:37 +08:00
Jack253-png a886df9c12
Merge branch 'main' of github.com:libsdl-org/SDL 2025-06-07 06:17:29 +08:00
Starcloudsea ec588468a0 Harmony port: fix napi call 2025-06-02 18:46:59 +08:00
Coder2 05f4fa7752
Merge branch 'libsdl-org:main' into main 2025-06-02 15:32:06 +08:00
Jack253-png 35ea9148b2
Harmony port: fix 2025-06-02 09:28:10 +08:00
Jack253-png a4b48d3e2e
Harmony port: surface destroy 2025-06-02 09:19:33 +08:00
Jack253-png 01fed59802
Harmony port: fix 2025-06-01 18:35:06 +08:00
Jack253-png 167fe8bdb0
Harmony port: fix 2025-06-01 18:30:05 +08:00
Jack253-png 048a59b21b
Harmony port: fix 2025-06-01 18:24:49 +08:00
Jack253-png e91906683c
Harmony port: fix 2025-06-01 18:19:35 +08:00
Jack253-png c951070638
Harmony port: touch event 2025-06-01 18:13:48 +08:00
Jack253-png 56ccf29d3c
Harmony port: napi shell 2025-06-01 15:18:20 +08:00
Jack253-png 9605a66f85
Harmony port: fix 2025-06-01 11:32:34 +08:00
Jack253-png cf3353a914
Harmony port: call test 2025-06-01 11:27:34 +08:00
Starcloudsea 27df3404d9 Harmony port: video device 2025-06-01 09:46:50 +08:00
Jack253-png d4039d3d66
Harmony port: entrypoint 2025-06-01 09:28:52 +08:00
Jack253-png 04e80426fb
Harmony port: entrypoint 2025-06-01 09:22:44 +08:00
Jack253-png d031a499f0
Harmony port: entrypoint 2025-06-01 09:16:28 +08:00
Jack253-png b182ae0f8b
Harmony port: entrypoint 2025-06-01 08:31:51 +08:00
Jack253-png a9109972bf
Harmony port: entrypoint 2025-06-01 08:25:47 +08:00
Jack253-png 0f2b280c76
Harmony port: entrypoint 2025-06-01 08:14:40 +08:00
Jack253-png 231ed48aab
Harmony port: review changes 2025-06-01 07:52:13 +08:00
Jack253-png 298581d269
Harmony port: review changes 2025-06-01 07:41:02 +08:00
Jack253-png c99ae6e155
Harmony port: review changes 2025-06-01 07:36:26 +08:00
Jack253-png 590509b34d
Harmony port: review changes 2025-06-01 07:22:00 +08:00
Jack253-png 4a0d0685ee
Harmony port: review changes 2025-06-01 06:48:06 +08:00
Jack253-png af9601874e
Harmony port: napi callback shell 2025-06-01 05:59:37 +08:00
Jack253-png 2570e9ac56
Harmony port: video drv fix 2025-06-01 05:59:36 +08:00
Jack253-png dc28e96952
Harmony port: keyboard event 2025-06-01 05:59:36 +08:00
Jack253-png 9e61fcb7f1
Harmony port: egl/gles lib 2025-06-01 05:59:36 +08:00
Jack253-png 8b6c78c688
Harmony port: window creation 2025-06-01 05:59:36 +08:00
Jack253-png cd0d25ca11
Harmony port: video library 2025-06-01 05:59:35 +08:00
Jack253-png 1e75f1fa6c
Harmony port: video vulkan library 2025-06-01 05:59:35 +08:00
Jack253-png e339bde505
Harmony port: video vulkan library 2025-06-01 05:59:35 +08:00
Jack253-png 4f5fcf6a16
Harmony port: video vulkan library & disable version test 2025-06-01 05:59:35 +08:00
Jack253-png f25cbb135c
Harmony port: video vulkan library & disable version test 2025-06-01 05:59:35 +08:00
Jack253-png 845ba7d5ce
Harmony port: video vulkan library & disable version test 2025-06-01 05:59:34 +08:00
Jack253-png addb748c64
Harmony port: disable lib version suffix 2025-06-01 05:59:34 +08:00
Jack253-png 1c48676f4f
Harmony port: window fetching 2025-06-01 05:59:34 +08:00
Jack253-png 8f0b9c1151
Harmony port: Workflows (fix script error) 2025-06-01 05:59:32 +08:00
Jack253-png 95ccfa69e5
Harmony port: Workflows (fix script error) 2025-06-01 05:58:14 +08:00
Jack253-png 15cbc266ec
Harmony port: Workflows (fix script error) 2025-06-01 05:58:13 +08:00
Jack253-png a6ebc6a63a
Harmony port: Workflows (disable other plats) 2025-06-01 05:58:13 +08:00
Jack253-png 462476f150
Harmony port: Workflows 2025-06-01 05:58:08 +08:00
35 changed files with 4397 additions and 202 deletions

View File

@ -0,0 +1,33 @@
name: 'Setup Harmony toolchain'
inputs:
version:
description: 'Harmony version'
default: '5.0.0-Release'
runs:
using: 'composite'
steps:
- uses: actions/cache/restore@v4
id: restore-cache
with:
path: /opt/native
key: harmony-${{ inputs.version }}
- name: Download Harmony toolchain
if: ${{ !steps.restore-cache.outputs.cache-hit }}
shell: bash
run: |
wget https://repo.huaweicloud.com/openharmony/os/${{ inputs.version }}/ohos-sdk-windows_linux-public.tar.gz
tar -zxvf ohos-sdk-windows_linux-public.tar.gz
mkdir -p /opt
unzip linux/native*.zip -d /opt
- uses: actions/cache/save@v4
if: ${{ !steps.restore-cache.outputs.cache-hit }}
with:
path: /opt/native
key: harmony-${{ inputs.version }}
- name: 'Set output vars'
id: final
shell: bash
run: |
echo "HARMONY_NATIVE_SDK=/opt/native" >> $GITHUB_OUTPUT

View File

@ -55,6 +55,7 @@ class SdlPlatform(Enum):
FreeBSD = "freebsd"
NetBSD = "netbsd"
NGage = "ngage"
Harmony = "harmony"
class Msys2Platform(Enum):
@ -98,6 +99,7 @@ class JobSpec:
clang_cl: bool = False
gdk: bool = False
vita_gles: Optional[VitaGLES] = None
harmony_arch: Optional[str] = None
JOB_SPECS = {
@ -141,6 +143,9 @@ JOB_SPECS = {
"netbsd": JobSpec(name="NetBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.NetBSD, artifact="SDL-netbsd-x64", ),
"freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ),
"ngage": JobSpec(name="N-Gage", os=JobOs.WindowsLatest, platform=SdlPlatform.NGage, artifact="SDL-ngage", ),
"harmony-arm64": JobSpec(name="Harmony (Arm64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-arm64", harmony_arch="arm64-v8a"),
"harmony-arm32": JobSpec(name="Harmony (Arm32)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-arm32", harmony_arch="armeabi-v7a"),
"harmony-x86_64": JobSpec(name="Harmony (x86-64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-x86_64", harmony_arch="x86_64"),
}
@ -757,6 +762,17 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
job.setup_gage_sdk_path = "C:/ngagesdk"
job.cmake_toolchain_file = "C:/ngagesdk/cmake/ngage-toolchain.cmake"
job.test_pkg_config = False
case SdlPlatform.Harmony:
job.cmake_arguments.extend((
f"-DOHOS_ARCH={spec.harmony_arch}",
"-DCMAKE_TOOLCHAIN_FILE=/opt/native/build/cmake/ohos.toolchain.cmake",
"-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=1"
))
job.shared_lib = SharedLibType.SO
job.static_lib = StaticLibType.A
job.run_tests = False
job.test_pkg_config = False
job.werror = False
case _:
raise ValueError(f"Unsupported platform={spec.platform}")

View File

@ -51,6 +51,9 @@ jobs:
uses: ./.github/actions/setup-msvc-libusb
with:
arch: ${{ matrix.platform.setup-libusb-arch }}
- name: 'Set up Harmony toolchain'
if: ${{ matrix.platform.platform == 'harmony' }}
uses: ./.github/actions/setup-harmony-toolchain
- uses: mymindstorm/setup-emsdk@v14
if: ${{ matrix.platform.platform == 'emscripten' }}
with:

View File

@ -1502,7 +1502,49 @@ if(ANDROID)
endif()
endif()
endif()
elseif(OHOS)
# disable warnings from the toolchain
sdl_compile_options(PRIVATE "-Wno-unused-command-line-argument")
sdl_link_dependency(ohos LIBS ace_napi.z hilog_ndk.z ace_ndk.z rawfile.z pixelmap_ndk.z)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/ohos/*.c")
if(SDL_VIDEO)
set(SDL_VIDEO_DRIVER_OHOS 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/ohos/*.c")
set(HAVE_SDL_VIDEO TRUE)
set(SDL_VULKAN ON)
set(HAVE_VULKAN ON)
set(SDL_VIDEO_VULKAN ON)
set(SDL_VIDEO_RENDER_VULKAN 1)
set(HAVE_RENDER_VULKAN TRUE)
add_definitions(-DVK_USE_PLATFORM_OHOS=1)
if(SDL_OPENGLES)
set(SDL_VIDEO_OPENGL_EGL 1)
set(HAVE_OPENGLES TRUE)
set(SDL_VIDEO_OPENGL_ES2 1)
set(SDL_VIDEO_RENDER_OGL_ES2 1)
sdl_link_dependency(opengles LIBS GLESv2)
endif()
endif()
set(SDL_LOADSO_DLOPEN 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/dlopen/*.c")
set(HAVE_SDL_LOADSO TRUE)
set(SDL_TIME_UNIX 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
set(HAVE_SDL_TIME TRUE)
set(SDL_TIMER_UNIX 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c")
set(HAVE_SDL_TIMERS TRUE)
set(SDL_PTHREADS 1)
CheckPTHREAD()
elseif(EMSCRIPTEN)
# Hide noisy warnings that intend to aid mostly during initial stages of porting a new
# project. Uncomment at will for verbose cross-compiling -I/../ path info.

View File

@ -373,7 +373,7 @@ function(SDL_PrintSummary)
message(STATUS "")
endif()
if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN OR HAIKU OR RISCOS))
if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN OR HAIKU OR RISCOS OR OHOS))
if(NOT (HAVE_X11 OR HAVE_WAYLAND))
if(NOT SDL_UNIX_CONSOLE_BUILD)
message(FATAL_ERROR

View File

@ -829,7 +829,7 @@ macro(CheckPTHREAD)
if(ANDROID OR SDL_PTHREADS_PRIVATE)
# the android libc provides built-in support for pthreads, so no
# additional linking or compile flags are necessary
elseif(LINUX)
elseif(LINUX OR OHOS)
set(PTHREAD_CFLAGS "-D_REENTRANT")
set(PTHREAD_LDFLAGS "-pthread")
elseif(BSDI)

View File

@ -1064,6 +1064,17 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au
/**
* Get the properties associated with an audio stream.
*
* The application can hang any data it wants here, but the following
* properties are understood by SDL:
*
* - `SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN`: if true (the default), the
* stream be automatically cleaned up when the audio subsystem quits. If set
* to false, the streams will persist beyond that. This property is ignored
* for streams created through SDL_OpenAudioDeviceStream(), and will always
* be cleaned up. Streams that are not cleaned up will still be unbound from
* devices when the audio subsystem quits. This property was added in SDL
* 3.4.0.
*
* \param stream the SDL_AudioStream to query.
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
@ -1074,6 +1085,9 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au
*/
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetAudioStreamProperties(SDL_AudioStream *stream);
#define SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN "SDL.audiostream.auto_cleanup"
/**
* Query the current format of an audio stream.
*

View File

@ -112,6 +112,11 @@
#undef SDL_PLATFORM_LINUX
#endif
#if defined(OHOS) || defined(__OHOS__)
#define SDL_PLATFORM_OHOS 1
#undef SDL_PLATFORM_LINUX
#endif
#if defined(__unix__) || defined(__unix) || defined(unix)
/**

View File

@ -269,6 +269,7 @@
#cmakedefine SDL_AUDIO_DRIVER_JACK 1
#cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_NETBSD 1
#cmakedefine SDL_VIDEO_DRIVER_OHOS 1
#cmakedefine SDL_AUDIO_DRIVER_OSS 1
#cmakedefine SDL_AUDIO_DRIVER_PIPEWIRE 1
#cmakedefine SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC @SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC@
@ -397,6 +398,7 @@
#cmakedefine SDL_VIDEO_DRIVER_N3DS 1
#cmakedefine SDL_VIDEO_DRIVER_NGAGE 1
#cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN 1
#cmakedefine SDL_VIDEO_DRIVER_OHOS 1
#cmakedefine SDL_VIDEO_DRIVER_PS2 1
#cmakedefine SDL_VIDEO_DRIVER_PSP 1
#cmakedefine SDL_VIDEO_DRIVER_RISCOS 1

View File

@ -36,6 +36,10 @@
#include <android/log.h>
#endif
#ifdef SDL_PLATFORM_OHOS
#include <hilog/log.h>
#endif
#include "stdlib/SDL_vacopy.h"
// The size of the stack buffer to use for rendering log messages.
@ -120,6 +124,19 @@ static int SDL_android_priority[] = {
SDL_COMPILE_TIME_ASSERT(android_priority, SDL_arraysize(SDL_android_priority) == SDL_LOG_PRIORITY_COUNT);
#endif // SDL_PLATFORM_ANDROID
#ifdef SDL_PLATFORM_OHOS
static int SDL_ohos_priority[] = {
LOG_DEBUG,
LOG_DEBUG,
LOG_DEBUG,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_FATAL
};
#endif
static void SDLCALL SDL_LoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_ResetLogPriorities();
@ -556,7 +573,7 @@ void SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_ST
va_end(ap);
}
#ifdef SDL_PLATFORM_ANDROID
#if defined(SDL_PLATFORM_ANDROID) || defined(SDL_PLATFORM_OHOS)
static const char *GetCategoryPrefix(int category)
{
if (category < SDL_LOG_CATEGORY_RESERVED2) {
@ -567,7 +584,7 @@ static const char *GetCategoryPrefix(int category)
}
return "CUSTOM";
}
#endif // SDL_PLATFORM_ANDROID
#endif
void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap)
{
@ -751,6 +768,13 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
__android_log_write(SDL_android_priority[priority], tag, message);
}
#elif defined(SDL_PLATFORM_OHOS)
{
char tag[32];
SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
OH_LOG_Print(LOG_APP, SDL_ohos_priority[priority], 0, tag, "%{public}s", message);
}
#elif defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))
/* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now.
*/

View File

@ -1073,9 +1073,16 @@ void SDL_QuitAudio(void)
current_audio.impl.DeinitializeStart();
// Destroy any audio streams that still exist...
while (current_audio.existing_streams) {
SDL_DestroyAudioStream(current_audio.existing_streams);
// Destroy any audio streams that still exist...unless app asked to keep it.
SDL_AudioStream *next = NULL;
for (SDL_AudioStream *i = current_audio.existing_streams; i; i = next) {
next = i->next;
if (i->simplified || SDL_GetBooleanProperty(i->props, SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN, true)) {
SDL_DestroyAudioStream(i);
} else {
i->prev = NULL;
i->next = NULL;
}
}
SDL_LockRWLockForWriting(current_audio.device_hash_lock);

View File

@ -536,9 +536,11 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32 *dst, const U
// be guarded by the STDC FENV_ACCESS pragma; otherwise, it's undefined
// behavior. However, the compiler support for this pragma is bad.
#if defined(__clang__)
#ifndef SDL_PLATFORM_OHOS
#if __clang_major__ >= 12
#pragma STDC FENV_ACCESS ON
#endif
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (on)
#elif defined(__GNUC__)
@ -813,9 +815,11 @@ static void SDL_Convert_Swap32_NEON(Uint32 *dst, const Uint32 *src, int num_samp
}
#if defined(__clang__)
#ifndef SDL_PLATFORM_OHOS
#if __clang_major__ >= 12
#pragma STDC FENV_ACCESS DEFAULT
#endif
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (off)
#elif defined(__GNUC__)

View File

@ -1157,7 +1157,7 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
#if SDL_ALSA_DEBUG
snd_pcm_uframes_t bufsize;
ALSA_snd_pcm_hw_params_get_buffer_size(cfg_ctx.hwparams, &bufsize);
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO,
"ALSA: period size = %ld, periods = %u, buffer size = %lu",
cfg_ctx.persize, cfg_ctx.periods, bufsize);
#endif

434
src/core/ohos/SDL_ohos.c Normal file
View File

@ -0,0 +1,434 @@
#include "SDL_internal.h"
#include "dynapi/SDL_dynapi_overrides.h"
#include <EGL/egl.h>
#include <EGL/eglplatform.h>
#include <dlfcn.h>
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <node_api.h>
#include <node_api_types.h>
#include <stdint.h>
#ifdef SDL_PLATFORM_OHOS
#include "../../video/ohos/SDL_ohoskeyboard.h"
#include "../../video/ohos/SDL_ohostouch.h"
#include "../../video/ohos/SDL_ohosvideo.h"
#include "SDL3/SDL_mutex.h"
#include "SDL_ohos.h"
#include "napi/native_api.h"
#include <ace/xcomponent/native_interface_xcomponent.h>
static OHNativeWindow *g_ohosNativeWindow;
static SDL_Mutex *g_ohosPageMutex = NULL;
static OH_NativeXComponent_Callback callback;
static OH_NativeXComponent_MouseEvent_Callback mouseCallback;
static int x, y, wid, hei;
static struct
{
napi_env env;
napi_threadsafe_function func;
napi_ref interface;
} napiEnv;
typedef enum
{
Int,
Long,
Double,
String
} napiArgType;
typedef struct
{
napiArgType type;
union
{
int i;
long long l;
double d;
const char *str;
} data;
} napiCallbackArg;
typedef struct
{
const char *func;
int argCount;
napiCallbackArg arg[16];
napiArgType type;
napiCallbackArg ret;
} napiCallbackData;
void OHOS_windowDataFill(SDL_Window *w)
{
w->internal = SDL_calloc(1, sizeof(SDL_WindowData));
w->x = x;
w->y = y;
w->w = wid;
w->h = hei;
w->internal->native_window = g_ohosNativeWindow;
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this->windows == NULL) {
_this->windows = w;
} else {
_this->windows->next = w;
w->prev = _this->windows;
}
#ifdef SDL_VIDEO_OPENGL_EGL
if (w->flags & SDL_WINDOW_OPENGL) {
SDL_LockMutex(g_ohosPageMutex);
if (w->internal->egl_surface == EGL_NO_SURFACE) {
w->internal->egl_surface = SDL_EGL_CreateSurface(_this, w, (NativeWindowType)g_ohosNativeWindow);
}
SDL_UnlockMutex(g_ohosPageMutex);
}
#endif
}
void OHOS_removeWindow(SDL_Window *w)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this->windows == w) {
_this->windows = _this->windows->next;
} else {
SDL_Window *curWin = _this->windows;
while (curWin != NULL) {
if (curWin == w) {
if (curWin->next == NULL) {
curWin->prev->next = NULL;
} else {
curWin->prev->next = curWin->next;
curWin->next->prev = curWin->prev;
}
break;
}
curWin = curWin->next;
}
}
#ifdef SDL_VIDEO_OPENGL_EGL
if (w->flags & SDL_WINDOW_OPENGL) {
SDL_LockMutex(g_ohosPageMutex);
if (w->internal->egl_context) {
SDL_EGL_DestroyContext(_this, w->internal->egl_context);
}
if (w->internal->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, w->internal->egl_surface);
}
SDL_UnlockMutex(g_ohosPageMutex);
}
SDL_free(w->internal);
#endif
}
void OHOS_LockPage()
{
SDL_LockMutex(g_ohosPageMutex);
}
void OHOS_UnlockPage()
{
SDL_UnlockMutex(g_ohosPageMutex);
}
int OHOS_FetchWidth()
{
return wid;
}
int OHOS_FetchHeight()
{
return hei;
}
static void sdlJSCallback(napi_env env, napi_value jsCb, void *content, void *data)
{
napiCallbackData *ar = (napiCallbackData *)data;
napi_value callb = NULL;
napi_get_reference_value(env, napiEnv.interface, &callb);
napi_value jsMethod = NULL;
napi_get_named_property(env, callb, ar->func, &jsMethod);
napi_value args[16];
for (int i = 0; i < ar->argCount; i++) {
switch (ar->arg[i].type) {
case Int:
{
napi_create_int32(env, ar->arg[i].data.i, args + i);
break;
}
case Long:
{
napi_create_int64(env, ar->arg[i].data.l, args + i);
break;
}
case Double:
{
napi_create_double(env, ar->arg[i].data.d, args + i);
break;
}
case String:
{
napi_create_string_utf8(env, ar->arg[i].data.str, SDL_strlen(ar->arg[i].data.str), args + i);
break;
}
}
}
napi_value v;
napi_call_function(env, NULL, jsMethod, ar->argCount, args, &v);
switch (ar->type) {
case Int:
{
napi_get_value_int32(env, v, &ar->ret.data.i);
break;
}
case Long:
{
napi_get_value_int64(env, v, (int64_t *)&ar->ret.data.l);
break;
}
case String:
{
size_t stringSize = 0;
napi_get_value_string_utf8(env, args[1], NULL, 0, &stringSize);
char *value = SDL_malloc(stringSize + 1);
napi_get_value_string_utf8(env, args[1], value, stringSize + 1, &stringSize);
ar->ret.data.str = value;
break;
}
case Double:
{
napi_get_value_double(env, v, &ar->ret.data.d);
break;
}
}
}
static napi_value sdlCallbackInit(napi_env env, napi_callback_info info)
{
napiEnv.env = env;
size_t argc = 1;
napi_value args[1] = { NULL };
napi_get_cb_info(env, info, &argc, args, NULL, NULL);
napi_create_reference(env, args[0], 1, &napiEnv.interface);
napi_value resName = NULL;
napi_create_string_utf8(env, "SDLThreadSafe", NAPI_AUTO_LENGTH, &resName);
napi_create_threadsafe_function(env, args[0], NULL, resName, 0, 1, NULL, NULL, NULL, sdlJSCallback, &napiEnv.func);
napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData));
data->func = "test";
data->argCount = 0;
napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_blocking);
// SDL_free(data);
napi_value result;
napi_create_int32(env, 0, &result);
return result;
}
static napi_value sdlLaunchMain(napi_env env, napi_callback_info info)
{
size_t argc = 2;
napi_value args[2] = { NULL, NULL };
napi_get_cb_info(env, info, &argc, args, NULL, NULL);
size_t libstringSize = 0;
napi_get_value_string_utf8(env, args[0], NULL, 0, &libstringSize);
char *libname = SDL_malloc(libstringSize + 1);
napi_get_value_string_utf8(env, args[0], libname, libstringSize + 1, &libstringSize);
size_t fstringSize = 0;
napi_get_value_string_utf8(env, args[1], NULL, 0, &fstringSize);
char *fname = SDL_malloc(fstringSize + 1);
napi_get_value_string_utf8(env, args[1], fname, fstringSize + 1, &fstringSize);
void *lib = dlopen(libname, RTLD_LAZY);
void *func = dlsym(lib, fname);
typedef int (*test)();
((test)func)();
dlclose(lib);
napi_value result;
napi_create_int32(env, 0, &result);
return result;
}
static void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
{
SDL_Log("Native window: %p", window);
g_ohosNativeWindow = (OHNativeWindow *)window;
uint64_t width;
uint64_t height;
double offsetX;
double offsetY;
OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY);
SDL_LockMutex(g_ohosPageMutex);
wid = width;
hei = height;
x = (int)offsetX;
y = (int)offsetY;
SDL_UnlockMutex(g_ohosPageMutex);
}
static void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window)
{
g_ohosNativeWindow = (OHNativeWindow *)window;
uint64_t width;
uint64_t height;
double offsetX;
double offsetY;
OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY);
SDL_LockMutex(g_ohosPageMutex);
wid = width;
hei = height;
x = (int)offsetX;
y = (int)offsetY;
SDL_UnlockMutex(g_ohosPageMutex);
}
static void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *win = _this->windows;
while (win != NULL) {
#ifdef SDL_VIDEO_OPENGL_EGL
if (win->flags & SDL_WINDOW_OPENGL) {
if (win->internal->egl_context) {
SDL_EGL_DestroyContext(_this, win->internal->egl_context);
}
if (win->internal->egl_surface) {
SDL_EGL_DestroySurface(_this, win->internal->egl_surface);
}
}
#endif
win = win->next;
}
}
static void onKeyEvent(OH_NativeXComponent *component, void *window)
{
OH_NativeXComponent_KeyEvent *keyEvent = NULL;
if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) {
OH_NativeXComponent_KeyAction action;
OH_NativeXComponent_KeyCode code;
OH_NativeXComponent_EventSourceType sourceType;
OH_NativeXComponent_GetKeyEventAction(keyEvent, &action);
OH_NativeXComponent_GetKeyEventCode(keyEvent, &code);
OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType);
if (sourceType == OH_NATIVEXCOMPONENT_SOURCE_TYPE_KEYBOARD) {
if (OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN == action) {
OHOS_OnKeyDown(code);
} else if (OH_NATIVEXCOMPONENT_KEY_ACTION_UP == action) {
OHOS_OnKeyUp(code);
}
}
}
}
static void onNativeTouch(OH_NativeXComponent *component, void *window)
{
OH_NativeXComponent_TouchEvent touchEvent;
OH_NativeXComponent_TouchPointToolType toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN;
OHOS_LockPage();
OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent);
OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType);
for (int i = 0; i < touchEvent.numPoints; i++) {
SDL_OHOSTouchEvent e;
e.timestamp = touchEvent.timeStamp;
e.deviceId = touchEvent.deviceId;
e.fingerId = touchEvent.touchPoints[i].id;
e.area = touchEvent.touchPoints[i].size;
e.x = touchEvent.touchPoints[i].x / (float)wid;
e.y = touchEvent.touchPoints[i].y / (float)hei;
e.p = touchEvent.touchPoints[i].force;
switch (touchEvent.touchPoints[i].type) {
case OH_NATIVEXCOMPONENT_DOWN:
e.type = SDL_EVENT_FINGER_DOWN;
break;
case OH_NATIVEXCOMPONENT_MOVE:
e.type = SDL_EVENT_FINGER_MOTION;
break;
case OH_NATIVEXCOMPONENT_UP:
e.type = SDL_EVENT_FINGER_UP;
break;
case OH_NATIVEXCOMPONENT_CANCEL:
case OH_NATIVEXCOMPONENT_UNKNOWN:
e.type = SDL_EVENT_FINGER_CANCELED;
break;
}
OHOS_OnTouch(e);
}
}
static void OnDispatchTouchEventCB(OH_NativeXComponent *component, void *window)
{
onNativeTouch(component, window);
}
// TODO
static void onNativeMouse(OH_NativeXComponent *component, void *window) {}
static napi_value SDL_OHOS_NAPI_Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{ "sdlCallbackInit", NULL, sdlCallbackInit, NULL, NULL, NULL, napi_default, NULL },
{ "sdlLaunchMain", NULL, sdlLaunchMain, NULL, NULL, NULL, napi_default, NULL }
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
napi_value exportInstance = NULL;
if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
return exports;
}
OH_NativeXComponent *nativeXComponent;
if (napi_unwrap(env, exportInstance, (void **)(&nativeXComponent)) != napi_ok) {
return exports;
}
callback.OnSurfaceCreated = OnSurfaceCreatedCB;
callback.OnSurfaceChanged = OnSurfaceChangedCB;
callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
callback.DispatchTouchEvent = onNativeTouch;
OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback);
mouseCallback.DispatchMouseEvent = OnDispatchTouchEventCB;
mouseCallback.DispatchMouseEvent = onNativeMouse;
OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback);
OH_NativeXComponent_RegisterKeyEventCallback(nativeXComponent, onKeyEvent);
g_ohosPageMutex = SDL_CreateMutex();
return exports;
}
napi_module OHOS_NAPI_Module = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = NULL,
.nm_register_func = SDL_OHOS_NAPI_Init,
.nm_modname = "SDL3",
.nm_priv = ((void *)0),
.reserved = { 0 },
};
__attribute__((constructor)) void RegisterEntryModule(void)
{
napi_module_register(&OHOS_NAPI_Module);
}
#endif

21
src/core/ohos/SDL_ohos.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef SDL_OHOS_H
#define SDL_OHOS_H
#include "SDL3/SDL_video.h"
#include "video/SDL_sysvideo.h"
#include <native_window/external_window.h>
void OHOS_windowDataFill(SDL_Window* w);
void OHOS_removeWindow(SDL_Window* w);
void OHOS_LockPage();
void OHOS_UnlockPage();
int OHOS_FetchWidth();
int OHOS_FetchHeight();
typedef struct SDL_VideoData {
SDL_Rect textRect;
int isPaused;
int isPausing;
} SDL_VideoData;
#endif

View File

@ -928,13 +928,14 @@ static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled)
static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
{
Uint8 *pLeftStickCal;
Uint8 *pRightStickCal;
Uint8 *pLeftStickCal = NULL;
Uint8 *pRightStickCal = NULL;
size_t stick, axis;
SwitchSubcommandInputPacket_t *user_reply = NULL;
SwitchSubcommandInputPacket_t *factory_reply = NULL;
SwitchSPIOpData_t readUserParams;
SwitchSPIOpData_t readFactoryParams;
Uint8 userParamsReadSuccessCount = 0;
// Read User Calibration Info
readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset;
@ -947,39 +948,52 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
const int MAX_ATTEMPTS = 3;
for (int attempt = 0; ; ++attempt) {
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
return false;
}
if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
// We successfully read the calibration data
break;
}
if (attempt == MAX_ATTEMPTS) {
return false;
}
}
// Automatically select the user calibration if magic bytes are set
if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) {
userParamsReadSuccessCount += 1;
pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration;
} else {
pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
}
if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) {
userParamsReadSuccessCount += 1;
pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
} else {
pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
}
// Only read the factory calibration info if we failed to receive the correct magic bytes
if (userParamsReadSuccessCount < 2) {
// Read Factory Calibration Info
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
const int MAX_ATTEMPTS = 3;
for (int attempt = 0;; ++attempt) {
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
return false;
}
if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
// We successfully read the calibration data
pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
break;
}
if (attempt == MAX_ATTEMPTS) {
return false;
}
}
}
// If we still don't have calibration data, return false
if (pLeftStickCal == NULL || pRightStickCal == NULL)
{
return false;
}
/* Stick calibration values are 12-bits each and are packed by bit
* For whatever reason the fields are in a different order for each stick
* Left: X-Max, Y-Max, X-Center, Y-Center, X-Min, Y-Min
* Right: X-Center, Y-Center, X-Max, Y-Max, X-Min, Y-Min
* Right: X-Center, Y-Center, X-Min, Y-Min, X-Max, Y-Max
*/
// Left stick
@ -993,10 +1007,10 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
// Right stick
ctx->m_StickCalData[1].axis[0].sCenter = ((pRightStickCal[1] << 8) & 0xF00) | pRightStickCal[0]; // X Axis center
ctx->m_StickCalData[1].axis[1].sCenter = (pRightStickCal[2] << 4) | (pRightStickCal[1] >> 4); // Y Axis center
ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis max above center
ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis max above center
ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis min below center
ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis min below center
ctx->m_StickCalData[1].axis[0].sMin = ((pRightStickCal[4] << 8) & 0xF00) | pRightStickCal[3]; // X Axis min below center
ctx->m_StickCalData[1].axis[1].sMin = (pRightStickCal[5] << 4) | (pRightStickCal[4] >> 4); // Y Axis min below center
ctx->m_StickCalData[1].axis[0].sMax = ((pRightStickCal[7] << 8) & 0xF00) | pRightStickCal[6]; // X Axis max above center
ctx->m_StickCalData[1].axis[1].sMax = (pRightStickCal[8] << 4) | (pRightStickCal[7] >> 4); // Y Axis max above center
// Filter out any values that were uninitialized (0xFFF) in the SPI read
for (stick = 0; stick < 2; ++stick) {

View File

@ -169,7 +169,7 @@ void SDL_SYS_SetupThread(const char *name)
pthread_sigmask(SIG_BLOCK, &mask, 0);
#endif
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
#if defined(PTHREAD_CANCEL_ASYNCHRONOUS) && !defined(SDL_PLATFORM_OHOS)
// Allow ourselves to be asynchronously cancelled
{
int oldstate;

View File

@ -542,6 +542,7 @@ extern VideoBootStrap Emscripten_bootstrap;
extern VideoBootStrap OFFSCREEN_bootstrap;
extern VideoBootStrap QNX_bootstrap;
extern VideoBootStrap OPENVR_bootstrap;
extern VideoBootStrap OHOS_bootstrap;
extern bool SDL_UninitializedVideo(void);
// Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work

View File

@ -148,6 +148,9 @@ static VideoBootStrap *bootstrap[] = {
#endif
#ifdef SDL_VIDEO_DRIVER_OPENVR
&OPENVR_bootstrap,
#endif
#ifdef SDL_VIDEO_DRIVER_OHOS
&OHOS_bootstrap,
#endif
NULL
};

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VULKAN_OHOS_H
#define VULKAN_OHOS_H 1
#include <vulkan/vulkan_core.h>
#ifdef __cplusplus
extern "C" {
#endif
#define VK_KHR_OHOS_XCOMPONENT 1
struct ONativeWindow;
#define VK_KHR_OHOS_XCOMPONENT_SPEC_VERSION 6
#define VK_KHR_OHOS_XCOMPONENT_EXTENSION_NAME "VK_OHOS_surface"
typedef VkFlags VkOHOSXComponentCreateFlagsKHR;
typedef struct VkOHOSXComponentCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkOHOSXComponentCreateFlagsKHR flags;
struct OHNativeWindow* window;
} VkOHOSXComponentCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateOHOSXComponentKHR)(VkInstance instance,
const VkOHOSXComponentCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pXComponent);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateOHOSXComponentKHR(
VkInstance instance,
const VkOHOSXComponentCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#define VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER 1
struct OHardwareBuffer;
#define VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER_SPEC_VERSION 3
#define VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER_EXTENSION_NAME "VK_OHOS_EXTERNAL_MEMORY_OHOS_HARDWARE_BUFFER"
typedef struct VkOHOSHardwareBufferUsageOHOS {
VkStructureType sType;
void* pNext;
uint64_t ohosHardwareBufferUsage;
} VkOHOSHardwareBufferUsageOHOS;
typedef struct VkOHOSHardwareBufferPropertiesOHOS {
VkStructureType sType;
void* pNext;
VkDeviceSize allocationSize;
uint32_t memoryTypeBits;
} VkOHOSHardwareBufferPropertiesOHOS;
typedef struct VkOHOSHardwareBufferFormatPropertiesOHOS {
VkStructureType sType;
void* pNext;
VkFormat format;
uint64_t externalFormat;
VkFormatFeatureFlags formatFeatures;
VkComponentMapping samplerYcbcrConversionComponents;
VkSamplerYcbcrModelConversion suggestedYcbcrModel;
VkSamplerYcbcrRange suggestedYcbcrRange;
VkChromaLocation suggestedXChromaOffset;
VkChromaLocation suggestedYChromaOffset;
} VkOHOSHardwareBufferFormatPropertiesOHOS;
typedef struct VkImportOHOSHardwareBufferInfoOHOS {
VkStructureType sType;
const void* pNext;
struct OHardwareBuffer* buffer;
} VkImportOHOSHardwareBufferInfoOHOS;
typedef struct VkMemoryGetOHOSHardwareBufferInfoOHOS {
VkStructureType sType;
const void* pNext;
VkDeviceMemory memory;
} VkMemoryGetOHOSHardwareBufferInfoOHOS;
typedef struct VkExternalFormatOHOS {
VkStructureType sType;
void* pNext;
uint64_t externalFormat;
} VkExternalFormatOHOS;
typedef VkResult (VKAPI_PTR *PFN_vkGetOHOSHardwareBufferPropertiesOHOS)(VkDevice device,
const struct OHardwareBuffer* buffer, VkOHOSHardwareBufferPropertiesOHOS* pProperties);
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryOHOSHardwareBufferOHOS)(VkDevice device,
const VkMemoryGetOHOSHardwareBufferInfoOHOS* pInfo, struct OHardwareBuffer** pBuffer);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetOHOSHardwareBufferPropertiesOHOS(
VkDevice device,
const struct OHardwareBuffer* buffer,
VkOHOSHardwareBufferPropertiesOHOS* pProperties);
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryOHOSHardwareBufferOHOS(
VkDevice device,
const VkMemoryGetOHOSHardwareBufferInfoOHOS* pInfo,
struct OHardwareBuffer** pBuffer);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -588,88 +588,51 @@ static void KMSDRM_DeinitDisplays(SDL_VideoDevice *_this)
}
}
static uint32_t KMSDRM_CrtcGetPropId(uint32_t drm_fd,
drmModeObjectPropertiesPtr props,
char const *name)
static bool KMSDRM_ConnectorCheckVrrCapable(uint32_t drm_fd, uint32_t output_id)
{
uint32_t i, prop_id = 0;
for (i = 0; !prop_id && i < props->count_props; ++i) {
drmModePropertyPtr drm_prop =
KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (!drm_prop) {
continue;
}
if (SDL_strcmp(drm_prop->name, name) == 0) {
prop_id = drm_prop->prop_id;
}
KMSDRM_drmModeFreeProperty(drm_prop);
}
return prop_id;
}
static bool KMSDRM_VrrPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *vrr_prop_id)
{
drmModeObjectPropertiesPtr drm_props;
drm_props = KMSDRM_drmModeObjectGetProperties(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!drm_props) {
return false;
}
*vrr_prop_id = KMSDRM_CrtcGetPropId(drm_fd,
drm_props,
"VRR_ENABLED");
KMSDRM_drmModeFreeObjectProperties(drm_props);
return true;
}
static bool KMSDRM_ConnectorCheckVrrCapable(uint32_t drm_fd,
uint32_t output_id,
char const *name)
{
uint32_t i;
bool found = false;
uint64_t prop_value = 0;
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd,
output_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!props) {
return false;
}
for (i = 0; !found && i < props->count_props; ++i) {
drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (!drm_prop) {
continue;
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd, output_id, DRM_MODE_OBJECT_CONNECTOR);
if (props) {
for (uint32_t i = 0; !found && i < props->count_props; ++i) {
drmModePropertyPtr prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (prop) {
if (SDL_strcasecmp(prop->name, "VRR_CAPABLE") == 0) {
prop_value = props->prop_values[i];
found = true;
}
KMSDRM_drmModeFreeProperty(prop);
}
}
if (SDL_strcasecmp(drm_prop->name, name) == 0) {
prop_value = props->prop_values[i];
found = true;
}
KMSDRM_drmModeFreeProperty(drm_prop);
KMSDRM_drmModeFreeObjectProperties(props);
}
if (found) {
return prop_value ? true : false;
}
return false;
}
static bool KMSDRM_VrrPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *vrr_prop_id)
{
bool found = false;
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd, crtc_id, DRM_MODE_OBJECT_CRTC);
if (props) {
for (uint32_t i = 0; !found && i < props->count_props; ++i) {
drmModePropertyPtr prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (prop) {
if (SDL_strcmp(prop->name, "VRR_ENABLED") == 0) {
*vrr_prop_id = prop->prop_id;
found = true;
}
KMSDRM_drmModeFreeProperty(prop);
}
}
KMSDRM_drmModeFreeObjectProperties(props);
}
return found;
}
static void KMSDRM_CrtcSetVrr(uint32_t drm_fd, uint32_t crtc_id, bool enabled)
{
uint32_t vrr_prop_id;
@ -677,119 +640,67 @@ static void KMSDRM_CrtcSetVrr(uint32_t drm_fd, uint32_t crtc_id, bool enabled)
return;
}
KMSDRM_drmModeObjectSetProperty(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CRTC,
vrr_prop_id,
enabled);
KMSDRM_drmModeObjectSetProperty(drm_fd, crtc_id, DRM_MODE_OBJECT_CRTC, vrr_prop_id, enabled);
}
static bool KMSDRM_CrtcGetVrr(uint32_t drm_fd, uint32_t crtc_id)
{
uint32_t object_prop_id, vrr_prop_id;
drmModeObjectPropertiesPtr props;
bool object_prop_value;
int i;
uint32_t vrr_prop_id = 0;
bool found = false;
uint64_t prop_value = 0;
if (!KMSDRM_VrrPropId(drm_fd, crtc_id, &vrr_prop_id)) {
return false;
}
props = KMSDRM_drmModeObjectGetProperties(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!props) {
return false;
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd, crtc_id, DRM_MODE_OBJECT_CRTC);
if (props) {
for (uint32_t i = 0; !found && i < props->count_props; ++i) {
drmModePropertyPtr prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (prop) {
if (prop->prop_id == vrr_prop_id) {
prop_value = props->prop_values[i];
found = true;
}
KMSDRM_drmModeFreeProperty(prop);
}
}
KMSDRM_drmModeFreeObjectProperties(props);
}
for (i = 0; i < props->count_props; ++i) {
drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (!drm_prop) {
continue;
}
object_prop_id = drm_prop->prop_id;
object_prop_value = props->prop_values[i] ? true : false;
KMSDRM_drmModeFreeProperty(drm_prop);
if (object_prop_id == vrr_prop_id) {
return object_prop_value;
}
if (found) {
return prop_value ? true : false;
}
return false;
}
static bool KMSDRM_OrientationPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *orientation_prop_id)
{
drmModeObjectPropertiesPtr drm_props;
drm_props = KMSDRM_drmModeObjectGetProperties(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!drm_props) {
return false;
}
*orientation_prop_id = KMSDRM_CrtcGetPropId(drm_fd,
drm_props,
"panel orientation");
KMSDRM_drmModeFreeObjectProperties(drm_props);
return true;
}
static int KMSDRM_CrtcGetOrientation(uint32_t drm_fd, uint32_t crtc_id)
{
uint32_t orientation_prop_id;
drmModeObjectPropertiesPtr props;
int i;
bool done = false;
bool found = false;
int orientation = 0;
if (!KMSDRM_OrientationPropId(drm_fd, crtc_id, &orientation_prop_id)) {
return orientation;
}
props = KMSDRM_drmModeObjectGetProperties(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!props) {
return orientation;
}
for (i = 0; i < props->count_props && !done; ++i) {
drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (!drm_prop) {
continue;
}
if (drm_prop->prop_id == orientation_prop_id && (drm_prop->flags & DRM_MODE_PROP_ENUM)) {
if (drm_prop->count_enums) {
// "Normal" is the default of no rotation (0 degrees)
if (SDL_strcmp(drm_prop->enums[0].name, "Left Side Up") == 0) {
orientation = 90;
} else if (SDL_strcmp(drm_prop->enums[0].name, "Upside Down") == 0) {
orientation = 180;
} else if (SDL_strcmp(drm_prop->enums[0].name, "Right Side Up") == 0) {
orientation = 270;
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd, crtc_id, DRM_MODE_OBJECT_CONNECTOR);
if (props) {
for (uint32_t i = 0; !found && i < props->count_props; ++i) {
drmModePropertyPtr prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (prop) {
if (SDL_strcasecmp(prop->name, "panel orientation") == 0 && (prop->flags & DRM_MODE_PROP_ENUM)) {
if (prop->count_enums) {
// "Normal" is the default of no rotation (0 degrees)
if (SDL_strcmp(prop->enums[0].name, "Left Side Up") == 0) {
orientation = 90;
} else if (SDL_strcmp(prop->enums[0].name, "Upside Down") == 0) {
orientation = 180;
} else if (SDL_strcmp(prop->enums[0].name, "Right Side Up") == 0) {
orientation = 270;
}
}
found = true;
}
KMSDRM_drmModeFreeProperty(prop);
}
done = true;
}
KMSDRM_drmModeFreeProperty(drm_prop);
KMSDRM_drmModeFreeObjectProperties(props);
}
KMSDRM_drmModeFreeObjectProperties(props);
return orientation;
}
@ -964,7 +875,7 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto
// save previous vrr state
dispdata->saved_vrr = KMSDRM_CrtcGetVrr(viddata->drm_fd, crtc->crtc_id);
// try to enable vrr
if (KMSDRM_ConnectorCheckVrrCapable(viddata->drm_fd, connector->connector_id, "VRR_CAPABLE")) {
if (KMSDRM_ConnectorCheckVrrCapable(viddata->drm_fd, connector->connector_id)) {
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Enabling VRR");
KMSDRM_CrtcSetVrr(viddata->drm_fd, crtc->crtc_id, true);
}

View File

@ -0,0 +1,46 @@
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_OHOS
#include "../../core/ohos/SDL_ohos.h"
#include "SDL_ohosvideo.h"
bool OHOS_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
{
if (window && context) {
return SDL_EGL_MakeCurrent(_this, window->internal->egl_surface, context);
} else {
return SDL_EGL_MakeCurrent(_this, NULL, NULL);
}
}
SDL_GLContext OHOS_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_GLContext result;
OHOS_LockPage();
result = SDL_EGL_CreateContext(_this, window->internal->egl_surface);
OHOS_UnlockPage();
return result;
}
bool OHOS_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
bool result;
OHOS_LockPage();
result = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface);
OHOS_UnlockPage();
return result;
}
bool OHOS_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType)0, 0);
}
#endif

View File

@ -0,0 +1,9 @@
#ifdef SDL_VIDEO_DRIVER_OHOS
#include "SDL_ohosvideo.h"
bool OHOS_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
SDL_GLContext OHOS_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
bool OHOS_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
bool OHOS_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
#ifdef SDL_VIDEO_DRIVER_OHOS
void OHOS_OnKeyDown(int keycode);
void OHOS_OnKeyUp(int keycode);
#endif

View File

@ -0,0 +1,34 @@
#include "SDL_ohostouch.h"
#include "../../events/SDL_touch_c.h"
#include "SDL_internal.h"
void OHOS_OnTouch(SDL_OHOSTouchEvent event)
{
if (SDL_AddTouch(event.deviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
SDL_Log("Cannot add touch");
return;
}
switch (event.type) {
case SDL_EVENT_FINGER_DOWN:
{
SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_DOWN, event.x, event.y, event.p);
break;
}
case SDL_EVENT_FINGER_MOTION:
{
SDL_SendTouchMotion(event.timestamp, event.deviceId, event.fingerId, NULL, event.x, event.y, event.p);
break;
}
case SDL_EVENT_FINGER_UP:
{
SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_UP, event.x, event.y, event.p);
break;
}
case SDL_EVENT_FINGER_CANCELED:
{
SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_CANCELED, event.x, event.y, event.p);
break;
}
}
}

View File

@ -0,0 +1,17 @@
#ifndef SDL_OHOSTOUCH_H
#define SDL_OHOSTOUCH_H
typedef struct SDL_OHOSTouchEvent {
long long deviceId;
int fingerId;
int type;
float x;
float y;
float p;
float area;
long long timestamp;
} SDL_OHOSTouchEvent;
void OHOS_OnTouch(SDL_OHOSTouchEvent event);
#endif

View File

@ -0,0 +1,79 @@
#include "../SDL_sysvideo.h"
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_OHOS
#include "../../core/ohos/SDL_ohos.h"
#include "SDL_ohosgl.h"
#include "SDL_ohosvulkan.h"
#include "SDL_ohoswindow.h"
bool OHOS_VideoInit(SDL_VideoDevice *_this)
{
SDL_DisplayMode mode;
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_RGBA32;
mode.w = OHOS_FetchWidth();
mode.h = OHOS_FetchHeight();
mode.refresh_rate = 60;
SDL_AddBasicVideoDisplay(&mode);
return true;
}
void OHOS_VideoQuit(SDL_VideoDevice *_this)
{
}
void OHOS_DeviceFree(SDL_VideoDevice *device)
{
SDL_free(device);
}
static SDL_VideoDevice *OHOS_CreateDevice(void)
{
SDL_VideoDevice *device;
SDL_VideoData *data;
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
return NULL;
}
data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
if (!data) {
return NULL;
}
device->internal = data;
device->free = OHOS_DeviceFree;
device->VideoInit = OHOS_VideoInit;
device->VideoQuit = OHOS_VideoQuit;
#ifdef SDL_VIDEO_VULKAN
device->Vulkan_LoadLibrary = OHOS_Vulkan_LoadLibrary;
device->Vulkan_UnloadLibrary = OHOS_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = OHOS_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = OHOS_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = OHOS_Vulkan_DestroySurface;
#endif
device->CreateSDLWindow = OHOS_CreateWindow;
device->DestroyWindow = OHOS_DestroyWindow;
#ifdef SDL_VIDEO_OPENGL_EGL
device->GL_LoadLibrary = OHOS_GLES_LoadLibrary;
device->GL_MakeCurrent = OHOS_GLES_MakeCurrent;
device->GL_CreateContext = OHOS_GLES_CreateContext;
device->GL_SwapWindow = OHOS_GLES_SwapWindow;
device->GL_GetProcAddress = SDL_EGL_GetProcAddressInternal;
device->GL_UnloadLibrary = SDL_EGL_UnloadLibrary;
device->GL_SetSwapInterval = SDL_EGL_SetSwapInterval;
device->GL_GetSwapInterval = SDL_EGL_GetSwapInterval;
device->GL_DestroyContext = SDL_EGL_DestroyContext;
#endif
return device;
}
VideoBootStrap OHOS_bootstrap = {
"ohos", "OpenHarmony video driver",
OHOS_CreateDevice,
NULL,
false
};
#endif

View File

@ -0,0 +1,17 @@
#ifndef SDL_OHOSVIDEO_H
#define SDL_OHOSVIDEO_H
#include "../SDL_egl_c.h"
#include "../../core/ohos/SDL_ohos.h"
struct SDL_WindowData {
#ifdef SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
EGLContext egl_context;
#endif
bool backup_done;
OHNativeWindow *native_window;
uint64_t width;
uint64_t height;
};
#endif

View File

@ -0,0 +1,130 @@
#include "SDL_ohosvulkan.h"
#include "SDL_internal.h"
#include <vulkan/vulkan_core.h>
#ifdef SDL_VIDEO_DRIVER_OHOS
#define VK_USE_PLATFORM_OHOS 1
#include "../../core/ohos/SDL_ohos.h"
#include "../SDL_sysvideo.h"
#include "SDL_ohosvideo.h"
#include "vulkan/vulkan.h"
#include "vulkan/vulkan_ohos.h"
#include <native_window/external_window.h>
static int loadedCount = 0;
bool OHOS_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
if (_this->vulkan_config.loader_handle) {
return SDL_SetError("Vulkan already loaded");
}
/* Load the Vulkan loader library */
if (!path) {
path = SDL_getenv("SDL_VULKAN_LIBRARY");
}
if (!path) {
path = "libvulkan.so";
}
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
if (!_this->vulkan_config.loader_handle) {
return false;
}
SDL_strlcpy(_this->vulkan_config.loader_path, path,
SDL_arraysize(_this->vulkan_config.loader_path));
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
if (!vkGetInstanceProcAddr) {
goto fail;
}
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) {
goto fail;
}
loadedCount++;
return true;
fail:
SDL_UnloadObject(_this->vulkan_config.loader_handle);
_this->vulkan_config.loader_handle = NULL;
return false;
}
void OHOS_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
{
if (loadedCount == 0) {
return;
}
loadedCount--;
if (_this->vulkan_config.loader_handle && loadedCount == 0) {
SDL_UnloadObject(_this->vulkan_config.loader_handle);
_this->vulkan_config.loader_handle = NULL;
}
}
char const *const *OHOS_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count)
{
static const char *const extensionsForOHOS[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_OHOS_SURFACE_EXTENSION_NAME
};
if (count) {
*count = SDL_arraysize(extensionsForOHOS);
}
return extensionsForOHOS;
}
bool OHOS_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface)
{
VkResult result;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS =
(PFN_vkCreateSurfaceOHOS)vkGetInstanceProcAddr(instance, "vkCreateSurfaceOHOS");
VkSurfaceCreateInfoOHOS createInfo;
if (!_this->vulkan_config.loader_handle) {
SDL_SetError("Vulkan is not loaded");
return false;
}
if (!vkCreateSurfaceOHOS) {
SDL_SetError(VK_OHOS_SURFACE_EXTENSION_NAME
" extension is not enabled in the Vulkan instance.");
return false;
}
SDL_zero(createInfo);
createInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.window = window->internal->native_window;
result = vkCreateSurfaceOHOS(instance, &createInfo, NULL, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateSurfaceOHOS failed: %d", result);
return false;
}
return true;
}
void OHOS_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR");
vkDestroySurfaceKHR(instance, surface, allocator);
}
}
#endif

View File

@ -0,0 +1,21 @@
#ifndef SDL_OHOSVULKAN_H
#define SDL_OHOSVULKAN_H
#ifdef SDL_VIDEO_DRIVER_OHOS
#include "../SDL_sysvideo.h"
bool OHOS_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
void OHOS_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
char const* const* OHOS_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count);
bool OHOS_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void OHOS_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif
#endif

View File

@ -0,0 +1,20 @@
#include "SDL_ohoswindow.h"
#include "SDL_internal.h"
#include <EGL/eglplatform.h>
#ifdef SDL_VIDEO_DRIVER_OHOS
#include "../../core/ohos/SDL_ohos.h"
#include "SDL_ohosvideo.h"
bool OHOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
{
OHOS_windowDataFill(window);
return true;
}
void OHOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
OHOS_removeWindow(window);
}
#endif

View File

@ -0,0 +1,8 @@
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_OHOS
#include "../SDL_sysvideo.h"
bool OHOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
void OHOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
#endif

View File

@ -420,7 +420,7 @@ add_sdl_test_executable(testdialog SOURCES testdialog.c)
add_sdl_test_executable(testtime SOURCES testtime.c)
add_sdl_test_executable(testmanymouse SOURCES testmanymouse.c)
add_sdl_test_executable(testmodal SOURCES testmodal.c)
add_sdl_test_executable(testtray SOURCES testtray.c)
add_sdl_test_executable(testtray NEEDS_RESOURCES TESTUTILS SOURCES testtray.c)
add_sdl_test_executable(testprocess

View File

@ -1,3 +1,4 @@
#include "testutils.h"
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
@ -520,14 +521,17 @@ int main(int argc, char **argv)
goto quit;
}
/* TODO: Resource paths? */
SDL_Surface *icon = SDL_LoadBMP("../test/sdl-test_round.bmp");
char *icon1filename = GetResourceFilename(NULL, "sdl-test_round.bmp");
SDL_Surface *icon = SDL_LoadBMP(icon1filename);
SDL_free(icon1filename);
if (!icon) {
SDL_Log("Couldn't load icon 1, proceeding without: %s", SDL_GetError());
}
SDL_Surface *icon2 = SDL_LoadBMP("../test/speaker.bmp");
char *icon2filename = GetResourceFilename(NULL, "speaker.bmp");
SDL_Surface *icon2 = SDL_LoadBMP(icon2filename);
SDL_free(icon2filename);
if (!icon2) {
SDL_Log("Couldn't load icon 2, proceeding without: %s", SDL_GetError());