Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share graphics context globally #4376

Merged
merged 2 commits into from
Jul 22, 2023
Merged

Share graphics context globally #4376

merged 2 commits into from
Jul 22, 2023

Conversation

psychon
Copy link
Contributor

@psychon psychon commented Mar 10, 2021

Instead of creating a graphics context for every surface_t, this commit
adds a cache that allows to "remember" up to two GCs. Thus, the code
uses less GCs. When a GC from the cache can be used, this also gets rid
of a round-trip to the X11 server. Both of these are tiny, insignificant
savings, but so what?

Fixes: #3478
Signed-off-by: Uli Schlachter psychon@znc.in


This adds a copy&paste duplicate of get_visual_depth() from src/xcb.c to `libi3. If you tell me what to do, I can clean this up again, but I was not really sure what the best option here is.

I tried testing the cache overflow by trying to create a window with a depth other than 24 or 32, but my X11 server does not offer any such visuals:

$ xdpyinfo| grep depth: | uniq
    depth:    24 planes
    depth:    32 planes

Also, initially I planned to use a SLIST for this and have the cache unlimited. After briefly staring at the macros, I went with a statically sized solution instead. Thus, there is now the possibility that a GC cannot be cached and is thus still owned by the surface_t.

Copy link
Member

@orestisfl orestisfl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, and sorry for the delayed review

libi3/draw_util.c Show resolved Hide resolved
libi3/draw_util.c Outdated Show resolved Hide resolved
static struct {
uint8_t depth;
xcb_gcontext_t gc;
} gc_cache[2] = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like in i3 we are sticking too much in primitive data structures even though we can take advantage of more advanced ones, e.g. this could have been implemented more easily with glib's hashtable and glib is already a dependency.

I am not really requesting that you re-write this, just an observation. You can ignore this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I didn't use much glib so far. I quickly looked at the link and then decided to go with You can ignore this comment. 😅

libi3/draw_util.c Outdated Show resolved Hide resolved
@psychon
Copy link
Contributor Author

psychon commented Jul 17, 2023

I rebased this on next (had some conflicts) and addressed the comments.

I am not entirely sure, but the following comments now seems outdated:

    if (surface->owns_gc) {
        /* NOTE: This function is also called on uninitialised surface_t instances.
         * The x11 error from xcb_free_gc(conn, XCB_NONE) is silently ignored
         * elsewhere.
         */
        xcb_free_gc(conn, surface->gc);
    }

uninitialised cannot really mean "contains arbitrary garbage". That sounds like a recipe for crashes. So I guess this means zero-initialised. In that case, owns_gc should be false and I just made this error case go away.

However, this is just a guess and I don't have the time right now to dig deeper, so I am just mentioning this here and keeping things otherwise the way they already were.

@psychon psychon force-pushed the gc_cache branch 3 times, most recently from 6ad3b66 to cb38b26 Compare July 17, 2023 18:04
Instead of creating a graphics context for every surface_t, this commit
adds a cache that allows to "remember" up to two GCs. Thus, the code
uses less GCs. When a GC from the cache can be used, this also gets rid
of a round-trip to the X11 server. Both of these are tiny, insignificant
savings, but so what?

Since GCs are per-depth, this code needs access to get_visual_depth().
To avoid a code duplication, this function is moved to libi3.

Fixes: i3#3478
Signed-off-by: Uli Schlachter <psychon@znc.in>
Copy link
Member

@orestisfl orestisfl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, couple of last things

libi3/draw_util.c Outdated Show resolved Hide resolved
}

xcb_gcontext_t gc = xcb_generate_id(conn);
xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(conn, gc, drawable, 0, NULL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(conn, gc, drawable, 0, NULL);
/* The drawable is only used to get the root and depth, thus the gc is not
* tied to the drawable and it can be re-used from different drawables. */
xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(conn, gc, drawable, 0, NULL);

I came up with this while trying to understand why this is safe to do e.g. when creating a gc from a drawable that is later freed. If my comment is correct, maybe we can include it for further context to readers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"Definitive answer" seems to come from the X11 protocol reference manual: https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html#requests:CreateGC

The gcontext can be used with any destination drawable having the same root and depth as the specified drawable [...]

Signed-off-by: Uli Schlachter <psychon@znc.in>
Copy link
Member

@orestisfl orestisfl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you

@orestisfl orestisfl merged commit d6e2a38 into i3:next Jul 22, 2023
3 checks passed
@psychon psychon deleted the gc_cache branch July 22, 2023 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Investigate using only two global GCs
2 participants