X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fplatform_surfaceless.c;h=dd283673a8374a506cfee80871916ffe8190fa7e;hb=6b4c474ed7d217ae27edc6f9e30feba651ef6a53;hp=c81eacafdac684487a6f60d7661ebd73d41dde7e;hpb=af7abc512c422183a761ce3d687086abe282fa74;p=mesa.git diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c index c81eacafdac..dd283673a83 100644 --- a/src/egl/drivers/dri2/platform_surfaceless.c +++ b/src/egl/drivers/dri2/platform_surfaceless.c @@ -34,7 +34,6 @@ #include #include "egl_dri2.h" -#include "egl_dri2_fallbacks.h" #include "loader.h" static __DRIimage* @@ -60,6 +59,9 @@ surfaceless_free_images(struct dri2_egl_surface *dri2_surf) dri2_dpy->image->destroyImage(dri2_surf->front); dri2_surf->front = NULL; } + + free(dri2_surf->swrast_device_buffer); + dri2_surf->swrast_device_buffer = NULL; } static int @@ -106,8 +108,8 @@ surfaceless_image_get_buffers(__DRIdrawable *driDrawable, } static _EGLSurface * -dri2_surfaceless_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, - _EGLConfig *conf, const EGLint *attrib_list) +dri2_surfaceless_create_surface(_EGLDisplay *disp, EGLint type, + _EGLConfig *conf, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); @@ -124,29 +126,24 @@ dri2_surfaceless_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, return NULL; } - if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) + if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, + false, NULL)) goto cleanup_surface; config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace); - if (!config) + if (!config) { + _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); goto cleanup_surface; + } - dri2_surf->dri_drawable = - (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config, - dri2_surf); - if (dri2_surf->dri_drawable == NULL) { - _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); + dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config); + if (dri2_surf->visual == __DRI_IMAGE_FORMAT_NONE) goto cleanup_surface; - } - if (conf->RedSize == 5) - dri2_surf->visual = __DRI_IMAGE_FORMAT_RGB565; - else if (conf->AlphaSize == 0) - dri2_surf->visual = __DRI_IMAGE_FORMAT_XRGB8888; - else - dri2_surf->visual = __DRI_IMAGE_FORMAT_ARGB8888; + if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) + goto cleanup_surface; return &dri2_surf->base; @@ -156,80 +153,32 @@ dri2_surfaceless_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, } static EGLBoolean -surfaceless_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) +surfaceless_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); surfaceless_free_images(dri2_surf); - (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); + dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); + dri2_fini_surface(surf); free(dri2_surf); return EGL_TRUE; } static _EGLSurface * -dri2_surfaceless_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, - _EGLConfig *conf, const EGLint *attrib_list) +dri2_surfaceless_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf, + const EGLint *attrib_list) { - return dri2_surfaceless_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, + return dri2_surfaceless_create_surface(disp, EGL_PBUFFER_BIT, conf, attrib_list); } -static EGLBoolean -surfaceless_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy) -{ - struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); - static const struct { - const char *format_name; - unsigned int rgba_masks[4]; - } visuals[] = { - { "ARGB8888", { 0xff0000, 0xff00, 0xff, 0xff000000 } }, - { "RGB888", { 0xff0000, 0xff00, 0xff, 0x0 } }, - { "RGB565", { 0x00f800, 0x07e0, 0x1f, 0x0 } }, - }; - unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 }; - unsigned int count, i, j; - - count = 0; - for (i = 0; dri2_dpy->driver_configs[i] != NULL; i++) { - for (j = 0; j < ARRAY_SIZE(visuals); j++) { - struct dri2_egl_config *dri2_conf; - - dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[i], - count + 1, EGL_PBUFFER_BIT, NULL, visuals[j].rgba_masks); - - if (dri2_conf) { - count++; - format_count[j]++; - } - } - } - - for (i = 0; i < ARRAY_SIZE(format_count); i++) { - if (!format_count[i]) { - _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", - visuals[i].format_name); - } - } - - return (count != 0); -} - -static struct dri2_egl_display_vtbl dri2_surfaceless_display_vtbl = { - .create_pixmap_surface = dri2_fallback_create_pixmap_surface, +static const struct dri2_egl_display_vtbl dri2_surfaceless_display_vtbl = { .create_pbuffer_surface = dri2_surfaceless_create_pbuffer_surface, .destroy_surface = surfaceless_destroy_surface, .create_image = dri2_create_image_khr, - .swap_interval = dri2_fallback_swap_interval, - .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, - .swap_buffers_region = dri2_fallback_swap_buffers_region, - .post_sub_buffer = dri2_fallback_post_sub_buffer, - .copy_buffers = dri2_fallback_copy_buffers, - .query_buffer_age = dri2_fallback_query_buffer_age, - .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, - .get_sync_values = dri2_fallback_get_sync_values, .get_dri_drawable = dri2_surface_get_dri_drawable, }; @@ -238,14 +187,25 @@ surfaceless_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate) { } +static unsigned +surfaceless_get_capability(void *loaderPrivate, enum dri_loader_cap cap) +{ + /* Note: loaderPrivate is _EGLDisplay* */ + switch (cap) { + case DRI_LOADER_CAP_FP16: + return 1; + default: + return 0; + } +} + static const __DRIimageLoaderExtension image_loader_extension = { - .base = { __DRI_IMAGE_LOADER, 1 }, + .base = { __DRI_IMAGE_LOADER, 2 }, .getBuffers = surfaceless_image_get_buffers, .flushFrontBuffer = surfaceless_flush_front_buffer, + .getCapability = surfaceless_get_capability, }; -#define DRM_RENDER_DEV_NAME "%s/renderD%d" - static const __DRIextension *image_loader_extensions[] = { &image_loader_extension.base, &image_lookup_extension.base, @@ -253,64 +213,157 @@ static const __DRIextension *image_loader_extensions[] = { NULL, }; -EGLBoolean -dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp) -{ - struct dri2_egl_display *dri2_dpy; - const char* err; - int i; - int driver_loaded = 0; +static const __DRIextension *swrast_loader_extensions[] = { + &swrast_pbuffer_loader_extension.base, + &image_loader_extension.base, + &image_lookup_extension.base, + &use_invalidate.base, + NULL, +}; - loader_set_logger(_eglLog); +static bool +surfaceless_probe_device(_EGLDisplay *disp, bool swrast) +{ +#define MAX_DRM_DEVICES 64 + const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL }; + int i, num_devices; - dri2_dpy = calloc(1, sizeof *dri2_dpy); - if (!dri2_dpy) - return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); + if (num_devices < 0) + return false; - disp->DriverData = (void *) dri2_dpy; + for (i = 0; i < num_devices; ++i) { + device = devices[i]; - const int limit = 64; - const int base = 128; - for (i = 0; i < limit; ++i) { - char *card_path; - if (asprintf(&card_path, DRM_RENDER_DEV_NAME, DRM_DIR_NAME, base + i) < 0) + if (!(device->available_nodes & (1 << node_type))) continue; - dri2_dpy->fd = loader_open_device(card_path); - - free(card_path); + dri2_dpy->fd = loader_open_device(device->nodes[node_type]); if (dri2_dpy->fd < 0) continue; - dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); - if (dri2_dpy->driver_name) { - if (dri2_load_driver(disp)) { - driver_loaded = 1; - break; - } - free(dri2_dpy->driver_name); + disp->Device = _eglAddDevice(dri2_dpy->fd, swrast); + if (!disp->Device) { + close(dri2_dpy->fd); + dri2_dpy->fd = -1; + continue; + } + + char *driver_name = loader_get_driver_for_fd(dri2_dpy->fd); + if (swrast) { + /* Use kms swrast only with vgem / virtio_gpu. + * virtio-gpu fallbacks to software rendering when 3D features + * are unavailable since 6c5ab, and kms_swrast is more + * feature complete than swrast. + */ + if (driver_name && + (strcmp(driver_name, "vgem") == 0 || + strcmp(driver_name, "virtio_gpu") == 0)) + dri2_dpy->driver_name = strdup("kms_swrast"); + free(driver_name); + } else { + /* Use the given hardware driver */ + dri2_dpy->driver_name = driver_name; } + + if (dri2_dpy->driver_name && dri2_load_driver_dri3(disp)) + break; + + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; close(dri2_dpy->fd); + dri2_dpy->fd = -1; } + drmFreeDevices(devices, num_devices); - if (!driver_loaded) { - err = "DRI2: failed to load driver"; - goto cleanup_display; + if (i == num_devices) + return false; + + if (swrast) + dri2_dpy->loader_extensions = swrast_loader_extensions; + else + dri2_dpy->loader_extensions = image_loader_extensions; + + return true; +} + +static bool +surfaceless_probe_device_sw(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + + dri2_dpy->fd = -1; + disp->Device = _eglAddDevice(dri2_dpy->fd, true); + assert(disp->Device); + + dri2_dpy->driver_name = strdup("swrast"); + if (!dri2_dpy->driver_name) + return false; + + if (!dri2_load_driver_swrast(disp)) { + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; + return false; } - dri2_dpy->loader_extensions = image_loader_extensions; + dri2_dpy->loader_extensions = swrast_loader_extensions; + return true; +} + +EGLBoolean +dri2_initialize_surfaceless(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy; + const char* err; + bool driver_loaded = false; + + dri2_dpy = calloc(1, sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + dri2_dpy->fd = -1; + disp->DriverData = (void *) dri2_dpy; + + if (!disp->Options.ForceSoftware) { + driver_loaded = surfaceless_probe_device(disp, false); + if (!driver_loaded) + _eglLog(_EGL_WARNING, + "No hardware driver found, falling back to software rendering"); + } + + if (!driver_loaded) + driver_loaded = surfaceless_probe_device(disp, true); + + if (!driver_loaded) { + _eglLog(_EGL_DEBUG, "Falling back to surfaceless swrast without DRM."); + if (!surfaceless_probe_device_sw(disp)) { + err = "DRI2: failed to load driver"; + goto cleanup; + } + } if (!dri2_create_screen(disp)) { err = "DRI2: failed to create screen"; - goto cleanup_driver; + goto cleanup; } - if (!surfaceless_add_configs_for_visuals(drv, disp)) { - err = "DRI2: failed to add configs"; - goto cleanup_screen; + if (!dri2_setup_extensions(disp)) { + err = "DRI2: failed to find required DRI extensions"; + goto cleanup; } - disp->Extensions.KHR_image_base = EGL_TRUE; + dri2_setup_screen(disp); +#ifdef HAVE_WAYLAND_PLATFORM + dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd); +#endif + dri2_set_WL_bind_wayland_display(disp); + + if (!dri2_add_pbuffer_configs_for_visuals(disp)) { + err = "DRI2: failed to add configs"; + goto cleanup; + } /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. @@ -319,16 +372,7 @@ dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp) return EGL_TRUE; -cleanup_screen: - dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); - -cleanup_driver: - dlclose(dri2_dpy->driver); - free(dri2_dpy->driver_name); - close(dri2_dpy->fd); -cleanup_display: - free(dri2_dpy); - disp->DriverData = NULL; - +cleanup: + dri2_display_destroy(disp); return _eglError(EGL_NOT_INITIALIZED, err); }