[PATCH] compositor-drm: render to a gbm_surface instead of renderbuffers

Ander Conselvan de Oliveira conselvan2 at gmail.com
Wed Dec 14 02:00:09 PST 2011


From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at 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



More information about the wayland-devel mailing list