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) [Emil Velikov] - Fix make check. - Split dri_open_driver() from dri_load_driver(). - Don't try to bind the swrast extensions when using dri. - Handle swrast->CreateNewScreen() failure. - strdup the driver_name, as it's free'd at destruction. - s/LIBGL_ALWAYS_SOFTWARE/GBM_ALWAYS_SOFTWARE/ - Move gbm_dri_bo_map/unmap to gbm_driiint.h. - Correct swrast fallback logic. Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>tags/10.3-branchpoint
@@ -44,6 +44,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 +53,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,13 +126,22 @@ 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"); | |||
_eglError(EGL_BAD_ALLOC, "createNewDrawable()"); | |||
goto cleanup_surf; | |||
} | |||
@@ -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,73 @@ dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id) | |||
return drmAuthMagic(dri2_dpy->fd, id); | |||
} | |||
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; | |||
if (get_swrast_front_bo(dri2_surf) < 0) | |||
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; | |||
if (get_swrast_front_bo(dri2_surf) < 0) | |||
return; | |||
bo = gbm_dri_bo(dri2_surf->current->bo); | |||
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, | |||
@@ -533,6 +639,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; | |||
@@ -542,6 +649,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; | |||
@@ -572,10 +681,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 */ |
@@ -34,7 +34,6 @@ | |||
#include <limits.h> | |||
#include <sys/types.h> | |||
#include <sys/mman.h> | |||
#include <unistd.h> | |||
#include <dlfcn.h> | |||
#include <xf86drm.h> | |||
@@ -124,6 +123,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 +216,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, | |||
}; | |||
@@ -175,6 +252,12 @@ static struct dri_extension_match gbm_dri_device_extensions[] = { | |||
{ NULL, 0, 0 } | |||
}; | |||
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, | |||
@@ -203,8 +286,8 @@ dri_bind_extensions(struct gbm_dri_device *dri, | |||
return ret; | |||
} | |||
static int | |||
dri_load_driver(struct gbm_dri_device *dri) | |||
static const __DRIextension ** | |||
dri_open_driver(struct gbm_dri_device *dri) | |||
{ | |||
const __DRIextension **extensions = NULL; | |||
char path[PATH_MAX], *search_paths, *p, *next, *end; | |||
@@ -255,7 +338,7 @@ dri_load_driver(struct gbm_dri_device *dri) | |||
if (dri->driver == NULL) { | |||
fprintf(stderr, "gbm: failed to open any driver (search paths %s)", | |||
search_paths); | |||
return -1; | |||
return NULL; | |||
} | |||
if (asprintf(&get_extensions_name, "%s_%s", | |||
@@ -274,16 +357,48 @@ dri_load_driver(struct gbm_dri_device *dri) | |||
if (extensions == NULL) { | |||
fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror()); | |||
dlclose(dri->driver); | |||
} | |||
return extensions; | |||
} | |||
static int | |||
dri_load_driver(struct gbm_dri_device *dri) | |||
{ | |||
const __DRIextension **extensions; | |||
extensions = dri_open_driver(dri); | |||
if (!extensions) | |||
return -1; | |||
if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) { | |||
dlclose(dri->driver); | |||
fprintf(stderr, "failed to bind extensions\n"); | |||
return -1; | |||
} | |||
dri->driver_extensions = extensions; | |||
if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) { | |||
return 0; | |||
} | |||
static int | |||
dri_load_driver_swrast(struct gbm_dri_device *dri) | |||
{ | |||
const __DRIextension **extensions; | |||
extensions = dri_open_driver(dri); | |||
if (!extensions) | |||
return -1; | |||
if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) { | |||
dlclose(dri->driver); | |||
fprintf(stderr, "failed to bind extensions\n"); | |||
return -1; | |||
} | |||
dri->driver_extensions = extensions; | |||
return 0; | |||
} | |||
@@ -338,6 +453,43 @@ free_screen: | |||
return ret; | |||
} | |||
static int | |||
dri_screen_create_swrast(struct gbm_dri_device *dri) | |||
{ | |||
int ret; | |||
dri->base.driver_name = strdup("swrast"); | |||
if (dri->base.driver_name == NULL) | |||
return -1; | |||
ret = dri_load_driver_swrast(dri); | |||
if (ret) { | |||
fprintf(stderr, "failed to load swrast driver\n"); | |||
return ret; | |||
} | |||
dri->extensions = gbm_dri_screen_extensions; | |||
if (dri->swrast == NULL) | |||
return -1; | |||
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; | |||
dri->lookup_image = NULL; | |||
dri->lookup_user_data = NULL; | |||
return 0; | |||
} | |||
static int | |||
gbm_dri_is_format_supported(struct gbm_device *gbm, | |||
uint32_t format, | |||
@@ -403,7 +555,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); | |||
@@ -449,7 +601,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) { | |||
errno = ENOSYS; | |||
return NULL; | |||
} | |||
@@ -573,16 +725,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)) { | |||
errno = EINVAL; | |||
return NULL; | |||
} | |||
if (format != GBM_FORMAT_ARGB8888) { | |||
is_cursor = (usage & GBM_BO_USE_CURSOR) != 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; | |||
} | |||
@@ -608,16 +760,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; | |||
@@ -642,7 +785,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); | |||
@@ -753,7 +896,7 @@ static struct gbm_device * | |||
dri_device_create(int fd) | |||
{ | |||
struct gbm_dri_device *dri; | |||
int ret; | |||
int ret, force_sw; | |||
dri = calloc(1, sizeof *dri); | |||
if (!dri) | |||
@@ -773,7 +916,15 @@ dri_device_create(int fd) | |||
dri->base.type = GBM_DRM_DRIVER_TYPE_DRI; | |||
dri->base.base.name = "drm"; | |||
ret = dri_screen_create(dri); | |||
force_sw = getenv("GBM_ALWAYS_SOFTWARE") != NULL; | |||
if (!force_sw) { | |||
ret = dri_screen_create(dri); | |||
if (ret) | |||
ret = dri_screen_create_swrast(dri); | |||
} else { | |||
ret = dri_screen_create_swrast(dri); | |||
} | |||
if (ret) | |||
goto err_dri; | |||
@@ -28,6 +28,7 @@ | |||
#ifndef _GBM_DRI_INTERNAL_H_ | |||
#define _GBM_DRI_INTERNAL_H_ | |||
#include <sys/mman.h> | |||
#include "gbmint.h" | |||
#include "common_drm.h" | |||
@@ -36,6 +37,7 @@ | |||
#include "GL/internal/dri_interface.h" | |||
struct gbm_dri_surface; | |||
struct gbm_dri_bo; | |||
struct gbm_dri_device { | |||
struct gbm_drm_device base; | |||
@@ -47,6 +49,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 +75,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 +100,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; | |||
}; | |||
@@ -110,4 +129,40 @@ gbm_dri_surface(struct gbm_surface *surface) | |||
return (struct gbm_dri_surface *) surface; | |||
} | |||
static inline 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) { | |||
bo->map = NULL; | |||
return NULL; | |||
} | |||
return bo->map; | |||
} | |||
static inline void | |||
gbm_dri_bo_unmap(struct gbm_dri_bo *bo) | |||
{ | |||
munmap(bo->map, bo->size); | |||
bo->map = NULL; | |||
} | |||
#endif |
@@ -21,6 +21,7 @@ gbm_bo_set_user_data | |||
gbm_bo_get_user_data | |||
gbm_bo_destroy | |||
gbm_surface_create | |||
gbm_surface_needs_lock_front_buffer | |||
gbm_surface_lock_front_buffer | |||
gbm_surface_release_buffer | |||
gbm_surface_has_free_buffers |
@@ -287,6 +287,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); | |||