mirror of https://github.com/libsdl-org/SDL.git
Compare commits
70 Commits
cfbfa4d808
...
cbf1f2529c
| Author | SHA1 | Date |
|---|---|---|
|
|
cbf1f2529c | |
|
|
9ed83e71f6 | |
|
|
603118c340 | |
|
|
aa4f916b71 | |
|
|
6cfe211142 | |
|
|
274aa0242e | |
|
|
af8bee2dd1 | |
|
|
bbc674b9e7 | |
|
|
796961acec | |
|
|
3a6f9e01f8 | |
|
|
973260a851 | |
|
|
e7fdb9c19d | |
|
|
e7e0bd2768 | |
|
|
38a7790ae9 | |
|
|
b8f497f720 | |
|
|
d7a01e6778 | |
|
|
e7bcd9a9ae | |
|
|
a649753853 | |
|
|
29c6d182e2 | |
|
|
376aa5dfd7 | |
|
|
2b5815ad72 | |
|
|
f6147e0a81 | |
|
|
0f4c8f597f | |
|
|
56cea28cbd | |
|
|
4781c60983 | |
|
|
cf696785e8 | |
|
|
9c3e5f2925 | |
|
|
a886df9c12 | |
|
|
ec588468a0 | |
|
|
05f4fa7752 | |
|
|
35ea9148b2 | |
|
|
a4b48d3e2e | |
|
|
01fed59802 | |
|
|
167fe8bdb0 | |
|
|
048a59b21b | |
|
|
e91906683c | |
|
|
c951070638 | |
|
|
56ccf29d3c | |
|
|
9605a66f85 | |
|
|
cf3353a914 | |
|
|
27df3404d9 | |
|
|
d4039d3d66 | |
|
|
04e80426fb | |
|
|
d031a499f0 | |
|
|
b182ae0f8b | |
|
|
a9109972bf | |
|
|
0f2b280c76 | |
|
|
231ed48aab | |
|
|
298581d269 | |
|
|
c99ae6e155 | |
|
|
590509b34d | |
|
|
4a0d0685ee | |
|
|
af9601874e | |
|
|
2570e9ac56 | |
|
|
dc28e96952 | |
|
|
9e61fcb7f1 | |
|
|
8b6c78c688 | |
|
|
cd0d25ca11 | |
|
|
1e75f1fa6c | |
|
|
e339bde505 | |
|
|
4f5fcf6a16 | |
|
|
f25cbb135c | |
|
|
845ba7d5ce | |
|
|
addb748c64 | |
|
|
1c48676f4f | |
|
|
8f0b9c1151 | |
|
|
95ccfa69e5 | |
|
|
15cbc266ec | |
|
|
a6ebc6a63a | |
|
|
462476f150 |
|
|
@ -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
|
||||
|
|
@ -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}")
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#ifdef SDL_VIDEO_DRIVER_OHOS
|
||||
void OHOS_OnKeyDown(int keycode);
|
||||
void OHOS_OnKeyUp(int keycode);
|
||||
#endif
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
Loading…
Reference in New Issue