Skip to content
  • Robert Bragg's avatar
    Adds initial clipped redraw support to Clutter · c0d5af5d
    Robert Bragg authored
    A new (internal only currently) API, _clutter_actor_queue_clipped_redraw
    can be used to queue a redraw along with a clip rectangle in actor
    coordinates. This clip rectangle propagates up to the stage and clutter
    backend which may optionally use the information to optimize stage
    redraws. The GLX backend in particular may scissor the next redraw to
    the clip rectangle and use GLX_MESA_copy_sub_buffer to present the stage
    subregion.
    
    The intention is that any actors that can naturally determine the bounds
    of updates should queue clipped redraws to reduce the cost of updating
    small regions of the screen.
    
    Notes:
    » If GLX_MESA_copy_sub_buffer isn't available then the GLX backend
      ignores any clip rectangles.
    
    » queuing multiple clipped redraws will result in the bounding box of
      each clip rectangle being used.
    
    » If a clipped redraw has a height > 300 pixels then it's promoted into
      a full stage redraw, so that the GPU doesn't end up blocking too long
      waiting for the vsync to reach the optimal position to avoid tearing.
    
      » Note: no empirical data was used to come up with this threshold so
        we may need to tune this.
    
    » Currently only ClutterX11TexturePixmap makes use of this new API. This
      is done via a new "queue-damage-redraw" signal that is emitted when
      the pixmap is updated. The default handler queues a clipped redraw
      with the assumption that the pixmap is being painted as a rectangle
      covering the actors transformed allocation. If you subclass
      ClutterX11TexturePixmap and change how it's painted you now also
      need to override the signal handler and queue your own redraw.
    
      Technically this is a semantic break, but it's assumed that no one
      is currently doing this.
    
    This still leaves a few unsolved issues with regards to optimizing sub
    stage redraws that need to be addressed in further work so this can only
    be considered a stepping stone a this point:
    
    » Because we have no reliable way to determine if the painting of any
      given actor is being modified any optimizations implemented using
      _clutter_actor_queue_redraw_with_clip must be overridable by a
      subclass, and technically must be opt-in for existing classes to avoid
      a change in semantics. E.g. consider that a user connects to the paint
      signal for ClutterTexture and paints a circle instead of a rectangle.
      In this case any original logic to queue clipped redraws would be
      incorrect.
    
    » Currently only the implementation of an actor has enough information
      with which to queue clipped redraws. E.g. It is not possible for
      generic code in clutter-actor.c to queue a clipped redraw when hiding
      an actor because actors have no way to report a "paint box". (remember
      actors can draw outside their allocation and actors with depth may
      also be projected outside of their allocation)
    
      » The current plan is to add a actor_class->get_paint_cuboid()
        virtual so actors can report a bounding cube for everything they
        would draw in their current state and use that to queue clipped
        redraws against the stage by projecting the paint cube into stage
        coordinates.
    
    » Our heuristics for promoting clipped redraws into full redraws to
      avoid blocking the GPU while we wait for the vsync need improving:
    
      » vsync issues aren't relevant for redirected/composited applications
        so they should use different heuristics. In this case we instead
        need to trade off the cost of blitting when using glXCopySubBuffer
        vs promoting to a full redraw and flipping instead.
    c0d5af5d