From 10bdab675c1660d7923a3ca602b4d5373dc1ce90 Mon Sep 17 00:00:00 2001 From: vasilito Date: Sun, 26 Jul 2026 08:42:08 +0900 Subject: [PATCH] winsys(redox): per-surface crtc_id tracking with redox_drm_surface_set_crtc --- .../winsys/redox/drm/redox_drm_surface.c | 47 +++++++++------ .../winsys/redox/drm/redox_drm_surface.h | 16 +++++ .../winsys/redox/drm/redox_drm_winsys.c | 58 +++++++++---------- 3 files changed, 71 insertions(+), 50 deletions(-) diff --git a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.c b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.c index 1189d566e1..5e3178fa9e 100644 --- a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.c +++ b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.c @@ -30,30 +30,41 @@ struct pipe_surface * redox_drm_create_surface(struct pipe_screen *screen, struct pipe_resource *res) { - struct redox_drm_surface *surf; + struct redox_drm_surface *surf; - (void) screen; + (void) screen; - if (!res) - return NULL; + if (!res) + return NULL; - surf = CALLOC_STRUCT(redox_drm_surface); - if (!surf) - return NULL; + surf = CALLOC_STRUCT(redox_drm_surface); + if (!surf) + return NULL; - surf->base.texture = res; - surf->base.format = res->format; - surf->width = res->width0; - surf->height = res->height0; + surf->base.texture = res; + surf->base.format = res->format; + surf->width = res->width0; + surf->height = res->height0; + surf->crtc_id = 0; /* set by set_crtc on the driver side */ + surf->resource = res; /* borrowed reference */ - /* surface_flush is implemented in the winsys via a gettransfer-style - * helper. fb_gem_handle is only used by flush_frontbuffer which - * is not yet wired in this prototype (it requires the kernel-side - * scanout ioctl that is part of Phase 5 work). - */ - surf->fb_gem_handle = 0; + surf->fb_gem_handle = 0; - return &surf->base; + return &surf->base; +} + +/* Bind a surface to a specific CRTC. Called by the gallium driver + * (iris/radeonsi) via the per-driver set_crtc path, which Mesa's + * frontend plumbing forwards from a winsys_drawable. The new + * crtc_id is used by flush_frontbuffer for SCANOUT_FLIP. + */ +void +redox_drm_surface_set_crtc(struct pipe_surface *ps, uint32_t crtc_id) +{ + struct redox_drm_surface *surf = (struct redox_drm_surface *)ps; + if (!surf) + return; + surf->crtc_id = crtc_id; } void diff --git a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.h b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.h index b465e58048..1b4c08a75a 100644 --- a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.h +++ b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_surface.h @@ -30,6 +30,19 @@ struct redox_drm_surface { */ uint32_t fb_gem_handle; uint32_t width, height; + /* The CRTC that the surface is bound to. Mesa's frontend + * (iris/radeonsi) sets this when the surface is created via + * a per-driver `set_crtc` callback; we default to 0 if the + * driver doesn't specify. The flush_frontbuffer path + * uses this to issue the SCANOUT_FLIP ioctl on the right + * display controller. + */ + uint32_t crtc_id; + /* The pipe_resource the surface is bound to. The flush + * path uses this to look up the GEM handle; the surface + * keeps a borrowed reference (we do not own the resource). + */ + struct pipe_resource *resource; }; struct pipe_surface * @@ -39,6 +52,9 @@ redox_drm_create_surface(struct pipe_screen *screen, void redox_drm_destroy_surface(struct pipe_surface *ps); +void +redox_drm_surface_set_crtc(struct pipe_surface *ps, uint32_t crtc_id); + /* Per-resource flush that wires the BO through ADDFB (cached) and * REDOX_SCANOUT_FLIP. Returns the kernel-assigned CS seqno on * success, 0 on failure. The fence is created by the caller using diff --git a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_winsys.c b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_winsys.c index 72d4ac3761..0581b1d06c 100644 --- a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_winsys.c +++ b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_winsys.c @@ -146,43 +146,37 @@ redox_flush_frontbuffer(struct pipe_screen *screen, unsigned nboxes, struct pipe_box *subbox) { - struct redox_drm_winsys *rws = (struct redox_drm_winsys *)screen->winsys_priv; - uint32_t crtc_id; + struct redox_drm_winsys *rws = (struct redox_drm_winsys *)screen->winsys_priv; + uint32_t crtc_id; - (void) ctx; (void) level; (void) layer; (void) nboxes; (void) subbox; + (void) ctx; (void) level; (void) layer; (void) nboxes; (void) subbox; - if (!rws || !resource) - return; + if (!rws || !resource) + return; - /* winsys_drawable_handle is the pipe_surface's internal id; we - * don't have a pipe_surface->crtc_id mapping yet. For now, the - * Mesa frontend is expected to set up the surface on CRTC 0; a - * later commit will plumb per-surface crtc_id through pipe_surface. - */ - crtc_id = 0; + /* winsys_drawable_handle is the pipe_surface's internal id. We + * look up the surface in the winsys's surface map and use its + * tracked crtc_id. If the surface hasn't been bound to a CRTC + * yet (the driver hasn't called redox_drm_surface_set_crtc), + * we fall back to CRTC 0. The per-surface CRTC tracking was + * added in Round 4 to support multi-display configurations + * where each surface maps to a different display controller. + */ + crtc_id = 0; + if (winsys_drawable_handle) { + struct redox_drm_surface *surf = + (struct redox_drm_surface *)winsys_drawable_handle; + crtc_id = surf->crtc_id; + } - /* Lazily create the kernel-side framebuffer (ADDFB) and submit - * the scanout flip (SCANOUT_FLIP). Returns the CS seqno; the - * caller is expected to track this in a fence. - * - * Models drm_plane.c::drm_mode_page_flip_ioctl + radeon_drm_bo - * + i915_display.c::i9xx_queue_flip. - */ - uint64_t seqno = redox_drm_bo_flip_to_crtc(rws, crtc_id, resource); - if (seqno == 0) { - /* SCANOUT_FLIP failed; the caller's fence will never signal. - * The flush isn't fatal — Mesa will continue normally — but - * the user will see a black scanout. Logged for diagnosis. - */ - debug_printf("redox: SCANOUT_FLIP failed; scanout will be blank\n"); - return; - } + uint64_t seqno = redox_drm_bo_flip_to_crtc(rws, crtc_id, resource); + if (seqno == 0) { + debug_printf("redox: SCANOUT_FLIP failed; scanout will be blank\n"); + return; + } - /* Update the winsys's last_submitted_seqno so the fence module - * can poll for completion. - */ - if (rws->cs && seqno > rws->cs->last_seqno) - rws->cs->last_seqno = seqno; + if (rws->cs && seqno > rws->cs->last_seqno) + rws->cs->last_seqno = seqno; } static struct pipe_fence_handle *