[Mesa-dev] [PATCH v2 1/3] Add support for swrast to the DRM EGL platform

Emil Velikov emil.l.velikov at gmail.com
Wed May 14 17:47:53 PDT 2014


On 05/05/14 17:07, Giovanni Campagna wrote:
> From: Giovanni Campagna <gcampagna at src.gnome.org>
> 
> Turn GBM into a swrast loader (providing putimage/getimage backed
> by a dumb KMS buffer). This allows to run KMS+DRM GL applications
> (such as weston or mutter-wayland) unmodified on cards that don't
> have any client side HW acceleration component but that can do
> modeset (examples include simpledrm and qxl)
> ---
>  src/egl/drivers/dri2/platform_drm.c | 186 ++++++++++++++++++++++++++++----
>  src/gbm/backends/dri/gbm_dri.c      | 210 +++++++++++++++++++++++++++++-------
>  src/gbm/backends/dri/gbm_driint.h   |  19 +++-
>  src/gbm/main/gbm.h                  |   3 +
>  src/loader/loader.c                 |   6 ++
>  5 files changed, 363 insertions(+), 61 deletions(-)
> 
> diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
> index 9a7633a..17b93db 100644
> --- a/src/egl/drivers/dri2/platform_drm.c
> +++ b/src/egl/drivers/dri2/platform_drm.c
> @@ -32,6 +32,7 @@
>  #include <dlfcn.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
> +#include <sys/mman.h>
>  #include <fcntl.h>
>  #include <unistd.h>
>  
> @@ -44,6 +45,7 @@ lock_front_buffer(struct gbm_surface *_surf)
>  {
>     struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
>     struct dri2_egl_surface *dri2_surf = surf->dri_private;
> +   struct gbm_dri_device *device = (struct gbm_dri_device *) _surf->gbm;
>     struct gbm_bo *bo;
>  
>     if (dri2_surf->current == NULL) {
> @@ -52,8 +54,11 @@ lock_front_buffer(struct gbm_surface *_surf)
>     }
>  
>     bo = dri2_surf->current->bo;
> -   dri2_surf->current->locked = 1;
> -   dri2_surf->current = NULL;
> +
> +   if (device->dri2) {
> +      dri2_surf->current->locked = 1;
> +      dri2_surf->current = NULL;
> +   }
>  
>     return bo;
>  }
> @@ -122,10 +127,18 @@ dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
>        goto cleanup_surf;
>     }
>  
> -   dri2_surf->dri_drawable =
> -      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
> -					    dri2_conf->dri_double_config,
> -					    dri2_surf->gbm_surf);
> +   if (dri2_dpy->dri2) {
> +      dri2_surf->dri_drawable =
> +         (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
> +                                               dri2_conf->dri_double_config,
> +                                               dri2_surf->gbm_surf);
> +   } else {
> +      assert (dri2_dpy->swrast != NULL);
> +      dri2_surf->dri_drawable =
> +         (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
> +                                                 dri2_conf->dri_double_config,
> +                                                 dri2_surf->gbm_surf);
> +   }
>  
>     if (dri2_surf->dri_drawable == NULL) {
>        _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
Can you update the above message ?

> @@ -221,6 +234,28 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
>     return 0;
>  }
>  
> +static int
> +get_swrast_front_bo(struct dri2_egl_surface *dri2_surf)
> +{
> +   struct dri2_egl_display *dri2_dpy =
> +      dri2_egl_display(dri2_surf->base.Resource.Display);
> +   struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
> +
> +   if (dri2_surf->current == NULL) {
> +      assert (!dri2_surf->color_buffers[0].locked);
> +      dri2_surf->current = &dri2_surf->color_buffers[0];
> +   }
> +
> +   if (dri2_surf->current->bo == NULL)
> +      dri2_surf->current->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
> +                                             surf->base.width, surf->base.height,
> +                                             surf->base.format, surf->base.flags);
> +   if (dri2_surf->current->bo == NULL)
> +      return -1;
> +
> +   return 0;
> +}
> +
>  static void
>  back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
>  {
> @@ -374,19 +409,23 @@ dri2_drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
>     struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
>     int i;
>  
> -   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
> -      if (dri2_surf->current)
> -	 _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
> -      for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
> -         if (dri2_surf->color_buffers[i].age > 0)
> -            dri2_surf->color_buffers[i].age++;
> -      dri2_surf->current = dri2_surf->back;
> -      dri2_surf->current->age = 1;
> -      dri2_surf->back = NULL;
> -   }
> +   if (dri2_dpy->swrast) {
> +      (*dri2_dpy->core->swapBuffers)(dri2_surf->dri_drawable);
> +   } else {
> +      if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
> +         if (dri2_surf->current)
> +            _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
> +         for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
> +            if (dri2_surf->color_buffers[i].age > 0)
> +               dri2_surf->color_buffers[i].age++;
> +         dri2_surf->current = dri2_surf->back;
> +         dri2_surf->current->age = 1;
> +         dri2_surf->back = NULL;
> +      }
>  
> -   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> -   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
> +      (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> +      (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
> +   }
>  
>     return EGL_TRUE;
>  }
> @@ -457,6 +496,108 @@ dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
>     return drmAuthMagic(dri2_dpy->fd, id);
>  }
>  
> +static void *
> +gbm_dri_bo_map(struct gbm_dri_bo *bo)
> +{
> +   struct drm_mode_map_dumb map_arg;
+   struct drm_mode_destroy_dumb destroy_arg;

> +   int ret;
> +
> +   if (bo->image != NULL)
> +      return NULL;
> +
> +   if (bo->map != NULL)
> +      return bo->map;
> +
> +   memset(&map_arg, 0, sizeof(map_arg));
> +   map_arg.handle = bo->handle;
> +
> +   ret = drmIoctl(bo->base.base.gbm->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
> +   if (ret)
> +      return NULL;
> +
> +   bo->map = mmap(0, bo->size, PROT_WRITE,
> +                  MAP_SHARED, bo->base.base.gbm->fd, map_arg.offset);
> +   if (bo->map == MAP_FAILED)
> +      return NULL;

You might want to cleanup the ioct on failure (and drop it from the caller).
Might be worth adding clearing up map, to prevent nasty things happening up
the call chain. Something like the code below:

+   if (bo->map == MAP_FAILED) {
+       memset(&destroy_arg, 0, sizeof destroy_arg);
+       destroy_arg.handle = map_arg.handle;
+       drmIoctl(bo->base.base.gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB,
&destroy_arg);
+       bo->map = NULL;
+   }


> +
> +   return bo->map;
> +
> +}
> +
> +static void
> +gbm_dri_bo_unmap(struct gbm_dri_bo *bo)
> +{
> +   munmap(bo->map, bo->size);
> +   bo->map = NULL;
Can you move the ioctl inside the function to keep things symmetric/prevent
leaks ?

> +}
> +
You can add the above two helpers into gbm_driint.h

> +static void
> +swrast_put_image2(__DRIdrawable *driDrawable,
> +                  int            op,
> +                  int            x,
> +                  int            y,
> +                  int            width,
> +                  int            height,
> +                  int            stride,
> +                  char          *data,
> +                  void          *loaderPrivate)
> +{
> +   struct dri2_egl_surface *dri2_surf = loaderPrivate;
> +   int internal_stride, i;
> +   struct gbm_dri_bo *bo;
> +
> +   if (op != __DRI_SWRAST_IMAGE_OP_DRAW &&
> +       op != __DRI_SWRAST_IMAGE_OP_SWAP)
> +      return;
> +
> +   get_swrast_front_bo(dri2_surf);
> +   bo = gbm_dri_bo(dri2_surf->current->bo);
> +   if (bo == NULL)
> +      return;
(trivial nitpick)
You introduced a return value for get_swrast_front_bo() but you seem to ignore
it. IMHO the following looks a bit better.
+   if (get_swrast_front_bo(dri2_surf))
+      return;
+   bo = gbm_dri_bo(dri2_surf->current->bo);


> +   if (gbm_dri_bo_map(bo) == NULL)
> +      return;
> +
> +   internal_stride = bo->base.base.stride;
> +
> +   for (i = 0; i < height; i++) {
> +      memcpy(bo->map + (x + i) * internal_stride + y,
> +             data + i * stride, stride);
> +   }
> +
> +   gbm_dri_bo_unmap(bo);
> +}
> +
> +static void
> +swrast_get_image(__DRIdrawable *driDrawable,
> +                 int            x,
> +                 int            y,
> +                 int            width,
> +                 int            height,
> +                 char          *data,
> +                 void          *loaderPrivate)
> +{
> +   struct dri2_egl_surface *dri2_surf = loaderPrivate;
> +   int internal_stride, stride, i;
> +   struct gbm_dri_bo *bo;
> +
> +   get_swrast_front_bo(dri2_surf);
> +   bo = gbm_dri_bo(dri2_surf->current->bo);
> +   if (bo == NULL)
> +      return;
Ditto

> +   if (gbm_dri_bo_map(bo) == NULL)
> +      return;
> +
> +   internal_stride = bo->base.base.stride;
> +   stride = width * 4;
> +
> +   for (i = 0; i < height; i++) {
> +      memcpy(data + i * stride,
> +             bo->map + (x + i) * internal_stride + y, stride);
> +   }
> +
> +   gbm_dri_bo_unmap(bo);
> +}
> +
>  static struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
>     .authenticate = dri2_drm_authenticate,
>     .create_window_surface = dri2_drm_create_window_surface,
> @@ -532,6 +673,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
>     dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
>     dri2_dpy->image = dri2_dpy->gbm_dri->image;
>     dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
> +   dri2_dpy->swrast = dri2_dpy->gbm_dri->swrast;
>     dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
>  
>     dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
> @@ -541,6 +683,8 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
>     dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
>     dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;
>     dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
> +   dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2;
> +   dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image;
>  
>     dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
>     dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
> @@ -571,10 +715,12 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
>                        i + 1, EGL_WINDOW_BIT, attr_list, NULL);
>     }
>  
> -   disp->Extensions.EXT_buffer_age = EGL_TRUE;
> +   if (dri2_dpy->dri2)
> +      disp->Extensions.EXT_buffer_age = EGL_TRUE;
>  
>  #ifdef HAVE_WAYLAND_PLATFORM
> -   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
> +   if (dri2_dpy->image)
> +      disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
>  #endif
>  
>     /* we're supporting EGL 1.4 */
> diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
> index cec12d1..53d0bf3 100644
> --- a/src/gbm/backends/dri/gbm_dri.c
> +++ b/src/gbm/backends/dri/gbm_dri.c
> @@ -124,6 +124,74 @@ image_get_buffers(__DRIdrawable *driDrawable,
>                                   surf->dri_private, buffer_mask, buffers);
>  }
>  
> +static void
> +swrast_get_drawable_info(__DRIdrawable *driDrawable,
> +                         int           *x,
> +                         int           *y,
> +                         int           *width,
> +                         int           *height,
> +                         void          *loaderPrivate)
> +{
> +   struct gbm_dri_surface *surf = loaderPrivate;
> +
> +   *x = 0;
> +   *y = 0;
> +   *width = surf->base.width;
> +   *height = surf->base.height;
> +}
> +
> +static void
> +swrast_put_image2(__DRIdrawable *driDrawable,
> +                  int            op,
> +                  int            x,
> +                  int            y,
> +                  int            width,
> +                  int            height,
> +                  int            stride,
> +                  char          *data,
> +                  void          *loaderPrivate)
> +{
> +   struct gbm_dri_surface *surf = loaderPrivate;
> +   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
> +
> +   dri->swrast_put_image2(driDrawable,
> +                          op, x, y,
> +                          width, height, stride,
> +                          data, surf->dri_private);
> +}
> +
> +static void
> +swrast_put_image(__DRIdrawable *driDrawable,
> +                 int            op,
> +                 int            x,
> +                 int            y,
> +                 int            width,
> +                 int            height,
> +                 char          *data,
> +                 void          *loaderPrivate)
> +{
> +   return swrast_put_image2(driDrawable, op, x, y, width, height,
> +                            width * 4, data, loaderPrivate);
> +}
> +
> +static void
> +swrast_get_image(__DRIdrawable *driDrawable,
> +                 int            x,
> +                 int            y,
> +                 int            width,
> +                 int            height,
> +                 char          *data,
> +                 void          *loaderPrivate)
> +{
> +   struct gbm_dri_surface *surf = loaderPrivate;
> +   struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm);
> +
> +   dri->swrast_get_image(driDrawable,
> +                         x, y,
> +                         width, height,
> +                         data, surf->dri_private);
> +}
> +
>  static const __DRIuseInvalidateExtension use_invalidate = {
>     .base = { __DRI_USE_INVALIDATE, 1 }
>  };
> @@ -149,11 +217,21 @@ static const __DRIimageLoaderExtension image_loader_extension = {
>     .flushFrontBuffer    = dri_flush_front_buffer,
>  };
>  
> +static const __DRIswrastLoaderExtension swrast_loader_extension = {
> +   .base = { __DRI_SWRAST_LOADER, 2 },
> +
> +   .getDrawableInfo = swrast_get_drawable_info,
> +   .putImage        = swrast_put_image,
> +   .getImage        = swrast_get_image,
> +   .putImage2       = swrast_put_image2
> +};
> +
>  static const __DRIextension *gbm_dri_screen_extensions[] = {
>     &image_lookup_extension.base,
>     &use_invalidate.base,
>     &dri2_loader_extension.base,
>     &image_loader_extension.base,
> +   &swrast_loader_extension.base,
>     NULL,
>  };
>  
> @@ -163,18 +241,24 @@ struct dri_extension_match {
>     int offset;
>  };
>  
> -static struct dri_extension_match dri_core_extensions[] = {
> +static struct dri_extension_match dri2_core_extensions[] = {
>     { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) },
>     { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) },
>     { NULL, 0, 0 }
>  };
>  
> -static struct dri_extension_match gbm_dri_device_extensions[] = {
> +static struct dri_extension_match gbm_dri2_device_extensions[] = {
>     { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) },
>     { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) },
>     { NULL, 0, 0 }
>  };
>  
Please keep the above two names as is.

> +static struct dri_extension_match gbm_swrast_device_extensions[] = {
> +   { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), },
> +   { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast) },
> +   { NULL, 0, 0 }
> +};
> +
>  static int
>  dri_bind_extensions(struct gbm_dri_device *dri,
>                      struct dri_extension_match *matches,
> @@ -268,10 +352,12 @@ dri_load_driver(struct gbm_dri_device *dri)
>     }
>     dri->driver_extensions = extensions;
>  
> -   if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) {
> -      dlclose(dri->driver);
> -      fprintf(stderr, "failed to bind extensions\n");
> -      return -1;
> +   if (dri_bind_extensions(dri, gbm_dri2_device_extensions, extensions) < 0) {
> +      if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) {
> +         dlclose(dri->driver);
> +         fprintf(stderr, "failed to bind extensions\n");
> +         return -1;
> +      }
Shouldn't one be checking the driver_name which extensions we need to bind ?

>     }
>  
>     return 0;
> @@ -290,31 +376,50 @@ dri_screen_create(struct gbm_dri_device *dri)
>     ret = dri_load_driver(dri);
>     if (ret) {
>        fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name);
> -      return ret;
> +
> +      dri->base.driver_name = "swrast";
> +      ret = dri_load_driver(dri);
> +      if (ret) {
> +         fprintf(stderr, "failed to fallback to software rendering\n");
> +         return ret;
> +      }
>     };
>  
>     dri->extensions = gbm_dri_screen_extensions;
>  
> -   if (dri->dri2 == NULL)
> +   if (dri->dri2 == NULL && dri->swrast == NULL)
>        return -1;
>  
> -   if (dri->dri2->base.version >= 4) {
> -      dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd,
> -                                                dri->extensions,
> -                                                dri->driver_extensions,
> -                                                &dri->driver_configs, dri);
> +   if (dri->dri2 != NULL) {
> +      if (dri->dri2->base.version >= 4) {
> +         dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd,
> +                                                   dri->extensions,
> +                                                   dri->driver_extensions,
> +                                                   &dri->driver_configs, dri);
> +      } else {
> +         dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd,
> +                                                  dri->extensions,
> +                                                  &dri->driver_configs, dri);
> +      }
> +      if (dri->screen == NULL)
> +         return -1;
>     } else {
> -      dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd,
> -                                               dri->extensions,
> -                                               &dri->driver_configs, dri);
> +      if (dri->swrast->base.version >= 4) {
> +         dri->screen = dri->swrast->createNewScreen2(0, dri->extensions,
> +                                                     dri->driver_extensions,
> +                                                     &dri->driver_configs, dri);
> +      } else {
> +         dri->screen = dri->swrast->createNewScreen(0, dri->extensions,
> +                                                    &dri->driver_configs, dri);
> +      }
>     }
> -   if (dri->screen == NULL)
> -      return -1;
swrast->createNewScreen{,2} can fail as well.

>  
>     extensions = dri->core->getExtensions(dri->screen);
> -   if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) {
> -      ret = -1;
> -      goto free_screen;
> +   if (dri->dri2 != NULL) {
> +      if (dri_bind_extensions(dri, dri2_core_extensions, extensions) < 0) {
> +         ret = -1;
> +         goto free_screen;
> +      }
>     }
>  
>     dri->lookup_image = NULL;
> @@ -383,6 +488,40 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo)
>     return fd;
>  }
>  
> +static void *
> +gbm_dri_bo_map(struct gbm_dri_bo *bo)
> +{
> +   struct drm_mode_map_dumb map_arg;
> +   int ret;
> +
> +   if (bo->image != NULL)
> +      return NULL;
> +
> +   if (bo->map != NULL)
> +      return bo->map;
> +
> +   memset(&map_arg, 0, sizeof(map_arg));
> +   map_arg.handle = bo->handle;
> +
> +   ret = drmIoctl(bo->base.base.gbm->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
> +   if (ret)
> +      return NULL;
> +
> +   bo->map = mmap(0, bo->size, PROT_WRITE,
> +                  MAP_SHARED, bo->base.base.gbm->fd, map_arg.offset);
> +   if (bo->map == MAP_FAILED)
> +      return NULL;
> +
> +   return bo->map;
> +}
> +
> +static void
> +gbm_dri_bo_unmap(struct gbm_dri_bo *bo)
> +{
> +   munmap(bo->map, bo->size);
> +   bo->map = NULL;
> +}
> +
>  static void
>  gbm_dri_bo_destroy(struct gbm_bo *_bo)
>  {
> @@ -393,7 +532,7 @@ gbm_dri_bo_destroy(struct gbm_bo *_bo)
>     if (bo->image != NULL) {
>        dri->image->destroyImage(bo->image);
>     } else {
> -      munmap(bo->map, bo->size);
> +      gbm_dri_bo_unmap(bo);
>        memset(&arg, 0, sizeof(arg));
>        arg.handle = bo->handle;
>        drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
> @@ -439,7 +578,7 @@ gbm_dri_bo_import(struct gbm_device *gbm,
>     int gbm_format;
>  
>     /* Required for query image WIDTH & HEIGHT */
> -   if (dri->image->base.version < 4) {
> +   if (dri->image == NULL || dri->image->base.version < 4)
Missing opening curly bracket                                 ^^

>        errno = ENOSYS;
>        return NULL;
>     }
> @@ -563,16 +702,16 @@ create_dumb(struct gbm_device *gbm,
>  {
>     struct gbm_dri_device *dri = gbm_dri_device(gbm);
>     struct drm_mode_create_dumb create_arg;
> -   struct drm_mode_map_dumb map_arg;
>     struct gbm_dri_bo *bo;
>     struct drm_mode_destroy_dumb destroy_arg;
>     int ret;
> +   int is_cursor, is_scanout;
>  
> -   if (!(usage & GBM_BO_USE_CURSOR_64X64)) {
> -      errno = EINVAL;
> -      return NULL;
> -   }
> -   if (format != GBM_FORMAT_ARGB8888) {
> +   is_cursor = (usage & GBM_BO_USE_CURSOR_64X64) != 0 &&
> +      format == GBM_FORMAT_ARGB8888;
> +   is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 &&
> +      format == GBM_FORMAT_XRGB8888;
> +   if (!is_cursor && !is_scanout) {
>        errno = EINVAL;
>        return NULL;
>     }
> @@ -598,16 +737,7 @@ create_dumb(struct gbm_device *gbm,
>     bo->handle = create_arg.handle;
>     bo->size = create_arg.size;
>  
> -   memset(&map_arg, 0, sizeof(map_arg));
> -   map_arg.handle = bo->handle;
> -
> -   ret = drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
> -   if (ret)
> -      goto destroy_dumb;
> -
> -   bo->map = mmap(0, bo->size, PROT_WRITE,
> -                  MAP_SHARED, dri->base.base.fd, map_arg.offset);
> -   if (bo->map == MAP_FAILED)
> +   if (gbm_dri_bo_map(bo) == NULL)
>        goto destroy_dumb;
>  
>     return &bo->base.base;
> @@ -632,7 +762,7 @@ gbm_dri_bo_create(struct gbm_device *gbm,
>     int dri_format;
>     unsigned dri_use = 0;
>  
> -   if (usage & GBM_BO_USE_WRITE)
> +   if (usage & GBM_BO_USE_WRITE || dri->image == NULL)
>        return create_dumb(gbm, width, height, format, usage);
>  
>     bo = calloc(1, sizeof *bo);
> diff --git a/src/gbm/backends/dri/gbm_driint.h b/src/gbm/backends/dri/gbm_driint.h
> index 9c4392d..74cbc5b 100644
> --- a/src/gbm/backends/dri/gbm_driint.h
> +++ b/src/gbm/backends/dri/gbm_driint.h
> @@ -47,6 +47,7 @@ struct gbm_dri_device {
>     const __DRIcoreExtension   *core;
>     const __DRIdri2Extension   *dri2;
>     const __DRIimageExtension  *image;
> +   const __DRIswrastExtension *swrast;
>     const __DRI2flushExtension *flush;
>     const __DRIdri2LoaderExtension *loader;
>  
> @@ -72,6 +73,22 @@ struct gbm_dri_device {
>                              void *loaderPrivate,
>                              uint32_t buffer_mask,
>                              struct __DRIimageList *buffers);
> +   void (*swrast_put_image2)(__DRIdrawable *driDrawable,
> +                             int            op,
> +                             int            x,
> +                             int            y,
> +                             int            width,
> +                             int            height,
> +                             int            stride,
> +                             char          *data,
> +                             void          *loaderPrivate);
> +   void (*swrast_get_image)(__DRIdrawable *driDrawable,
> +                            int            x,
> +                            int            y,
> +                            int            width,
> +                            int            height,
> +                            char          *data,
> +                            void          *loaderPrivate);
>  
>     struct wl_drm *wl_drm;
>  };
> @@ -81,7 +98,7 @@ struct gbm_dri_bo {
>  
>     __DRIimage *image;
>  
> -   /* Only used for cursors */
> +   /* Used for cursors and the swrast front BO */
>     uint32_t handle, size;
>     void *map;
>  };
> diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h
> index 92d472a..6ade720 100644
> --- a/src/gbm/main/gbm.h
> +++ b/src/gbm/main/gbm.h
> @@ -285,6 +285,9 @@ gbm_surface_create(struct gbm_device *gbm,
>                     uint32_t width, uint32_t height,
>  		   uint32_t format, uint32_t flags);
>  
> +int
> +gbm_surface_needs_lock_front_buffer(struct gbm_surface *surface);
> +
>  struct gbm_bo *
>  gbm_surface_lock_front_buffer(struct gbm_surface *surface);
>  
> diff --git a/src/loader/loader.c b/src/loader/loader.c
> index 666d015..8361cf4 100644
> --- a/src/loader/loader.c
> +++ b/src/loader/loader.c
> @@ -67,6 +67,7 @@
>  #include <stdarg.h>
>  #include <stdio.h>
>  #include <string.h>
> +#include <stdlib.h>
>  #ifdef HAVE_LIBUDEV
>  #include <assert.h>
>  #include <dlfcn.h>
> @@ -325,6 +326,11 @@ loader_get_driver_for_fd(int fd, unsigned driver_types)
>     if (!driver_types)
>        driver_types = _LOADER_GALLIUM | _LOADER_DRI;
>  
> +   if (getenv("LIBGL_ALWAYS_SOFTWARE") != NULL) {
> +      log_(_LOADER_INFO, "using software rendering (forced by environment)\n");
> +      return "swrast";
> +   }
> +
Not a fan of this. What exatly are you trying to achieve here ?

-Emil
>     if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) {
>  
>  #ifndef __NOT_HAVE_DRM_H
> 



More information about the mesa-dev mailing list