From adec216eb08e32aed8e364b89d4bcc7e769be7a2 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Mon, 24 Nov 2025 14:01:04 -0800 Subject: [PATCH] meson,gfxstream: add Android support via meson2hermetic Previously, there were no meson.build rules for the Android portion of gfxstream_vk, since nobody builds gfxstream_vk + Android via the Android NDK. Using Soong (and not the Android NDK) is an absolute requirement, since Android Virtual Devices (AVDs) were amongst to fully transition to Soong over Android makefiles, leading to breath-taking and exhilarating build speeds. The meson build rules that do exist works are designed for gfxstream_vk + Linux. That leads to higher maintainence costs: maintaining hand-written Android.bp files for Android, and meson.build for Linux. Enter meson2hermetic. With this tool, meson.build becomes the source of truth, and Android.bp are generating automatically, reducing maintainence costs. But for this to work, the portion of gfxstream_vk that didn't have meson build rules needs them. This patch does this and there are two things to note: 1) gfxstream_vk + Android needs dependencies that don't have any pkg-config files, and exist only with the AOSP tree. These include things like: - libqemupipe.ranchu - libOpenglCodecCommon - libgralloc_cb.ranchu - renderControlEncoder Most of these dependencies support the Goldfish AVD, and will be deleted over time as the that emulator transitions to virtio-gpu. There are more generic Android deps too, like "android_base". Generic Android dependencies are given the prefix "android-", while Goldfish (a.k.a Android Emulator) is given the prefix "android-aemu-". The ability to use dependencies that don't have a direct Linux-distro style analogue is the one of motivators meson2hermetic. 2) There's a special "gfxstream_emulated_android" case. This is for the GfxstreamEnd2EndTests target, which uses the code defined here: - src/gfxstream/guest/android/ANativeWindowEmulated.cpp - src/gfxstream/guest/android/GrallocEmulated.cpp This is used by Gfxstream Github for CI/CD. Acked-by: Eric Engestrom Part-of: --- meson.build | 26 +++- src/gfxstream/guest/android/meson.build | 44 +++++++ .../guest/connection-manager/meson.build | 2 +- src/gfxstream/guest/meson.build | 61 +++++++++ src/gfxstream/guest/platform/drm/meson.build | 2 +- .../guest/platform/kumquat/meson.build | 1 + src/gfxstream/guest/vulkan/meson.build | 20 ++- src/gfxstream/guest/vulkan_enc/meson.build | 122 ++++++++---------- 8 files changed, 192 insertions(+), 86 deletions(-) create mode 100644 src/gfxstream/guest/android/meson.build diff --git a/meson.build b/meson.build index 38b5be2f26d..33255e04a77 100644 --- a/meson.build +++ b/meson.build @@ -451,6 +451,27 @@ with_platform_haiku = _platforms.contains('haiku') with_platform_windows = _platforms.contains('windows') with_platform_macos = _platforms.contains('macos') +with_gfxstream_emulated_android = with_gfxstream_vk and with_platform_android and host_machine.system() == 'linux' +if with_gfxstream_emulated_android + # When building the android_stub with a non-Bionic sysroot/target, we to have + # define macros that are typically in when using a Bionic + # sysroot + pre_args += '-D__INTRODUCED_IN(api_level)=' + + # We don't want to build Vulkan common code when running the emulated + # gfxstream Android platform. This causes issues when building in + # tandem with host Lavapipe. + # + # TODO(gfxstream-devs@): Modifying the user-provided platform can be removed + # when Cuttlefish moves it's host library builds off Soong, and on to Github. + # For now, add basic sanity checks before modifying user arguments. + if _platforms.contains('android') and _platforms.length() != 1 + error('You cannot enable platform "android" at the same time as another platform') + endif + _platforms = [] + with_platform_android = false +endif + with_glx = get_option('glx') if with_glx == 'auto' if not with_opengl @@ -925,8 +946,9 @@ endif pre_args += '-DGLAPI_EXPORT_PROTO_ENTRY_POINTS=@0@'.format(with_glapi_export_proto_entry_points.to_int()) with_android_stub = get_option('android-stub') -if with_android_stub and not with_platform_android - error('`-D android-stub=true` makes no sense without `-D platforms=android`') +need_android_stub = with_platform_android or with_gfxstream_emulated_android +if with_android_stub and not need_android_stub + error('`-D android-stub=true` makes no sense without `-D platforms=android` or emulated Android') endif with_libbacktrace = get_option('android-libbacktrace') \ diff --git a/src/gfxstream/guest/android/meson.build b/src/gfxstream/guest/android/meson.build new file mode 100644 index 00000000000..9d171edf8d4 --- /dev/null +++ b/src/gfxstream/guest/android/meson.build @@ -0,0 +1,44 @@ +# Copyright 2026 Google +# SPDX-License-Identifier: MIT + +inc_gfxstream_android = include_directories('include') +deps_gfxstream_android = [dependency('android-utils')] +if host_machine.system() == 'android' + dep_android_minigbm_headers = dependency('android-minigbm-headers') + dep_android_nativebase_headers = dependency('android-nativebase-headers') + dep_android_aemu_gralloc_headers = dependency('android-aemu-gralloc-headers') + + files_gfxstream_android = files( + 'ANativeWindowAndroid.cpp', + 'GfxStreamGralloc.cpp', + 'GrallocGoldfish.cpp', + 'GrallocMinigbm.cpp', + ) + + deps_gfxstream_android += [ + dep_android_minigbm_headers, + dep_android_nativebase_headers, + dep_android_aemu_gralloc_headers, + ] +else + files_gfxstream_android = files( + 'ANativeWindowEmulated.cpp', + 'GrallocEmulated.cpp', + ) +endif + +libgfxstream_guest_android = static_library( + 'gfxstream_android', + files_gfxstream_android, + cpp_args: gfxstream_guest_args, + include_directories: [inc_gfxstream_android, inc_platform_virtgpu, inc_src, inc_include], + link_with: [libplatform_virtgpu], + dependencies: deps_gfxstream_android + dep_android, +) + +idep_gfxstream_guest_android = declare_dependency( + link_with: libgfxstream_guest_android, + include_directories: inc_gfxstream_android, +) + +gfxstream_deps += idep_gfxstream_guest_android diff --git a/src/gfxstream/guest/connection-manager/meson.build b/src/gfxstream/guest/connection-manager/meson.build index 924f82e1a5a..e8dba7007ea 100644 --- a/src/gfxstream/guest/connection-manager/meson.build +++ b/src/gfxstream/guest/connection-manager/meson.build @@ -24,5 +24,5 @@ libconnection_manager = static_library( inc_aemu, ], link_with: [lib_goldfish_address_space, libplatform_virtgpu], - dependencies: dep_libdrm, + dependencies: [dep_libdrm, dep_android_aemu_qemupipe, idep_mesautil], ) diff --git a/src/gfxstream/guest/meson.build b/src/gfxstream/guest/meson.build index c549a69b4fe..521486fad8c 100644 --- a/src/gfxstream/guest/meson.build +++ b/src/gfxstream/guest/meson.build @@ -21,6 +21,7 @@ if host_machine.system() == 'windows' else gfxstream_guest_args += '-DLINUX_GUEST_BUILD' endif + # Include the gfxstream private VkStructureType definitions gfxstream_guest_args += '-DVK_GFXSTREAM_STRUCTURE_TYPE_EXT' @@ -44,6 +45,61 @@ gfxstream_guest_args += '-DVK_BASE_VERSION_1_4' gfxstream_guest_args += '-DVK_GRAPHICS_VERSION_1_4' gfxstream_guest_args += '-DVK_COMPUTE_VERSION_1_4' +if with_gfxstream_emulated_android + gfxstream_guest_args += '-DEND2END_TESTS' +endif + + +#====================================# +# Standard deps # +#====================================# +gfxstream_deps = [ + dep_libdrm, + idep_mesautil, + idep_vulkan_wsi_headers, + idep_vulkan_lite_runtime, + idep_vulkan_util_headers, + idep_vulkan_wsi, + dep_valgrind, +] + +if with_perfetto + gfxstream_deps += dep_perfetto +endif + +#====================================# +# Android deps (mostly Goldfish) # +# Only works with meson2hermetic # +#====================================# +dep_android_base = null_dep +dep_android_arect = null_dep +dep_android_aemu_base = null_dep +dep_android_aemu_gl_codec = null_dep +dep_android_aemu_qemupipe = null_dep +dep_android_aemu_ringbuffer = null_dep +dep_android_aemu_rc_encoder = null_dep +if with_platform_android or with_gfxstream_emulated_android + gfxstream_guest_args += '-DVK_USE_PLATFORM_ANDROID_KHR' + dep_android_base = dependency('android-base') + dep_android_arect = dependency('android-arect') + dep_android_aemu_base = dependency('android-aemu-base') + dep_android_aemu_gl_codec = dependency('android-aemu-gl-codec') + dep_android_aemu_qemupipe = dependency('android-aemu-qemupipe') + dep_android_aemu_ringbuffer = dependency('android-aemu-ringbuffer') + dep_android_aemu_rc_encoder = dependency('android-aemu-rc-encoder') + + gfxstream_deps += dep_android + gfxstream_deps += [ + dep_android_base, + dep_android_arect, + dep_android_aemu_base, + dep_android_aemu_gl_codec, + dep_android_aemu_ringbuffer, + dep_android_aemu_rc_encoder, + dep_android_aemu_qemupipe, + ] +endif + #===============# # Includes # #===============# @@ -58,5 +114,10 @@ subdir('iostream') subdir('platform') subdir('GoldfishAddressSpace') subdir('connection-manager') + +if with_platform_android or with_gfxstream_emulated_android + subdir('android') +endif + subdir('vulkan_enc') subdir('vulkan') diff --git a/src/gfxstream/guest/platform/drm/meson.build b/src/gfxstream/guest/platform/drm/meson.build index 86748f60b9c..949f3c280cd 100644 --- a/src/gfxstream/guest/platform/drm/meson.build +++ b/src/gfxstream/guest/platform/drm/meson.build @@ -13,5 +13,5 @@ libplatform_virtgpu_drm = static_library( files_libplatform_virtgpu_drm, cpp_args: gfxstream_guest_args, include_directories: [inc_platform_virtgpu, inc_src, inc_include], - dependencies: dep_libdrm, + dependencies: [dep_libdrm, idep_mesautil], ) diff --git a/src/gfxstream/guest/platform/kumquat/meson.build b/src/gfxstream/guest/platform/kumquat/meson.build index 959f6d35600..2ab14fd9992 100644 --- a/src/gfxstream/guest/platform/kumquat/meson.build +++ b/src/gfxstream/guest/platform/kumquat/meson.build @@ -26,6 +26,7 @@ libplatform_virtgpu_kumquat = static_library( ], dependencies: [ idep_vulkan_util_headers, + idep_mesautil, dep_virtgpu_kumquat_ffi, dep_gfxstream_vulkan_mapper, ], diff --git a/src/gfxstream/guest/vulkan/meson.build b/src/gfxstream/guest/vulkan/meson.build index 8a091b1e5f9..f7c99ea2b61 100644 --- a/src/gfxstream/guest/vulkan/meson.build +++ b/src/gfxstream/guest/vulkan/meson.build @@ -18,22 +18,18 @@ if with_platform_wayland gfxstream_vk_wsi_args += '-DGFXSTREAM_VK_WAYLAND' endif -gfxstream_deps = [ - dep_libdrm, - idep_vulkan_wsi_headers, - idep_vulkan_lite_runtime, - idep_vulkan_util_headers, - idep_vulkan_wsi, - dep_valgrind, -] +files_vulkan_gfxstream = files_lib_vulkan_gfxstream + files_lib_vulkan_enc +files_vulkan_gfxstream += gfxstream_vk_entrypoints +files_vulkan_gfxstream += gfxstream_guest_vk_autogen +files_vulkan_gfxstream += vulkan_gfxstream_h -if with_perfetto - gfxstream_deps += dep_perfetto +if with_platform_android or with_gfxstream_emulated_android + files_vulkan_gfxstream += files_lib_vulkan_enc_android endif lib_vulkan_gfxstream = shared_library( 'vulkan_gfxstream', - files_lib_vulkan_gfxstream + files_lib_vulkan_enc + gfxstream_vk_entrypoints + gfxstream_guest_vk_autogen + vulkan_gfxstream_h, + files_vulkan_gfxstream, cpp_args: gfxstream_guest_args + gfxstream_vk_wsi_args, include_directories: [ inc_vulkan_headers, @@ -66,7 +62,7 @@ icd_file_name = libname_prefix + 'vulkan_gfxstream.' + libname_suffix gfxstream_icd = custom_target( 'gfxstream_vk_icd', input: [vk_icd_gen, vk_api_xml], - output : 'gfxstream_vk_icd.' + vulkan_manifest_suffix, + output: 'gfxstream_vk_icd.' + vulkan_manifest_suffix, command: [ prog_python, '@INPUT0@', diff --git a/src/gfxstream/guest/vulkan_enc/meson.build b/src/gfxstream/guest/vulkan_enc/meson.build index f86c4aca186..e4ec02fb21b 100644 --- a/src/gfxstream/guest/vulkan_enc/meson.build +++ b/src/gfxstream/guest/vulkan_enc/meson.build @@ -4,83 +4,61 @@ output_host_path = meson.current_build_dir() + '/host/vulkan/cereal' guest_enc_path = meson.current_build_dir() -if build_machine.system() != 'android' - gfxstream_guest_vk_autogen = custom_target( - 'gfxstream_guest_vk_autogen', - output: [ - 'VkEncoder.h', - 'goldfish_vk_counting_guest.h', - 'goldfish_vk_deepcopy_guest.h', - 'goldfish_vk_marshaling_guest.h', - 'goldfish_vk_extension_structs_guest.h', - 'goldfish_vk_reserved_marshaling_guest.h', - 'goldfish_vk_transform_guest.h', - 'goldfish_vk_counting_guest.cpp', - 'goldfish_vk_deepcopy_guest.cpp', - 'goldfish_vk_extension_structs_guest.cpp', - 'goldfish_vk_marshaling_guest.cpp', - 'goldfish_vk_reserved_marshaling_guest.cpp', - 'goldfish_vk_transform_guest.cpp', - 'VkEncoder.cpp', - 'func_table.cpp', - ], - depend_files: genvk_depends, - env: { - 'GFXSTREAM_NO_CLANG_FMT': '1', - 'CEREAL_VARIANT' : 'guest', - 'GFXSTREAM_GUEST_ENCODER_DIR': guest_enc_path, - }, - input: [genvk, vk_api_xml, vk_gfxstream_xml], - command: [ - prog_python, - '@INPUT0@', - '-registry', - '@INPUT1@', - '-registryGfxstream', - '@INPUT2@', - 'cereal', - '-o', - output_host_path, - ], - ) - - vulkan_gfxstream_h = custom_target( - 'vulkan_gfxstream_header', - output: ['vulkan_gfxstream.h'], - env: {'GFXSTREAM_NO_CLANG_FMT': '1', 'CEREAL_VARIANT' : 'guest'}, - input: [genvk, vk_gfxstream_xml], - depend_files: genvk_depends, - command: [ - prog_python, - '@INPUT0@', - '-registry', - '@INPUT1@', - 'vulkan_gfxstream.h', - '-o', - guest_enc_path, - ], - ) -else - gfxstream_guest_vk_autogen = files( - 'VkEncoder.cpp', +gfxstream_guest_vk_autogen = custom_target( + 'gfxstream_guest_vk_autogen', + output: [ 'VkEncoder.h', - 'func_table.cpp', - 'goldfish_vk_counting_guest.cpp', 'goldfish_vk_counting_guest.h', - 'goldfish_vk_deepcopy_guest.cpp', 'goldfish_vk_deepcopy_guest.h', - 'goldfish_vk_extension_structs_guest.cpp', - 'goldfish_vk_extension_structs_guest.h', - 'goldfish_vk_marshaling_guest.cpp', 'goldfish_vk_marshaling_guest.h', - 'goldfish_vk_reserved_marshaling_guest.cpp', + 'goldfish_vk_extension_structs_guest.h', 'goldfish_vk_reserved_marshaling_guest.h', - 'goldfish_vk_transform_guest.cpp', 'goldfish_vk_transform_guest.h', - ) + 'goldfish_vk_counting_guest.cpp', + 'goldfish_vk_deepcopy_guest.cpp', + 'goldfish_vk_extension_structs_guest.cpp', + 'goldfish_vk_marshaling_guest.cpp', + 'goldfish_vk_reserved_marshaling_guest.cpp', + 'goldfish_vk_transform_guest.cpp', + 'VkEncoder.cpp', + 'func_table.cpp', + ], + depend_files: genvk_depends, + env: { + 'GFXSTREAM_NO_CLANG_FMT': '1', + 'CEREAL_VARIANT' : 'guest', + 'GFXSTREAM_GUEST_ENCODER_DIR': guest_enc_path, + }, + input: [genvk, vk_api_xml, vk_gfxstream_xml], + command: [ + prog_python, + '@INPUT0@', + '-registry', + '@INPUT1@', + '-registryGfxstream', + '@INPUT2@', + 'cereal', + '-o', + output_host_path, + ], +) - vulkan_gfxstream_h = files('vulkan_gfxstream.h') -endif +vulkan_gfxstream_h = custom_target( + 'vulkan_gfxstream_header', + output: ['vulkan_gfxstream.h'], + depend_files: genvk_depends, + env: {'GFXSTREAM_NO_CLANG_FMT': '1', 'CEREAL_VARIANT' : 'guest'}, + input: [genvk, vk_gfxstream_xml], + command: [ + prog_python, + '@INPUT0@', + '-registry', + '@INPUT1@', + 'vulkan_gfxstream.h', + '-o', + guest_enc_path, + ], +) gfxstream_vk_entrypoints = custom_target( 'gfxstream_vk_entrypoints', @@ -116,3 +94,7 @@ files_lib_vulkan_enc = files( 'VulkanStreamGuest.cpp', 'gfxstream_vk_private.cpp', ) + sha1_h + +files_lib_vulkan_enc_android = files( + 'AndroidHardwareBuffer.cpp', +)