diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2014-11-22 09:07:51 -0800 |
---|---|---|
committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2014-11-22 11:46:53 -0800 |
commit | 10a7a89311ba0edf93c70470ddac23ecf2d8c3e7 (patch) | |
tree | eb5ebbd9c718ab804e79387113f359c5558f8837 /gdk/gdkinternals.h | |
parent | c01e37a9a5db5957d08fcb4b8f11ea86c344f6d1 (diff) | |
download | gtk+-10a7a89311ba0edf93c70470ddac23ecf2d8c3e7.tar.gz |
gdkinternals: Document our drawing and painting process better
Diffstat (limited to 'gdk/gdkinternals.h')
-rw-r--r-- | gdk/gdkinternals.h | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 67a58da1fb..cbb87e44a2 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -216,15 +216,82 @@ struct _GdkWindow cairo_pattern_t *background; + /* The paint logic here is a bit complex because of our intermingling of + * cairo and GL. Let's first go over the cairo-alone case: + * + * 1) gdk_window_begin_paint_region() is called with an update region. If + * the backend wants it, we redirect drawing to a temporary surface + * sized the same as the update region and set `surface_needs_composite` + * to TRUE. Otherwise, we paint directly onto the real server-side window. + * + * 2) Things paint with cairo using gdk_cairo_create(). + * + * 3) When everything is painted, the user calls gdk_window_end_paint(). + * If there was a temporary surface, this is composited back onto the + * real backing surface in the appropriate places. + * + * This is similar to double buffering, except we only have partial surfaces + * of undefined contents, and instead of swapping between two buffers, we + * create a new temporary buffer every time. + * + * When we add GL to the mix, we have this instead: + * + * 1) gdk_window_begin_paint_region() is called with an update region like + * before. We always redirect cairo drawing to a temporary surface when + * GL is enabled. + * + * 2) Things paint with cairo using gdk_cairo_create(). Whenever + * something paints, it calls gdk_window_mark_paint_from_clip() to mark + * which regions it has painted in software. We'll learn what this does + * soon. + * + * 3) Something paints with GL and uses gdk_cairo_draw_from_gl() to + * composite back into the scene. We paint this onto the backing + * store for the window *immediately* by using GL, rather than + * painting to the temporary surface, and keep track of the area that + * we've painted in `flushed_region`. + * + * 4) Something paints using software again. It calls + * gdk_window_mark_paint_from_clip(), which subtracts the region it + * has painted from `flushed_region` and adds the region to + * `needs_blended_region`. + * + * 5) Something paints using GL again, using gdk_cairo_draw_from_gl(). + * It paints directly to the backing store, removes the region it + * painted from `needs_blended_region`, and adds to `flushed_region`. + * + * 6) gdk_window_end_paint() is called. It composites the temporary surface + * back to the window, using GL, except it doesn't bother copying + * `flushed_region`, and when it paints `needs_blended_region`, it also + * turns on GL blending. + * + * That means that at any point in time, we have three regions: + * + * * `region` - This is the original invalidated region and is never + * touched. + * + * * `flushed_region` - This is the portion of `region` that has GL + * contents that have been painted directly to the window, and + * doesn't have any cairo drawing painted over it. + * + * * `needs_blended_region` - This is the portion of `region` that + * GL contents that have part cairo drawing painted over it. + * gdk_window_end_paint() will draw this region using blending. + * + * `flushed_region` and `needs_blended_region` never intersect, and the + * rest of `region` that isn't covered by either is the "opaque region", + * which is any area of cairo drawing that didn't ever intersect with GL. + * We can paint these from GL without turning on blending. + **/ + struct { - cairo_region_t *region; + /* The temporary surface that we're painting to. This will be composited + * back into the window when we call end_paint. This is our poor-man's + * way of doing double buffering. */ cairo_surface_t *surface; - /* Areas of region that have been copied to the back buffer already */ + cairo_region_t *region; cairo_region_t *flushed_region; - /* Areas of region that have been copied to the back buffer but - needs furter blending of surface data. These two regions are - always non-intersecting. */ cairo_region_t *need_blend_region; gboolean surface_needs_composite; |