Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.
Open
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
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