From e4753cbdced136e842340315c6509156749a2e17 Mon Sep 17 00:00:00 2001 From: Marcus Figueiredo Date: Mon, 22 Jun 2026 23:15:31 -0300 Subject: [PATCH 1/4] common: make shm_open names POSIX-compliant and fix macOS shared memory macOS has no memfd_create(); fall back to shm_open() for the SHARED_MEMORY share type there. POSIX.1-2017 (System Interfaces, shm_open) requires the name to begin with a '/' for portable behavior, so normalize names that lack the leading slash. Per review, the normalization is applied universally (not just on macOS) so callers never need to care about it, with the POSIX requirement cited inline. Signed-off-by: Marcus Figueiredo --- common/base/SharedMemory_posix.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/common/base/SharedMemory_posix.cpp b/common/base/SharedMemory_posix.cpp index 638751a07..efd971c4a 100644 --- a/common/base/SharedMemory_posix.cpp +++ b/common/base/SharedMemory_posix.cpp @@ -55,7 +55,10 @@ SharedMemory::SharedMemory(const std::string& name, size_t size) { mName = PathUtils::recompose(PathUtils::decompose(std::move(path))); } else { mShareType = ShareType::SHARED_MEMORY; - mName = name; + // POSIX.1-2017 (System Interfaces) requires shm_open() names to begin + // with a '/' character to avoid implementation-defined behavior. + // Normalize unconditionally so callers don't need to care about it. + mName = (!name.empty() && name[0] != '/') ? ("/" + name) : name; } } @@ -111,7 +114,9 @@ int SharedMemory::openInternal(int oflag, int mode, bool doMapping) { int err = 0; struct stat sb; if (mShareType == ShareType::SHARED_MEMORY) { -#if defined(HAVE_MEMFD_CREATE) +#if defined(__APPLE__) + mFd = ::shm_open(mName.c_str(), oflag, mode); +#elif defined(HAVE_MEMFD_CREATE) mFd = memfd_create(mName.c_str(), MFD_CLOEXEC | MFD_ALLOW_SEALING); #else mFd = syscall(__NR_memfd_create, mName.c_str(), FD_CLOEXEC); From bc03e044d6e94da95089ea1f5493c9f9b1fa92e4 Mon Sep 17 00:00:00 2001 From: Marcus Figueiredo Date: Mon, 22 Jun 2026 23:15:31 -0300 Subject: [PATCH 2/4] host: propagate createBlob failures Signed-off-by: Marcus Figueiredo --- host/virtio_gpu_gfxstream_renderer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/host/virtio_gpu_gfxstream_renderer.cpp b/host/virtio_gpu_gfxstream_renderer.cpp index a92b96020..a8a1768d1 100644 --- a/host/virtio_gpu_gfxstream_renderer.cpp +++ b/host/virtio_gpu_gfxstream_renderer.cpp @@ -450,8 +450,7 @@ VG_EXPORT int stream_renderer_create_blob(uint32_t ctx_id, uint32_t res_handle, GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_STREAM_RENDERER_CATEGORY, "stream_renderer_create_blob()"); - sFrontend()->createBlob(ctx_id, res_handle, create_blob, handle); - return 0; + return sFrontend()->createBlob(ctx_id, res_handle, create_blob, handle); } VG_EXPORT int stream_renderer_export_blob(uint32_t res_handle, From 1a027d516bd1b45ebbd7cd6e3a3550b54128f47b Mon Sep 17 00:00:00 2001 From: Marcus Figueiredo Date: Tue, 14 Jul 2026 14:21:32 -0300 Subject: [PATCH 3/4] host: fix the macOS meson host build The macOS host build has bit-rotted in ways no current CI exercises: - meson.build: declare the 'objc' and 'objcpp' languages, required to compile mac_native.m and native_sub_window_cocoa.mm on Darwin; without them meson cannot even configure ("No host machine compiler for ..."). - host/gles_compat.h: the GLES-compat shim typedef'd EGLNativeWindowType as `unsigned int`, which truncates pointers on 64-bit platforms (the real type is pointer-sized, e.g. `void*` on Apple). native_sub_window_cocoa.mm returns an NSView* through this type, so the shim must stay ABI-compatible. - host/frame_buffer.h, host/native_sub_window.h: the GLES-disabled branch still included "GlesCompat.h"; the file on disk is gles_compat.h. No configuration that takes this branch was ever compiled by CI, so the rename went unnoticed. - host/iostream, host/snapshot: these static libraries have no sources, which GNU ar tolerates but macOS (BSD) ar rejects ("no archive members specified"). Add an intentionally-empty translation unit on Darwin. - host/meson.build, host/gl/meson.build: hoist the GL include-path declarations out of the `use_gles` conditional; the Vulkan server includes GLES dispatch headers even in Vulkan-only builds, and include_directories() on paths costs nothing when GLES is disabled. host/color_buffer.cpp: guard the ColorBufferGl using-declaration and the vulkanOnly derivation for GLES-disabled builds. With this, the default host build (meson setup -Ddefault_library=static -Dgfxstream-build=host) configures and compiles to completion on macOS/AArch64 with Homebrew meson/ninja/molten-vk/vulkan-loader. Vulkan-only (-Ddecoders=vulkan) now configures but still has further compile errors in GLES-entangled sources; that is left for a follow-up. Signed-off-by: Marcus Figueiredo --- host/color_buffer.cpp | 6 ++++++ host/frame_buffer.h | 2 +- host/gl/meson.build | 6 ------ host/gles_compat.h | 5 ++++- host/iostream/iostream_stub.cpp | 2 ++ host/iostream/meson.build | 4 ++++ host/meson.build | 7 +++++++ host/native_sub_window.h | 2 +- host/snapshot/meson.build | 4 ++++ host/snapshot/snapshot_stub.cpp | 2 ++ meson.build | 2 +- 11 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 host/iostream/iostream_stub.cpp create mode 100644 host/snapshot/snapshot_stub.cpp diff --git a/host/color_buffer.cpp b/host/color_buffer.cpp index 2733c4a6e..e150110de 100644 --- a/host/color_buffer.cpp +++ b/host/color_buffer.cpp @@ -27,7 +27,9 @@ namespace gfxstream { namespace host { namespace { +#if GFXSTREAM_ENABLE_HOST_GLES using gl::ColorBufferGl; +#endif using vk::ColorBufferVk; // ColorBufferVk natively supports YUV images. However, ColorBufferGl @@ -158,7 +160,11 @@ std::unique_ptr ColorBuffer::Impl::create( #endif if (emulationVk) { +#if GFXSTREAM_ENABLE_HOST_GLES const bool vulkanOnly = colorBuffer->mColorBufferGl == nullptr; +#else + const bool vulkanOnly = true; +#endif const uint32_t memoryProperty = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; const uint32_t mipLevels = 1; colorBuffer->mColorBufferVk = vk::ColorBufferVk::create( diff --git a/host/frame_buffer.h b/host/frame_buffer.h index 95c9526bf..865f31424 100644 --- a/host/frame_buffer.h +++ b/host/frame_buffer.h @@ -25,7 +25,7 @@ #include #include #else -#include "GlesCompat.h" +#include "gles_compat.h" #endif // GFXSTREAM_ENABLE_HOST_GLES #include diff --git a/host/gl/meson.build b/host/gl/meson.build index 7c62f47b3..7be97bf1f 100644 --- a/host/gl/meson.build +++ b/host/gl/meson.build @@ -1,12 +1,6 @@ # Copyright 2023 Android Open Source Project # SPDX-License-Identifier: Apache-2.0 -inc_gl_server = include_directories('.') -inc_gl_snapshot = include_directories('glsnapshot') - -# Needs forward declaration. -inc_gl_openglesdispatch = include_directories('OpenGLESDispatch/include') - # GLES translator subdir('glestranslator') diff --git a/host/gles_compat.h b/host/gles_compat.h index f1f56dc66..6aef3b1ef 100644 --- a/host/gles_compat.h +++ b/host/gles_compat.h @@ -19,7 +19,10 @@ typedef unsigned int GLenum; typedef int32_t EGLint; -typedef unsigned int EGLNativeWindowType; +// Must stay ABI-compatible with the real EGLNativeWindowType from +// , which is pointer-sized on 64-bit platforms +// (e.g. `void*` on Apple); a 32-bit integer here truncates pointers. +typedef void* EGLNativeWindowType; namespace gfxstream { namespace gl { diff --git a/host/iostream/iostream_stub.cpp b/host/iostream/iostream_stub.cpp new file mode 100644 index 000000000..611e764fa --- /dev/null +++ b/host/iostream/iostream_stub.cpp @@ -0,0 +1,2 @@ +// Intentionally empty: macOS ar(1) refuses to create an archive with no +// members, so Darwin builds need at least one translation unit here. diff --git a/host/iostream/meson.build b/host/iostream/meson.build index b407ca89a..0c1be3886 100644 --- a/host/iostream/meson.build +++ b/host/iostream/meson.build @@ -5,6 +5,10 @@ inc_host_iostream = include_directories('include') files_lib_host_iostream = files( ) +if host_machine.system() == 'darwin' + # macOS ar requires at least one member per static archive. + files_lib_host_iostream += files('iostream_stub.cpp') +endif lib_host_iostream = static_library( 'host_iostream', diff --git a/host/meson.build b/host/meson.build index 54b7c49fc..2cea3ccdf 100644 --- a/host/meson.build +++ b/host/meson.build @@ -94,6 +94,13 @@ if use_gles or use_vulkan ] endif +# GL include paths are needed even in Vulkan-only builds: the Vulkan server +# includes the GLES dispatch headers (e.g. for interop declarations), so keep +# them visible regardless of which decoders are enabled. +inc_gl_server = include_directories('gl') +inc_gl_snapshot = include_directories('gl/glsnapshot') +inc_gl_openglesdispatch = include_directories('gl/OpenGLESDispatch/include') + if use_gles subdir('gl') diff --git a/host/native_sub_window.h b/host/native_sub_window.h index 87a6f4184..3791a9e71 100644 --- a/host/native_sub_window.h +++ b/host/native_sub_window.h @@ -21,7 +21,7 @@ #if GFXSTREAM_ENABLE_HOST_GLES #include #else -#include "GlesCompat.h" +#include "gles_compat.h" #endif #ifdef __cplusplus diff --git a/host/snapshot/meson.build b/host/snapshot/meson.build index 75188fd9e..179fa621c 100644 --- a/host/snapshot/meson.build +++ b/host/snapshot/meson.build @@ -4,6 +4,10 @@ inc_host_snapshot = include_directories('include') files_lib_host_snapshot = files() +if host_machine.system() == 'darwin' + # macOS ar requires at least one member per static archive. + files_lib_host_snapshot += files('snapshot_stub.cpp') +endif lib_host_snapshot = static_library( 'host_snapshot', diff --git a/host/snapshot/snapshot_stub.cpp b/host/snapshot/snapshot_stub.cpp new file mode 100644 index 000000000..611e764fa --- /dev/null +++ b/host/snapshot/snapshot_stub.cpp @@ -0,0 +1,2 @@ +// Intentionally empty: macOS ar(1) refuses to create an archive with no +// members, so Darwin builds need at least one translation unit here. diff --git a/meson.build b/meson.build index 80f1c0b5a..0f33512bd 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ # Copyright 2023 Android Open Source Project # SPDX-License-Identifier: Apache-2.0 -project('gfxstream', 'cpp', 'c', +project('gfxstream', 'cpp', 'c', 'objc', 'objcpp', version : '0.1.2', license : 'Apache-2.0', default_options : ['cpp_std=gnu++17', From a6023abebda18aa4b54c3ca343284650f5f25b0f Mon Sep 17 00:00:00 2001 From: Marcus Figueiredo Date: Tue, 14 Jul 2026 14:21:32 -0300 Subject: [PATCH 4/4] ci: add macOS meson host build to presubmit Per review, the macOS build lives in presubmit.yaml alongside the other platform builds instead of a separate workflow file. The job mirrors the Linux meson job's structure (same step names, checkout pinned to the same SHA) and builds the host renderer with the Vulkan loader + MoltenVK from Homebrew: meson setup -Ddefault_library=static -Dgfxstream-build=host This is the configuration used to run gfxstream as the virtio-gpu backend on Apple Silicon hosts (HVF VMMs such as libkrun), where the Vulkan device is MoltenVK on Metal. It also guards the macOS-only code paths (ObjC sources, BSD ar, the GLES-compat shim) that no existing job compiles. Signed-off-by: Marcus Figueiredo --- .github/workflows/presubmit.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index 5a137e053..bce7af5c0 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -102,6 +102,23 @@ jobs: run: | meson compile -C build + run-gfxstream-meson-build-macos: + runs-on: macos-latest + steps: + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - name: Install toolchain dependencies + run: brew install meson ninja molten-vk vulkan-loader + - name: Configure Build + run: | + meson setup \ + -Ddefault_library=static \ + -Dgfxstream-build=host \ + build + - name: Build + run: | + meson compile -C build + run-gfxstream-meson-build-windows: runs-on: windows-latest defaults: