2014-05-15 2:47 GMT+02:00 Emil Velikov <emil.l.veli...@gmail.com>: > On 05/05/14 17:07, Giovanni Campagna wrote: >> From: Giovanni Campagna <gcampa...@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; > + }
Except that I don't want to destroy the buffer on failure, it might be a transient issue like out of address space, and the code is not prepared to reallocate the buffer. I could "clean up" the map_dumb ioctl, except that it is a getter ioctl really, there is nothing to cleanup. > >> + >> + 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 ? Which ioctl? You don't want to destroy on unmap, it would make the whole drawing useless. >> +} >> + > 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. Well, to me it's more clear to rename gbm_dri_device_extensions to gbm_dri2_device_extensions, because they are the marker for a dri2 driver. And the dri_core_extensions are only used with dri2 drivers, so they make sense as dri2_core_extensions. >> +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 ? No other loader does that. >> } >> >> 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 ? Debugging, mostly. It allows testing this code on a real drm driver. Giovanni _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev