Blog

Blog

Rig 1

Posted at 18:39 on 31 Oct 2012

Today is the first release of Rig. This is a project that Robert Bragg and I have been working for the past few months. I won't try to describe it here, but instead I will try to entice you with a screenshot and ask you to take a look at Robert's detailed blog post.

image

Cogl Shader Snippets

Posted at 22:37 on 07 Dec 2011

Cogl has been getting some love lately to move towards the 2.0 API that will eventually replace the existing API. Now that Cogl has split out from Clutter and it can be used as a standalone library we are getting close to the goal of Cogl being a convenient replacement for OpenGL. However one thing that until recently has been severely lacking for Cogl to be a credible modern graphics library is good support for shaders. Cogl has had a sort of shader support for a long time but it has hardly been touched since the days when Cogl was just a very thin wrapper over the GL API. Cogl has evolved a lot since then so the previous shader support no longer fits with Cogl's design.

We've finally got around to improving this situation so there are now a few changes in git master of Cogl to make this better. In 2.0 land, instead of having to create a CoglProgram to replace the entire of either the vertex or fragment pipeline you can now create CoglSnippets. These can be inserted at specific hook points on a CoglPipeline to either wrap around or completely replace a part of the pipeline. For example, imagine we have a function in GLSL that can take an input colour and convert it to black-and-white. If we wanted to use this in Cogl we would previously have had to implement the entire fragment pipeline. Usually this would mean having to create a sampler uniform, update that uniform and writing the code to get a texel from the sampler. If we wanted to use this shader in another situation without texturing, for example when drawing a solid colour rectangle, we would have to write another shader that includes the function without the texturing.

With the snippets API we can now create an object that just contains the black-and-white conversion in a single line, like this:

snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
                            NULL,
                            "cogl_color_out.rgb = "
                            "vec3 (length (cogl_color_out.rgb) / 1.732);");

Then we can attach that snippet to any CoglPipeline and Cogl will fill in the rest of the code needed to make it work. It can be attached to multiple pipelines, for example one with texturing and one without.

The second feature that has landed recently is to be able to store uniform values on a CoglPipeline. The idea behind the design of Cogl is that you will store as much of the GL state as possible in a CoglPipeline object and try to switch between these cached states rather than redescribing the state to the graphics library every time something is drawn. That way Cogl can minimise the state changes by recognising the minimal set of differences between two pipelines. The previous approach for uniforms - which was the same as OpenGL where the uniform values are attached to the program object - doesn't match well to this design. If you wanted to use a program multiple times with different values then you would have to reset the values on the program for every primitive.

In Cogl master you can instead encapsulate these uniform values on the pipeline and Cogl can efficiently recognise which uniforms are different between two pipelines sharing the same program and avoid flushing uniforms that haven't changed. For example, imagine this snippet which just replaces the red component of the fragment colour based on the value of a uniform:

snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
                            "uniform float red_value;",
                            "cogl_color_out.r = red_value;");
pipeline = cogl_pipeline_new ();
cogl_pipeline_add_snippet (pipeline, snippet);
cogl_object_unref (snippet);

Now if we want to frequently paint using this snippet with two different values, we can create two pipelines like this:

pipeline1 = cogl_pipeline_copy (pipeline);
location = cogl_pipeline_get_uniform_location (pipeline, "red_value");
cogl_pipeline_set_uniform_1f (pipeline1, location, 0.5f);

pipeline2 = cogl_pipeline_copy (pipeline);
location = cogl_pipeline_get_uniform_location (pipeline, "red_value");
cogl_pipeline_set_uniform_1f (pipeline2, location, 0.8f);

Now we can draw with these two pipelines easily:

cogl_push_source (pipeline1);
cogl_rectangle (0, 0, 10, 10);
cogl_pop_source ();

cogl_push_source (pipeline2);
cogl_rectangle (10, 10, 20, 20);
cogl_pop_source ();

Cogl will quickly know that the two pipelines are using the same program because they are copied from the same parent so it will only flush the state for the new uniform value when switching between the two.

The third recent addition to Cogl related to shaders is support for custom attributes. The API has already been in place for this for a while from both CoglPrimitive and the now deprecated CoglVertexBuffer. However it was never actually connected together properly so no-one could use it. The custom attributes can be set by just naming them when a CoglAttribute is created. Here is a short example:

/* Create a pipeline with a snippet using a custom attribute. This
   will just replace the red component of the colour using a float */
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
                            "attribute float redness;",
                            "cogl_color_out.r = redness;");
pipeline = cogl_pipeline_new ();
cogl_pipeline_add_snippet (pipeline, snippet);
cogl_object_unref (snippet);

/* Create a primitive with two attributes. One will be our custom
   attribute and the other will be the normal position attribute */
static const float verts[] = { 0, 0, 0.0,
                               100, 0, 0.5,
                               50, 100, 1.0 };
CoglAttributeBuffer *buffer =
 cogl_attribute_buffer_new (sizeof (verts), verts);
CoglAttribute *attributes[2];
attributes[0] = cogl_attribute_new (buffer,
                                    "cogl_position_in",
                                    /* Stride */
                                    sizeof (float) * 3,
                                    /* Offset */
                                    0,
                                    /* n_components */
                                    2,
                                    COGL_ATTRIBUTE_TYPE_FLOAT);
attributes[1] = cogl_attribute_new (buffer,
                                    "redness",
                                    /* Stride */
                                    sizeof (float) * 3,
                                    /* Offset */
                                    sizeof (float) * 2,
                                    /* n_components */
                                    1,
                                    COGL_ATTRIBUTE_TYPE_FLOAT);
primitive =
  cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
                                      3, /* n_vertices */
                                      attributes,
                                      2 /* n_attributes */);
cogl_object_unref (attributes[0]);
cogl_object_unref (attributes[1]);
cogl_object_unref (buffer);

/* Now we can draw with this primitive and pipeline */
cogl_push_source (pipeline);
cogl_primitive_draw (primitive);
cogl_pop_source ();

I've uploaded the current documentation to a temporary location if you want further details of the API. It's all still experimental so we'd very much welcome any testing and feedback. The Cogl developers can be contacted on the new mailing list or at #clutter on GIMPnet.

gtk-im-extra

Posted at 01:13 on 17 Nov 2011

Is anybody else using gtk-im-extra? If so you might be interested to know I've made a git repo (it's currently still in CVS!) and added some patches to make it build with GTK+3. It would be really great if someone would get this into a Fedora package so I don't have to keep building it.

 git clone git://git.busydoingnothing.co.uk/gtk-im-extra

Gemelo

Posted at 07:50 on 11 Jul 2011

This year I have been taking French lessons in the evenings and it's given me the language learning bug. The tricky part so far has been finding people to practice the language with. As I am still too chicken to speak to real people, I thought it might be fun to try something like Omegle which lets you talk to random strangers. There is a sleazy French equivalent but most of the conversations go like this:

Partenaire : bonsoir
Vous : bonsoir
Partenaire : h ou f
Vous : je suis un homme
Votre partenaire a mis fin à la conversation ;-(

I was thinking it would be fun to make a similar website but that is specifically designed for language learning so that people can expect beginners of the languages to use the service too. Some quick hacking later and Gemelo is born. It is basically working but it's currently quite ugly and it only supports three languages. It hardly gets any traffic at the moment so it is unlikely that you'll find someone to talk to there unless you ask a friend to join at the same time.

The server is written as a custom HTTP server in C using GLib. I know that sounds a bit silly considering there are many existing libraries to a web service, but I really wanted to make each connection as light-weight as possible so that it could potentially handle 1000s of simultaneous connections. It is using a single thread model with epoll instead of the glib main context so that it scales by the amount of traffic instead of the amount of connections.

The code is all available in Git. So far I haven't been able to drum up much interest in the project so it might turn out to be a stupid idea. However if anyone wants to contribute it would be much appreciated, particularly if someone wants to make it look pretty or translate it to more languages. Also the code might be useful to someone as a base lightweight HTTP server for something else.

Embedded linked lists

Posted at 18:19 on 16 Jun 2011

GLib already has a pretty cool linked list implementation that everyone knows very well. It works by slice allocating small list nodes that each contain a void* pointer to some other data structure. This is convenient to use and it works well. However there are some situations where the implementation of the thing being listed is very closely tied to some list that is referring to it. For example, in the GdkWindow struct there is this:

 struct _GdkWindow
 {
   /* ... */

   GdkWindow *parent;

   /* ... */

   GList *children;
 };

In this case the idea of listing the child windows of a window is intrinsic to the implementation of a GdkWindow. The implementation itself owns the list. Almost every GdkWindow belongs to a list of children so there is almost always this extra list node being allocated in addition to the GdkWindow struct. A window can only ever have one parent so it will only ever belong to one of these lists. If we know we're always going to allocate a list node for the window, why don't we just put the list node directly in the struct? Then we have something like this:

 struct _GdkWindow
 {
   /* ... */

   GdkWindow *parent;

   GdkWindow *next_sibling;
   GdkWindow *prev_sibling;

   GdkWindow *first_child;
 };

This is starting to look much more like a DOM style tree structure. The major benefit of this is now if we want to know the siblings of a window we can just directly look at the pointers in its data structure. When the sibling pointers are stored in a separate GList allocation there is no simple way to get a pointer to the list node so we can't easily determine the siblings. This is an annoying problem for implementing g_list_remove because it needs to iterate the entire list to find the node that corresponds to the data pointer. For something like GdkWindow this is not good because it frequently uses g_list_remove to reorganise the window list for example in gdk_window_raise.

The downside of embedding the prev/next pointers directly is that you can no longer use the nice GList API to manipulate the list and instead you have to update the pointers manually. This can be quite fiddly and it can be easy to forget to update one of the prev pointers which can sometimes cause hidden confusing bugs.

I think it would make sense to have something in GLib itself to help applications use this embedded list approach so that we don't have to have home-grown implementations spread all over Gnome. I've opened a bug about this here:

https://bugzilla.gnome.org/show_bug.cgi?id=652587

I have two suggestions. One is to steal the embedded list implementation from the FreeBSD kernel. This is implemented as a short series of macros in a single header. It makes it very convenient to code in terms of the pointers to the objects themselves rather than having to pass the list node pointers to the list API. The second suggestion is to add some extra functions to the g_list_* API to make it convenient to directly add GList nodes inline to another struct. The downside of this is that the data pointer in the node is then redundant but it may be a better fit for the existing style of GLib API.

The bug so far doesn't seem to be getting much traction. I know however that a fair few Gnome projects are already using their own embedded list implementations so I'm sure there must be others interested in this idea. Please help and comment on the bug if you are interested! Thanks.