diff --git a/libobs-opengl/gl-egl-common.c b/libobs-opengl/gl-egl-common.c index 4bc1d24e9..eb11820cc 100644 --- a/libobs-opengl/gl-egl-common.c +++ b/libobs-opengl/gl-egl-common.c @@ -177,6 +177,31 @@ create_dmabuf_egl_image(EGLDisplay egl_display, unsigned int width, EGL_LINUX_DMA_BUF_EXT, 0, attribs); } +struct gs_texture *gl_egl_create_texture_from_eglimage( + EGLDisplay egl_display, uint32_t width, uint32_t height, + enum gs_color_format color_format, EGLint target, EGLImage image) +{ + UNUSED_PARAMETER(target); + struct gs_texture *texture = NULL; + texture = gs_texture_create(width, height, color_format, 1, NULL, + GS_DYNAMIC); + const GLuint gltex = *(GLuint *)gs_texture_get_obj(texture); + + gl_bind_texture(GL_TEXTURE_2D, gltex); + gl_tex_param_i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl_tex_param_i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + if (!gl_success("glEGLImageTargetTexture2DOES")) { + gs_texture_destroy(texture); + texture = NULL; + } + + gl_bind_texture(GL_TEXTURE_2D, 0); + + return texture; +} + struct gs_texture * gl_egl_create_dmabuf_image(EGLDisplay egl_display, unsigned int width, unsigned int height, uint32_t drm_format, @@ -199,24 +224,42 @@ gl_egl_create_dmabuf_image(EGLDisplay egl_display, unsigned int width, return NULL; } - if ((texture = gs_texture_create(width, height, color_format, 1, NULL, - GS_DYNAMIC)) == NULL) { + texture = gl_egl_create_texture_from_eglimage(egl_display, width, + height, color_format, + GL_TEXTURE_2D, egl_image); + if (texture) + eglDestroyImage(egl_display, egl_image); + + return texture; +} + +struct gs_texture * +gl_egl_create_texture_from_pixmap(EGLDisplay egl_display, uint32_t width, + uint32_t height, + enum gs_color_format color_format, + EGLint target, EGLClientBuffer pixmap) +{ + if (!init_egl_image_target_texture_2d_ext()) + return NULL; + + const EGLAttrib pixmap_attrs[] = { + EGL_IMAGE_PRESERVED_KHR, + EGL_TRUE, + EGL_NONE, + }; + + EGLImage image = eglCreateImage(egl_display, EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, pixmap, + pixmap_attrs); + if (image == EGL_NO_IMAGE) { + blog(LOG_ERROR, "Cannot create EGLImage: %s", + gl_egl_error_to_string(eglGetError())); return NULL; } - const GLuint gltex = *(GLuint *)gs_texture_get_obj(texture); - gl_bind_texture(GL_TEXTURE_2D, gltex); - gl_tex_param_i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl_tex_param_i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image); - if (!gl_success("glEGLImageTargetTexture2DOES")) { - gs_texture_destroy(texture); - texture = NULL; - } - - gl_bind_texture(GL_TEXTURE_2D, 0); - eglDestroyImage(egl_display, egl_image); + struct gs_texture *texture = gl_egl_create_texture_from_eglimage( + egl_display, width, height, color_format, target, image); + eglDestroyImage(egl_display, image); return texture; } diff --git a/libobs-opengl/gl-egl-common.h b/libobs-opengl/gl-egl-common.h index e9b010e07..a168c580e 100644 --- a/libobs-opengl/gl-egl-common.h +++ b/libobs-opengl/gl-egl-common.h @@ -21,3 +21,9 @@ bool gl_egl_query_dmabuf_modifiers_for_format(EGLDisplay egl_display, uint32_t drm_format, uint64_t **modifiers, size_t *n_modifiers); + +struct gs_texture * +gl_egl_create_texture_from_pixmap(EGLDisplay egl_display, uint32_t width, + uint32_t height, + enum gs_color_format color_format, + EGLint target, EGLClientBuffer pixmap); diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c index e87eb007e..f3771027b 100644 --- a/libobs-opengl/gl-nix.c +++ b/libobs-opengl/gl-nix.c @@ -157,3 +157,11 @@ extern bool device_query_dmabuf_modifiers_for_format(gs_device_t *device, return gl_vtable->device_query_dmabuf_modifiers_for_format( device, drm_format, modifiers, n_modifiers); } + +struct gs_texture *device_texture_create_from_pixmap( + gs_device_t *device, uint32_t width, uint32_t height, + enum gs_color_format color_format, uint32_t target, void *pixmap) +{ + return gl_vtable->device_texture_create_from_pixmap( + device, width, height, color_format, target, pixmap); +} diff --git a/libobs-opengl/gl-nix.h b/libobs-opengl/gl-nix.h index 41b69d546..f2801d5d6 100644 --- a/libobs-opengl/gl-nix.h +++ b/libobs-opengl/gl-nix.h @@ -68,4 +68,9 @@ struct gl_winsys_vtable { uint32_t drm_format, uint64_t **modifiers, size_t *n_modifiers); + + struct gs_texture *(*device_texture_create_from_pixmap)( + gs_device_t *device, uint32_t width, uint32_t height, + enum gs_color_format color_format, uint32_t target, + void *pixmap); }; diff --git a/libobs-opengl/gl-wayland-egl.c b/libobs-opengl/gl-wayland-egl.c index 27a8d2a68..cc15c82ab 100644 --- a/libobs-opengl/gl-wayland-egl.c +++ b/libobs-opengl/gl-wayland-egl.c @@ -383,6 +383,13 @@ static bool gl_wayland_egl_device_query_dmabuf_modifiers_for_format( plat->display, drm_format, modifiers, n_modifiers); } +static struct gs_texture *gl_wayland_egl_device_texture_create_from_pixmap( + gs_device_t *device, uint32_t width, uint32_t height, + enum gs_color_format color_format, uint32_t target, void *pixmap) +{ + return NULL; +} + static const struct gl_winsys_vtable egl_wayland_winsys_vtable = { .windowinfo_create = gl_wayland_egl_windowinfo_create, .windowinfo_destroy = gl_wayland_egl_windowinfo_destroy, @@ -404,6 +411,8 @@ static const struct gl_winsys_vtable egl_wayland_winsys_vtable = { gl_wayland_egl_device_query_dmabuf_capabilities, .device_query_dmabuf_modifiers_for_format = gl_wayland_egl_device_query_dmabuf_modifiers_for_format, + .device_texture_create_from_pixmap = + gl_wayland_egl_device_texture_create_from_pixmap, }; const struct gl_winsys_vtable *gl_wayland_egl_get_winsys_vtable(void) diff --git a/libobs-opengl/gl-x11-egl.c b/libobs-opengl/gl-x11-egl.c index 80ff2afac..ecffffdac 100644 --- a/libobs-opengl/gl-x11-egl.c +++ b/libobs-opengl/gl-x11-egl.c @@ -650,6 +650,17 @@ static struct gs_texture *gl_x11_egl_device_texture_create_from_dmabuf( fds, strides, offsets, modifiers); } +static struct gs_texture *gl_x11_egl_device_texture_create_from_pixmap( + gs_device_t *device, uint32_t width, uint32_t height, + enum gs_color_format color_format, uint32_t target, void *pixmap) +{ + struct gl_platform *plat = device->plat; + + return gl_egl_create_texture_from_pixmap(plat->edisplay, width, height, + color_format, target, + (EGLClientBuffer)pixmap); +} + static bool gl_x11_egl_device_query_dmabuf_capabilities( gs_device_t *device, enum gs_dmabuf_flags *dmabuf_flags, uint32_t **drm_formats, size_t *n_formats) @@ -691,6 +702,8 @@ static const struct gl_winsys_vtable egl_x11_winsys_vtable = { gl_x11_egl_device_query_dmabuf_capabilities, .device_query_dmabuf_modifiers_for_format = gl_x11_egl_device_query_dmabuf_modifiers_for_format, + .device_texture_create_from_pixmap = + gl_x11_egl_device_texture_create_from_pixmap, }; const struct gl_winsys_vtable *gl_x11_egl_get_winsys_vtable(void) diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index 599a34ba8..4a7e31d9b 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -237,6 +237,7 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, GRAPHICS_IMPORT(device_texture_create_from_dmabuf); GRAPHICS_IMPORT(device_query_dmabuf_capabilities); GRAPHICS_IMPORT(device_query_dmabuf_modifiers_for_format); + GRAPHICS_IMPORT(device_texture_create_from_pixmap); #endif return success; diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 540cf28a2..fb2a75e3c 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -360,6 +360,10 @@ struct gs_exports { uint32_t drm_format, uint64_t **modifiers, size_t *n_modifiers); + struct gs_texture *(*device_texture_create_from_pixmap)( + gs_device_t *device, uint32_t width, uint32_t height, + enum gs_color_format color_format, uint32_t target, + void *pixmap); #endif }; diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 7fae78fc8..66365e1bf 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -1421,6 +1421,16 @@ bool gs_query_dmabuf_modifiers_for_format(uint32_t drm_format, graphics->device, drm_format, modifiers, n_modifiers); } +gs_texture_t *gs_texture_create_from_pixmap(uint32_t width, uint32_t height, + enum gs_color_format color_format, + uint32_t target, void *pixmap) +{ + graphics_t *graphics = thread_graphics; + + return graphics->exports.device_texture_create_from_pixmap( + graphics->device, width, height, color_format, target, pixmap); +} + #endif gs_texture_t *gs_cubetexture_create(uint32_t size, diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index f8c045287..fa9f9e55b 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -987,6 +987,11 @@ EXPORT bool gs_query_dmabuf_modifiers_for_format(uint32_t drm_format, uint64_t **modifiers, size_t *n_modifiers); +EXPORT gs_texture_t * +gs_texture_create_from_pixmap(uint32_t width, uint32_t height, + enum gs_color_format color_format, + uint32_t target, void *pixmap); + #endif /* inline functions used by modules */