diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-10-02 08:46:06 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-02 08:46:06 -0400 |
commit | 87a0cb7ba37eed29662ec16ce95493a0238ef660 (patch) | |
tree | 95554cb777848ce7246b651c09740d307bcdd506 /backend/drm/drm.c | |
parent | aa8a4f12b7e7ea8c3a1876f0585dd6171f8cb705 (diff) | |
parent | 9ec9edc40d4694dedfd7f00eb9106ce5ed133239 (diff) |
Merge pull request #182 from ascent12/drm-multi-gpu
DRM Multi-GPU
Diffstat (limited to 'backend/drm/drm.c')
-rw-r--r-- | backend/drm/drm.c | 790 |
1 files changed, 331 insertions, 459 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 1a656172..1a5fea9f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -20,27 +20,25 @@ #include <wlr/render/matrix.h> #include <wlr/render/gles2.h> #include <wlr/render.h> -#include "backend/drm.h" -#include "backend/drm-util.h" +#include "backend/drm/drm.h" +#include "backend/drm/iface.h" +#include "backend/drm/util.h" -bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - extern const struct wlr_drm_interface legacy_iface; - extern const struct wlr_drm_interface atomic_iface; - - if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { +bool wlr_drm_check_features(struct wlr_drm_backend *drm) { + if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); return false; } if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - backend->iface = &legacy_iface; - } else if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { + drm->iface = &legacy_iface; + } else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - backend->iface = &legacy_iface; + drm->iface = &legacy_iface; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - backend->iface = &atomic_iface; + drm->iface = &atomic_iface; } return true; @@ -53,8 +51,8 @@ static int cmp_plane(const void *arg1, const void *arg2) { return (int)a->type - (int)b->type; } -static bool init_planes(struct wlr_drm_backend *backend) { - drmModePlaneRes *plane_res = drmModeGetPlaneResources(backend->fd); +static bool init_planes(struct wlr_drm_backend *drm) { + drmModePlaneRes *plane_res = drmModeGetPlaneResources(drm->fd); if (!plane_res) { wlr_log_errno(L_ERROR, "Failed to get DRM plane resources"); return false; @@ -67,17 +65,17 @@ static bool init_planes(struct wlr_drm_backend *backend) { return true; } - backend->num_planes = plane_res->count_planes; - backend->planes = calloc(backend->num_planes, sizeof(*backend->planes)); - if (!backend->planes) { + drm->num_planes = plane_res->count_planes; + drm->planes = calloc(drm->num_planes, sizeof(*drm->planes)); + if (!drm->planes) { wlr_log_errno(L_ERROR, "Allocation failed"); goto error_res; } - for (size_t i = 0; i < backend->num_planes; ++i) { - struct wlr_drm_plane *p = &backend->planes[i]; + for (size_t i = 0; i < drm->num_planes; ++i) { + struct wlr_drm_plane *p = &drm->planes[i]; - drmModePlane *plane = drmModeGetPlane(backend->fd, plane_res->planes[i]); + drmModePlane *plane = drmModeGetPlane(drm->fd, plane_res->planes[i]); if (!plane) { wlr_log_errno(L_ERROR, "Failed to get DRM plane"); goto error_planes; @@ -87,44 +85,43 @@ static bool init_planes(struct wlr_drm_backend *backend) { p->possible_crtcs = plane->possible_crtcs; uint64_t type; - if (!wlr_drm_get_plane_props(backend->fd, p->id, &p->props) || - !wlr_drm_get_prop(backend->fd, p->id, p->props.type, &type)) { + if (!wlr_drm_get_plane_props(drm->fd, p->id, &p->props) || + !wlr_drm_get_prop(drm->fd, p->id, p->props.type, &type)) { drmModeFreePlane(plane); goto error_planes; } p->type = type; - backend->num_type_planes[type]++; + drm->num_type_planes[type]++; drmModeFreePlane(plane); } wlr_log(L_INFO, "(%zu overlay, %zu primary, %zu cursor)", - backend->num_overlay_planes, - backend->num_primary_planes, - backend->num_cursor_planes); + drm->num_overlay_planes, + drm->num_primary_planes, + drm->num_cursor_planes); - qsort(backend->planes, backend->num_planes, - sizeof(*backend->planes), cmp_plane); + qsort(drm->planes, drm->num_planes, sizeof(*drm->planes), cmp_plane); - backend->overlay_planes = backend->planes; - backend->primary_planes = backend->overlay_planes - + backend->num_overlay_planes; - backend->cursor_planes = backend->primary_planes - + backend->num_primary_planes; + drm->overlay_planes = drm->planes; + drm->primary_planes = drm->overlay_planes + + drm->num_overlay_planes; + drm->cursor_planes = drm->primary_planes + + drm->num_primary_planes; drmModeFreePlaneResources(plane_res); return true; error_planes: - free(backend->planes); + free(drm->planes); error_res: drmModeFreePlaneResources(plane_res); return false; } -bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { - drmModeRes *res = drmModeGetResources(backend->fd); +bool wlr_drm_resources_init(struct wlr_drm_backend *drm) { + drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { wlr_log_errno(L_ERROR, "Failed to get DRM resources"); return false; @@ -132,20 +129,20 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { wlr_log(L_INFO, "Found %d DRM CRTCs", res->count_crtcs); - backend->num_crtcs = res->count_crtcs; - backend->crtcs = calloc(backend->num_crtcs, sizeof(backend->crtcs[0])); - if (!backend->crtcs) { + drm->num_crtcs = res->count_crtcs; + drm->crtcs = calloc(drm->num_crtcs, sizeof(drm->crtcs[0])); + if (!drm->crtcs) { wlr_log_errno(L_ERROR, "Allocation failed"); goto error_res; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { - struct wlr_drm_crtc *crtc = &backend->crtcs[i]; + for (size_t i = 0; i < drm->num_crtcs; ++i) { + struct wlr_drm_crtc *crtc = &drm->crtcs[i]; crtc->id = res->crtcs[i]; - wlr_drm_get_crtc_props(backend->fd, crtc->id, &crtc->props); + wlr_drm_get_crtc_props(drm->fd, crtc->id, &crtc->props); } - if (!init_planes(backend)) { + if (!init_planes(drm)) { goto error_crtcs; } @@ -154,311 +151,185 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { return true; error_crtcs: - free(backend->crtcs); + free(drm->crtcs); error_res: drmModeFreeResources(res); return false; } -void wlr_drm_resources_free(struct wlr_drm_backend *backend) { - if (!backend) { +void wlr_drm_resources_free(struct wlr_drm_backend *drm) { + if (!drm) { return; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { - struct wlr_drm_crtc *crtc = &backend->crtcs[i]; + + for (size_t i = 0; i < drm->num_crtcs; ++i) { + struct wlr_drm_crtc *crtc = &drm->crtcs[i]; drmModeAtomicFree(crtc->atomic); if (crtc->mode_id) { - drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); + drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); } } - free(backend->crtcs); - free(backend->planes); -} - -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { - renderer->gbm = gbm_create_device(fd); - if (!renderer->gbm) { - wlr_log(L_ERROR, "Failed to create GBM device: %s", strerror(errno)); - return false; - } - - if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, - GBM_FORMAT_ARGB8888, renderer->gbm)) { - gbm_device_destroy(renderer->gbm); - return false; - } - - renderer->fd = fd; - return true; + free(drm->crtcs); + free(drm->planes); } -void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer) { - if (!renderer) { - return; - } - - wlr_egl_free(&renderer->egl); - gbm_device_destroy(renderer->gbm); +static void wlr_drm_connector_make_current(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + wlr_drm_surface_make_current(&conn->crtc->primary->surf); } -static bool wlr_drm_plane_renderer_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { - if (plane->width == width && plane->height == height) { - return true; - } - - plane->width = width; - plane->height = height; - - plane->gbm = gbm_surface_create(renderer->gbm, width, height, - format, GBM_BO_USE_RENDERING | flags); - if (!plane->gbm) { - wlr_log_errno(L_ERROR, "Failed to create GBM surface for plane"); - return false; - } - - plane->egl = wlr_egl_create_surface(&renderer->egl, plane->gbm); - if (plane->egl == EGL_NO_SURFACE) { - wlr_log(L_ERROR, "Failed to create EGL surface for plane"); - return false; - } - - return true; -} - -static void wlr_drm_plane_renderer_free(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - if (!renderer || !plane) { - return; - } - - eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - } - if (plane->back) { - gbm_surface_release_buffer(plane->gbm, plane->back); - } - - if (plane->egl) { - eglDestroySurface(renderer->egl.display, plane->egl); - } - if (plane->gbm) { - gbm_surface_destroy(plane->gbm); - } - - if (plane->wlr_tex) { - wlr_texture_destroy(plane->wlr_tex); - } - if (plane->wlr_rend) { - wlr_renderer_destroy(plane->wlr_rend); - } - if (plane->cursor_bo) { - gbm_bo_destroy(plane->cursor_bo); - } - - plane->width = 0; - plane->height = 0; - plane->egl = EGL_NO_SURFACE; - plane->gbm = NULL; - plane->front = NULL; - plane->back = NULL; - plane->wlr_rend = NULL; - plane->wlr_tex = NULL; - plane->cursor_bo = NULL; -} - -static void wlr_drm_plane_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - eglMakeCurrent(renderer->egl.display, plane->egl, plane->egl, - renderer->egl.context); -} - -static void wlr_drm_plane_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - } - - eglSwapBuffers(renderer->egl.display, plane->egl); +static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; - plane->front = plane->back; - plane->back = gbm_surface_lock_front_buffer(plane->gbm); -} - -static void wlr_drm_output_make_current(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_plane_make_current(output->renderer, output->crtc->primary); -} - -static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - wlr_drm_plane_swap_buffers(renderer, plane); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf); + if (drm->parent) { + bo = wlr_drm_surface_mgpu_copy(&plane->mgpu_surf, bo); + } - uint32_t fb_id = get_fb_for_bo(plane->back); + uint32_t fb_id = get_fb_for_bo(bo); - if (backend->iface->crtc_pageflip(backend, output, crtc, fb_id, NULL)) { - output->pageflip_pending = true; + if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { + conn->pageflip_pending = true; } else { - wl_event_source_timer_update(output->retry_pageflip, - 1000.0f / output->output.current_mode->refresh); + wl_event_source_timer_update(conn->retry_pageflip, + 1000.0f / conn->output.current_mode->refresh); } } -static void wlr_drm_output_set_gamma(struct wlr_output *_output, +static void wlr_drm_connector_set_gamma(struct wlr_output *output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - drmModeCrtcSetGamma(backend->fd, output->crtc->id, size, r, g, b); + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + drmModeCrtcSetGamma(conn->drm->fd, conn->crtc->id, size, r, g, b); } -static uint16_t wlr_drm_output_get_gamma_size(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - drmModeCrtc *crtc = output->old_crtc; - if (!crtc) { - return 0; - } - return crtc->gamma_size; +static uint16_t wlr_drm_connector_get_gamma_size(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + drmModeCrtc *crtc = conn->old_crtc; + return crtc ? crtc->gamma_size : 0; } -void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { +void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_backend *drm = conn->drm; + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = plane->front; - if (!bo) { - // Render a black frame to start the rendering loop - wlr_drm_plane_make_current(renderer, plane); - glViewport(0, 0, plane->width, plane->height); - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - wlr_drm_plane_swap_buffers(renderer, plane); - - bo = plane->back; - } + struct gbm_bo *bo = wlr_drm_surface_get_front( + drm->parent ? &plane->mgpu_surf : &plane->surf); + uint32_t fb_id = get_fb_for_bo(bo); - struct wlr_drm_output_mode *_mode = - (struct wlr_drm_output_mode *)output->output.current_mode; - drmModeModeInfo *mode = &_mode->mode; - if (backend->iface->crtc_pageflip(backend, output, crtc, get_fb_for_bo(bo), mode)) { - output->pageflip_pending = true; + struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; + if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, &mode->drm_mode)) { + conn->pageflip_pending = true; } else { - wl_event_source_timer_update(output->retry_pageflip, - 1000.0f / output->output.current_mode->refresh); + wl_event_source_timer_update(conn->retry_pageflip, + 1000.0f / conn->output.current_mode->refresh); } } -static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { +static void wlr_drm_connector_enable(struct wlr_output *output, bool enable) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - backend->iface->conn_enable(backend, output, enable); + struct wlr_drm_backend *drm = conn->drm; + drm->iface->conn_enable(drm, conn, enable); if (enable) { - wlr_drm_output_start_renderer(output); + wlr_drm_connector_start_renderer(conn); } } -static void realloc_planes(struct wlr_drm_backend *backend, const uint32_t *crtc_in) { +static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) { // overlay, primary, cursor for (int type = 0; type < 3; ++type) { - if (backend->num_type_planes[type] == 0) { + if (drm->num_type_planes[type] == 0) { continue; } - uint32_t possible[backend->num_type_planes[type]]; - uint32_t crtc[backend->num_crtcs]; - uint32_t crtc_res[backend->num_crtcs]; + uint32_t possible[drm->num_type_planes[type]]; + uint32_t crtc[drm->num_crtcs]; + uint32_t crtc_res[drm->num_crtcs]; - for (size_t i = 0; i < backend->num_type_planes[type]; ++i) { - possible[i] = backend->type_planes[type][i].possible_crtcs; + for (size_t i = 0; i < drm->num_type_planes[type]; ++i) { + possible[i] = drm->type_planes[type][i].possible_crtcs; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_in[i] == UNMATCHED) { crtc[i] = SKIP; - } else if (backend->crtcs[i].planes[type]) { - crtc[i] = backend->crtcs[i].planes[type] - - backend->type_planes[type]; + } else if (drm->crtcs[i].planes[type]) { + crtc[i] = drm->crtcs[i].planes[type] + - drm->type_planes[type]; } else { crtc[i] = UNMATCHED; } } - match_obj(backend->num_type_planes[type], possible, - backend->num_crtcs, crtc, crtc_res); + match_obj(drm->num_type_planes[type], possible, + drm->num_crtcs, crtc, crtc_res); - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_res[i] == UNMATCHED || crtc_res[i] == SKIP) { continue; } - struct wlr_drm_crtc *c = &backend->crtcs[i]; + struct wlr_drm_crtc *c = &drm->crtcs[i]; struct wlr_drm_plane **old = &c->planes[type]; - struct wlr_drm_plane *new = &backend->type_planes[type][crtc_res[i]]; + struct wlr_drm_plane *new = &drm->type_planes[type][crtc_res[i]]; if (*old != new) { - wlr_drm_plane_renderer_free(&backend->renderer, *old); - wlr_drm_plane_renderer_free(&backend->renderer, new); + if (*old) { + wlr_drm_surface_finish(&(*old)->surf); + } + wlr_drm_surface_finish(&new->surf); *old = new; } } } } -static void realloc_crtcs(struct wlr_drm_backend *backend, - struct wlr_drm_output *output) { - uint32_t crtc[backend->num_crtcs]; - uint32_t crtc_res[backend->num_crtcs]; - uint32_t possible_crtc[backend->outputs->length]; +static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_connector *conn) { + uint32_t crtc[drm->num_crtcs]; + uint32_t crtc_res[drm->num_crtcs]; + uint32_t possible_crtc[drm->outputs->length]; - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { crtc[i] = UNMATCHED; } memset(possible_crtc, 0, sizeof(possible_crtc)); ssize_t index = -1; - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *o = backend->outputs->items[i]; - if (o == output) { + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_connector *c = drm->outputs->items[i]; + if (c == conn) { index = i; } - if (o->state != WLR_DRM_OUTPUT_CONNECTED) { + if (c->state != WLR_DRM_CONN_CONNECTED) { continue; } - possible_crtc[i] = o->possible_crtc; - crtc[o->crtc - backend->crtcs] = i; + possible_crtc[i] = c->possible_crtc; + crtc[c->crtc - drm->crtcs] = i; } assert(index != -1); - possible_crtc[index] = output->possible_crtc; - match_obj(backend->outputs->length, possible_crtc, - backend->num_crtcs, crtc, crtc_res); + possible_crtc[index] = conn->possible_crtc; + match_obj(drm->outputs->length, possible_crtc, drm->num_crtcs, + crtc, crtc_res); bool matched = false; - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { // We don't want any of the current monitors to be deactivated. if (crtc[i] != UNMATCHED && crtc_res[i] == UNMATCHED) { return; @@ -473,43 +344,35 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, return; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_res[i] == UNMATCHED) { continue; } if (crtc_res[i] != crtc[i]) { - struct wlr_drm_output *o = backend->outputs->items[crtc_res[i]]; - o->crtc = &backend->crtcs[i]; + struct wlr_drm_connector *c = drm->outputs->items[crtc_res[i]]; + c->crtc = &drm->crtcs[i]; } } - realloc_planes(backend, crtc_res); + realloc_planes(drm, crtc_res); } -static bool wlr_drm_output_set_mode(struct wlr_output *_output, - struct wlr_output_mode *mode) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend - = wl_container_of(output->renderer, backend, renderer); - - wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, - mode->width, mode->height, mode->refresh); - - drmModeConnector *conn = drmModeGetConnector(backend->fd, output->connector); +static uint32_t get_possible_crtcs(int fd, uint32_t conn_id) { + drmModeConnector *conn = drmModeGetConnector(fd, conn_id); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); - goto error_output; + return 0; } if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) { - wlr_log(L_ERROR, "%s is not connected", output->output.name); - goto error_output; + wlr_log(L_ERROR, "Output is not connected"); + goto error_conn; } drmModeEncoder *enc = NULL; for (int i = 0; !enc && i < conn->count_encoders; ++i) { - enc = drmModeGetEncoder(backend->fd, conn->encoders[i]); + enc = drmModeGetEncoder(fd, conn->encoders[i]); } if (!enc) { @@ -517,77 +380,92 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, goto error_conn; } - output->possible_crtc = enc->possible_crtcs; - realloc_crtcs(backend, output); + uint32_t ret = enc->possible_crtcs; + drmModeFreeEncoder(enc); + drmModeFreeConnector(conn); + return ret; + +error_conn: + drmModeFreeConnector(conn); + return 0; +} + +static bool wlr_drm_connector_set_mode(struct wlr_output *output, + struct wlr_output_mode *mode) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; + + wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", conn->output.name, + mode->width, mode->height, mode->refresh); + + conn->possible_crtc = get_possible_crtcs(drm->fd, conn->id); + if (conn->possible_crtc == 0) { + goto error_conn; + } + + realloc_crtcs(drm, conn); - if (!output->crtc) { - wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->output.name); - goto error_enc; + if (!conn->crtc) { + wlr_log(L_ERROR, "Unable to match %s with a CRTC", conn->output.name); + goto error_conn; } - struct wlr_drm_crtc *crtc = output->crtc; - wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", output->output.name, - crtc - backend->crtcs, - crtc->overlay ? crtc->overlay - backend->overlay_planes : -1, - crtc->primary ? crtc->primary - backend->primary_planes : -1, - crtc->cursor ? crtc->cursor - backend->cursor_planes : -1); + struct wlr_drm_crtc *crtc = conn->crtc; + wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", conn->output.name, + crtc - drm->crtcs, + crtc->overlay ? crtc->overlay - drm->overlay_planes : -1, + crtc->primary ? crtc->primary - drm->primary_planes : -1, + crtc->cursor ? crtc->cursor - drm->cursor_planes : -1); - output->state = WLR_DRM_OUTPUT_CONNECTED; - output->width = output->output.width = mode->width; - output->height = output->output.height = mode->height; - output->output.current_mode = mode; - wl_signal_emit(&output->output.events.resolution, &output->output); + conn->state = WLR_DRM_CONN_CONNECTED; + conn->output.width = mode->width; + conn->output.height = mode->height; + conn->output.current_mode = mode; + wl_signal_emit(&conn->output.events.resolution, &conn->output); // Since realloc_crtcs can deallocate planes on OTHER outputs, // we actually need to reinitalise all of them - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; - struct wlr_output_mode *mode = output->output.current_mode; - struct wlr_drm_crtc *crtc = output->crtc; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_connector *conn = drm->outputs->items[i]; + struct wlr_output_mode *mode = conn->output.current_mode; + struct wlr_drm_crtc *crtc = conn->crtc; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { + if (conn->state != WLR_DRM_CONN_CONNECTED) { continue; } - if (!wlr_drm_plane_renderer_init(&backend->renderer, crtc->primary, - mode->width, mode->height, GBM_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT)) { + if (!wlr_drm_plane_surfaces_init(crtc->primary, drm, + mode->width, mode->height, GBM_FORMAT_XRGB8888)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); - goto error_enc; + goto error_conn; } - wlr_drm_output_start_renderer(output); + wlr_drm_connector_start_renderer(conn); } - drmModeFreeEncoder(enc); - drmModeFreeConnector(conn); return true; -error_enc: - drmModeFreeEncoder(enc); error_conn: - drmModeFreeConnector(conn); -error_output: - wlr_drm_output_cleanup(output); + wlr_drm_connector_cleanup(conn); return false; } -static void wlr_drm_output_transform(struct wlr_output *output, +static void wlr_drm_connector_transform(struct wlr_output *output, enum wl_output_transform transform) { output->transform = transform; } -static bool wlr_drm_output_set_cursor(struct wlr_output *_output, +static bool wlr_drm_connector_set_cursor(struct wlr_output *output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend - = wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; + struct wlr_drm_renderer *renderer = &drm->renderer; + + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->cursor; if (!buf) { - return backend->iface->crtc_set_cursor(backend, crtc, NULL); + return drm->iface->crtc_set_cursor(drm, crtc, NULL); } // We don't have a real cursor plane, so we make a fake one @@ -600,12 +478,12 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, crtc->cursor = plane; } - if (!plane->gbm) { + if (!plane->surf.gbm) { int ret; uint64_t w, h; - ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_WIDTH, &w); + ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &w); w = ret ? 64 : w; - ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_HEIGHT, &h); + ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h); h = ret ? 64 : h; if (width > w || height > h) { @@ -613,7 +491,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return false; } - if (!wlr_drm_plane_renderer_init(renderer, plane, w, h, GBM_FORMAT_ARGB8888, 0)) { + if (!wlr_drm_surface_init(&plane->surf, renderer, w, h, GBM_FORMAT_ARGB8888, 0)) { wlr_log(L_ERROR, "Cannot allocate cursor resources"); return false; } @@ -627,12 +505,12 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // OpenGL will read the pixels out upside down, // so we need to flip the image vertically - wlr_matrix_texture(plane->matrix, plane->width, plane->height, - output->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); + wlr_matrix_texture(plane->matrix, plane->surf.width, plane->surf.height, + conn->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); // TODO the image needs to be rotated depending on the output rotation - plane->wlr_rend = wlr_gles2_renderer_create(&backend->backend); + plane->wlr_rend = wlr_gles2_renderer_create(&drm->backend); if (!plane->wlr_rend) { return false; } @@ -655,12 +533,12 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return false; } - wlr_drm_plane_make_current(renderer, plane); + wlr_drm_surface_make_current(&plane->surf); wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); - glViewport(0, 0, plane->width, plane->height); + glViewport(0, 0, plane->surf.width, plane->surf.height); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); @@ -670,26 +548,25 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, glFinish(); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride); - glReadPixels(0, 0, plane->width, plane->height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); + glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - wlr_drm_plane_swap_buffers(renderer, plane); + wlr_drm_surface_swap_buffers(&plane->surf); gbm_bo_unmap(bo, bo_data); - return backend->iface->crtc_set_cursor(backend, crtc, bo); + return drm->iface->crtc_set_cursor(drm, crtc, bo); } -static bool wlr_drm_output_move_cursor(struct wlr_output *_output, +static bool wlr_drm_connector_move_cursor(struct wlr_output *output, int x, int y) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; int width, height, tmp; - wlr_output_effective_resolution(_output, &width, &height); + wlr_output_effective_resolution(output, &width, &height); - switch (_output->transform) { + switch (output->transform) { case WL_OUTPUT_TRANSFORM_NORMAL: // nothing to do break; @@ -706,51 +583,45 @@ static bool wlr_drm_output_move_cursor(struct wlr_output *_output, default: // TODO other transformations wlr_log(L_ERROR, "TODO: handle surface to crtc for transformation = %d", - _output->transform); + output->transform); break; } - return backend->iface->crtc_move_cursor(backend, output->crtc, x, y); + return drm->iface->crtc_move_cursor(drm, conn->crtc, x, y); } -static void wlr_drm_output_destroy(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_output_cleanup(output); - wl_event_source_remove(output->retry_pageflip); - free(output); +static void wlr_drm_connector_destroy(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + wlr_drm_connector_cleanup(conn); + wl_event_source_remove(conn->retry_pageflip); + free(conn); } static struct wlr_output_impl output_impl = { - .enable = wlr_drm_output_enable, - .set_mode = wlr_drm_output_set_mode, - .transform = wlr_drm_output_transform, - .set_cursor = wlr_drm_output_set_cursor, - .move_cursor = wlr_drm_output_move_cursor, - .destroy = wlr_drm_output_destroy, - .make_current = wlr_drm_output_make_current, - .swap_buffers = wlr_drm_output_swap_buffers, - .set_gamma = wlr_drm_output_set_gamma, - .get_gamma_size = wlr_drm_output_get_gamma_size, + .enable = wlr_drm_connector_enable, + .set_mode = wlr_drm_connector_set_mode, + .transform = wlr_drm_connector_transform, + .set_cursor = wlr_drm_connector_set_cursor, + .move_cursor = wlr_drm_connector_move_cursor, + .destroy = wlr_drm_connector_destroy, + .make_current = wlr_drm_connector_make_current, + .swap_buffers = wlr_drm_connector_swap_buffers, + .set_gamma = wlr_drm_connector_set_gamma, + .get_gamma_size = wlr_drm_connector_get_gamma_size, }; static int retry_pageflip(void *data) { - struct wlr_drm_output *output = data; - wlr_log(L_INFO, "%s: Retrying pageflip", output->output.name); - wlr_drm_output_start_renderer(output); + struct wlr_drm_connector *conn = data; + wlr_log(L_INFO, "%s: Retrying pageflip", conn->output.name); + wlr_drm_connector_start_renderer(conn); return 0; } static int find_id(const void *item, const void *cmp_to) { - const struct wlr_drm_output *output = item; + const struct wlr_drm_connector *conn = item; const uint32_t *id = cmp_to; - if (output->connector < *id) { - return -1; - } else if (output->connector > *id) { - return 1; - } else { - return 0; - } + return (int)conn->id - (int)*id; } static const int32_t subpixel_map[] = { @@ -762,126 +633,126 @@ static const int32_t subpixel_map[] = { [DRM_MODE_SUBPIXEL_NONE] = WL_OUTPUT_SUBPIXEL_NONE, }; -void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { +void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { wlr_log(L_INFO, "Scanning DRM connectors"); - drmModeRes *res = drmModeGetResources(backend->fd); + drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { wlr_log_errno(L_ERROR, "Failed to get DRM resources"); return; } - size_t seen_len = backend->outputs->length; + size_t seen_len = drm->outputs->length; // +1 so it can never be 0 bool seen[seen_len + 1]; memset(seen, 0, sizeof(seen)); for (int i = 0; i < res->count_connectors; ++i) { - drmModeConnector *conn = drmModeGetConnector(backend->fd, + drmModeConnector *drm_conn = drmModeGetConnector(drm->fd, res->connectors[i]); - if (!conn) { + if (!drm_conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); continue; } - struct wlr_drm_output *output; - int index = list_seq_find(backend->outputs, find_id, &conn->connector_id); + struct wlr_drm_connector *wlr_conn; + int index = list_seq_find(drm->outputs, find_id, &drm_conn->connector_id); if (index == -1) { - output = calloc(1, sizeof(*output)); - if (!output) { + wlr_conn = calloc(1, sizeof(*wlr_conn)); + if (!wlr_conn) { wlr_log_errno(L_ERROR, "Allocation failed"); - drmModeFreeConnector(conn); + drmModeFreeConnector(drm_conn); continue; } - wlr_output_init(&output->output, &output_impl); + wlr_output_init(&wlr_conn->output, &output_impl); - struct wl_event_loop *ev = wl_display_get_event_loop(backend->display); - output->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, - output); + struct wl_event_loop *ev = wl_display_get_event_loop(drm->display); + wlr_conn->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, + wlr_conn); - output->renderer = &backend->renderer; - output->state = WLR_DRM_OUTPUT_DISCONNECTED; - output->connector = conn->connector_id; + wlr_conn->drm = drm; + wlr_conn->state = WLR_DRM_CONN_DISCONNECTED; + wlr_conn->id = drm_conn->connector_id; - drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, - conn->encoder_id); + drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, + drm_conn->encoder_id); if (curr_enc) { - output->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id); + wlr_conn->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); drmModeFreeEncoder(curr_enc); } - output->output.phys_width = conn->mmWidth; - output->output.phys_height = conn->mmHeight; - output->output.subpixel = subpixel_map[conn->subpixel]; - snprintf(output->output.name, sizeof(output->output.name), "%s-%"PRIu32, - conn_get_name(conn->connector_type), - conn->connector_type_id); + wlr_conn->output.phys_width = drm_conn->mmWidth; + wlr_conn->output.phys_height = drm_conn->mmHeight; + wlr_conn->output.subpixel = subpixel_map[drm_conn->subpixel]; + snprintf(wlr_conn->output.name, sizeof(wlr_conn->output.name), + "%s-%"PRIu32, + conn_get_name(drm_conn->connector_type), + drm_conn->connector_type_id); - wlr_drm_get_connector_props(backend->fd, - output->connector, &output->props); + wlr_drm_get_connector_props(drm->fd, wlr_conn->id, &wlr_conn->props); size_t edid_len = 0; - uint8_t *edid = wlr_drm_get_prop_blob(backend->fd, - output->connector, output->props.edid, &edid_len); - parse_edid(&output->output, edid_len, edid); + uint8_t *edid = wlr_drm_get_prop_blob(drm->fd, + wlr_conn->id, wlr_conn->props.edid, &edid_len); + parse_edid(&wlr_conn->output, edid_len, edid); free(edid); - if (list_add(backend->outputs, output) == -1) { + if (list_add(drm->outputs, wlr_conn) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); - drmModeFreeConnector(conn); - wl_event_source_remove(output->retry_pageflip); - free(output); + drmModeFreeConnector(drm_conn); + wl_event_source_remove(wlr_conn->retry_pageflip); + free(wlr_conn); continue; } - wlr_output_create_global(&output->output, backend->display); - wlr_log(L_INFO, "Found display '%s'", output->output.name); + wlr_output_create_global(&wlr_conn->output, drm->display); + wlr_log(L_INFO, "Found display '%s'", wlr_conn->output.name); } else { - output = backend->outputs->items[index]; + wlr_conn = drm->outputs->items[index]; seen[index] = true; } - if (output->state == WLR_DRM_OUTPUT_DISCONNECTED && - conn->connection == DRM_MODE_CONNECTED) { + if (wlr_conn->state == WLR_DRM_CONN_DISCONNECTED && + drm_conn->connection == DRM_MODE_CONNECTED) { - wlr_log(L_INFO, "'%s' connected", output->output.name); + wlr_log(L_INFO, "'%s' connected", wlr_conn->output.name); wlr_log(L_INFO, "Detected modes:"); - for (int i = 0; i < conn->count_modes; ++i) { - struct wlr_drm_output_mode *mode = calloc(1, - sizeof(struct wlr_drm_output_mode)); + for (int i = 0; i < drm_conn->count_modes; ++i) { + struct wlr_drm_mode *mode = calloc(1, sizeof(*mode)); if (!mode) { wlr_log_errno(L_ERROR, "Allocation failed"); continue; } - mode->mode = conn->modes[i]; - mode->wlr_mode.width = mode->mode.hdisplay; - mode->wlr_mode.height = mode->mode.vdisplay; - mode->wlr_mode.refresh = calculate_refresh_rate(&mode->mode); + mode->drm_mode = drm_conn->modes[i]; + mode->wlr_mode.width = mode->drm_mode.hdisplay; + mode->wlr_mode.height = mode->drm_mode.vdisplay; + mode->wlr_mode.refresh = calculate_refresh_rate(&mode->drm_mode); wlr_log(L_INFO, " %"PRId32"@%"PRId32"@%"PRId32, mode->wlr_mode.width, mode->wlr_mode.height, mode->wlr_mode.refresh); - if (list_add(output->output.modes, mode) == -1) { + if (list_add(wlr_conn->output.modes, mode) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); free(mode); continue; } } - output->state = WLR_DRM_OUTPUT_NEEDS_MODESET; - wlr_log(L_INFO, "Sending modesetting signal for '%s'", output->output.name); - wl_signal_emit(&backend->backend.events.output_add, &output->output); - } else if (output->state == WLR_DRM_OUTPUT_CONNECTED && - conn->connection != DRM_MODE_CONNECTED) { + wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET; + wlr_log(L_INFO, "Sending modesetting signal for '%s'", + wlr_conn->output.name); + wl_signal_emit(&drm->backend.events.output_add, &wlr_conn->output); + } else if (wlr_conn->state == WLR_DRM_CONN_CONNECTED && + drm_conn->connection != DRM_MODE_CONNECTED) { - wlr_log(L_INFO, "'%s' disconnected", output->output.name); - wlr_drm_output_cleanup(output); + wlr_log(L_INFO, "'%s' disconnected", wlr_conn->output.name); + wlr_drm_connector_cleanup(wlr_conn); } - drmModeFreeConnector(conn); + drmModeFreeConnector(drm_conn); } drmModeFreeResources(res); @@ -891,38 +762,36 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { continue; } - struct wlr_drm_output *output = backend->outputs->items[i]; + struct wlr_drm_connector *conn = drm->outputs->items[i]; - wlr_log(L_INFO, "'%s' disappeared", output->output.name); - wlr_drm_output_cleanup(output); + wlr_log(L_INFO, "'%s' disappeared", conn->output.name); + wlr_drm_connector_cleanup(conn); - drmModeFreeCrtc(output->old_crtc); - wl_event_source_remove(output->retry_pageflip); - free(output); + drmModeFreeCrtc(conn->old_crtc); + wl_event_source_remove(conn->retry_pageflip); + free(conn); - list_del(backend->outputs, i); + list_del(drm->outputs, i); } } static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { - struct wlr_drm_output *output = user; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_connector *conn = user; + struct wlr_drm_backend *drm = conn->drm; - output->pageflip_pending = false; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { + conn->pageflip_pending = false; + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_plane *plane = output->crtc->primary; - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - plane->front = NULL; + wlr_drm_surface_post(&conn->crtc->primary->surf); + if (drm->parent) { + wlr_drm_surface_post(&conn->crtc->primary->mgpu_surf); } - if (backend->session->active) { - wl_signal_emit(&output->output.events.frame, &output->output); + if (drm->session->active) { + wl_signal_emit(&conn->output.events.frame, &conn->output); } } @@ -940,9 +809,9 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { uint64_t to_close = (1 << drm->outputs->length) - 1; for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - if (output->state == WLR_DRM_OUTPUT_CONNECTED) { - output->state = WLR_DRM_OUTPUT_CLEANUP; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + if (conn->state == WLR_DRM_CONN_CONNECTED) { + conn->state = WLR_DRM_CONN_CLEANUP; } } @@ -951,8 +820,8 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { while (to_close && time(NULL) < timeout) { wlr_drm_event(drm->fd, 0, NULL); for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - if (output->state != WLR_DRM_OUTPUT_CLEANUP || !output->pageflip_pending) { + struct wlr_drm_connector *conn = drm->outputs->items[i]; + if (conn->state != WLR_DRM_CONN_CLEANUP || !conn->pageflip_pending) { to_close &= ~(1 << i); } } @@ -963,50 +832,53 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { } for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - drmModeCrtc *crtc = output->old_crtc; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + drmModeCrtc *crtc = conn->old_crtc; if (!crtc) { continue; } drmModeSetCrtc(drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, - &output->connector, 1, &crtc->mode); + &conn->id, 1, &crtc->mode); drmModeFreeCrtc(crtc); } } -void wlr_drm_output_cleanup(struct wlr_drm_output *output) { - if (!output) { +void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { + if (!conn) { return; } - struct wlr_drm_renderer *renderer = output->renderer; - struct wlr_drm_backend *backend = - wl_container_of(renderer, backend, renderer); + struct wlr_drm_backend *drm = conn->drm; - switch (output->state) { - case WLR_DRM_OUTPUT_CONNECTED: - case WLR_DRM_OUTPUT_CLEANUP:; - struct wlr_drm_crtc *crtc = output->crtc; + switch (conn->state) { + case WLR_DRM_CONN_CONNECTED: + case WLR_DRM_CONN_CLEANUP:; + struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_plane_renderer_free(renderer, crtc->planes[i]); - if (crtc->planes[i] && crtc->planes[i]->id == 0) { + if (!crtc->planes[i]) { + continue; + } + + wlr_drm_surface_finish(&crtc->planes[i]->surf); + wlr_drm_surface_finish(&crtc->planes[i]->mgpu_surf); + if (crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; } } - output->crtc = NULL; - output->possible_crtc = 0; + conn->crtc = NULL; + conn->possible_crtc = 0; /* Fallthrough */ - case WLR_DRM_OUTPUT_NEEDS_MODESET: + case WLR_DRM_CONN_NEEDS_MODESET: wlr_log(L_INFO, "Emmiting destruction signal for '%s'", - output->output.name); - wl_signal_emit(&backend->backend.events.output_remove, &output->output); + conn->output.name); + wl_signal_emit(&drm->backend.events.output_remove, &conn->output); break; - case WLR_DRM_OUTPUT_DISCONNECTED: + case WLR_DRM_CONN_DISCONNECTED: break; } - output->state = WLR_DRM_OUTPUT_DISCONNECTED; + conn->state = WLR_DRM_CONN_DISCONNECTED; } |