-
-
Notifications
You must be signed in to change notification settings - Fork 121
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
kitty multiframe with annihilations can't properly rebuild using composing animations #2143
Comments
i think the issue here is just that we're calling |
so we need the reset in |
wait hrmmm if you hit |
we're also seeing the 4th state, "should now see empty square", come back as a full square. i think this is due to the wipe not reaching down far enough. in the second stage we see a lot of:
but the fourth stage is just a lot of:
|
so we're coming in on the wipe and they're showing |
yep, that looks to be the case! |
hrmmm...they're coming into |
and yeah, on exit we've got
|
auxvec incoming is 0, so we're setting it up wrong, or passing the wrong one in. setup is going to take place in wipe and initial blit. |
i think we're failing to set up ... yep, setting up |
wait, we shouldn't be seeing a full square on the right, from what i can tell: emit(notcurses_stdplane(nc), "Ought *still* see 16 *s");
notcurses_debug(nc, stderr);
notcurses_render(nc);
sleep(2);
ncplane_move_yx(n, 0, 7);
emit(notcurses_stdplane(nc), "Full square on right");
notcurses_debug(nc, stderr);
notcurses_render(nc);
sleep(2);
ncplane_move_yx(n, 0, 0);
emit(notcurses_stdplane(nc), "Ought see 16 *s");
notcurses_debug(nc, stderr);
notcurses_render(nc);
sleep(2);
ncplane_move_yx(n, 0, 7);
emit(notcurses_stdplane(nc), "Full square on right");
notcurses_debug(nc, stderr);
notcurses_render(nc);
sleep(2); we're never filling that square. are we seeing a full square on other terminals? |
we are, and we should not be, from what i can tell! |
well wait, there's right above that: if(ncvisual_render(nc, ncv, &vopts) == NULL){
return -1;
} so yeah, we've got it rerendered, but the asterisks are on top. when we move it, we ought get rebuilds across the covered part. but we are not. ahhhhh. |
so rebulding is triggered in |
but we're setting |
nvm, we are coming in on 5... Full square on right
-------------------------- notcurses debug state -----------------------------
************************* 0x4eafe50 pile ****************************
0000 off y: 0 x: 0 geom y: 70 x: 113 curs y: 6 x: 20 0x4e90e50 std
bound 0x4e90e50 ← 0x4eafe60 → (nil) binds 0x4f8d450
0001 off y: 0 x: 7 geom y: 6 x: 6 curs y: 0 x: 0 0x4f8d450 bmap
bound 0x4e90e50 ← 0x4e90ec0 → (nil) binds (nil)
______________________________________________________________________________
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 5
sprite_rebuild:764:rebuilding 9127382 1/1
kitty_rebuild_selfref:914:rematerializing 9127382 at 1/1 (20x10)
CHECING FOR REBUILD STATE: 5
sprite_rebuild:764:rebuilding 9127382 1/2
kitty_rebuild_selfref:914:rematerializing 9127382 at 1/2 (20x10)
CHECING FOR REBUILD STATE: 5
sprite_rebuild:764:rebuilding 9127382 1/3
kitty_rebuild_selfref:914:rematerializing 9127382 at 1/3 (20x10)
CHECING FOR REBUILD STATE: 5
sprite_rebuild:764:rebuilding 9127382 1/4
kitty_rebuild_selfref:914:rematerializing 9127382 at 1/4 (20x10)
CHECING FOR REBUILD STATE: 2
CHECING FOR REBUILD STATE: 2 |
it seems odd that we're coming in in |
but i suspect what's happening here is we're writing all the animations, then resetting the fbuf, then writing the move. we ought be able to check this by looking at our actual output, and seeing whether the reanimations are there. |
hrmmm we do seem to see a lot of animations prior to the presentation:
and they look pretty much correct, too... |
writes 9127382. |
|
so we're definitely sending the reflective compositions....what's odd here is that we're not sending wipes when we move it back over to the left. we should be, assuming we're in OPAQUE, which we ought be following the compositions. and we furthermore have no wipes between the load and the initial compositions. it's almost as if we're loading with transparent regions. but we know(?) we're not, looking at the actual inline load data. right? |
perhaps we're copying over from the old TAM? if we were copying over ANNIHILATED, that would explain this...and would point at not correcting the sprixcell state during rebuild, right? |
yeah, we're copying over annihilated states. that's exactly what's going on. we don't rebuild at the time because we're underneath the asterisks. we move and rebuild, no longer being annihilated, and we pop ANNIHILATED into our state. no, wait... we blit with STATE_ANNIHILATED in the old tam, which we write to the auxvec. our states all become STATE_ANNIHILATED inside the core:
note that we only have rebuilds around the perimeter. we're OPAQUE, so we don't rebuild. in our core, we're all 5s. it seems we ought be writing all AAAAAs here. are we not? we don't seem to be. but either way we're getting ANNIHILATED directly from the blit:
the asterisks then annihilate several, but there is no wiping going on, due to this TAM. and yet we do indeed display the asterisks(!)... we move to the right:
we are rebuilding as expected, and we are emitting the compositions, as demonstrated above. yet we are empty. this realllllly seems to suggest that we're not writing ... wait. maybe we're writing 0 alpha from the that's exactly what's happening. fuck! mystery resolved. how to fix this without flicker? i guess we could write the data as loaded, and then replay the wipes? ugh, that sounds like the only way to do it. so long as it's all done at once, we oughtn't see any flicker; we'll load them all and only then do the presentation. hopefully that works with kitty. if it does, it ought solve this problem. |
so tl;dr:
to prove this, we could do an experiment where we cleared the asterisks instead of moving the square. i expect we would get an empty square. i'm sufficiently certain about the problem that i feel this unnecessary. |
confirmed. i'm now drawing the original load with alphas intact, then writing the nulls out, then displaying. this is working perfectly for the problem frames mentioned. unfortunately, we now have one new problem frame: the frame between these two, where the full square is moved back to the left, is now only showing the square -- i.e., there's no wiping going on when we move back to the left. i've verified that in the logs. so let's get this last bit squeezed out, and we'll be done. |
looking at
|
yep, im rebuild we're reloading 5 from the auxvec. pretty clear. |
so yeah we come in and have ANNIHILATED as our state. auxvec holds the true state of frame 1. we will have a new true state of frame 2. it needs go in the auxvec, and we need to keep ANNIHILATED as our state. then, on the rebuild, we'll pop true frame 2 state from the auxvec. auxvec ought never have ANNIHILATED. |
|
in the selfref model, auxvec only ever serves to retain the old state when a cell is annihilated. they're all allocated at the beginning, because they're small and who cares, but those are dont-cares until an actual wipe happens. so on a reload, we can freely blow them away. they're invalidated. so just keep a running state in the ANNIHILATED stanza matching what you keep below, assigning it to auxvec, for the selfref case only. |
i think i might have it....testing... |
kitty 0.23.1 now runs |
When using the reflexive composition extension to the Kitty graphics protocol, we refer to the previously- blitted image to rebuild cells, and thus don't have to keep a copy of the image ourselves. We just blit null- alpha cells to wipe, and then execute a reflective composition to rebuild. The auxvector is a single word, holding the state we were in before the wipe, since we don't have a copy of the image to look at to determine the state afresh (and caching it is more efficient anyway). Good, good. Except. When we reload the plane, we want to carry over those wipe cells, yes? I.e. if there was a plane above the graphic before, and we replace the graphic, that plane still better be above it. And that means editing the cell out of the new graphic that we blit up, on the fly. Which we were doing. Problem is, if we later need to rebuild that cell, and we reflexively compose using this new image, *we reflexively compose the edited-out cell*, and thus remain wiped (our RGB values get set properly, but we have all 0 alphas). No good! So instead, in KITTY_SELFREF (the most advanced kitty implementation, corresponding to reflexive composition), do a pass at the end and send AAAAA wipes for any ANNIHILATED{_TRANS} sprixcells. We don't present until both have hit (since we're using a new image ID), so there's no flicker, though there is some bandwidth cost. That handles rebuilding. Problem is, if we then need to wipe these same sprixcells *again*, our auxvecs were set to ANNIHILATED{_TRANS}, and thus no wipe takes place. Rather than blindly propagating the auxvec across the frames, properly reset the auxvec according to the new blit. This handles wiping post rebuild, closing the cycle. Kitty 0.22.0+ now runs the bitmapstates PoC perfectly. Closes #2143. woo-hah!
When using the reflexive composition extension to the Kitty graphics protocol, we refer to the previously- blitted image to rebuild cells, and thus don't have to keep a copy of the image ourselves. We just blit null- alpha cells to wipe, and then execute a reflective composition to rebuild. The auxvector is a single word, holding the state we were in before the wipe, since we don't have a copy of the image to look at to determine the state afresh (and caching it is more efficient anyway). Good, good. Except. When we reload the plane, we want to carry over those wipe cells, yes? I.e. if there was a plane above the graphic before, and we replace the graphic, that plane still better be above it. And that means editing the cell out of the new graphic that we blit up, on the fly. Which we were doing. Problem is, if we later need to rebuild that cell, and we reflexively compose using this new image, *we reflexively compose the edited-out cell*, and thus remain wiped (our RGB values get set properly, but we have all 0 alphas). No good! So instead, in KITTY_SELFREF (the most advanced kitty implementation, corresponding to reflexive composition), do a pass at the end and send AAAAA wipes for any ANNIHILATED{_TRANS} sprixcells. We don't present until both have hit (since we're using a new image ID), so there's no flicker, though there is some bandwidth cost. That handles rebuilding. Problem is, if we then need to wipe these same sprixcells *again*, our auxvecs were set to ANNIHILATED{_TRANS}, and thus no wipe takes place. Rather than blindly propagating the auxvec across the frames, properly reset the auxvec according to the new blit. This handles wiping post rebuild, closing the cycle. Kitty 0.22.0+ now runs the bitmapstates PoC perfectly. Closes #2143. woo-hah!
see #2142 for more info. kitty 0.19.3 works fine with
bitmapstates
. current kitty, however, breaks on three states:"full square on right" is empty square on right
"ought see 16*s" empty square below and to right, very off
"full square on right" is once again an empty square
these states involve a move + restore. working fine on old kitty suggests a problem using the animation protocol to restore. it only happens when there's movement, though. i dimly recall seeing something like this before...?
The text was updated successfully, but these errors were encountered: