From b5a2667f6c94d5a275251bf6cc359480100a651c Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sun, 4 Sep 2022 23:13:36 -0700 Subject: til: fixup til_fb_fragment_t.texture fragmenting Until now when fragmenting with a texture present the texture pointer was simply copied through to the new logical fragment. The problem with that is when sampling pixels from the texture in a nested frame scenario, the locations didn't align with the placement of the logical fragment. With this change when the incoming fragment has a texture, the output fragment gets some uninitialized memory attached in the outgoing fragment's texture pointer. Then the fragmenter is expected to do the same populating of res_fragment->texture it already did for res_fragment, just relative to fragment->texture->{buf,stride,pitch} etc. It's a bit hairy/janky because til_fb_fragment_t.texture is just a pointer to another til_fb_fragment_t. So the ephemeral/logical fragments fragmenting/tiling produces which tend to just be sitting on the stack need to get another til_fb_fragment_t instance somewhere and made available at the ephemeral til_fb_fragment_t's .texture member. We don't want to be allocating and freeing these things constantly, so for now I'm just ad-hoc stowing the pointer of an adjacent on-stack texture fragment in the .texture member when the incoming fragment has a texture. But this is gross because the rest of the fragment contents don't get initialized _at_all_, and currently if the incoming fragment has no texture the res_fragment->texture member isn't even initialized. The fragmenters aren't really supposed to be expecting anything sensible in *res_fragment, but now we're making use of res_fragment->texture *if* fragment->texture is set. This is just gross. So there's a bunch of asserts sprinkled around to help police this fragility for now, but if someone writes new fragmenters there's a good chance this will trip them up. --- src/modules/checkers/checkers.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'src/modules/checkers') diff --git a/src/modules/checkers/checkers.c b/src/modules/checkers/checkers.c index 32b5aa3..9dcc05c 100644 --- a/src/modules/checkers/checkers.c +++ b/src/modules/checkers/checkers.c @@ -146,6 +146,9 @@ int checkers_fragment_tile_single(const til_fb_fragment_t *fragment, unsigned ti unsigned tiled_w = w * tile_size, tiled_h = h * tile_size; unsigned x, y, xoff, yoff, xshift = 0, yshift = 0; + assert(fragment); + assert(res_fragment); + /* Detect the need for fractional tiles on both axis and shift the fragments * to keep the overall checkered output centered. This complicates res_fragment.{x,y,width,height} * calculations for the peripheral checker tiles as those must clip when shifted. @@ -171,8 +174,32 @@ int checkers_fragment_tile_single(const til_fb_fragment_t *fragment, unsigned ti xoff = x * tile_size; yoff = y * tile_size; + if (fragment->texture) { + assert(res_fragment->texture); + assert(fragment->frame_width == fragment->texture->frame_width); + assert(fragment->frame_height == fragment->texture->frame_height); + assert(fragment->width == fragment->texture->width); + assert(fragment->height == fragment->texture->height); + assert(fragment->x == fragment->texture->x); + assert(fragment->y == fragment->texture->y); + + *(res_fragment->texture) = (til_fb_fragment_t){ + .buf = fragment->texture->buf + (yoff * fragment->texture->pitch) - (y ? (yshift * fragment->texture->pitch) : 0) + (xoff - (x ? xshift : 0)), + .width = MIN(fragment->width - (xoff - xshift), x ? tile_size : (tile_size - xshift)), + .height = MIN(fragment->height - (yoff - yshift), y ? tile_size : (tile_size - yshift)), + .x = x ? 0 : xshift, + .y = y ? 0 : yshift, + .frame_width = tile_size, + .frame_height = tile_size, + .stride = fragment->texture->stride + (fragment->width - MIN(fragment->width - (xoff - xshift), x ? tile_size : (tile_size - xshift))), + .pitch = fragment->texture->pitch, + .cleared = fragment->texture->cleared, + }; + } + *res_fragment = (til_fb_fragment_t){ - .texture = fragment->texture, + .texture = fragment->texture ? res_fragment->texture : NULL, + /* TODO: copy pasta! */ .buf = fragment->buf + (yoff * fragment->pitch) - (y ? (yshift * fragment->pitch) : 0) + (xoff - (x ? xshift : 0)), .width = MIN(fragment->width - (xoff - xshift), x ? tile_size : (tile_size - xshift)), .height = MIN(fragment->height - (yoff - yshift), y ? tile_size : (tile_size - yshift)), -- cgit v1.2.1