Graphics compiler

Before rendering an InstructionGroup, we compile the group in order to reduce the number of instructions executed at rendering time.

Reducing the context instructions

Imagine that you have a scheme like this:

Color(1, 1, 1)
Rectangle(source='button.png', pos=(0, 0), size=(20, 20))
Color(1, 1, 1)
Rectangle(source='button.png', pos=(10, 10), size=(20, 20))
Color(1, 1, 1)
Rectangle(source='button.png', pos=(10, 20), size=(20, 20))

The real instructions seen by the graphics canvas would be:

Color: change 'color' context to 1, 1, 1
BindTexture: change 'texture0' to `button.png texture`
Rectangle: push vertices (x1, y1...) to vbo & draw
Color: change 'color' context to 1, 1, 1
BindTexture: change 'texture0' to `button.png texture`
Rectangle: push vertices (x1, y1...) to vbo & draw
Color: change 'color' context to 1, 1, 1
BindTexture: change 'texture0' to `button.png texture`
Rectangle: push vertices (x1, y1...) to vbo & draw

Only the first Color and BindTexture are useful and really change the context. We can reduce them to:

Color: change 'color' context to 1, 1, 1
BindTexture: change 'texture0' to `button.png texture`
Rectangle: push vertices (x1, y1...) to vbo & draw
Rectangle: push vertices (x1, y1...) to vbo & draw
Rectangle: push vertices (x1, y1...) to vbo & draw

This is what the compiler does in the first place, by flagging all the unused instruction with GI_IGNORE flag. As soon as a Color content changes, the whole InstructionGroup will be recompiled and a previously unused Color might be used for the next compilation.

Note to any Kivy contributor / internal developer:

  • All context instructions are checked to see if they change anything in the cache.
  • We must ensure that a context instruction is needed for our current Canvas.
  • We must ensure that we don’t depend of any other canvas.
  • We must reset our cache if one of our children is another instruction group because we don’t know whether it might do weird things or not.