Commit 6e7c40f6 authored by Louis-Francis Ratté-Boulianne's avatar Louis-Francis Ratté-Boulianne Committed by Adam Jackson

dri3: Add multi-planar/modifier buffer requests

Initial implementation for DRI3 v1.1. Only the DRI3 implementation
is there, backends need to implement the proper hooks.

Version is still set to 1.0 so clients shouldn't use the new
requests yet.

v2: Use depth/bpp instead of DRM formats in requests

v3: Remove DMA fence requests from v1.1
    Add screen/drawable modifier sets

v4: Free array returned by 'get_drawable_modifiers()'

v5: Fix FD leak
Signed-off-by: Daniel Stone's avatarDaniel Stone <daniels@collabora.com>
Signed-off-by: Louis-Francis Ratté-Boulianne's avatarLouis-Francis Ratté-Boulianne <lfrb@collabora.com>
Acked-by: Keith Packard's avatarKeith Packard <keithp@keithp.com>
Reviewed-by: Adam Jackson's avatarAdam Jackson <ajax@redhat.com>
parent 0ff40742
......@@ -729,7 +729,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1"
RESOURCEPROTO="resourceproto >= 1.2.0"
DRIPROTO="xf86driproto >= 2.1.0"
DRI2PROTO="dri2proto >= 2.8"
DRI3PROTO="dri3proto >= 1.0"
DRI3PROTO="dri3proto >= 1.2"
XINERAMAPROTO="xineramaproto"
BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
DGAPROTO="xf86dgaproto >= 2.0.99.1"
......
......@@ -26,6 +26,8 @@
#include "dri3_priv.h"
#include <drm_fourcc.h>
static int dri3_request;
DevPrivateKeyRec dri3_screen_private_key;
......@@ -99,3 +101,20 @@ dri3_extension_init(void)
bail:
FatalError("Cannot initialize DRI3 extension");
}
uint32_t
drm_format_for_depth(uint32_t depth, uint32_t bpp)
{
switch (bpp) {
case 16:
return DRM_FORMAT_RGB565;
case 24:
return DRM_FORMAT_XRGB8888;
case 30:
return DRM_FORMAT_XRGB2101010;
case 32:
return DRM_FORMAT_ARGB8888;
default:
return 0;
}
}
......@@ -28,7 +28,7 @@
#include <X11/extensions/dri3proto.h>
#include <randrstr.h>
#define DRI3_SCREEN_INFO_VERSION 1
#define DRI3_SCREEN_INFO_VERSION 2
typedef int (*dri3_open_proc)(ScreenPtr screen,
RRProviderPtr provider,
......@@ -47,11 +47,43 @@ typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen,
CARD8 depth,
CARD8 bpp);
typedef PixmapPtr (*dri3_pixmap_from_fds_proc) (ScreenPtr screen,
CARD8 num_fds,
int *fds,
CARD16 width,
CARD16 height,
CARD32 *strides,
CARD32 *offsets,
CARD8 depth,
CARD8 bpp,
CARD64 modifier);
typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen,
PixmapPtr pixmap,
CARD16 *stride,
CARD32 *size);
typedef int (*dri3_fds_from_pixmap_proc) (ScreenPtr screen,
PixmapPtr pixmap,
int *fds,
CARD32 *strides,
CARD32 *offsets,
CARD64 *modifier);
typedef int (*dri3_get_formats_proc) (ScreenPtr screen,
CARD32 *num_formats,
CARD32 **formats);
typedef int (*dri3_get_modifiers_proc) (ScreenPtr screen,
CARD32 format,
CARD32 *num_modifiers,
CARD64 **modifiers);
typedef int (*dri3_get_drawable_modifiers_proc) (DrawablePtr draw,
CARD32 format,
CARD32 *num_modifiers,
CARD64 **modifiers);
typedef struct dri3_screen_info {
uint32_t version;
......@@ -62,6 +94,13 @@ typedef struct dri3_screen_info {
/* Version 1 */
dri3_open_client_proc open_client;
/* Version 2 */
dri3_pixmap_from_fds_proc pixmap_from_fds;
dri3_fds_from_pixmap_proc fds_from_pixmap;
dri3_get_formats_proc get_formats;
dri3_get_modifiers_proc get_modifiers;
dri3_get_drawable_modifiers_proc get_drawable_modifiers;
} dri3_screen_info_rec, *dri3_screen_info_ptr;
extern _X_EXPORT Bool
......@@ -70,6 +109,9 @@ dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
extern _X_EXPORT int
dri3_send_open_reply(ClientPtr client, int fd);
extern _X_EXPORT uint32_t
drm_format_for_depth(uint32_t depth, uint32_t bpp);
#endif
#endif /* _DRI3_H_ */
......@@ -34,11 +34,21 @@
extern DevPrivateKeyRec dri3_screen_private_key;
typedef struct dri3_dmabuf_format {
uint32_t format;
uint32_t num_modifiers;
uint64_t *modifiers;
} dri3_dmabuf_format_rec, *dri3_dmabuf_format_ptr;
typedef struct dri3_screen_priv {
CloseScreenProcPtr CloseScreen;
ConfigNotifyProcPtr ConfigNotify;
DestroyWindowProcPtr DestroyWindow;
Bool formats_cached;
CARD32 num_formats;
dri3_dmabuf_format_ptr formats;
dri3_screen_info_ptr info;
} dri3_screen_priv_rec, *dri3_screen_priv_ptr;
......@@ -69,10 +79,21 @@ int
dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd);
int
dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp);
dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen, CARD8 num_fds, int *fds,
CARD16 width, CARD16 height, CARD32 *strides, CARD32 *offsets,
CARD8 depth, CARD8 bpp, CARD64 modifier);
int
dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
CARD32 *strides, CARD32 *offsets,
CARD64 *modifier);
int
dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
CARD8 depth, CARD8 bpp,
CARD32 *num_drawable_modifiers,
CARD64 **drawable_modifiers,
CARD32 *num_screen_modifiers,
CARD64 **screen_modifiers);
#endif /* _DRI3PRIV_H_ */
This diff is collapsed.
......@@ -29,6 +29,7 @@
#include <misync.h>
#include <misyncshm.h>
#include <randrstr.h>
#include <drm_fourcc.h>
static inline Bool has_open(dri3_screen_info_ptr info) {
if (info == NULL)
......@@ -60,17 +61,30 @@ dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
}
int
dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen,
CARD8 num_fds, int *fds,
CARD16 width, CARD16 height,
CARD32 *strides, CARD32 *offsets,
CARD8 depth, CARD8 bpp, CARD64 modifier)
{
dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
dri3_screen_info_ptr info = ds->info;
PixmapPtr pixmap;
if (!info || !info->pixmap_from_fd)
if (!info)
return BadImplementation;
pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp);
if (info->version >= 2 && info->pixmap_from_fds != NULL) {
pixmap = (*info->pixmap_from_fds) (screen, num_fds, fds, width, height,
strides, offsets, depth, bpp, modifier);
} else if (info->pixmap_from_fd != NULL && num_fds == 1 &&
modifier == DRM_FORMAT_MOD_INVALID) {
pixmap = (*info->pixmap_from_fd) (screen, fds[0], width, height,
strides[0], depth, bpp);
} else {
return BadImplementation;
}
if (!pixmap)
return BadAlloc;
......@@ -79,20 +93,182 @@ dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
}
int
dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
CARD32 *strides, CARD32 *offsets,
CARD64 *modifier)
{
ScreenPtr screen = pixmap->drawable.pScreen;
dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
dri3_screen_info_ptr info = ds->info;
int fd;
if (!info || !info->fd_from_pixmap)
if (!info)
return 0;
if (info->version >= 2 && info->fds_from_pixmap != NULL) {
return (*info->fds_from_pixmap)(screen, pixmap, fds, strides, offsets,
modifier);
} else if (info->fd_from_pixmap != NULL) {
CARD16 stride;
CARD32 size;
fds[0] = (*info->fd_from_pixmap)(screen, pixmap, &stride, &size);
if (fds[0] < 0)
return 0;
strides[0] = stride;
offsets[0] = 0;
*modifier = DRM_FORMAT_MOD_INVALID;
return 1;
} else {
return 0;
}
}
static int
cache_formats_and_modifiers(ScreenPtr screen)
{
dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
dri3_screen_info_ptr info = ds->info;
CARD32 *formats = NULL;
CARD64 *modifiers = NULL;
int i;
if (ds->formats_cached)
return Success;
if (!info)
return BadImplementation;
fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size);
if (fd < 0)
if (!info->get_formats || !info->get_modifiers) {
ds->formats = NULL;
ds->num_formats = 0;
ds->formats_cached = TRUE;
return Success;
}
(*info->get_formats) (screen, &ds->num_formats, &formats);
ds->formats = calloc(ds->num_formats, sizeof(dri3_dmabuf_format_rec));
if (!ds->formats)
return BadAlloc;
*pfd = fd;
for (i = 0; i < ds->num_formats; i++) {
dri3_dmabuf_format_ptr iter = &ds->formats[i];
iter->format = formats[i];
(*info->get_modifiers) (screen, formats[i],
&iter->num_modifiers,
&modifiers);
iter->modifiers = malloc(iter->num_modifiers * sizeof(CARD64));
if (iter->modifiers == NULL)
goto error;
memcpy(iter->modifiers, modifiers,
iter->num_modifiers * sizeof(CARD64));
goto done;
error:
iter->num_modifiers = 0;
free(iter->modifiers);
done:
free(modifiers);
}
free(formats);
ds->formats_cached = TRUE;
return Success;
}
int
dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
CARD8 depth, CARD8 bpp,
CARD32 *num_intersect_modifiers,
CARD64 **intersect_modifiers,
CARD32 *num_screen_modifiers,
CARD64 **screen_modifiers)
{
dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
dri3_screen_info_ptr info = ds->info;
int i, j;
int ret;
CARD32 num_drawable_mods;
CARD64 *drawable_mods;
CARD64 *intersect_mods = NULL;
CARD64 *screen_mods = NULL;
CARD32 format;
dri3_dmabuf_format_ptr screen_format = NULL;
ret = cache_formats_and_modifiers(screen);
if (ret != Success)
return ret;
format = drm_format_for_depth(depth, bpp);
if (format == 0)
return BadValue;
/* Find screen-global modifiers from cache
*/
for (i = 0; i < ds->num_formats; i++) {
if (ds->formats[i].format == format) {
screen_format = &ds->formats[i];
break;
}
}
if (screen_format == NULL)
return BadMatch;
if (screen_format->num_modifiers == 0) {
*num_screen_modifiers = 0;
*num_intersect_modifiers = 0;
return Success;
}
if (info->get_drawable_modifiers)
(*info->get_drawable_modifiers) (drawable, format,
&num_drawable_mods,
&drawable_mods);
/* We're allocating slightly more memory than necessary but it reduces
* the complexity of finding the intersection set.
*/
screen_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
if (!screen_mods)
return BadAlloc;
if (num_drawable_mods > 0) {
intersect_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
if (!intersect_mods) {
free(screen_mods);
return BadAlloc;
}
}
*num_screen_modifiers = 0;
*num_intersect_modifiers = 0;
for (i = 0; i < screen_format->num_modifiers; i++) {
CARD64 modifier = screen_format->modifiers[i];
Bool intersect = FALSE;
for (j = 0; j < num_drawable_mods; j++) {
if (drawable_mods[j] == modifier) {
intersect = TRUE;
break;
}
}
if (intersect) {
intersect_mods[*num_intersect_modifiers] = modifier;
*num_intersect_modifiers += 1;
} else {
screen_mods[*num_screen_modifiers] = modifier;
*num_screen_modifiers += 1;
}
}
assert(*num_intersect_modifiers + *num_screen_modifiers == screen_format->num_modifiers);
*intersect_modifiers = intersect_mods;
*screen_modifiers = screen_mods;
free(drawable_mods);
return Success;
}
......@@ -59,7 +59,7 @@ xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
}
static uint32_t
drm_format_for_depth(int depth)
wl_drm_format_for_depth(int depth)
{
switch (depth) {
case 15:
......@@ -170,7 +170,7 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
pixmap->drawable.width,
pixmap->drawable.height,
drm_format_for_depth(pixmap->drawable.depth),
wl_drm_format_for_depth(pixmap->drawable.depth),
0, gbm_bo_get_stride(xwl_pixmap->bo),
0, 0,
0, 0);
......
......@@ -78,7 +78,7 @@ scrnsaverproto_dep = dependency('scrnsaverproto', version: '>= 1.1')
resourceproto_dep = dependency('resourceproto', version: '>= 1.2.0')
xf86driproto_dep = dependency('xf86driproto', version: '>= 2.1.0', required: get_option('dri1') == 'true')
dri2proto_dep = dependency('dri2proto', version: '>= 2.8', required: get_option('dri2') == 'true')
dri3proto_dep = dependency('dri3proto', version: '>= 1.0', required: get_option('dri3') == 'true')
dri3proto_dep = dependency('dri3proto', version: '>= 1.2', required: get_option('dri3') == 'true')
xineramaproto_dep = dependency('xineramaproto')
xf86bigfontproto_dep = dependency('xf86bigfontproto', version: '>= 1.2.0')
xf86vidmodeproto_dep = dependency('xf86vidmodeproto', version: '>= 2.2.99.1', required: false)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment