This commit is contained in:
Coder2 2026-06-06 06:30:21 +08:00 committed by GitHub
commit d8034cba3c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
78 changed files with 6311 additions and 5 deletions

View file

@ -0,0 +1,33 @@
name: 'Setup Harmony toolchain'
inputs:
version:
description: 'Harmony version'
default: '6.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

@ -61,6 +61,7 @@ class SdlPlatform(Enum):
OpenBSD = "openbsd"
NGage = "ngage"
DJGPP = "djgpp"
Harmony = "harmony"
class Msys2Platform(Enum):
@ -105,6 +106,7 @@ class JobSpec:
gdk: bool = False
vita_gles: Optional[VitaGLES] = None
more_hard_deps: bool = False
harmony_arch: Optional[str] = None
JOB_SPECS = {
@ -153,6 +155,9 @@ JOB_SPECS = {
"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", ),
"djgpp": JobSpec(name="DOS (DJGPP)", os=JobOs.UbuntuLatest, platform=SdlPlatform.DJGPP, artifact="SDL-djgpp", ),
"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"),
}
@ -868,6 +873,17 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool, ctest_args
job.run_tests = False
job.test_pkg_config = False
job.cmake_toolchain_file = "$GITHUB_WORKSPACE/build-scripts/i586-pc-msdosdjgpp.cmake"
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

@ -53,6 +53,9 @@ jobs:
if: ${{ matrix.platform.platform == 'emscripten' }}
with:
version: 3.1.35
- name: 'Set up Harmony toolchain'
if: ${{ matrix.platform.platform == 'harmony' }}
uses: ./.github/actions/setup-harmony-toolchain
- uses: browser-actions/setup-chrome@v2
id: setup-chrome
if: ${{ matrix.platform.platform == 'emscripten' }}

View file

@ -1709,6 +1709,84 @@ if(ANDROID)
target_link_options(SDL3-static INTERFACE "-Wl,-u,JNI_OnLoad")
endif()
if(TARGET SDL3-shared)
target_link_options(SDL3-shared PRIVATE "-Wl,-z,max-page-size=16384")
target_link_options(SDL3-shared PRIVATE "-Wl,-z,common-page-size=16384")
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 ohsensor)
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(HAVE_VULKAN ON)
set(SDL_VIDEO_VULKAN ON)
set(SDL_VIDEO_RENDER_VULKAN 1)
set(HAVE_RENDER_VULKAN TRUE)
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()
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/misc/ohos/*.c"
)
set(HAVE_SDL_MISC TRUE)
if(SDL_POWER)
set(SDL_POWER_OHOS 1)
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/power/ohos/*.c"
"${SDL3_SOURCE_DIR}/src/power/ohos/*.h"
)
set(HAVE_SDL_POWER TRUE)
endif()
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/ohos/*.c")
set(HAVE_SDL_LOCALE TRUE)
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_FILESYSTEM_OHOS 1)
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/filesystem/ohos/*.c"
"${SDL3_SOURCE_DIR}/src/filesystem/ohos/*.h"
)
set(HAVE_SDL_FILESYSTEM TRUE)
if(SDL_SENSOR)
set(SDL_SENSOR_OHOS 1)
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/sensor/ohos/*.c"
"${SDL3_SOURCE_DIR}/src/sensor/ohos/*.h"
)
set(HAVE_SDL_SENSOR TRUE)
endif()
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.
@ -3522,6 +3600,9 @@ if (SDL_DIALOG)
if(ANDROID)
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/android/SDL_androiddialog.c)
set(HAVE_SDL_DIALOG TRUE)
elseif (OHOS)
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/ohos/SDL_ohosdialog.c)
set(HAVE_SDL_DIALOG TRUE)
elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_unixdialog.c)
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_portaldialog.c)

View file

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

View file

@ -970,7 +970,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)

28
docs/README-ohos.md Normal file
View file

@ -0,0 +1,28 @@
OpenHarmony / HarmonyOS
================================================================================
Requirements
================================================================================
DevEco Studio 5.0.0 or later
https://developer.huawei.com/consumer/en/download
Harmony OS Development Toolchain 5.0.0 (API 12) or later (Bundled in the DevEco Studio)
How the port works
================================================================================
- OpenHarmony / Harmony OS apps are based on ArkTS/JS running on the Ark JS runtime, optionally with parts written in C
- We can use the napi and ndk provided by the Harmony SDK to fetch the app window, context and so on. We wrote a simple Harmony shell for SDL, simpily initialize the basic application and the context for SDL library, then runs your app in another thread. (Harmony JS apps only contains one thread, if we runs your app main loop directly in JS, the whole app just freezes)
- This produces a .hap or .app package which can be installed in OpenHarmony and HarmonyOS Emulators (you will need to apply for a certificate to sign the app before testing it on a real HarmonyOS machine)
Building the example app and test it (HarmonyOS Emulator)
================================================================================
Download the DevEco Studio, and open the ohos-project folder in this repo
Then, download a emulator in the Device Manager tab, and runs it.
Click the run button, the IDE will automatically build the app and run it for you, you can act with your app in the emulator window.

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

@ -277,6 +277,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@
@ -343,6 +344,7 @@
/* Enable various sensor drivers */
#cmakedefine SDL_SENSOR_ANDROID 1
#cmakedefine SDL_SENSOR_OHOS 1
#cmakedefine SDL_SENSOR_COREMOTION 1
#cmakedefine SDL_SENSOR_WINDOWS 1
#cmakedefine SDL_SENSOR_DUMMY 1
@ -409,6 +411,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
@ -498,6 +501,7 @@
/* Enable system power support */
#cmakedefine SDL_POWER_ANDROID 1
#cmakedefine SDL_POWER_OHOS 1
#cmakedefine SDL_POWER_LINUX 1
#cmakedefine SDL_POWER_WINDOWS 1
#cmakedefine SDL_POWER_MACOSX 1
@ -513,6 +517,7 @@
/* Enable system filesystem support */
#cmakedefine SDL_FILESYSTEM_ANDROID 1
#cmakedefine SDL_FILESYSTEM_OHOS 1
#cmakedefine SDL_FILESYSTEM_HAIKU 1
#cmakedefine SDL_FILESYSTEM_COCOA 1
#cmakedefine SDL_FILESYSTEM_DUMMY 1

12
ohos-project/.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
/node_modules
/oh_modules
/local.properties
/.idea
**/build
/.hvigor
.cxx
/.clangd
/.clang-format
/.clang-tidy
**/.test
/.appanalyzer

View file

@ -0,0 +1,10 @@
{
"app": {
"bundleName": "org.libsdl.SdlShell",
"vendor": "libsdl-org",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:layered_image",
"label": "$string:app_name"
}
}

View file

@ -0,0 +1,12 @@
{
"string": [
{
"name": "app_name",
"value": "SDL Demo"
},
{
"name": "perm_reason",
"value": "Subsystem for SDL / SDL 子系统"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,7 @@
{
"layered-image":
{
"background" : "$media:background",
"foreground" : "$media:foreground"
}
}

View file

@ -0,0 +1,43 @@
{
"app": {
"signingConfigs": [],
"products": [
{
"name": "default",
"signingConfig": "default",
"targetSdkVersion": "6.0.0(20)",
"compatibleSdkVersion": "5.0.0(12)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"nativeCompiler": "BiSheng",
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],
"buildModeSet": [
{
"name": "debug",
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}

View file

@ -0,0 +1,32 @@
{
"files": [
"**/*.ets"
],
"ignore": [
"**/src/ohosTest/**/*",
"**/src/test/**/*",
"**/src/mock/**/*",
"**/node_modules/**/*",
"**/oh_modules/**/*",
"**/build/**/*",
"**/.preview/**/*"
],
"ruleSet": [
"plugin:@performance/recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"@security/no-unsafe-aes": "error",
"@security/no-unsafe-hash": "error",
"@security/no-unsafe-mac": "warn",
"@security/no-unsafe-dh": "error",
"@security/no-unsafe-dsa": "error",
"@security/no-unsafe-ecdsa": "error",
"@security/no-unsafe-rsa-encrypt": "error",
"@security/no-unsafe-rsa-sign": "error",
"@security/no-unsafe-rsa-key": "error",
"@security/no-unsafe-dsa-key": "error",
"@security/no-unsafe-dh-key": "error",
"@security/no-unsafe-3des": "error"
}
}

6
ohos-project/entry/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

View file

@ -0,0 +1,45 @@
{
"apiType": "stageMode",
"buildOption": {
"resOptions": {
"copyCodeResource": {
"enable": false
}
},
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=1",
"cppFlags": "",
"abiFilters": ["arm64-v8a", "x86_64"]
}
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": [
"./obfuscation-rules.txt"
]
}
}
},
"nativeLib": {
"debugSymbol": {
"strip": true,
"exclude": []
}
}
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}

View file

@ -0,0 +1,6 @@
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
}

View file

@ -0,0 +1,23 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope
-enable-property-obfuscation
-enable-toplevel-obfuscation
-enable-filename-obfuscation
-enable-export-obfuscation

View file

@ -0,0 +1,19 @@
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"libSDL3.so@src/main/cpp/sdl": "libSDL3.so@src/main/cpp/sdl"
},
"packages": {
"libSDL3.so@src/main/cpp/sdl": {
"name": "libSDL3.so",
"version": "1.0.0",
"resolved": "",
"registryType": "local"
}
}
}

View file

@ -0,0 +1,11 @@
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"libSDL3.so": "file:./src/main/cpp/sdl"
}
}

View file

@ -0,0 +1,21 @@
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(MyApplication10)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
add_subdirectory(../../../../.. external/sdlbin)
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
add_definitions(-DVK_USE_PLATFORM_OHOS=1)
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include
${SDL3_SOURCE_DIR}/include)
add_library(entry SHARED entrypoint.cpp)
add_dependencies(entry SDL3::SDL3-shared)
target_link_libraries(entry PUBLIC libace_napi.z.so libSDL3.so libvulkan.so libGLESv2.so libohaudio.so libohsensor.so)

View file

@ -0,0 +1,177 @@
#include "SDL3/SDL_assert.h"
#include "SDL3/SDL_init.h"
#include "SDL3/SDL_messagebox.h"
#include "SDL3/SDL_misc.h"
#include "SDL3/SDL_render.h"
#include "SDL3/SDL_timer.h"
#include "SDL3/SDL_video.h"
#include "SDL3/SDL_vulkan.h"
#include "SDL3/SDL_locale.h"
#include "SDL3/SDL_clipboard.h"
#include "SDL3/SDL_log.h"
#include "SDL3/SDL_hints.h"
#include "SDL3/SDL_power.h"
#include "SDL3/SDL_dialog.h"
#include "SDL3/SDL_sensor.h"
#include <GLES2/gl2.h>
#include <stdlib.h>
#include <thread>
#include <unistd.h>
#include <vulkan/vulkan_core.h>
#include <ohaudio/native_audiorenderer.h>
#include <ohaudio/native_audiostreambuilder.h>
#include <fstream>
float vtxdata[] = {
-0.5f, -0.5f, 0.f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
float vtxdata2[] = {
0.f, 0.f, 1.f,
0.f, 1.f, 0.f,
1.f, 0.f, 0.f
};
int main()
{
/*OH_AudioStreamBuilder* builder;
OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
OH_AudioStreamBuilder_SetSamplingRate(builder, 48000);
OH_AudioStreamBuilder_SetChannelCount(builder, 2);
OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_U8);
OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
// OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST);
OH_AudioRenderer_Callbacks callbacks;
srand(time(nullptr));
callbacks.OH_AudioRenderer_OnStreamEvent = nullptr;
callbacks.OH_AudioRenderer_OnInterruptEvent = nullptr;
callbacks.OH_AudioRenderer_OnError = nullptr;
callbacks.OH_AudioRenderer_OnWriteData = [](OH_AudioRenderer* renderer, void* userData, void* buffer, int32_t length) {
auto p = (uint8_t *)buffer;
int t = length;
while (t > 0) {
*p = rand() % 255;
p++;
t--;
}
return 0;
};
OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
OH_AudioRenderer* audioRenderer;
OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
OH_AudioRenderer_Start(audioRenderer);
OH_AudioStreamBuilder_Destroy(builder);*/
SDL_SetHint(SDL_HINT_EGL_LIBRARY, "libEGL.so");
SDL_SetHint(SDL_HINT_OPENGL_LIBRARY, "libGLESv2.so");
SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "libGLESv2.so");
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_SENSOR);
int i = 0;
auto t = SDL_GetPreferredLocales(&i);
SDL_Log("Main func invoke !!! %s %s", t[0]->country, t[0]->language);
// SDL_GL_LoadLibrary("libGLESv2.so");
SDL_Log("sdl error: %s", SDL_GetError());
SDL_Window* win = SDL_CreateWindow("test", 1024, 1024, SDL_WINDOW_OPENGL);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "SDL Application", "test!", win);
auto context = SDL_GL_CreateContext(win);
SDL_GL_MakeCurrent(win, context);
int frgshader = ((PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"))(GL_FRAGMENT_SHADER);
int vexshader = ((PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"))(GL_VERTEX_SHADER);
auto frag = "varying vec4 v_color;void main() {gl_FragColor = v_color;}";
((PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"))(frgshader, 1, &frag, nullptr);
((PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"))(frgshader);
int status = 1;
((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(frgshader, GL_COMPILE_STATUS, &status);
int status2 = 1;
((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(frgshader, GL_INFO_LOG_LENGTH, &status2);
std::string log(status2, '\0');
((PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"))(frgshader, status2, nullptr, (char*)log.c_str());
SDL_Log("test: %d %d %s", status, status2, log.c_str());
auto vert = "attribute vec3 pos;attribute vec3 color;varying vec4 v_color;void main() {gl_Position=vec4(pos,1.0);v_color=vec4(color, 1.0);}";
((PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"))(vexshader, 1, &vert, nullptr);
((PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"))(vexshader);
((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(vexshader, GL_COMPILE_STATUS, &status);
((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(vexshader, GL_INFO_LOG_LENGTH, &status2);
std::string log2(status2, '\0');
((PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"))(vexshader, status2, nullptr, (char*)log2.c_str());
SDL_Log("test: %d %d %s", status, status2, log2.c_str());
auto prog = ((PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram"))();
((PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"))(prog, vexshader);
((PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"))(prog, frgshader);
((PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram"))(prog);
((PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv"))(prog, GL_LINK_STATUS, &status);
SDL_Log("link: %d", status);
((PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"))(vexshader);
((PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"))(frgshader);
((PFNGLCLEARCOLORPROC)SDL_GL_GetProcAddress("glClearColor"))(0, 0, 0, 0);
while (true) {
SDL_StartTextInput(win);
int w, h;
SDL_GetWindowSize(win, &w, &h);
((PFNGLVIEWPORTPROC)SDL_GL_GetProcAddress("glViewport"))(0, 0, w, h);
((PFNGLCLEARPROC)SDL_GL_GetProcAddress("glClear"))(GL_COLOR_BUFFER_BIT);
((PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"))(prog);
for (int i = 0; i < 9; i++) {
vtxdata2[i] = SDL_randf();
/*vtxdata2[i] += 0.01f;
if (vtxdata2[i] >= 1.f) {
vtxdata2[i] = 0.f;
}*/
}
((PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"))(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)vtxdata);
((PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"))(0);
((PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"))(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)vtxdata2);
((PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"))(1);
((PFNGLDRAWARRAYSPROC)SDL_GL_GetProcAddress("glDrawArrays"))(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(win);
SDL_Event event;
if (SDL_PollEvent(&event)) {
SDL_Log("event type: %d", event.type);
if (event.type == SDL_EVENT_FINGER_DOWN || event.type == SDL_EVENT_FINGER_UP || event.type == SDL_EVENT_FINGER_MOTION) {
SDL_Log("finger %f %f", event.tfinger.x, event.tfinger.y);
}
if (event.type == SDL_EVENT_QUIT) {
break;
}
if (event.type == SDL_EVENT_TEXT_INPUT) {
SDL_Log("text %s", event.text.text);
}
}
}
SDL_Log("glversion: %s", ((PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString"))(GL_VERSION));
SDL_GL_DestroyContext(context);
SDL_DestroyWindow(win);
return 0;
}

View file

@ -0,0 +1,14 @@
export const sdlCallbackInit: (d) => void;
export const sdlLaunchMain: (lib: string, func: string) => number;
export const sdlKeyEvent: (scancode: number, type: number) => number;
export const sdlTextAppend: (str: string) => number;
export const sdlTextEditing: (str: string, loc: number, length: number) => number;
export const sdlDialogExecCallback: () => void;
export const sdlDialogClearSelection: () => void;
export const sdlDialogFileSelected: (path: string) => void;
export const sdlSendDialogStatus: (idx: number) => void;
export const sdlOnBackground: () => void;
export const sdlOnForeground: () => void;
export const sdlOnLowMemory: () => void;
export const sdlOnTerminate: () => void;
export const sdlOnConfigUpdate: () => void;

View file

@ -0,0 +1,6 @@
{
"name": "libSDL3.so",
"types": "./Index.d.ts",
"version": "1.0.0",
"description": "Please describe the basic information."
}

View file

@ -0,0 +1,93 @@
import { abilityAccessCtrl, AbilityConstant,
common,
Configuration,
ConfigurationConstant,
Permissions,
UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { KeyboardAvoidMode } from '@ohos.arkui.UIContext';
import { BusinessError } from '@kit.BasicServicesKit';
import sdl from 'libSDL3.so';
const DOMAIN = 0x0000;
const permissions: Array<Permissions> = ['ohos.permission.INPUT_KEYBOARD_CONTROLLER', 'ohos.permission.READ_PASTEBOARD'];
function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
for (let i = 0; i < length; i++) {
if (grantStatus[i] === 0) {
// promptAction.showDialog({title: "permissions", message: "granted", buttons: [{text: 'Ok', color: '#999999'}]});
} else {
// promptAction.showDialog({title: "permissions", message: "not granted", buttons: [{text: 'Ok', color: '#999999'}]});
return;
}
}
// 授权成功
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
})
}
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onDestroy');
}
async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
reqPermissionsFromUser(permissions, this.context);
windowStage.getMainWindow().then(async (win) => {
try {
win.getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET)
} catch (error) {
let ll: BusinessError = error;
hilog.error(DOMAIN, 'surfaceLayer', 'Failed to load the content. Cause: %{public}s', JSON.stringify(ll));
}
})
if (err.code) {
hilog.error(DOMAIN, 'surfaceLayer', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'surfaceLayer', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onWindowStageDestroy');
sdl.sdlOnTerminate();
}
onForeground(): void {
hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onForeground');
sdl.sdlOnForeground();
}
onBackground(): void {
hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onBackground');
sdl.sdlOnBackground();
}
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
if (level == AbilityConstant.MemoryLevel.MEMORY_LEVEL_LOW || level == AbilityConstant.MemoryLevel.MEMORY_LEVEL_CRITICAL) {
sdl.sdlOnLowMemory();
}
}
onConfigurationUpdate(newConfig: Configuration): void {
sdl.sdlOnConfigUpdate();
}
}

View file

@ -0,0 +1,16 @@
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
const DOMAIN = 0x0000;
export default class EntryBackupAbility extends BackupExtensionAbility {
async onBackup() {
hilog.info(DOMAIN, 'surfaceLayer', 'onBackup ok');
await Promise.resolve();
}
async onRestore(bundleVersion: BundleVersion) {
hilog.info(DOMAIN, 'surfaceLayer', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
await Promise.resolve();
}
}

View file

@ -0,0 +1,212 @@
import { hilog } from '@kit.PerformanceAnalysisKit';
import sdl from 'libSDL3.so';
import { intl } from '@kit.LocalizationKit';
import { promptAction, ShowDialogSuccessResponse } from '@kit.ArkUI';
import { inputMethod } from '@kit.IMEKit'
import { deviceInfo, pasteboard } from '@kit.BasicServicesKit';
import { common, ConfigurationConstant } from '@kit.AbilityKit';
import { batteryInfo } from '@kit.BasicServicesKit';
import { picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN = 0x0000;
let controller = inputMethod.getController()
let input = false
let targetText = ""
let context: UIContext
export class ArkNapiCallback {
onMainLaunch() {
sdl.sdlLaunchMain("libentry.so", "main")
}
showDialog(title: string, message: string, indexMapping: number[], names: string[]) {
let target: promptAction.Button[] = []
for (let i = 0; i < names.length; i++)
{
target.push({ text: names[i], color: '#999999' })
}
promptAction.showDialog({ title: title, message: message, buttons: target }).then((a) => {
sdl.sdlSendDialogStatus(indexMapping[a.index])
})
}
fetchLocale(): string {
let locale = new intl.Locale()
return locale.language + "_" + locale.region
}
firstCall() {
hilog.info(DOMAIN, 'surfaceLayer', 'Native binding finished.')
sdl.sdlOnConfigUpdate();
}
openLink(url: string) {
let con = context.getHostContext() as common.UIAbilityContext
con.openLink(url)
}
hasBattery(): number {
return batteryInfo.isBatteryPresent ? 1 : 0
}
batteryCharging(): number {
return batteryInfo.chargingStatus == batteryInfo.BatteryChargeState.ENABLE ? 1 : 0
}
batteryCharged(): number {
return batteryInfo.chargingStatus == batteryInfo.BatteryChargeState.FULL ? 1 : 0
}
batteryPercent(): number {
return batteryInfo.batterySOC
}
setPasteboardString(text: string) {
let pasteData: pasteboard.PasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text);
let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard();
systemPasteboard.setData(pasteData, (err, data) => {
if (err) {
hilog.error(DOMAIN, 'surfaceLayer', 'Failed to set PasteData. Cause: ' + err.message);
return;
}
hilog.info(DOMAIN, 'surfaceLayer', 'Succeed in setting PasteData.');
});
}
textEditing(): number {
return input ? 1 : 0;
}
startTextInput() {
input = true
controller.showTextInput()
hilog.info(DOMAIN, 'surfaceLayer', 'text input start')
}
stopTextInput() {
input = false
controller.hideTextInput()
hilog.info(DOMAIN, 'surfaceLayer', 'text input stop')
targetText = ""
}
openFileDialog(id: number, defpath: string, itemcount: number, filter: string) {
const documentSelectOptions = new picker.DocumentSelectOptions();
documentSelectOptions.maxSelectNumber = itemcount;
documentSelectOptions.defaultFilePathUri = defpath;
if (id == 0 || id == 1)
{
documentSelectOptions.selectMode = picker.DocumentSelectMode.FILE;
}
if (id == 2)
{
documentSelectOptions.selectMode = picker.DocumentSelectMode.FOLDER;
}
let targetfilter: string[] = []
let temp = filter.split('\u0002')
for (let index = 0; index < temp.length; index++) {
const element = temp[index];
let temp2 = element.split("|")
// broken filter!
if (temp2.length == 1)
{
targetfilter.push(element + "|.*")
}
else
{
let targettemp = temp2[0] + "|";
let temp3 = temp2[1].split(";")
for (let index1 = 0; index1 < temp3.length; index1++) {
targettemp += "." + temp3[index1] + ",";
}
targetfilter.push(targettemp)
}
}
documentSelectOptions.fileSuffixFilters = targetfilter;
documentSelectOptions.authMode = false;
documentSelectOptions.mergeMode = picker.MergeTypeMode.DEFAULT;
documentSelectOptions.isEncryptionSupported = false;
let uris: string[] = [];
let contextt = context.getHostContext() as common.UIAbilityContext;
const documentViewPicker = new picker.DocumentViewPicker(contextt);
documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
uris = documentSelectResult;
sdl.sdlDialogClearSelection()
for (let idx = 0; idx < uris.length; idx++)
{
let target = uris[idx].replace("file://docs", "")
sdl.sdlDialogFileSelected(target)
console.info('documentViewPicker.select to file succeed and uris are: ' + target);
}
sdl.sdlDialogExecCallback()
}).catch((err: BusinessError) => {
console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
}
getInternalPath(): string {
let contextt = context.getHostContext() as common.UIAbilityContext
return contextt.filesDir
}
themeIsDark(): number {
let contextt = context.getHostContext() as common.UIAbilityContext
return (contextt.config.colorMode == ConfigurationConstant.ColorMode.COLOR_MODE_DARK) ? 1 : 0;
}
isPhone(): number {
return deviceInfo.deviceType == "phone" ? 1 : 0;
}
}
let callbackRef: ArkNapiCallback = new ArkNapiCallback()
@Entry
@Component
struct Index {
async aboutToAppear(): Promise<void> {
context = this.getUIContext()
sdl.sdlCallbackInit(callbackRef)
focusControl.requestFocus('mainView')
await controller.attach(true, {
inputAttribute: {
textInputType: inputMethod.TextInputType.TEXT,
enterKeyType: inputMethod.EnterKeyType.DONE
}
});
controller.on('insertText', (text) => {
targetText += text;
sdl.sdlTextAppend(text)
})
controller.on('deleteLeft', (i) => {
sdl.sdlTextEditing(targetText, targetText.length - 1 - i, i);
if (targetText.length > 0) {
targetText = targetText.substring(0, targetText.length - i)
}
})
controller.on('deleteRight', (i) => {
sdl.sdlTextEditing(targetText, 0, i);
if (targetText.length > 0) {
targetText = targetText.substring(i, targetText.length)
}
})
}
build() {
Column() {
XComponent({ id: 'mainView', type: 'surface', libraryname: 'SDL3' })
.id('mainView')
}
.onKeyEvent((keyevent) => {
sdl.sdlKeyEvent(keyevent.keyCode, keyevent.type);
})
}
}

View file

@ -0,0 +1,76 @@
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"requestPermissions": [
{
"name": "ohos.permission.INPUT_KEYBOARD_CONTROLLER",
"reason": "$string:perm_reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"inuse"
}
},
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.ACCELEROMETER"
},
{
"name": "ohos.permission.GYROSCOPE"
}
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"orientation": "landscape",
"exported": true,
"supportWindowMode": ["floating", "fullscreen", "split"],
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
]
}
}

View file

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View file

@ -0,0 +1,8 @@
{
"float": [
{
"name": "page_text_font_size",
"value": "50fp"
}
]
}

View file

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "SDL Demo"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

@ -0,0 +1,7 @@
{
"layered-image":
{
"background" : "$media:background",
"foreground" : "$media:foreground"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,3 @@
{
"allowToBackupRestore": true
}

View file

@ -0,0 +1,5 @@
{
"src": [
"pages/Index"
]
}

View file

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#000000"
}
]
}

View file

@ -0,0 +1,23 @@
{
"modelVersion": "6.0.0",
"dependencies": {
},
"execution": {
// "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
// "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */
},
"logging": {
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
},
"debugging": {
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
},
"nodeOptions": {
// "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
// "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
}
}

View file

@ -0,0 +1,6 @@
import { appTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
}

View file

@ -0,0 +1,28 @@
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
"@ohos/hypium@1.0.24": "@ohos/hypium@1.0.24"
},
"packages": {
"@ohos/hamock@1.0.0": {
"name": "",
"version": "1.0.0",
"integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
"registryType": "ohpm"
},
"@ohos/hypium@1.0.24": {
"name": "",
"version": "1.0.24",
"integrity": "sha512-3dCqc+BAR5LqEGG2Vtzi8O3r7ci/3fYU+FWjwvUobbfko7DUnXGOccaror0yYuUhJfXzFK0aZNMGSnXaTwEnbw==",
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.24.har",
"registryType": "ohpm"
}
}
}

View file

@ -0,0 +1,10 @@
{
"modelVersion": "6.0.0",
"description": "Please describe the basic information.",
"dependencies": {
},
"devDependencies": {
"@ohos/hypium": "1.0.24",
"@ohos/hamock": "1.0.0"
}
}

View file

@ -61,6 +61,10 @@
#include "core/android/SDL_android.h"
#endif
#ifdef SDL_PLATFORM_OHOS
#include "core/ohos/SDL_ohos.h"
#endif
#define SDL_ALL_SUBSYSTEM_FLAGS ~0U
// Initialization/Cleanup routines
@ -824,6 +828,8 @@ const char *SDL_GetPlatform(void)
return "GNU/Hurd";
#elif defined(__managarm__)
return "Managarm";
#elif defined(SDL_PLATFORM_OHOS)
return "OpenHarmony/HarmonyOS";
#else
return "Unknown (see SDL_platform.h)";
#endif
@ -836,6 +842,8 @@ bool SDL_IsPhone(void)
if (!SDL_IsTablet() && !SDL_IsTV()) {
return true;
}
#elif defined(SDL_PLATFORM_OHOS)
return OHOS_IsPhone();
#endif
return false;
}

View file

@ -40,6 +40,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.
@ -124,6 +128,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();
@ -583,7 +600,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) {
@ -594,7 +611,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)
{
@ -765,6 +782,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

@ -530,6 +530,9 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32 *dst, const U
}
#endif
#ifndef SDL_PLATFORM_OHOS
#undef SDL_NEON_INTRINSICS
#endif
#ifdef SDL_NEON_INTRINSICS
// C99 requires that all code modifying floating point environment should

1020
src/core/ohos/SDL_ohos.c Normal file

File diff suppressed because it is too large Load diff

40
src/core/ohos/SDL_ohos.h Normal file
View file

@ -0,0 +1,40 @@
#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();
int OHOS_MessageBox(const char* title, const char* message, int ml, int* mapping, int bl, const char * const *buttons);
const char* OHOS_Locale();
void OHOS_OpenLink(const char* url);
bool OHOS_IsBatteryPresent();
bool OHOS_IsBatteryCharging();
bool OHOS_IsBatteryCharged();
int OHOS_GetBatteryPercent();
void OHOS_SetClipboardText(const char* data);
char* OHOS_GetStoragePath();
bool OHOS_ThemeDark();
bool OHOS_IsPhone();
void OHOS_FileDialog(int id, const char* defpath, int allowmany, const char* filter);
bool OHOS_IsScreenKeyboardShown();
void OHOS_StartTextInput();
void OHOS_StopTextInput();
typedef struct SDL_VideoData {
SDL_Rect textRect;
int isPaused;
int isPausing;
} SDL_VideoData;
#endif

View file

@ -0,0 +1,92 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "../SDL_dialog.h"
#include "../../core/ohos/SDL_ohos.h"
#define MAX_FILENUM 256
static SDL_DialogFileCallback current = NULL;
static void* userdatad = NULL;
static const char* paths[MAX_FILENUM];
static int idxCurrent = 0;
void SDL_OHOS_FileSelected(const char* data)
{
if (idxCurrent >= MAX_FILENUM) {
return;
}
paths[idxCurrent] = data;
idxCurrent++;
}
void SDL_OHOS_ClearSelection()
{
for (int i = 0; i < MAX_FILENUM; i++) {
paths[i] = NULL;
}
idxCurrent = 0;
}
void SDL_OHOS_ExecCallback()
{
if (current) {
current(userdatad, (const char * const *)paths, 0);
}
}
void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
{
current = callback;
userdatad = userdata;
const char* defpath = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, "");
bool allowmany = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
void* rawfilters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL);
int filterscount = SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
char* filterstring = (char*)SDL_malloc(1024);
if (rawfilters && filterscount > 0) {
SDL_DialogFileFilter *data = (SDL_DialogFileFilter*)rawfilters;
char *begin = filterstring;
for (int idx = 0; idx < filterscount; idx++)
{
SDL_DialogFileFilter filter = data[idx];
if (begin - filterstring + SDL_strlen(filter.name) >= 1024) break;
SDL_memcpy(begin, filter.name, SDL_strlen(filter.name));
begin += SDL_strlen(filter.name);
if (begin - filterstring + 1 >= 1024) break;
*begin = '|';
begin++;
if (begin - filterstring + SDL_strlen(filter.pattern) >= 1024) break;
SDL_memcpy(begin, filter.pattern, SDL_strlen(filter.pattern));
begin += SDL_strlen(filter.pattern);
if (begin - filterstring + 1 >= 1024) break;
*begin = (char)0x2;
begin++;
}
}
OHOS_FileDialog(type, defpath, allowmany ? MAX_FILENUM : 1, filterstring);
}

View file

@ -0,0 +1,58 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#if defined(SDL_FILESYSTEM_OHOS)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// System dependent filesystem routines
#include "../SDL_sysfilesystem.h"
#include "../../core/ohos/SDL_ohos.h"
char *SDL_SYS_GetBasePath(void)
{
SDL_Unsupported();
return NULL;
}
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{
return OHOS_GetStoragePath();
}
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
{
SDL_Unsupported();
return NULL;
}
char *SDL_SYS_GetCurrentDirectory(void)
{
const char *base = SDL_GetBasePath();
if (!base) {
return NULL;
}
return SDL_strdup(base);
}
#endif // SDL_FILESYSTEM_OHOS

View file

@ -0,0 +1,11 @@
#include "SDL_internal.h"
#include "../SDL_syslocale.h"
#include "../../core/ohos/SDL_ohos.h"
bool SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
{
const char* result = OHOS_Locale();
SDL_memcpy(buf, result, buflen);
SDL_Log("target %s", buf);
return true;
}

View file

@ -0,0 +1,10 @@
#include "SDL_internal.h"
#include "../../core/ohos/SDL_ohos.h"
#include "../SDL_sysurl.h"
bool SDL_SYS_OpenURL(const char *url)
{
OHOS_OpenLink(url);
return true;
}

View file

@ -74,6 +74,9 @@ static SDL_GetPowerInfo_Impl implementations[] = {
#ifdef SDL_POWER_EMSCRIPTEN // handles Emscripten
SDL_GetPowerInfo_Emscripten,
#endif
#ifdef SDL_POWER_OHOS
SDL_GetPowerInfo_OHOS
#endif
#ifdef SDL_POWER_HARDWIRED
SDL_GetPowerInfo_Hardwired,

View file

@ -35,6 +35,7 @@ bool SDL_GetPowerInfo_UIKit(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_MacOSX(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_Haiku(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_OHOS(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_VITA(SDL_PowerState *, int *, int *);
bool SDL_GetPowerInfo_N3DS(SDL_PowerState *, int *, int *);

View file

@ -0,0 +1,46 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifndef SDL_POWER_DISABLED
#ifdef SDL_POWER_OHOS
#include "../SDL_syspower.h"
#include "../../core/ohos/SDL_ohos.h"
bool SDL_GetPowerInfo_OHOS(SDL_PowerState *state, int *seconds, int *percent)
{
if (!OHOS_IsBatteryPresent()) {
*state = SDL_POWERSTATE_NO_BATTERY;
return true;
}
else {
*seconds = -1;
*percent = OHOS_GetBatteryPercent();
*state = OHOS_IsBatteryCharging() ? SDL_POWERSTATE_CHARGING : (OHOS_IsBatteryCharged() ? SDL_POWERSTATE_CHARGED : SDL_POWERSTATE_ON_BATTERY);
}
return true;
}
#endif // SDL_POWER_OHOS
#endif // SDL_POWER_DISABLED

View file

@ -46,6 +46,9 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = {
#ifdef SDL_SENSOR_EMSCRIPTEN
&SDL_EMSCRIPTEN_SensorDriver,
#endif
#ifdef SDL_SENSOR_OHOS
&SDL_OHOS_SensorDriver,
#endif
#if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED)
&SDL_DUMMY_SensorDriver
#endif

View file

@ -108,5 +108,6 @@ extern SDL_SensorDriver SDL_DUMMY_SensorDriver;
extern SDL_SensorDriver SDL_VITA_SensorDriver;
extern SDL_SensorDriver SDL_N3DS_SensorDriver;
extern SDL_SensorDriver SDL_EMSCRIPTEN_SensorDriver;
extern SDL_SensorDriver SDL_OHOS_SensorDriver;
#endif // SDL_syssensor_h_

View file

@ -0,0 +1,226 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef SDL_SENSOR_OHOS
#include "../SDL_syssensor.h"
#include "sensors/oh_sensor.h"
#include "sensors/oh_sensor_type.h"
typedef struct {
Sensor_Info *info;
Sensor_Subscriber *subs;
Sensor_SubscriptionId *subid;
Sensor_SubscriptionAttribute *subattr;
SDL_Sensor *sensor;
SDL_SensorID id;
} OHSensorMapping;
static uint32_t sensorCount;
static OHSensorMapping *mapping;
static bool SDL_OHOS_SensorInit(void)
{
Sensor_Info **infobase;
uint32_t s;
if (OH_Sensor_GetInfos(NULL, &s) != SENSOR_SUCCESS) {
return false;
}
sensorCount = s;
infobase = OH_Sensor_CreateInfos(s);
mapping = (OHSensorMapping *)SDL_calloc(sizeof(OHSensorMapping), s);
if (OH_Sensor_GetInfos(infobase, &s) != SENSOR_SUCCESS) {
return false;
}
for (int i = 0; i < s; i++)
{
mapping[i].sensor = NULL;
mapping[i].info = infobase[i];
mapping[i].id = SDL_GetNextObjectID();
}
return true;
}
static int SDL_OHOS_SensorGetCount(void)
{
return sensorCount;
}
static void SDL_OHOS_SensorDetect(void)
{
}
static const char *SDL_OHOS_SensorGetDeviceName(int device_index)
{
char *data;
uint32_t length;
OH_SensorInfo_GetName(mapping[device_index].info, NULL, &length);
data = (char*)SDL_malloc(length);
OH_SensorInfo_GetName(mapping[device_index].info, data, &length);
return data;
}
static SDL_SensorType SDL_OHOS_SensorGetDeviceType(int device_index)
{
Sensor_Type type;
if (OH_SensorInfo_GetType(mapping[device_index].info, &type) != SENSOR_SUCCESS) {
return SDL_SENSOR_INVALID;
}
switch (type) {
case SENSOR_TYPE_ACCELEROMETER:
return SDL_SENSOR_ACCEL;
case SENSOR_TYPE_GYROSCOPE:
return SDL_SENSOR_GYRO;
default:
return SDL_SENSOR_UNKNOWN;
}
}
static int SDL_OHOS_SensorGetDeviceNonPortableType(int device_index)
{
Sensor_Type type;
if (OH_SensorInfo_GetType(mapping[device_index].info, &type) != SENSOR_SUCCESS) {
return -1;
}
return type;
}
static SDL_SensorID SDL_OHOS_SensorGetDeviceInstanceID(int device_index)
{
return mapping[device_index].id;
}
static void SDL_OHOS_EventSub(Sensor_Event *event)
{
Sensor_Type type;
if (OH_SensorEvent_GetType(event, &type) != SENSOR_SUCCESS) {
return;
}
int64_t timestamp;
if (OH_SensorEvent_GetTimestamp(event, &timestamp) != SENSOR_SUCCESS) {
return;
}
for (int i = 0; i < sensorCount; i++) {
if (mapping[i].sensor && SDL_OHOS_SensorGetDeviceNonPortableType(i) == type) {
uint32_t length;
if (OH_SensorEvent_GetData(event, NULL, &length) != SENSOR_SUCCESS) {
return;
}
float *data = (float *)SDL_malloc(sizeof(float) * length);
if (OH_SensorEvent_GetData(event, &data, &length) != SENSOR_SUCCESS) {
return;
}
SDL_SendSensorUpdate(timestamp, mapping[i].sensor, timestamp, data, length);
SDL_free(data);
break;
}
}
}
static bool SDL_OHOS_SensorOpen(SDL_Sensor *sensor, int device_index)
{
if (device_index >= sensorCount) {
return false;
}
mapping[device_index].sensor = sensor;
mapping[device_index].subs = OH_Sensor_CreateSubscriber();
if (OH_SensorSubscriber_SetCallback(mapping[device_index].subs, SDL_OHOS_EventSub) != SENSOR_SUCCESS) {
return false;
}
mapping[device_index].subid = OH_Sensor_CreateSubscriptionId();
if (OH_SensorSubscriptionId_SetType(mapping[device_index].subid, (Sensor_Type)SDL_OHOS_SensorGetDeviceNonPortableType(device_index)) != SENSOR_SUCCESS) {
return false;
}
mapping[device_index].subattr = OH_Sensor_CreateSubscriptionAttribute();
if (OH_SensorSubscriptionAttribute_SetSamplingInterval(mapping[device_index].subattr, 10000000) != SENSOR_SUCCESS) {
return false;
}
if (OH_Sensor_Subscribe(mapping[device_index].subid, mapping[device_index].subattr, mapping[device_index].subs) != SENSOR_SUCCESS) {
return false;
}
return true;
}
static void SDL_OHOS_SensorUpdate(SDL_Sensor *sensor)
{
}
static void SDL_OHOS_SensorClose(SDL_Sensor *sensor)
{
for (int i = 0; i < sensorCount; i++) {
if (mapping[i].sensor == sensor) {
mapping[i].sensor = NULL;
OH_Sensor_Unsubscribe(mapping[i].subid, mapping[i].subs);
if (mapping[i].subattr) {
OH_Sensor_DestroySubscriptionAttribute(mapping[i].subattr);
mapping[i].subattr = NULL;
}
if (mapping[i].subid) {
OH_Sensor_DestroySubscriptionId(mapping[i].subid);
mapping[i].subid = NULL;
}
if (mapping[i].subs) {
OH_Sensor_DestroySubscriber(mapping[i].subs);
mapping[i].subs = NULL;
}
break;
}
}
}
static void SDL_OHOS_SensorQuit(void)
{
for (int i = 0; i < sensorCount; i++) {
if (mapping[i].sensor) {
SDL_OHOS_SensorClose(mapping[i].sensor);
}
}
sensorCount = 0;
SDL_free(mapping);
}
SDL_SensorDriver SDL_OHOS_SensorDriver = {
SDL_OHOS_SensorInit,
SDL_OHOS_SensorGetCount,
SDL_OHOS_SensorDetect,
SDL_OHOS_SensorGetDeviceName,
SDL_OHOS_SensorGetDeviceType,
SDL_OHOS_SensorGetDeviceNonPortableType,
SDL_OHOS_SensorGetDeviceInstanceID,
SDL_OHOS_SensorOpen,
SDL_OHOS_SensorUpdate,
SDL_OHOS_SensorClose,
SDL_OHOS_SensorQuit,
};
#endif // SDL_SENSOR_DUMMY || SDL_SENSOR_DISABLED

View file

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

View file

@ -547,6 +547,7 @@ extern VideoBootStrap OFFSCREEN_bootstrap;
extern VideoBootStrap QNX_bootstrap;
extern VideoBootStrap OPENVR_bootstrap;
extern VideoBootStrap DOSVESA_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

@ -110,6 +110,9 @@ static VideoBootStrap *bootstrap[] = {
#ifdef SDL_VIDEO_DRIVER_ANDROID
&Android_bootstrap,
#endif
#ifdef SDL_VIDEO_DRIVER_OHOS
&OHOS_bootstrap,
#endif
#ifdef SDL_VIDEO_DRIVER_PS2
&PS2_bootstrap,
#endif

View file

@ -0,0 +1,47 @@
#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();
OHOS_windowDataFill(window);
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);
}
#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,11 @@
#include "SDL_internal.h"
#include "events/SDL_mouse_c.h"
#include "SDL_ohosmouse.h"
void OHOS_OnMouse(SDL_OHOSMouseEvent event)
{
SDL_SendMouseMotion(event.timestamp, NULL, SDL_DEFAULT_MOUSE_ID, false, event.x, event.y);
if (!event.motion) {
SDL_SendMouseButton(event.timestamp, NULL, SDL_DEFAULT_MOUSE_ID, event.button, event.down);
}
}

View file

@ -0,0 +1,15 @@
#ifndef SDL_OHOSMOUSE_H
#define SDL_OHOSMOUSE_H
typedef struct SDL_OHOSMouseEvent {
float x;
float y;
long long timestamp;
int button;
bool motion;
bool down;
} SDL_OHOSMouseEvent;
void OHOS_OnMouse(SDL_OHOSMouseEvent event);
#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,141 @@
#include "../SDL_sysvideo.h"
#include "SDL_internal.h"
#include "dynapi/SDL_dynapi_overrides.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);
}
bool OHOS_SetClipboardTextImpl(SDL_VideoDevice *, const char *data)
{
OHOS_SetClipboardText(data);
return true;
}
bool OHOS_HasClipboardText(SDL_VideoDevice *)
{
return false;
}
bool OHOS_HasScreenKeyboardSupport(SDL_VideoDevice *)
{
return true;
}
bool OHOS_IsScreenKeyboardShownImpl(SDL_VideoDevice *, SDL_Window *)
{
return OHOS_IsScreenKeyboardShown();
}
bool OHOS_StartTextInputImpl(SDL_VideoDevice *, SDL_Window *, SDL_PropertiesID)
{
OHOS_StartTextInput();
return true;
}
bool OHOS_StopTextInputImpl(SDL_VideoDevice *, SDL_Window *)
{
OHOS_StopTextInput();
return true;
}
void OHOS_PumpEvents(SDL_VideoDevice *)
{
}
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
device->SetClipboardText = OHOS_SetClipboardTextImpl;
device->HasClipboardText = OHOS_HasClipboardText;
device->HasScreenKeyboardSupport = OHOS_HasScreenKeyboardSupport;
device->StartTextInput = OHOS_StartTextInputImpl;
device->StopTextInput = OHOS_StopTextInputImpl;
device->PumpEvents = OHOS_PumpEvents;
return device;
}
bool OHOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID)
{
int length1 = SDL_strlen(messageboxdata->title) + 1;
char* titlecopy = (char*)SDL_malloc(length1);
SDL_memcpy(titlecopy, messageboxdata->title, length1);
length1 = SDL_strlen(messageboxdata->message) + 1;
char* messagecopy = (char*)SDL_malloc(length1);
SDL_memcpy(messagecopy, messageboxdata->message, length1);
int* mapping = (int *)SDL_malloc(sizeof(int) * messageboxdata->numbuttons);
const char ** btns = (const char **)SDL_malloc(sizeof(void*) * messageboxdata->numbuttons);
for (int i = 0; i < messageboxdata->numbuttons; i++)
{
mapping[i] = messageboxdata->buttons[i].buttonID;
btns[i] = messageboxdata->buttons[i].text;
}
*buttonID = OHOS_MessageBox(titlecopy, messagecopy, messageboxdata->numbuttons, mapping, messageboxdata->numbuttons, btns);
return true;
}
VideoBootStrap OHOS_bootstrap = {
"ohos", "OpenHarmony video driver",
OHOS_CreateDevice,
OHOS_ShowMessageBox,
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