#include "egl_dri2.h"
#include "egl_dri2_fallbacks.h"
#include "loader.h"
-#include "util/debug.h"
static __DRIimage*
surfaceless_alloc_image(struct dri2_egl_display *dri2_dpy,
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->image_driver->createNewDrawable(dri2_dpy->dri_screen, config,
}
static EGLBoolean
-surfaceless_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
-{
- assert(!surf || surf->Type == EGL_PBUFFER_BIT);
-
- /* From the EGL 1.5 spec:
- * If surface is a [...] pbuffer surface, eglSwapBuffers has no effect.
- */
- return EGL_TRUE;
-}
-
-static EGLBoolean
-surfaceless_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
+surfaceless_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
{
- struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
static const struct {
const char *format_name;
unsigned int rgba_masks[4];
for (unsigned j = 0; j < ARRAY_SIZE(visuals); j++) {
struct dri2_egl_config *dri2_conf;
- dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[i],
+ dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
config_count + 1, EGL_PBUFFER_BIT, NULL,
visuals[j].rgba_masks);
.create_pbuffer_surface = dri2_surfaceless_create_pbuffer_surface,
.destroy_surface = surfaceless_destroy_surface,
.create_image = dri2_create_image_khr,
- .swap_buffers = surfaceless_swap_buffers,
- .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
.swap_buffers_region = dri2_fallback_swap_buffers_region,
.set_damage_region = dri2_fallback_set_damage_region,
.post_sub_buffer = dri2_fallback_post_sub_buffer,
.flushFrontBuffer = surfaceless_flush_front_buffer,
};
+static const __DRIswrastLoaderExtension swrast_loader_extension = {
+ .base = { __DRI_SWRAST_LOADER, 1 },
+ .getDrawableInfo = NULL,
+ .putImage = NULL,
+ .getImage = NULL,
+};
+
#define DRM_RENDER_DEV_NAME "%s/renderD%d"
static const __DRIextension *image_loader_extensions[] = {
NULL,
};
+static const __DRIextension *swrast_loader_extensions[] = {
+ &swrast_loader_extension.base,
+ &image_loader_extension.base,
+ &image_lookup_extension.base,
+ &use_invalidate.base,
+ NULL,
+};
+
static bool
-surfaceless_probe_device(_EGLDisplay *dpy, bool swrast)
+surfaceless_probe_device(_EGLDisplay *disp, bool swrast)
{
- struct dri2_egl_display *dri2_dpy = dpy->DriverData;
+ struct dri2_egl_display *dri2_dpy = disp->DriverData;
const int limit = 64;
const int base = 128;
int fd;
int i;
+ /* Attempt to find DRM device. */
for (i = 0; i < limit; ++i) {
char *card_path;
if (asprintf(&card_path, DRM_RENDER_DEV_NAME, DRM_DIR_NAME, base + i) < 0)
if (fd < 0)
continue;
- if (swrast)
+ if (swrast) {
dri2_dpy->driver_name = strdup("kms_swrast");
- else
+ dri2_dpy->loader_extensions = swrast_loader_extensions;
+ } else {
dri2_dpy->driver_name = loader_get_driver_for_fd(fd);
+ dri2_dpy->loader_extensions = image_loader_extensions;
+ }
if (!dri2_dpy->driver_name) {
close(fd);
continue;
}
dri2_dpy->fd = fd;
- if (dri2_load_driver_dri3(dpy))
+ if (dri2_load_driver_dri3(disp)) {
+ _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, swrast);
+ if (!dev) {
+ dlclose(dri2_dpy->driver);
+ _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
+ continue;
+ }
+ disp->Device = dev;
return true;
+ }
close(fd);
dri2_dpy->fd = -1;
free(dri2_dpy->driver_name);
dri2_dpy->driver_name = NULL;
+ dri2_dpy->loader_extensions = NULL;
}
return false;
}
+static bool
+surfaceless_probe_device_sw(_EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy = disp->DriverData;
+
+ 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 = swrast_loader_extensions;
+ return true;
+}
+
EGLBoolean
dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp)
{
const char* err;
bool driver_loaded = false;
- loader_set_logger(_eglLog);
-
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 (!env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false)) {
+ 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 && !surfaceless_probe_device(disp, true)) {
- err = "DRI2: failed to load driver";
- goto cleanup;
- }
+ if (!driver_loaded)
+ driver_loaded = surfaceless_probe_device(disp, true);
- dri2_dpy->loader_extensions = image_loader_extensions;
+ 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";