[meta-freescale] [meta-fsl-arm][PATCH 3/6] weston: Add clone mode support for multi display

Tom Hochstein tom.hochstein at nxp.com
Fri Oct 7 15:36:56 PDT 2016


Support showing the same contents on multiple displays.
Use the following command to enable multi-display:
    openvt -v -- weston-launch -- --idle-time=0 --use-g2d=1 --device=/dev/fb0,/dev/fb4 --clone-mode --log=/var/log/weston.log

Signed-off-by: Tom Hochstein <tom.hochstein at nxp.com>
---
 ...ld-Add-clone-mode-support-for-multi-displ.patch | 421 +++++++++++++++++++++
 recipes-graphics/wayland/weston_%.bbappend         |   1 +
 2 files changed, 422 insertions(+)
 create mode 100644 recipes-graphics/wayland/weston/0012-MGS-1783-xwld-Add-clone-mode-support-for-multi-displ.patch

diff --git a/recipes-graphics/wayland/weston/0012-MGS-1783-xwld-Add-clone-mode-support-for-multi-displ.patch b/recipes-graphics/wayland/weston/0012-MGS-1783-xwld-Add-clone-mode-support-for-multi-displ.patch
new file mode 100644
index 0000000..10bae4d
--- /dev/null
+++ b/recipes-graphics/wayland/weston/0012-MGS-1783-xwld-Add-clone-mode-support-for-multi-displ.patch
@@ -0,0 +1,421 @@
+From f2025a7e8c178b8c52c2ca553459a7fea6caf5c8 Mon Sep 17 00:00:00 2001
+From: "yong.gan" <yong.gan at nxp.com>
+Date: Tue, 17 May 2016 09:10:50 +0800
+Subject: [PATCH 1/2] MGS-1783: xwld: Add clone mode support for multi display
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Support showing the same contents on multiple displays.
+Use the following command to enable multi-display:
+    openvt -v -- weston-launch -- --idle-time=0 --use-g2d=1 --device=/dev/fb0,/dev/fb4 --clone-mode --log=/var/log/weston.log
+
+Upstream-Status: Inappropriate [i.MX specific]
+Date: May 16, 2016
+Signed-off-by: Yong Gan <yong.gan at nxp.com>
+---
+ src/compositor-fbdev.c |  33 +++++++---
+ src/g2d-renderer.c     | 171 ++++++++++++++++++++++++++++++++++++++++---------
+ src/g2d-renderer.h     |   4 +-
+ 3 files changed, 167 insertions(+), 41 deletions(-)
+
+Index: weston-1.11.0/src/compositor-fbdev.c
+===================================================================
+--- weston-1.11.0.orig/src/compositor-fbdev.c	2016-10-06 13:17:41.738142236 -0500
++++ weston-1.11.0/src/compositor-fbdev.c	2016-10-06 13:28:22.000000000 -0500
+@@ -61,6 +61,8 @@
+ 	struct udev_input input;
+ 	int use_pixman;
+ 	int use_g2d;
++	int clone_mode;
++	char *clone_device;
+ 	uint32_t output_transform;
+ 	struct wl_listener session_listener;
+ #ifdef ENABLE_EGL
+@@ -525,12 +527,15 @@
+ 		if (pixman_renderer_output_create(&output->base) < 0)
+ 			goto out_hw_surface;
+ 	} else if(backend->use_g2d) {
++		const char *g2d_device = device;
++		if (backend->clone_mode)
++			g2d_device = backend->clone_device;
++
+ 		if (g2d_renderer->output_create(&output->base,
+-					backend->compositor->wl_display, device) < 0) {
++					backend->compositor->wl_display, g2d_device) < 0) {
+ 			weston_log("g2d_renderer_output_create failed.\n");
+ 			goto out_hw_surface;
+ 		}
+-
+ 	} else {
+ #ifdef ENABLE_EGL
+ 		setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
+@@ -803,6 +808,8 @@
+ 	backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
+ 	backend->use_pixman = !(param->use_gl || param->use_g2d);
+ 	backend->use_g2d = param->use_g2d;
++	backend->clone_mode = param->clone_mode;
++	backend->clone_device = param->device;
+ 	backend->output_transform = param->output_transform;
+ 
+ 	weston_setup_vt_switch_bindings(compositor);
+@@ -844,16 +851,21 @@
+ 		displays[dispCount][k] = '\0';
+ 		dispCount++;
+ 
+-		for(i=0; i<dispCount; i++)
+-		{
+-			if (fbdev_output_create(backend, x, y, displays[i]) < 0)
++		if(backend->clone_mode){
++			if (fbdev_output_create(backend, x, y, displays[0]) < 0)
+ 				goto out_launcher;
+-			x += container_of(backend->compositor->output_list.prev,
+-								  struct weston_output,
+-								  link)->width;
++		}
++		else{
++			for(i= 0; i < dispCount; i++){
++				if (fbdev_output_create(backend, x, y, displays[i]) < 0)
++					goto out_launcher;
++				x += container_of(backend->compositor->output_list.prev,
++						struct weston_output,
++						link)->width;
++			}
+ 		}
+ 	}
+-	 else {
++	else {
+ #ifdef ENABLE_EGL
+ 		gl_renderer = weston_load_module("gl-renderer.so",
+ 						 "gl_renderer_interface");
+Index: weston-1.11.0/src/g2d-renderer.c
+===================================================================
+--- weston-1.11.0.orig/src/g2d-renderer.c	2016-10-06 13:17:41.738142236 -0500
++++ weston-1.11.0/src/g2d-renderer.c	2016-10-06 13:17:41.734142216 -0500
+@@ -37,15 +37,16 @@
+ #include <sys/ioctl.h>
+ #include <fcntl.h>
+ #include <unistd.h>
++#include <g2dExt.h>
++#include <HAL/gc_hal_eglplatform.h>
+ 
+ #include "compositor.h"
+ #include "g2d-renderer.h"
+ #include "vertex-clipping.h"
+ #include "shared/helpers.h"
+-#include "HAL/gc_hal_eglplatform.h"
+-#include "g2dExt.h"
+ 
+ #define BUFFER_DAMAGE_COUNT 2
++extern struct wl_global* gcoOS_WaylandCreateVivGlobal(struct wl_display* display);
+ 
+ typedef struct _g2dRECT
+ {
+@@ -63,6 +64,7 @@
+ 	size_t buffer_length; /* length of frame buffer memory in bytes */
+ 	size_t physical;
+ 	enum g2d_format pixel_format; /* frame buffer pixel format */
++	int fb_fd;
+ };
+ 
+ struct g2d_output_state {
+@@ -74,10 +76,12 @@
+ 	struct g2d_surfaceEx offscreenSurface;
+ 	struct g2d_buf *offscreen_buf;
+ 	struct fb_screeninfo fb_info;
++	struct fb_screeninfo *mirror_fb_info;
++	struct g2d_surfaceEx *mirrorSurf;
+ 	int directBlit;
++	int clone_display_num;
+ 	int width;
+ 	int height;
+-	int fb_fd;
+ };
+ 
+ struct g2d_surface_state {
+@@ -366,7 +370,7 @@
+ 	struct g2d_output_state *go = get_output_state(output);
+ 	go->fb_info.varinfo.yoffset  = go->activebuffer * go->fb_info.y_resolution;
+ 
+-	if(ioctl(go->fb_fd, FBIOPAN_DISPLAY, &(go->fb_info.varinfo)) < 0)
++	if(ioctl(go->fb_info.fb_fd, FBIOPAN_DISPLAY, &(go->fb_info.varinfo)) < 0)
+ 	{
+ 		weston_log("FBIOPAN_DISPLAY Failed\n");
+ 	}
+@@ -388,6 +392,28 @@
+ 			&go->renderSurf[go->activebuffer], &srcRect, &dstrect);
+ 	}
+ 
++	if(go->clone_display_num)
++	{
++		int i = 0;
++		for(i = 0; i < go->clone_display_num; i++)
++		{
++			g2dRECT srcRect  = {0, 0, go->renderSurf[go->activebuffer].base.width, go->renderSurf[go->activebuffer].base.height};
++			g2dRECT dstrect  = {0, 0, go->mirrorSurf[i].base.width, go->mirrorSurf[i].base.height};
++			g2dRECT clipRect = srcRect;
++			g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
++			if(go->directBlit || go->nNumBuffers > 1)
++			{
++				g2d_blitSurface(gr->handle, &go->renderSurf[go->activebuffer],
++				&go->mirrorSurf[i], &srcRect, &dstrect);
++			}
++			else
++			{
++				g2d_blitSurface(gr->handle, &go->offscreenSurface,
++					&go->mirrorSurf[i], &srcRect, &dstrect);
++			}
++		}
++	}
++
+ 	g2d_finish(gr->handle);
+ 
+ 	if(go->nNumBuffers > 1)
+@@ -940,10 +966,10 @@
+ 		go->offscreen_buf = NULL;
+ 	}
+ 
+-	if(go->fb_fd)
++	if(go->fb_info.fb_fd)
+ 	{
+-		close(go->fb_fd);
+-		go->fb_fd = 0;
++		close(go->fb_info.fb_fd);
++		go->fb_info.fb_fd = 0;
+ 	}
+ 
+ 	if(go->renderSurf)
+@@ -951,6 +977,24 @@
+ 		free(go->renderSurf);
+ 		go->renderSurf = NULL;
+ 	}
++	for (i = 0; i < go->clone_display_num; i++)
++	{
++		if(go->mirror_fb_info[i].fb_fd)
++		{
++			close(go->mirror_fb_info[i].fb_fd);
++			go->mirror_fb_info[i].fb_fd = 0;
++		}
++	}
++	if(go->mirrorSurf)
++	{
++		free(go->mirrorSurf);
++		go->mirrorSurf = NULL;
++	}
++	if(go->mirror_fb_info)
++	{
++		free(go->mirror_fb_info);
++		go->mirror_fb_info = NULL;
++	}
+ 
+ 	free(go);
+ }
+@@ -1085,39 +1129,27 @@
+                         struct fb_screeninfo *screen_info)
+ {
+ 	/* Open the frame buffer device. */
+-	output->fb_fd = open(fb_dev, O_RDWR | O_CLOEXEC);
+-	if (output->fb_fd < 0) {
++	screen_info->fb_fd = open(fb_dev, O_RDWR | O_CLOEXEC);
++	if (screen_info->fb_fd < 0) {
+ 		weston_log("Failed to open frame buffer device%s \n", fb_dev);
+ 		return -1;
+ 	}
+ 
+ 	/* Grab the screen info. */
+-	if (fb_query_screen_info(output, output->fb_fd, screen_info) < 0) {
++	if (fb_query_screen_info(output, screen_info->fb_fd, screen_info) < 0) {
+ 		weston_log("Failed to get frame buffer info \n");
+ 
+-		close(output->fb_fd);
++		close(screen_info->fb_fd);
+ 		return -1;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static int
+-g2d_renderer_output_create(struct weston_output *output, struct wl_display *wl_display, const char *device)
+-
+- {
+-	struct g2d_renderer *gr = get_renderer(output->compositor);
+-	struct g2d_output_state *go;
+-	int i = 0;
+-	int offset = 0;
++static void
++getBufferNumber(struct g2d_output_state *go)
++{
+ 	char *p = NULL;
+-	go = zalloc(sizeof *go);
+-	if (go == NULL)
+-		return -1;
+-
+-	output->renderer_state = go;
+-	gr->viv_global = gcoOS_WaylandCreateVivGlobal(wl_display);
+-
+ 	p = getenv("FB_MULTI_BUFFER");
+ 	if (p == gcvNULL)
+ 	{
+@@ -1126,7 +1158,7 @@
+ 	else
+ 	{
+ 		go->nNumBuffers = atoi(p);
+-		if (go->nNumBuffers < 1)
++		if (go->nNumBuffers < 2)
+ 		{
+ 			go->nNumBuffers  = 1;
+ 		}
+@@ -1137,13 +1169,19 @@
+ 		}
+ 	}
+ 	weston_log("FB_MULTI_BUFFER = %d\n", go->nNumBuffers);
++}
+ 
++static int
++g2d_renderer_surface_create(struct g2d_output_state *go, struct g2d_renderer *gr, const char *device)
++{
++	int i = 0;
++	int offset = 0;
++	weston_log("Opend device=%s\n", device);
+ 	if(fb_frame_buffer_open(go, device, &go->fb_info) < 0)
+ 	{
+ 		weston_log("Open frame buffer failed.\n");
+ 		return -1;
+ 	}
+-
+ 	go->renderSurf = zalloc(sizeof(struct g2d_surfaceEx) * go->nNumBuffers);
+ 	offset = go->fb_info.buffer_length/go->nNumBuffers;
+ 	for(i = 0; i < go->nNumBuffers; i++)
+@@ -1161,9 +1199,84 @@
+ 		go->offscreenSurface.base.planes[0] = go->offscreen_buf->buf_paddr;
+ 		g2d_clear(gr->handle, &go->offscreenSurface.base);
+ 	}
++	return 0;
++}
++
++static int
++g2d_renderer_output_create(struct weston_output *output, struct wl_display *wl_display, const char *device)
+ 
++ {
++	struct g2d_renderer *gr = get_renderer(output->compositor);
++	struct g2d_output_state *go;
++	int i;
++	int clone_display_num = 0;
++	int count = 0;
++	int k=0, dispCount = 0;
++	char displays[5][32];
++	weston_log("g2d_renderer_output_create device=%s\n", device);
++	count = strlen(device);
++
++	if(count > 0)
++	{
++		for(i= 0; i < count; i++)
++		{
++			if(device[i] == ',')
++			{
++				displays[dispCount][k] = '\0';
++				dispCount++;
++				k = 0;
++				continue;
++			}
++			else if(device[i] != ' ')
++			{
++				displays[dispCount][k++] = device[i];
++			}
++		}
++		displays[dispCount][k] = '\0';
++		clone_display_num = dispCount++;
++		weston_log("clone_display_num = %d\n", clone_display_num);
++	}
++	else
++	{
++		weston_log("Invalid device name\n");
++		return -1;
++	}
++
++	go = zalloc(sizeof *go);
++	if (go == NULL)
++		return -1;
++	go->clone_display_num  = clone_display_num;
++	output->renderer_state = go;
++	gr->viv_global = gcoOS_WaylandCreateVivGlobal(wl_display);
++	getBufferNumber(go);
++
++	if(g2d_renderer_surface_create(go, gr, displays[0]) < 0)
++	{
++		weston_log("Create Render surface failed.\n");
++		return -1;
++	}
++
++	if(go->clone_display_num)
++	{
++		go->mirrorSurf = zalloc(sizeof(struct g2d_surfaceEx) * clone_display_num);
++		go->mirror_fb_info = zalloc(sizeof(struct fb_screeninfo) * clone_display_num);
++		if(go->mirrorSurf == NULL || go->mirror_fb_info == NULL)
++			return -1;
++
++		for(i = 0; i < clone_display_num; i++)
++		{
++			if(fb_frame_buffer_open(go, displays[i + 1], &go->mirror_fb_info[i]) < 0)
++			{
++				weston_log("Open frame buffer failed.\n");
++				return -1;
++			}
++			get_G2dSurface_from_screeninfo(&go->mirror_fb_info[i], &go->mirrorSurf[i]);
++			go->mirrorSurf[i].base.planes[0] = go->mirror_fb_info[i].physical;
++			g2d_clear(gr->handle, &go->mirrorSurf[i].base);
++		}
++	}
+ 	g2d_finish(gr->handle);
+-	for (i = 0; i < 2; i++)
++	for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
+ 		pixman_region32_init(&go->buffer_damage[i]);
+     return 0;
+  }
+Index: weston-1.11.0/src/g2d-renderer.h
+===================================================================
+--- weston-1.11.0.orig/src/g2d-renderer.h	2016-10-06 13:17:41.738142236 -0500
++++ weston-1.11.0/src/g2d-renderer.h	2016-10-06 13:17:41.734142216 -0500
+@@ -27,13 +27,11 @@
+ #define __g2d_renderer_h_
+ 
+ #include  "compositor.h"
++
+ #ifdef ENABLE_EGL
+ #include <EGL/egl.h>
+-#else
+-#include <HAL/gc_hal_eglplatform.h>
+ #endif
+ 
+-
+ struct g2d_renderer_interface {
+ 
+ 	int (*create)(struct weston_compositor *ec);
+Index: weston-1.11.0/src/main.c
+===================================================================
+--- weston-1.11.0.orig/src/main.c	2016-10-06 13:39:13.000000000 -0500
++++ weston-1.11.0/src/main.c	2016-10-06 13:39:39.000000000 -0500
+@@ -287,11 +287,12 @@
+ 		"  --device=DEVICE\tThe framebuffer device to use\n"
+ #if defined ENABLE_EGL
+ 		"  --no-use-gl\t\tDo not use the GL renderer\n"
+-		"  --use-g2d\t\tUse the G2D renderer\n\n");
++		"  --use-g2d\t\tUse the G2D renderer\n"
+ #else
+ 		"  --use-gl\t\tUse the GL renderer\n"
+-		"  --no-use-g2d\t\tDo not use the G2D renderer\n\n");
++		"  --no-use-g2d\t\tDo not use the G2D renderer\n"
+ #endif
++		"  --clone-mode\t\tClone display to multiple devices\n\n");
+ #endif
+ 
+ #if defined(BUILD_HEADLESS_COMPOSITOR)
+@@ -888,6 +889,7 @@
+ 		{ WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
+ 		{ WESTON_OPTION_BOOLEAN, "no-use-g2d", 0, &no_use_g2d },
+ #endif
++		{ WESTON_OPTION_BOOLEAN, "clone-mode", 0, &config.clone_mode },
+ 	};
+ 
+ 	parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
diff --git a/recipes-graphics/wayland/weston_%.bbappend b/recipes-graphics/wayland/weston_%.bbappend
index 815936c..d0ccb01 100644
--- a/recipes-graphics/wayland/weston_%.bbappend
+++ b/recipes-graphics/wayland/weston_%.bbappend
@@ -10,6 +10,7 @@ SRC_URI_append_imxgpu2d = " \
     file://0009-MGS-1284-xwld-Re-implement-weston-2d-renderer-with-p.patch \
     file://0010-MGS-1284-1-xwld-Re-implement-weston-2d-renderer-with.patch \
     file://0011-MGS-1724-xwld-G2D-compositor-build-failed-in-slevk-b.patch \
+    file://0012-MGS-1783-xwld-Add-clone-mode-support-for-multi-displ.patch \
 "
 
 PACKAGECONFIG_IMX_TO_APPEND = ""
-- 
1.9.1



More information about the meta-freescale mailing list