feat: add Mesa EGL hardware GPU probe with virgl support
P5: Enable PRIME export for GBM dumb buffers so virgl can import scanout\nbuffers via fd-to-handle. P6: Add redox_probe_device_hw() that opens /scheme/drm/card0, resolves the\nDRI driver via PCI ID lookup (loader_get_driver_for_fd), and initializes the\nhardware path through dri2_load_driver_dri3 with __DRIimageLoaderExtension.\nIncludes fprintf(stderr) debug logging tagged [REDOX-EGL] for tracing the\nHW init sequence. Falls back to software rendering if HW probe fails.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
|
||||
index 91fcc1fd2..af26e20d6 100644
|
||||
--- a/src/gbm/backends/dri/gbm_dri.c
|
||||
+++ b/src/gbm/backends/dri/gbm_dri.c
|
||||
@@ -578,8 +578,11 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo)
|
||||
struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
|
||||
int fd;
|
||||
|
||||
- if (bo->image == NULL)
|
||||
- return -1;
|
||||
+ if (bo->image == NULL) {
|
||||
+ if (drmPrimeHandleToFD(dri->base.v0.fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd) != 0)
|
||||
+ return -1;
|
||||
+ return fd;
|
||||
+ }
|
||||
|
||||
if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd))
|
||||
return -1;
|
||||
@@ -663,8 +666,11 @@ gbm_dri_bo_get_plane_fd(struct gbm_bo *_bo, int plane)
|
||||
|
||||
/* dumb BOs can only utilize non-planar formats */
|
||||
if (!bo->image) {
|
||||
- errno = EINVAL;
|
||||
- return -1;
|
||||
+ if (plane != 0) {
|
||||
+ errno = EINVAL;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return gbm_dri_bo_get_fd(_bo);
|
||||
}
|
||||
|
||||
if (plane >= get_number_planes(dri, bo->image)) {
|
||||
@@ -0,0 +1,240 @@
|
||||
diff --git a/src/egl/drivers/dri2/platform_redox.c b/src/egl/drivers/dri2/platform_redox.c
|
||||
index d6ceb1107..03d8e4c21 100644
|
||||
--- a/src/egl/drivers/dri2/platform_redox.c
|
||||
+++ b/src/egl/drivers/dri2/platform_redox.c
|
||||
@@ -62,10 +62,46 @@ redox_free_images(struct dri2_egl_surface *dri2_surf)
|
||||
dri2_surf->front = NULL;
|
||||
}
|
||||
|
||||
+ if (dri2_surf->dri_image_back) {
|
||||
+ dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
|
||||
+ dri2_surf->dri_image_back = NULL;
|
||||
+ }
|
||||
+
|
||||
free(dri2_surf->swrast_device_buffer);
|
||||
dri2_surf->swrast_device_buffer = NULL;
|
||||
}
|
||||
|
||||
+static int
|
||||
+redox_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format,
|
||||
+ uint32_t *stamp, void *loaderPrivate,
|
||||
+ uint32_t buffer_mask,
|
||||
+ struct __DRIimageList *buffers)
|
||||
+{
|
||||
+ struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
+ struct dri2_egl_display *dri2_dpy =
|
||||
+ dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
+
|
||||
+ buffers->image_mask = 0;
|
||||
+ buffers->front = NULL;
|
||||
+ buffers->back = NULL;
|
||||
+
|
||||
+ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
|
||||
+ if (!dri2_surf->front)
|
||||
+ dri2_surf->front = redox_alloc_image(dri2_dpy, dri2_surf);
|
||||
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
|
||||
+ buffers->front = dri2_surf->front;
|
||||
+ }
|
||||
+
|
||||
+ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
|
||||
+ if (!dri2_surf->dri_image_back)
|
||||
+ dri2_surf->dri_image_back = redox_alloc_image(dri2_dpy, dri2_surf);
|
||||
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
|
||||
+ buffers->back = dri2_surf->dri_image_back;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static EGLBoolean
|
||||
redox_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
|
||||
{
|
||||
@@ -220,6 +256,10 @@ dri2_redox_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
goto cleanup_surface;
|
||||
}
|
||||
|
||||
+ dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config);
|
||||
+ if (dri2_surf->visual == __DRI_IMAGE_FORMAT_NONE)
|
||||
+ goto cleanup_surface;
|
||||
+
|
||||
if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) {
|
||||
goto cleanup_surface;
|
||||
}
|
||||
@@ -366,6 +406,27 @@ static const __DRIkopperLoaderExtension kopper_loader_extension = {
|
||||
.SetSurfaceCreateInfo = NULL,
|
||||
};
|
||||
|
||||
+static void
|
||||
+redox_hw_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static const __DRIimageLoaderExtension redox_image_loader_extension = {
|
||||
+ .base = {__DRI_IMAGE_LOADER, 2},
|
||||
+ .getBuffers = redox_image_get_buffers,
|
||||
+ .flushFrontBuffer = redox_hw_flush_front_buffer,
|
||||
+ .getCapability = redox_get_capability,
|
||||
+};
|
||||
+
|
||||
+static const __DRIextension *redox_hw_loader_extensions[] = {
|
||||
+ &redox_image_loader_extension.base,
|
||||
+ &image_lookup_extension.base,
|
||||
+ &use_invalidate.base,
|
||||
+ &background_callable_extension.base,
|
||||
+ &kopper_loader_extension.base,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static const __DRIswrastLoaderExtension swrast_loader_extension = {
|
||||
.base = {__DRI_SWRAST_LOADER, 1},
|
||||
.getDrawableInfo = redox_swrast_get_drawable_info,
|
||||
@@ -381,6 +442,92 @@ static const __DRIextension *redox_swrast_loader_extensions[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
+static bool
|
||||
+redox_probe_device_hw(_EGLDisplay *disp)
|
||||
+{
|
||||
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
+ struct _egl_device *device;
|
||||
+ int fd = -1;
|
||||
+
|
||||
+ /* Try to open a DRM device on Redox first, then the conventional path. */
|
||||
+ const char *drm_paths[] = {
|
||||
+ "/scheme/drm/card0",
|
||||
+ "/dev/dri/card0",
|
||||
+ NULL,
|
||||
+ };
|
||||
+
|
||||
+ fprintf(stderr, "[REDOX-EGL] redox_probe_device_hw: starting\n");
|
||||
+
|
||||
+ for (int i = 0; drm_paths[i]; i++) {
|
||||
+ fd = open(drm_paths[i], O_RDWR | O_CLOEXEC);
|
||||
+ fprintf(stderr, "[REDOX-EGL] open(%s) = %d\n", drm_paths[i], fd);
|
||||
+ if (fd >= 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "[REDOX-EGL] no DRM device found\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Resolve the DRI driver from the DRM fd via PCI ID lookup. */
|
||||
+ char *driver_name = loader_get_driver_for_fd(fd);
|
||||
+ fprintf(stderr, "[REDOX-EGL] loader_get_driver_for_fd returned: %s\n",
|
||||
+ driver_name ? driver_name : "(null)");
|
||||
+ if (!driver_name) {
|
||||
+ close(fd);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(driver_name, "swrast") == 0 ||
|
||||
+ strcmp(driver_name, "kms_swrast") == 0) {
|
||||
+ fprintf(stderr, "[REDOX-EGL] driver is swrast/kms_swrast, skipping HW path\n");
|
||||
+ free(driver_name);
|
||||
+ close(fd);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ dri2_dpy->fd_render_gpu = fd;
|
||||
+ dri2_dpy->driver_name = driver_name;
|
||||
+
|
||||
+ device = _eglFindDevice(fd, false);
|
||||
+ fprintf(stderr, "[REDOX-EGL] _eglFindDevice returned: %p\n", (void *)device);
|
||||
+ if (!device) {
|
||||
+ free(driver_name);
|
||||
+ close(fd);
|
||||
+ dri2_dpy->driver_name = NULL;
|
||||
+ dri2_dpy->fd_render_gpu = -1;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (_eglHasAttrib(disp, EGL_DEVICE_EXT) && disp->Device != device) {
|
||||
+ fprintf(stderr, "[REDOX-EGL] EGL_DEVICE_EXT mismatch\n");
|
||||
+ free(driver_name);
|
||||
+ close(fd);
|
||||
+ dri2_dpy->driver_name = NULL;
|
||||
+ dri2_dpy->fd_render_gpu = -1;
|
||||
+ return false;
|
||||
+ }
|
||||
+ disp->Device = device;
|
||||
+
|
||||
+ /* Hardware drivers expose the DRI3/image entrypoints we need here. */
|
||||
+ fprintf(stderr, "[REDOX-EGL] calling dri2_load_driver_dri3 (driver=%s)...\n", driver_name);
|
||||
+ if (!dri2_load_driver_dri3(disp)) {
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_load_driver_dri3 FAILED\n");
|
||||
+ free(driver_name);
|
||||
+ close(fd);
|
||||
+ dri2_dpy->driver_name = NULL;
|
||||
+ dri2_dpy->fd_render_gpu = -1;
|
||||
+ return false;
|
||||
+ }
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_load_driver_dri3 succeeded\n");
|
||||
+
|
||||
+ dri2_dpy->loader_extensions = redox_hw_loader_extensions;
|
||||
+
|
||||
+ fprintf(stderr, "[REDOX-EGL] redox_probe_device_hw: SUCCESS (driver=%s)\n", driver_name);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static bool
|
||||
redox_probe_device_sw(_EGLDisplay *disp)
|
||||
{
|
||||
@@ -488,6 +635,8 @@ dri2_initialize_redox(_EGLDisplay *disp)
|
||||
bool driver_loaded = false;
|
||||
struct dri2_egl_display *dri2_dpy = dri2_display_create();
|
||||
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_initialize_redox: starting\n");
|
||||
+
|
||||
if (!dri2_dpy) {
|
||||
err = "dri2_display_create failed";
|
||||
goto cleanup;
|
||||
@@ -495,7 +644,12 @@ dri2_initialize_redox(_EGLDisplay *disp)
|
||||
|
||||
disp->DriverData = (void *)dri2_dpy;
|
||||
|
||||
- driver_loaded = redox_probe_device_sw(disp);
|
||||
+ /* Try hardware GPU first (virgl, amdgpu, etc.). */
|
||||
+ driver_loaded = redox_probe_device_hw(disp);
|
||||
+ fprintf(stderr, "[REDOX-EGL] HW probe: %s\n", driver_loaded ? "SUCCESS" : "FAILED");
|
||||
+ /* Fall back to software rendering (llvmpipe/softpipe). */
|
||||
+ if (!driver_loaded)
|
||||
+ driver_loaded = redox_probe_device_sw(disp);
|
||||
|
||||
if (!driver_loaded) {
|
||||
err = "DRI2: failed to load driver";
|
||||
@@ -503,16 +657,21 @@ dri2_initialize_redox(_EGLDisplay *disp)
|
||||
}
|
||||
|
||||
dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
|
||||
+ fprintf(stderr, "[REDOX-EGL] calling dri2_create_screen...\n");
|
||||
|
||||
if (!dri2_create_screen(disp)) {
|
||||
err = "DRI2: failed to create screen";
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_create_screen FAILED\n");
|
||||
goto cleanup;
|
||||
}
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_create_screen succeeded\n");
|
||||
|
||||
if (!dri2_setup_extensions(disp)) {
|
||||
err = "DRI2: failed to find required DRI extensions";
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_setup_extensions FAILED\n");
|
||||
goto cleanup;
|
||||
}
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_setup_extensions succeeded\n");
|
||||
|
||||
dri2_setup_screen(disp);
|
||||
|
||||
@@ -532,9 +691,11 @@ dri2_initialize_redox(_EGLDisplay *disp)
|
||||
|
||||
dri2_dpy->vtbl = &dri2_redox_display_vtbl;
|
||||
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_initialize_redox: COMPLETE\n");
|
||||
return EGL_TRUE;
|
||||
|
||||
cleanup:
|
||||
+ fprintf(stderr, "[REDOX-EGL] dri2_initialize_redox: FAILED: %s\n", err);
|
||||
dri2_display_destroy(disp);
|
||||
return _eglError(EGL_NOT_INITIALIZED, err);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ git = "https://gitlab.redox-os.org/redox-os/mesa.git"
|
||||
upstream = "https://gitlab.freedesktop.org/mesa/mesa"
|
||||
branch = "redox-24.0"
|
||||
shallow_clone = true
|
||||
patches = ["../../../local/patches/mesa/P4-virgl-redox-disk-cache.patch"]
|
||||
patches = ["../../../local/patches/mesa/P4-virgl-redox-disk-cache.patch", "../../../local/patches/mesa/P5-gbm-dumb-prime-export.patch", "../../../local/patches/mesa/P6-platform-redox-gpu-probe.patch"]
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = [
|
||||
|
||||
Reference in New Issue
Block a user