egl/x11: Support DRI3 v1.1
Add support for DRI3 v1.1, which allows pixmaps to be backed by multi-planar buffers, or those with format modifiers. This is both for allocating render buffers, as well as EGLImage imports from a native pixmap (EGL_NATIVE_PIXMAP_KHR). Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com> Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com> Reviewed-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
parent
61309c2a72
commit
069fdd5f9f
|
@ -881,6 +881,13 @@ dri2_setup_extensions(_EGLDisplay *disp)
|
||||||
if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
|
if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
|
||||||
return EGL_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);
|
dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true);
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,9 @@ struct dri2_egl_display
|
||||||
xcb_screen_t *screen;
|
xcb_screen_t *screen;
|
||||||
bool swap_available;
|
bool swap_available;
|
||||||
#ifdef HAVE_DRI3
|
#ifdef HAVE_DRI3
|
||||||
|
bool multibuffers_available;
|
||||||
|
int dri3_major_version;
|
||||||
|
int dri3_minor_version;
|
||||||
struct loader_dri3_extensions loader_dri3_ext;
|
struct loader_dri3_extensions loader_dri3_ext;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,23 @@
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "loader_dri3_helper.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 *
|
static struct dri3_egl_surface *
|
||||||
loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
|
loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
|
||||||
size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
|
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,
|
if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
|
||||||
dri2_dpy->dri_screen,
|
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,
|
&dri2_dpy->loader_dri3_ext,
|
||||||
&egl_dri3_vtable,
|
&egl_dri3_vtable,
|
||||||
&dri3_surf->loader_drawable)) {
|
&dri3_surf->loader_drawable)) {
|
||||||
|
@ -274,20 +293,8 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (bp_reply->depth) {
|
format = dri3_format_for_depth(bp_reply->depth);
|
||||||
case 16:
|
if (format == __DRI_IMAGE_FORMAT_NONE) {
|
||||||
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:
|
|
||||||
_eglError(EGL_BAD_PARAMETER,
|
_eglError(EGL_BAD_PARAMETER,
|
||||||
"dri3_create_image_khr: unsupported pixmap depth");
|
"dri3_create_image_khr: unsupported pixmap depth");
|
||||||
free(bp_reply);
|
free(bp_reply);
|
||||||
|
@ -315,13 +322,74 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
|
||||||
return &dri2_img->base;
|
return &dri2_img->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 *
|
static _EGLImage *
|
||||||
dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
|
dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
|
||||||
_EGLContext *ctx, EGLenum target,
|
_EGLContext *ctx, EGLenum target,
|
||||||
EGLClientBuffer buffer, const EGLint *attr_list)
|
EGLClientBuffer buffer, const EGLint *attr_list)
|
||||||
{
|
{
|
||||||
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||||
|
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case EGL_NATIVE_PIXMAP_KHR:
|
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);
|
return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
|
||||||
default:
|
default:
|
||||||
return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
|
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);
|
free(error);
|
||||||
return EGL_FALSE;
|
return EGL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dri2_dpy->dri3_major_version = dri3_query->major_version;
|
||||||
|
dri2_dpy->dri3_minor_version = dri3_query->minor_version;
|
||||||
free(dri3_query);
|
free(dri3_query);
|
||||||
|
|
||||||
present_query =
|
present_query =
|
||||||
|
|
|
@ -357,7 +357,10 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,
|
||||||
{
|
{
|
||||||
struct dri3_drawable *pdraw;
|
struct dri3_drawable *pdraw;
|
||||||
struct dri3_screen *psc = (struct dri3_screen *) base;
|
struct dri3_screen *psc = (struct dri3_screen *) base;
|
||||||
|
const struct dri3_display *const pdp = (struct dri3_display *)
|
||||||
|
base->display->dri3Display;
|
||||||
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
|
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
|
||||||
|
bool has_multibuffer = false;
|
||||||
|
|
||||||
pdraw = calloc(1, sizeof(*pdraw));
|
pdraw = calloc(1, sizeof(*pdraw));
|
||||||
if (!pdraw)
|
if (!pdraw)
|
||||||
|
@ -368,11 +371,16 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,
|
||||||
pdraw->base.drawable = drawable;
|
pdraw->base.drawable = drawable;
|
||||||
pdraw->base.psc = &psc->base;
|
pdraw->base.psc = &psc->base;
|
||||||
|
|
||||||
|
if ((psc->image && psc->image->base.version >= 15) &&
|
||||||
|
(pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)))
|
||||||
|
has_multibuffer = true;
|
||||||
|
|
||||||
(void) __glXInitialize(psc->base.dpy);
|
(void) __glXInitialize(psc->base.dpy);
|
||||||
|
|
||||||
if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
|
if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
|
||||||
xDrawable, psc->driScreen,
|
xDrawable, psc->driScreen,
|
||||||
psc->is_different_gpu, config->driConfig,
|
psc->is_different_gpu, has_multibuffer,
|
||||||
|
config->driConfig,
|
||||||
&psc->loader_dri3_ext, &glx_dri3_vtable,
|
&psc->loader_dri3_ext, &glx_dri3_vtable,
|
||||||
&pdraw->loader_drawable)) {
|
&pdraw->loader_drawable)) {
|
||||||
free(pdraw);
|
free(pdraw);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <X11/xshmfence.h>
|
#include <X11/xshmfence.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
|
|
||||||
#include "loader_dri3_helper.h"
|
#include "loader_dri3_helper.h"
|
||||||
#include "util/macros.h"
|
#include "util/macros.h"
|
||||||
|
#include "drm_fourcc.h"
|
||||||
|
|
||||||
/* From xmlpool/options.h, user exposed so should be stable */
|
/* From xmlpool/options.h, user exposed so should be stable */
|
||||||
#define DRI_CONF_VBLANK_NEVER 0
|
#define DRI_CONF_VBLANK_NEVER 0
|
||||||
|
@ -257,6 +259,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
|
||||||
xcb_drawable_t drawable,
|
xcb_drawable_t drawable,
|
||||||
__DRIscreen *dri_screen,
|
__DRIscreen *dri_screen,
|
||||||
bool is_different_gpu,
|
bool is_different_gpu,
|
||||||
|
bool multiplanes_available,
|
||||||
const __DRIconfig *dri_config,
|
const __DRIconfig *dri_config,
|
||||||
struct loader_dri3_extensions *ext,
|
struct loader_dri3_extensions *ext,
|
||||||
const struct loader_dri3_vtable *vtable,
|
const struct loader_dri3_vtable *vtable,
|
||||||
|
@ -274,6 +277,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
|
||||||
draw->drawable = drawable;
|
draw->drawable = drawable;
|
||||||
draw->dri_screen = dri_screen;
|
draw->dri_screen = dri_screen;
|
||||||
draw->is_different_gpu = is_different_gpu;
|
draw->is_different_gpu = is_different_gpu;
|
||||||
|
draw->multiplanes_available = multiplanes_available;
|
||||||
|
|
||||||
draw->have_back = 0;
|
draw->have_back = 0;
|
||||||
draw->have_fake_front = 0;
|
draw->have_fake_front = 0;
|
||||||
|
@ -1023,6 +1027,41 @@ image_format_to_fourcc(int format)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
has_supported_modifier(struct loader_dri3_drawable *draw, unsigned int format,
|
||||||
|
uint64_t *modifiers, uint32_t count)
|
||||||
|
{
|
||||||
|
uint64_t *supported_modifiers;
|
||||||
|
int32_t supported_modifiers_count;
|
||||||
|
bool found = false;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!draw->ext->image->queryDmaBufModifiers(draw->dri_screen,
|
||||||
|
format, 0, NULL, NULL,
|
||||||
|
&supported_modifiers_count) ||
|
||||||
|
supported_modifiers_count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
supported_modifiers = malloc(supported_modifiers_count * sizeof(uint64_t));
|
||||||
|
if (!supported_modifiers)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
draw->ext->image->queryDmaBufModifiers(draw->dri_screen, format,
|
||||||
|
supported_modifiers_count,
|
||||||
|
supported_modifiers, NULL,
|
||||||
|
&supported_modifiers_count);
|
||||||
|
|
||||||
|
for (i = 0; !found && i < supported_modifiers_count; i++) {
|
||||||
|
for (j = 0; !found && j < count; j++) {
|
||||||
|
if (supported_modifiers[i] == modifiers[j])
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(supported_modifiers);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/** loader_dri3_alloc_render_buffer
|
/** loader_dri3_alloc_render_buffer
|
||||||
*
|
*
|
||||||
* Use the driver createImage function to construct a __DRIimage, then
|
* Use the driver createImage function to construct a __DRIimage, then
|
||||||
|
@ -1039,8 +1078,10 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
|
||||||
xcb_pixmap_t pixmap;
|
xcb_pixmap_t pixmap;
|
||||||
xcb_sync_fence_t sync_fence;
|
xcb_sync_fence_t sync_fence;
|
||||||
struct xshmfence *shm_fence;
|
struct xshmfence *shm_fence;
|
||||||
int buffer_fd, fence_fd;
|
int buffer_fds[4], fence_fd;
|
||||||
int stride;
|
int num_planes = 0;
|
||||||
|
int i, mod;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Create an xshmfence object and
|
/* Create an xshmfence object and
|
||||||
* prepare to send that to the X server
|
* prepare to send that to the X server
|
||||||
|
@ -1065,13 +1106,79 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
|
||||||
goto no_image;
|
goto no_image;
|
||||||
|
|
||||||
if (!draw->is_different_gpu) {
|
if (!draw->is_different_gpu) {
|
||||||
buffer->image = draw->ext->image->createImage(draw->dri_screen,
|
if (draw->multiplanes_available &&
|
||||||
width, height,
|
draw->ext->image->base.version >= 15 &&
|
||||||
format,
|
draw->ext->image->queryDmaBufModifiers &&
|
||||||
__DRI_IMAGE_USE_SHARE |
|
draw->ext->image->createImageWithModifiers) {
|
||||||
__DRI_IMAGE_USE_SCANOUT |
|
xcb_dri3_get_supported_modifiers_cookie_t mod_cookie;
|
||||||
__DRI_IMAGE_USE_BACKBUFFER,
|
xcb_dri3_get_supported_modifiers_reply_t *mod_reply;
|
||||||
buffer);
|
xcb_generic_error_t *error = NULL;
|
||||||
|
uint64_t *modifiers = NULL;
|
||||||
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
mod_cookie = xcb_dri3_get_supported_modifiers(draw->conn,
|
||||||
|
draw->drawable,
|
||||||
|
depth, buffer->cpp * 8);
|
||||||
|
mod_reply = xcb_dri3_get_supported_modifiers_reply(draw->conn,
|
||||||
|
mod_cookie,
|
||||||
|
&error);
|
||||||
|
if (!mod_reply)
|
||||||
|
goto no_image;
|
||||||
|
|
||||||
|
if (mod_reply->num_window_modifiers) {
|
||||||
|
count = mod_reply->num_window_modifiers;
|
||||||
|
modifiers = malloc(count * sizeof(uint64_t));
|
||||||
|
if (!modifiers) {
|
||||||
|
free(mod_reply);
|
||||||
|
goto no_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(modifiers,
|
||||||
|
xcb_dri3_get_supported_modifiers_window_modifiers(mod_reply),
|
||||||
|
count * sizeof(uint64_t));
|
||||||
|
|
||||||
|
if (!has_supported_modifier(draw, image_format_to_fourcc(format),
|
||||||
|
modifiers, count)) {
|
||||||
|
free(modifiers);
|
||||||
|
count = 0;
|
||||||
|
modifiers = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod_reply->num_screen_modifiers && modifiers == NULL) {
|
||||||
|
count = mod_reply->num_screen_modifiers;
|
||||||
|
modifiers = malloc(count * sizeof(uint64_t));
|
||||||
|
if (!modifiers) {
|
||||||
|
free(modifiers);
|
||||||
|
free(mod_reply);
|
||||||
|
goto no_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(modifiers,
|
||||||
|
xcb_dri3_get_supported_modifiers_screen_modifiers(mod_reply),
|
||||||
|
count * sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(mod_reply);
|
||||||
|
|
||||||
|
buffer->image = draw->ext->image->createImageWithModifiers(draw->dri_screen,
|
||||||
|
width, height,
|
||||||
|
format,
|
||||||
|
modifiers,
|
||||||
|
count,
|
||||||
|
buffer);
|
||||||
|
free(modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer->image)
|
||||||
|
buffer->image = draw->ext->image->createImage(draw->dri_screen,
|
||||||
|
width, height,
|
||||||
|
format,
|
||||||
|
__DRI_IMAGE_USE_SHARE |
|
||||||
|
__DRI_IMAGE_USE_SCANOUT |
|
||||||
|
__DRI_IMAGE_USE_BACKBUFFER,
|
||||||
|
buffer);
|
||||||
|
|
||||||
pixmap_buffer = buffer->image;
|
pixmap_buffer = buffer->image;
|
||||||
|
|
||||||
if (!buffer->image)
|
if (!buffer->image)
|
||||||
|
@ -1099,25 +1206,67 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
|
||||||
goto no_linear_buffer;
|
goto no_linear_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* X wants the stride, so ask the image for it
|
/* X want some information about the planes, so ask the image for it
|
||||||
*/
|
*/
|
||||||
if (!draw->ext->image->queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_STRIDE,
|
if (!draw->ext->image->queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_NUM_PLANES,
|
||||||
&stride))
|
&num_planes))
|
||||||
goto no_buffer_attrib;
|
num_planes = 1;
|
||||||
|
|
||||||
buffer->pitch = stride;
|
for (i = 0; i < num_planes; i++) {
|
||||||
|
__DRIimage *image = draw->ext->image->fromPlanar(pixmap_buffer, i, NULL);
|
||||||
|
|
||||||
if (!draw->ext->image->queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD,
|
if (!image) {
|
||||||
&buffer_fd))
|
assert(i == 0);
|
||||||
goto no_buffer_attrib;
|
image = pixmap_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
xcb_dri3_pixmap_from_buffer(draw->conn,
|
ret = draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD,
|
||||||
(pixmap = xcb_generate_id(draw->conn)),
|
&buffer_fds[i]);
|
||||||
draw->drawable,
|
ret &= draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE,
|
||||||
buffer->size,
|
&buffer->strides[i]);
|
||||||
width, height, buffer->pitch,
|
ret &= draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET,
|
||||||
depth, buffer->cpp * 8,
|
&buffer->offsets[i]);
|
||||||
buffer_fd);
|
if (image != pixmap_buffer)
|
||||||
|
draw->ext->image->destroyImage(image);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
goto no_buffer_attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = draw->ext->image->queryImage(pixmap_buffer,
|
||||||
|
__DRI_IMAGE_ATTRIB_MODIFIER_UPPER, &mod);
|
||||||
|
buffer->modifier = (uint64_t) mod << 32;
|
||||||
|
ret &= draw->ext->image->queryImage(pixmap_buffer,
|
||||||
|
__DRI_IMAGE_ATTRIB_MODIFIER_LOWER, &mod);
|
||||||
|
buffer->modifier |= (uint64_t)(mod & 0xffffffff);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
buffer->modifier = DRM_FORMAT_MOD_INVALID;
|
||||||
|
|
||||||
|
pixmap = xcb_generate_id(draw->conn);
|
||||||
|
if (draw->multiplanes_available &&
|
||||||
|
buffer->modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
|
xcb_dri3_pixmap_from_buffers(draw->conn,
|
||||||
|
pixmap,
|
||||||
|
draw->drawable,
|
||||||
|
num_planes,
|
||||||
|
width, height,
|
||||||
|
buffer->strides[0], buffer->offsets[0],
|
||||||
|
buffer->strides[1], buffer->offsets[1],
|
||||||
|
buffer->strides[2], buffer->offsets[2],
|
||||||
|
buffer->strides[3], buffer->offsets[3],
|
||||||
|
depth, buffer->cpp * 8,
|
||||||
|
buffer->modifier,
|
||||||
|
buffer_fds);
|
||||||
|
} else {
|
||||||
|
xcb_dri3_pixmap_from_buffer(draw->conn,
|
||||||
|
pixmap,
|
||||||
|
draw->drawable,
|
||||||
|
buffer->size,
|
||||||
|
width, height, buffer->strides[0],
|
||||||
|
depth, buffer->cpp * 8,
|
||||||
|
buffer_fds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
xcb_dri3_fence_from_fd(draw->conn,
|
xcb_dri3_fence_from_fd(draw->conn,
|
||||||
pixmap,
|
pixmap,
|
||||||
|
@ -1139,6 +1288,9 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
no_buffer_attrib:
|
no_buffer_attrib:
|
||||||
|
do {
|
||||||
|
close(buffer_fds[i]);
|
||||||
|
} while (--i >= 0);
|
||||||
draw->ext->image->destroyImage(pixmap_buffer);
|
draw->ext->image->destroyImage(pixmap_buffer);
|
||||||
no_linear_buffer:
|
no_linear_buffer:
|
||||||
if (draw->is_different_gpu)
|
if (draw->is_different_gpu)
|
||||||
|
@ -1295,6 +1447,48 @@ loader_dri3_create_image(xcb_connection_t *c,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__DRIimage *
|
||||||
|
loader_dri3_create_image_from_buffers(xcb_connection_t *c,
|
||||||
|
xcb_dri3_buffers_from_pixmap_reply_t *bp_reply,
|
||||||
|
unsigned int format,
|
||||||
|
__DRIscreen *dri_screen,
|
||||||
|
const __DRIimageExtension *image,
|
||||||
|
void *loaderPrivate)
|
||||||
|
{
|
||||||
|
__DRIimage *ret;
|
||||||
|
int *fds;
|
||||||
|
uint32_t *strides_in, *offsets_in;
|
||||||
|
int strides[4], offsets[4];
|
||||||
|
unsigned error;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (bp_reply->nfd > 4)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fds = xcb_dri3_buffers_from_pixmap_reply_fds(c, bp_reply);
|
||||||
|
strides_in = xcb_dri3_buffers_from_pixmap_strides(bp_reply);
|
||||||
|
offsets_in = xcb_dri3_buffers_from_pixmap_offsets(bp_reply);
|
||||||
|
for (i = 0; i < bp_reply->nfd; i++) {
|
||||||
|
strides[i] = strides_in[i];
|
||||||
|
offsets[i] = offsets_in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = image->createImageFromDmaBufs2(dri_screen,
|
||||||
|
bp_reply->width,
|
||||||
|
bp_reply->height,
|
||||||
|
image_format_to_fourcc(format),
|
||||||
|
bp_reply->modifier,
|
||||||
|
fds, bp_reply->nfd,
|
||||||
|
strides, offsets,
|
||||||
|
0, 0, 0, 0, /* UNDEFINED */
|
||||||
|
&error, loaderPrivate);
|
||||||
|
|
||||||
|
for (i = 0; i < bp_reply->nfd; i++)
|
||||||
|
close(fds[i]);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/** dri3_get_pixmap_buffer
|
/** dri3_get_pixmap_buffer
|
||||||
*
|
*
|
||||||
* Get the DRM object for a pixmap from the X server and
|
* Get the DRM object for a pixmap from the X server and
|
||||||
|
@ -1308,10 +1502,10 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
|
||||||
int buf_id = loader_dri3_pixmap_buf_id(buffer_type);
|
int buf_id = loader_dri3_pixmap_buf_id(buffer_type);
|
||||||
struct loader_dri3_buffer *buffer = draw->buffers[buf_id];
|
struct loader_dri3_buffer *buffer = draw->buffers[buf_id];
|
||||||
xcb_drawable_t pixmap;
|
xcb_drawable_t pixmap;
|
||||||
xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
|
|
||||||
xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
|
|
||||||
xcb_sync_fence_t sync_fence;
|
xcb_sync_fence_t sync_fence;
|
||||||
struct xshmfence *shm_fence;
|
struct xshmfence *shm_fence;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
int fence_fd;
|
int fence_fd;
|
||||||
__DRIscreen *cur_screen;
|
__DRIscreen *cur_screen;
|
||||||
|
|
||||||
|
@ -1333,17 +1527,6 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
|
||||||
goto no_fence;
|
goto no_fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_dri3_fence_from_fd(draw->conn,
|
|
||||||
pixmap,
|
|
||||||
(sync_fence = xcb_generate_id(draw->conn)),
|
|
||||||
false,
|
|
||||||
fence_fd);
|
|
||||||
|
|
||||||
bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap);
|
|
||||||
bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie, NULL);
|
|
||||||
if (!bp_reply)
|
|
||||||
goto no_image;
|
|
||||||
|
|
||||||
/* Get the currently-bound screen or revert to using the drawable's screen if
|
/* Get the currently-bound screen or revert to using the drawable's screen if
|
||||||
* no contexts are currently bound. The latter case is at least necessary for
|
* no contexts are currently bound. The latter case is at least necessary for
|
||||||
* obs-studio, when using Window Capture (Xcomposite) as a Source.
|
* obs-studio, when using Window Capture (Xcomposite) as a Source.
|
||||||
|
@ -1353,27 +1536,62 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
|
||||||
cur_screen = draw->dri_screen;
|
cur_screen = draw->dri_screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format,
|
xcb_dri3_fence_from_fd(draw->conn,
|
||||||
cur_screen, draw->ext->image,
|
pixmap,
|
||||||
buffer);
|
(sync_fence = xcb_generate_id(draw->conn)),
|
||||||
|
false,
|
||||||
|
fence_fd);
|
||||||
|
|
||||||
|
if (draw->multiplanes_available &&
|
||||||
|
draw->ext->image->base.version >= 15 &&
|
||||||
|
draw->ext->image->createImageFromDmaBufs2) {
|
||||||
|
xcb_dri3_buffers_from_pixmap_cookie_t bps_cookie;
|
||||||
|
xcb_dri3_buffers_from_pixmap_reply_t *bps_reply;
|
||||||
|
|
||||||
|
bps_cookie = xcb_dri3_buffers_from_pixmap(draw->conn, pixmap);
|
||||||
|
bps_reply = xcb_dri3_buffers_from_pixmap_reply(draw->conn, bps_cookie,
|
||||||
|
NULL);
|
||||||
|
if (!bps_reply)
|
||||||
|
goto no_image;
|
||||||
|
buffer->image =
|
||||||
|
loader_dri3_create_image_from_buffers(draw->conn, bps_reply, format,
|
||||||
|
cur_screen, draw->ext->image,
|
||||||
|
buffer);
|
||||||
|
width = bps_reply->width;
|
||||||
|
height = bps_reply->height;
|
||||||
|
free(bps_reply);
|
||||||
|
} else {
|
||||||
|
xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
|
||||||
|
xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
|
||||||
|
|
||||||
|
bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap);
|
||||||
|
bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie, NULL);
|
||||||
|
if (!bp_reply)
|
||||||
|
goto no_image;
|
||||||
|
|
||||||
|
buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format,
|
||||||
|
cur_screen, draw->ext->image,
|
||||||
|
buffer);
|
||||||
|
width = bp_reply->width;
|
||||||
|
height = bp_reply->height;
|
||||||
|
free(bp_reply);
|
||||||
|
}
|
||||||
|
|
||||||
if (!buffer->image)
|
if (!buffer->image)
|
||||||
goto no_image;
|
goto no_image;
|
||||||
|
|
||||||
buffer->pixmap = pixmap;
|
buffer->pixmap = pixmap;
|
||||||
buffer->own_pixmap = false;
|
buffer->own_pixmap = false;
|
||||||
buffer->width = bp_reply->width;
|
buffer->width = width;
|
||||||
buffer->height = bp_reply->height;
|
buffer->height = height;
|
||||||
buffer->shm_fence = shm_fence;
|
buffer->shm_fence = shm_fence;
|
||||||
buffer->sync_fence = sync_fence;
|
buffer->sync_fence = sync_fence;
|
||||||
|
|
||||||
draw->buffers[buf_id] = buffer;
|
draw->buffers[buf_id] = buffer;
|
||||||
|
|
||||||
free(bp_reply);
|
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
no_image:
|
no_image:
|
||||||
free(bp_reply);
|
|
||||||
xcb_sync_destroy_fence(draw->conn, sync_fence);
|
xcb_sync_destroy_fence(draw->conn, sync_fence);
|
||||||
xshmfence_unmap_shm(shm_fence);
|
xshmfence_unmap_shm(shm_fence);
|
||||||
no_fence:
|
no_fence:
|
||||||
|
|
|
@ -62,8 +62,11 @@ struct loader_dri3_buffer {
|
||||||
bool busy; /* Set on swap, cleared on IdleNotify */
|
bool busy; /* Set on swap, cleared on IdleNotify */
|
||||||
bool own_pixmap; /* We allocated the pixmap ID, free on destroy */
|
bool own_pixmap; /* We allocated the pixmap ID, free on destroy */
|
||||||
|
|
||||||
|
uint32_t num_planes;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t pitch;
|
int strides[4];
|
||||||
|
int offsets[4];
|
||||||
|
uint64_t modifier;
|
||||||
uint32_t cpp;
|
uint32_t cpp;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
|
@ -120,6 +123,7 @@ struct loader_dri3_drawable {
|
||||||
/* Information about the GPU owning the buffer */
|
/* Information about the GPU owning the buffer */
|
||||||
__DRIscreen *dri_screen;
|
__DRIscreen *dri_screen;
|
||||||
bool is_different_gpu;
|
bool is_different_gpu;
|
||||||
|
bool multiplanes_available;
|
||||||
|
|
||||||
/* Present extension capabilities
|
/* Present extension capabilities
|
||||||
*/
|
*/
|
||||||
|
@ -180,6 +184,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
|
||||||
xcb_drawable_t drawable,
|
xcb_drawable_t drawable,
|
||||||
__DRIscreen *dri_screen,
|
__DRIscreen *dri_screen,
|
||||||
bool is_different_gpu,
|
bool is_different_gpu,
|
||||||
|
bool is_multiplanes_available,
|
||||||
const __DRIconfig *dri_config,
|
const __DRIconfig *dri_config,
|
||||||
struct loader_dri3_extensions *ext,
|
struct loader_dri3_extensions *ext,
|
||||||
const struct loader_dri3_vtable *vtable,
|
const struct loader_dri3_vtable *vtable,
|
||||||
|
@ -237,6 +242,14 @@ loader_dri3_create_image(xcb_connection_t *c,
|
||||||
const __DRIimageExtension *image,
|
const __DRIimageExtension *image,
|
||||||
void *loaderPrivate);
|
void *loaderPrivate);
|
||||||
|
|
||||||
|
__DRIimage *
|
||||||
|
loader_dri3_create_image_from_buffers(xcb_connection_t *c,
|
||||||
|
xcb_dri3_buffers_from_pixmap_reply_t *bp_reply,
|
||||||
|
unsigned int format,
|
||||||
|
__DRIscreen *dri_screen,
|
||||||
|
const __DRIimageExtension *image,
|
||||||
|
void *loaderPrivate);
|
||||||
|
|
||||||
int
|
int
|
||||||
loader_dri3_get_buffers(__DRIdrawable *driDrawable,
|
loader_dri3_get_buffers(__DRIdrawable *driDrawable,
|
||||||
unsigned int format,
|
unsigned int format,
|
||||||
|
|
|
@ -25,7 +25,7 @@ if with_platform_x11 and with_dri3
|
||||||
'loader_dri3_helper',
|
'loader_dri3_helper',
|
||||||
['loader_dri3_helper.c', 'loader_dri3_helper.h'],
|
['loader_dri3_helper.c', 'loader_dri3_helper.h'],
|
||||||
c_args : c_vis_args,
|
c_args : c_vis_args,
|
||||||
include_directories : [inc_include, inc_src],
|
include_directories : [inc_include, inc_src, inc_drm_uapi],
|
||||||
dependencies : [
|
dependencies : [
|
||||||
dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence,
|
dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence,
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue