From 58d30fed2f34112c577ebb132afcfd609944d04d Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 3 Mar 2025 10:27:43 -0600 Subject: [PATCH] zink: Use pipe_box helpers for damage calculations The old code got the accumulation a bit wrong. For one thing, it always accumulates with whatever was there instead of resetting to empty each time. For another, it sets with with y and height with x when it writes back to the resource. This is also all too complicated because it converts between pipe_box, u_rect, and VkRect2D on every iteration. Instead, there are helpers in util/box.h which will do most of this work for us and they're correct. Let's just use them to get rid of the bugs and make everything simpler and more obvious at the same time. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12194 Fixes: 3d38c9597ff3 ("zink: hook up KHR_partial_update") Reviewed-by: Kenneth Graunke Part-of: (cherry picked from commit 11939a70df887b68df1afe7393d35f7774c13fab) --- .pick_status.json | 2 +- src/gallium/drivers/zink/zink_screen.c | 49 ++++++++++++++------------ 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 82d89f11505..3a6348c9dc4 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -5104,7 +5104,7 @@ "description": "zink: Use pipe_box helpers for damage calculations", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "3d38c9597ff3b687026fa4c664f8b4aa20b97f53", "notes": null diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index ac9e726630c..bc0cc58d2b9 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1469,30 +1469,35 @@ zink_set_damage_region(struct pipe_screen *pscreen, struct pipe_resource *pres, { struct zink_resource *res = zink_resource(pres); - for (unsigned i = 0; i < nrects; i++) { - int y = pres->height0 - rects[i].y - rects[i].height; - /* convert back to coord-based rects to use coordinate calcs */ - struct u_rect currect = { - .x0 = res->damage.offset.x, - .y0 = res->damage.offset.y, - .x1 = res->damage.offset.x + res->damage.extent.width, - .y1 = res->damage.offset.y + res->damage.extent.height, - }; - struct u_rect newrect = { - .x0 = rects[i].x, - .y0 = y, - .x1 = rects[i].x + rects[i].width, - .y1 = y + rects[i].height, - }; - struct u_rect u; - u_rect_union(&u, &currect, &newrect); - res->damage.extent.width = u.y1 - u.y0; - res->damage.extent.height = u.x1 - u.x0; - res->damage.offset.x = u.x0; - res->damage.offset.y = u.y0; + if (nrects == 0) { + res->use_damage = false; + return; } - res->use_damage = nrects > 0; + struct pipe_box damage = rects[0]; + for (unsigned i = 1; i < nrects; i++) + u_box_union_2d(&damage, &damage, &rects[i]); + + /* The damage we get from EGL uses a lower-left origin but Vulkan uses + * upper-left so we need to flip it. + */ + damage.y = pres->height0 - (damage.y + damage.height); + + /* Intersect with the area of the resource */ + struct pipe_box res_area; + u_box_origin_2d(pres->width0, pres->height0, &res_area); + u_box_intersect_2d(&damage, &damage, &res_area); + + res->damage = (VkRect2D) { + .offset.x = damage.x, + .offset.y = damage.y, + .extent.width = damage.width, + .extent.height = damage.height, + }; + res->use_damage = damage.x != 0 || + damage.y != 0 || + damage.width != res->base.b.width0 || + damage.height != res->base.b.height0; } static void