winsys(redox): per-surface crtc_id tracking with redox_drm_surface_set_crtc

This commit is contained in:
2026-07-26 08:42:08 +09:00
parent b0410e5665
commit 10bdab675c
3 changed files with 71 additions and 50 deletions
@@ -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
@@ -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
@@ -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 *