Clutter Wiki

Views
From ClutterProject
Jump to: navigation, search

Note: the write up of the whiteboard discussions is a work in progress

Contents

Overview

Broadly speaking renderlists refers to a mechanism that lets us retain the low level Cogl primitives used to paint an actor essentially as part of the scenegraph. The low level primitives don't warrant having a ClutterActor each but the actors will start to maintain a list of primitives internally. The primitives owned by each actor will be part of a data structure called a renderlist which gives us a way to sort all the primitives of a scene so we can optimize how we submit the primitives to the GPU when painting the scene.

Whiteboard discussions

The plans for using render lists on Cogl were originally made with whiteboard discussions:

Apparently image scaling doesn't work on this wiki so here are links to the full size versions instead:

What needs to be logged in the renderlists?

Each entry in the renderlist needs to encapsulate all the state to draw a single Cogl primitive at a given position. We've identified that the following needs to be associated with each primitive renderlist entry:

  • z-index (This is the painters algorithm z-index)
  • clip stack handle (clip stacks have been re-worked so it's now very cheap to get an handle to an immutable clip stack)
  • material handle (this needs to have the semantics of a deep copy for the material, the layers it references and the textures they reference, but using copy-on-write optimizations internally)
  • primitive type: path, vertex buffer, rectangle, polygon
  • modelview matrix (unless software transform is applied to the primitive first)
  • primitive geometry: path handle, vertex buffer handle, or float arrays for rectangles/polygons.


Data structures

Changes to Clutter actor:

  1. We need a reliable way to query all the children of an actor. Currently the only way to traverse all the actors of the scene is by doing a ::paint() traversal.
    • Currently only actors implementing the container interface give a way to iterate the children. We are going to add an internal _clutter_actor_get_children() API applicable to any actor including composite (non container) actors.
    • We will add a more formal priv->parent_state[parent_id] structure that allows us to associate data with an actor relating to a specific parent. NB: clutter actors can have multiple parents since we support cloning of actors. The primitives we are going to be adding to the renderlists need to be associated with an a position in the scenegraph which means associating them with an actor and a specific parent.

Changes to Cogl

  1. The primitives APIs; cogl_rectangle(), cogl_polygon(), cogl_vertex_buffer_draw() and cogl_path_fill() need to support redirection of primitives into a retained renderlist,

FIXME continue here

Example renderlist API

stage_init:

rl = cogl_renderlist_new ();
z_index_prop_id =
  cogl_render_list_install_property ("z-index", COGL_RENDERLIST_PROPERTY_TYPE_INT);

clutter_actor_paint() - BEFORE actor::paint

/* This lets you insert into the renderlist relative to pre-existing
 * primitives of this actor. If the actor doesn't have pre-existing
 * primitives then it will pass NULL which push a mark at the end
 * of the renderlist so we append */
cogl_renderlist_push_marker (rl, priv->parent_state[parent_id].prim_list);
g_list_foreach (priv->parent_state[parent_id].prim_list, cogl_renderlist_remove);
cogl_renderlist_set_property_int (z_index_prop_id, paint_z++);

actor::paint()

cogl_translate()
cogl_scale()
cogl_set_source()
cogl_rectangle() ->
   _cogl_renderlist_set_modelview();
   _cogl_renderlist_set_material(rl, ctx->source_material);
   _cogl_renderlist_set_clip_stack(rl, cogl_clip_stack_copy (ctx->clip_stack));
   _cogl_renderlist_log_rectangle();

clutter_actor_paint() - AFTER actor::paint

priv->parent_state[parent_id].prim_list = cogl_renderlist_pop_marker()

Problems

push/pop renderlists
We need a way to push and pop renderlists marks since it's clutter_actor_paint that determins where we add to a renderlist but an actor may recursively call clutter_actor_paint
push/pop framebuffer
We need a mechanism to allow Clutter to hook into cogl_push/pop_framebuffer calls so that it can redirect us to a new renderlist.
cogl_enable_depth_test
This becomes a sorting barrier like vertex shaders.
  • clear @ enable if there were preceding primitives
  • clear @ new primitive after disable
  • transient period when prim-list not consistent while painting an actor; is that ok? - i think we figured this was ok
  • We need to be able to handle texture atlas reorganization:
    • This means we need to be able to scrap arbitrary entries in a renderlist and notify the toolkit so they can be recreated.
    • We also need to maintain list of renderlist entries with every CoglAtlasTexture / GLES2 NPOT texture so if the backends want to change the textures underlying storage we know when entries to scrap.

Rendering

Sorting the renderlist entries

We sort in this order of priority...

  1. whether a vertex shader is associated with the material (barrier)
    • If the user explicitly specifies a vertex program then we can't override the z necessary for faking the painters algorithm so this adds a barrier that makes sure all primitives with vertex programs will actually be painted with painters algorithm.
  2. depth enable (barrier)
    • Since we are going to be using the depth buffer to fake painters algorithm, when the user enables depth testing we have to clear the depth buffer before and after the points where the user enables and disables depth testing.
      • clear @ enable if there were preceding primitives
      • clear @ new primitive after disable
  3. clip stack ancestry (barrier)
    • We need to use barriers to make sure that primitives with a given clip state don't get sorted and muddled with primitives with different clipping states.
  4. material
    • Here we need to sort primitives so as to minimize the overall amount of state changes.
  5. journal compatibility
    • Currently only rectangles go through the journal but paths and polygons might eventually too. We should aim to keep journal compatible entries next to each other so the journal can further assist with minimizing state changes.
  6. modelview (only for primitives that we don't perform a software transform on)
  7. z-index

"Barriers" delimit sublists which the sorting can't move entries across.

Drawing

  1. set alpha function to discard non opaque fragments.
  2. render everything front to back with the color channels masked and write z-index to depth buffer. (may need to consider some state changes)
  3. set depth test to ==
  4. render opaque geometry sorted to minimize state changes and overriding the z to = z-index.
  5. render non opaque geometry front to back with depth test set to < and alpha set to discard opaque fragments.
Personal tools