+static _EGLImage *
+dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
+ const EGLint *attr_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_image *dri2_img;
+ _EGLImageAttribs attrs;
+ unsigned int dri_use, valid_mask;
+ int format;
+ EGLint err = EGL_SUCCESS;
+
+ (void) drv;
+
+ dri2_img = malloc(sizeof *dri2_img);
+ if (!dri2_img) {
+ _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ if (!attr_list) {
+ err = EGL_BAD_PARAMETER;
+ goto cleanup_img;
+ }
+
+ if (!_eglInitImage(&dri2_img->base, disp)) {
+ err = EGL_BAD_PARAMETER;
+ goto cleanup_img;
+ }
+
+ err = _eglParseImageAttribList(&attrs, disp, attr_list);
+ if (err != EGL_SUCCESS)
+ goto cleanup_img;
+
+ if (attrs.Width <= 0 || attrs.Height <= 0) {
+ _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
+ attrs.Width, attrs.Height);
+ goto cleanup_img;
+ }
+
+ switch (attrs.DRMBufferFormatMESA) {
+ case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+ format = __DRI_IMAGE_FORMAT_ARGB8888;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
+ attrs.DRMBufferFormatMESA);
+ goto cleanup_img;
+ }
+
+ valid_mask =
+ EGL_DRM_BUFFER_USE_SCANOUT_MESA |
+ EGL_DRM_BUFFER_USE_SHARE_MESA |
+ EGL_DRM_BUFFER_USE_CURSOR_MESA;
+ if (attrs.DRMBufferUseMESA & ~valid_mask) {
+ _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
+ attrs.DRMBufferUseMESA & ~valid_mask);
+ goto cleanup_img;
+ }
+
+ dri_use = 0;
+ if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
+ dri_use |= __DRI_IMAGE_USE_SHARE;
+ if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
+ dri_use |= __DRI_IMAGE_USE_SCANOUT;
+ if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
+ dri_use |= __DRI_IMAGE_USE_CURSOR;
+
+ dri2_img->dri_image =
+ dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+ attrs.Width, attrs.Height,
+ format, dri_use, dri2_img);
+ if (dri2_img->dri_image == NULL) {
+ err = EGL_BAD_ALLOC;
+ goto cleanup_img;
+ }
+
+ return &dri2_img->base;
+
+ cleanup_img:
+ free(dri2_img);
+ _eglError(err, "dri2_create_drm_image_mesa");
+
+ return EGL_NO_IMAGE_KHR;
+}
+
+static EGLBoolean
+dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
+ EGLint *name, EGLint *handle, EGLint *stride)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+ (void) drv;
+
+ if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
+ __DRI_IMAGE_ATTRIB_NAME, name)) {
+ _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
+ return EGL_FALSE;
+ }
+
+ if (handle)
+ dri2_dpy->image->queryImage(dri2_img->dri_image,
+ __DRI_IMAGE_ATTRIB_HANDLE, handle);
+
+ if (stride)
+ dri2_dpy->image->queryImage(dri2_img->dri_image,
+ __DRI_IMAGE_ATTRIB_STRIDE, stride);
+
+ return EGL_TRUE;
+}
+
+#ifdef HAVE_WAYLAND_PLATFORM
+
+static void *
+dri2_wl_reference_buffer(void *user_data, uint32_t name,
+ int32_t width, int32_t height,
+ uint32_t stride, struct wl_visual *visual)
+{
+ _EGLDisplay *disp = user_data;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ __DRIimage *image;
+
+ image = dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
+ width, height,
+ __DRI_IMAGE_FORMAT_ARGB8888,
+ name, stride / 4,
+ NULL);
+
+ return image;
+}
+
+static void
+dri2_wl_release_buffer(void *user_data, void *buffer)
+{
+ _EGLDisplay *disp = user_data;
+ __DRIimage *image = buffer;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ dri2_dpy->image->destroyImage(image);
+}
+
+static struct wayland_drm_callbacks wl_drm_callbacks = {
+ .authenticate = NULL,
+ .reference_buffer = dri2_wl_reference_buffer,
+ .release_buffer = dri2_wl_release_buffer
+};
+
+static EGLBoolean
+dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
+ struct wl_display *wl_dpy)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ (void) drv;
+
+ if (dri2_dpy->wl_server_drm)
+ return EGL_FALSE;
+
+ wl_drm_callbacks.authenticate =
+ (int(*)(void *, uint32_t)) dri2_dpy->authenticate;
+
+ dri2_dpy->wl_server_drm =
+ wayland_drm_init(wl_dpy, dri2_dpy->device_name,
+ &wl_drm_callbacks, disp);
+
+ if (!dri2_dpy->wl_server_drm)
+ return EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
+ struct wl_display *wl_dpy)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ (void) drv;
+
+ if (!dri2_dpy->wl_server_drm)
+ return EGL_FALSE;
+
+ wayland_drm_uninit(dri2_dpy->wl_server_drm);
+ dri2_dpy->wl_server_drm = NULL;
+
+ return EGL_TRUE;
+}
+#endif
+
+static void
+dri2_unload(_EGLDriver *drv)
+{
+ struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+
+ if (dri2_drv->handle)
+ dlclose(dri2_drv->handle);
+ free(dri2_drv);
+}
+
+static EGLBoolean
+dri2_load(_EGLDriver *drv)
+{
+ struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+#ifdef HAVE_SHARED_GLAPI
+ const char *libname = "libglapi.so.0";
+#else
+ /*
+ * Both libGL.so and libglapi.so are glapi providers. There is no way to
+ * tell which one to load.
+ */
+ const char *libname = NULL;
+#endif
+ void *handle;
+
+ /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
+ handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
+ if (handle) {
+ dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
+ dlsym(handle, "_glapi_get_proc_address");
+ if (!dri2_drv->get_proc_address || !libname) {
+ /* no need to keep a reference */
+ dlclose(handle);
+ handle = NULL;
+ }
+ }
+
+ /* if glapi is not available, loading DRI drivers will fail */
+ if (!dri2_drv->get_proc_address) {
+ _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
+ return EGL_FALSE;
+ }
+
+ dri2_drv->glFlush = (void (*)(void))
+ dri2_drv->get_proc_address("glFlush");
+
+ dri2_drv->handle = handle;
+
+ return EGL_TRUE;
+}
+