diff options
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 7 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 3 | ||||
-rw-r--r-- | src/egl/drivers/dri2/platform_x11_dri3.c | 101 |
3 files changed, 96 insertions, 15 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index c06a0ca0995..1bd57c9ea31 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -881,6 +881,13 @@ dri2_setup_extensions(_EGLDisplay *disp) if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false)) return EGL_FALSE; +#ifdef HAVE_DRI3 + dri2_dpy->multibuffers_available = + (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 && + dri2_dpy->dri3_minor_version >= 2)) && + (dri2_dpy->image && dri2_dpy->image->base.version >= 15); +#endif + dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true); return EGL_TRUE; } diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index d36d02c3c49..00c4768d421 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -199,6 +199,9 @@ struct dri2_egl_display xcb_screen_t *screen; bool swap_available; #ifdef HAVE_DRI3 + bool multibuffers_available; + int dri3_major_version; + int dri3_minor_version; struct loader_dri3_extensions loader_dri3_ext; #endif #endif diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c index 2073c592dc9..c1efa930159 100644 --- a/src/egl/drivers/dri2/platform_x11_dri3.c +++ b/src/egl/drivers/dri2/platform_x11_dri3.c @@ -39,6 +39,23 @@ #include "loader.h" #include "loader_dri3_helper.h" +static uint32_t +dri3_format_for_depth(uint32_t depth) +{ + switch (depth) { + case 16: + return __DRI_IMAGE_FORMAT_RGB565; + case 24: + return __DRI_IMAGE_FORMAT_XRGB8888; + case 30: + return __DRI_IMAGE_FORMAT_XRGB2101010; + case 32: + return __DRI_IMAGE_FORMAT_ARGB8888; + default: + return __DRI_IMAGE_FORMAT_NONE; + } +} + static struct dri3_egl_surface * loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) { size_t offset = offsetof(struct dri3_egl_surface, loader_drawable); @@ -168,7 +185,9 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, if (loader_dri3_drawable_init(dri2_dpy->conn, drawable, dri2_dpy->dri_screen, - dri2_dpy->is_different_gpu, dri_config, + dri2_dpy->is_different_gpu, + dri2_dpy->multibuffers_available, + dri_config, &dri2_dpy->loader_dri3_ext, &egl_dri3_vtable, &dri3_surf->loader_drawable)) { @@ -274,20 +293,8 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, return NULL; } - switch (bp_reply->depth) { - case 16: - format = __DRI_IMAGE_FORMAT_RGB565; - break; - case 24: - format = __DRI_IMAGE_FORMAT_XRGB8888; - break; - case 30: - format = __DRI_IMAGE_FORMAT_XRGB2101010; - break; - case 32: - format = __DRI_IMAGE_FORMAT_ARGB8888; - break; - default: + format = dri3_format_for_depth(bp_reply->depth); + if (format == __DRI_IMAGE_FORMAT_NONE) { _eglError(EGL_BAD_PARAMETER, "dri3_create_image_khr: unsupported pixmap depth"); free(bp_reply); @@ -316,12 +323,73 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, } static _EGLImage * +dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, + const EGLint *attr_list) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_image *dri2_img; + xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie; + xcb_dri3_buffers_from_pixmap_reply_t *bp_reply; + xcb_drawable_t drawable; + unsigned int format; + + drawable = (xcb_drawable_t) (uintptr_t) buffer; + bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable); + bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn, + bp_cookie, NULL); + + if (!bp_reply) { + _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr"); + return EGL_NO_IMAGE_KHR; + } + + format = dri3_format_for_depth(bp_reply->depth); + if (format == __DRI_IMAGE_FORMAT_NONE) { + _eglError(EGL_BAD_PARAMETER, + "dri3_create_image_khr: unsupported pixmap depth"); + free(bp_reply); + return EGL_NO_IMAGE_KHR; + } + + dri2_img = malloc(sizeof *dri2_img); + if (!dri2_img) { + _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr"); + free(bp_reply); + return EGL_NO_IMAGE_KHR; + } + + _eglInitImage(&dri2_img->base, disp); + + dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn, + bp_reply, + format, + dri2_dpy->dri_screen, + dri2_dpy->image, + dri2_img); + free(bp_reply); + + if (!dri2_img->dri_image) { + _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr"); + free(dri2_img); + return EGL_NO_IMAGE_KHR; + } + + return &dri2_img->base; +} + +static _EGLImage * dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list) { + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + switch (target) { case EGL_NATIVE_PIXMAP_KHR: + if (dri2_dpy->multibuffers_available) + return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer, + attr_list); return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list); default: return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); @@ -483,6 +551,9 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy) free(error); return EGL_FALSE; } + + dri2_dpy->dri3_major_version = dri3_query->major_version; + dri2_dpy->dri3_minor_version = dri3_query->minor_version; free(dri3_query); present_query = |