Starling 2.8

Daniel Sperl on January 1, 2026

Be honest: you wouldn’t have expected to see a new Starling version appear, seemingly out of the blue, right? It’s been more than 4 years since I wrote the last blog entry for Starling 2.7. And, truth be told – personally, I haven’t found a lot of time to move our little red bird forward in those years.

However, that doesn’t mean Starling stood still.

The Starling community is still alive – and in the course of the previous years, the master branch has seen numerous really great pull requests adding new features, bug fixes and other enhancements. Thanks so much for all your contributions – I’m humbled that so many developers are still working with Starling, against all industry trends and all the competition out there!

In addition, I’m happy to report that I finally did find at least some time in 2025 to do some Starling development myself. I really enjoyed that – it felt a little bit like coming home!

In summary: it was high time to bundle all these changes together into a new release! I wouldn’t want any developers to use the outdated “2.7” version, after all, just because they didn’t dare to use the master branch directly.

Furthermore, releasing a new version for me is like sending a message: this framework is still actively supported! As you all know, Harman is doing a fantastic job of keeping AIR in great shape – and so I believe it is my duty to make sure Starling keeps working fine with all their latest releases.

A note on the Starling Handbook

Before we dive into the technical changes, there’s one more piece of good news I’d like to share. Just two days ago, I decided to make the Starling Handbook free for everyone.

The handbook has always been meant as a practical companion to Starling — and at this point, it felt right to remove the last barrier and make it accessible to anyone interested in the framework, whether they are new to Starling or returning after a longer break.

You can find all the details (and some background on that decision) in this forum announcement.

New vector drawing APIs for ‘Canvas’

The Canvas class has always been a handy little helper when you needed a quick mask or a few primitive shapes. Thanks to a great contribution by Fancy2209, it can now do something much closer to classic Flash-style Graphics drawing!

You can build paths with moveTo and lineTo, and even quadratic curves via curveTo. When the path closes (either by returning to the first point or simply calling endFill), Canvas triangulates the shape and renders it as a mesh — fully batched and GPU-friendly, just like the rest of Starling.

var canvas:Canvas = new Canvas();
canvas.beginFill(0xff9933);
canvas.moveTo(60, 0);
canvas.curveTo(120, 0, 120, 60);
canvas.lineTo(0, 60);
canvas.endFill();
addChild(canvas);

Even better, Canvas can now consume Graphics data directly via drawGraphicsData:

var shape:Shape = new Shape();
shape.graphics.beginFill(0x00ccff);
shape.graphics.drawCircle(0, 0, 50);
shape.graphics.endFill();

var data:Vector.<IGraphicsData> =
  shape.graphics.readGraphicsData();

var canvas:Canvas = new Canvas();
canvas.drawGraphicsData(data);
addChild(canvas);

At the moment, Canvas supports GraphicsSolidFill / GraphicsEndFill and the path commands MOVE_TO, LINE_TO, and CURVE_TO – which already covers a surprising number of vector assets. Line styles are not implemented yet, so think in terms of fills, not strokes.

Under the hood, this path support is powered by a much improved triangulation algorithm. Polygon.triangulate now defaults to the Earcut implementation (ported from Mapbox), which is both faster and produces better triangles for complex shapes. If you ever run into a regression or unexpected triangulation issue, you can revert to the old algorithm via Polygon.useEarcut = false. Thanks also to johnridges for spotting and fixing an offset issue in the new Earcut path.

And while we’re in Canvas land: Josh Tynjala added a tiny but very handy helper, Canvas.drawRoundRectangle(), so you don’t have to build rounded corners by hand.

MultiTextureStyle

Probably every Starling developer knows: keeping draw calls down is a must for great performance. And every time the texture changes on rendering (switching from one texture atlas to another), a new draw call occurs.

Well, of course that’s not a law of nature, but a side-effect of how the standard MeshStyle is implemented. So, back in 2016 (yep, you read right), I created an alternative MultiTextureStyle that supports up to four different textures. In other words: if you use this MultiTextureStyle in a scene that uses four or less texture atlases, all can be batched together in one draw call. (I say “can” because, as you surely know, texture switches are not the only reason for introducing additional draw calls.)

All that you have to do is make MultiTextureStyle the default for all your meshes:

Mesh.defaultStyle = MultiTextureStyle;

That’s it! (Ideally, you’d do this before starting Starling.)

Beware that this means that your fragment shaders will become much more complex than with the standard MeshStyle, so this is no silver bullet: you simply exchange load on the CPU with load on the GPU. But since many Starling apps are CPU bound, that’s often just what you need.

But you might ask: if this has been around since 2016, how come I haven’t heard of this before?

Well, my original version contained a bug that prevented it from rendering correctly in some circumstances; I didn’t find the reason for the error back then and, frankly, never revisited the topic. However, it turned out that johnridges got behind the issue – and shared the fix with us.

Since this style is so useful – and actually works reliably, now – this class is now part of the official Starling release.

Replacing FlexUnit

Starling doesn’t use or require Flex – however, the standard unit test library for AS3 projects was always FlexUnit, so Starling relied on the corresponding libraries for its unit tests. And it was always a pain to set up for developers not familiar with Flex (such as (cough) myself).

This always bugged me. The Unit tests of Starling are far from all-encompassing, but still: it should be easy for developers to run them or write their own tests.

And we don’t even need that much functionality from a unit test framework; just an easy way to make assertions and list any problems that are found along the way to the console or the app window.

So I finally took the time and removed the FlexUnit dependency, replacing it with a few home-brewed unit test classes that work just fine for our purposes.

The result is that it’s now really easy to run the tests. Simply compile the test-project just like any other AIR project, e.g. as a Desktop AIR app. The unit tests will start immediately when that app is launched.

Other changes

Here’s a quick recap of notable other changes. Of course, the complete change log can be found at the usual place.

  • Set Starling.defaultTextureSmoothing to configure default texture smoothing globally (thanks to Adolio!)
  • Mipmap generation of ConcretePotTexture is enhanced (thanks to zach-xhx!)
  • Mask handling was optimized and some mask-related bugs fixed (thanks to MatseFR!)
  • The performance of removeChild was optimized (thanks to HaimZik!)
  • Several state exceptions inside Canvas were fixed (thanks to Josh!)
  • Added a few new tween hooks: onRepeatStart, onRepeatFinish, and repeatReverseDelay (thanks to Mintonist!)
  • A really annoying (because: rather rare) RangeError within BatchProcessor was finally fixed (thanks to Ross Przybylski for pointing me to the right direction!)
  • … and more additions, fixes and optimizations.

You see: most of the additions are contributions from the Starling community. Really — without you, there would simply be no new release. I can’t thank you enough for continuing to dig into the Starling source code.

All the best for 2026, my friends!