Skip to content

pharo-graphics/PharoSDL3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

628 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PharoSDL3

Pharo Smalltalk bindings for SDL (Simple DirectMedia Layer) version 3.0.

SDL is a cross-platform development library designed to provide low-level access to audio, keyboard, mouse, joystick, and graphics hardware. It is used by video playback software, emulators, and games.

License: MIT Test

Installation

1. Load the Pharo project

In a Pharo 14 image, evaluate the following Metacello script:

Metacello new
    baseline: 'SDL3';
    repository: 'github://tinchodias/PharoSDL3:dev/src';
    load

Alternatively, from your terminal:

curl https://get.pharo.org/140+vmLatest | bash
./pharo Pharo.image metacello install --save github://tinchodias/PharoSDL3:dev/src SDL3

2. Ensure SDL3 library is available

Since end of June/2026, the Pharo 14 "latest" VM ships SDL3 for Mac and Windows (not Linux yet). Find below other options to ensure the SDL3 library is available on your system so Pharo's FFI can find it.

  • MacOS: brew install sdl3
  • Linux: Build from source or use your package manager.
  • Windows: Download the DLL from SDL releases and place it in the same folder as your Pharo image.

New OSWindow Drivers

The System Settings provide an option to establish the OSWindow driver. Search for "OSWindow": System Settings

You can force the driver from an environment variable, from terminal:

  1. Download Pharo 14 via zeroconf script as described above
  2. Load this project's baseline
  3. Save and Close
  4. Run in terminal: PHARO_WINDOW_DRIVER=OSSDL3Driver ./pharo-ui Pharo.image
  5. Verify that OSWindowDriver current answers a OSSDL3Driver

Other options define the strategy for refreshing the window & VSYNC. The OSBenchmarkMorph can show metrics and visuals related to such options.

Demos & Tests

The project includes automated tests as well as interactive demos. These demos complement automated testing by allowing for human verification of visual rendering and event handling.

Important: Pharo's UI and SDL2 (used by default in Pharo 14) conflict with SDL3's subsystems. It is recommended to run SDL3 tests and demos in headless mode or ensure proper work.

Tests

Run tests from the terminal:

./pharo Pharo.image test 'SDL3-Tests' 'SDL3-GPU-Tests'

Demos

You can run any of the following demos by evaluating ./pharo Pharo.image eval '<ClassName> new run' from terminal. They are listed below from simplest to most advanced:

Core API Demos

  • SDL3ClearDemoApp: The basic "Hello World" of window management and rendering clear operations.
  • SDL3LogEventsDemoApp: Real-time logging of the SDL3 event stream (mouse, keyboard, window) to a console.
  • SDL3SystemQueryDemoApp: Queries system and device properties like display modes, audio drivers, and video drivers.
  • SDL3DisplayDemoApp: Visualizes logical display layouts, hardware specs, and multiple display boundary frontiers.
  • SDL3MouseDemoApp: Mouse-related functions including grabbing, relative mode, window confinement, warping, and system cursors.
  • SDL3KeyboardDemoApp: Low-level keyboard state monitoring (scancodes, keycodes, modifiers) and Unicode text input.
  • SDL3WindowChildrenDemoApp: Parent/child window relationships including utility, tooltip, popup menu, and modal behaviors.
  • SDL3AnimatedCursorDemoApp: Creation and usage of custom animated cursors from image frames.
  • SDL3MultiWindowDemoApp: Management and update loops for multiple top-level windows simultaneously.
  • SDL3TouchpadDemoApp: Multi-touch finger tracking on modern touchpads.
  • SDL3TouchpadZoomDemoApp: Smooth zooming gestures utilizing complex touchpad pinch events.
  • SDL3AudioRecorderDemoApp: Audio capture from the system's default microphone and playback.
  • SDL3CameraDemoApp: Live frame acquisition from a system camera with orientation support.
  • SDL3TrayMenuDemoApp: System tray integration, including icon management and contextual menus.
  • SDL3ImageClipboardDemoApp: System clipboard integration for copying and pasting image data.
  • SDL3FolderDialogDemoApp: Native system file/folder selection dialogs.

GPU API Demos (Advanced Graphics)

  • SDL3GPUClearDemoApp: The simplest entry point to the hardware-accelerated GPU API, showing basic render pass and clear color setup.
  • SDL3GPURenderStateDemoApp: Simplified use of the graphics pipeline via the SDL_Renderer API. (Video)
  • SDL3GPUQuadDemoApp: Foundations of geometry: rendering a textured quad using vertex buffers, index buffers, and UV mapping.
  • SDL3GPURoundedRectDemoApp: Perfectly anti-aliased procedural shapes using Signed Distance Fields (SDF) and fragment shaders.
  • SDL3GPUShimmerDemoApp: Mock UI with a loading effect utilizing time uniforms and procedural shader generation.
  • SDL3GPUInstancedQuadDemoApp: High-performance rendering of thousands of objects using hardware instancing and instance buffers.
  • SDL3GPUInstancingDemoApp: Massive amounts of geometric shapes rendered via GPU instancing and Shader Storage Buffer Objects (SSBO).
  • SDL3TextScrollDemoApp: Smooth text scrolling of a large file utilizing a texture atlas and instanced quad rendering.
  • SDL3GPUBlurComputeDemoApp: Real-time image processing utilizing compute shaders, storage textures, and a Gaussian blur algorithm.
  • SDL3GPUKawaseBlurDemoApp: Multi-pass post-processing effect demonstrating ping-pong buffers, downsampling/upsampling, and a Dual Kawase Blur.
  • SDL3GPUBoidsDemoApp: High-performance particle system using a compute-to-vertex-buffer architecture for a flocking simulation.
  • SDL3GPUNodeForceDemoApp: Force-directed graph simulation utilizing N-body physics in a compute shader.
  • SDL3GPUMandelbrotDemoApp: Background GPU fractal generation showcasing tiled rendering, level-of-detail (LOD), and asynchronous GPU resource loading.

Mapping SDL3 Functions to Pharo Methods

The bindings follow a consistent naming convention to map C functions to Pharo methods.

1. Low-level API (LibSDL3)

The LibSDL3 class provides direct access to the C API.

  • Prefix Removal: The SDL_ prefix is removed.
  • CamelCase: The first letter of the function name is lowercased.
  • Keywords: Function parameters are converted into Pharo keywords.
  • Argument Naming: Arguments are named using camelCase (e.g., numThreads instead of num_threads).

You can browse a mapping table in our wiki with a complete mapping from SDL functions to each Pharo method in LibSDL3.

Examples:

  • SDL_Init(flags) maps to LibSDL3 >> init: flags
  • SDL_CreateWindow(title, w, h, flags) maps to LibSDL3 >> newWindowTitle:w:h:flags:

2. High-level API (Convenience Methods)

Object-oriented classes like SDL3Window and SDL3Renderer provide more idiomatic Smalltalk methods.

  • Accessors: Getter and setter functions are converted to Smalltalk-style accessors by omitting the Get and Set prefixes.
    • SDL_GetWindowFlags(window) maps to SDL3Window >> flags
    • SDL_SetWindowBordered(window, bordered) maps to SDL3Window >> bordered: bordered
  • Output Parameters (Into): When a function returns values via pointers (output parameters), the Pharo method typically uses the Into keyword in the selector.
    • SDL_GetWindowSize(window, &w, &h) maps to SDL3Window >> getSizeIntoW:w h:h
    • SDL_GetRenderClipRect(renderer, &rect) maps to SDL3Renderer >> getRenderClipRectInto: rect
  • Argument Naming: Just like in the low-level API, all arguments use camelCase.

You can explore all available functions in the LibSDL3 class or by browsing the object classes. The tables in our wiki page can help, as well.

3. Instance Creation (Class-side Methods)

Independent root classes provide class-side methods for creating or opening resources.

  • Explicit Ownership: These methods are prefixed with unsafeNew (for creation) or unsafeOpen (for opening peripherals). This naming convention explicitly signals that the caller is responsible for manual memory management (e.g., calling destroy, close, or release).
  • Internal Assertions: These methods internally perform success assertions (typically using assertNotNullReturn).

Examples:

  • SDL3Window unsafeNewTitle: 'title' w: 800 h: 600 flags: 0
  • SDL3Joystick unsafeOpen: 0
  • SDL3PropertyGroup unsafeNew

4. GPU Block-Based API (Automatic Lifecycle)

The GPU stack provides specialized methods that use Block Closures to manage the lifecycle of transient resources (like passes, mapping addresses, or configuration structs). These methods use ensure: blocks internally to guarantee that resources are correctly closed, unmapped, or freed, even if an error occurs.

  • Pass Management: Methods like renderPassTargets:do:, computePassTextures:do:, and copyPassDo: automatically call the underlying EndGPU...Pass functions when the block finishes.
  • Safe Resource Creation: Methods like newGraphicsPipeline:, newSamplerDo:, and newBufferDo: provide a temporary CreateInfo struct to the block and automatically free it once the resource is created.
  • Memory Mapping: mapTransferBuffer:cycle:do: [ :mappedAddress | ... ] automatically unmaps the transfer buffer when the block terminates.

Example:

commandBuffer renderPassTargets: targets do: [ :renderPass |
	renderPass
		pipeline: myPipeline;
		drawPrimitives: 3 instances: 1 firstVertex: 0 firstInstance: 0
].
The block closure will be preceded by a FFI call to [SDL_BeginGPURenderPass](https://wiki.libsdl.org/SDL3/SDL_BeginGPURenderPass) and ended with a FFI call to [SDL_EndGPURenderPass](https://wiki.libsdl.org/SDL3/SDL_EndGPURenderPass)

Success Assertions

To provide a more idiomatic and safe experience, many wrapper methods in the High-level API handle error checking internally:

  • Boolean Success: Methods that return a boolean success code in C (e.g., SDL_SetWindowBordered) use assertSuccess: internally. If the call fails, an SDL3Error is raised with the message from SDL_GetError(). These methods return self on success.
  • Pointer Results: Methods that create or return SDL3 objects (e.g., newRendererFor:) use assertNotNullReturn internally. If the returned pointer is NULL, an SDL3Error is raised.
  • Void Returns: Methods returning void in C (e.g., destroy) do not perform assertions and return self to allow for method chaining.
  • Query Methods: Methods that return a state or value (e.g., isTextInputActive or flags) do not perform internal assertions and return the value directly.

You can explore all available functions in the LibSDL3 class or by browsing the object classes.

More Information

  • Is this code generated? Yes, it was initially generated with CIG and post-processed manually.
  • Wiki: Check the project wiki for post-processing details and technical documentation.

License

This project is licensed under the MIT license.

About

No description, website, or topics provided.

Resources

License

Stars

5 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors