From d5290fc26983a9b232ece9a04edd67f848d8ed30 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Wed, 22 Jan 2025 11:40:49 +0100 Subject: [PATCH 1/6] util/detect_os: Add OpenHarmony OS support Signed-off-by: Christian Gmeiner --- src/util/detect_os.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/util/detect_os.h b/src/util/detect_os.h index 74037240c74..5c7a62bdd23 100644 --- a/src/util/detect_os.h +++ b/src/util/detect_os.h @@ -28,6 +28,14 @@ #define DETECT_OS_ANDROID 1 #endif +/* + * OpenHarmony defines __linux__, so DETECT_OS_LINUX and DETECT_OS_POSIX will + * also be defined. + */ +#if defined(__OHOS_FAMILY__) +#define DETECT_OS_OHOS 1 +#endif + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #define DETECT_OS_FREEBSD 1 #define DETECT_OS_BSD 1 @@ -146,5 +154,8 @@ #ifndef DETECT_OS_MANAGARM #define DETECT_OS_MANAGARM 0 #endif +#ifndef DETECT_OS_OHOS +#define DETECT_OS_OHOS 0 +#endif #endif /* DETECT_OS_H */ From da399c913448fd046e5170927ad7f2f8d5910a35 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 20 Jan 2025 15:41:30 +0100 Subject: [PATCH 2/6] meson: Add OHOS platform Signed-off-by: Christian Gmeiner --- meson.build | 11 ++++++++++- meson.options | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index f1b561b6ad5..3ab4b5ff0d9 100644 --- a/meson.build +++ b/meson.build @@ -334,7 +334,8 @@ if freedreno_kmds.length() != 0 and freedreno_kmds != [ 'msm' ] and with_freedre endif # This has to be below the freedreno_kmds check since that can change system_has_kms_drm -with_gallium_kmsro = with_gallium_drm or (system_has_kms_drm and with_gallium_zink) +# OHOS reports as 'linux' but has no libdrm, so exclude it from the zink+kmsro fallback. +with_gallium_kmsro = with_gallium_drm or (system_has_kms_drm and with_gallium_zink and not get_option('platforms').contains('ohos')) pre_args += ['-DMESA_SYSTEM_HAS_KMS_DRM=@0@'.format(system_has_kms_drm.to_int())] if host_machine.cpu_family() == 'x86' and with_glx_read_only_text @@ -482,6 +483,12 @@ with_platform_wayland = _platforms.contains('wayland') with_platform_haiku = _platforms.contains('haiku') with_platform_windows = _platforms.contains('windows') with_platform_macos = _platforms.contains('macos') +with_platform_ohos = _platforms.contains('ohos') + +if with_platform_ohos + pre_args += '-DVK_USE_PLATFORM_OHOS=1' + system_has_kms_drm = false +endif with_gfxstream_emulated_android = with_gfxstream_vk and with_platform_android and host_machine.system() == 'linux' if with_gfxstream_emulated_android @@ -510,6 +517,8 @@ if with_glx == 'auto' with_glx = 'disabled' elif with_platform_android with_glx = 'disabled' + elif with_platform_ohos + with_glx = 'disabled' elif with_dri with_glx = 'dri' elif with_platform_haiku diff --git a/meson.options b/meson.options index 024b8340252..3429a4c41e5 100644 --- a/meson.options +++ b/meson.options @@ -12,7 +12,7 @@ option( type : 'array', value : ['auto'], choices : [ - 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'macos', + 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'macos', 'ohos', ], description : 'window systems to support. If this is set to `auto`, all ' + 'platforms applicable will be enabled.' @@ -23,7 +23,7 @@ option( type : 'combo', value : 'auto', choices : [ - 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', + 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'ohos', 'surfaceless', 'drm', ], description : 'the window system EGL assumes for EGL_DEFAULT_DISPLAY', From cd5048db2456ced60801350e9bf982fba7d55e24 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Wed, 22 Jan 2025 11:32:42 +0100 Subject: [PATCH 3/6] util/log: Add logger_ohos Use OHOS's HiLog module for logging. Signed-off-by: Christian Gmeiner --- src/util/log.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/util/meson.build | 4 ++++ 2 files changed, 50 insertions(+) diff --git a/src/util/log.c b/src/util/log.c index b594a8f8c30..604a7ca9324 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -44,12 +44,20 @@ #include #endif +#if DETECT_OS_OHOS +/* There is a conflict with syslog.h */ +#undef LOG_DEBUG +#undef LOG_INFO +#include +#endif + enum mesa_log_control { MESA_LOG_CONTROL_NULL = 1 << 0, MESA_LOG_CONTROL_FILE = 1 << 1, MESA_LOG_CONTROL_SYSLOG = 1 << 2, MESA_LOG_CONTROL_ANDROID = 1 << 3, MESA_LOG_CONTROL_WINDBG = 1 << 4, + MESA_LOG_CONTROL_OHOS = 1 << 5, MESA_LOG_CONTROL_LOGGER_MASK = 0xff, MESA_LOG_CONTROL_WAIT = 1 << 8, @@ -68,6 +76,7 @@ static const struct debug_control mesa_log_control_options[] = { { "syslog", MESA_LOG_CONTROL_SYSLOG }, { "android", MESA_LOG_CONTROL_ANDROID }, { "windbg", MESA_LOG_CONTROL_WINDBG }, + { "ohos", MESA_LOG_CONTROL_OHOS }, /* flags */ { "wait", MESA_LOG_CONTROL_WAIT }, { NULL, 0 }, @@ -120,6 +129,8 @@ mesa_log_init_once(void) /* pick the default loggers */ #if DETECT_OS_ANDROID mesa_log_control |= MESA_LOG_CONTROL_ANDROID; +#elif DETECT_OS_OHOS + mesa_log_control |= MESA_LOG_CONTROL_OHOS; #else mesa_log_control |= MESA_LOG_CONTROL_FILE; #endif @@ -420,6 +431,38 @@ logger_windbg(enum mesa_log_level level, #endif /* DETECT_OS_WINDOWS */ +#if DETECT_OS_OHOS + +static inline LogLevel +level_to_ohos(enum mesa_log_level l) +{ + switch (l) { + case MESA_LOG_ERROR: return LOG_ERROR; + case MESA_LOG_WARN: return LOG_WARN; + case MESA_LOG_INFO: return LOG_INFO; + case MESA_LOG_DEBUG: return LOG_DEBUG; + case MESA_NUM_LOG_LEVELS: + break; + } + + UNREACHABLE("bad mesa_log_level"); +} + +static void +logger_ohos(enum mesa_log_level level, + const char *tag, + const char *format, + va_list va) +{ + char local_msg[1024]; + char *msg = logger_vasnprintf(local_msg, sizeof(local_msg), 0, level, tag, + format, va); + + HiLogPrint(LOG_APP, level_to_ohos(level), 0xFF00, tag, "%{public}s", msg); +} + +#endif /* DETECT_OS_OHOS */ + /* This is for use with debug functions that take a FILE, such as * nir_print_shader, although switching to nir_log_shader* is preferred. */ @@ -460,6 +503,9 @@ mesa_log_v(enum mesa_log_level level, const char *tag, const char *format, #endif #if DETECT_OS_WINDOWS { MESA_LOG_CONTROL_WINDBG, logger_windbg }, +#endif +#if DETECT_OS_OHOS + { MESA_LOG_CONTROL_OHOS, logger_ohos }, #endif }; diff --git a/src/util/meson.build b/src/util/meson.build index 30cf227b13d..0b0ad552e1a 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -299,6 +299,10 @@ if with_platform_haiku deps_for_libmesa_util += dep_network endif +if with_platform_ohos + deps_for_libmesa_util += dependency('libhilog') +endif + if with_perfetto files_mesa_util += files( 'perf/u_perfetto.cc', From 375c838984411dc6858ce2670c16c365567d8182 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 28 Feb 2025 22:09:46 +0100 Subject: [PATCH 4/6] kopper: Add support for OHOS Signed-off-by: Christian Gmeiner --- src/gallium/drivers/zink/zink_instance.py | 11 ++++---- src/gallium/drivers/zink/zink_kopper.c | 31 +++++++++++++++++++++++ src/gallium/drivers/zink/zink_kopper.h | 3 ++- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/zink/zink_instance.py b/src/gallium/drivers/zink/zink_instance.py index 234d0ec02cd..ca334cf11ee 100755 --- a/src/gallium/drivers/zink/zink_instance.py +++ b/src/gallium/drivers/zink/zink_instance.py @@ -18,7 +18,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -# +# # Authors: # Hoe Hao Cheng # @@ -49,6 +49,7 @@ EXTENSIONS = [ Extension("VK_KHR_xcb_surface"), Extension("VK_KHR_win32_surface"), Extension("VK_EXT_swapchain_colorspace"), + Extension("VK_OHOS_surface"), ] if platform.system() == "Darwin": @@ -139,7 +140,7 @@ zink_create_instance(struct zink_screen *screen, struct zink_instance_info *inst /* reserve one slot for MoltenVK */ const char *layers[${len(layers) + 1}] = {0}; uint32_t num_layers = 0; - + const char *extensions[${len(extensions) + 1}] = {0}; uint32_t num_extensions = 0; @@ -361,7 +362,7 @@ zink_verify_instance_extensions(struct zink_screen *screen) def replace_code(code: str, replacement: dict): for (k, v) in replacement.items(): code = code.replace(k, v) - + return code @@ -395,7 +396,7 @@ if __name__ == "__main__": error_count += 1 print("The extension {} is not registered in vk.xml - a typo?".format(ext.name)) continue - + entry = registry.get_registry_entry(ext.name) if entry.ext_type != "instance": @@ -407,7 +408,7 @@ if __name__ == "__main__": ext.core_since = Version((*entry.promoted_in, 0)) if entry.platform_guard: - ext.platform_guard = entry.platform_guard + ext.platform_guard = entry.platform_guard if error_count > 0: print("zink_instance.py: Found {} error(s) in total. Quitting.".format(error_count)) diff --git a/src/gallium/drivers/zink/zink_kopper.c b/src/gallium/drivers/zink/zink_kopper.c index 2773efbe29f..5596f00bbfc 100644 --- a/src/gallium/drivers/zink/zink_kopper.c +++ b/src/gallium/drivers/zink/zink_kopper.c @@ -79,6 +79,11 @@ init_dt_type(struct kopper_displaytarget *cdt) case VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR: cdt->type = KOPPER_WIN32; break; +#endif +#ifdef VK_USE_PLATFORM_OHOS + case VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS: + cdt->type = KOPPER_OHOS; + break; #endif default: UNREACHABLE("unsupported!"); @@ -118,6 +123,13 @@ kopper_CreateSurface(struct zink_screen *screen, struct kopper_displaytarget *cd error = VKSCR(CreateWin32SurfaceKHR)(screen->instance, win32, NULL, &surface); break; } +#endif +#ifdef VK_USE_PLATFORM_OHOS + case VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS: { + VkSurfaceCreateInfoOHOS *sci = (VkSurfaceCreateInfoOHOS *)&cdt->info.bos; + error = VKSCR(CreateSurfaceOHOS)(screen->instance, sci, NULL, &surface); + break; + } #endif default: UNREACHABLE("unsupported!"); @@ -234,6 +246,13 @@ find_dt_entry(struct zink_screen *screen, const struct kopper_displaytarget *cdt he = _mesa_hash_table_search(&screen->dts, win32->hwnd); break; } +#endif +#ifdef VK_USE_PLATFORM_OHOS + case KOPPER_OHOS: { + VkSurfaceCreateInfoOHOS *sci = (VkSurfaceCreateInfoOHOS *)&cdt->info.bos; + he = _mesa_hash_table_search(&screen->dts, sci->window); + break; + } #endif default: UNREACHABLE("unsupported!"); @@ -340,6 +359,10 @@ kopper_CreateSwapchain(struct zink_screen *screen, struct kopper_displaytarget * cswap->scci.imageExtent.width = w; cswap->scci.imageExtent.height = h; break; + case KOPPER_OHOS: + cswap->scci.imageExtent.width = w; + cswap->scci.imageExtent.height = h; + break; default: UNREACHABLE("unknown display platform"); } @@ -444,6 +467,7 @@ zink_kopper_displaytarget_create(struct zink_screen *screen, unsigned tex_usage, break; case KOPPER_WAYLAND: case KOPPER_WIN32: + case KOPPER_OHOS: _mesa_hash_table_init(&screen->dts, screen, _mesa_hash_pointer, _mesa_key_pointer_equal); break; default: @@ -515,6 +539,13 @@ zink_kopper_displaytarget_create(struct zink_screen *screen, unsigned tex_usage, _mesa_hash_table_insert(&screen->dts, win32->hwnd, cdt); break; } +#endif +#ifdef VK_USE_PLATFORM_OHOS + case KOPPER_OHOS: { + VkSurfaceCreateInfoOHOS *sci = (VkSurfaceCreateInfoOHOS *)&cdt->info.bos; + _mesa_hash_table_insert(&screen->dts, sci->window, cdt); + break; + } #endif default: UNREACHABLE("unsupported!"); diff --git a/src/gallium/drivers/zink/zink_kopper.h b/src/gallium/drivers/zink/zink_kopper.h index d1971ecb8b5..26083238516 100644 --- a/src/gallium/drivers/zink/zink_kopper.h +++ b/src/gallium/drivers/zink/zink_kopper.h @@ -74,7 +74,8 @@ struct kopper_swapchain { enum kopper_type { KOPPER_X11, KOPPER_WAYLAND, - KOPPER_WIN32 + KOPPER_WIN32, + KOPPER_OHOS, }; struct kopper_displaytarget From cceee1f8729e3682597006014b360650b05054d4 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Sun, 23 Feb 2025 23:08:56 +0100 Subject: [PATCH 5/6] zink: Define VK_LIBNAME for OHOS Makes it possible for zink to load the Vulkan driver on OHOS. Signed-off-by: Christian Gmeiner --- src/gallium/drivers/zink/zink_screen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index e56ecb7a7c0..8988220eef6 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -74,6 +74,8 @@ bool zink_tracing = false; #define VK_LIBNAME "libvulkan.1.dylib" #elif DETECT_OS_ANDROID #define VK_LIBNAME "libvulkan.so" +#elif DETECT_OS_OHOS +#define VK_LIBNAME "libvulkan.so" #else #define VK_LIBNAME "libvulkan.so.1" #endif From f5e042e70265939cb6c5ee5fb81146f5a7578fe6 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 28 Feb 2025 22:18:25 +0100 Subject: [PATCH 6/6] egl_dri2: Add support for OHOS This is enough to make kopper happy. Signed-off-by: Christian Gmeiner --- src/egl/drivers/dri2/egl_dri2.c | 5 + src/egl/drivers/dri2/egl_dri2.h | 15 ++ src/egl/drivers/dri2/platform_ohos.c | 345 +++++++++++++++++++++++++++ src/egl/main/egldisplay.c | 1 + src/egl/main/egldisplay.h | 1 + src/egl/meson.build | 6 +- 6 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 src/egl/drivers/dri2/platform_ohos.c diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 89c31fb08b9..a5abc7a9273 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -897,6 +897,9 @@ dri2_initialize(_EGLDisplay *disp) case _EGL_PLATFORM_ANDROID: ret = dri2_initialize_android(disp); break; + case _EGL_PLATFORM_OHOS: + ret = dri2_initialize_ohos(disp); + break; default: UNREACHABLE("Callers ensure we cannot get here."); return EGL_FALSE; @@ -990,6 +993,8 @@ dri2_display_destroy(_EGLDisplay *disp) break; case _EGL_PLATFORM_DEVICE: break; + case _EGL_PLATFORM_OHOS: + break; default: UNREACHABLE("Platform teardown is not properly hooked."); break; diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 4ee70dfae18..f03745c5d30 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -385,6 +385,10 @@ struct dri2_egl_surface { uint32_t gralloc_usage; #endif +#ifdef HAVE_OHOS_PLATFORM + struct NativeWindow *window; +#endif + /* surfaceless and device */ struct dri_image *front; enum pipe_format visual; @@ -570,6 +574,17 @@ dri2_initialize_android(_EGLDisplay *disp) } #endif +#ifdef HAVE_OHOS_PLATFORM +EGLBoolean +dri2_initialize_ohos(_EGLDisplay *disp); +#else +static inline EGLBoolean +dri2_initialize_ohos(_EGLDisplay *disp) +{ + return _eglError(EGL_NOT_INITIALIZED, "OHOS platform not built"); +} +#endif + EGLBoolean dri2_initialize_surfaceless(_EGLDisplay *disp); diff --git a/src/egl/drivers/dri2/platform_ohos.c b/src/egl/drivers/dri2/platform_ohos.c new file mode 100644 index 00000000000..c3eeb2cc72c --- /dev/null +++ b/src/egl/drivers/dri2/platform_ohos.c @@ -0,0 +1,345 @@ +/* TODO */ + +#include +#include + +#include + +#include "dri_util.h" +#include "egl_dri2.h" +#include "kopper_interface.h" + +#include "display_type.h" +#include "external_window.h" + +static _EGLSurface * +ohos_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, + void *native_window, const EGLint *attrib_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); + struct dri2_egl_surface *dri2_surf; + struct NativeWindow *window = native_window; + const struct dri_config *config; + + dri2_surf = calloc(1, sizeof *dri2_surf); + if (!dri2_surf) { + _eglError(EGL_BAD_ALLOC, "ohos_create_surface"); + return NULL; + } + + if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, + false, native_window)) + goto cleanup_surface; + + if (type == EGL_WINDOW_BIT) { + int format = 0; + + OH_NativeWindow_NativeWindowHandleOpt(native_window, GET_FORMAT, &format); + if (format < 0) { + _eglError(EGL_BAD_NATIVE_WINDOW, "ohos_create_surface"); + goto cleanup_surface; + } + + if (format != dri2_conf->base.NativeVisualID) { + _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", format, + dri2_conf->base.NativeVisualID); + } + + OH_NativeWindow_NativeWindowHandleOpt(native_window, GET_BUFFER_GEOMETRY, + &dri2_surf->base.Height, + &dri2_surf->base.Width); + + dri2_surf->window = window; + } + + config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace); + if (!config) { + _eglError(EGL_BAD_MATCH, + "Unsupported surfacetype/colorspace configuration"); + goto cleanup_surface; + } + + if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) + goto cleanup_surface; + + if (window) + OH_NativeWindow_NativeObjectReference(window); + + return &dri2_surf->base; + +cleanup_surface: + free(dri2_surf); + return NULL; +} + +static EGLBoolean +device_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) +{ + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + + driDestroyDrawable(dri2_surf->dri_drawable); + + if (dri2_surf->window) + OH_NativeWindow_NativeObjectUnreference(dri2_surf->window); + + dri2_fini_surface(surf); + free(dri2_surf); + return EGL_TRUE; +} + +static _EGLSurface * +ohos_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, + void *native_window, const EGLint *attrib_list) +{ + return ohos_create_surface(disp, EGL_WINDOW_BIT, conf, native_window, + attrib_list); +} + +static _EGLSurface * +ohos_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf, + const EGLint *attrib_list) +{ + return ohos_create_surface(disp, EGL_PBUFFER_BIT, conf, NULL, attrib_list); +} + +static EGLBoolean +ohos_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) +{ + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + + driSwapBuffers(dri2_surf->dri_drawable); + + return EGL_TRUE; +} + +static const struct dri2_egl_display_vtbl dri2_ohos_display_vtbl = { + .create_window_surface = ohos_create_window_surface, + .create_pbuffer_surface = ohos_create_pbuffer_surface, + .destroy_surface = device_destroy_surface, + .create_image = dri2_create_image_khr, + .get_dri_drawable = dri2_surface_get_dri_drawable, + .swap_buffers = ohos_swap_buffers, +}; + +static void +kopperSetSurfaceCreateInfo(void *_draw, struct kopper_loader_info *out) +{ + struct dri2_egl_surface *dri2_surf = _draw; + VkSurfaceCreateInfoOHOS *sci = (VkSurfaceCreateInfoOHOS *)&out->bos; + + sci->sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS; + sci->pNext = NULL; + sci->flags = 0; + sci->window = dri2_surf->window; + + out->present_opaque = dri2_surf->base.PresentOpaque; + /* convert to vulkan constants */ + switch (dri2_surf->base.CompressionRate) { + case EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT: + out->compression = 0; + break; + case EGL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT: + out->compression = UINT32_MAX; + break; +#define EGL_VK_COMP(NUM) \ + case EGL_SURFACE_COMPRESSION_FIXED_RATE_##NUM##BPC_EXT: \ + out->compression = VK_IMAGE_COMPRESSION_FIXED_RATE_##NUM##BPC_BIT_EXT; \ + break + EGL_VK_COMP(1); + EGL_VK_COMP(2); + EGL_VK_COMP(3); + EGL_VK_COMP(4); + EGL_VK_COMP(5); + EGL_VK_COMP(6); + EGL_VK_COMP(7); + EGL_VK_COMP(8); + EGL_VK_COMP(9); + EGL_VK_COMP(10); + EGL_VK_COMP(11); + EGL_VK_COMP(12); +#undef EGL_VK_COMP + default: + UNREACHABLE("unknown compression rate"); + } +} + +static const __DRIkopperLoaderExtension kopper_loader_extension = { + .base = {__DRI_KOPPER_LOADER, 1}, + .SetSurfaceCreateInfo = kopperSetSurfaceCreateInfo, +}; + +static void +ohos_drawable_info(struct dri_drawable *draw, int *x, int *y, int *w, int *h, + void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + *x = *y = 0; + *w = dri2_surf->base.Width; + *h = dri2_surf->base.Height; +} + +static const __DRIswrastLoaderExtension swrast_loader_extension = { + .base = {__DRI_SWRAST_LOADER, 1}, + .getDrawableInfo = ohos_drawable_info, +}; + +static int +ohos_image_get_buffers(struct dri_drawable *driDrawable, unsigned int format, + uint32_t *stamp, void *loaderPrivate, + uint32_t buffer_mask, struct __DRIimageList *buffers) +{ + buffers->image_mask = 0; + buffers->front = NULL; + buffers->back = NULL; + return 1; +} + +static void +ohos_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate) +{ +} + +static unsigned +ohos_get_capability(void *loaderPrivate, enum dri_loader_cap cap) +{ + /* Note: loaderPrivate is _EGLDisplay* */ + switch (cap) { + case DRI_LOADER_CAP_RGBA_ORDERING: + return 1; + default: + return 0; + } +} + +static const __DRIimageLoaderExtension image_loader_extension = { + .base = {__DRI_IMAGE_LOADER, 2}, + .getBuffers = ohos_image_get_buffers, + .flushFrontBuffer = ohos_flush_front_buffer, + .getCapability = ohos_get_capability, +}; + +static const __DRIextension *image_loader_extensions[] = { + &image_lookup_extension.base, + &kopper_loader_extension.base, + &swrast_loader_extension.base, + &image_loader_extension.base, + NULL, +}; + +static bool +load_zink_kopper(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + + dri2_dpy->fd_render_gpu = -1; + dri2_dpy->fd_display_gpu = -1; + dri2_dpy->driver_name = strdup("zink"); + if (!dri2_dpy->driver_name) + return false; + + dri2_detect_swrast_kopper(disp); + + dri2_dpy->loader_extensions = image_loader_extensions; + + return true; +} + +static void +ohos_add_configs_for_visuals(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + static const struct { + int hal_format; + enum pipe_format pipe_format; + } visuals[] = { + {PIXEL_FMT_RGBA_8888, PIPE_FORMAT_RGBA8888_UNORM}, + {PIXEL_FMT_RGBX_8888, PIPE_FORMAT_BGRX8888_UNORM}, + {PIXEL_FMT_RGB_565, PIPE_FORMAT_B5G6R5_UNORM}, + /* This must be after HAL_PIXEL_FMT_RGBA_8888, we only keep BGRA + * visual if it turns out RGBA visual is not available. + */ + {PIXEL_FMT_BGRA_8888, PIPE_FORMAT_BGRA8888_UNORM}, + }; + + unsigned int format_count[ARRAY_SIZE(visuals)] = {0}; + + bool has_rgba = false; + for (int i = 0; i < ARRAY_SIZE(visuals); i++) { + if (visuals[i].hal_format == PIXEL_FMT_BGRA_8888 && has_rgba) + continue; + for (int j = 0; dri2_dpy->driver_configs[j]; j++) { + const struct gl_config *gl_config = + (struct gl_config *)dri2_dpy->driver_configs[j]; + + /* Rather than have duplicate table entries for _SRGB formats, just + * use the linear version of the format for the comparision: + */ + enum pipe_format linear_format = + util_format_linear(gl_config->color_format); + if (linear_format != visuals[i].pipe_format) + continue; + + const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + const EGLint config_attrs[] = { + EGL_NATIVE_VISUAL_ID, visuals[i].hal_format, EGL_NATIVE_VISUAL_TYPE, + visuals[i].hal_format, EGL_NONE}; + + _eglLog(_EGL_DEBUG, "calling dri2_add_config for %x", + visuals[i].hal_format); + struct dri2_egl_config *dri2_conf = dri2_add_config( + disp, dri2_dpy->driver_configs[j], surface_type, config_attrs); + if (dri2_conf) + format_count[i]++; + } + + if (visuals[i].hal_format == PIXEL_FMT_RGBA_8888 && format_count[i]) + has_rgba = true; + } + + for (int i = 0; i < ARRAY_SIZE(format_count); i++) { + if (!format_count[i]) { + _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x", + visuals[i].hal_format); + } + } +} + +EGLBoolean +dri2_initialize_ohos(_EGLDisplay *disp) +{ + const char *err; + struct dri2_egl_display *dri2_dpy = dri2_display_create(disp); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + err = "DRI2: failed to load driver"; + if (!load_zink_kopper(disp)) + goto cleanup; + + if (!dri2_create_screen(disp)) { + err = "DRI2: failed to create screen"; + goto cleanup; + } + + dri2_setup_screen(disp); + + /* Create configs *after* enabling extensions because presence of DRI + * driver extensions can affect the capabilities of EGLConfigs. + */ + ohos_add_configs_for_visuals(disp); + + disp->Extensions.KHR_image = EGL_TRUE; + + /* Fill vtbl last to prevent accidentally calling virtual function during + * initialization. + */ + dri2_dpy->vtbl = &dri2_ohos_display_vtbl; + + return EGL_TRUE; + +cleanup: + dri2_display_destroy(disp); + return _eglError(EGL_NOT_INITIALIZED, err); +} diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index a75855c00c5..328b5797e53 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -84,6 +84,7 @@ static const struct { {_EGL_PLATFORM_SURFACELESS, "surfaceless"}, {_EGL_PLATFORM_DEVICE, "device"}, {_EGL_PLATFORM_WINDOWS, "windows"}, + {_EGL_PLATFORM_OHOS, "ohos"}, }; /** diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 6178140e7e7..a9aa3df0a89 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -55,6 +55,7 @@ enum _egl_platform_type { _EGL_PLATFORM_SURFACELESS, _EGL_PLATFORM_DEVICE, _EGL_PLATFORM_WINDOWS, + _EGL_PLATFORM_OHOS, _EGL_NUM_PLATFORMS, _EGL_INVALID_PLATFORM = -1 diff --git a/src/egl/meson.build b/src/egl/meson.build index 16809846236..b8bba5dc919 100644 --- a/src/egl/meson.build +++ b/src/egl/meson.build @@ -113,7 +113,7 @@ if with_dri endif deps_for_egl += [dep_x11_xcb, dep_xcb_xrandr, dep_xcb_xfixes, dep_xcb_shm] endif - if with_gbm and not with_platform_android + if with_gbm and not with_platform_android and not with_platform_ohos files_egl += files('drivers/dri2/platform_drm.c') incs_for_egl += [include_directories('../gbm/backends/dri')] deps_for_egl += [dep_libdrm, dep_gbm] @@ -137,6 +137,10 @@ if with_dri deps_for_egl += [dep_android, idep_u_gralloc] files_egl += files('drivers/dri2/platform_android.c') endif + if with_platform_ohos + deps_for_egl += [dependency('libnative_window')] + files_egl += files('drivers/dri2/platform_ohos.c') + endif elif with_platform_haiku c_args_for_egl += [ '-D_EGL_BUILT_IN_DRIVER_HAIKU',