From e81426f93b5a1413af97c289c1bc6f9db5dafdb3 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 1 Oct 2019 14:15:26 +0200 Subject: [PATCH] [build] Clean the different targets --- apps/Makefile | 20 +++--- build/targets.device.mak | 12 ++-- build/targets.mak | 21 ++++-- build/targets.simulator.mak | 22 +++---- build/targets.simulator.web.mak | 17 +++++ build/toolchain.emscripten.mak | 9 ++- ion/Makefile | 7 ++ ion/src/device/Makefile | 2 +- ion/src/device/bench/Makefile | 4 +- ion/src/device/flasher/Makefile | 8 ++- ion/src/device/shared/drivers/Makefile | 4 +- .../device/shared/drivers/console_dummy.cpp | 19 ++++++ ion/src/shared/console_display.cpp | 29 +++++++++ ion/src/simulator/Makefile | 21 ++++-- .../{ => simulator}/shared/console_stdio.cpp | 0 ion/src/simulator/shared/display.cpp | 44 ++----------- ion/src/simulator/shared/display.h | 6 +- ion/src/simulator/shared/events.h | 15 +++++ ...board_platform.cpp => events_keyboard.cpp} | 2 +- ion/src/simulator/shared/events_stdin.cpp | 58 +++++++++++++++++ ion/src/simulator/shared/framebuffer.h | 18 +++++ ion/src/simulator/shared/framebuffer_base.cpp | 61 +++++++++++++++++ ion/src/simulator/shared/framebuffer_png.cpp | 53 +++++++++++++++ ion/src/simulator/shared/keyboard_dummy.cpp | 18 +++++ .../shared/{keyboard.cpp => keyboard_sdl.cpp} | 4 +- ion/src/simulator/shared/layout.cpp | 2 +- ion/src/simulator/shared/layout.h | 6 +- ion/src/simulator/shared/main.h | 6 +- ion/src/simulator/shared/main_headless.cpp | 65 +++++++++++++++++++ .../shared/{main.cpp => main_sdl.cpp} | 6 +- ion/src/simulator/shared/platform.h | 4 +- quiz/Makefile | 5 +- quiz/src/runner.cpp | 23 ------- 33 files changed, 463 insertions(+), 128 deletions(-) create mode 100644 build/targets.simulator.web.mak create mode 100644 ion/src/device/shared/drivers/console_dummy.cpp create mode 100644 ion/src/shared/console_display.cpp rename ion/src/{ => simulator}/shared/console_stdio.cpp (100%) create mode 100644 ion/src/simulator/shared/events.h rename ion/src/simulator/shared/{events_keyboard_platform.cpp => events_keyboard.cpp} (99%) create mode 100644 ion/src/simulator/shared/events_stdin.cpp create mode 100644 ion/src/simulator/shared/framebuffer.h create mode 100644 ion/src/simulator/shared/framebuffer_base.cpp create mode 100644 ion/src/simulator/shared/framebuffer_png.cpp create mode 100644 ion/src/simulator/shared/keyboard_dummy.cpp rename ion/src/simulator/shared/{keyboard.cpp => keyboard_sdl.cpp} (94%) create mode 100644 ion/src/simulator/shared/main_headless.cpp rename ion/src/simulator/shared/{main.cpp => main_sdl.cpp} (97%) diff --git a/apps/Makefile b/apps/Makefile index 6a98142e9..65670c6ae 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -20,7 +20,9 @@ app_src += $(addprefix apps/,\ empty_battery_window.cpp \ exam_pop_up_controller.cpp \ global_preferences.cpp \ + i18n.py \ lock_view.cpp \ + main.cpp \ math_toolbox.cpp \ shift_alpha_lock_view.cpp \ suspend_timer.cpp \ @@ -83,18 +85,14 @@ $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) -# Handle epsilon-only sources -# Other executables may want to do their own i18n and main. That's the case for -# the test runner. Let's add those files to a specific epsilon-only src. When -# building apps/i18n.o, the extension doesn't really matter since it'll be -# processed by the object_for function. - -epsilon_src += $(addprefix apps/, \ - main.cpp \ - i18n.py \ -) - all_app_src = $(app_src) $(epsilon_src) $(apps_launch_on_boarding_src) $(apps_launch_default_src) $(apps_prompt_none_src) $(apps_container_prompt_update) $(apps_prompt_beta_src) $(tests_src) $(call object_for,$(all_app_src)): $(BUILD_DIR)/apps/i18n.h $(call object_for,$(all_app_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h + +apps_tests_src = $(app_calculation_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_solver_test_src) + +apps_default_src = $(app_src) $(apps_launch_default_src) $(apps_prompt_none_src); +apps_onboarding_src = $(app_src) $(apps_launch_on_boarding_src) $(apps_prompt_none_src); +apps_onboarding_update_src = $(app_src) $(apps_launch_on_boarding_src) $(apps_prompt_update_src); +apps_onboarding_beta_src = $(app_src) $(apps_launch_on_boarding_src) $(apps_prompt_beta_src); diff --git a/build/targets.device.mak b/build/targets.device.mak index 4c30db642..6f6100ddb 100644 --- a/build/targets.device.mak +++ b/build/targets.device.mak @@ -49,17 +49,17 @@ openocd: # fully filled $(BUILD_DIR)/flasher.%.$(EXE): LDFLAGS += -Lion/src/$(PLATFORM)/flasher $(BUILD_DIR)/flasher.%.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/shared/ram.ld -flasher_objs = $(call object_for,$(ion_src) $(liba_src) $(kandinsky_src) $(flasher_src) $(ion_device_dfu_xip_src)) -$(BUILD_DIR)/flasher.light.$(EXE): $(BUILD_DIR)/ion/src/$(PLATFORM)/flasher/display_light.o $(flasher_objs) -$(BUILD_DIR)/flasher.verbose.$(EXE): $(BUILD_DIR)/ion/src/$(PLATFORM)/flasher/display_verbose.o $(flasher_objs) +flasher_base_src = $(ion_xip_src) $(liba_src) $(kandinsky_src) +$(BUILD_DIR)/flasher.light.$(EXE): $(call object_for,$(flasher_base_src) $(ion_target_device_flasher_light_src)) +$(BUILD_DIR)/flasher.verbose.$(EXE): $(call object_for,$(flasher_base_src) $(ion_target_device_flasher_verbose_src)) #TODO Do not build all apps... Put elsewhere? $(BUILD_DIR)/bench.ram.$(EXE): LDFLAGS += -Lion/src/$(PLATFORM)/bench $(BUILD_DIR)/bench.ram.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/shared/ram.ld $(BUILD_DIR)/bench.flash.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/$(MODEL)/internal_flash.ld -bench_objs = $(call object_for,$(ion_src) $(liba_src) $(kandinsky_src) $(ion_device_dfu_xip_src) $(poincare_src) $(libaxx_src) $(bench_src) $(app_shared_src)) -$(BUILD_DIR)/bench.ram.$(EXE): $(bench_objs) -$(BUILD_DIR)/bench.flash.$(EXE): $(bench_objs) +bench_src = $(ion_xip_src) $(liba_src) $(kandinsky_src) $(poincare_src) $(libaxx_src) $(app_shared_src) $(ion_target_device_bench_src) +$(BUILD_DIR)/bench.ram.$(EXE): $(call object_for,$(bench_src)) +$(BUILD_DIR)/bench.flash.$(EXE): $(call object_for,$(bench_src)) .PHONY: %.two_binaries %.two_binaries: %.elf diff --git a/build/targets.mak b/build/targets.mak index ff4efa650..6c716eb67 100644 --- a/build/targets.mak +++ b/build/targets.mak @@ -1,13 +1,20 @@ # Define standard Epsilon targets -all_epsilon_common_src = $(ion_src) $(liba_src) $(kandinsky_src) $(epsilon_src) $(app_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src) $(ion_device_dfu_relocated_src) -all_epsilon_default_src = $(all_epsilon_common_src) $(apps_launch_default_src) $(apps_prompt_none_src) +base_src = $(liba_src) $(kandinsky_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src) -$(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(all_epsilon_default_src)) -$(BUILD_DIR)/epsilon.on-boarding.$(EXE): $(call object_for,$(all_epsilon_common_src) $(apps_launch_on_boarding_src) $(apps_prompt_none_src)) -$(BUILD_DIR)/epsilon.on-boarding.update.$(EXE): $(call object_for,$(all_epsilon_common_src) $(apps_launch_on_boarding_src) $(apps_prompt_update_src)) -$(BUILD_DIR)/epsilon.on-boarding.beta.$(EXE): $(call object_for,$(all_epsilon_common_src) $(apps_launch_on_boarding_src) $(apps_prompt_beta_src)) +epsilon_src = $(base_src) $(ion_default_src) $(apps_default_src) +epsilon_onboarding_src = $(base_src) $(ion_default_src) $(apps_onboarding_src) +epsilon_onboarding_update_src = $(base_src) $(ion_default_src) $(apps_onboarding_update_src) +epsilon_onboarding_beta_src = $(base_src) $(ion_default_src) $(apps_onboarding_beta_src) -$(BUILD_DIR)/test.$(EXE): $(BUILD_DIR)/quiz/src/tests_symbols.o $(call object_for,$(ion_src) $(liba_src) $(kandinsky_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src) $(ion_device_dfu_relocated_src) $(tests_src) $(runner_src) $(app_calculation_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_solver_test_src)) +$(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(epsilon_src)) +$(BUILD_DIR)/epsilon.onboarding.$(EXE): $(call object_for,$(epsilon_onboarding_src)) +$(BUILD_DIR)/epsilon.onboarding.update.$(EXE): $(call object_for,$(epsilon_onboarding_update_src)) +$(BUILD_DIR)/epsilon.onboarding.beta.$(EXE): $(call object_for,$(epsilon_onboarding_beta_src)) + +test_base_src = $(base_src) $(apps_tests_src) $(runner_src) $(tests_src) + +test_runner_src = $(test_base_src) $(ion_default_src) +$(BUILD_DIR)/test.$(EXE): $(call object_for,$(test_runner_src)) # Define handy targets # Those can be built easily by simply invoking "make target.ext". The named file diff --git a/build/targets.simulator.mak b/build/targets.simulator.mak index e7fae0855..8899125c7 100644 --- a/build/targets.simulator.mak +++ b/build/targets.simulator.mak @@ -1,14 +1,12 @@ -$(BUILD_DIR)/epsilon.packed.js: LDFLAGS += --memory-init-file 0 -$(BUILD_DIR)/epsilon.packed.js: $(call object_for,$(all_epsilon_default_src)) +# Headless targets +epsilon_headless_src = $(base_src) $(ion_headless_src) $(apps_default_src) +$(BUILD_DIR)/epsilon.headless.$(EXE): $(call object_for,$(epsilon_headless_src)) +$(BUILD_DIR)/epsilon.headless.$(EXE): LDFLAGS += `libpng-config --ldflags` -.PHONY: workshop_python_emulator -workshop_python_emulator: - make PLATFORM=simulator TARGET=web clean_for_apps_selection - make PLATFORM=simulator TARGET=web EPSILON_APPS=code - make PLATFORM=simulator TARGET=web clean_for_apps_selection +test_runner_headless_src = $(test_base_src) $(ion_headless_src) +$(BUILD_DIR)/test.headless.$(EXE): $(call object_for,$(test_runner_headless_src)) +$(BUILD_DIR)/test.headless.$(EXE): LDFLAGS += `libpng-config --ldflags` -.PHONY: clean_for_apps_selection -clean_for_apps_selection: - @echo "CLEAN BEFORE CHANGING EPSILON_APPS" - $(Q) rm -f $(BUILD_DIR)/apps/apps_container_storage.o - $(Q) rm -f $(BUILD_DIR)/apps/i18n.* +HANDY_TARGETS += epsilon.headless test.headless + +-include build/targets.simulator.$(TARGET).mak diff --git a/build/targets.simulator.web.mak b/build/targets.simulator.web.mak new file mode 100644 index 000000000..9011e2831 --- /dev/null +++ b/build/targets.simulator.web.mak @@ -0,0 +1,17 @@ +$(BUILD_DIR)/epsilon.js: EMSCRIPTEN_INIT_FILE = 1 + +$(BUILD_DIR)/test.headless.js: EMSCRIPTEN_MODULARIZE = 0 + +$(BUILD_DIR)/epsilon.packed.js: $(call object_for,$(epsilon_src)) + +.PHONY: workshop_python_emulator +workshop_python_emulator: + make PLATFORM=simulator TARGET=web clean_for_apps_selection + make PLATFORM=simulator TARGET=web EPSILON_APPS=code + make PLATFORM=simulator TARGET=web clean_for_apps_selection + +.PHONY: clean_for_apps_selection +clean_for_apps_selection: + @echo "CLEAN BEFORE CHANGING EPSILON_APPS" + $(Q) rm -f $(BUILD_DIR)/apps/apps_container_storage.o + $(Q) rm -f $(BUILD_DIR)/apps/i18n.* diff --git a/build/toolchain.emscripten.mak b/build/toolchain.emscripten.mak index c547d59e5..9ac1010a2 100644 --- a/build/toolchain.emscripten.mak +++ b/build/toolchain.emscripten.mak @@ -110,7 +110,14 @@ EMFLAGS += -s SAFE_HEAP=1 EMFLAGS += -s STACK_OVERFLOW_CHECK=1 endif -EMFLAGS += -s WASM=0 -s MODULARIZE=1 -s 'EXPORT_NAME="Epsilon"' +# Configure EMFLAGS +EMFLAGS += -s WASM=0 + +# Configure LDFLAGS +EMSCRIPTEN_MODULARIZE ?= 1 +LDFLAGS += -s MODULARIZE=$(EMSCRIPTEN_MODULARIZE) -s 'EXPORT_NAME="Epsilon"' +EMSCRIPTEN_INIT_FILE ?= 0 +LDFLAGS += --memory-init-file $(EMSCRIPTEN_INIT_FILE) SFLAGS += $(EMFLAGS) LDFLAGS += $(EMFLAGS) -Oz -s EXPORTED_FUNCTIONS='["_main", "_IonSimulatorKeyboardKeyDown", "_IonSimulatorKeyboardKeyUp", "_IonSimulatorEventsPushEvent", "_IonSoftwareVersion", "_IonPatchLevel"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='["UTF8ToString"]' diff --git a/ion/Makefile b/ion/Makefile index d41dcbbc4..a9a948031 100644 --- a/ion/Makefile +++ b/ion/Makefile @@ -15,6 +15,8 @@ include ion/src/$(PLATFORM)/Makefile -include ion/test/$(PLATFORM)/Makefile include ion/src/shared/tools/Makefile +ion_console_display_src += ion/src/shared/console_display.cpp + # We need to work around a GCC bug (concerning versions < 5.1). It is valid in # C++11 to initialize a character array by providing a string litteral (e.g. # char test[4]= "ab"; is valid and should initialize test to 'a','b',0,0). @@ -23,6 +25,7 @@ initializer_list = $(shell echo $(1) | sed "s/\(.\)/'\1',/g")0 $(call object_for,ion/src/shared/platform_info.cpp): SFLAGS += -DPATCH_LEVEL="$(call initializer_list,$(PATCH_LEVEL))" -DEPSILON_VERSION="$(call initializer_list,$(EPSILON_VERSION))" ion_src += $(addprefix ion/src/shared/, \ + console_line.cpp \ crc32_eat_byte.cpp \ decompress.cpp \ events.cpp \ @@ -46,3 +49,7 @@ tests_src += $(addprefix ion/test/,\ ifdef ION_STORAGE_LOG SFLAGS += -DION_STORAGE_LOG=1 endif + +ion_default_src = $(ion_src) $(ion_simulator_sdl_src) $(ion_device_dfu_relocated_src) $(ion_console_display_src) +ion_xip_src = $(ion_src) $(ion_simulator_sdl_src) $(ion_device_dfu_xip_src) $(ion_console_uart_src) +ion_headless_src = $(ion_src) $(ion_simulator_headless_src) $(ion_device_dfu_relocated_src) $(ion_console_stdio_src) diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index b77ef170f..5adb13861 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -19,7 +19,7 @@ ion_src += $(addprefix ion/src/shared/, \ ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/shared -$(call object_for,$(ion_device_src) $(dfu_src) $(flasher_src) $(usb_src) $(bench_src) $(ion_device_dfu_xip_src) $(ion_device_dfu_relocated_src)): SFLAGS += $(ION_DEVICE_SFLAGS) +$(call object_for,$(ion_device_src) $(dfu_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(usb_src) $(ion_target_device_bench_src) $(ion_device_dfu_xip_src) $(ion_device_dfu_relocated_src) $(ion_console_uart_src)): SFLAGS += $(ION_DEVICE_SFLAGS) ion_src += $(ion_device_src) # When using the register.h C++ file in production mode, we expect the compiler diff --git a/ion/src/device/bench/Makefile b/ion/src/device/bench/Makefile index 096a93182..5e59a61cf 100644 --- a/ion/src/device/bench/Makefile +++ b/ion/src/device/bench/Makefile @@ -1,11 +1,11 @@ -bench_src += $(addprefix ion/src/device/bench/, \ +ion_target_device_bench_src += $(addprefix ion/src/device/bench/, \ bench.cpp \ command_handler.cpp \ command_list.cpp \ runner.cpp \ ) -bench_src += $(addprefix ion/src/device/bench/command/, \ +ion_target_device_bench_src += $(addprefix ion/src/device/bench/command/, \ adc.cpp \ backlight.cpp \ charge.cpp \ diff --git a/ion/src/device/flasher/Makefile b/ion/src/device/flasher/Makefile index 6952e2809..840b63d2c 100644 --- a/ion/src/device/flasher/Makefile +++ b/ion/src/device/flasher/Makefile @@ -1,3 +1,9 @@ -flasher_src += $(addprefix ion/src/device/flasher/, \ +ion_target_device_flasher_light_src = $(addprefix ion/src/device/flasher/, \ main.cpp \ + display_light.cpp \ +) + +ion_target_device_flasher_verbose_src = $(addprefix ion/src/device/flasher/, \ + main.cpp \ + display_verbose.cpp \ ) diff --git a/ion/src/device/shared/drivers/Makefile b/ion/src/device/shared/drivers/Makefile index 4b227faf2..6def5933e 100644 --- a/ion/src/device/shared/drivers/Makefile +++ b/ion/src/device/shared/drivers/Makefile @@ -3,7 +3,6 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \ battery.cpp \ base64.cpp \ board.cpp \ - console.cpp \ crc32.cpp \ display.cpp \ events_keyboard_platform.cpp \ @@ -20,3 +19,6 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \ usb.cpp \ wakeup.cpp \ ) + +ion_console_uart_src = ion/src/device/shared/drivers/console.cpp +ion_console_display_src += ion/src/device/shared/drivers/console_dummy.cpp diff --git a/ion/src/device/shared/drivers/console_dummy.cpp b/ion/src/device/shared/drivers/console_dummy.cpp new file mode 100644 index 000000000..9ed1718f5 --- /dev/null +++ b/ion/src/device/shared/drivers/console_dummy.cpp @@ -0,0 +1,19 @@ +#include "console.h" + +namespace Ion { +namespace Device { +namespace Console { + +void init() { +} + +void shutdown() { +} + +bool peerConnected() { + return false; +} + +} +} +} diff --git a/ion/src/shared/console_display.cpp b/ion/src/shared/console_display.cpp new file mode 100644 index 000000000..4b9e67694 --- /dev/null +++ b/ion/src/shared/console_display.cpp @@ -0,0 +1,29 @@ +#include +#include +#include + +namespace Ion { +namespace Console { + +char readChar() { + return NULL; +} + +static KDPoint cursor = KDPointZero; + +void writeChar(char c) { + char text[2] = {c, 0}; + KDContext * ctx = KDIonContext::sharedContext(); + cursor = ctx->drawString(text, cursor); + if (cursor.y() > Ion::Display::Height) { + cursor = KDPoint(cursor.x(), 0); + } +} + +bool transmissionDone() { + // Always true because we flush after each writeChar + return true; +} + +} +} diff --git a/ion/src/simulator/Makefile b/ion/src/simulator/Makefile index 84d333a6c..b8547460b 100644 --- a/ion/src/simulator/Makefile +++ b/ion/src/simulator/Makefile @@ -17,13 +17,26 @@ ion_src += $(addprefix ion/src/shared/, \ dummy/usb.cpp \ ) -ion_src += $(addprefix ion/src/simulator/shared/, \ +ion_simulator_sdl_src += $(addprefix ion/src/simulator/shared/, \ display.cpp \ - events_keyboard_platform.cpp \ - keyboard.cpp \ - main.cpp \ + events_keyboard.cpp \ + framebuffer_base.cpp \ + keyboard_sdl.cpp \ + main_sdl.cpp \ layout.cpp \ ) +ion_simulator_headless_src += $(addprefix ion/src/simulator/shared/, \ + events_stdin.cpp \ + framebuffer_base.cpp \ + framebuffer_png.cpp \ + keyboard_dummy.cpp \ + main_headless.cpp \ +) + +$(call object_for,ion/src/simulator/shared/framebuffer_png.cpp): SFLAGS += `libpng-config --cflags` + +ion_console_stdio_src = ion/src/simulator/shared/console_stdio.cpp + include ion/src/simulator/$(TARGET)/Makefile include ion/src/simulator/external/Makefile diff --git a/ion/src/shared/console_stdio.cpp b/ion/src/simulator/shared/console_stdio.cpp similarity index 100% rename from ion/src/shared/console_stdio.cpp rename to ion/src/simulator/shared/console_stdio.cpp diff --git a/ion/src/simulator/shared/display.cpp b/ion/src/simulator/shared/display.cpp index 96e060d5d..28069012d 100644 --- a/ion/src/simulator/shared/display.cpp +++ b/ion/src/simulator/shared/display.cpp @@ -1,52 +1,22 @@ #include "display.h" -#include "main.h" +#include "framebuffer.h" +#include #include #include #include -/* Drawing on an SDL texture - * In SDL2, drawing bitmap data happens through textures, whose data lives in - * the GPU's memory. Reading data back from a texture is not possible, so we - * simply maintain a framebuffer in RAM since Ion::Display::pullRect expects to - * be able to read pixel data back. - * A side effect is that we rewrite the whole texture when redrawing the screen. - * This might not be the most efficient way since sending pixels to the GPU is - * rather expensive. */ - -static KDColor sPixels[Ion::Display::Width * Ion::Display::Height]; - namespace Ion { -namespace Display { - -static KDFrameBuffer sFrameBuffer = KDFrameBuffer(sPixels, KDSize(Ion::Display::Width, Ion::Display::Height)); - -void pushRect(KDRect r, const KDColor * pixels) { - SDL::Main::setNeedsRefresh(); - sFrameBuffer.pushRect(r, pixels); -} - -void pushRectUniform(KDRect r, KDColor c) { - SDL::Main::setNeedsRefresh(); - sFrameBuffer.pushRectUniform(r, c); -} - -void pullRect(KDRect r, KDColor * pixels) { - sFrameBuffer.pullRect(r, pixels); -} - -} -} - -namespace Ion { -namespace SDL { +namespace Simulator { namespace Display { static SDL_Texture * sFramebufferTexture = nullptr; void init(SDL_Renderer * renderer) { + Uint32 texturePixelFormat = SDL_PIXELFORMAT_RGB565; + assert(sizeof(KDColor) == SDL_BYTESPERPIXEL(texturePixelFormat)); sFramebufferTexture = SDL_CreateTexture( renderer, - SDL_PIXELFORMAT_RGB565, + texturePixelFormat, SDL_TEXTUREACCESS_STREAMING, Ion::Display::Width, Ion::Display::Height @@ -63,7 +33,7 @@ void draw(SDL_Renderer * renderer, SDL_Rect * rect) { void * pixels = nullptr; SDL_LockTexture(sFramebufferTexture, nullptr, &pixels, &pitch); assert(pitch == 2*Ion::Display::Width); - memcpy(pixels, sPixels, sizeof(sPixels)); + memcpy(pixels, Framebuffer::address(), sizeof(KDColor)*Ion::Display::Width*Ion::Display::Height); SDL_UnlockTexture(sFramebufferTexture); SDL_RenderCopy(renderer, sFramebufferTexture, nullptr, rect); diff --git a/ion/src/simulator/shared/display.h b/ion/src/simulator/shared/display.h index 0734977d1..5b1b98170 100644 --- a/ion/src/simulator/shared/display.h +++ b/ion/src/simulator/shared/display.h @@ -1,11 +1,11 @@ -#ifndef ION_SDL_DISPLAY_H -#define ION_SDL_DISPLAY_H +#ifndef ION_SIMULATOR_DISPLAY_H +#define ION_SIMULATOR_DISPLAY_H #include #include namespace Ion { -namespace SDL { +namespace Simulator { namespace Display { void init(SDL_Renderer * renderer); diff --git a/ion/src/simulator/shared/events.h b/ion/src/simulator/shared/events.h new file mode 100644 index 000000000..5245e0a20 --- /dev/null +++ b/ion/src/simulator/shared/events.h @@ -0,0 +1,15 @@ +#ifndef ION_SIMULATOR_EVENTS_H +#define ION_SIMULATOR_EVENTS_H + +namespace Ion { +namespace Simulator { +namespace Events { + +void dumpEventCount(int i); +void logAfter(int numberOfEvents); + +} +} +} + +#endif diff --git a/ion/src/simulator/shared/events_keyboard_platform.cpp b/ion/src/simulator/shared/events_keyboard.cpp similarity index 99% rename from ion/src/simulator/shared/events_keyboard_platform.cpp rename to ion/src/simulator/shared/events_keyboard.cpp index ebd67ba29..19f6e43a6 100644 --- a/ion/src/simulator/shared/events_keyboard_platform.cpp +++ b/ion/src/simulator/shared/events_keyboard.cpp @@ -185,7 +185,7 @@ Event getPlatformEvent() { // The while is important: it'll do a fast-pass over all useless SDL events if (event.type == SDL_WINDOWEVENT) { if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - Ion::SDL::Main::relayout(); + Ion::Simulator::Main::relayout(); } } if (event.type == SDL_QUIT) { diff --git a/ion/src/simulator/shared/events_stdin.cpp b/ion/src/simulator/shared/events_stdin.cpp new file mode 100644 index 000000000..64fab5bd2 --- /dev/null +++ b/ion/src/simulator/shared/events_stdin.cpp @@ -0,0 +1,58 @@ +#include "main.h" +#include "platform.h" +#include "framebuffer.h" +#include "events.h" + +#include +#include +#include + +void IonSimulatorEventsPushEvent(int eventNumber) { +} + +static int sLogAfterNumberOfEvents = -1; +static int sEventCount = 0; + +namespace Ion { +namespace Events { + +Event getPlatformEvent() { + Ion::Events::Event event = Ion::Events::None; + while (!(event.isDefined() && event.isKeyboardEvent())) { + int c = getchar(); + if (c == EOF) { + printf("Finished processing %d events\n", sEventCount); + event = Ion::Events::Termination; + break; + } + event = Ion::Events::Event(c); + } + if (sEventCount++ > sLogAfterNumberOfEvents && sLogAfterNumberOfEvents >= 0) { + char filename[32]; + sprintf(filename, "event%d.png", sEventCount); + Ion::Simulator::Framebuffer::writeToFile(filename); +#if DEBUG + printf("Event %d is %s\n", sEventCount, event.name()); +#endif + } + return event; +} + +} +} + +namespace Ion { +namespace Simulator { +namespace Events { + +void dumpEventCount(int i) { + printf("Current event index: %d\n", sEventCount); +} + +void logAfter(int numberOfEvents) { + sLogAfterNumberOfEvents = numberOfEvents; +} + +} +} +} diff --git a/ion/src/simulator/shared/framebuffer.h b/ion/src/simulator/shared/framebuffer.h new file mode 100644 index 000000000..e9eed19e2 --- /dev/null +++ b/ion/src/simulator/shared/framebuffer.h @@ -0,0 +1,18 @@ +#ifndef ION_SIMULATOR_FRAMEBUFFER_H +#define ION_SIMULATOR_FRAMEBUFFER_H + +#include + +namespace Ion { +namespace Simulator { +namespace Framebuffer { + +const KDColor * address(); +void setActive(bool enabled); +void writeToFile(const char * filename); + +} +} +} + +#endif diff --git a/ion/src/simulator/shared/framebuffer_base.cpp b/ion/src/simulator/shared/framebuffer_base.cpp new file mode 100644 index 000000000..0eb597a5e --- /dev/null +++ b/ion/src/simulator/shared/framebuffer_base.cpp @@ -0,0 +1,61 @@ +#include "framebuffer.h" +#include +#include "main.h" + +/* Drawing on an SDL texture + * In SDL2, drawing bitmap data happens through textures, whose data lives in + * the GPU's memory. Reading data back from a texture is not possible, so we + * simply maintain a framebuffer in RAM since Ion::Display::pullRect expects to + * be able to read pixel data back. + * A side effect is that we rewrite the whole texture when redrawing the screen. + * This might not be the most efficient way since sending pixels to the GPU is + * rather expensive. + * This is also very useful when running headless because we can easily log the + * framebuffer to a PNG file. */ + +static KDColor sPixels[Ion::Display::Width * Ion::Display::Height]; +static bool sFrameBufferActive = true; + +namespace Ion { +namespace Display { + +static KDFrameBuffer sFrameBuffer = KDFrameBuffer(sPixels, KDSize(Ion::Display::Width, Ion::Display::Height)); + +void pushRect(KDRect r, const KDColor * pixels) { + if (sFrameBufferActive) { + Simulator::Main::setNeedsRefresh(); + sFrameBuffer.pushRect(r, pixels); + } +} + +void pushRectUniform(KDRect r, KDColor c) { + if (sFrameBufferActive) { + Simulator::Main::setNeedsRefresh(); + sFrameBuffer.pushRectUniform(r, c); + } +} + +void pullRect(KDRect r, KDColor * pixels) { + if (sFrameBufferActive) { + sFrameBuffer.pullRect(r, pixels); + } +} + +} +} + +namespace Ion { +namespace Simulator { +namespace Framebuffer { + +const KDColor * address() { + return sPixels; +} + +void setActive(bool enabled) { + sFrameBufferActive = enabled; +} + +} +} +} diff --git a/ion/src/simulator/shared/framebuffer_png.cpp b/ion/src/simulator/shared/framebuffer_png.cpp new file mode 100644 index 000000000..73ee454ee --- /dev/null +++ b/ion/src/simulator/shared/framebuffer_png.cpp @@ -0,0 +1,53 @@ +#include "framebuffer.h" +#include +#include +#include + +typedef struct { + uint8_t red; + uint8_t green; + uint8_t blue; +} pixel_t; + +void Ion::Simulator::Framebuffer::writeToFile(const char * filename) { + FILE * file = fopen(filename, "wb"); // Write in binary mode + //ENSURE(file != NULL, "Opening file %s", filename); + + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + //ENSURE(png != NULL, "Allocating PNG write structure"); + + png_infop info = png_create_info_struct(png); + //ENSURE(info != NULL, "Allocating info structure"); + + png_init_io(png, file); + + png_set_IHDR(png, info, + Ion::Display::Width, Ion::Display::Height, + 8, // Number of bits per channel + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png, info); + + static_assert(sizeof(pixel_t) == 3, "pixel_t shall be 3 bytes long (RGB888 format)"); + pixel_t * row = (pixel_t *)malloc(3*Ion::Display::Width); + const KDColor * pixels = address(); + for (int j=0;j +#include "platform.h" + +void IonSimulatorKeyboardKeyDown(int keyNumber) { +} + +void IonSimulatorKeyboardKeyUp(int keyNumber) { +} + +namespace Ion { +namespace Keyboard { + +State scan() { + return 0; +} + +} +} diff --git a/ion/src/simulator/shared/keyboard.cpp b/ion/src/simulator/shared/keyboard_sdl.cpp similarity index 94% rename from ion/src/simulator/shared/keyboard.cpp rename to ion/src/simulator/shared/keyboard_sdl.cpp index 911957051..4940c2c98 100644 --- a/ion/src/simulator/shared/keyboard.cpp +++ b/ion/src/simulator/shared/keyboard_sdl.cpp @@ -30,7 +30,7 @@ State scan() { IonSimulatorCallbackDidScanKeyboard(); // Grab this opportunity to refresh the display if needed - SDL::Main::refresh(); + Simulator::Main::refresh(); #if EPSILON_SDL_SCREEN_ONLY // In this case, keyboard states will be sent over another channel @@ -43,7 +43,7 @@ State scan() { SDL_Point p; Uint32 mouseState = SDL_GetMouseState(&p.x, &p.y); if (mouseState & SDL_BUTTON(SDL_BUTTON_LEFT)) { - Key k = SDL::Layout::keyAt(&p); + Key k = Simulator::Layout::keyAt(&p); state.setKey(k); } diff --git a/ion/src/simulator/shared/layout.cpp b/ion/src/simulator/shared/layout.cpp index 2a7f10dfa..0b2241778 100644 --- a/ion/src/simulator/shared/layout.cpp +++ b/ion/src/simulator/shared/layout.cpp @@ -1,7 +1,7 @@ #include "layout.h" namespace Ion { -namespace SDL { +namespace Simulator { namespace Layout { static constexpr int backgroundWidth = 1160; diff --git a/ion/src/simulator/shared/layout.h b/ion/src/simulator/shared/layout.h index 765a79648..9e0f10ec6 100644 --- a/ion/src/simulator/shared/layout.h +++ b/ion/src/simulator/shared/layout.h @@ -1,11 +1,11 @@ -#ifndef ION_SDL_LAYOUT_H -#define ION_SDL_LAYOUT_H +#ifndef ION_SIMULATOR_LAYOUT_H +#define ION_SIMULATOR_LAYOUT_H #include #include namespace Ion { -namespace SDL { +namespace Simulator { namespace Layout { void recompute(int width, int height); diff --git a/ion/src/simulator/shared/main.h b/ion/src/simulator/shared/main.h index 8d5959017..544f008f4 100644 --- a/ion/src/simulator/shared/main.h +++ b/ion/src/simulator/shared/main.h @@ -1,8 +1,8 @@ -#ifndef ION_SDL_MAIN_H -#define ION_SDL_MAIN_H +#ifndef ION_SIMULATOR_MAIN_H +#define ION_SIMULATOR_MAIN_H namespace Ion { -namespace SDL { +namespace Simulator { namespace Main { void init(); diff --git a/ion/src/simulator/shared/main_headless.cpp b/ion/src/simulator/shared/main_headless.cpp new file mode 100644 index 000000000..c1cdfbe0b --- /dev/null +++ b/ion/src/simulator/shared/main_headless.cpp @@ -0,0 +1,65 @@ +#include "main.h" +#include "display.h" +#include "platform.h" +#include "framebuffer.h" +#include "events.h" + +#include +#include +#include +#include +#include +#include + +constexpr int kHeapSize = 131072; +constexpr int kStackSize = 32768; + +char heap[kHeapSize]; +extern "C" { + char * _heap_start = (char *)heap; + char * _heap_end = _heap_start+kHeapSize; + int main(int argc, char * argv[]); +} + +void Ion::Timing::msleep(uint32_t ms) { +} + +int main(int argc, char * argv[]) { + Ion::Simulator::Framebuffer::setActive(false); + // Parse command-line arguments + for (int i=1; i i+1) { + Ion::Simulator::Framebuffer::setActive(true); + Ion::Simulator::Events::logAfter(atoi(argv[i+1])); + } + } + + // Handle signals + signal(SIGABRT, Ion::Simulator::Events::dumpEventCount); + + // Limit stack usage + struct rlimit stackLimits = {kStackSize, kStackSize}; + setrlimit(RLIMIT_STACK, &stackLimits); + + ion_main(argc, argv); + return 0; +} + +namespace Ion { +namespace Simulator { +namespace Main { + +void init() { +} + +void setNeedsRefresh() { +} + +void relayout() { +} + +void refresh() { +} +} +} +} diff --git a/ion/src/simulator/shared/main.cpp b/ion/src/simulator/shared/main_sdl.cpp similarity index 97% rename from ion/src/simulator/shared/main.cpp rename to ion/src/simulator/shared/main_sdl.cpp index ea2f828d3..6a468da21 100644 --- a/ion/src/simulator/shared/main.cpp +++ b/ion/src/simulator/shared/main_sdl.cpp @@ -25,17 +25,17 @@ int main(int argc, char * argv[]) { } IonSimulatorTelemetryInit(); - Ion::SDL::Main::init(); + Ion::Simulator::Main::init(); IonSimulatorTelemetryEvent("Calculator"); ion_main(arguments.size(), &arguments[0]); - Ion::SDL::Main::quit(); + Ion::Simulator::Main::quit(); IonSimulatorTelemetryDeinit(); return 0; } namespace Ion { -namespace SDL { +namespace Simulator { namespace Main { static SDL_Window * sWindow = nullptr; diff --git a/ion/src/simulator/shared/platform.h b/ion/src/simulator/shared/platform.h index ae23ef68e..4b8e461cb 100644 --- a/ion/src/simulator/shared/platform.h +++ b/ion/src/simulator/shared/platform.h @@ -1,5 +1,5 @@ -#ifndef ION_SDL_PLATFORM_H -#define ION_SDL_PLATFORM_H +#ifndef ION_SIMULATOR_PLATFORM_H +#define ION_SIMULATOR_PLATFORM_H #include diff --git a/quiz/Makefile b/quiz/Makefile index 6343b6f90..25ddd96b1 100644 --- a/quiz/Makefile +++ b/quiz/Makefile @@ -1,8 +1,5 @@ SFLAGS += -Iquiz/include -QUIZ_USE_CONSOLE ?= 0 -$(call object_for,quiz/src/runner.cpp): SFLAGS += -DQUIZ_USE_CONSOLE=$(QUIZ_USE_CONSOLE) - define rule_for_quiz_symbols $$(BUILD_DIR)/quiz/src/$(subst _src,,$(1))_symbols.c: $$($(1)) | $$$$(@D)/. @ echo "AWK $$@" @@ -19,7 +16,7 @@ runner_src += $(addprefix quiz/src/, \ runner.cpp \ ) -runner_src += $(symbols_file) +runner_src += $(BUILD_DIR)/quiz/src/tests_symbols.c $(call object_for,$(runner_src)): SFLAGS += -Iquiz/src $(BUILD_DIR)/quiz/src/%_symbols.o: SFLAGS += -Iquiz/src diff --git a/quiz/src/runner.cpp b/quiz/src/runner.cpp index 3ac3d1cb0..892d7bfb7 100644 --- a/quiz/src/runner.cpp +++ b/quiz/src/runner.cpp @@ -8,20 +8,7 @@ #include void quiz_print(const char * message) { -#if QUIZ_USE_CONSOLE Ion::Console::writeLine(message); -#else - static int line_y = 0; - KDContext * ctx = KDIonContext::sharedContext(); - const KDFont * font = KDFont::LargeFont; - int line_height = font->glyphSize().height(); - ctx->drawString(message, KDPoint(0, line_y), font); - line_y += line_height; - if (line_y + line_height > Ion::Display::Height) { - line_y = 0; - // Clear screen maybe? - } -#endif } static inline void ion_main_inner() { @@ -37,11 +24,6 @@ static inline void ion_main_inner() { i++; } quiz_print("ALL TESTS FINISHED"); -#if !QUIZ_USE_CONSOLE - while (1) { - Ion::Timing::msleep(1000); - } -#endif } void ion_main(int argc, char * argv[]) { @@ -59,10 +41,5 @@ void ion_main(int argc, char * argv[]) { Poincare::TreePool::sharedPool()->log(); #endif quiz_assert(false); -#if !QUIZ_USE_CONSOLE - while (1) { - Ion::Timing::msleep(1000); - } -#endif } }