mesa/redox: port the Redox GPU winsys + EGL/pipe-loader to Mesa 26.1.4

Make the vendored Red Bear Redox GPU port compile against Mesa 26.1.4:

- winsys meson.build: fix doubled 'drm/' source paths (meson.build already sits
  in drm/); drop invalid declare_dependency(sources: [static_library]).
- redox_drm_winsys.c: adapt the custom swrast pipe_screen to 26.1.4 — the
  never-mainline pipe_screen_ops indirection is gone (wire get_name/get_vendor/
  get_device_vendor/get_screen_fd/is_format_supported/resource_create/destroy/
  flush_frontbuffer/fence_reference/fence_finish directly on pipe_screen) and
  per-cap get_param() is replaced by u_init_pipe_screen_caps(). The context-level
  callbacks (resource_map/unmap, create_surface/destroy, fence_create/submit/
  signalled) stay defined for the future full HW screen but leave the vtable.
  Drop the dead rws->base.base.screen tracking (sw_winsys has no such member).
- redox_drm_surface.h: forward-declare struct redox_drm_winsys so the
  flip_to_crtc prototype matches its definition (was a prototype-scoped tag ->
  'conflicting types'). redox_drm_bo.c: PIPE_TEXTURE_ARRAY -> PIPE_TEXTURE_2D_ARRAY,
  util/u_format.h -> util/format/u_format.h.
- pipe_loader_redox.c: include <xf86drm.h>; store the drm_driver_descriptor on
  the redux device (base pipe_loader_device has no 'dd'); drop the bogus cast to
  the private pipe_loader_drm_device.
- platform_redox.c: define redox_flush_front_buffer (was undefined
  dri2_flush_front_buffer). egl_dri2.h: rename the surfaceless/device dri_image
  front/back to image_front/image_back to avoid colliding with the wayland/drm
  color-buffer 'back' when all platforms are enabled.

Result: the entire Mesa tree (iris/radeonsi/ANV + softpipe/llvmpipe/virgl/lavapipe)
compiles for x86_64-unknown-redox.
This commit is contained in:
2026-07-31 18:22:09 +03:00
parent e35feb1dbe
commit 72e686f120
8 changed files with 73 additions and 180 deletions
@@ -385,9 +385,11 @@ struct dri2_egl_surface {
uint32_t gralloc_usage;
#endif
/* surfaceless and device */
struct dri_image *front;
struct dri_image *back;
/* surfaceless and device (renamed from front/back to avoid colliding with
* the wayland/drm color-buffer 'back' member when Red Bear enables the
* wayland, drm and surfaceless/device/redox platforms together). */
struct dri_image *image_front;
struct dri_image *image_back;
enum pipe_format visual;
int out_fence_fd;
@@ -38,14 +38,14 @@ redox_alloc_image(struct dri2_egl_display *dri2_dpy,
static void
redox_free_images(struct dri2_egl_surface *dri2_surf)
{
if (dri2_surf->front) {
dri2_destroy_image(dri2_surf->front);
dri2_surf->front = NULL;
if (dri2_surf->image_front) {
dri2_destroy_image(dri2_surf->image_front);
dri2_surf->image_front = NULL;
}
if (dri2_surf->back) {
dri2_destroy_image(dri2_surf->back);
dri2_surf->back = NULL;
if (dri2_surf->image_back) {
dri2_destroy_image(dri2_surf->image_back);
dri2_surf->image_back = NULL;
}
free(dri2_surf->swrast_device_buffer);
@@ -66,17 +66,17 @@ redox_image_get_buffers(struct dri_drawable *driDrawable, unsigned int format,
buffers->back = NULL;
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
if (!dri2_surf->front)
dri2_surf->front = redox_alloc_image(dri2_dpy, dri2_surf);
if (!dri2_surf->image_front)
dri2_surf->image_front = redox_alloc_image(dri2_dpy, dri2_surf);
buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
buffers->front = dri2_surf->front;
buffers->front = dri2_surf->image_front;
}
if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
if (!dri2_surf->back)
dri2_surf->back = redox_alloc_image(dri2_dpy, dri2_surf);
if (!dri2_surf->image_back)
dri2_surf->image_back = redox_alloc_image(dri2_dpy, dri2_surf);
buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
buffers->back = dri2_surf->back;
buffers->back = dri2_surf->image_back;
}
return 1;
@@ -95,10 +95,17 @@ redox_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
}
}
static void
redox_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
{
(void) driDrawable;
(void) loaderPrivate;
}
static const __DRIimageLoaderExtension redox_image_loader_extension = {
.base = {__DRI_IMAGE_LOADER, 2},
.getBuffers = redox_image_get_buffers,
.flushFrontBuffer = dri2_flush_front_buffer,
.flushFrontBuffer = redox_flush_front_buffer,
.getCapability = redox_get_capability,
};
@@ -25,6 +25,8 @@
#include <string.h>
#include <unistd.h>
#include <xf86drm.h>
#include "loader.h"
#include "pipe_loader_priv.h"
#include "target-helpers/drm_helper_public.h"
@@ -40,6 +42,7 @@
struct pipe_loader_redux_device {
struct pipe_loader_device base;
int fd;
const struct drm_driver_descriptor *dd;
};
#define pipe_loader_redux_device(dev) ((struct pipe_loader_redux_device *)dev)
@@ -76,7 +79,7 @@ pipe_loader_redux_probe_nodup(struct pipe_loader_device **dev, int fd)
dd = get_driver_descriptor(driver_name);
if (!dd)
goto fail;
rdev->base.dd = dd;
rdev->dd = dd;
*dev = &rdev->base;
return true;
@@ -134,31 +137,28 @@ pipe_loader_redux_create_screen(struct pipe_loader_device *dev,
const struct pipe_screen_config *config, bool sw_vk)
{
struct pipe_loader_redux_device *rdev = pipe_loader_redux_device(dev);
struct pipe_loader_drm_device *ddev = (struct pipe_loader_drm_device *)dev;
int ret_fd = rdev->fd;
struct pipe_screen *screen;
(void) sw_vk;
if (!ddev->dd)
if (!rdev->dd)
return NULL;
screen = ddev->dd->create_screen(ret_fd, config);
if (screen)
((struct pipe_loader_drm_device *)dev)->fd = ret_fd;
screen = rdev->dd->create_screen(ret_fd, config);
return screen;
}
static const struct driOptionDescription *
pipe_loader_redux_get_driconf(struct pipe_loader_device *dev, unsigned *count)
{
struct pipe_loader_drm_device *ddev = (struct pipe_loader_drm_device *)dev;
if (!ddev->dd) {
struct pipe_loader_redux_device *rdev = pipe_loader_redux_device(dev);
if (!rdev->dd) {
*count = 0;
return NULL;
}
*count = ddev->dd->driconf_count;
return ddev->dd->driconf;
*count = rdev->dd->driconf_count;
return rdev->dd->driconf;
}
static void
@@ -24,16 +24,16 @@
libredoxwinsys = static_library(
'redoxwinsys',
files(
'drm/redox_drm_bo.c',
'drm/redox_drm_bo.h',
'drm/redox_drm_cs.c',
'drm/redox_drm_cs.h',
'drm/redox_drm_surface.c',
'drm/redox_drm_surface.h',
'drm/redox_drm_fence.c',
'drm/redox_drm_fence.h',
'drm/redox_drm_winsys.c',
'drm/redox_drm_winsys.h',
'redox_drm_bo.c',
'redox_drm_bo.h',
'redox_drm_cs.c',
'redox_drm_cs.h',
'redox_drm_surface.c',
'redox_drm_surface.h',
'redox_drm_fence.c',
'redox_drm_fence.h',
'redox_drm_winsys.c',
'redox_drm_winsys.h',
),
include_directories : [
inc_gallium, inc_gallium_aux, inc_include, inc_src,
@@ -46,5 +46,4 @@ libredoxwinsys = static_library(
redoxwinsys_link = declare_dependency(
link_with : [libredoxwinsys],
sources : [libredoxwinsys],
)
@@ -21,7 +21,7 @@
#include <xf86drm.h>
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/format/u_format.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_debug.h"
@@ -185,7 +185,7 @@ redox_drm_bo_create(struct redox_drm_winsys *rws,
templat->target != PIPE_TEXTURE_2D &&
templat->target != PIPE_TEXTURE_3D &&
templat->target != PIPE_TEXTURE_CUBE &&
templat->target != PIPE_TEXTURE_ARRAY) {
templat->target != PIPE_TEXTURE_2D_ARRAY) {
debug_printf("redox: unsupported target %d\n", templat->target);
return NULL;
}
@@ -17,6 +17,12 @@
#include "pipe/p_state.h"
/* Forward declaration so the redox_drm_bo_flip_to_crtc() prototype below refers
* to the file-scope struct (defined in redox_drm_winsys.h) rather than an
* incomplete prototype-scoped tag — otherwise the definition in
* redox_drm_surface.c (which sees the full struct) is a "conflicting type". */
struct redox_drm_winsys;
struct redox_drm_surface {
struct pipe_surface base;
/* The GEM handle that backs the surface's primary buffer. */
@@ -66,122 +66,6 @@ redox_get_screen_fd(struct pipe_screen *screen)
return (void *)(intptr_t)rws->fd;
}
static int
redox_get_param(struct pipe_screen *screen, enum pipe_cap param)
{
(void) screen;
switch (param) {
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return 14;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return 8;
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return 14;
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
return 2048;
case PIPE_CAP_MAX_RENDER_TARGETS:
return 8;
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
return 1;
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
return 32;
case PIPE_CAP_MAX_SAMPLERS:
return 16;
case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
return 65536;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 256;
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
return 16;
case PIPE_CAP_MAX_VIEWPORTS:
return 16;
case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
return 1024;
case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
return 16384;
case PIPE_CAP_MAX_VERTEX_STREAMS:
return 4;
case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
return 2048;
case PIPE_CAP_MAX_TEXTURE_UPLOAD_MEMORY_BUDGET:
return 64 * 1024 * 1024;
case PIPE_CAP_MAX_VARYINGS:
return 32;
case PIPE_CAP_NPOT_TEXTURES:
return 1;
case PIPE_CAP_SHAREABLE_SHADERS:
return 1;
case PIPE_CAP_DEPTH_CLIP_DISABLE:
return 1;
case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE:
return 1;
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
return 1;
case PIPE_CAP_SEAMLESS_CUBE_MAP:
return 1;
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
return 1;
case PIPE_CAP_INDEP_BLEND_ENABLE:
return 1;
case PIPE_CAP_INDEP_BLEND_FUNC:
return 1;
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 1;
case PIPE_CAP_PRIMITIVE_RESTART:
return 1;
case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:
return 1;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_TEXTURE_SWIZZLE:
return 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_QUERY_TIME_ELAPSED:
return 1;
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
return 1;
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
return 0;
case PIPE_CAP_VS_INSTANCEID:
case PIPE_CAP_VS_LAYER_VIEWPORT_SELECT:
case PIPE_CAP_VS_WINDOW_SPACE_POSITION:
case PIPE_CAP_VS_LAYER:
return 1;
case PIPE_CAP_TGSI_INSTANCEID:
case PIPE_CAP_TGSI_VS_LAYER:
return 1;
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
case PIPE_CAP_FRAGMENT_DEPTH_CLAMPED:
return 0;
case PIPE_CAP_SHADER_STENCIL_EXPORT:
case PIPE_CAP_CONDITIONAL_RENDER:
case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
case PIPE_CAP_TEXTURE_BARRIER:
return 1;
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
return 0;
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
case PIPE_CAP_VERTEX_COLOR_CLAMPED:
return 1;
case PIPE_CAP_USER_CONSTANT_BUFFERS:
case PIPE_CAP_USER_VERTEX_BUFFERS:
return 1;
default:
return 0;
}
}
static bool
redox_is_format_supported(struct pipe_screen *screen,
enum pipe_format format,
@@ -369,27 +253,6 @@ redox_fence_signalled(struct pipe_screen *screen,
return redox_drm_fence_signalled(fence);
}
const struct pipe_screen_ops redox_drm_screen_ops = {
.get_name = redox_get_name,
.get_vendor = redox_get_vendor,
.get_device_vendor = redox_get_device_vendor,
.get_param = redox_get_param,
.get_screen_fd = redox_get_screen_fd,
.is_format_supported = redox_is_format_supported,
.resource_create = redox_resource_create,
.resource_destroy = redox_resource_destroy,
.resource_map = redox_resource_map,
.resource_unmap = redox_resource_unmap,
.create_surface = redox_create_surface,
.surface_destroy = redox_surface_destroy,
.flush_frontbuffer = redox_flush_frontbuffer,
.fence_create = redox_fence_create,
.fence_submit = redox_fence_submit,
.fence_finish = redox_fence_finish,
.fence_reference = redox_fence_reference,
.fence_signalled = redox_fence_signalled,
};
/* ---- winsys lifecycle ------------------------------------------------- */
bool
@@ -472,7 +335,6 @@ redox_drm_create_screen(int fd, const struct pipe_screen_config *config)
return NULL;
}
rws->base.base.screen = NULL; /* set below */
rws->fd = fd;
rws->fd_name = fd_name;
@@ -489,8 +351,25 @@ redox_drm_create_screen(int fd, const struct pipe_screen_config *config)
return NULL;
}
screen->winsys_priv = rws;
screen->ops = &redox_drm_screen_ops;
rws->base.base.screen = screen;
/* Mesa 26.1.4 dropped the (never-mainline) pipe_screen_ops indirection:
* pipe_screen exposes its callbacks as direct members, and per-cap
* get_param() is replaced by the pipe_caps struct filled at init. Wire the
* screen-level callbacks directly and populate caps with the software
* defaults (this is a swrast-only screen). The resource_map/unmap,
* create_surface/surface_destroy and fence_create/submit/signalled callbacks
* are pipe_context-level in 26.1.4, not pipe_screen — they remain defined for
* the future full HW screen but are not part of the screen vtable. */
screen->get_name = redox_get_name;
screen->get_vendor = redox_get_vendor;
screen->get_device_vendor = redox_get_device_vendor;
screen->get_screen_fd = redox_get_screen_fd;
screen->is_format_supported = redox_is_format_supported;
screen->resource_create = redox_resource_create;
screen->resource_destroy = redox_resource_destroy;
screen->flush_frontbuffer = redox_flush_frontbuffer;
screen->fence_reference = redox_fence_reference;
screen->fence_finish = redox_fence_finish;
u_init_pipe_screen_caps(screen, 0);
if (!screen_init_common(screen, config)) {
screen_destroy(screen);
@@ -9,7 +9,7 @@
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
#include "winsys/sw_winsys.h"
#include "frontend/sw_winsys.h"
#include "c11/threads.h" /* mtx_t for batch_pool_mutex */