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

wlr_egl_context #3208

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
54 changes: 37 additions & 17 deletions include/render/egl.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,45 @@
#ifndef RENDER_EGL_H
#define RENDER_EGL_H

#include <wlr/render/dmabuf.h>
#include <wlr/render/egl.h>

struct wlr_egl_context {
EGLDisplay display;
EGLContext context;
EGLSurface draw_surface;
EGLSurface read_surface;
struct wlr_egl {
struct wlr_egl_context ctx;
EGLDeviceEXT device; // may be EGL_NO_DEVICE_EXT
struct gbm_device *gbm_device;

struct {
// Display extensions
bool KHR_image_base;
bool EXT_image_dma_buf_import;
bool EXT_image_dma_buf_import_modifiers;

// Device extensions
bool EXT_device_drm;
bool EXT_device_drm_render_node;

// Client extensions
bool EXT_device_query;
bool KHR_platform_gbm;
bool EXT_platform_device;
} exts;

struct {
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL;
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT;
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT;
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR;
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT;
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
} procs;

struct wlr_drm_format_set dmabuf_texture_formats;
struct wlr_drm_format_set dmabuf_render_formats;
};

/**
Expand Down Expand Up @@ -48,16 +80,4 @@ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image);

int wlr_egl_dup_drm_fd(struct wlr_egl *egl);

/**
* Save the current EGL context to the structure provided in the argument.
*
* This includes display, context, draw surface and read surface.
*/
void wlr_egl_save_context(struct wlr_egl_context *context);

/**
* Restore EGL context that was previously saved using wlr_egl_save_current().
*/
bool wlr_egl_restore_context(struct wlr_egl_context *context);

#endif
1 change: 1 addition & 0 deletions include/render/gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ struct wlr_gles2_texture {
struct wlr_addon buffer_addon;
};

struct wlr_renderer *gles2_renderer_create(struct wlr_egl *egl);

bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer,
const struct wlr_gles2_pixel_format *format);
Expand Down
62 changes: 21 additions & 41 deletions include/wlr/render/egl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,49 +23,14 @@

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <pixman.h>
#include <stdbool.h>
#include <wayland-server-core.h>
#include <wlr/render/dmabuf.h>
#include <wlr/render/drm_format_set.h>

struct wlr_egl {
struct wlr_egl_context {
EGLDisplay display;
EGLContext context;
EGLDeviceEXT device; // may be EGL_NO_DEVICE_EXT
struct gbm_device *gbm_device;

struct {
// Display extensions
bool KHR_image_base;
bool EXT_image_dma_buf_import;
bool EXT_image_dma_buf_import_modifiers;

// Device extensions
bool EXT_device_drm;
bool EXT_device_drm_render_node;

// Client extensions
bool EXT_device_query;
bool KHR_platform_gbm;
bool EXT_platform_device;
} exts;

struct {
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL;
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT;
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT;
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR;
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT;
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
} procs;

struct wlr_drm_format_set dmabuf_texture_formats;
struct wlr_drm_format_set dmabuf_render_formats;
EGLSurface draw_surface;
EGLSurface read_surface;
};

/**
Expand All @@ -74,10 +39,25 @@ struct wlr_egl {
* Callers are expected to clear the current context when they are done by
* calling wlr_egl_unset_current.
*/
bool wlr_egl_make_current(struct wlr_egl *egl);
bool wlr_egl_context_set_current(struct wlr_egl_context *ctx);

/**
* Clear the EGL context
*/
bool wlr_egl_context_unset_current(struct wlr_egl_context *ctx);

bool wlr_egl_unset_current(struct wlr_egl *egl);
bool wlr_egl_context_is_current(struct wlr_egl_context *ctx);

bool wlr_egl_is_current(struct wlr_egl *egl);
/**
* Save the current EGL context to the structure provided in the argument.
*
* This includes display, context, draw surface and read surface.
*/
void wlr_egl_context_save(struct wlr_egl_context *context);

/**
* Restore EGL context that was previously saved using wlr_egl_context_save().
*/
bool wlr_egl_context_restore(struct wlr_egl_context *context);

#endif
11 changes: 8 additions & 3 deletions include/wlr/render/gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@
#include <wlr/backend.h>
#include <wlr/render/wlr_renderer.h>

struct wlr_egl;
struct wlr_egl_context;

struct wlr_renderer *wlr_gles2_renderer_create_with_drm_fd(int drm_fd);
struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl);

struct wlr_egl *wlr_gles2_renderer_get_egl(struct wlr_renderer *renderer);
/**
* Returns the current EGL context
* The pointer returned is not owned by the caller
*/
struct wlr_egl_context *wlr_gles2_renderer_get_egl_context(
struct wlr_renderer *wlr_renderer);

bool wlr_gles2_renderer_check_ext(struct wlr_renderer *renderer,
const char *ext);
/**
Expand Down
72 changes: 38 additions & 34 deletions render/egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,21 @@ static struct wlr_egl *egl_create(void) {

static bool egl_init(struct wlr_egl *egl, EGLenum platform,
void *remote_display) {
egl->display = egl->procs.eglGetPlatformDisplayEXT(platform,
egl->ctx.display = egl->procs.eglGetPlatformDisplayEXT(platform,
remote_display, NULL);
if (egl->display == EGL_NO_DISPLAY) {
if (egl->ctx.display == EGL_NO_DISPLAY) {
wlr_log(WLR_ERROR, "Failed to create EGL display");
return false;
}

EGLint major, minor;
if (eglInitialize(egl->display, &major, &minor) == EGL_FALSE) {
if (eglInitialize(egl->ctx.display, &major, &minor) == EGL_FALSE) {
wlr_log(WLR_ERROR, "Failed to initialize EGL");
return false;
}

const char *display_exts_str = eglQueryString(egl->display, EGL_EXTENSIONS);
const char *display_exts_str =
eglQueryString(egl->ctx.display, EGL_EXTENSIONS);
if (display_exts_str == NULL) {
wlr_log(WLR_ERROR, "Failed to query EGL display extensions");
return false;
Expand All @@ -262,7 +263,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform,
const char *device_exts_str = NULL, *driver_name = NULL;
if (egl->exts.EXT_device_query) {
EGLAttrib device_attrib;
if (!egl->procs.eglQueryDisplayAttribEXT(egl->display,
if (!egl->procs.eglQueryDisplayAttribEXT(egl->ctx.display,
EGL_DEVICE_EXT, &device_attrib)) {
wlr_log(WLR_ERROR, "eglQueryDisplayAttribEXT(EGL_DEVICE_EXT) failed");
return false;
Expand Down Expand Up @@ -318,7 +319,8 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform,
wlr_log(WLR_INFO, "Supported EGL device extensions: %s", device_exts_str);
}
wlr_log(WLR_INFO, "Using EGL %d.%d", (int)major, (int)minor);
wlr_log(WLR_INFO, "EGL vendor: %s", eglQueryString(egl->display, EGL_VENDOR));
wlr_log(WLR_INFO, "EGL vendor: %s",
eglQueryString(egl->ctx.display, EGL_VENDOR));
if (driver_name != NULL) {
wlr_log(WLR_INFO, "EGL driver name: %s", driver_name);
}
Expand Down Expand Up @@ -347,16 +349,16 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform,
attribs[atti++] = EGL_NONE;
assert(atti <= sizeof(attribs)/sizeof(attribs[0]));

egl->context = eglCreateContext(egl->display, EGL_NO_CONFIG_KHR,
egl->ctx.context = eglCreateContext(egl->ctx.display, EGL_NO_CONFIG_KHR,
EGL_NO_CONTEXT, attribs);
if (egl->context == EGL_NO_CONTEXT) {
if (egl->ctx.context == EGL_NO_CONTEXT) {
wlr_log(WLR_ERROR, "Failed to create EGL context");
return false;
}

if (request_high_priority) {
EGLint priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
eglQueryContext(egl->display, egl->context,
eglQueryContext(egl->ctx.display, egl->ctx.context,
EGL_CONTEXT_PRIORITY_LEVEL_IMG, &priority);
if (priority != EGL_CONTEXT_PRIORITY_HIGH_IMG) {
wlr_log(WLR_INFO, "Failed to obtain a high priority context");
Expand Down Expand Up @@ -495,10 +497,10 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {

error:
wlr_log(WLR_ERROR, "Failed to initialize EGL context");
if (egl->display) {
eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
if (egl->ctx.display) {
eglMakeCurrent(egl->ctx.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
eglTerminate(egl->display);
eglTerminate(egl->ctx.display);
}
free(egl);
eglReleaseThread();
Expand All @@ -513,10 +515,11 @@ void wlr_egl_destroy(struct wlr_egl *egl) {
wlr_drm_format_set_finish(&egl->dmabuf_render_formats);
wlr_drm_format_set_finish(&egl->dmabuf_texture_formats);

eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglMakeCurrent(egl->ctx.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);

eglDestroyContext(egl->display, egl->context);
eglTerminate(egl->display);
eglDestroyContext(egl->ctx.display, egl->ctx.context);
eglTerminate(egl->ctx.display);
eglReleaseThread();

if (egl->gbm_device) {
Expand All @@ -535,39 +538,39 @@ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImage image) {
if (!image) {
return true;
}
return egl->procs.eglDestroyImageKHR(egl->display, image);
return egl->procs.eglDestroyImageKHR(egl->ctx.display, image);
}

bool wlr_egl_make_current(struct wlr_egl *egl) {
if (!eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
egl->context)) {
bool wlr_egl_context_set_current(struct wlr_egl_context *ctx) {
if (!eglMakeCurrent(ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
ctx->context)) {
wlr_log(WLR_ERROR, "eglMakeCurrent failed");
return false;
}
return true;
}

bool wlr_egl_unset_current(struct wlr_egl *egl) {
if (!eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
bool wlr_egl_context_unset_current(struct wlr_egl_context *ctx) {
if (!eglMakeCurrent(ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT)) {
wlr_log(WLR_ERROR, "eglMakeCurrent failed");
return false;
}
return true;
}

bool wlr_egl_is_current(struct wlr_egl *egl) {
return eglGetCurrentContext() == egl->context;
bool wlr_egl_context_is_current(struct wlr_egl_context *ctx) {
return eglGetCurrentContext() == ctx->context;
}

void wlr_egl_save_context(struct wlr_egl_context *context) {
void wlr_egl_context_save(struct wlr_egl_context *context) {
context->display = eglGetCurrentDisplay();
context->context = eglGetCurrentContext();
context->draw_surface = eglGetCurrentSurface(EGL_DRAW);
context->read_surface = eglGetCurrentSurface(EGL_READ);
}

bool wlr_egl_restore_context(struct wlr_egl_context *context) {
bool wlr_egl_context_restore(struct wlr_egl_context *context) {
// If the saved context is a null-context, we must use the current
// display instead of the saved display because eglMakeCurrent() can't
// handle EGL_NO_DISPLAY.
Expand Down Expand Up @@ -672,15 +675,15 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
attribs[atti++] = EGL_NONE;
assert(atti < sizeof(attribs)/sizeof(attribs[0]));

EGLImageKHR image = egl->procs.eglCreateImageKHR(egl->display, EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
EGLImageKHR image = egl->procs.eglCreateImageKHR(egl->ctx.display,
EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
if (image == EGL_NO_IMAGE_KHR) {
wlr_log(WLR_ERROR, "eglCreateImageKHR failed");
return EGL_NO_IMAGE_KHR;
}

*external_only = !wlr_drm_format_set_has(&egl->dmabuf_render_formats,
attributes->format, attributes->modifier);
attributes->format, attributes->modifier);
return image;
}

Expand Down Expand Up @@ -714,7 +717,7 @@ static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats) {
}

EGLint num;
if (!egl->procs.eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) {
if (!egl->procs.eglQueryDmaBufFormatsEXT(egl->ctx.display, 0, NULL, &num)) {
wlr_log(WLR_ERROR, "Failed to query number of dmabuf formats");
return -1;
}
Expand All @@ -725,7 +728,8 @@ static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats) {
return -1;
}

if (!egl->procs.eglQueryDmaBufFormatsEXT(egl->display, num, *formats, &num)) {
if (!egl->procs.eglQueryDmaBufFormatsEXT(egl->ctx.display, num, *formats,
&num)) {
wlr_log(WLR_ERROR, "Failed to query dmabuf format");
free(*formats);
return -1;
Expand All @@ -747,7 +751,7 @@ static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format,
}

EGLint num;
if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->display, format, 0,
if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->ctx.display, format, 0,
NULL, NULL, &num)) {
wlr_log(WLR_ERROR, "Failed to query dmabuf number of modifiers");
return -1;
Expand All @@ -769,7 +773,7 @@ static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format,
return -1;
}

if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->display, format, num,
if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->ctx.display, format, num,
*modifiers, *external_only, &num)) {
wlr_log(WLR_ERROR, "Failed to query dmabuf modifiers");
free(*modifiers);
Expand Down Expand Up @@ -870,8 +874,8 @@ int wlr_egl_dup_drm_fd(struct wlr_egl *egl) {
#endif

if (render_name == NULL) {
const char *primary_name = egl->procs.eglQueryDeviceStringEXT(egl->device,
EGL_DRM_DEVICE_FILE_EXT);
const char *primary_name = egl->procs.eglQueryDeviceStringEXT(
egl->device, EGL_DRM_DEVICE_FILE_EXT);
if (primary_name == NULL) {
wlr_log(WLR_ERROR,
"eglQueryDeviceStringEXT(EGL_DRM_DEVICE_FILE_EXT) failed");
Expand Down
Loading