Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

render/egl: add wlr_egl_create_image_from_wl_drm #798

Merged
merged 1 commit into from
Apr 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions include/wlr/render/egl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,22 @@ struct wlr_egl {

// TODO: Allocate and return a wlr_egl
/**
* Initializes an egl context for the given platform and remote display.
* Initializes an EGL context for the given platform and remote display.
* Will attempt to load all possibly required api functions.
*/
bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
EGLint *config_attribs, EGLint visual_id);

/**
* Frees all related egl resources, makes the context not-current and
* Frees all related EGL resources, makes the context not-current and
* unbinds a bound wayland display.
*/
void wlr_egl_finish(struct wlr_egl *egl);

/**
* Binds the given display to the egl instance.
* This will allow clients to create egl surfaces from wayland ones and render to it.
* Binds the given display to the EGL instance.
* This will allow clients to create EGL surfaces from wayland ones and render
* to it.
*/
bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display);

Expand All @@ -53,7 +54,14 @@ bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display)
EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window);

/**
* Creates an egl image from the given dmabuf attributes. Check usability
* Creates an EGL image from the given wl_drm buffer resource.
*/
EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl,
struct wl_resource *data, EGLint *fmt, int *width, int *height,
bool *inverted_y);

/**
* Creates an EGL image from the given dmabuf attributes. Check usability
* of the dmabuf with wlr_egl_check_import_dmabuf once first.
*/
EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
Expand All @@ -78,7 +86,7 @@ int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, int format,
uint64_t **modifiers);

/**
* Destroys an egl image created with the given wlr_egl.
* Destroys an EGL image created with the given wlr_egl.
*/
bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image);

Expand Down
2 changes: 1 addition & 1 deletion include/wlr/render/wlr_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer,
const void *data);

/**
* Create a new texture from a wayland DRM resource. The returned texture is
* Create a new texture from a wl_drm resource. The returned texture is
* immutable.
*/
struct wlr_texture *wlr_texture_from_wl_drm(struct wlr_renderer *renderer,
Expand Down
40 changes: 36 additions & 4 deletions render/egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ static void print_dmabuf_formats(struct wlr_egl *egl) {

char str_formats[num * 5 + 1];
for (int i = 0; i < num; i++) {
snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ", (char*)&formats[i]);
snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ",
(char*)&formats[i]);
}
wlr_log(L_DEBUG, "Supported dmabuf buffer formats: %s", str_formats);
free(formats);
Expand Down Expand Up @@ -230,8 +231,9 @@ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImage image) {
}

EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) {
EGLSurface surf = eglCreatePlatformWindowSurfaceEXT(egl->display, egl->config,
window, NULL);
assert(eglCreatePlatformWindowSurfaceEXT);
EGLSurface surf = eglCreatePlatformWindowSurfaceEXT(egl->display,
egl->config, window, NULL);
if (surf == EGL_NO_SURFACE) {
wlr_log(L_ERROR, "Failed to create EGL surface");
return EGL_NO_SURFACE;
Expand Down Expand Up @@ -302,7 +304,37 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
return true;
}

EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl,
struct wl_resource *data, EGLint *fmt, int *width, int *height,
bool *inverted_y) {
if (!eglQueryWaylandBufferWL || !eglCreateImageKHR) {
return NULL;
}

if (!eglQueryWaylandBufferWL(egl->display, data, EGL_TEXTURE_FORMAT, fmt)) {
return NULL;
}

eglQueryWaylandBufferWL(egl->display, data, EGL_WIDTH, width);
eglQueryWaylandBufferWL(egl->display, data, EGL_HEIGHT, height);

EGLint _inverted_y;
if (eglQueryWaylandBufferWL(egl->display, data, EGL_WAYLAND_Y_INVERTED_WL,
&_inverted_y)) {
*inverted_y = !!_inverted_y;
} else {
*inverted_y = false;
}

const EGLint attribs[] = {
EGL_WAYLAND_PLANE_WL, 0,
EGL_NONE,
};
return eglCreateImageKHR(egl->display, egl->context, EGL_WAYLAND_BUFFER_WL,
data, attribs);
}

EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
struct wlr_dmabuf_buffer_attribs *attributes) {
bool has_modifier = false;
if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) {
Expand Down
49 changes: 13 additions & 36 deletions render/gles2/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) {
}
if (texture->image) {
assert(eglDestroyImageKHR);
eglDestroyImageKHR(texture->renderer->egl->display, texture->image);
wlr_egl_destroy_image(texture->renderer->egl, texture->image);
}

if (texture->type == WLR_GLES2_TEXTURE_GLTEX) {
Expand Down Expand Up @@ -144,34 +144,17 @@ struct wlr_texture *gles2_texture_from_pixels(struct wlr_renderer *wlr_renderer,
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);

GLES2_DEBUG_POP;
return (struct wlr_texture *)texture;
return &texture->wlr_texture;
}

struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer,
struct wl_resource *data) {
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);

if (!eglQueryWaylandBufferWL || !eglCreateImageKHR ||
!glEGLImageTargetTexture2DOES) {
return NULL;
}

EGLint fmt;
if (!eglQueryWaylandBufferWL(renderer->egl->display, data,
EGL_TEXTURE_FORMAT, &fmt)) {
if (!glEGLImageTargetTexture2DOES) {
return NULL;
}

EGLint width, height;
eglQueryWaylandBufferWL(renderer->egl->display, data, EGL_WIDTH, &width);
eglQueryWaylandBufferWL(renderer->egl->display, data, EGL_HEIGHT, &height);

EGLint inverted_y;
if (!eglQueryWaylandBufferWL(renderer->egl->display, data,
EGL_WAYLAND_Y_INVERTED_WL, &inverted_y)) {
inverted_y = 0;
}

struct wlr_gles2_texture *texture =
calloc(1, sizeof(struct wlr_gles2_texture));
if (texture == NULL) {
Expand All @@ -180,10 +163,15 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer,
}
wlr_texture_init(&texture->wlr_texture, &texture_impl);
texture->renderer = renderer;
texture->width = width;
texture->height = height;
texture->wl_drm = data;
texture->inverted_y = !!inverted_y;

EGLint fmt;
texture->image = wlr_egl_create_image_from_wl_drm(renderer->egl, data, &fmt,
&texture->width, &texture->height, &texture->inverted_y);
if (texture->image == NULL) {
free(texture);
return NULL;
}

GLenum target;
switch (fmt) {
Expand All @@ -204,25 +192,14 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer,
return NULL;
}

EGLint attribs[] = {
EGL_WAYLAND_PLANE_WL, 0,
EGL_NONE,
};
texture->image = eglCreateImageKHR(renderer->egl->display,
renderer->egl->context, EGL_WAYLAND_BUFFER_WL, data, attribs);
if (texture->image == NULL) {
free(texture);
return NULL;
}

GLES2_DEBUG_PUSH;

glGenTextures(1, &texture->image_tex);
glBindTexture(target, texture->image_tex);
glEGLImageTargetTexture2DOES(target, texture->image);

GLES2_DEBUG_POP;
return (struct wlr_texture *)texture;
return &texture->wlr_texture;
}

struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer,
Expand Down Expand Up @@ -267,5 +244,5 @@ struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer,
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, texture->image);

GLES2_DEBUG_POP;
return (struct wlr_texture *)texture;
return &texture->wlr_texture;
}