[PATCH 5/6] implement set_mode for drm backend

juan.j.zhao at linux.intel.com juan.j.zhao at linux.intel.com
Fri Dec 30 12:21:25 PST 2011


From: Zhiwen Wu <zhiwen.wu at linux.intel.com>

fill in the set_mode interface for fullscreen usage
---
 compositor/compositor-drm.c |  158 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 158 insertions(+), 0 deletions(-)

diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c
index f1047ee..03ed9f0 100644
--- a/compositor/compositor-drm.c
+++ b/compositor/compositor-drm.c
@@ -78,6 +78,20 @@ struct drm_output {
 	uint32_t pending_fs_surf_fb_id;
 };
 
+static struct drm_mode *
+choose_mode (struct drm_output *output, char *mode_name)
+{
+	struct drm_mode *mode, *next;
+	printf ("%s: mode to choose: %s\n", __FUNCTION__, mode_name);
+
+	wl_list_for_each_safe(mode, next,
+			      &output->base.mode_list,base.link) {
+		if (!strcmp (mode->mode_info.name, mode_name))
+			return mode;
+		}
+	return NULL;
+}
+
 static int
 drm_output_prepare_render(struct wlsc_output *output_base)
 {
@@ -258,6 +272,147 @@ out:
 	return ret;
 }
 
+static int
+drm_output_set_mode (struct wlsc_output *output_base, char *mode)
+{
+	struct drm_output *output;
+	struct drm_mode *drm_mode, *next;
+	drmModeEncoder *encoder;
+	int i, ret;
+	unsigned handle, stride;
+	struct drm_compositor *ec;
+
+	ec = (struct drm_compositor *)output_base->compositor;
+	output = (struct drm_output *)output_base;
+	if (output == NULL) {
+		return -1;
+	}
+
+	drm_mode  = (struct drm_mode *)(output->base.current);
+
+	printf ("current mode: %s, w=%d, h=%d, refresh=%u, flags=%u\n",
+			drm_mode->mode_info.name, drm_mode->base.width,
+			drm_mode->base.height, drm_mode->base.refresh,
+			drm_mode->base.flags);
+
+	drm_mode  = choose_mode (output, mode);
+
+	if (!drm_mode) {
+		printf ("%s, invalid mode:%s\n", __FUNCTION__, mode);
+		return -1;
+	}
+
+	printf ("next mode: %s, w=%d, h=%d, refresh=%u, flags=%u\n",
+			drm_mode->mode_info.name, drm_mode->base.width,
+			drm_mode->base.height, drm_mode->base.refresh,
+			drm_mode->base.flags);
+
+
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+				  GL_COLOR_ATTACHMENT0,
+				  GL_RENDERBUFFER, 0);
+
+
+	/* Destroy output buffers */
+	for (i = 0; i < 2; i++) {
+		drmModeRmFB(ec->drm.fd, output->fb_id[i]);
+		ec->base.destroy_image(ec->base.display, output->image[i]);
+		gbm_bo_destroy(output->bo[i]);
+	}
+
+	glBindRenderbuffer(GL_RENDERBUFFER, 0);
+	glDeleteRenderbuffers(2, output->rbo);
+	wlsc_output_destroy(output);
+
+	output->base.current = &drm_mode->base;
+	drm_mode->base.flags =
+		WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+
+	/* create new output buffers */
+	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->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;
+		}
+	}
+
+	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->connector_id, 1, &drm_mode->mode_info);
+
+	if (ret) {
+		fprintf(stderr, "failed to set mode: %m\n");
+		goto err_fb;
+	}
+
+	output->base.x = 0;
+	output->base.y = 0;
+	output->base.mm_width = output->base.current->width;
+	output->base.mm_height = output->base.current->height;
+	wlsc_output_move(&output->base, 0, 0);
+
+	printf ("%s: ret 0\n", __FUNCTION__);
+	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);
+
+	printf ("%s: ret -1\n", __FUNCTION__);
+	return -1;
+}
+
+
 static void
 drm_output_destroy(struct wlsc_output *output_base)
 {
@@ -489,6 +644,8 @@ create_output_for_connector(struct drm_compositor *ec,
 	drm_mode = container_of(output->base.mode_list.next,
 				struct drm_mode, base.link);
 	output->base.current = &drm_mode->base;
+	output->base.saved_mode = NULL;
+	output->base.fs_dirty = NULL;
 	drm_mode->base.flags =
 		WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
 
@@ -553,6 +710,7 @@ create_output_for_connector(struct drm_compositor *ec,
 	output->base.prepare_scanout_surface =
 		drm_output_prepare_scanout_surface;
 	output->base.set_hardware_cursor = drm_output_set_cursor;
+	output->base.set_mode = drm_output_set_mode;
 	output->base.destroy = drm_output_destroy;
 
 	return 0;
-- 
1.7.2.2



More information about the wayland-devel mailing list