From 15dacebc36ffa137aefafcfbe723c7b35af5cc2b Mon Sep 17 00:00:00 2001 From: Mariusz Bialonczyk Date: Thu, 2 Aug 2018 13:37:23 +0200 Subject: [PATCH 1/5] multi-backend: do not expose internal renderers backend_get_renderer() is now returning the renderer of the primary GPU, instead of its own renderer, since that's the thing which actually does all of the "real" rendering wlr_multi_backend_add() is now adding all subbackends (otherwise only one GPU is handled). credits: @ascent12 --- backend/drm/backend.c | 7 ++++++- backend/multi/backend.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 5833d46e..1df5cdd1 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -51,7 +51,12 @@ static void backend_destroy(struct wlr_backend *backend) { static struct wlr_renderer *backend_get_renderer( struct wlr_backend *backend) { struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; - return drm->renderer.wlr_rend; + + if (drm->parent) { + return drm->parent->renderer.wlr_rend; + } else { + return drm->renderer.wlr_rend; + } } static struct wlr_backend_impl backend_impl = { diff --git a/backend/multi/backend.c b/backend/multi/backend.c index f1d50347..e0038955 100644 --- a/backend/multi/backend.c +++ b/backend/multi/backend.c @@ -143,7 +143,7 @@ bool wlr_multi_backend_add(struct wlr_backend *_multi, struct wlr_renderer *multi_renderer = multi_backend_get_renderer(&multi->backend); struct wlr_renderer *backend_renderer = wlr_backend_get_renderer(backend); - if (multi_renderer != NULL && backend_renderer != NULL) { + if (multi_renderer != NULL && backend_renderer != NULL && multi_renderer != backend_renderer) { wlr_log(WLR_ERROR, "Could not add backend: multiple renderers at the " "same time aren't supported"); return false; From ad406db21c7cebf21bf73ae6ceb88fdf1849395e Mon Sep 17 00:00:00 2001 From: Mariusz Bialonczyk Date: Thu, 2 Aug 2018 13:38:00 +0200 Subject: [PATCH 2/5] gles2: change context when it is not current Texture functions, that create and manipulate textures should switch the current context if necessary. thanks to: @emersion Fixes #934 --- include/render/gles2.h | 2 +- render/gles2/renderer.c | 8 ++++---- render/gles2/texture.c | 18 +++++++++++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 8b036f80..f649f3e2 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -88,7 +88,7 @@ const struct wlr_gles2_pixel_format *get_gles2_format_from_wl( enum wl_shm_format fmt); const enum wl_shm_format *get_gles2_formats(size_t *len); -struct wlr_gles2_texture *get_gles2_texture_in_context( +struct wlr_gles2_texture *gles2_get_texture( struct wlr_texture *wlr_texture); void push_gles2_marker(const char *file, const char *func); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 27c16e52..b6e97041 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -116,7 +116,7 @@ static bool gles2_render_texture_with_matrix(struct wlr_renderer *wlr_renderer, struct wlr_gles2_renderer *renderer = gles2_get_renderer_in_context(wlr_renderer); struct wlr_gles2_texture *texture = - get_gles2_texture_in_context(wlr_texture); + gles2_get_texture(wlr_texture); struct wlr_gles2_tex_shader *shader = NULL; GLenum target = 0; @@ -213,7 +213,7 @@ static const enum wl_shm_format *gles2_renderer_formats( static bool gles2_resource_is_wl_drm_buffer(struct wlr_renderer *wlr_renderer, struct wl_resource *resource) { struct wlr_gles2_renderer *renderer = - gles2_get_renderer_in_context(wlr_renderer); + gles2_get_renderer(wlr_renderer); if (!eglQueryWaylandBufferWL) { return false; @@ -227,7 +227,7 @@ static bool gles2_resource_is_wl_drm_buffer(struct wlr_renderer *wlr_renderer, static void gles2_wl_drm_buffer_get_size(struct wlr_renderer *wlr_renderer, struct wl_resource *buffer, int *width, int *height) { struct wlr_gles2_renderer *renderer = - gles2_get_renderer_in_context(wlr_renderer); + gles2_get_renderer(wlr_renderer); if (!eglQueryWaylandBufferWL) { return; @@ -323,7 +323,7 @@ static struct wlr_texture *gles2_texture_from_dmabuf( static void gles2_init_wl_display(struct wlr_renderer *wlr_renderer, struct wl_display *wl_display) { struct wlr_gles2_renderer *renderer = - gles2_get_renderer_in_context(wlr_renderer); + gles2_get_renderer(wlr_renderer); if (!wlr_egl_bind_display(renderer->egl, wl_display)) { wlr_log(WLR_INFO, "failed to bind wl_display to EGL"); } diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 1e55f4c4..22d02cde 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -16,7 +16,7 @@ static const struct wlr_texture_impl texture_impl; -static struct wlr_gles2_texture *gles2_get_texture( +struct wlr_gles2_texture *gles2_get_texture( struct wlr_texture *wlr_texture) { assert(wlr_texture->impl == &texture_impl); return (struct wlr_gles2_texture *)wlr_texture; @@ -25,7 +25,9 @@ static struct wlr_gles2_texture *gles2_get_texture( struct wlr_gles2_texture *get_gles2_texture_in_context( struct wlr_texture *wlr_texture) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - assert(wlr_egl_is_current(texture->egl)); + if (!wlr_egl_is_current(texture->egl)) { + wlr_egl_make_current(texture->egl, EGL_NO_SURFACE, NULL); + } return texture; } @@ -143,7 +145,9 @@ static const struct wlr_texture_impl texture_impl = { struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl, enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width, uint32_t height, const void *data) { - assert(wlr_egl_is_current(egl)); + if (!wlr_egl_is_current(egl)) { + wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); + } const struct wlr_gles2_pixel_format *fmt = get_gles2_format_from_wl(wl_fmt); if (fmt == NULL) { @@ -180,7 +184,9 @@ struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl, struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, struct wl_resource *data) { - assert(wlr_egl_is_current(egl)); + if (!wlr_egl_is_current(egl)) { + wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); + } if (!glEGLImageTargetTexture2DOES) { return NULL; @@ -239,7 +245,9 @@ struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, struct wlr_dmabuf_attributes *attribs) { - assert(wlr_egl_is_current(egl)); + if (!wlr_egl_is_current(egl)) { + wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); + } if (!glEGLImageTargetTexture2DOES) { return NULL; From e547e55be079b612a8b81b18cdca09f3c523f939 Mon Sep 17 00:00:00 2001 From: Mariusz Bialonczyk Date: Thu, 2 Aug 2018 23:41:59 +0200 Subject: [PATCH 3/5] multi-gpu: do not flip screens on secondary GPU All screens on secondary GPU in multiple GPU configurations was flipped 180. The flipped screens was always on secondary card (the primary card was always correct). Tested on nouveau with: WLR_DRM_DEVICES=/dev/dri/card1:/dev/dri/card2 WLR_DRM_DEVICES=/dev/dri/card2:/dev/dri/card1 The commit is fixing this problem. Now all screens are "normal". --- backend/drm/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 38e6315d..b5485327 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -238,7 +238,7 @@ struct gbm_bo *copy_drm_surface_mgpu(struct wlr_drm_surface *dest, assert(tex); float mat[9]; - wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_FLIPPED_180); + wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_NORMAL); struct wlr_renderer *renderer = dest->renderer->wlr_rend; wlr_renderer_begin(renderer, dest->width, dest->height); From 4bee710c308924395ca8a7ff8492a3feb696ca48 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 4 Aug 2018 15:03:34 +1200 Subject: [PATCH 4/5] Fix hardware cursor on secondary GPU Create rendering resources on parent GPU, so that we can sample the passed in texture properly. The cursor buffer needs to remain on the same GPU. --- backend/drm/drm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 9d030dff..c050a356 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -628,7 +628,6 @@ static bool drm_connector_set_cursor(struct wlr_output *output, bool update_texture) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; - struct wlr_drm_renderer *renderer = &drm->renderer; struct wlr_drm_crtc *crtc = conn->crtc; if (!crtc) { @@ -654,13 +653,16 @@ static bool drm_connector_set_cursor(struct wlr_output *output, ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h); h = ret ? 64 : h; + struct wlr_drm_renderer *renderer = + drm->parent ? &drm->parent->renderer : &drm->renderer; + if (!init_drm_surface(&plane->surf, renderer, w, h, GBM_FORMAT_ARGB8888, 0)) { wlr_log(WLR_ERROR, "Cannot allocate cursor resources"); return false; } - plane->cursor_bo = gbm_bo_create(renderer->gbm, w, h, + plane->cursor_bo = gbm_bo_create(drm->renderer.gbm, w, h, GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); if (!plane->cursor_bo) { wlr_log_errno(WLR_ERROR, "Failed to create cursor bo"); From 1a2b3445dcd2c53fa5a1e315e436f5814c8765e6 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 4 Aug 2018 17:02:53 +1200 Subject: [PATCH 5/5] Remove unused data from gbm_bo userdata These aren't used anymore and crashes when the gbm_bo tries to get destroyed (e.g. on hotplug). --- backend/drm/renderer.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index b5485327..fa7d090e 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -188,46 +188,29 @@ bool export_drm_bo(struct gbm_bo *bo, struct wlr_dmabuf_attributes *attribs) { return true; } -struct tex { - struct wlr_egl *egl; - EGLImageKHR img; - struct wlr_texture *tex; -}; - -static void free_eglimage(struct gbm_bo *bo, void *data) { - struct tex *tex = data; - - wlr_egl_destroy_image(tex->egl, tex->img); - wlr_texture_destroy(tex->tex); - free(tex); +static void free_tex(struct gbm_bo *bo, void *data) { + struct wlr_texture *tex = data; + wlr_texture_destroy(tex); } static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer, struct gbm_bo *bo) { - struct tex *tex = gbm_bo_get_user_data(bo); - if (tex != NULL) { - return tex->tex; - } - - tex = calloc(1, sizeof(struct tex)); - if (tex == NULL) { - return NULL; + struct wlr_texture *tex = gbm_bo_get_user_data(bo); + if (tex) { + return tex; } struct wlr_dmabuf_attributes attribs; if (!export_drm_bo(bo, &attribs)) { - free(tex); return NULL; } - tex->tex = wlr_texture_from_dmabuf(renderer->wlr_rend, &attribs); - if (tex->tex == NULL) { - free(tex); - return NULL; + tex = wlr_texture_from_dmabuf(renderer->wlr_rend, &attribs); + if (tex) { + gbm_bo_set_user_data(bo, tex, free_tex); } - gbm_bo_set_user_data(bo, tex, free_eglimage); - return tex->tex; + return tex; } struct gbm_bo *copy_drm_surface_mgpu(struct wlr_drm_surface *dest,