diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 40b73925..ecd98fda 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -593,8 +593,8 @@ static bool drm_connector_commit(struct wlr_output *output) { } static void drm_connector_rollback_render(struct wlr_output *output) { - struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend); - wlr_egl_unset_current(&drm->renderer.egl); + struct wlr_drm_connector *conn = get_drm_connector_from_output(output); + return drm_surface_unset_current(&conn->crtc->primary->surf); } size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, @@ -883,7 +883,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output, return false; } - if (!plane->surf.gbm) { + if (!plane->surf.swapchain) { int ret; uint64_t w, h; ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &w); diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 4b6e9bf1..b78cf7e2 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -12,9 +12,13 @@ #include #include #include "backend/drm/drm.h" +#include "render/gbm_allocator.h" +#include "render/swapchain.h" +#include "render/wlr_renderer.h" bool init_drm_renderer(struct wlr_drm_backend *drm, struct wlr_drm_renderer *renderer, wlr_renderer_create_func_t create_renderer_func) { + // TODO: get rid of renderer->gbm renderer->gbm = gbm_create_device(drm->fd); if (!renderer->gbm) { wlr_log(WLR_ERROR, "Failed to create GBM device"); @@ -44,9 +48,17 @@ bool init_drm_renderer(struct wlr_drm_backend *drm, goto error_gbm; } + renderer->allocator = wlr_gbm_allocator_create(drm->fd); + if (renderer->allocator == NULL) { + wlr_log(WLR_ERROR, "Failed to create allocator"); + goto error_wlr_rend; + } + renderer->fd = drm->fd; return true; +error_wlr_rend: + wlr_renderer_destroy(renderer->wlr_rend); error_gbm: gbm_device_destroy(renderer->gbm); return false; @@ -57,6 +69,7 @@ void finish_drm_renderer(struct wlr_drm_renderer *renderer) { return; } + wlr_allocator_destroy(&renderer->allocator->base); wlr_renderer_destroy(renderer->wlr_rend); wlr_egl_finish(&renderer->egl); gbm_device_destroy(renderer->gbm); @@ -64,7 +77,7 @@ void finish_drm_renderer(struct wlr_drm_renderer *renderer) { static bool init_drm_surface(struct wlr_drm_surface *surf, struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, - uint32_t format, struct wlr_drm_format_set *set, uint32_t flags) { + uint32_t format, const struct wlr_drm_format_set *set, uint32_t flags) { if (surf->width == width && surf->height == height) { return true; } @@ -73,43 +86,41 @@ static bool init_drm_surface(struct wlr_drm_surface *surf, surf->width = width; surf->height = height; - if (surf->gbm) { - gbm_surface_destroy(surf->gbm); - surf->gbm = NULL; - } - wlr_egl_destroy_surface(&surf->renderer->egl, surf->egl); + wlr_buffer_unlock(surf->back_buffer); + surf->back_buffer = NULL; + wlr_swapchain_destroy(surf->swapchain); + surf->swapchain = NULL; - if (!(flags & GBM_BO_USE_LINEAR) && set != NULL) { - const struct wlr_drm_format *drm_format = - wlr_drm_format_set_get(set, format); - if (drm_format != NULL) { - surf->gbm = gbm_surface_create_with_modifiers(renderer->gbm, - width, height, format, drm_format->modifiers, drm_format->len); + const struct wlr_drm_format *drm_format = NULL; + const struct wlr_drm_format format_no_modifiers = { .format = format }; + if (set != NULL) { + drm_format = wlr_drm_format_set_get(set, format); + } else { + drm_format = &format_no_modifiers; + } + + struct wlr_drm_format *format_linear = NULL; + if (flags & GBM_BO_USE_LINEAR) { + format_linear = calloc(1, sizeof(struct wlr_drm_format) + sizeof(uint64_t)); + if (format_linear == NULL) { + return false; } + format_linear->format = format; + format_linear->len = 1; + format_linear->modifiers[0] = DRM_FORMAT_MOD_LINEAR; + drm_format = format_linear; } - if (surf->gbm == NULL) { - surf->gbm = gbm_surface_create(renderer->gbm, width, height, - format, GBM_BO_USE_RENDERING | flags); - } - if (!surf->gbm) { - wlr_log_errno(WLR_ERROR, "Failed to create GBM surface"); - goto error_zero; - } - - surf->egl = wlr_egl_create_surface(&renderer->egl, surf->gbm); - if (surf->egl == EGL_NO_SURFACE) { - wlr_log(WLR_ERROR, "Failed to create EGL surface"); - goto error_gbm; + surf->swapchain = wlr_swapchain_create(&renderer->allocator->base, + width, height, drm_format); + free(format_linear); + if (surf->swapchain == NULL) { + wlr_log(WLR_ERROR, "Failed to create swapchain"); + memset(surf, 0, sizeof(*surf)); + return false; } return true; - -error_gbm: - gbm_surface_destroy(surf->gbm); -error_zero: - memset(surf, 0, sizeof(*surf)); - return false; } static void finish_drm_surface(struct wlr_drm_surface *surf) { @@ -117,17 +128,44 @@ static void finish_drm_surface(struct wlr_drm_surface *surf) { return; } - wlr_egl_destroy_surface(&surf->renderer->egl, surf->egl); - if (surf->gbm) { - gbm_surface_destroy(surf->gbm); - } + wlr_buffer_unlock(surf->back_buffer); + wlr_swapchain_destroy(surf->swapchain); memset(surf, 0, sizeof(*surf)); } bool drm_surface_make_current(struct wlr_drm_surface *surf, int *buffer_age) { - return wlr_egl_make_current(&surf->renderer->egl, surf->egl, buffer_age); + wlr_buffer_unlock(surf->back_buffer); + surf->back_buffer = wlr_swapchain_acquire(surf->swapchain); + if (surf->back_buffer == NULL) { + wlr_log(WLR_ERROR, "Failed to acquire swapchain buffer"); + return false; + } + + if (!wlr_egl_make_current(&surf->renderer->egl, EGL_NO_SURFACE, NULL)) { + return false; + } + if (!wlr_renderer_bind_buffer(surf->renderer->wlr_rend, surf->back_buffer)) { + wlr_log(WLR_ERROR, "Failed to attach buffer to renderer"); + return false; + } + + // TODO: damage tracking + if (buffer_age != NULL) { + *buffer_age = -1; + } + return true; +} + +void drm_surface_unset_current(struct wlr_drm_surface *surf) { + assert(surf->back_buffer != NULL); + + wlr_renderer_bind_buffer(surf->renderer->wlr_rend, NULL); + wlr_egl_unset_current(&surf->renderer->egl); + + wlr_buffer_unlock(surf->back_buffer); + surf->back_buffer = NULL; } bool export_drm_bo(struct gbm_bo *bo, struct wlr_dmabuf_attributes *attribs) { @@ -251,7 +289,7 @@ void drm_fb_clear(struct wlr_drm_fb *fb) { assert(!fb->bo); break; case WLR_DRM_FB_TYPE_SURFACE: - gbm_surface_release_buffer(fb->surf->gbm, fb->bo); + abort(); // TODO: remove this case entirely break; case WLR_DRM_FB_TYPE_WLR_BUFFER: gbm_bo_destroy(fb->bo); @@ -264,29 +302,22 @@ void drm_fb_clear(struct wlr_drm_fb *fb) { fb->bo = NULL; if (fb->mgpu_bo) { - assert(fb->mgpu_surf); + // TODO + /*assert(fb->mgpu_surf); gbm_surface_release_buffer(fb->mgpu_surf->gbm, fb->mgpu_bo); fb->mgpu_bo = NULL; - fb->mgpu_surf = NULL; + fb->mgpu_surf = NULL;*/ } } bool drm_fb_lock_surface(struct wlr_drm_fb *fb, struct wlr_drm_surface *surf) { - drm_fb_clear(fb); + assert(surf->back_buffer != NULL); - if (!wlr_egl_swap_buffers(&surf->renderer->egl, surf->egl, NULL)) { - wlr_log(WLR_ERROR, "Failed to swap buffers"); + if (!drm_fb_import_wlr(fb, surf->renderer, surf->back_buffer, NULL)) { return false; } - fb->bo = gbm_surface_lock_front_buffer(surf->gbm); - if (!fb->bo) { - wlr_log(WLR_ERROR, "Failed to lock front buffer"); - return false; - } - - fb->type = WLR_DRM_FB_TYPE_SURFACE; - fb->surf = surf; + drm_surface_unset_current(surf); return true; } @@ -299,7 +330,7 @@ bool drm_fb_import_wlr(struct wlr_drm_fb *fb, struct wlr_drm_renderer *renderer, return false; } - if (!wlr_drm_format_set_has(set, attribs.format, attribs.modifier)) { + if (set && !wlr_drm_format_set_has(set, attribs.format, attribs.modifier)) { // The format isn't supported by the plane. Try stripping the alpha // channel, if any. uint32_t format = strip_alpha_channel(attribs.format); @@ -410,7 +441,8 @@ struct gbm_bo *drm_fb_acquire(struct wlr_drm_fb *fb, struct wlr_drm_backend *drm wlr_render_texture_with_matrix(renderer, tex, mat, 1.0f); wlr_renderer_end(renderer); - if (!wlr_egl_swap_buffers(&mgpu->renderer->egl, mgpu->egl, NULL)) { + // TODO + /*if (!wlr_egl_swap_buffers(&mgpu->renderer->egl, mgpu->egl, NULL)) { wlr_log(WLR_ERROR, "Failed to swap buffers"); return NULL; } @@ -421,6 +453,6 @@ struct gbm_bo *drm_fb_acquire(struct wlr_drm_fb *fb, struct wlr_drm_backend *drm return NULL; } - fb->mgpu_surf = mgpu; + fb->mgpu_surf = mgpu;*/ return fb->mgpu_bo; } diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index bfccf9d5..8cc4b0de 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -20,6 +20,7 @@ struct wlr_drm_renderer { uint32_t gbm_format; struct wlr_renderer *wlr_rend; + struct wlr_gbm_allocator *allocator; }; struct wlr_drm_surface { @@ -28,8 +29,8 @@ struct wlr_drm_surface { uint32_t width; uint32_t height; - struct gbm_surface *gbm; - EGLSurface egl; + struct wlr_swapchain *swapchain; + struct wlr_buffer *back_buffer; }; enum wlr_drm_fb_type { @@ -45,10 +46,7 @@ struct wlr_drm_fb { struct wlr_drm_surface *mgpu_surf; struct gbm_bo *mgpu_bo; - union { - struct wlr_drm_surface *surf; - struct wlr_buffer *wlr_buf; - }; + struct wlr_buffer *wlr_buf; }; bool init_drm_renderer(struct wlr_drm_backend *drm, @@ -56,6 +54,7 @@ bool init_drm_renderer(struct wlr_drm_backend *drm, void finish_drm_renderer(struct wlr_drm_renderer *renderer); bool drm_surface_make_current(struct wlr_drm_surface *surf, int *buffer_age); +void drm_surface_unset_current(struct wlr_drm_surface *surf); bool export_drm_bo(struct gbm_bo *bo, struct wlr_dmabuf_attributes *attribs); void drm_fb_clear(struct wlr_drm_fb *fb);