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

weird transparent regions in kitty #1117

Closed
dankamongmen opened this issue Nov 15, 2020 · 20 comments · Fixed by #1244
Closed

weird transparent regions in kitty #1117

dankamongmen opened this issue Nov 15, 2020 · 20 comments · Fixed by #1244
Assignees
Labels
bug Something isn't working
Milestone

Comments

@dankamongmen
Copy link
Owner

When running notcurses-demo in Kitty, I get large unexpected transparent sections, almost always when blitting video. For example, the background of this video is expected to be an opaque black, but it is instead transparent (from the xray demo).

I suspect this to be an upstream bug, but I'm not going to file it as such until I can prove (and ideally fix) that.

2020-11-15-015842_1094x1417_scrot

@dankamongmen dankamongmen added the bug Something isn't working label Nov 15, 2020
@dankamongmen dankamongmen self-assigned this Nov 15, 2020
@dankamongmen
Copy link
Owner Author

This could also be that we're assuming the cells to be the background color when we clear, which would be our bug (and I think there's a terminfo capability for detecting exactly that). So let's keep our minds open.

@kovidgoyal
Copy link

@kovidgoyal
Copy link

The relevant capability is bce in terminfo, and you should not use it unless the terminfo advertises suport for it, which kitty's does not.

@dankamongmen dankamongmen added this to the 2.2.0 milestone Nov 28, 2020
@dankamongmen
Copy link
Owner Author

dankamongmen commented Dec 18, 2020

@kovidgoyal awesome, i think you're quite correct. thanks for the pointer! i ought be able to have this fixed in 2.1.2.

@dankamongmen
Copy link
Owner Author

Hrmmm, I agree that this looks like failure to take bce (back color erase) into account. I don't think that's what's going on, though -- we never use a clear escape, so I don't see how bce would be relevant. I'm fairly certain that all the transparent blocks are places where we've explicitly written RGB(0, 0, 0)+RGB(0, 0, 0) space characters (0x20). We then refrain from updating these cells afresh until they're damaged. So we cursor over the cells, but we're never clearing the screen and expecting a solid black as a result.

Nonetheless, I still suspect that this might be a Notcurses problem. I'll look more deeply into it ASAP.

@dankamongmen
Copy link
Owner Author

Alright, some experimentation today indicates that this only happens with black cells. I.e. in the xray demo shown above, the second phase is greenish, and everything gets drawn properly. In the first phase, however, we're black, and the black goes transparent. In the following demo, eagle, you see it once more, in the small vertical strip of shadow on the left. This is intended to be RGB(0, 0, 0), and it goes transparent.

So the question becomes, am I properly emitting authentic RGB(0, 0, 0)/(0, 0, 0) spaces? Let's demonstrate that before going any further.

@dankamongmen
Copy link
Owner Author

Ok, in xray we've got 9 rows of large assembled text, with a transparent background. underneath that is the ncvisual plane, which is entirely opaque, and the surface for a video which is entirely opaque. wherever we write something with a foreground color, we get our background black. wherever we don't, we get a transparent background (with kitty 0.19.3) let's see what exactly we're emitting there...

@dankamongmen
Copy link
Owner Author

So for where we have the pink intermixed with the top text, we're rasterizing sequences of the form:

RAST 00000064 [d] to 8/15 cols: 1 4097e7bc40000000
RAST 00000038 [8] to 8/16 cols: 1 4097e7bc40000000
RAST 00000022 ["] to 8/17 cols: 1 4097e7bc40000000
RAST 00000027 ['] to 8/18 cols: 1 4097e7bc40bf51d9
RAST 00000020 [ ] to 8/19 cols: 1 4097e7bc40cf37f6
RAST 00000020 [ ] to 8/20 cols: 1 4097e7bc40cb45f1
RAST 00000038 [8] to 8/21 cols: 1 4097e7bc40c441e8
RAST 00000038 [8] to 8/22 cols: 1 4097e7bc40bd32e0
RAST 00000020 [ ] to 8/23 cols: 1 4097e7bc40bc2be1
RAST 00000020 [ ] to 8/24 cols: 1 4097e7bc40c12ce5
RAST 00000020 [ ] to 8/25 cols: 1 4097e7bc40be2be1
RAST 00000060 [`] to 8/26 cols: 1 4097e7bc40c225e7
RAST 00000059 [Y] to 8/27 cols: 1 4097e7bc40c028e4
RAST 00000038 [8] to 8/28 cols: 1 4097e7bc40c337e9
RAST 00000061 [a] to 8/29 cols: 1 4097e7bc40781094
RAST 00000020 [ ] to 8/30 cols: 1 4097e7bc40000100
RAST 00000038 [8] to 8/35 cols: 1 4097e7bc40000000
RAST 00000059 [Y] to 8/36 cols: 1 4097e7bc40000000

so here we see all the same foreground (0x97e7bc), because everything's coming from the bigtext plane, and we write long strings there based off the plane's attributes. so even the spaces have a set fg color. the background, however, is changing, where the "N" in "Notcurses II" comes up into the text. on either side, we've got 0x40000000 (explicit RGB(0,0,0) -- all 0s is "default background color"). within those two sides we have various red-dominated RGBs, exactly like what we see.

so going into rasterization (i.e. the frame post-render), we've got the right values. the next thing to see is whether we're actually emitting the correct escapes. i'll debug on line 8 only.

@dankamongmen
Copy link
Owner Author

heh, just got the exact same behavior in vim (kitty 0.19.3)

2020-12-20-211925_1147x1417_scrot

@dankamongmen
Copy link
Owner Author

It looks like I'm definitely emitting the setbf(0, 0, 0), though only at the beginning of a string of (0, 0, 0)s:

EMITTING SETBF 164/46/194
RAST 00000038 [8] to 8/6 cols: 1 4097e7bc40a42ec2
EMITTING SETBF 2/0/4
RAST 00000038 [8] to 8/7 cols: 1 4097e7bc40020004
EMITTING SETBF 0/0/0
RAST 00000020 [ ] to 8/8 cols: 1 4097e7bc40000000
RAST 00000020 [ ] to 8/10 cols: 1 4097e7bc40000000
RAST 00000060 [`] to 8/11 cols: 1 4097e7bc40000000
RAST 00000022 ["] to 8/12 cols: 1 4097e7bc40000000
EMITTING SETBF 0/2/0
RAST 00000059 [Y] to 8/13 cols: 1 4097e7bc40000200
EMITTING SETBF 86/44/95
RAST 00000062 [b] to 8/14 cols: 1 4097e7bc40562c5f
EMITTING SETBF 205/52/243
RAST 00000062 [b] to 8/15 cols: 1 4097e7bc40cd34f3
EMITTING SETBF 202/61/240
RAST 00000064 [d] to 8/16 cols: 1 4097e7bc40ca3df0
EMITTING SETBF 207/76/246
RAST 00000038 [8] to 8/17 cols: 1 4097e7bc40cf4cf6
EMITTING SETBF 204/61/243
RAST 00000022 ["] to 8/18 cols: 1 4097e7bc40cc3df3
EMITTING SETBF 101/1/125
RAST 00000027 ['] to 8/19 cols: 1 4097e7bc4065017d
EMITTING SETBF 131/24/157
RAST 00000020 [ ] to 8/20 cols: 1 4097e7bc4083189d
EMITTING SETBF 196/40/235
RAST 00000020 [ ] to 8/21 cols: 1 4097e7bc40c428eb
EMITTING SETBF 188/44/224
RAST 00000038 [8] to 8/22 cols: 1 4097e7bc40bc2ce0
EMITTING SETBF 194/41/229
RAST 00000038 [8] to 8/23 cols: 1 4097e7bc40c229e5
EMITTING SETBF 195/36/234
RAST 00000020 [ ] to 8/24 cols: 1 4097e7bc40c324ea
EMITTING SETBF 208/68/246
RAST 00000020 [ ] to 8/25 cols: 1 4097e7bc40d044f6
EMITTING SETBF 190/52/229
RAST 00000020 [ ] to 8/26 cols: 1 4097e7bc40be34e5
EMITTING SETBF 190/85/221
RAST 00000060 [`] to 8/27 cols: 1 4097e7bc40be55dd
EMITTING SETBF 0/2/0
RAST 00000059 [Y] to 8/28 cols: 1 4097e7bc40000200
EMITTING SETBF 0/0/0
RAST 00000038 [8] to 8/29 cols: 1 4097e7bc40000000
RAST 00000061 [a] to 8/30 cols: 1 4097e7bc40000000
RAST 00000020 [ ] to 8/31 cols: 1 4097e7bc40000000
RAST 00000038 [8] to 8/36 cols: 1 4097e7bc40000000

so i definitely don't think bce is relevant here (could be wrong). we're just relying on the background set with setbf to persist from one character to the next. we're emitting a series of spaces, and expect them all to have black background, but instead they're being drawn with default color background (in this case, transparent).

@dankamongmen
Copy link
Owner Author

so yeah, this is looking to me like a kitty issue. let me try to prepare a minimum test case.

@dankamongmen
Copy link
Owner Author

dankamongmen commented Dec 21, 2020

Alright, yeah, I think I've demonstrated that this is a kitty bug. Here's my minimal example:

[schwarzgerat](0) $ cat ../src/poc/kittyzapper.c 
#include <notcurses/direct.h>

int main(void){
  struct ncdirect* n = ncdirect_init(NULL, NULL, 0);
  if(!n){
    return EXIT_FAILURE;
  }
  ncdirect_fg_rgb8(n, 100, 100, 100);
  ncdirect_bg_rgb8(n, 0xff, 0xff, 0xff);
  printf("a");
  ncdirect_fg_rgb8(n, 100, 100, 100);
  ncdirect_bg_rgb8(n, 0, 0, 0);
  printf("b");
  printf(" ");
  printf(" ");
  ncdirect_fg_rgb8(n, 100, 100, 100);
  ncdirect_bg_rgb8(n, 0xff, 0xff, 0xff);
  printf("d");
  printf("\n");
  ncdirect_stop(n);
  return EXIT_SUCCESS;
}
[schwarzgerat](0) $ 

this results in:

2020-12-20-214548_584x272_scrot

when, so far as i can tell, this absolutely ought be pure opaque black backgrounds behind both "b" and the two following spaces.

and in fact...

2020-12-20-214725_682x256_scrot

that's exactly what i get if i use RGB(0, 0, 1) instead of RGB(0, 0, 0). so yeah, this looks pretty clearly to be kitty drawing default color instead of black for RGB(0, 0, 0) drawn with setbf, do you agree @kovidgoyal ?

@dankamongmen
Copy link
Owner Author

"\33[?1h\33(B\33[0m\33[38;2;100;100;100m\33[48;2;255;255;255ma\33[48;2;0;0;0mb \33[48;2;0;0;1mc \33[48;2;255;255;255md\n" is the exact string i'm writing

@dankamongmen
Copy link
Owner Author

So the setbf of \33[48;2;255;255;255m works to set background white, and the setbf of \33[48;2;0;0;1m works to set background 0x000001, but \33[48;2;0;0;0m does not work as expected -- it instead sets the default background color (transparent in this case).

i'm gonna go ahead and file an issue on kitty based on this analysis.

@dankamongmen
Copy link
Owner Author

kovidgoyal/kitty#3185 has been filed.

@dankamongmen
Copy link
Owner Author

Ack, this is apparently intended behavior, see kovidgoyal/kitty@2045055.

I've confirmed that in my config, if I replace any (0, 0, 0) with (0, 0, 1) in term_esc_rgb(), we work as expected in Kitty. That's obviously not a desirable solution, but it confirms our understanding of things, and gives us an out if nothing else flies.

@dankamongmen
Copy link
Owner Author

See kovidgoyal/kitty#3185 for more info, but basically:

  • the only real thing we can do about this is to slightly alter our color if it matches the background color,
  • i'm not sure we can look up the background color (we can set+restore it), and
  • our best indication that this is going to happen is a TERM value beginning with kitty

60a1114a9cc4fb4ee3cb5a02bf998033

so we could theoretically go down this road. one annoyance is that we'd have to somehow backconvert when people use ncplane_at_yx() etc., since the result otherwise won't be what's expected. or maybe we say fuck it and return (0, 0, 1) or whatever on (0, 0, 0). all in all this seems kinda unfortunate.

(kitty has this behavior basically, AFAICT, to allow applications which don't use the default background color to get default background color effects. it's admittedly cool for old tools like alsamixer, but definitely kinda fucks us).

alright. detect kitty based off TERM and expose that knowledge to the rasterizer. first, assume a default background color of 0,0,0, and get things working. later, we'll want to learn/set the actual default background color.

@kovidgoyal
Copy link

Note that the default value of TERM for kitty is xterm-kitty, so
checking for a TERM that starts with kitty is not enough.

dankamongmen added a commit that referenced this issue Dec 22, 2020
dankamongmen added a commit that referenced this issue Dec 22, 2020
Kitty conflates an RGB background specification that aligns
with the default background color with that actual background
color. This can result in translucent background when we're
expecting opaque ones. Detect kitty (strstr check of terminal
name for "kitty"), and if it's active, mark `bg_collides_default`
with the rgb of the default background color. For now, we assume
this to be (0,0,0), but we ought improve it by determining (or
setting, if that's impossible) the precise default bg color.
Closes #1117.
dankamongmen added a commit that referenced this issue Dec 22, 2020
@dankamongmen
Copy link
Owner Author

thansk for the assistance, @kovidgoyal . We're now detecting kitty based off the terminal name (we strstr() for kitty, not the most rigorous thing ever, but it will do). For now we're assuming that the default background color is (0, 0, 0) -- this is unsafe, and we ought either determine or set the default background color (if we set it, be sure to push and then pop the user's configured dynamic colors; see the Kitty extensions). Either way, if bg_collids_default is set by interrogate_terminfo, we check our RGB in term_bg_esc8(), and if they match, we change the blue value by 1.

Verified that this eliminates our large transparent expanses (when using a 0, 0, 0 default background color) in the xray and eagle demos.

Calling this done for now! (Incomplete) fix is present in 2.1.2.

@kovidgoyal
Copy link

You're welcome and just FYI, XTerm copied kitty's color stack this year,
sadly using its own escape codes.
kovidgoyal/kitty@5f8dee8

I just added support for the XTerm escape codes as well, to kitty.

dankamongmen added a commit that referenced this issue Dec 22, 2020
Kitty conflates an RGB background specification that aligns
with the default background color with that actual background
color. This can result in translucent background when we're
expecting opaque ones. Detect kitty (strstr check of terminal
name for "kitty"), and if it's active, mark `bg_collides_default`
with the rgb of the default background color. For now, we assume
this to be (0,0,0), but we ought improve it by determining (or
setting, if that's impossible) the precise default bg color.
Closes #1117.
dankamongmen added a commit that referenced this issue Dec 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants