summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>2022-04-25 14:32:59 -0400
committerMarge Bot <emma+marge@anholt.net>2022-04-27 03:54:29 +0000
commit63d75ac797ec5e3c8a82b4bbf3d335e4b1362bb9 (patch)
tree280dddd95efa5bf187cb9f132c9c4a89de960f69
parent5e3b01c515cbe13b799617607f055c4275a2cfb8 (diff)
kopper: copy a bunch of code for texture_from_pixmap
seems to work? Reviewed-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16179>
-rw-r--r--src/gallium/frontends/dri/kopper.c299
1 files changed, 296 insertions, 3 deletions
diff --git a/src/gallium/frontends/dri/kopper.c b/src/gallium/frontends/dri/kopper.c
index a11ffc09875..1e2b5962e70 100644
--- a/src/gallium/frontends/dri/kopper.c
+++ b/src/gallium/frontends/dri/kopper.c
@@ -43,9 +43,18 @@
#include <vulkan/vulkan.h>
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/present.h>
+#include <xcb/xfixes.h>
+#include "util/libsync.h"
+#include <X11/Xlib-xcb.h>
+#include "drm-uapi/drm_fourcc.h"
+
struct kopper_drawable {
struct dri_drawable base;
struct kopper_loader_info info;
+ __DRIimage *image; //texture_from_pixmap
bool is_pixmap;
};
@@ -199,6 +208,266 @@ dri_image_drawable_get_buffers(struct dri_drawable *drawable,
const enum st_attachment_type *statts,
unsigned statts_count);
+#ifdef VK_USE_PLATFORM_XCB_KHR
+static int
+get_dri_format(enum pipe_format pf)
+{
+ int image_format;
+ switch (pf) {
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ image_format = __DRI_IMAGE_FORMAT_ABGR16161616F;
+ break;
+ case PIPE_FORMAT_R16G16B16X16_FLOAT:
+ image_format = __DRI_IMAGE_FORMAT_XBGR16161616F;
+ break;
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_ARGB1555;
+ break;
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_RGB565;
+ break;
+ case PIPE_FORMAT_BGRX8888_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_XRGB8888;
+ break;
+ case PIPE_FORMAT_BGRA8888_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_ARGB8888;
+ break;
+ case PIPE_FORMAT_RGBX8888_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_XBGR8888;
+ break;
+ case PIPE_FORMAT_RGBA8888_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_ABGR8888;
+ break;
+ case PIPE_FORMAT_B10G10R10X2_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_XRGB2101010;
+ break;
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_ARGB2101010;
+ break;
+ case PIPE_FORMAT_R10G10B10X2_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_XBGR2101010;
+ break;
+ case PIPE_FORMAT_R10G10B10A2_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_ABGR2101010;
+ break;
+ default:
+ image_format = __DRI_IMAGE_FORMAT_NONE;
+ break;
+ }
+ return image_format;
+}
+
+/* the DRIimage createImage function takes __DRI_IMAGE_FORMAT codes, while
+ * the createImageFromFds call takes DRM_FORMAT codes. To avoid
+ * complete confusion, just deal in __DRI_IMAGE_FORMAT codes for now and
+ * translate to DRM_FORMAT codes in the call to createImageFromFds
+ */
+static int
+image_format_to_fourcc(int format)
+{
+
+ /* Convert from __DRI_IMAGE_FORMAT to DRM_FORMAT (sigh) */
+ switch (format) {
+ case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888;
+ case __DRI_IMAGE_FORMAT_SABGR8: return __DRI_IMAGE_FOURCC_SABGR8888;
+ case __DRI_IMAGE_FORMAT_SXRGB8: return __DRI_IMAGE_FOURCC_SXRGB8888;
+ case __DRI_IMAGE_FORMAT_RGB565: return DRM_FORMAT_RGB565;
+ case __DRI_IMAGE_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
+ case __DRI_IMAGE_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
+ case __DRI_IMAGE_FORMAT_ABGR8888: return DRM_FORMAT_ABGR8888;
+ case __DRI_IMAGE_FORMAT_XBGR8888: return DRM_FORMAT_XBGR8888;
+ case __DRI_IMAGE_FORMAT_XRGB2101010: return DRM_FORMAT_XRGB2101010;
+ case __DRI_IMAGE_FORMAT_ARGB2101010: return DRM_FORMAT_ARGB2101010;
+ case __DRI_IMAGE_FORMAT_XBGR2101010: return DRM_FORMAT_XBGR2101010;
+ case __DRI_IMAGE_FORMAT_ABGR2101010: return DRM_FORMAT_ABGR2101010;
+ case __DRI_IMAGE_FORMAT_XBGR16161616F: return DRM_FORMAT_XBGR16161616F;
+ case __DRI_IMAGE_FORMAT_ABGR16161616F: return DRM_FORMAT_ABGR16161616F;
+ }
+ return 0;
+}
+
+#ifdef HAVE_DRI3_MODIFIERS
+static __DRIimage *
+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;
+}
+#endif
+
+static __DRIimage *
+dri3_create_image(xcb_connection_t *c,
+ xcb_dri3_buffer_from_pixmap_reply_t *bp_reply,
+ unsigned int format,
+ __DRIscreen *dri_screen,
+ const __DRIimageExtension *image,
+ void *loaderPrivate)
+{
+ int *fds;
+ __DRIimage *image_planar, *ret;
+ int stride, offset;
+
+ /* Get an FD for the pixmap object
+ */
+ fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, bp_reply);
+
+ stride = bp_reply->stride;
+ offset = 0;
+
+ /* createImageFromFds creates a wrapper __DRIimage structure which
+ * can deal with multiple planes for things like Yuv images. So, once
+ * we've gotten the planar wrapper, pull the single plane out of it and
+ * discard the wrapper.
+ */
+ image_planar = image->createImageFromFds(dri_screen,
+ bp_reply->width,
+ bp_reply->height,
+ image_format_to_fourcc(format),
+ fds, 1,
+ &stride, &offset, loaderPrivate);
+ close(fds[0]);
+ if (!image_planar)
+ return NULL;
+
+ ret = image->fromPlanar(image_planar, 0, loaderPrivate);
+
+ if (!ret)
+ ret = image_planar;
+ else
+ image->destroyImage(image_planar);
+
+ return ret;
+}
+
+
+static void
+handle_in_fence(__DRIcontext *context, __DRIimage *img)
+{
+ struct dri_context *ctx = dri_context(context);
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_fence_handle *fence;
+ int fd = img->in_fence_fd;
+
+ if (fd == -1)
+ return;
+
+ validate_fence_fd(fd);
+
+ img->in_fence_fd = -1;
+
+ pipe->create_fence_fd(pipe, &fence, fd, PIPE_FD_TYPE_NATIVE_SYNC);
+ pipe->fence_server_sync(pipe, fence);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+
+ close(fd);
+}
+
+/** kopper_get_pixmap_buffer
+ *
+ * Get the DRM object for a pixmap from the X server and
+ * wrap that with a __DRIimage structure using createImageFromFds
+ */
+static struct pipe_resource *
+kopper_get_pixmap_buffer(struct kopper_drawable *cdraw,
+ enum pipe_format pf)
+{
+ xcb_drawable_t pixmap;
+ int width;
+ int height;
+ int format = get_dri_format(pf);
+ __DRIscreen *cur_screen;
+ struct kopper_loader_info *info = &cdraw->info;
+ assert(info->bos.sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR);
+ xcb_connection_t *conn = info->xcb.connection;
+ pixmap = info->xcb.window;
+
+ if (cdraw->image)
+ return cdraw->image->texture;
+
+ /* FIXME: probably broken for OBS studio?
+ * see dri3_get_pixmap_buffer()
+ */
+ cur_screen = cdraw->base.sPriv;
+ struct kopper_screen *kscreen = (struct kopper_screen*)cur_screen->driverPrivate;
+
+#ifdef HAVE_DRI3_MODIFIERS
+ if (kscreen->has_dmabuf) {
+ 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(conn, pixmap);
+ bps_reply = xcb_dri3_buffers_from_pixmap_reply(conn, bps_cookie,
+ NULL);
+ if (!bps_reply)
+ return NULL;
+ cdraw->image =
+ dri3_create_image_from_buffers(conn, bps_reply, format,
+ cur_screen, &driVkImageExtension,
+ cdraw);
+ width = bps_reply->width;
+ height = bps_reply->height;
+ free(bps_reply);
+ } else
+#endif
+ {
+ 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(conn, pixmap);
+ bp_reply = xcb_dri3_buffer_from_pixmap_reply(conn, bp_cookie, NULL);
+ if (!bp_reply)
+ return NULL;
+
+ cdraw->image = dri3_create_image(conn, bp_reply, format,
+ cur_screen, &driVkImageExtension,
+ cdraw);
+ width = bp_reply->width;
+ height = bp_reply->height;
+ free(bp_reply);
+ }
+
+ cdraw->base.dPriv->w = width;
+ cdraw->base.dPriv->h = height;
+
+ return cdraw->image->texture;
+}
+#endif //VK_USE_PLATFORM_XCB_KHR
+
static void
kopper_allocate_textures(struct dri_context *ctx,
struct dri_drawable *drawable,
@@ -215,6 +484,9 @@ kopper_allocate_textures(struct dri_context *ctx,
const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
struct kopper_drawable *cdraw = (struct kopper_drawable *)drawable;
+ bool is_window = !cdraw->is_pixmap;
+ bool is_pixmap = !is_window && cdraw->info.bos.sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+
width = drawable->dPriv->w;
height = drawable->dPriv->h;
@@ -269,12 +541,16 @@ kopper_allocate_textures(struct dri_context *ctx,
/* remove outdated textures */
if (resized) {
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
- if (drawable->textures[i] && i < ST_ATTACHMENT_DEPTH_STENCIL) {
+ if (drawable->textures[i] && i < ST_ATTACHMENT_DEPTH_STENCIL && !is_pixmap) {
drawable->textures[i]->width0 = width;
drawable->textures[i]->height0 = height;
} else
pipe_resource_reference(&drawable->textures[i], NULL);
pipe_resource_reference(&drawable->msaa_textures[i], NULL);
+ if (is_pixmap && i == ST_ATTACHMENT_FRONT_LEFT) {
+ FREE(cdraw->image);
+ cdraw->image = NULL;
+ }
}
}
}
@@ -289,7 +565,16 @@ kopper_allocate_textures(struct dri_context *ctx,
templ.depth0 = 1;
templ.array_size = 1;
templ.last_level = 0;
- bool is_window = !cdraw->is_pixmap;
+
+#if 0
+XXX do this once swapinterval is hooked up
+ /* pixmaps always have front buffers.
+ * Exchange swaps also mandate fake front buffers.
+ */
+ if (draw->type != LOADER_DRI3_DRAWABLE_WINDOW ||
+ draw->swap_method == __DRI_ATTRIB_SWAP_EXCHANGE)
+ buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
+#endif
uint32_t attachments = 0;
for (i = 0; i < statts_count; i++)
@@ -325,9 +610,17 @@ kopper_allocate_textures(struct dri_context *ctx,
assert(data);
drawable->textures[statts[i]] =
screen->base.screen->resource_create_drawable(screen->base.screen, &templ, data);
- } else
+ }
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ else if (is_pixmap && statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
+ drawable->textures[statts[i]] = kopper_get_pixmap_buffer(cdraw, format);
+ handle_in_fence(ctx->cPriv, cdraw->image);
+ }
+#endif
+ else {
drawable->textures[statts[i]] =
screen->base.screen->resource_create(screen->base.screen, &templ);
+ }
}
if (drawable->stvis.samples > 1 && !drawable->msaa_textures[statts[i]]) {
templ.bind = templ.bind &