Compare commits

...

5 Commits

Author SHA1 Message Date
Matthias Clasen
1868d71163 Add a more complete implementation
Support multiple planes, and modifiers.

And make this a backend API.
2021-05-09 10:30:16 -04:00
Matthias Clasen
ff35efeb41 wayland: Destroy the EglImage right away
I'm told there is no need to keep it around.
2021-05-09 10:30:16 -04:00
Matthias Clasen
354bf71940 wip: x11: Implement importing dmabufs
This doesn't work yet.
Whatever I do, libepoxy complains.
2021-05-08 09:45:25 -04:00
Matthias Clasen
da72c4e451 wayland: Implement importing dmabufs 2021-05-08 09:45:25 -04:00
Matthias Clasen
ad91d213c3 Add an api to turn dmabufs into textures 2021-05-07 21:31:03 -04:00
6 changed files with 318 additions and 3 deletions

View File

@@ -1258,3 +1258,21 @@ gdk_gl_context_use_es_bgra (GdkGLContext *context)
return FALSE;
}
GdkTexture *
gdk_gl_context_import_dmabuf (GdkGLContext *context,
int fd,
int fourcc,
int width,
int height,
int offset,
int stride)
{
if (GDK_GL_CONTEXT_GET_CLASS (context)->import_dmabuf)
return GDK_GL_CONTEXT_GET_CLASS (context)->import_dmabuf (context,
fd, fourcc,
width, height,
offset, stride);
return NULL;
}

View File

@@ -90,6 +90,15 @@ GdkGLContext * gdk_gl_context_get_current (void);
GDK_AVAILABLE_IN_ALL
void gdk_gl_context_clear_current (void);
GDK_AVAILABLE_IN_4_4
GdkTexture * gdk_gl_context_import_dmabuf (GdkGLContext *context,
int fd,
int fourcc,
int width,
int height,
int offset,
int stride);
G_END_DECLS
#endif /* __GDK_GL_CONTEXT_H__ */

View File

@@ -45,10 +45,18 @@ struct _GdkGLContextClass
{
GdkDrawContextClass parent_class;
gboolean (* realize) (GdkGLContext *context,
GError **error);
gboolean (* realize) (GdkGLContext *context,
GError **error);
cairo_region_t * (* get_damage) (GdkGLContext *context);
GdkTexture * (* import_dmabuf) (GdkGLContext *context,
int fd,
int fourcc,
int width,
int height,
int offset,
int stride);
};
typedef struct {

View File

@@ -313,6 +313,181 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
gdk_wayland_surface_notify_committed (surface);
}
int
gdk_wayland_gl_context_import_dmabuf (GdkGLContext *context,
uint32_t format,
unsigned int width,
unsigned int height,
uint32_t n_planes,
const int *fds,
const uint32_t *strides,
const uint32_t *offsets,
const uint64_t *modifiers)
{
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
guint texture;
EGLint attribs[2 * (3 + 4 * 5) + 1];
int i;
EGLImage image;
g_return_val_if_fail (GDK_IS_WAYLAND_GL_CONTEXT (context), 0);
g_return_val_if_fail (0 < n_planes && n_planes <= 4, 0);
i = 0;
attribs[i++] = EGL_WIDTH;
attribs[i++] = width;
attribs[i++] = EGL_HEIGHT;
attribs[i++] = height;
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[i++] = format;
if (n_planes > 0)
{
attribs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attribs[i++] = fds[0];
attribs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attribs[i++] = offsets[0];
attribs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attribs[i++] = strides[0];
if (modifiers)
{
attribs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attribs[i++] = modifiers[0] & 0xFFFFFFFF;
attribs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attribs[i++] = modifiers[0] >> 32;
}
}
if (n_planes > 1)
{
attribs[i++] = EGL_DMA_BUF_PLANE1_FD_EXT;
attribs[i++] = fds[1];
attribs[i++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
attribs[i++] = offsets[1];
attribs[i++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
attribs[i++] = strides[1];
if (modifiers)
{
attribs[i++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
attribs[i++] = modifiers[1] & 0xFFFFFFFF;
attribs[i++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
attribs[i++] = modifiers[1] >> 32;
}
}
if (n_planes > 2)
{
attribs[i++] = EGL_DMA_BUF_PLANE2_FD_EXT;
attribs[i++] = fds[2];
attribs[i++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
attribs[i++] = offsets[2];
attribs[i++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
attribs[i++] = strides[2];
if (modifiers)
{
attribs[i++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
attribs[i++] = modifiers[2] & 0xFFFFFFFF;
attribs[i++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
attribs[i++] = modifiers[2] >> 32;
}
}
if (n_planes > 3)
{
attribs[i++] = EGL_DMA_BUF_PLANE3_FD_EXT;
attribs[i++] = fds[3];
attribs[i++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
attribs[i++] = offsets[3];
attribs[i++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
attribs[i++] = strides[3];
if (modifiers)
{
attribs[i++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
attribs[i++] = modifiers[3] & 0xFFFFFFFF;
attribs[i++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
attribs[i++] = modifiers[3] >> 32;
}
}
attribs[i++] = EGL_NONE;
image = eglCreateImageKHR (display_wayland->egl_display,
EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT,
(EGLClientBuffer)NULL,
attribs);
if (image == EGL_NO_IMAGE)
{
switch (eglGetError ())
{
#define EGL_ERROR(name) \
case name: \
g_print (#name); \
break;
EGL_ERROR(EGL_NOT_INITIALIZED)
EGL_ERROR(EGL_BAD_ACCESS)
EGL_ERROR(EGL_BAD_ALLOC)
EGL_ERROR(EGL_BAD_ATTRIBUTE)
EGL_ERROR(EGL_BAD_CONTEXT)
EGL_ERROR(EGL_BAD_CONFIG)
EGL_ERROR(EGL_BAD_CURRENT_SURFACE)
EGL_ERROR(EGL_BAD_DISPLAY)
EGL_ERROR(EGL_BAD_SURFACE)
EGL_ERROR(EGL_BAD_MATCH)
EGL_ERROR(EGL_BAD_PARAMETER)
EGL_ERROR(EGL_BAD_NATIVE_PIXMAP)
EGL_ERROR(EGL_BAD_NATIVE_WINDOW)
EGL_ERROR(EGL_CONTEXT_LOST)
default:
g_print ("error: %d\n", eglGetError ());
break;
}
return 0;
}
gdk_gl_context_make_current (context);
glGenTextures (1, &texture);
glBindTexture (GL_TEXTURE_2D, texture);
glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, image);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
eglDestroyImage (display_wayland->egl_display, image);
return texture;
}
static GdkTexture *
import_dmabuf (GdkGLContext *context,
int fd,
int fourcc,
int width,
int height,
int offset,
int stride)
{
int texture;
texture = gdk_wayland_gl_context_import_dmabuf (context,
fourcc,
width,
height,
1,
(const int *)&fd,
(const uint32_t *)&stride,
(const uint32_t *)&offset,
NULL);
return gdk_gl_texture_new (context,
texture,
width, height,
NULL, NULL);
}
static void
gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
{
@@ -326,6 +501,8 @@ gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
context_class->realize = gdk_wayland_gl_context_realize;
context_class->get_damage = gdk_wayland_gl_context_get_damage;
context_class->import_dmabuf = import_dmabuf;
}
static void
@@ -576,3 +753,4 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
return TRUE;
}

View File

@@ -32,7 +32,7 @@ G_BEGIN_DECLS
#define GDK_TYPE_WAYLAND_GL_CONTEXT (gdk_wayland_gl_context_get_type ())
#define GDK_WAYLAND_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WAYLAND_GL_CONTEXT, GdkWaylandGLContext))
#define GDK_WAYLAND_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WAYLAND_GL_CONTEXT))
#define GDK_IS_WAYLAND_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WAYLAND_GL_CONTEXT))
typedef struct _GdkWaylandGLContext GdkWaylandGLContext;
typedef struct _GdkWaylandGLContextClass GdkWaylandGLContextClass;
@@ -40,6 +40,17 @@ typedef struct _GdkWaylandGLContextClass GdkWaylandGLContextClass;
GDK_AVAILABLE_IN_ALL
GType gdk_wayland_gl_context_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_4
int gdk_wayland_gl_context_import_dmabuf (GdkGLContext *context,
uint32_t fourcc,
unsigned int width,
unsigned int height,
uint32_t n_planes,
const int *fd,
const uint32_t *stride,
const uint32_t *offset,
const uint64_t *modifiers);
G_END_DECLS
#endif /* __GDK_WAYLAND_GL_CONTEXT_H__ */

View File

@@ -40,6 +40,8 @@
#include <cairo-xlib.h>
#include <epoxy/glx.h>
#include <epoxy/egl.h>
G_DEFINE_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT)
@@ -710,6 +712,94 @@ gdk_x11_gl_context_dispose (GObject *gobject)
G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject);
}
typedef struct {
EGLDisplay display;
EGLImage image;
} ImageData;
static void
free_image (gpointer data)
{
ImageData *idata = data;
eglDestroyImage (idata->display, idata->image);
g_free (data);
}
static GdkTexture *
gdk_x11_gl_context_import_dmabuf (GdkGLContext *context,
int fd,
int fourcc,
int width,
int height,
int offset,
int stride)
{
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
guint texture;
const EGLAttrib attribute_list[] = {
EGL_WIDTH, width,
EGL_HEIGHT, height,
EGL_LINUX_DRM_FOURCC_EXT, fourcc,
EGL_DMA_BUF_PLANE0_FD_EXT, fd,
EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset,
EGL_DMA_BUF_PLANE0_PITCH_EXT, stride,
EGL_NONE
};
EGLDisplay egl_display;
EGLImage image;
ImageData *idata;
int major, minor;
gdk_gl_context_make_current (context);
egl_display = eglGetDisplay ((EGLNativeDisplayType) display_x11->xdisplay);
if (!eglInitialize (egl_display, &major, &minor))
{
g_warning ("Failed to initialize EGL: %x", eglGetError());
return NULL;
}
if (!eglBindAPI(EGL_OPENGL_API))
{
g_warning ("Failed to bind EGL API: %x", eglGetError());
return NULL;
}
g_message ("EGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Version: %s\n"
" - Client APIs: %s\n"
" - Extensions:\n"
"\t%s",
major, minor,
eglQueryString (egl_display, EGL_VENDOR),
eglQueryString (egl_display, EGL_VERSION),
eglQueryString (egl_display, EGL_CLIENT_APIS),
eglQueryString (egl_display, EGL_EXTENSIONS));
image = eglCreateImage (egl_display,
EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT,
(EGLClientBuffer)NULL,
attribute_list);
if (image == EGL_NO_IMAGE)
return NULL;
glGenTextures (1, &texture);
glBindTexture (GL_TEXTURE_2D, texture);
glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, image);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
idata = g_new (ImageData, 1);
idata->display = egl_display;
idata->image = image;
return gdk_gl_texture_new (context, texture, width, height, free_image, idata);
}
static void
gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
{
@@ -719,6 +809,7 @@ gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
context_class->realize = gdk_x11_gl_context_realize;
context_class->get_damage = gdk_x11_gl_context_get_damage;
context_class->import_dmabuf = gdk_x11_gl_context_import_dmabuf;
draw_context_class->end_frame = gdk_x11_gl_context_end_frame;