Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions .github/workflows/smoke_render.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,46 @@ on:
- cron: "0 7 * * *" # daily, 07:00 UTC

jobs:
macos:
name: macOS (Flutter master)
runs-on: macos-latest
timeout-minutes: 12
linux:
name: linux (Flutter master)
runs-on: ubuntu-latest
timeout-minutes: 20
env:
# No GPU on the runner; force Mesa's software rasterizers (GL llvmpipe,
# Vulkan lavapipe) so Impeller has a backend under Xvfb.
LIBGL_ALWAYS_SOFTWARE: "1"
GALLIUM_DRIVER: llvmpipe
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: master
- name: Flutter and engine revision
run: flutter --version
- run: flutter config --enable-native-assets
- name: Install Linux desktop build deps + software GL/Vulkan + Xvfb
run: |
sudo apt-get update
sudo apt-get install -y \
clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev \
xvfb libgl1-mesa-dri libegl-mesa0 libgles2 mesa-vulkan-drivers
- run: flutter config --enable-linux-desktop --enable-native-assets
- run: flutter pub get
- name: Render smoke scenes
working-directory: examples/smoke_render
run: >
xvfb-run -a -s "-screen 0 1280x1024x24"
flutter drive
--driver=test_driver/integration_test.dart
--target=integration_test/smoke_test.dart
-d macos --enable-impeller --enable-flutter-gpu
-d linux --enable-impeller --enable-flutter-gpu
- name: Upload to Argos
id: argos
if: ${{ !cancelled() }}
working-directory: examples/smoke_render
env:
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
run: |
out=$(npx --yes @argos-ci/cli upload build/smoke --build-name macos 2>&1) || true
out=$(npx --yes @argos-ci/cli upload build/smoke --build-name linux 2>&1) || true
echo "$out"
url=$(printf '%s' "$out" | grep -oE 'https://app\.argos-ci\.com/[^[:space:]]+' | head -1)
echo "build_url=$url" >> "$GITHUB_OUTPUT"
Expand All @@ -50,7 +62,7 @@ jobs:
run: |
[ -z "$DISCORD_WEBHOOK_URL" ] && exit 0
RUN_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
CONTENT="Smoke render failed (macOS, Flutter master). Run: $RUN_URL"
CONTENT="Smoke render failed (linux, Flutter master). Run: $RUN_URL"
[ -n "$ARGOS_URL" ] && CONTENT="$CONTENT | Argos: $ARGOS_URL"
curl -sf -H "Content-Type: application/json" \
-d "{\"content\": \"$CONTENT\"}" "$DISCORD_WEBHOOK_URL" || true
Expand Down
12 changes: 6 additions & 6 deletions examples/smoke_render/.metadata
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.

version:
revision: "b5cf21f90aece859cd4f33812b2b75538bbde9b4"
revision: "72d04ce778634d7e6c2d383174c9a086f2b8bfba"
channel: "[user-branch]"

project_type: app
Expand All @@ -13,11 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: b5cf21f90aece859cd4f33812b2b75538bbde9b4
base_revision: b5cf21f90aece859cd4f33812b2b75538bbde9b4
- platform: macos
create_revision: b5cf21f90aece859cd4f33812b2b75538bbde9b4
base_revision: b5cf21f90aece859cd4f33812b2b75538bbde9b4
create_revision: 72d04ce778634d7e6c2d383174c9a086f2b8bfba
base_revision: 72d04ce778634d7e6c2d383174c9a086f2b8bfba
- platform: linux
create_revision: 72d04ce778634d7e6c2d383174c9a086f2b8bfba
base_revision: 72d04ce778634d7e6c2d383174c9a086f2b8bfba

# User provided section

Expand Down
24 changes: 7 additions & 17 deletions examples/smoke_render/integration_test/smoke_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,6 @@ void main() {
// pumpWidget) touches baseShaderLibrary, which throws on web if touched
// before initialization completes.
await Scene.initializeStaticResources();
// ignore: avoid_print
print('SMOKEDBG ${smoke.id}: init done');

// Bare frame with no flutter_scene content: isolates whether the
// headless runner pumps frames at all (vsync) from scene rendering.
await tester.pumpWidget(
const MaterialApp(home: ColoredBox(color: Color(0xFF202020))),
);
// ignore: avoid_print
print('SMOKEDBG ${smoke.id}: bare pumped');

await tester.pumpWidget(
MaterialApp(
Expand All @@ -40,23 +30,17 @@ void main() {
),
),
);
// ignore: avoid_print
print('SMOKEDBG ${smoke.id}: pumped');

// Let the post-ready repaint and GPU frames settle.
for (var i = 0; i < 20; i++) {
await tester.pump(const Duration(milliseconds: 50));
await Future<void>.delayed(const Duration(milliseconds: 50));
}
// ignore: avoid_print
print('SMOKEDBG ${smoke.id}: settled');

final boundary =
smokeSceneKey.currentContext!.findRenderObject()
as RenderRepaintBoundary;
final ui.Image image = await boundary.toImage(pixelRatio: 1.0);
// ignore: avoid_print
print('SMOKEDBG ${smoke.id}: toImage done');
final png = (await image.toByteData(format: ui.ImageByteFormat.png))!;
final rgba =
(await image.toByteData(format: ui.ImageByteFormat.rawRgba))!;
Expand Down Expand Up @@ -92,9 +76,15 @@ void main() {
greaterThan(20),
reason: 'foreground is ~black; lighting or textures may have broken',
);
// A loose backstop against a flat/uniform fill; coverage and foreground
// luma above are the primary blank detectors. Kept low because this
// metric is noisy (dominated by the anti-aliased clear/geometry edge)
// and software rasterizers (e.g. llvmpipe on the Linux CI) produce far
// fewer distinct values than hardware, especially for a low-roughness
// metallic surface reflecting a smooth environment.
expect(
stats.distinctColors,
greaterThan(100),
greaterThan(24),
reason: 'frame looks uniform; possible blank render',
);
});
Expand Down
8 changes: 0 additions & 8 deletions examples/smoke_render/lib/smoke_scenes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,9 @@ class _SmokeSceneViewState extends State<SmokeSceneView> {
@override
void initState() {
super.initState();
// ignore: avoid_print
print('SMOKEDBG ${widget.scene.id}: initState building scene');
final setup = widget.scene.setup();
_scene = setup.scene;
_camera = setup.camera;
// ignore: avoid_print
print('SMOKEDBG ${widget.scene.id}: initState scene built');

// The first paint happens before flutter_scene's static resources finish
// loading and is skipped; this view is otherwise static, so trigger one
Expand Down Expand Up @@ -170,11 +166,7 @@ class _SmokePainter extends CustomPainter {

@override
void paint(Canvas canvas, Size size) {
// ignore: avoid_print
print('SMOKEDBG paint: before scene.render');
scene.render(camera, canvas, viewport: Offset.zero & size);
// ignore: avoid_print
print('SMOKEDBG paint: after scene.render');
}

@override
Expand Down
1 change: 1 addition & 0 deletions examples/smoke_render/linux/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
flutter/ephemeral
128 changes: 128 additions & 0 deletions examples/smoke_render/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Project-level configuration.
cmake_minimum_required(VERSION 3.13)
project(runner LANGUAGES CXX)

# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "smoke_render")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "com.example.smoke_render")

# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(SET CMP0063 NEW)

# Load bundled libraries from the lib/ directory relative to the binary.
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")

# Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()

# Define build configuration options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()

# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()

# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})

# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)

# Application build; see runner/CMakeLists.txt.
add_subdirectory("runner")

# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)

# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)


# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)


# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()

# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)

set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")

install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)

install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)

install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)

foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
install(FILES "${bundled_library}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endforeach(bundled_library)

# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)

# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)

# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
88 changes: 88 additions & 0 deletions examples/smoke_render/linux/flutter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.10)

set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")

# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)

# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.

# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()

# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)

set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")

# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)

list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
)
add_dependencies(flutter flutter_assemble)

# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)
Loading
Loading