From: Ander Conselvan de Oliveira <ander.conselvan.de.olive...@intel.com>
--- compositor/compositor-drm.c | 228 +++++++++++++++++++++++-------------------- 1 files changed, 120 insertions(+), 108 deletions(-) diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c index cd342e6..c52d4a0 100644 --- a/compositor/compositor-drm.c +++ b/compositor/compositor-drm.c @@ -65,28 +65,25 @@ struct drm_output { uint32_t crtc_id; uint32_t connector_id; drmModeCrtcPtr original_crtc; - GLuint rbo[2]; - uint32_t fb_id[2]; - EGLImageKHR image[2]; - struct gbm_bo *bo[2]; - uint32_t current; - - uint32_t fs_surf_fb_id; - uint32_t pending_fs_surf_fb_id; + struct gbm_surface *surface; + EGLSurface egl_surface; + uint32_t current_fb_id; + uint32_t next_fb_id; + struct gbm_bo *current_bo; + struct gbm_bo *next_bo; }; static int drm_output_prepare_render(struct wlsc_output *output_base) { struct drm_output *output = (struct drm_output *) output_base; + struct wlsc_compositor *ec = output->base.compositor; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + if (!eglMakeCurrent(ec->display, output->egl_surface, + output->egl_surface, ec->context)) { + fprintf(stderr, "failed to make current\n"); return -1; + } return 0; } @@ -97,20 +94,35 @@ drm_output_present(struct wlsc_output *output_base) struct drm_output *output = (struct drm_output *) output_base; struct drm_compositor *c = (struct drm_compositor *) output->base.compositor; - uint32_t fb_id = 0; + EGLint handle, stride; + int ret; + + if (output->next_fb_id == 0) { + if (drm_output_prepare_render(output_base)) + return -1; - glFlush(); + eglSwapBuffers(c->base.display, output->egl_surface); + output->next_bo = gbm_surface_get_bo(output->surface); - output->current ^= 1; + if (!output->next_bo) + return -1; - if (output->pending_fs_surf_fb_id != 0) { - fb_id = output->pending_fs_surf_fb_id; - } else { - fb_id = output->fb_id[output->current ^ 1]; + stride = gbm_bo_get_pitch(output->next_bo); + handle = gbm_bo_get_handle(output->next_bo).u32; + + ret = drmModeAddFB(c->drm.fd, + output->base.current->width, + output->base.current->height, + 24, 32, stride, handle, &output->next_fb_id); + if (ret) { + gbm_surface_release_bo(output->surface, output->next_bo); + output->next_bo = NULL; + return ret; + } } drmModePageFlip(c->drm.fd, output->crtc_id, - fb_id, + output->next_fb_id, DRM_MODE_PAGE_FLIP_EVENT, output); return 0; @@ -125,14 +137,20 @@ page_flip_handler(int fd, unsigned int frame, (struct drm_compositor *) output->base.compositor; uint32_t msecs; - if (output->fs_surf_fb_id) { - drmModeRmFB(c->drm.fd, output->fs_surf_fb_id); - output->fs_surf_fb_id = 0; + drmModeRmFB(c->drm.fd, output->current_fb_id); + output->current_fb_id = 0; + + output->current_fb_id = output->next_fb_id; + output->next_fb_id = 0; + + if (output->current_bo) { + gbm_surface_release_bo(output->surface, output->current_bo); + output->current_bo = NULL; } - if (output->pending_fs_surf_fb_id) { - output->fs_surf_fb_id = output->pending_fs_surf_fb_id; - output->pending_fs_surf_fb_id = 0; + if (output->next_bo) { + output->current_bo = output->next_bo; + output->next_bo = NULL; } msecs = sec * 1000 + usec / 1000; @@ -179,7 +197,7 @@ drm_output_prepare_scanout_surface(struct wlsc_output *output_base, if (ret) return -1; - output->pending_fs_surf_fb_id = fb_id; + output->next_fb_id = fb_id; return 0; } @@ -262,7 +280,6 @@ drm_output_destroy(struct wlsc_output *output_base) struct drm_compositor *c = (struct drm_compositor *) output->base.compositor; drmModeCrtcPtr origcrtc = output->original_crtc; - int i; /* Turn off hardware cursor */ drm_output_set_cursor(&output->base, NULL); @@ -273,24 +290,12 @@ drm_output_destroy(struct wlsc_output *output_base) &output->connector_id, 1, &origcrtc->mode); drmModeFreeCrtc(origcrtc); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - 0); - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glDeleteRenderbuffers(2, output->rbo); - - /* Destroy output buffers */ - for (i = 0; i < 2; i++) { - drmModeRmFB(c->drm.fd, output->fb_id[i]); - c->base.destroy_image(c->base.display, output->image[i]); - gbm_bo_destroy(output->bo[i]); - } - c->crtc_allocator &= ~(1 << output->crtc_id); c->connector_allocator &= ~(1 << output->connector_id); + eglDestroySurface(c->base.display, output->egl_surface); + gbm_surface_destroy(output->surface); + wlsc_output_destroy(&output->base); wl_list_remove(&output->base.link); @@ -313,7 +318,7 @@ on_drm_input(int fd, uint32_t mask, void *data) static int init_egl(struct drm_compositor *ec, struct udev_device *device) { - EGLint major, minor; + EGLint major, minor, n; const char *extensions, *filename; int fd; static const EGLint context_attribs[] = { @@ -321,6 +326,17 @@ init_egl(struct drm_compositor *ec, struct udev_device *device) EGL_NONE }; + static const EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 1, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + filename = udev_device_get_devnode(device); fd = open(filename, O_RDWR | O_CLOEXEC); if (fd < 0) { @@ -354,7 +370,13 @@ init_egl(struct drm_compositor *ec, struct udev_device *device) return -1; } - ec->base.context = eglCreateContext(ec->base.display, NULL, + if (!eglChooseConfig(ec->base.display, config_attribs, + &ec->base.config, 1, &n) || n != 1) { + fprintf(stderr, "failed to choose config: %d\n", n); + return -1; + } + + ec->base.context = eglCreateContext(ec->base.display, ec->base.config, EGL_NO_CONTEXT, context_attribs); if (ec->base.context == NULL) { fprintf(stderr, "failed to create context\n"); @@ -454,8 +476,6 @@ create_output_for_connector(struct drm_compositor *ec, drmModeFreeEncoder(encoder); return -1; } - output->fb_id[0] = -1; - output->fb_id[1] = -1; memset(output, 0, sizeof *output); output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel); @@ -489,49 +509,52 @@ create_output_for_connector(struct drm_compositor *ec, drm_mode->base.flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; - glGenRenderbuffers(2, output->rbo); - for (i = 0; i < 2; i++) { - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]); - - output->bo[i] = - gbm_bo_create(ec->gbm, - output->base.current->width, - output->base.current->height, - GBM_BO_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT | - GBM_BO_USE_RENDERING); - if (!output->bo[i]) - goto err_bufs; - - output->image[i] = ec->base.create_image(ec->base.display, - NULL, - EGL_NATIVE_PIXMAP_KHR, - output->bo[i], NULL); - if (!output->image[i]) - goto err_bufs; - - ec->base.image_target_renderbuffer_storage(GL_RENDERBUFFER, - output->image[i]); - stride = gbm_bo_get_pitch(output->bo[i]); - handle = gbm_bo_get_handle(output->bo[i]).u32; - - ret = drmModeAddFB(ec->drm.fd, + output->surface = + gbm_surface_create(ec->gbm, output->base.current->width, output->base.current->height, - 24, 32, stride, handle, &output->fb_id[i]); - if (ret) { - fprintf(stderr, "failed to add fb %d: %m\n", i); - goto err_bufs; - } + GBM_BO_FORMAT_XRGB8888); + if (!output->surface) { + fprintf(stderr, "failed to create gbm surface\n"); + return -1; + } + + output->egl_surface = + eglCreateWindowSurface(ec->base.display, ec->base.config, + output->surface, NULL); + + if (output->egl_surface == EGL_NO_SURFACE) { + fprintf(stderr, "failed to create egl surface\n"); + goto err_surface; + } + + if (!eglMakeCurrent(ec->base.display, output->egl_surface, + output->egl_surface, ec->base.context)) { + fprintf(stderr, "failed to make surface current\n"); + goto err_egl_surface; + } + + output->current_bo = gbm_surface_get_bo(output->surface); + + if (!output->current_bo) { + fprintf(stderr, "failed to get surface bo\n"); + goto err_egl_surface; + } + + stride = gbm_bo_get_pitch(output->current_bo); + handle = gbm_bo_get_handle(output->current_bo).u32; + + ret = drmModeAddFB(ec->drm.fd, + output->base.current->width, + output->base.current->height, + 24, 32, stride, handle, &output->current_fb_id); + if (ret) { + fprintf(stderr, "failed to add fb %d: %m\n", i); + goto err_bo; } - output->current = 0; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); ret = drmModeSetCrtc(ec->drm.fd, output->crtc_id, - output->fb_id[output->current ^ 1], 0, 0, + output->current_fb_id, 0, 0, &output->connector_id, 1, &drm_mode->mode_info); if (ret) { @@ -540,11 +563,12 @@ create_output_for_connector(struct drm_compositor *ec, } wlsc_output_init(&output->base, &ec->base, x, y, - connector->mmWidth, connector->mmHeight, 0); + connector->mmWidth, connector->mmHeight, + WL_OUTPUT_FLIPPED); wl_list_insert(ec->base.output_list.prev, &output->base.link); - output->pending_fs_surf_fb_id = 0; + output->next_fb_id = 0; output->base.prepare_render = drm_output_prepare_render; output->base.present = drm_output_present; output->base.prepare_scanout_surface = @@ -555,22 +579,13 @@ create_output_for_connector(struct drm_compositor *ec, return 0; err_fb: - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - 0); -err_bufs: - for (i = 0; i < 2; i++) { - if (output->fb_id[i] != -1) - drmModeRmFB(ec->drm.fd, output->fb_id[i]); - if (output->image[i]) - ec->base.destroy_image(ec->base.display, - output->image[i]); - if (output->bo[i]) - gbm_bo_destroy(output->bo[i]); - } - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glDeleteRenderbuffers(2, output->rbo); + drmModeRmFB(ec->drm.fd, output->current_fb_id); +err_bo: + gbm_surface_release_bo(output->surface, output->current_bo); +err_egl_surface: + eglDestroySurface(ec->base.display, output->egl_surface); +err_surface: + gbm_surface_destroy(output->surface); err_free: wl_list_for_each_safe(drm_mode, next, &output->base.mode_list, base.link) { @@ -865,9 +880,6 @@ drm_compositor_create(struct wl_display *display, ec->base.focus = 1; - glGenFramebuffers(1, &ec->base.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, ec->base.fbo); - /* Can't init base class until we have a current egl context */ if (wlsc_compositor_init(&ec->base, display) < 0) return NULL; -- 1.7.4.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel