<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>SDL3 for Scala Native</title>
  <link href="https://sdl3.edadma.dev/feed.xml" rel="self"/>
  <link href="https://sdl3.edadma.dev/"/>
  <id>https://sdl3.edadma.dev/feed.xml</id>
  <updated>2026-06-07T00:00:41.559004835Z</updated>
  <author><name>Ed Maxedon</name></author>
  <entry>
    <title>sdl3_ttf — text</title>
    <link href="https://sdl3.edadma.dev/modules/ttf/"/>
    <id>https://sdl3.edadma.dev/modules/ttf/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>TrueType text rendering, layered on the core binding. Pulls in sdl3 transitively and adds @link(&quot;SDL3_ttf&quot;); install the native library with brew install sdl3_ttf (or your platform’s package). Colours are the…</summary>
    <content type="html">&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3_ttf&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TrueType text rendering, layered on the core binding. Pulls in &lt;code&gt;sdl3&lt;/code&gt; transitively and
adds &lt;code&gt;@link(&amp;quot;SDL3_ttf&amp;quot;)&lt;/code&gt;; install the native library with &lt;code&gt;brew install sdl3_ttf&lt;/code&gt; (or your
platform’s package). Colours are the core &lt;code&gt;sdl3.Color&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lifecycle-and-fonts&quot;&gt;Lifecycle and fonts&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;ttfInit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;                                       &lt;span class=&quot;hl-comment&quot;&gt;// initialise SDL_ttf&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; font &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; openFont&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;/path/to/font.ttf&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;24.0&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;hl-comment&quot;&gt;// path, point size&lt;/span&gt;
&lt;span class=&quot;hl-comment&quot;&gt;// …&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
ttfQuit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;Font&lt;/code&gt; is an &lt;code&gt;AnyVal&lt;/code&gt; over the SDL_ttf handle:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;isNull
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setSize&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;18.0&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;              &lt;span class=&quot;hl-comment&quot;&gt;// re-set point size&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;style &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;STYLE_BOLD&lt;/span&gt; | &lt;span class=&quot;hl-type&quot;&gt;STYLE_ITALIC&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;style                      &lt;span class=&quot;hl-comment&quot;&gt;// current style bitmask&lt;/span&gt;

font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;height                    &lt;span class=&quot;hl-comment&quot;&gt;// line height, pixels&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;ascent
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;descent
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;lineSkip                  &lt;span class=&quot;hl-comment&quot;&gt;// recommended line spacing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Style flags: &lt;code&gt;STYLE_NORMAL&lt;/code&gt;, &lt;code&gt;STYLE_BOLD&lt;/code&gt;, &lt;code&gt;STYLE_ITALIC&lt;/code&gt;, &lt;code&gt;STYLE_UNDERLINE&lt;/code&gt;,
&lt;code&gt;STYLE_STRIKETHROUGH&lt;/code&gt; (combine with &lt;code&gt;|&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&quot;measuring&quot;&gt;Measuring&lt;/h2&gt;
&lt;p&gt;Get the pixel size a string would occupy without rendering it — the basis for laying text
out before you draw:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;Hello, SDL3&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;rendering&quot;&gt;Rendering&lt;/h2&gt;
&lt;p&gt;Each render call produces an &lt;code&gt;sdl3.Surface&lt;/code&gt;. The quality/cost ladder:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;renderSolid&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; fg&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                    &lt;span class=&quot;hl-comment&quot;&gt;// fast, aliased, transparent bg&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;renderShaded&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; fg&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; bg&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;hl-comment&quot;&gt;// antialiased on a solid box&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;renderBlended&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; fg&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                  &lt;span class=&quot;hl-comment&quot;&gt;// antialiased with alpha — the usual choice&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;renderBlendedWrapped&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; fg&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; wrapPixels&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-comment&quot;&gt;// word-wrapped; 0 wraps only on newlines&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Upload the surface to a texture and free it, or let &lt;code&gt;texture&lt;/code&gt; do both:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; tex &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;texture&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;renderer&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;Hello, SDL3&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;241&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;243&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;245&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;tex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For text that doesn’t change every frame, &lt;strong&gt;cache the texture&lt;/strong&gt; rather than rebuilding it
each frame — &lt;code&gt;texture&lt;/code&gt; allocates a surface, uploads it, and frees the surface on every
call.&lt;/p&gt;
&lt;h2 id=&quot;a-note-on-colour-passing&quot;&gt;A note on colour passing&lt;/h2&gt;
&lt;p&gt;SDL_ttf’s render functions take &lt;code&gt;SDL_Color&lt;/code&gt; by value in C. Scala Native mis-marshals a
small by-value struct argument, so the binding passes the colour as a packed little-endian
&lt;code&gt;uint32&lt;/code&gt; instead — ABI-identical to the 4-byte struct on the supported platforms. This is
internal; you just pass an &lt;code&gt;sdl3.Color&lt;/code&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Quick Start</title>
    <link href="https://sdl3.edadma.dev/getting-started/quick-start/"/>
    <id>https://sdl3.edadma.dev/getting-started/quick-start/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>A complete program: open a window, run an event loop, and draw an animated frame.</summary>
    <content type="html">&lt;p&gt;A complete program: open a window, run an event loop, and draw an animated frame.&lt;/p&gt;
&lt;h2 id=&quot;a-window-and-a-frame-loop&quot;&gt;A window and a frame loop&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;

@main &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; main&lt;span class=&quot;hl-punctuation&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt;
  setMainReady&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;!&lt;/span&gt;init&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;INIT_VIDEO&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;hl-type&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;err&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;println&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;SDL_Init failed: $error&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;return&lt;/span&gt;

  &lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; window &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; createWindow&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;sdl3 quick start&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;isNull &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;hl-type&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;err&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;println&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;createWindow failed: $error&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;return&lt;/span&gt;

  &lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; renderer &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createRenderer&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
  renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setVSync&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-variable&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-comment&quot;&gt;// throttle the loop to the display refresh&lt;/span&gt;

  &lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; running &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;while&lt;/span&gt; running &lt;span class=&quot;hl-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hl-comment&quot;&gt;// Drain the event queue each frame.&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; e &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; pollEvent&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;while&lt;/span&gt; e&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;isDefined &lt;span class=&quot;hl-keyword&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; ev &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;get
      &lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;hl-keyword&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;QUIT&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; running &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;false&lt;/span&gt;
      e &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; pollEvent&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;hl-comment&quot;&gt;// Clear, draw, present.&lt;/span&gt;
    renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
    renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setDrawColor&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;247&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;103&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
    renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;fillRect&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;270&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;190&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;fillCircle&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
    renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;present&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;

  renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
  window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
  quit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Build and run it with &lt;code&gt;sbt run&lt;/code&gt; (it blocks on the window). &lt;code&gt;sbt nativeLink&lt;/code&gt; just produces
the binary.&lt;/p&gt;
&lt;h2 id=&quot;reading-input&quot;&gt;Reading input&lt;/h2&gt;
&lt;p&gt;Poll discrete events from the queue, or read the live device state at any time:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-comment&quot;&gt;// Event-driven: react to a key press as it happens.&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; ev &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; pollEvent&lt;span class=&quot;hl-punctuation&quot;&gt;().&lt;/span&gt;get
&lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;hl-keyword&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;KEY_DOWN&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;keyScancode &lt;span class=&quot;hl-keyword&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Scancode&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Escape&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; running &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;hl-comment&quot;&gt;// State-driven: query held keys / the mouse each frame.&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; keys &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Keyboard&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;state
&lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; keys&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Scancode&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Space&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; jump&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; mouse &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Mouse&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;state
&lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; mouse&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;left &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; paint&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;mouse&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; mouse&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;y&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;adding-text&quot;&gt;Adding text&lt;/h2&gt;
&lt;p&gt;Bring in &lt;a href=&quot;/modules/ttf/&quot;&gt;&lt;code&gt;sdl3_ttf&lt;/code&gt;&lt;/a&gt; to draw a label. Initialise it alongside SDL, open a
font once, and blit rendered text as a texture:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3_ttf&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;

ttfInit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; font &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; openFont&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;/System/Library/Fonts/Helvetica.ttc&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;hl-comment&quot;&gt;// each frame, after clear:&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; tex &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;texture&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;renderer&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;Hello, SDL3&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;241&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;243&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;245&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;tex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;hl-comment&quot;&gt;// at shutdown:&lt;/span&gt;
font&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;close&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
ttfQuit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For real apps, cache the text texture instead of rebuilding it every frame. See the
&lt;a href=&quot;/modules/&quot;&gt;modules&lt;/a&gt; section for each library’s full surface.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>sdl3_mixer — audio</title>
    <link href="https://sdl3.edadma.dev/modules/mixer/"/>
    <id>https://sdl3.edadma.dev/modules/mixer/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>Audio playback, layered on the core binding. Pulls in sdl3 transitively and adds @link(&quot;SDL3_mixer&quot;); install the native library with brew install sdl3_mixer (or your platform’s package).</summary>
    <content type="html">&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3_mixer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Audio playback, layered on the core binding. Pulls in &lt;code&gt;sdl3&lt;/code&gt; transitively and adds
&lt;code&gt;@link(&amp;quot;SDL3_mixer&amp;quot;)&lt;/code&gt;; install the native library with &lt;code&gt;brew install sdl3_mixer&lt;/code&gt; (or your
platform’s package).&lt;/p&gt;
&lt;p&gt;SDL3_mixer’s model is a &lt;strong&gt;mixer device&lt;/strong&gt; that plays &lt;strong&gt;audio&lt;/strong&gt; clips, optionally through
named &lt;strong&gt;tracks&lt;/strong&gt; you can control individually (gain, pause, fades, looping).&lt;/p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;mixInit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; mixer &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; openMixer&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;        &lt;span class=&quot;hl-comment&quot;&gt;// default playback device&lt;/span&gt;
&lt;span class=&quot;hl-comment&quot;&gt;// …&lt;/span&gt;
mixer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
mixQuit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;fire-and-forget-playback&quot;&gt;Fire-and-forget playback&lt;/h2&gt;
&lt;p&gt;The simplest path — load a clip and play it once on the device:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; clip &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; mixer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;loadAudio&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;assets/blip.wav&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;hl-comment&quot;&gt;// predecode = true by default&lt;/span&gt;
mixer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;play&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;clip&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-comment&quot;&gt;// …&lt;/span&gt;
clip&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;loadAudio(path, predecode = false)&lt;/code&gt; streams from disk instead of decoding up front —
prefer it for long music tracks.&lt;/p&gt;
&lt;h2 id=&quot;tracks-control-a-sound-over-time&quot;&gt;Tracks: control a sound over time&lt;/h2&gt;
&lt;p&gt;For looping, fades, pausing, or per-sound gain, play through a &lt;code&gt;Track&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; track &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; mixer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createTrack&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setAudio&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;clip&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;

track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;play&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;                   &lt;span class=&quot;hl-comment&quot;&gt;// play once&lt;/span&gt;
track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;play&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;loops &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;          &lt;span class=&quot;hl-comment&quot;&gt;// play, then repeat twice more&lt;/span&gt;
track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;play&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;loops &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;LOOP_FOREVER&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;

track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setGain&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;             &lt;span class=&quot;hl-comment&quot;&gt;// 0.0 … 1.0&lt;/span&gt;
track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;pause&lt;span class=&quot;hl-punctuation&quot;&gt;();&lt;/span&gt; track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;resume&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;playing                  &lt;span class=&quot;hl-comment&quot;&gt;// Boolean&lt;/span&gt;

track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;stop&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;                   &lt;span class=&quot;hl-comment&quot;&gt;// stop now&lt;/span&gt;
track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;stop&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;fadeOutFrames &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-comment&quot;&gt;// fade out over N sample frames&lt;/span&gt;

track&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;LOOP_FOREVER&lt;/code&gt; is &lt;code&gt;-1&lt;/code&gt;. Most calls return &lt;code&gt;Boolean&lt;/code&gt; success. Destroy tracks and audio
clips when done, then the mixer, then &lt;code&gt;mixQuit()&lt;/code&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Installation</title>
    <link href="https://sdl3.edadma.dev/getting-started/installation/"/>
    <id>https://sdl3.edadma.dev/getting-started/installation/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>These are Scala Native bindings, so there are two halves: the native SDL3 libraries (C shared objects on your system) and the Scala artifacts (added to your build).</summary>
    <content type="html">&lt;p&gt;These are Scala Native bindings, so there are two halves: the &lt;strong&gt;native SDL3 libraries&lt;/strong&gt;
(C shared objects on your system) and the &lt;strong&gt;Scala artifacts&lt;/strong&gt; (added to your build).&lt;/p&gt;
&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Scala 3&lt;/li&gt;
&lt;li&gt;sbt with the &lt;code&gt;sbt-scala-native&lt;/code&gt; plugin&lt;/li&gt;
&lt;li&gt;LLVM/Clang (the Scala Native toolchain)&lt;/li&gt;
&lt;li&gt;The SDL3 shared libraries on your system&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;install-the-native-sdl3-libraries&quot;&gt;Install the native SDL3 libraries&lt;/h2&gt;
&lt;p&gt;The Scala layer links against the system SDL3 libraries via &lt;code&gt;@link&lt;/code&gt;, so they must be
installed and discoverable by the linker. On macOS with Homebrew:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hl-function&quot;&gt;brew&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;sdl3&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;sdl3_ttf&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;sdl3_image&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;sdl3_mixer&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On Linux, install the SDL3 development packages from your distribution (or build from
source). You only need the satellite libraries for the modules you use — &lt;code&gt;sdl3&lt;/code&gt; alone
needs just SDL3 itself.&lt;/p&gt;
&lt;h2 id=&quot;enable-scala-native&quot;&gt;Enable Scala Native&lt;/h2&gt;
&lt;p&gt;In &lt;code&gt;project/plugins.sbt&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;addSbtPlugin&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;org.scala-native&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;sbt-scala-native&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;0.5.12&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;add-the-dependencies&quot;&gt;Add the dependencies&lt;/h2&gt;
&lt;p&gt;Each module is published for Scala Native under &lt;code&gt;io.github.edadma&lt;/code&gt;. Enable the Scala
Native plugin on your module and add the artifacts you need:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; app &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; project
  &lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;in&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;app&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;enablePlugins&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;ScalaNativePlugin&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;settings&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;
    libraryDependencies &lt;span class=&quot;hl-keyword&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;io.github.edadma&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%%%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;sdl3&amp;quot;&lt;/span&gt;       &lt;span class=&quot;hl-keyword&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;0.2.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt;
    libraryDependencies &lt;span class=&quot;hl-keyword&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;io.github.edadma&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%%%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;sdl3_ttf&amp;quot;&lt;/span&gt;   &lt;span class=&quot;hl-keyword&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;0.2.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt;
    libraryDependencies &lt;span class=&quot;hl-keyword&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;io.github.edadma&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%%%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;sdl3_image&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;0.2.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt;
    libraryDependencies &lt;span class=&quot;hl-keyword&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;io.github.edadma&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%%%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;sdl3_mixer&amp;quot;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;0.2.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The satellites (&lt;code&gt;sdl3_ttf&lt;/code&gt;, &lt;code&gt;sdl3_image&lt;/code&gt;, &lt;code&gt;sdl3_mixer&lt;/code&gt;) depend on &lt;code&gt;sdl3&lt;/code&gt; transitively, so
you do not list the core separately when you use one of them. Each satellite also adds its
own &lt;code&gt;@link&lt;/code&gt; to the matching native library (&lt;code&gt;SDL3_ttf&lt;/code&gt;, etc.), pulling &lt;code&gt;SDL3&lt;/code&gt; in with it.&lt;/p&gt;
&lt;p&gt;No &lt;code&gt;linkingOptions&lt;/code&gt; are needed: Scala Native finds the Homebrew-installed libraries
through each binding’s &lt;code&gt;@link(&amp;quot;SDL3&amp;quot;)&lt;/code&gt; / &lt;code&gt;@link(&amp;quot;SDL3_ttf&amp;quot;)&lt;/code&gt; declaration.&lt;/p&gt;
&lt;h2 id=&quot;provide-a-main&quot;&gt;Provide a &lt;code&gt;main&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;SDL apps call &lt;code&gt;SDL_SetMainReady&lt;/code&gt; so SDL knows you own &lt;code&gt;main&lt;/code&gt;. The binding exposes it as
&lt;code&gt;setMainReady()&lt;/code&gt;; call it before &lt;code&gt;init&lt;/code&gt;. Continue to the
&lt;a href=&quot;/getting-started/quick-start/&quot;&gt;quick start&lt;/a&gt; for a full window-and-loop example.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>sdl3_image — images</title>
    <link href="https://sdl3.edadma.dev/modules/image/"/>
    <id>https://sdl3.edadma.dev/modules/image/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>Image loading and PNG saving, layered on the core binding. Pulls in sdl3 transitively and adds @link(&quot;SDL3_image&quot;); install the native library with brew install sdl3_image (or your platform’s package). SDL_image…</summary>
    <content type="html">&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3_image&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Image loading and PNG saving, layered on the core binding. Pulls in &lt;code&gt;sdl3&lt;/code&gt; transitively
and adds &lt;code&gt;@link(&amp;quot;SDL3_image&amp;quot;)&lt;/code&gt;; install the native library with &lt;code&gt;brew install sdl3_image&lt;/code&gt;
(or your platform’s package). SDL_image handles PNG, JPEG, and the other formats SDL3
supports.&lt;/p&gt;
&lt;h2 id=&quot;loading&quot;&gt;Loading&lt;/h2&gt;
&lt;p&gt;Load straight to a GPU texture (the common case — ready to draw), or to a CPU surface when
you need to inspect or transform pixels first:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-comment&quot;&gt;// To a texture, ready for renderer.copy:&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; tex &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; loadTexture&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;renderer&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;assets/sprite.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;size
renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;tex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;hl-comment&quot;&gt;// To a surface (CPU pixels):&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; surface &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; load&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;assets/sprite.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
surface&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt; surface&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;height
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; gpu &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; renderer&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createTextureFromSurface&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;surface&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
surface&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;free&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both return the core &lt;code&gt;Texture&lt;/code&gt; / &lt;code&gt;Surface&lt;/code&gt; handles, so everything in
&lt;a href=&quot;/modules/core/&quot;&gt;sdl3&lt;/a&gt; applies. Check &lt;code&gt;isNull&lt;/code&gt; after loading to detect failure (a missing
or unreadable file).&lt;/p&gt;
&lt;h2 id=&quot;saving&quot;&gt;Saving&lt;/h2&gt;
&lt;p&gt;Write a surface out as a PNG:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; ok&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; savePNG&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;surface&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;out.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <title>sdl3 — core</title>
    <link href="https://sdl3.edadma.dev/modules/core/"/>
    <id>https://sdl3.edadma.dev/modules/core/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>The core artifact: lifecycle, a window, the 2D renderer, textures and surfaces, filled geometry, events, and live input state. Everything here lives in the io.github.edadma.sdl3 package object.</summary>
    <content type="html">&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;github&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;edadma&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sdl3&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The core artifact: lifecycle, a window, the 2D renderer, textures and surfaces, filled
geometry, events, and live input state. Everything here lives in the
&lt;code&gt;io.github.edadma.sdl3&lt;/code&gt; package object.&lt;/p&gt;
&lt;h2 id=&quot;lifecycle&quot;&gt;Lifecycle&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;setMainReady&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;                  &lt;span class=&quot;hl-comment&quot;&gt;// tell SDL you provide main (call before init)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; ok&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; init&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;INIT_VIDEO&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; msg&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; error         &lt;span class=&quot;hl-comment&quot;&gt;// last SDL error message&lt;/span&gt;
delay&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                       &lt;span class=&quot;hl-comment&quot;&gt;// sleep, milliseconds&lt;/span&gt;
setHint&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;HINT_RENDER_VSYNC&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
quit&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;init&lt;/code&gt; takes a bitmask of subsystem flags: &lt;code&gt;INIT_TIMER&lt;/code&gt;, &lt;code&gt;INIT_AUDIO&lt;/code&gt;, &lt;code&gt;INIT_VIDEO&lt;/code&gt;,
&lt;code&gt;INIT_EVENTS&lt;/code&gt; (default &lt;code&gt;INIT_VIDEO&lt;/code&gt;). It returns &lt;code&gt;true&lt;/code&gt; on success; on failure read
&lt;code&gt;error&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;window&quot;&gt;Window&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; window &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; createWindow&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;          &lt;span class=&quot;hl-comment&quot;&gt;// flags default to 0&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; window &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; createWindow&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;WINDOW_RESIZABLE&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Window flags: &lt;code&gt;WINDOW_FULLSCREEN&lt;/code&gt;, &lt;code&gt;WINDOW_OPENGL&lt;/code&gt;, &lt;code&gt;WINDOW_HIDDEN&lt;/code&gt;, &lt;code&gt;WINDOW_BORDERLESS&lt;/code&gt;,
&lt;code&gt;WINDOW_RESIZABLE&lt;/code&gt;, &lt;code&gt;WINDOW_HIGH_PIXEL_DENSITY&lt;/code&gt;. A &lt;code&gt;Window&lt;/code&gt; is an &lt;code&gt;AnyVal&lt;/code&gt; over the SDL
handle:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;isNull                       &lt;span class=&quot;hl-comment&quot;&gt;// creation failed?&lt;/span&gt;
window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createRenderer&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;             &lt;span class=&quot;hl-comment&quot;&gt;// or createRenderer(&amp;quot;metal&amp;quot;) to pick a driver&lt;/span&gt;
window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setPosition&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;hl-comment&quot;&gt;// SDL3 has no creation-time position&lt;/span&gt;
window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;pixelFormat                  &lt;span class=&quot;hl-comment&quot;&gt;// Int&lt;/span&gt;
window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;size            &lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-comment&quot;&gt;// logical size, in points&lt;/span&gt;
window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;sizeInPixels    &lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-comment&quot;&gt;// backbuffer size, in pixels (≠ size on HiDPI)&lt;/span&gt;
window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A window is &lt;strong&gt;not&lt;/strong&gt; high-DPI unless created with &lt;code&gt;WINDOW_HIGH_PIXEL_DENSITY&lt;/code&gt;; otherwise
&lt;code&gt;sizeInPixels == size&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;renderer&quot;&gt;Renderer&lt;/h2&gt;
&lt;p&gt;The renderer is the 2D drawing context. Coordinates are &lt;code&gt;Double&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; r &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createRenderer&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setVSync&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-variable&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                    &lt;span class=&quot;hl-comment&quot;&gt;// sync present to the display refresh&lt;/span&gt;

r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setDrawColor&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;247&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;103&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;hl-comment&quot;&gt;// or setDrawColor(r, g, b, a)&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setBlendMode&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;BLENDMODE_BLEND&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;hl-comment&quot;&gt;// NONE / BLEND / ADD / MOD / MUL&lt;/span&gt;

r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;                           &lt;span class=&quot;hl-comment&quot;&gt;// clear to the current draw colour&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;          &lt;span class=&quot;hl-comment&quot;&gt;// set colour and clear&lt;/span&gt;

r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;drawPoint&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;drawLine&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x1&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y1&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; x2&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y2&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;drawRect&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;              &lt;span class=&quot;hl-comment&quot;&gt;// outline&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;fillRect&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;              &lt;span class=&quot;hl-comment&quot;&gt;// filled&lt;/span&gt;

r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;present&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;                         &lt;span class=&quot;hl-comment&quot;&gt;// show the frame&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;filled-geometry&quot;&gt;Filled geometry&lt;/h3&gt;
&lt;p&gt;Shapes SDL has no primitive for are drawn as triangle meshes via &lt;code&gt;SDL_RenderGeometry&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;fillCircle&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;cx&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; cy&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; radius&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;White&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;thickLine&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x1&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y1&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; x2&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y2&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; width &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;247&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;103&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;fillConvexPolygon&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;x0&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y0&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; x1&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y1&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; x2&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y2&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-comment&quot;&gt;/* … */&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;White&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;fillConvexPolygon&lt;/code&gt; takes a flat &lt;code&gt;Array[Double]&lt;/code&gt; of &lt;code&gt;x, y&lt;/code&gt; pairs (a triangle fan from the
first vertex). The mesh builders are pure and unit-tested.&lt;/p&gt;
&lt;h3 id=&quot;render-targets&quot;&gt;Render targets&lt;/h3&gt;
&lt;p&gt;Draw into an off-screen texture, then blit it to the window — useful for supersampling or
flicker-free compositing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; target &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createTexture&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;pixelFormat&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;TEXTUREACCESS_TARGET&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setTarget&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-comment&quot;&gt;// … draw …&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;resetTarget&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                      &lt;span class=&quot;hl-comment&quot;&gt;// blit the whole texture across the window&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;present&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Texture access modes: &lt;code&gt;TEXTUREACCESS_STATIC&lt;/code&gt;, &lt;code&gt;TEXTUREACCESS_STREAMING&lt;/code&gt;,
&lt;code&gt;TEXTUREACCESS_TARGET&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;textures-and-surfaces&quot;&gt;Textures and surfaces&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;surface&lt;/strong&gt; is CPU pixels; a &lt;strong&gt;texture&lt;/strong&gt; is GPU pixels. Upload a surface (from
&lt;a href=&quot;/modules/ttf/&quot;&gt;sdl3_ttf&lt;/a&gt; or &lt;a href=&quot;/modules/image/&quot;&gt;sdl3_image&lt;/a&gt;) to a texture, then draw it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; tex &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;createTextureFromSurface&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;surface&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;setScaleMode&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;SCALEMODE_LINEAR&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;hl-comment&quot;&gt;// NEAREST / LINEAR / PIXELART&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;size

r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;tex&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                         &lt;span class=&quot;hl-comment&quot;&gt;// fill the whole target&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;tex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;                   &lt;span class=&quot;hl-comment&quot;&gt;// at (x, y), the texture&apos;s own size&lt;/span&gt;
r&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;copy&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;tex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; w&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; h&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;hl-comment&quot;&gt;// into a destination rect&lt;/span&gt;

tex&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;destroy&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;

surface&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt; surface&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;height
surface&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;free&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;events&quot;&gt;Events&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;pollEvent()&lt;/code&gt; returns &lt;code&gt;Option[Event]&lt;/code&gt;; drain it each frame. An &lt;code&gt;Event&lt;/code&gt; is a view over a
reusable union buffer, so read &lt;code&gt;kind&lt;/code&gt; first, then only the fields valid for that kind:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; e &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; pollEvent&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;while&lt;/span&gt; e&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;isDefined &lt;span class=&quot;hl-keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; ev &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;get
  ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;hl-keyword&quot;&gt;match&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;QUIT&lt;/span&gt;              &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; running &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;KEY_DOWN&lt;/span&gt;          &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; onKey&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;keyScancode&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;keyRepeat&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;MOUSE_BUTTON_DOWN&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; onClick&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;mouseX&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;mouseY&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;mouseButton&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;MOUSE_MOTION&lt;/span&gt;      &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; onMove&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;mouseX&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;mouseY&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;MOUSE_WHEEL&lt;/span&gt;       &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; onScroll&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;wheelX&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;wheelY&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; _                 &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
  e &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; pollEvent&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Event kinds: &lt;code&gt;QUIT&lt;/code&gt;, &lt;code&gt;KEY_DOWN&lt;/code&gt;, &lt;code&gt;KEY_UP&lt;/code&gt;, &lt;code&gt;MOUSE_MOTION&lt;/code&gt;, &lt;code&gt;MOUSE_BUTTON_DOWN&lt;/code&gt;,
&lt;code&gt;MOUSE_BUTTON_UP&lt;/code&gt;, &lt;code&gt;MOUSE_WHEEL&lt;/code&gt;. Field accessors: &lt;code&gt;keyScancode&lt;/code&gt;, &lt;code&gt;keyRepeat&lt;/code&gt;, &lt;code&gt;mouseX&lt;/code&gt;,
&lt;code&gt;mouseY&lt;/code&gt;, &lt;code&gt;mouseButton&lt;/code&gt; (1 = left, 2 = middle, 3 = right), &lt;code&gt;wheelX&lt;/code&gt;, &lt;code&gt;wheelY&lt;/code&gt; (positive y
= away from the user).&lt;/p&gt;
&lt;h3 id=&quot;event-watches&quot;&gt;Event watches&lt;/h3&gt;
&lt;p&gt;Register a callback fired for every event as it is pumped (handy for resize/expose
without restructuring the loop):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; id &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; addEventWatch &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; ev &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; ev&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;kind &lt;span class=&quot;hl-keyword&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;QUIT&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; save&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
removeEventWatch&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;live-input-state&quot;&gt;Live input state&lt;/h2&gt;
&lt;p&gt;Instead of (or alongside) events, read the current device state directly:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; keys &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Keyboard&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;state
&lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; keys&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Scancode&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Space&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; jump&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; keys&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Scancode&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Escape&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; running &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; m &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Mouse&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;state          &lt;span class=&quot;hl-comment&quot;&gt;// MouseState(buttons, x, y)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;if&lt;/span&gt; m&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;left &lt;span class=&quot;hl-keyword&quot;&gt;then&lt;/span&gt; paint&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; m&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;y&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
m&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;middle&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt; m&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;right&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Scancode&lt;/code&gt; names the physical keys: letters &lt;code&gt;A&lt;/code&gt;–&lt;code&gt;Z&lt;/code&gt;, digits &lt;code&gt;Num0&lt;/code&gt;–&lt;code&gt;Num9&lt;/code&gt;, &lt;code&gt;Return&lt;/code&gt;,
&lt;code&gt;Escape&lt;/code&gt;, &lt;code&gt;Backspace&lt;/code&gt;, &lt;code&gt;Tab&lt;/code&gt;, &lt;code&gt;Space&lt;/code&gt;, &lt;code&gt;Minus&lt;/code&gt;, &lt;code&gt;Equals&lt;/code&gt;, &lt;code&gt;LeftBracket&lt;/code&gt;, &lt;code&gt;RightBracket&lt;/code&gt;,
and the arrows &lt;code&gt;Left&lt;/code&gt;, &lt;code&gt;Right&lt;/code&gt;, &lt;code&gt;Up&lt;/code&gt;, &lt;code&gt;Down&lt;/code&gt;. These are the standard USB-HID scancodes
SDL reports.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Design</title>
    <link href="https://sdl3.edadma.dev/guide/architecture/"/>
    <id>https://sdl3.edadma.dev/guide/architecture/</id>
    <updated>2026-06-07T00:00:41.559004835Z</updated>
    <summary>The binding is deliberately two-layered, and follows a few consistent conventions. You rarely need to know this to use it, but it explains why the API looks the way it…</summary>
    <content type="html">&lt;p&gt;The binding is deliberately two-layered, and follows a few consistent conventions. You
rarely need to know this to &lt;em&gt;use&lt;/em&gt; it, but it explains why the API looks the way it does
and is essential if you extend it.&lt;/p&gt;
&lt;h2 id=&quot;two-layers&quot;&gt;Two layers&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The &lt;code&gt;@extern&lt;/code&gt; layer&lt;/strong&gt; is the raw FFI: one object per native library
(&lt;code&gt;extern.LibSDL3&lt;/code&gt;, &lt;code&gt;extern.LibSDL3Ttf&lt;/code&gt;, …) that declares the C functions with Scala
Native FFI types and &lt;code&gt;@link&lt;/code&gt;s the shared library. This is the only place &lt;code&gt;Ptr&lt;/code&gt;,
&lt;code&gt;CStruct&lt;/code&gt;, &lt;code&gt;CString&lt;/code&gt;, and &lt;code&gt;UInt&lt;/code&gt; appear. You never import it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The pure-Scala layer&lt;/strong&gt; is the package object you do import (&lt;code&gt;io.github.edadma.sdl3&lt;/code&gt;,
&lt;code&gt;io.github.edadma.sdl3_ttf&lt;/code&gt;, …). It speaks in &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;Double&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, a
&lt;code&gt;Color&lt;/code&gt; case class, and wrapped handles, and it does the marshalling — allocating C
strings in a &lt;code&gt;Zone&lt;/code&gt;, converting numbers, packing structs — so callers never touch FFI
types.&lt;/p&gt;
&lt;p&gt;This split keeps the unsafe surface small and auditable, and lets the ergonomic layer
evolve without changing the ABI declarations.&lt;/p&gt;
&lt;h2 id=&quot;handle-wrappers-are-zero-cost&quot;&gt;Handle wrappers are zero-cost&lt;/h2&gt;
&lt;p&gt;SDL hands back opaque pointers — &lt;code&gt;SDL_Window *&lt;/code&gt;, &lt;code&gt;SDL_Renderer *&lt;/code&gt;, &lt;code&gt;SDL_Texture *&lt;/code&gt;,
&lt;code&gt;SDL_Surface *&lt;/code&gt;. Each is wrapped in an &lt;code&gt;AnyVal&lt;/code&gt; value class:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Renderer&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;val&lt;/span&gt; ptr&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; sdl&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;SDL_Renderer&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;AnyVal&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; clear&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; present&lt;span class=&quot;hl-punctuation&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Unit&lt;/span&gt;       &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because they extend &lt;code&gt;AnyVal&lt;/code&gt;, the wrapper is erased at runtime — a &lt;code&gt;Renderer&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; the
pointer, with methods. You get &lt;code&gt;renderer.present()&lt;/code&gt; instead of &lt;code&gt;SDL_RenderPresent(ptr)&lt;/code&gt;
at no allocation cost. Each wrapper carries an &lt;code&gt;isNull&lt;/code&gt; check for the common “did this
fail?” test.&lt;/p&gt;
&lt;h2 id=&quot;colours&quot;&gt;Colours&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Color(r, g, b, a)&lt;/code&gt; is a plain case class with channels &lt;code&gt;0–255&lt;/code&gt; (&lt;code&gt;a&lt;/code&gt; defaults to 255).
&lt;code&gt;Color.fromRGB(0xRRGGBB)&lt;/code&gt; unpacks a packed literal, and &lt;code&gt;Color.blend(a, b, t)&lt;/code&gt; does a
clamped linear interpolation. The renderer and text APIs take &lt;code&gt;Color&lt;/code&gt; directly.&lt;/p&gt;
&lt;h2 id=&quot;conventions-worth-knowing&quot;&gt;Conventions worth knowing&lt;/h2&gt;
&lt;p&gt;These are the rules the binding holds to internally. They matter if you read the source
or add functions.&lt;/p&gt;
&lt;h3 id=&quot;structs-are-passed-by-pointer&quot;&gt;Structs are passed by pointer&lt;/h3&gt;
&lt;p&gt;SDL functions that take a struct (&lt;code&gt;SDL_FRect&lt;/code&gt;, &lt;code&gt;SDL_Vertex&lt;/code&gt;, …) are called with a
&lt;strong&gt;pointer&lt;/strong&gt; to a buffer the wrapper fills, never a by-value Scala &lt;code&gt;CStruct&lt;/code&gt;. Scala
Native’s marshalling of small by-value struct &lt;em&gt;arguments&lt;/em&gt; is unreliable, so the binding
avoids it entirely. Where a C API insists on a by-value struct, the wrapper passes it in
an ABI-equivalent form instead — for example &lt;code&gt;SDL_Color&lt;/code&gt; (four bytes) is passed to the
SDL_ttf render functions as a packed little-endian &lt;code&gt;uint32&lt;/code&gt;, which lands in the same
register as the 4-byte struct on the SysV-AMD64 and AArch64 ABIs.&lt;/p&gt;
&lt;h3 id=&quot;scratch-buffers-outlive-the-call-not-the-helper&quot;&gt;Scratch buffers outlive the call, not the helper&lt;/h3&gt;
&lt;p&gt;A C call that needs a temporary struct (a rect for &lt;code&gt;SDL_RenderFillRect&lt;/code&gt;, an event union
for &lt;code&gt;SDL_PollEvent&lt;/code&gt;) reads it from a &lt;strong&gt;persistent heap buffer&lt;/strong&gt; owned by the package
object, refilled per call. It is never &lt;code&gt;stackalloc&lt;/code&gt;‘d in a helper that returns the
pointer: stack memory belongs to the frame that allocates it, so such a pointer would
dangle the instant the helper returns and SDL would read garbage. Reuse is safe because
SDL reads the buffer synchronously within the call and rendering is single-threaded.&lt;/p&gt;
&lt;h3 id=&quot;events-are-a-view-over-a-union&quot;&gt;Events are a view over a union&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;pollEvent()&lt;/code&gt; fills one reusable &lt;code&gt;SDL_Event&lt;/code&gt; buffer and returns an &lt;code&gt;Event&lt;/code&gt; view. The
field accessors (&lt;code&gt;kind&lt;/code&gt;, &lt;code&gt;keyScancode&lt;/code&gt;, &lt;code&gt;mouseX&lt;/code&gt;, &lt;code&gt;wheelY&lt;/code&gt;, …) are only meaningful for
the matching &lt;code&gt;kind&lt;/code&gt;, because the underlying struct is a union. Read &lt;code&gt;kind&lt;/code&gt; first, then
the fields for that event type.&lt;/p&gt;
&lt;h3 id=&quot;geometry-is-floating-point&quot;&gt;Geometry is floating-point&lt;/h3&gt;
&lt;p&gt;SDL3’s render API takes &lt;code&gt;float&lt;/code&gt; coordinates — the SDL2-era 16-bit clamping is gone. The
binding exposes &lt;code&gt;Double&lt;/code&gt; throughout and narrows to &lt;code&gt;float&lt;/code&gt; at the FFI boundary. Filled
shapes SDL has no primitive for (circles, thick lines) are built as triangle meshes and
drawn through &lt;code&gt;SDL_RenderGeometry&lt;/code&gt;; the mesh builders are unit-tested headlessly.&lt;/p&gt;</content>
  </entry>
</feed>
