Monospace Conference: Boston, July 2011

by Miguel de Icaza

The Mono community is organizing the Monospace conference to be held in July in Boston. This event is being organized by Dale Ragan, Louis Salin and Paul Bowden.

The organizers have just made a call for speakers.

If you have an interesting technology that you would like to talk about during this 3-day event, you should submit a talk.

Monospace is on a very aggressive schedule. The good news is that the entire Mono team will be participating in the event.

Once the dates are set in stone, we will open registration. Currently we are thinking of hosting an event for some 200 attendees.

Posted on 29 Mar 2011


Save your Cleverness

by Miguel de Icaza

Today, while discussing how @hipsterhacker reminds us some of our friends, Nat pointed me to this interview where Maciej has this beautiful nugget of wisdom:

Q: The Pinboard about page says: "There is absolutely nothing interesting about the Pinboard architecture or implementation; I consider that a feature!"

Can you explain why you think that's a feature?

I believe that relying on very basic and well-understood technologies at the architectural level forces you to save all your cleverness and new ideas for the actual app, where it can make a difference to users.

I think many developers (myself included) are easily seduced by new technology and are willing to burn a lot of time rigging it together just for the joy of tinkering. So nowadays we see a lot of fairly uninteresting web apps with very technically sweet implementations.

Too many people over-engineer their software to the point that you can no longer see what the software was supposed to do. Once people find a religion in one of the modern development fads, they tend to jump with both feet, and we end up with uninspiring user-facing software, but internally amazing.

This disease is widespread. From everyone trying to turn their program into a platform (current fad: dependency injection), to trying to force programming models, to compulsively writing unit tests while ignoring the basic principles that unit tests can not be used to prove the absence of bugs (update: this is my favorite book on the subject; Namedrop alert: Bertrand Meyer introduced me to it).

There is only one reason to throw away your life writing useless code and that is to train yourself. If you are writing this in a Karate Kid wax-on, wax-off kind of way, go ahead.

But if you are building a product, you end up spending all of your time designing your architecture, and very little time in delivering a great experience.

Premature architecture design is like premature optimization: you will be wrong about the things that actually mattered.

Take the shortcut. Build the product. And if later, it turns out you made a design mistake, refactor the code. But at least you will have a product that your users love.

Posted on 29 Mar 2011


Hardware Accelerated Video Playback in Moonlight

by Miguel de Icaza

David Reveman has just completed a series of optimizations in the Moonlight engine that allows Moonlight to take advantage of your GPU for the data intensive video rendering operations. This is in addition to the standard GPU hardware acceleration that we debuted a few weeks ago.

This is what the video rendering loop looks like in Moonlight:

Every one of those steps is an expensive process as it has to crunch to a lot of data. For example, a 720p video which has a frame size of 1280x720, this turns out to be 921,600 pixels. This frame while stored in RGB format at 8 bits per channel takes 2,764,800 bytes of memory. If you are decoding video at 30 frames per second, you need to at least move from the encoded input to the video 82 megabytes per second. Things are worse because the data is transformed on every step in that pipeline. This is what each step does:

The video decoding is the step that decompresses your video frames. This is done one frame at a time, the input might be small, but the output will be the size of the original video.

The decoding process generates images in YUV format. This format is used to store images and videos but and with previous versions of Moonlight, we had to convert this YUV data into an in-memory bitmap encoded in RGB format.

The final step is to transfer this image to the graphics card. This typically involves copying the data from the system memory to the graphics card, and in Unix this goes through the user process to the X server process, which eventually moves the data to the graphics card.

New Hardware Accelerated Framework

The new hardware acceleration framework now skips plenty of these steps and lets the GPU on the system take over, this is what the new pipeline looks like:

The uncompressed image in YUV format is sent directly to the GPU. Since OpenGL does not really know about YUV images, we use a custom pixel shader that runs on the graphics card to do the conversion for us and we also let the GPU take care of scaling the image.

The resulting buffer is composited with the rest of the scene, using the new rendering framework introduced in Moonlight 4.

Although native video playback solutions have been doing similar things for a while on Linux, we had to integrate this into the larger retained graphics system that is Moonlight. We might be late to the party, but it is now a hardware accelerated and smooth party.

And what does this looks like? It looks like heaven.

We were watching 1080p videos, running at full screen in David's office and it is absolutely perfect.

Getting the Code

The code is available now on Github and will be available in a few hours as a pre-packaged binary from our nightly builds.

Posted on 23 Mar 2011


Kid's Games on the iPad

by Miguel de Icaza

My eight month old daugther loves her iPad.

We have gotten a bunch of baby games, kids games and visualizations for her.

But many of these apps have one fundamental issue: the author adds one or more buttons with useless stuff like "Provide Feedback", "Info", "Visit Web Site", "Check my Other Apps" and other assorted buttons on the screen:

Now, perhaps the apps did great when used by a professional QA team in Daytona that reported back "yes, every animal in the app makes the proper sound, and the cows scroll as they are intended to".

In this case, the "Main" button, will bring up a convenient page with options to send feedback to the author, to visit his web site and check out his other apps.

This means that my daugther can not really enjoy her games without supervision, since every few seconds, she will end up visiting a web site in Safari.

Joseph has a similar problem, he has equipped both of his kids with iPads, and they routinely report "the iPad broke", every time one of their games ends up in some lame web site for the developer.

Developers for kid games should use slider switches if they really want to impose their hooks into their customers.

Some Games

On twitter Paul Hudson suggested a couple of games for 1-year olds: Uzu (my daughter also loves this one), BeBot and SoundTouch.

I have found that she likes GarageBand a lot (we just have to be around to make sure we can reset the screen when she changes instruments).

Posted on 23 Mar 2011


GDC 2011

by Miguel de Icaza

Three years ago, we were almost laughed out of the Game Developer Conference Show floor.

C# as the heir to C++ back then was mostly an academic discussion. And there were only a few anecdotal examples of developers using C# for fast and safe scripting in games such as Second Life and Unity.

Three years ago, C# as a scripting language for games had shared the reputation that Javascript had before the Ajax and Web 2.0 revolutions. It was a bad word. Anything short of C++ and assembly language was not up to the taste of most game developers. Ironically, developers were willing to take the hit of an interpreted languages to drive their games.

It was perhaps Unity Technologies that started to change this when they adopted Mono as their scripting engine, giving their developers a choice of C#, strongly typed Javascript and Boo as programming languages to author their game's logic, effects and behaviors. They got the benefits of high-level languages, with the added performance of being compiled:

A New Generation of Game Developers

In the past years, a new generation of game developers have entered the stage. These are developers that have cut their teeth with Unity, XNA and frameworks like PyGame.

They value malleability, rapid iteration and safe environments without crashing over raw performance. They have grown used to profiling their software and tuning the hot-spots instead of depending on hunches that lead to premature optimizing.

This year things were very different at our booth. Lots of happy Unity users came by to talk about MonoDevelop, about the new soft debugger, and about the joy of using C# to build applications with Unity. Lots of people are working on big and small game titles using Mono.

MonoTouch and MonoDroid also helped us gain visibility in this space. Lots of existing users, and users-to-be came to discuss Mono's state.

But Mono has now spread its wings from being a pure extension system for C++-based systems (like Unity or the Sims3), to be used as the main language for building game engines and game frameworks.

There is the 2D MonoGame (an open source effort previously known as XNAtouch) which supports iPhone, Android (and they are working on Windows and Mac backends).

At the show, both DeltaEngine and Silicon Studio were showing pure C#-based 3D game engines powered by Mono. There were as well a number of stealth-mode projects and startups using Mono either as their scripting engine or the main runtime.

Walking around the GDC show-floor, you could see Mono running in many booths thanks to Unity's overwhelming popularity.

Perhaps my favorite Unity game at the show was Rochard, an upcoming PS3 game with interesting puzzles and the level of polish that you expect from a game like Ratchet and Clank (videos, screenshots).

Helping Game Developers

In the past couple of years we have made some changes to Mono that help developers use Mono as either a scripting system for an existing C or C++ code base, or for those using Mono as their main runtime.

We still deliver all the bonus features that come from using C# and the CLI, like lambda functions, functional style-programming, garbage collection, type safety, iterators, generics and improve upon the basics to include:

  • Mobile profile: a minimal profile of class libraries that is better suited for mobile, embedded and console uses.
  • LLVM-based code optimizer: in addition to our standard code generator designed for JIT compilation, we now offer developers a choice to use the LLVM optimizing compiler to generate code. Modulo a handful of issues, the code generated is as good as the one you would get by doing low-level programming with C++.
  • SIMD intrinsics: we treat the various Vector data types in the Mono.Simd namespace as first-class types recognized by the JIT and mapped directly to hardware supported SIMD operations:
    		// This code:
    		using Mono.Simd;
    		
    		Vector4f Add (Vector4f one, Vector4f two)
    		{
    			return one + two;
    		}
    
    		// Is inlined by our LLVM code generator when invoked
    		// with the two statics first and second:
    		mov    first,%eax
    		movups (%eax),%xmm0
    		mov    second,%eax
    		movups (%eax),%xmm1
    		addps  %xmm1,%xmm0
    		
  • Unsafe execution: some of our users wanted to continue using Mono and C# for their code for compute intensive operations. We now offer an unsafe option that will remove all arrays bounds check from the code. This, needless to say, is incredibly unsafe as it would open the doors to the sort of bugs that are common in C++. But if you are dying to squeeze the last bit of performance and treat C# as a nicer C++ and are ready to make a commitment to debug memory-corruption bugs, we got you covered.
  • Runtime Continuations: to create lightweight co-routines that are not bound to threads and allow developers to suspend execution at any point without having to change their code, or require new compilers. Silicon Studio's Homei system uses it.

Additionally, many developers are doing a little bit of embrace-and-extending the Mono runtime in creative ways to extend the CLI in new ways.

We want for example to introduce both a [ForceInline] and a [UnsafeCode] attributes that can be applied to methods to hint the code generation engine to always inline a method, and to remove arrays-bounds-checking on a per-method basis.

Hot Topics

A hot topic at the GDC was when we would bring the new C# 5 "await" feature to Mono.

C#'s await is a perfect solution to many of the problems that game developers face. Although there are solutions like Unity's co-routines, Mono Continuations/microthreads and Michael Hutchinson's open sourced micro-threading framework these features require a particular set of programming practices and pattern or support in the VM to do this.

C# Await is beautiful in that it integrates directly into the language and allows developers to focus on the algorithm and not in the administrivia of suspending execution and the boilerplate involved.

Which leads me to F#. The C# await functionality is based on F#'s Asynchronous Workflows which is available to everyone (thanks to Microsoft open sourcing the F# compiler and runtime).

What is fascinating is what some people are doing with F# in games: they can use F# to express the game AI in more succinct terms than any other scripting language can do. Not being a game designer, I do not quite understand the domain space, but apparently F# is just what the doctor ordered for complicated AI behaviors.

This coupled with async execution is a game engine developer's dream. But F# is not for everyone, there is a learning curve for getting to express problems in F# that is not suitable for game developers that have simple needs for their in-game logic.

WPF: A Recurring Topic

Many tool vendors (animation, pipeline, version control) have used WPF for their software or are planning on using it for new projects. These vendors have historically only supported Windows and are now looking at adding either Mac or Linux. This became almost a FAQ at the Mono booth: when are you going to ship WPF on Mac/Linux.

We have no plans on building WPF. We just do not have the man power to build an implementation in any reasonable time-frame.

Today, we offer a few suggestions to developers. Feel free to pick and choose:

  • Use Gtk# if you want to share the same code across all three platforms.
  • Split your UI code from the non-UI code and build a UI per system. On Windows, use WPF, on Mac use MonoMac, on Linux Gtk#. Or use gtk# on Mac and Linux.
  • For tools that are mostly OpenGL/DirectX based, use Windows.Forms, keeping in mind that some bug fixing or work around on their part might be needed as our Windows.Forms is not actively developed.

If you can afford building two or three UIs

Those are the toolkits you can use today to get your .NET-based tools working on multiple platforms. There are a number of longer-term options in the horizon that could be useful, but would require a concerted effort by the community to complete:

    Monomac.Winforms: assist the effort to have a Winforms look-alike API that happens to be based entirely on MonoMac and provides a native experience at the expense of dropping compatibility with some Winforms features.

    Create an SWT-like toolkit, like Eclipse did for Java, but this time for .NET. Mapping UI components to Cocoa, Gtk+ or WPF depending on the platform.

    Use Silverlight on Windows. And then use a modified version of Moonlight on Linux (and assist porting Moonlight to Mac) to get enough support to integrate with the native OS (menus, file dialogs, file system access) and to access and embed OpenGL in their applications.

    WPF implementation: not impossible, but this will require someone to fund some 15-20 developers to implement this enormous stack and some 2-3 years of work.

Posted on 07 Mar 2011


Saturday Mono Update

by Miguel de Icaza

Following a long established tradition of doing a quick Mono update after we do a major release, we released Mono 2.10.1 to the world.

There are four big features in this release that we backported from our master branch in addition to some 25 fresh bug fixes:

  • Support for running OrchardCMS on Linux. We also wrote a PostgreSQL backend for it. You can find the patches in this discussion.
  • The Parallel Framework's Default task scheduler has been switched to use our new and improved internal threadpool that we introduced with Mono 2.10. Previously it used its own (and amazing) scheduler, but did not share the same properties as .NET as there were by default two active threadpools, now there is only one.
  • Plenty of updates to the WCF stack.
  • OSX is a fast growing OS for Mono, this release brings performance counters for OSX as well as adding debugging symbols to all of our libraries if you install the CSDK package from our download page.

There were also three important regressions from Mono 2.8 that have been fixed. We encourage everyone to use Mono 2.10.1.

Posted on 26 Feb 2011


MVP Summit and GDC 2011

by Miguel de Icaza

Next week I will be in Bellevue, WA from Sunday to Wednesday to participate in the 2011 Microsoft MVP Summit.

From Wednesday to Friday I will be San Francisco attending the Game Developer's Conference.

Ping me if you want to get together.

Posted on 25 Feb 2011


C# Compiler as a Service Update

by Miguel de Icaza

Our C# compiler-as-a-service library can now process any C# construct, it is no longer limited to expressions and statements.

This means, that you can now enter entire class definitions in the command line:

csharp> class Demo {
      >     public int Add (int a, int b)
      >     {
      >          return a + b;
      >     }
      > }
csharp> new Demo ().Add (1, 3);
4
csharp>

This work was done by the amazing Marek and is now available on Mono's master branch in github.

This functionality can also be used for scripts, in particular in Unix, you can now create C# "source executable" files, like this:

bash$ cat demo.cs
#!/usr/bin/csharp
class Demo {
	public dynamic Add (dynamic a, dynamic b)
	{
		return a + b;
	}
}
Console.WriteLine (new Demo ().Add ("this is", " cute"));
bash$ chmod +x demo.cs
bash$ ./demo.cs
this is cute
bash$

Multiple Compiler Instances

In addition, we turned the static API Evalutor.Eval (string expression), into an instance API. The instance API allows developers that are embedding the C# compiler-as-a-service in their application to have different contexts.

This required the entire compiler to be updated from being a giant set of static classes that could safely use global variables and state into a state that was properly encapsulated.

The API is now richer, we provide a way to configure the compiler settings using a settings class. This can be populated either manually, or by using the build-in command-line parser for compiler options. The following sample shows how this could be used:

using Mono.CSharp;
using System;

class Runner {
	static int Main (string [] args)
	{
		var r = new Report (new ConsoleReportPrinter ());
		var cmd = new CommandLineParser (r);
		
		var settings = cmd.ParseArguments (args);
		if (settings == null || r.Errors > 0)
			Environment.Exit (1);

		var evaluator = new Evaluator (settings, r);

		evaluator.Run ("class Demo { public static int Add (int a, int b) { return a+b; }}");
		evaluator.Run ("print (Demo.Add (1,2));");
		return 0;
	}
}

Testers Wanted

This revamped compiler will be part of Mono 2.12, but we would love to get users to test the new functionality and to help us identify any problems early on, before we even release this code.

We do provide a convenient sln file that you can use the compiler as a service, and it works both in Visual Studio/.NET and Mono.

Silverlight

We have not tested this with Silverlight, but in theory, it should now work fine with it. We would love to see someone build an interactive shell like the one we did with Gtk# but hosted on the browser:

Posted on 24 Feb 2011


Well, Actually

by Miguel de Icaza

Why you are not getting laid

As software developers, we develop habits that allow us to build products that work and do not fail under stress. Every software developer knows what an "off-by-one" error is, and like the Karate Kid, we train extensively so we can avoid those traps. We learn how to avoid these and other similar software problems and we sharpen our skills to find logic errors.

As we mature as developers, finding logic errors and incomplete solutions becomes our way of life. It defines us.

But our engineering strength is also our social weakness. Countless times as engineers you will find yourself interrupting someone telling a story, an anecdote or a joke to correct a false assumption, provide an extra fact that the narrator overlooked, give a bigger perspective on the problem or point out that the joke premise is actually flawed.

You can identify this behavior because the person interrupting usually starts with the phrase "Well, actually...".

As a kid, I thought this was my strength. I knew a little bit more than my sister. So whenever she would say something, I would quickly interject something like "Well, actually, the origin of the word Shih Tzu means Lion Dog and has nothing to do with the dog's digestive patterns".

Yes, I was really fun to hang out with.

As a child, I wondered why my sister could make friends and keep them so easily, while I could not. It would take me years to discover this. And now, as a public service I am sharing with you, my fellow geek friends, what I learned.

Whoever pulls a "well, actually" almost always shifts the conversation to himself. And now we are no longer following along with your friend's joke, we get to learn how much more you know about the limitations of the Sun Protection Factor scale in sunblock products.

You are doing it wrong

As a seasoned engineer, you need to learn control your impulses. Having dealt with my own well, actually problem, I can attest that adjusting this social behavior might even get you laid.

Jokes are funny because they surprise us. But a joke is not funny if you have to present a 30-page document setting up every little detail. An ill-placed "Well, actually" will get your colleagues to abandon in an instant the water cooler conversation and escape to the peaceful solitude of their workstations.

Range of Action

You can find full-time well-actually folks both in person or monitoring your every quip on twitter.

Even the most rudimentary of the well-actuallistas is able to spoil even the best Ricky Gervais material.

Twitter being a medium limited to 140 character is like catnip for patronizing douchebags. They can not resist the urge to point out logic flaws in your minimalist observation.

This is particularly a problem for those of us that love to tweet things that amuse us or that we find amusing. Fear of a barrage of factoids from an omitted detail can be paralyzing.

Dealing with the Well Actually crowd

The well-actually crowd wants as much as everyone else to participate in the conversation. They want to be loved.

But instead of rolling with the punches and participating in a brainstorm of ideas and exploding humor, they contribute interruptions, facts and details that merely produce stop energy on an ongoing discussion. They turn the center of attention towards them.

The well-actually crowd means well. They want to be loved, they just have not realized that they are undermining their own quest for friends.

If you are a sagacious well-actuallista you need to understand that you are not outwitting anyone. It takes more intelligence to build a joke, tell a funny anecdote or narrate a gripping story than it takes to nitpick.

You are not impressing anyone with your hard earned encyclopedic knowledge that you obtained by spending hours on the Internet. You are just making everyone around you realize that you are as much fun to have lunch with as a flaming turd in a bag.

Those of us in the receiving end of a well-actually, need to start an awareness campaign. Perhaps using Twibbons to cure this disease. Unlike many diseases, this awareness program will lead to a cure.

While being technically correct is the best kind of correct, what you don't realize is that while you enjoy the triumph of your well-actually, everyone around you is secretly hoping that you choke on a bucket of cocks.

Practical Solutions

In the office, we have lots of talented engineers and at one point or another one of us will interject a well placed "well, actually" at an innapropriate moment.

These days we are fully aware of this social disease and we strive to avoid it. When someone interrupts a discussion with a well-actually you can hear someone say:

"Did you just well-actually me?"

Which is basically a way of saying "That has nothing to do with the topic, but thanks for derailing us" without having to go into the explanation and getting lost on the tangent.

This is a good first step. In our case, we have printed copies of the Ok, It's Time To Explain Some Stuff Patronizing Douchebag Trollcat in two sizes: a full-size well-actually cat, and a small one that is given as an award to the douchiest interruption:

Okay it’s time to explain some stuff patronizing douchebag trollcat

On the Internet, you can try to point the patronizing douchebag to this blog post. Or if you have no patience, just click "block" on twitter.

Posted on 17 Feb 2011


Moonlight 4 Preview 1 is out

by Miguel de Icaza

Yesterday we released Moonlight 4, Preview 1.

This release of Moonlight completes the Moonlight 3 feature set and includes many features from Silverlight 4. Check out our release notes for the list of things that are currently missing from our Silverlight 4 support.

Rendering

Moonlight rendering system uses a painter's algorithm coupled with culling to reduce the amount of rasterization that needs to take place.

For example, if we had these objects all rendered at the same location, on top of each other:

A simple implementation would render the triangle, then the rectangle and then the circle, and we would get this result:

Moonlight optimizes this rendering by computing the bounding boxes of each element and determining which objects are completely obscured. In this case, the triangle never needs to be rendered as it is fully covered.

Since we have the entire graph scene in memory, we can push all the rendering to the X server without ever having to pull data back from it.

Each visible element on Silverlight derives from the class UIElement and Moonlight tracks the bounding box for all of each individual element. As you compose elements, the aggregate bounding box is computed. For example, a canvas that hosts these three UIElements would have a bounding box that contains all three of them:

New Rendering Features

With Silverlight 3, Microsoft introduced two large important changes to the framework: 3D transformations on objects and support for pixel shaders. Both of these are applied to every visual element in Silverlight (this is implemented in the class UIElement).

In addition to the properties inherited from Silverlight 2, UIElements now have two new properties: Projection and Effect.

The Projection property is a 3D matrix transformation (the 3D variation of the 2D affine transform that is available in most 2D graphics APIs). Silverlight exposes both the raw 3D matrix or a set of convenient properties that are easier to use and require no understanding of the interactions of the twelve elements of the 3D matrix (see this page for an explanation).

Just like 2D affine APIs typically expose convenience methods to scale, rotate, skew and translate, the PlaneProjection properties allow developers to focus on those components.

You can see a sample here.

Effects follow a similar pattern. The blur and drop-shadow effects are given convenient names and accessors (BlurEffect and DropShadowEffect but Silverlight exposes an API to create programmable pixel shaders that go beyond these two simple cases.

The ShaderEffect allows users to load pixel shaders written using the High Level Shader Language (HLSL). Here is a sample app showing pixel shaders in action.

3D transformations and pixel shaders require that the contents of a UIElement are rendered to an intermediate output surface. The 3D transformation and shader effect is applied when this surface is composited onto the parent output surface. This compositing operation can be accelerated using graphics hardware.

From our previous example, the three elements would be rendered into a 2D surface, and the actual transformation can be done in the hardware:

Finally, the third new rendering upgrade was the introduction of a bitmap cache that can be applied to a UIElement. When a UIElement is flagged for being bitmap cached, the same kind of intermediate surface rendering and hardware accelerated compositing is performed as for elements with 3D transformations or pixel shaders. The contents of bitmap cache elements are also rendered once and kept on a bitmap that is later composited. This can improve performance vastly for complex controls with many interlocking pieces: instead of computing and re-rendering the entire contents every time, the bitmap cache is used.

This of course has some visible effect. If you instruct Silverlight to use a bitmap cache, and then you zoom-in the contents, you will see the result get pixelated. You can learn more about this on the BitmapCache documentation.

Moonlight's New Rendering Pipeline and GPU Acceleration

Both effects and projections can be implemented purely in software. Effects can be implemented by providing a small interpreter for HLSL code and projections by performing the rendering in software and compositing the results.

David Reveman, the hacker behind Compiz joined the Moonlight team last year to implement the new rendering primitives, but also to figure out how we could hardware accelerate Moonlight. The results of his work are available on yesterday's release of Moonlight 4.

The rendering pipeline was modified. Now, whenever a UIElement has either a Projection, an Effect or has the the flag BitmapCache set the entire UIElement and its children are rendered into a surface that is then off-loaded for the GPU to render.

When OpenGL is available on the system, the composition of UIElements is entirely done by the GPU.

Moonlight will use the GPU to accelerate for compositing, perspective transformations and pixel shaders if the hardware is present without having to turn this on. Silverlight by default requires developers to opt into hardware acceleration and has its own set of features that it will hardware accelerate.

In general, Moonlight uses the GPU more than Silverlight does, except in the case of DeepZoom, where we still do not accelerate this code path.

Gallium3D

Our new rendering pipeline is built using OpenGL and Gallium3D.

Gallium is an engine that is typically used to implement OpenGL. In our case, we use the Gallium3D API when we need to fallback to software rendering 3D transforms on Linux. Otherwise we go through the OpenGL pipeline:

If we were to only support Linux/X11, Gallium3D would have been a better choice for us. But we want to allow the Moonlight runtime to be ported to other windowing systems (Like Wayland on Linux) and other operating systems.

Room for Growth

Now that we have this 3D accelerated platform in place, it is easy to fine-tune specific UIElements to be hardware accelerated.

This first release did only the basics, but we can now trivially use hardware decoders for video and have that directly composited in hardware with the rest of a scene, or we can offload image transformations entirely to the hardware on a type-by-type basis and of course, DeepZoom.

Object Lifecycle

Objects in moonlight live in two spaces, low-level components live in C++ and are surfaced to C#. Typically this means that we have code that looks like this in C++:

	//
	class MyElement : public UIElement {
	  protected:
		MyElement ();
	  private:
	        // fields and methods for MyElement go here
	}
	

In C# we create a mirror, like this:


	public class DependencyObject {
		// Points to the C++ instance.
		IntPtr _native;
	}
	

When a user wrote in C# "new MyElement", we would P/Invoke into C++ code that does "new MyElement", get a pointer back to this instance and store it in the "_native" field.

In the other direction, if we created a C++ object and then we had to "surface" it to the managed world, we would initialize the object based on our C++ "this" pointer.

We could create instances of MyElement in C++, and when this instance needs to be surfaces to the managed world, we would create an instance of the managed object, and store the pointer to the underlying C++ object in the _native pointer.

In the Moonlight 2.0 days we used to have C++ objects that would only create managed objects on demand. At the time, we did this to avoid creating thousands of managed objects when loading a XAML file when only a handful of those would be controlled by user code.

The Moonlight runtime, running in pure C++ code, surfaced objects to the C# world and we tracked the object life cycle with good old reference counts. But with Silverlight 2, we started to see problems with the design as it was possible to end up with cycles. These cycles did not happen only in the C++ side or the C# side, but they spanned the boundaries. This made it very hard to debug and it made it hard to keep Moonlight from not leaking memory.

Templates for example could create these cycles.

With Moonlight 4, we have landed a new life cycle management system that works like this:

  • Every C++ object that we create always points to a managed counterpart. Gone are the days where the managed peer was created only when needed.
  • Every C++ instance field that points to a DependencyObject subclass goes through this cool C++ templated class that notifies managed when the reference changes.
  • There are no ref/unref pairs surrounding stores to instance fields in c++ anymore.

Now our base class in C++ has this:

	// Our entire hierarchy exposed to managed code
	// derives from EventObject
	class EventObject {
        	GCHandle managed_handle;
	}
	

Now all the c++ objects exist and are kept alive solely by their managed peers (there are some rare exceptions for things like async calls) and the whole graph is traversable by Mono's GC because all stores to c++ instance fields result in a managed ref between the respective peers.

With the new code, we no longer live in a world of refs/unrefs (again, except for some rare cases) and whenever we assign to a C++ field that points to a managed object we notify the managed peer of the change.

We were not able to ship Moonlight 4 with our new garbage collection system (Sgen) as we ran into a couple of hard to track down bugs at the last minute, but we are going to switch it on again soon.

Future Work

There is still room for improvement, and now that we know how to cook this kind of code, the goal is to use Mono's new GC in Moonlight more extensively.

We want to teach SGen to scan the C++ heap and track references to managed objects, dropping another potential source of problems and reducing the code needed. We would also love to go back to only creating managed objects on demand.

Platform Abstraction Layer

Moonlight was originally designed as a Linux-only, X11-only plugin for rendering Silverlight content. Developers constantly ask us whether they could run Moonlight on platform XX that is either not Linux or does not use X11.

The amount of work to port Moonlight 2 to those kinds of scenarios was so overwhelming that most people abandoned the efforts relatively quickly.

With Moonlight 4, we have introduced a new platform abstraction layer that will make it simpler for developers to port the Moonlight engine to other platforms.

Whether you want hardware accelerated user experiences in your video game or you want to put Moonlight on a the FreezeMaster 10000 Domestic Fridge with an Internet Connection and SmoothStreaming running on a barebones ARM CPU, you can now enjoy this in the comfort of your home.

We have done some minimal tests to exercise the API and can run the Moonlight engine on both MacOS and Android. You can look at exclusive footage of the animation test suite running on OSX and on Android.

If you are like me, not much of a click-on-the-video kind of person, and would rather get a screenshot, you can bask on the smooth colors of this screenshot on Android or in this delightful test on MacOS.

We are currently not planning on completing that work ourselves, so this is a fabulous opportunity for a caffeine-driven hacker to complete these ports.

Some possibilities, from the top of my head include being able to use Silverlight to design parts of your user experience for apps on the Mac AppStore (think MoonlightView in your MonoMac apps), or for your Android app.

Using Expression beats coding cute animations and futuristic UIs by hand. That is why every major video game embeds ScaleForm, the embeddable Flash runtime for handling the UI.

New XAML Parser

Our original XAML parser was written in C++, this worked fine for Moonlight 1, but with Moonlight 2 it started to become obvious that we were spending too much time calling back from C++ to C# to create managed objects.

This was acceptable up to version 2, but it no longer scaled with Moonlight 3. Too much time was spent going back and forth between the C++ world and the C# world. Those following the development of Moonlight would have noticed that every couple of weeks a new extra parameter to the xaml_load function was added to deal with yet another callback.

The new XAML parser is entirely written in C#, is faster and more reliable.

And lots more

Check out our release notes for Moonlight 4 Preview 1.

Posted on 16 Feb 2011


« Newer entries | Older entries »