weston: all patch add merge weston [1/1]

PD#SWPL-169736

Problem:
all patch merge to weston

Solution:
all patch merge to weston

Verify:
ah212

Change-Id: I15b12aa89264c6b129d7bc64f3fc44b8a541286d
Signed-off-by: leng.fang <leng.fang@amlogic.com>
diff --git a/aml-weston/aml-backend.c b/aml-weston/aml-backend.c
new file mode 100644
index 0000000..21de57a
--- /dev/null
+++ b/aml-weston/aml-backend.c
@@ -0,0 +1,1066 @@
+/*
+ * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+#include "config.h"
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <linux/vt.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <time.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <libudev.h>
+
+#include <libweston/libweston.h>
+#include <libweston/backend-drm.h>
+#include <libweston/weston-log.h>
+#include "drm-internal.h"
+#include "shared/helpers.h"
+#include "shared/timespec-util.h"
+#include "shared/string-helpers.h"
+#include "shared/weston-drm-fourcc.h"
+#include "pixman-renderer.h"
+#include "pixel-formats.h"
+#include "libbacklight.h"
+#include "libinput-seat.h"
+#include "launcher-util.h"
+#include "vaapi-recorder.h"
+
+#include "aml-backend.h"
+
+#ifdef ENABLE_DRM_HELP
+static const char *const aspect_ratio_as_string[] = {
+		[WESTON_MODE_PIC_AR_NONE] = "",
+		[WESTON_MODE_PIC_AR_4_3] = " 4:3",
+		[WESTON_MODE_PIC_AR_16_9] = " 16:9",
+		[WESTON_MODE_PIC_AR_64_27] = " 64:27",
+		[WESTON_MODE_PIC_AR_256_135] = " 256:135",
+};
+#endif
+
+#ifdef BUILD_AML_TV
+#include <linux/amlogic/tvin.h>
+
+#define FRAME_RATE_DURATION_2397                4004
+#define FRAME_RATE_DURATION_2398                4003
+#define FRAME_RATE_DURATION_24                  4000
+#define FRAME_RATE_DURATION_25                  3840
+#define FRAME_RATE_DURATION_2997                3203
+#define FRAME_RATE_DURATION_30                  3200
+#define FRAME_RATE_DURATION_50                  1920
+#define FRAME_RATE_DURATION_5994                1601
+#define FRAME_RATE_DURATION_5992                1602
+#define FRAME_RATE_DURATION_60                  1600
+#define FRAME_RATE_HDMI_OFF                     "0"
+#define FRAME_RATE_HDMI_CLK_PULLDOWN            "1"
+#define FRAME_RATE_HDMI_SWITCH_FORCE            "2"
+
+#define VDIN_DEV_PATH "/dev/vdin0"
+
+enum REFRESH_RATE {
+	FPS_24 = 24,
+	FPS_47 = 47,
+	FPS_48 = 48,
+	FPS_50 = 50,
+	FPS_59 = 59,
+	FPS_60 = 60,
+	FPS_100 = 100,
+	FPS_119 = 119,
+	FPS_120 = 120,
+};
+#endif
+
+bool drm_change_to_dummy_mode( struct weston_compositor *compositor )
+{
+	bool ret = false;
+	bool dummy_conn_found = false;
+	struct weston_head *base;
+	struct drm_head *head;
+	drmModeConnector *conn = NULL;
+	int i;
+	int dummy_index = -1;
+	int rc = -1;
+	int rc1 = -1;
+	int rc2 = -1;
+	int rc3 = -1;
+	struct weston_output* output = NULL;
+	struct drm_output* drm_output = NULL;
+	uint32_t flags = 0;
+
+	wl_list_for_each(base,
+			 &compositor->head_list, compositor_link) {
+		head = to_drm_head(base);
+		if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) {
+			conn = head->connector.conn;
+			dummy_conn_found = true;
+			weston_log("\n dummy connector exist\n");
+			break;
+		}
+	}
+	if (!dummy_conn_found) {
+		wl_list_for_each(base,
+			 &compositor->head_list, compositor_link) {
+			head = to_drm_head(base);
+			if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+				conn = head->connector.conn;
+				weston_log("\n dummy connector exist\n");
+				break;
+			}
+		}
+	}
+	if (conn) {
+		for (i = 0; i < conn->count_modes; i ++) {
+			if ( !strcmp(conn->modes[i].name, "dummy_l"))
+			{
+				dummy_index = i;
+				weston_log("\n dummy_l mode exist :%d\n", dummy_index);
+				break;
+			}
+		}
+	}
+	if (dummy_index >= 0)
+	{
+		uint32_t blobId = 0;
+		output = weston_compositor_find_output_by_name(compositor, "HDMI-A-1");
+		drm_output = to_drm_output(output);
+		struct drm_property_info *info = &head->connector.props[WDRM_CONNECTOR_CRTC_ID];
+		drmModeAtomicReq *req = drmModeAtomicAlloc();
+		rc = drmModeAtomicAddProperty(req, head->connector.connector_id,
+					info->prop_id, drm_output->crtc->crtc_id);
+		weston_log("\n %s %d (%d %d %d)\n", __FUNCTION__, __LINE__,
+			head->connector.connector_id, info->prop_id, drm_output->crtc->crtc_id);
+		rc = drmModeCreatePropertyBlob( head->backend->drm.fd, &conn->modes[dummy_index],
+										sizeof(drmModeModeInfo), &blobId );
+		if ( rc == 0 )
+		{
+			if (drm_output) {
+				info = &drm_output->crtc->props_crtc[WDRM_CRTC_MODE_ID];
+				rc1 = drmModeAtomicAddProperty(req, drm_output->crtc->crtc_id,
+										info->prop_id, blobId);
+				info = &drm_output->crtc->props_crtc[WDRM_CRTC_ACTIVE];
+				rc2 = drmModeAtomicAddProperty(req, drm_output->crtc->crtc_id,
+										info->prop_id, 1);
+			}
+			weston_log("\n %s %d (%d %d %d)\n", __FUNCTION__, __LINE__, rc, rc1, rc2);
+			if (rc1 >=0 && rc2 >=0) {
+				flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
+				rc3 = drmModeAtomicCommit( head->backend->drm.fd, req, flags, 0 );
+				weston_log("\n %s %d commit :%d errno:%d\n", __FUNCTION__, __LINE__, rc3, errno);
+				ret = (rc3 == 0) ? true : false;
+			}
+		}
+	}
+	return ret;
+}
+
+int drm_get_frame_time(struct weston_output *output_base, uint64_t* frametime,
+		uint64_t* refresh_interval)
+{
+	int ret = -1;
+	uint64_t refresh_nsec = 0;
+	struct drm_output *output = to_drm_output(output_base);
+	struct drm_backend *backend =
+		to_drm_backend(output_base->compositor);
+	if (!output_base || !frametime || !refresh_interval) {
+		return ret;
+		weston_log("\n invalid input %s\n", __func__);
+	}
+	drmVBlank vbl = {
+		.request.type = DRM_VBLANK_RELATIVE,
+		.request.sequence = 0,
+		.request.signal = 0,
+	};
+	ret = drmWaitVBlank(backend->drm.fd, &vbl);
+	if ((ret == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
+		*frametime = vbl.reply.tval_sec * 1000000LL+vbl.reply.tval_usec;
+		refresh_nsec =
+			millihz_to_nsec(output->base.current_mode->refresh);
+		*refresh_interval = refresh_nsec/1000;
+		ret = 0;
+	}
+	return ret;
+}
+
+int drm_close_video_plane(struct weston_compositor *ec, struct weston_plane* plane)
+{
+	int rc = -1;
+	struct drm_backend* b = to_drm_backend(ec);
+	struct drm_plane* plane_drm = drm_get_weston_plane(b, to_drm_plane(plane));
+	uint32_t crtc_id = 0;
+	weston_log("\n %s %d plane:%p crtc:%p\n", __FUNCTION__, __LINE__, plane_drm, plane_drm->crtc );
+	if (plane_drm && plane_drm->crtc && plane_drm->state_cur) {
+		crtc_id = plane_drm->crtc->crtc_id;
+		rc= drmModeSetPlane( b->drm.fd,
+					plane_drm->plane_id,
+					crtc_id,
+					0, // fbid
+					0, // flags
+					0, // plane x
+					0, // plane y
+					plane_drm->state_cur->dest_w,
+					plane_drm->state_cur->dest_h,
+					0, // fb rect x
+					0, // fb rect y
+					plane_drm->state_cur->dest_w<<16,
+					plane_drm->state_cur->dest_h<<16 );
+
+		weston_log("\n %s %d crtc id:%d dest(%d %d) rc:%d\n",__FUNCTION__, __LINE__,
+			crtc_id, plane_drm->state_cur->dest_w, plane_drm->state_cur->dest_h, rc );
+	}
+	return rc;
+}
+
+void drm_output_render_aml_config(struct drm_output *output, struct drm_plane_state *scanout_state)
+{
+	if (output && scanout_state) {
+#ifdef ENABLE_DRM_HELP
+		help_get_scanout_viewport(&scanout_state->dest_x, &scanout_state->dest_y, &scanout_state->dest_w, &scanout_state->dest_h);
+#endif
+
+#ifdef MESON_DRM_FIX_UI_SIZE
+		// for scale to full screen
+		//// TODO: Need consider different aspect_ration
+		scanout_state->dest_w = output->display_size.width;
+		scanout_state->dest_h = output->display_size.height;
+#endif
+	}
+}
+
+void drm_switch_mode_aml_config_ui_size(struct drm_output* output, struct weston_output *output_base,
+			struct drm_mode *drm_mode)
+{
+	if (output && output_base && drm_mode) {
+#ifdef MESON_DRM_FIX_UI_SIZE
+		struct drm_backend *b = to_drm_backend(output_base->compositor);
+
+		//restore the orgin size of current_mode
+		if (output->base.current_mode && output->current_mode_need_restore) {
+			output->base.current_mode->width = output->display_size.width;
+			output->base.current_mode->height = output->display_size.height;
+		}
+		//Save the orgin size of next current_mode
+		output->display_size.width = drm_mode->base.width;
+		output->display_size.height = drm_mode->base.height;
+		//Set the fixed ui size to current_mode
+		drm_mode->base.width = b->fixed_ui_size.width;
+		drm_mode->base.height = b->fixed_ui_size.height;
+#endif
+	}
+}
+
+static void drm_help_update_display(struct drm_head *head,
+			struct drm_mode *drm_mode, int width, int height)
+{
+	if (head && head->connector.conn) {
+		if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+			help_update_display_mode_info(&drm_mode->mode_info);
+			help_update_ui_logic_size_info(width, height);
+			weston_log("\n %s %d current connector type is HDMI, current_mode(%d %d)\n",
+				__FUNCTION__, __LINE__, width, height);
+		}
+	}
+}
+
+void drm_switch_mode_aml_config_help(struct drm_output* output, struct weston_output *output_base,
+			struct drm_mode *drm_mode )
+{
+	if (output && output_base && drm_mode) {
+#ifdef ENABLE_DRM_HELP
+		struct drm_head *head = to_drm_head(weston_output_get_first_head(output_base));
+		drm_help_update_display(head, drm_mode,
+			output->base.current_mode->width,
+			output->base.current_mode->height);
+#endif
+	}
+}
+
+void drm_set_mode_update_aml_info(struct drm_head *head,
+		struct drm_output *output, struct drm_mode *current)
+{
+	if (head && output) {
+		struct drm_backend *b = output->backend;
+
+#ifdef ENABLE_DRM_HELP
+		drm_help_update_display(head, current,
+			output->base.current_mode->width,
+			output->base.current_mode->height);
+#endif
+
+#ifdef MESON_DRM_FIX_UI_SIZE
+		//the first current_mode should have no restoration needed
+		assert(!output->current_mode_need_restore);
+		//Save the orgin size of next current_mode
+		output->display_size.width = output->base.current_mode->width;
+		output->display_size.height = output->base.current_mode->height;
+		//Set the fixed ui size to current_mode
+		output->base.current_mode->width = b->fixed_ui_size.width;
+		output->base.current_mode->height = b->fixed_ui_size.height;
+		output->current_mode_need_restore = true;
+#endif
+	}
+}
+
+void drm_enable_aml_output_config(struct drm_output* output,
+			struct weston_output *base, struct drm_backend *b)
+{
+	if (output && base && b) {
+#ifdef MESON_DRM_FIX_UI_SIZE
+		if (output->base.current_mode && output->current_mode_need_restore) {
+			output->base.current_mode->width = b->fixed_ui_size.width;
+			output->base.current_mode->height = b->fixed_ui_size.height;
+			output->current_mode_need_restore = false;
+		}
+#endif
+
+		struct drm_plane *plane;
+		wl_list_for_each(plane, &b->plane_list, link) {
+			if (!drm_plane_is_available(plane, output))
+				continue;
+			if (plane->is_video_plane) {
+				plane->video_plane = output->video_plane_count++;
+				weston_log("drm_output_enable video plane for current output id:%d is_video_plane:%d video plane:%d \n",
+					plane->plane_id, plane->is_video_plane, plane->video_plane);
+			}
+		}
+
+#ifdef ENABLE_DRM_HELP
+		struct drm_head *head = to_drm_head(weston_output_get_first_head(base));
+		if (head && head->connector.conn)
+		{
+			if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			{
+				help_set_switch_mode_function((output_ctx)base, drm_output_switch_mode_helper);
+			}
+		}
+#endif
+	}
+}
+
+void drm_output_disable_aml(struct drm_output *output, struct weston_output *base)
+{
+	weston_log("Disabling output %s (page_flip_pending:%d  atomic_complete_pending:%d output->base.enabled:%d)\n",
+		output->base.name, output->page_flip_pending, output->atomic_complete_pending, output->base.enabled );
+
+#ifdef ENABLE_DRM_HELP
+	struct drm_head *head = to_drm_head(weston_output_get_first_head(base));
+	if (head && head->connector.conn)
+	{
+		if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+		{
+			help_set_switch_mode_function(NULL, NULL);
+		}
+	}
+#endif
+	struct drm_crtc *crtc = output->crtc;
+	if (output->page_flip_pending || output->atomic_complete_pending) {
+		weston_log("\n %s %d output_change:%d\n", __FUNCTION__, __LINE__, crtc->output_change );
+		crtc->output_change = true;
+		crtc->disable_output = output;
+	}
+}
+
+void drm_append_helper_connector(struct drm_head *head)
+{
+#ifdef ENABLE_DRM_HELP
+	if (head && head->connector.conn)
+		if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			help_append_connector(head->connector.conn);
+#endif
+}
+
+void drm_update_helper_connector(struct drm_connector *connector,
+			 drmModeConnector *conn)
+{
+#ifdef ENABLE_DRM_HELP
+	if (connector && connector->conn)
+		if (connector->conn->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			help_update_connector(connector->conn, conn);
+#endif
+}
+
+void drm_delete_helper_connector(struct drm_head *head)
+{
+#ifdef ENABLE_DRM_HELP
+	if (head && head->connector.conn)
+		if (head->connector.conn->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			help_delete_connector(head->connector.conn);
+#endif
+}
+
+void drm_init_aml_output_config(struct weston_compositor *compositor,
+			struct drm_output *output)
+{
+	if (output) {
+#ifdef MESON_DRM_FIX_UI_SIZE
+		output->display_size.width = 0;
+		output->display_size.height = 0;
+		output->current_mode_need_restore = false;
+#endif
+		output->video_plane_count = 0;
+		char* env = getenv("WESTON_USE_GBM_MODIFIERS");
+		weston_log("\n WESTON_USE_GBM_MODIFIERS :%s \n", env);
+		if (env && !atoi(env)) {
+			compositor->use_gbm_modifiers = false;
+		    weston_log("\n WESTON_USE_GBM_MODIFIERS false \n");
+		}
+	}
+}
+
+void drm_config_fixed_UIsize( struct drm_backend *b,
+		struct weston_drm_backend_config *config)
+{
+#ifdef MESON_DRM_FIX_UI_SIZE
+	if (b && config) {
+		if (config->fixed_ui_size.width > 0 && config->fixed_ui_size.height > 0) {
+			b->fixed_ui_size.width = config->fixed_ui_size.width;
+			b->fixed_ui_size.height = config->fixed_ui_size.height;
+		} else {
+			b->fixed_ui_size.width = 1920;
+			b->fixed_ui_size.height = 1080;
+		}
+		weston_log("Fix ui-size to : %dx%d\n", b->fixed_ui_size.width, b->fixed_ui_size.height);
+	}
+#endif
+}
+
+#ifdef BUILD_AML_TV
+int udev_event_frame_rate_hint(struct udev_device *device)
+{
+	const char *val;
+
+	val = udev_device_get_property_value(device, "FRAME_RATE_HINT");
+	if (!val)
+		return -1;
+
+	return atoi(val);
+}
+
+int udev_event_is_vdin_event(struct udev_device *device)
+{
+	const char *dev_type_val;
+	const char *dev_name_val;
+
+	dev_type_val = udev_device_get_property_value(device, "DEVTYPE");
+	dev_name_val = udev_device_get_property_value(device, "DEVNAME");
+
+	if (dev_type_val &&
+		(strstr(dev_type_val, "vdin0event") || strstr(dev_type_val, "vdin1event")))
+		return 1;
+
+	if (dev_name_val &&
+		(strstr(dev_name_val, "vdin0event") || strstr(dev_name_val, "vdin1event")))
+		return 1;
+
+	return 0;
+}
+
+static int drm_get_frame_rate_value(struct drm_backend *b, int vdin_event)
+{
+	struct vdin_event_info v_info;
+	struct tvin_info_s t_info;
+	int frame_rate_value = 0;
+	int ret = 0;
+
+	if (b->vdin_detect_fd < 0)
+		b->vdin_detect_fd = open(VDIN_DEV_PATH, O_RDWR);
+
+	if (b->vdin_detect_fd < 0 || vdin_event <= 0)
+		return 0;
+
+	v_info.event_sts = 0;
+	ret = ioctl(b->vdin_detect_fd, TVIN_IOC_G_EVENT_INFO, &v_info);
+	if (((v_info.event_sts & TVIN_SIG_CHG_STS) != 0) ||
+		((v_info.event_sts & TVIN_SIG_CHG_VS_FRQ) != 0)) {
+		ret = ioctl(b->vdin_detect_fd, TVIN_IOC_G_SIG_INFO, &t_info);
+		if (t_info.status == TVIN_SIG_STATUS_STABLE) {
+			drm_debug(b, "AFR, get input fps: %d\n", t_info.fps);
+			frame_rate_value = t_info.fps;
+			if (frame_rate_value == 48) {
+				frame_rate_value = 24;
+			} else if (frame_rate_value >= 100) {
+				frame_rate_value /= 2;
+			} else if (frame_rate_value < 0) {
+				frame_rate_value = 0;
+			}
+		}
+	}
+	return frame_rate_value;
+}
+
+static bool drm_exit_play_need_reset_mode()
+{
+	const char *env= getenv("WESTON_GL_NEED_RESET_MODE");
+	if (env) {
+		int value= atoi(env);
+		return ( value != 0 );
+	}
+	return false;
+}
+
+static struct drm_mode*
+drm_output_choose_mode_by_name(struct drm_output *output,
+				   const char *name)
+{
+	struct drm_mode *tmp_mode = NULL, *mode;
+
+	if (strlen(name) == 0)
+		return tmp_mode;
+
+	wl_list_for_each(mode, &output->base.mode_list, base.link) {
+		if (!strcmp(mode->mode_info.name, name))
+			tmp_mode = mode;
+	}
+	return tmp_mode;
+}
+
+static void drm_get_match_dur_output_mode(struct weston_output *output_base,
+		char *frameRateMode,
+		struct weston_mode *mode,
+		int rate_hint,
+		int rate_value)
+{
+	struct drm_output *output = to_drm_output(output_base);
+	struct weston_mode *cur_mode = output_base->current_mode;
+	struct drm_mode *drm_mode = NULL;
+	struct drm_mode *cur_drm_mode = NULL;
+	int dur = rate_hint;
+	char resolution[20] = { 0 };
+	char firstMode[32] = { 0 };
+	char secondMode[32] = { 0 };
+
+	cur_mode = cur_mode ? cur_mode : output_base->original_mode;
+	if (!cur_mode) {
+		drm_debug(output->backend, "cur_mode is null\n");
+		return;
+	}
+
+	cur_drm_mode = to_drm_mode(output_base->current_mode);
+	weston_log("\n cur_drm_mode(%s) frameRateMode:%s, rate_hint:%d rate_value:%d",
+		cur_drm_mode->mode_info.name,
+		frameRateMode, rate_hint, rate_value);
+	if (strstr(cur_drm_mode->mode_info.name, "smpte"))
+		return;
+
+	if (!strcmp(frameRateMode, FRAME_RATE_HDMI_CLK_PULLDOWN)) {
+		if ((dur == FRAME_RATE_DURATION_2397) ||
+			(dur == FRAME_RATE_DURATION_2398) ||
+			(dur == FRAME_RATE_DURATION_2997) ||
+			(dur == FRAME_RATE_DURATION_5992) ||
+			(dur == FRAME_RATE_DURATION_5994)) {
+
+			if (strstr(cur_drm_mode->mode_info.name, "24hz") ||
+				strstr(cur_drm_mode->mode_info.name, "30hz") ||
+				strstr(cur_drm_mode->mode_info.name, "60hz")) {
+				return;
+			}
+		}
+	} else if (!strcmp(frameRateMode, FRAME_RATE_HDMI_SWITCH_FORCE)) {
+		char *pos = strstr(cur_drm_mode->mode_info.name, "hz");
+		if (!pos)
+			return;
+		pos -= 2; // filter 24,30,50,60...
+		pos--;
+		if (*pos < '0' || *pos > '9') // filter 120
+			pos++;
+		strncpy(resolution, cur_drm_mode->mode_info.name, (int)(pos - cur_drm_mode->mode_info.name));
+		drm_debug(output->backend, "resolution: %s\n", resolution);
+
+		if (rate_value > 0) {
+			enum REFRESH_RATE timingMode;
+			if (rate_value <= 24) {
+				timingMode = FPS_24;
+			} else if (rate_value <= 25) {
+				timingMode = FPS_50;
+			} else if (rate_value <= 30) {
+				timingMode = FPS_60;
+			} else if (rate_value <= 50) {
+				timingMode = FPS_50;
+			} else if (rate_value <= 60) {
+				timingMode = FPS_60;
+			} else if (rate_value <= 100) {
+				timingMode = FPS_100;
+			} else if (rate_value <= 119) {
+				timingMode = FPS_119;
+			} else {
+				timingMode = FPS_120;
+			}
+			int height = 0;
+			char flag;
+			sscanf(resolution, "%d%c", &height, &flag);
+			switch (height) {
+			case 768:
+			case 1080:
+				break;
+			case 2160:
+				if (timingMode >= 100 && timingMode <= 120) {
+					height = 1080;
+				}
+				if (timingMode >= 47 && timingMode <= 60) {
+					height = 2160;
+				}
+				break;
+			default:
+				return;
+			}
+
+			snprintf(firstMode, sizeof(firstMode), "%d%c%dhz", height, flag,
+					(int)timingMode);
+			drm_debug(output->backend, "AFR set mode: %s\n", firstMode);
+			if (strcmp(firstMode, cur_drm_mode->mode_info.name)) {
+				drm_mode = drm_output_choose_mode_by_name(output, firstMode);
+				if (drm_mode) {
+					*mode = drm_mode->base;
+					drm_debug(output->backend, "mode: %s, %dx%d\n",
+							drm_mode->mode_info.name, mode->width, mode->height);
+				}
+			}
+		} else {
+			switch (dur) {
+			case 0:
+				if (drm_exit_play_need_reset_mode())
+					sprintf(firstMode, "%s%s", resolution, "60hz");
+				break;
+			case FRAME_RATE_DURATION_2397:
+			case FRAME_RATE_DURATION_2398:
+				sprintf(firstMode, "%s%s", resolution, "59hz");
+				sprintf(secondMode, "%s%s", resolution, "60hz");
+				break;
+			case FRAME_RATE_DURATION_24:
+				sprintf(firstMode, "%s%s", resolution, "24hz");
+				sprintf(secondMode, "%s%s", resolution, "60hz");
+				break;
+			case FRAME_RATE_DURATION_2997:
+				sprintf(secondMode, "%s%s", resolution, "59hz");
+				sprintf(secondMode, "%s%s", resolution, "60hz");
+				break;
+			case FRAME_RATE_DURATION_30:
+				sprintf(firstMode, "%s%s", resolution, "30hz");
+				sprintf(secondMode, "%s%s", resolution, "60hz");
+				break;
+			case FRAME_RATE_DURATION_5992:
+			case FRAME_RATE_DURATION_5994:
+				sprintf(firstMode, "%s%s", resolution, "59hz");
+				sprintf(secondMode, "%s%s", resolution, "60hz");
+				break;
+			case FRAME_RATE_DURATION_60:
+				sprintf(firstMode, "%s%s", resolution, "60hz");
+				sprintf(secondMode, "%s%s", resolution, "30hz");
+				break;
+			case FRAME_RATE_DURATION_25:
+				sprintf(firstMode, "%s%s", resolution, "25hz");
+				sprintf(secondMode, "%s%s", resolution, "50hz");
+				break;
+			case FRAME_RATE_DURATION_50:
+				sprintf(firstMode, "%s%s", resolution, "50hz");
+				sprintf(secondMode, "%s%s", resolution, "25hz");
+				break;
+			default:
+				break;
+			}
+			weston_log("\n update mode first(%s) second(%s)", firstMode, secondMode);
+			drm_mode = drm_output_choose_mode_by_name(output, firstMode);
+			if (drm_mode && strcmp(firstMode, cur_drm_mode->mode_info.name)) {
+				*mode = drm_mode->base;
+				weston_log("\n need switch to first mode: %s, %dx%d\n",
+						drm_mode->mode_info.name, mode->width, mode->height);
+				return;
+			}
+
+			drm_mode = drm_output_choose_mode_by_name(output, secondMode);
+			if (drm_mode && strcmp(secondMode, cur_drm_mode->mode_info.name)) {
+				*mode = drm_mode->base;
+				weston_log("\n need switch to second mode: %s, %dx%d\n",
+						drm_mode->mode_info.name, mode->width, mode->height);
+				return;
+			}
+		}
+	}
+}
+
+void drm_backend_afr_update(struct drm_backend *b,
+		int rate_hint,
+		int vdin_event)
+{
+	struct weston_mode mode = { 0 };
+	struct weston_compositor *compositor = b->compositor;
+	struct weston_output *output;
+	int frame_value = 0;
+
+	if (rate_hint == -1 && !vdin_event)
+		return;
+
+	frame_value = drm_get_frame_rate_value(b, vdin_event);
+	if (rate_hint != -1 || frame_value != 0) {
+		wl_list_for_each(output, &compositor->output_list, link) {
+			if (!strstr(output->name, "LVDS"))
+				continue;
+			drm_get_match_dur_output_mode(output,
+					FRAME_RATE_HDMI_SWITCH_FORCE,
+					&mode,
+					rate_hint,
+					frame_value);
+			if (mode.width > 0 && mode.height > 0) {
+				output->switch_mode(output, &mode);
+				weston_output_damage(output);
+			}
+		}
+	}
+}
+
+static int get_frame_rate(int frame_rate_value, int frame_rate_scale)
+{
+	int rate = -1;
+	int frame_rate = frame_rate_value * 100 / frame_rate_scale;
+	switch (frame_rate)
+	{
+		case 2397:
+			rate = FRAME_RATE_DURATION_2397;
+			break;
+		case 2398:
+			rate = FRAME_RATE_DURATION_2398;
+			break;
+		case 2400:
+			rate = FRAME_RATE_DURATION_24;
+			break;
+		case 2500:
+			rate = FRAME_RATE_DURATION_25;
+			break;
+		case 2997:
+			rate = FRAME_RATE_DURATION_2997;
+			break;
+		case 3000:
+			rate = FRAME_RATE_DURATION_30;
+			break;
+		case 5000:
+			rate = FRAME_RATE_DURATION_50;
+			break;
+		case 5994:
+			rate = FRAME_RATE_DURATION_5994;
+			break;
+		case 5992:
+			rate = FRAME_RATE_DURATION_5992;
+			break;
+		case 6000:
+			rate = FRAME_RATE_DURATION_60;
+			break;
+		default:
+			rate = FRAME_RATE_DURATION_60;
+			break;
+	}
+	weston_log("\n get_frame_rate (%d %d)", frame_rate, rate);
+	return rate;
+}
+
+static void drm_backend_update_rate(struct weston_compositor *compositor,
+		int frame_rate_value,
+		int frame_rate_scale)
+{
+	struct weston_mode mode = { 0 };
+	struct weston_output *output;
+	int rate_num = get_frame_rate(frame_rate_value, frame_rate_scale);
+
+
+	wl_list_for_each(output, &compositor->output_list, link) {
+		weston_log("\n output name %s", output->name);
+		if (!strstr(output->name, "LVDS"))
+			continue;
+		drm_get_match_dur_output_mode(output,
+				FRAME_RATE_HDMI_SWITCH_FORCE,
+				&mode,
+				rate_num,
+				-1);
+
+		if (mode.width > 0 && mode.height > 0) {
+			weston_log("\n drm_backend_update_rate  switch mode");
+			if (output->switch_mode)
+				output->switch_mode(output, &mode);
+			weston_output_damage(output);
+		}
+	}
+}
+#endif
+
+#ifdef ENABLE_DRM_HELP
+void weston_print_info(struct weston_compositor* ec, int count)
+{
+	ec->aml_log_nframes = count;
+	ec->aml_log_enable = true;
+}
+
+static void drm_output_refresh_force(struct weston_compositor *compositor)
+{
+	weston_compositor_damage_all(compositor);
+}
+
+int drm_output_switch_mode_helper(output_ctx ctx, drm_helper_mode* mode)
+{
+	struct weston_mode m;
+	int ratio = 0;
+	int ret = 0;
+
+	m.width = mode->width;
+	m.height = mode->height;
+	//mhz:refresh * 1000
+	m.refresh = mode->refresh * 1000;
+	//hack: use weston_mode's flags as drm_mode's flags.
+	m.flags = mode->flags;
+	m.aspect_ratio = 0;
+	weston_log("\n  %s %d, (%d %d %d %d)\n",
+		__FUNCTION__, __LINE__, m.width, m.height, m.refresh, mode->flags);
+	if (mode->width == 720 && mode->height == 480 && mode->refresh == 56)
+	{
+		if (!drm_change_to_dummy_mode(((struct weston_output *)ctx)->compositor)) {
+			weston_log("\n  %s %d, set dummy mode and return \n",
+							__FUNCTION__, __LINE__);
+			ret = -1;
+		}
+		return ret;
+	}
+
+	for (ratio = 0;  ratio >= ARRAY_LENGTH(aspect_ratio_as_string); ratio++) {
+		if (0 == strcmp(mode->aspect_ratio, aspect_ratio_as_string[ratio])) {
+			m.aspect_ratio = ratio;
+			break;
+		}
+	}
+	ret = weston_output_mode_set_native((struct weston_output *)ctx, &m, ((struct weston_output *)ctx)->current_scale);
+	drm_output_refresh_force(((struct weston_output *)ctx)->compositor);
+	return ret;
+}
+
+static void debug_write_fd_to_file(int fd, int buffer_size, int offset, int plane_id, FILE *msg_fp )
+{
+	void *mapPtr = NULL;
+	mapPtr = mmap(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, offset);
+	if ( mapPtr == MAP_FAILED || mapPtr == NULL) {
+		fprintf(msg_fp, " debug_write_fd_to_file ->failed to map buffer: %s\n", strerror(errno));
+	} else {
+		char plane_id_name[16] = {'\0'};
+		sprintf(plane_id_name, "plane_%d", plane_id );
+		weston_debug_write_buffer_to_file(mapPtr, buffer_size, plane_id_name, msg_fp);
+		munmap(mapPtr, buffer_size);
+	}
+}
+
+static int drm_print_output_status(struct weston_compositor *compositor,
+			     void *repaint_data, FILE* fp) {
+	struct drm_pending_state* state = (struct drm_pending_state*)repaint_data;
+	fprintf(fp, "\ndrm_print_output_status: \n");
+	struct drm_output_state *output_state;
+	wl_list_for_each(output_state, &state->output_list, link) {
+		struct drm_output *output = output_state->output;
+		struct drm_crtc *crtc = output->crtc;
+		struct drm_plane_state *plane_state;
+		wl_list_for_each(plane_state, &output_state->plane_list, link) {
+			struct drm_plane *plane = plane_state->plane;
+			fprintf(fp, " \t\t[plane id:%d] fb id:%d\n", plane->plane_id, plane_state->fb ? plane_state->fb->fb_id : 0);
+			fprintf(fp, "  \t\t[plane id:%d] crtc id:%d\n", plane->plane_id, plane_state->fb ? crtc->crtc_id : 0);
+			fprintf(fp, "  \t\t[plane id:%d] crtc id:%d\n", plane->plane_id, plane_state->fb ? crtc->crtc_id : 0);
+			fprintf(fp, "  \t\t[plane id:%d] src_x:%d\n", plane->plane_id, plane_state->src_x);
+			fprintf(fp, "  \t\t[plane id:%d] src_y:%d\n", plane->plane_id, plane_state->src_y);
+			fprintf(fp, "  \t\t[plane id:%d] src_w:%d\n", plane->plane_id, plane_state->src_w);
+			fprintf(fp, "  \t\t[plane id:%d] src_h:%d\n", plane->plane_id, plane_state->src_h);
+			fprintf(fp, "  \t\t[plane id:%d] crtc_x:%d\n", plane->plane_id, plane_state->dest_x);
+			fprintf(fp, "  \t\t[plane id:%d] crtc_y:%d\n", plane->plane_id, plane_state->dest_y);
+			fprintf(fp, "  \t\t[plane id:%d] crtc_w:%d\n", plane->plane_id, plane_state->dest_w);
+			fprintf(fp, "  \t\t[plane id:%d] crtc_h:%d\n", plane->plane_id, plane_state->dest_h);
+			fprintf(fp, "  \t\t[plane id:%d] fb format:%s\n", plane->plane_id, plane_state->fb->format->drm_format_name);
+			if (plane_state->fb) {
+				int rc = -255;
+				int dmabuf_fd = -1;
+				int size = plane_state->fb->height * plane_state->fb->width * 4;
+				rc = drmPrimeHandleToFD(plane_state->fb->fd, plane_state->fb->handles[0], 0, &dmabuf_fd);
+				debug_write_fd_to_file(dmabuf_fd, size, plane_state->fb->offsets[0], plane_state->plane->plane_id,fp);
+				fprintf(fp, "\n drm_print_output_status: start to write fb(none afbc)\n");
+				fprintf(fp, "\n drm_print_output_status: fd:%d size:%d (%d * %d * 4), plane id:%d \n\n\n\n\n\n\n",
+							dmabuf_fd, size, plane_state->fb->height, plane_state->fb->width, plane_state->plane->plane_id);
+
+				close(dmabuf_fd);
+			} else {
+				fprintf(fp, " plane_state->fb not exsit\n");
+			}
+		}
+	}
+	return 0;
+}
+#endif
+
+void drm_add_aml_callback(struct drm_backend *b)
+{
+	b->base.print_output_status = drm_print_output_status;
+	b->base.get_frame_time = drm_get_frame_time;
+	b->base.close_video_plane = drm_close_video_plane;
+#ifdef BUILD_AML_TV
+	b->base.update_frame_rate = drm_backend_update_rate;
+#endif
+}
+
+struct weston_plane *
+drm_get_weston_plane(struct drm_backend *backend, struct drm_plane* drm_plane)
+{
+	struct weston_plane* plane = NULL;
+	struct drm_plane* drm_plane_temp = NULL;
+	if (backend && drm_plane)
+	{
+		wl_list_for_each(plane, &backend->compositor->plane_list, link) {
+			drm_plane_temp = to_drm_plane(plane);
+			if (drm_plane == drm_plane_temp) {
+				break;
+			}
+		}
+	}
+	return plane;
+}
+
+void drm_fb_destroy_aml(struct drm_fb *fb)
+{
+	if (fb) {
+		if (fb->fb_id != 0) {
+			if (fb && fb->plane && fb->plane->keep_last_frame
+				&& (fb->fb_id == fb->plane->last_fb_id)) {
+				struct weston_plane* plane = drm_get_weston_plane(fb->plane->backend, fb->plane);
+				if (plane && plane->keep_last_frame) {
+					weston_log("\n drm_fb_destroy keep:%d last fb id:%d plane_weston:%p,drm plane:%p line:%d\n",
+						fb->plane->keep_last_frame, fb->plane->last_fb_id, plane, fb->plane, __LINE__ );
+					drmIoctl(fb->fd, DRM_IOCTL_MESON_RMFB, &fb->fb_id);
+					plane->keep_last_frame = false;
+				} else {
+					drmModeRmFB(fb->fd, fb->fb_id);
+				}
+			} else {
+				drmModeRmFB(fb->fd, fb->fb_id);
+			}
+		}
+		free(fb);
+	}
+}
+
+void drm_update_buffer_commit_result(int ret, struct drm_pending_state *pending_state)
+{
+	if (ret != 0) {
+		struct drm_output_state *output_state_tmp;
+		wl_list_for_each(output_state_tmp, &pending_state->output_list, link) {
+			if (output_state_tmp->output->virtual)
+				continue;
+			struct drm_plane_state *plane_state_tmp;
+			wl_list_for_each(plane_state_tmp, &output_state_tmp->plane_list, link) {
+				if (plane_state_tmp && plane_state_tmp->fb && plane_state_tmp->fb_ref.buffer.buffer) {
+					plane_state_tmp->fb_ref.buffer.buffer->commit_fail = true;
+					weston_log("\n%s %d buffer :%p commit  fail\n",
+						__FUNCTION__, __LINE__, plane_state_tmp->fb_ref.buffer.buffer);
+				}
+			}
+		}
+	}
+}
+
+void drm_update_video_plane_info(struct drm_plane_state *plane_state, uint32_t *flags)
+{
+	if (plane_state) {
+		struct drm_output *output = plane_state->output;
+		struct drm_backend *b = to_drm_backend(output->base.compositor);
+		struct drm_crtc *crtc = output->crtc;
+		if ( plane_state->plane && plane_state->plane->keep_last_frame) {
+			plane_state->plane->last_fb_id = plane_state->fb->fb_id;
+			plane_state->plane->crtc = crtc;
+			drm_debug(plane_state->plane->backend, "\t\t\t need keep last frame .update last fb_id:%u\n",
+				(unsigned long) plane_state->fb->fb_id);
+		}
+		if ( !(*flags & DRM_MODE_ATOMIC_TEST_ONLY) && b->compositor->enable_video_debug && plane_state->plane) {
+			if (plane_state->plane->is_video_plane) {
+				struct timespec time;
+
+				weston_compositor_get_time(&time);
+				weston_log("%llu commit buffer:%p to drm \n", timespec_to_usec(&time), plane_state->fb_ref.buffer.buffer);
+			}
+		}
+	}
+}
+
+void atomic_flip_handler_time(struct drm_backend *b)
+{
+	struct timespec now;
+	int64_t mdiff;
+
+	weston_compositor_read_presentation_clock(b->compositor, &now);
+	mdiff = timespec_sub_to_msec(&now, &b->compositor->last_repaint_start);
+
+	if (mdiff > 17)
+		weston_log("\n output_repaint_timer_handler %d now (%ld.%09ld) last (%ld.%09ld) diff:%lld\n", __LINE__,
+			now.tv_sec, now.tv_nsec, b->compositor->last_repaint_start.tv_sec, b->compositor->last_repaint_start.tv_nsec, mdiff);
+}
+
+void drm_update_aml_state_coords(struct drm_output* output, struct drm_plane_state *state)
+{
+	if (output && state) {
+#ifdef MESON_DRM_FIX_UI_SIZE
+		// For overlayer plane eg: video plane
+		// Move the frame buffer at center of display
+		float scale_w = (float)output->display_size.width / output->base.width;
+		float scale_h = (float)output->display_size.height / output->base.height;
+		float last_scale = scale_w < scale_h ? scale_w : scale_h;
+		if (scale_w < scale_h) {
+			scale_h = (scale_h - scale_w) / 2;
+			state->dest_x = scale_w * state->dest_x;
+			state->dest_y = scale_w * state->dest_y + scale_h * output->base.height;
+			state->dest_w = scale_w * state->dest_w;
+			state->dest_h = scale_w * state->dest_h;
+		} else {
+			scale_w = (scale_w - scale_h) / 2;
+			state->dest_x = scale_h * state->dest_x + scale_w * output->base.width;
+			state->dest_y = scale_h * state->dest_y;
+			state->dest_w = scale_h * state->dest_w;
+			state->dest_h = scale_h * state->dest_h;
+		}
+#endif
+	}
+}
+
+void drm_update_keep_frame_info(struct weston_view *ev,
+		struct drm_fb *fb, struct drm_plane_state *ps)
+{
+	if (ev->surface->is_video_surface && fb && ps) {
+		fb->plane = ps->plane;
+		fb->plane->keep_last_frame = true;
+		ev->surface->plane = drm_get_weston_plane(ps->output->backend, fb->plane);
+		if (ev->surface->plane)
+			ev->surface->plane->keep_last_frame = ev->surface->keep_last_frame;
+		drm_debug(ps->output->backend, "\n \t\t\t\t[view] video surface: %d keep_last_frame %d "
+			"view:%p surface: %p plane:%d weston_plane:%p drm_plane:%p\n",
+			ev->surface->is_video_surface, ev->surface->keep_last_frame,
+			ev, ev->surface, ps->plane->plane_id, ev->surface->plane, fb->plane);
+	}
+}
+
+bool drm_check_video_plane_destroy_zpos(struct drm_backend *b,
+			struct weston_view *ev,
+			struct drm_plane *plane,
+			const char *p_name)
+{
+	if (ev && ev->surface && plane) {
+		if (ev->surface->video_plane != 255 && ev->surface->is_video_surface) {
+			if (plane->is_video_plane && ev->surface->video_plane != plane->video_plane) {
+				drm_debug(b, "\t\t\t\t[plane] plane %d is video plane:%d  type: %s, "
+					"surface was assighed to video plane:%d, continue\n",
+					plane->plane_id, plane->video_plane, p_name, ev->surface->video_plane);
+				return true;
+			}
+		}
+	}
+	return false;
+}
diff --git a/aml-weston/aml-backend.h b/aml-weston/aml-backend.h
new file mode 100644
index 0000000..0c1eba8
--- /dev/null
+++ b/aml-weston/aml-backend.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+#ifndef AML_BACKEND_H
+#define AML_BACKEND_H
+
+#include <linux/amlogic/drm/meson_drm.h>
+
+#ifdef ENABLE_DRM_HELP
+#include "compositor-drm-help.h"
+#include "shared/file-util.h"
+
+void weston_print_info(struct weston_compositor* ec, int count);
+int drm_output_switch_mode_helper(output_ctx ctx, drm_helper_mode* mode);
+#endif
+
+void drm_output_render_aml_config(struct drm_output *output, struct drm_plane_state *scanout_state);
+void drm_switch_mode_aml_config_ui_size(struct drm_output* output, struct weston_output *output_base,
+			struct drm_mode *drm_mode);
+void drm_switch_mode_aml_config_help(struct drm_output* output, struct weston_output *output_base,
+			struct drm_mode *drm_mode);
+void drm_enable_aml_output_config(struct drm_output* output,
+			struct weston_output *base, struct drm_backend *b);
+void drm_output_disable_aml(struct drm_output *output, struct weston_output *base);
+void drm_update_helper_connector(struct drm_connector *connector,
+			drmModeConnector *conn);
+void drm_append_helper_connector(struct drm_head *head);
+void drm_delete_helper_connector(struct drm_head *head);
+void drm_init_aml_output_config(struct weston_compositor *compositor,
+			struct drm_output *output);
+
+#ifdef BUILD_AML_TV
+void drm_backend_afr_update(struct drm_backend *b,
+		int rate_hint,
+		int vdin_event);
+#endif
+
+bool drm_change_to_dummy_mode( struct weston_compositor *compositor);
+void drm_config_fixed_UIsize( struct drm_backend *b,
+		struct weston_drm_backend_config *config);
+void drm_add_aml_callback(struct drm_backend *b);
+
+void drm_fb_destroy_aml(struct drm_fb *fb);
+void drm_update_buffer_commit_result(int ret, struct drm_pending_state *pending_state);
+void drm_update_video_plane_info(struct drm_plane_state *plane_state, uint32_t *flags);
+void atomic_flip_handler_time(struct drm_backend *b);
+
+void drm_set_mode_update_aml_info(struct drm_head *head,
+		struct drm_output *output, struct drm_mode *current);
+void drm_update_aml_state_coords(struct drm_output* output, struct drm_plane_state *state);
+void drm_update_keep_frame_info(struct weston_view *ev,
+		struct drm_fb *fb, struct drm_plane_state *ps);
+bool drm_check_video_plane_destroy_zpos(struct drm_backend *b,
+			struct weston_view *ev,
+			struct drm_plane *plane,
+			const char *p_name);
+#endif
diff --git a/aml-weston/aml-compositor.c b/aml-weston/aml-compositor.c
new file mode 100644
index 0000000..933eeed
--- /dev/null
+++ b/aml-weston/aml-compositor.c
@@ -0,0 +1,1027 @@
+/*
+ * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+#if MESON_VIDEO_PLAN_SUPPORT
+#include <drm_fourcc.h>
+#endif
+#ifdef ENABLE_DRM_HELP
+#include "weston-drm-helper/compositor-drm-help.h"
+#include "shared/file-util.h"
+#endif
+
+#include <libweston/backend-drm.h>
+#include <libweston/backend-drm/drm-internal.h>
+
+#include <linux/dma-buf.h>
+#include <linux/types.h>
+#include <poll.h>
+
+#ifndef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
+struct dma_buf_export_sync_file {
+	/**
+	 * @flags: Read/write flags
+	 *
+	 * Must be DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, or both.
+	 *
+	 * If DMA_BUF_SYNC_READ is set and DMA_BUF_SYNC_WRITE is not set,
+	 * the returned sync file waits on any writers of the dma-buf to
+	 * complete.  Waiting on the returned sync file is equivalent to
+	 * poll() with POLLIN.
+	 *
+	 * If DMA_BUF_SYNC_WRITE is set, the returned sync file waits on
+	 * any users of the dma-buf (read or write) to complete.  Waiting
+	 * on the returned sync file is equivalent to poll() with POLLOUT.
+	 * If both DMA_BUF_SYNC_WRITE and DMA_BUF_SYNC_READ are set, this
+	 * is equivalent to just DMA_BUF_SYNC_WRITE.
+	 */
+	__u32 flags;
+	/** @fd: Returned sync file descriptor */
+	__s32 fd;
+};
+#define DMA_BUF_BASE		'b'
+#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE	_IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)
+#endif
+
+#define FRAMES_RELEASE (3)
+#define FRAME_CURR (0)
+#define FRAME_PREV (1)
+#define FRAME_FREE (2)
+#define MAX_VIDEO_SURFACE 2
+
+static struct weston_buffer* video_buffer_release[FRAMES_RELEASE];
+static bool release_cur = false;
+static bool release_pre = false;
+
+#ifdef ENABLE_DRM_HELP
+static void weston_compositor_print_node_info(struct weston_compositor *ec);
+#endif
+static void weston_compositor_debug_print_scene(struct weston_compositor *ec);
+static struct weston_subsurface *
+weston_surface_to_subsurface(struct weston_surface *surface);
+static void
+weston_subsurface_commit(struct weston_subsurface *sub);
+static int
+weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
+			    void *repaint_data);
+static void
+weston_output_schedule_repaint_reset(struct weston_output *output);
+static void
+output_repaint_timer_arm(struct weston_compositor *compositor);
+static void
+debug_scene_view_print_tree(struct weston_view *view,
+			    FILE *fp, int *view_idx);
+static const char *
+output_repaint_status_text(struct weston_output *output);
+
+
+WL_EXPORT void weston_view_opacity(struct weston_view *view, float opacity)
+{
+#ifdef FORCE_BACKGROUND_TRANSPARENT
+	if (opacity > 1.0)
+		opacity = 1.0;
+	weston_log("\n %s view :%p surface :%p   opacity:%f\n",
+		__FUNCTION__,view, view->surface, opacity);
+	if (view)
+		view->alpha = opacity;
+#endif
+// do nothing if not set FORCE_BACKGROUND_TRANSPARENT
+}
+
+static void weston_init_video_surface_info(struct weston_surface *surface)
+{
+#if MESON_VIDEO_PLAN_SUPPORT
+	surface->is_video_surface = false;
+#endif
+	surface->video_plane = 255;
+	surface->commit_queue = NULL;
+	surface->queue_capacity = SURFACE_QUEUE_CAPACITY;
+	surface->queue_size = 0;
+	wl_list_init(&surface->link);
+	surface->keep_last_frame = false;
+}
+
+static void weston_clear_video_surface_info(struct weston_surface *surface)
+{
+	if (surface->is_video_surface) {
+		video_buffer_release[FRAME_FREE] = NULL;
+		video_buffer_release[FRAME_PREV] = NULL;
+		video_buffer_release[FRAME_CURR] = NULL;
+		release_cur = false;
+		release_pre = false;
+		if (surface->compositor->video_surface_count > 0)
+			surface->compositor->video_surface_count -= 1;
+	}
+	struct weston_surface *surface_tmp = NULL;
+	struct weston_surface *surface_pos = NULL;
+	wl_list_for_each_safe(surface_pos, surface_tmp, &surface->compositor->video_surface_list, link) {
+		if (surface_pos == surface) {
+			wl_list_remove(&surface->link);
+			wl_list_init(&surface->link);
+			break;
+		}
+	}
+	if (surface->commit_queue) {
+		free(surface->commit_queue);
+		surface->commit_queue = NULL;
+	}
+
+	if (surface->is_video_surface && !surface->keep_last_frame)
+		surface->compositor->backend->close_video_plane(surface->compositor, surface->plane);
+}
+
+static int video_fence( struct weston_buffer *buffer)
+{
+	struct linux_dmabuf_buffer *dmabuf = NULL;
+	int dmabuffd = -1;
+	int rc = -1;
+
+	if (buffer) {
+		dmabuf = linux_dmabuf_buffer_get(buffer->resource);
+	} else {
+		weston_log("\n buffer is NULL!\n");
+		return rc;
+	}
+
+	if (dmabuf) {
+		dmabuffd = dmabuf->attributes.fd[0];
+	} else {
+		weston_log("dmabuf is NULL!\n");
+	}
+
+	struct dma_buf_export_sync_file dma_fence;
+	memset(&dma_fence, 0, sizeof(struct dma_buf_export_sync_file));
+
+	if (dmabuffd <= 0) {
+		weston_log("dmabuffd <= 0 return!\n");
+		return rc;
+	}
+
+	dma_fence.flags |= DMA_BUF_SYNC_READ;
+	rc = ioctl(dmabuffd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &dma_fence);
+	if (!rc && dma_fence.fd >= 0) {
+		struct pollfd pfd;
+		pfd.fd = dma_fence.fd;
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		rc = poll( &pfd, 1, 0);
+		close( dma_fence.fd );
+		dma_fence.fd = -1;
+	}
+	// rc==1 means buffer can release safe
+	return rc;
+}
+
+static bool is_video_buffer(struct weston_buffer *buffer)
+{
+	bool isVideoBuffer = false;
+#if MESON_VIDEO_PLAN_SUPPORT
+	struct linux_dmabuf_buffer *dmabuf = NULL;
+	if (buffer) {
+		dmabuf = linux_dmabuf_buffer_get(buffer->resource);
+		if (dmabuf) {
+			switch (dmabuf->attributes.format) {
+				case DRM_FORMAT_NV12:
+				case DRM_FORMAT_NV21:
+				case DRM_FORMAT_YUV420:
+				case DRM_FORMAT_YVU420:
+				case DRM_FORMAT_YUYV:
+				case DRM_FORMAT_YVYU:
+					// add WESTON_FORCE_DRI env for dri yuv dmabuffer, if we not use weston_direct_display protocol
+					if (!dmabuf->direct_display) {
+						if (getenv("WESTON_FORCE_DRI"))
+							isVideoBuffer = true;
+					}
+					if (dmabuf->direct_display)
+						isVideoBuffer = true;
+					break;
+				default:
+					break;
+			}
+		}
+	}
+#endif
+	return isVideoBuffer;
+}
+
+WL_EXPORT void weston_release_stranded_buffers()
+{
+	struct timespec time;
+	if (video_buffer_release[FRAME_FREE] != NULL) {
+		weston_compositor_get_time(&time);
+		weston_log("\n weston_release_stranded_buffers  line:%d :%p, time:%lld \n", __LINE__,
+				video_buffer_release[FRAME_FREE], timespec_to_usec(&time));
+		wl_buffer_send_release(video_buffer_release[FRAME_FREE]->resource);
+		video_buffer_release[FRAME_FREE] = NULL;
+	}
+	if (video_buffer_release[FRAME_PREV] != NULL) {
+		weston_compositor_get_time(&time);
+		weston_log("\n weston_release_stranded_buffers  line:%d :%p, time:%lld \n", __LINE__,
+				video_buffer_release[FRAME_PREV], timespec_to_usec(&time));
+		wl_buffer_send_release(video_buffer_release[FRAME_PREV]->resource);
+		video_buffer_release[FRAME_PREV] = NULL;
+	}
+	if (video_buffer_release[FRAME_CURR] != NULL) {
+		weston_compositor_get_time(&time);
+		weston_log("\n weston_release_stranded_buffers  line:%d :%p, time:%lld \n", __LINE__,
+				video_buffer_release[FRAME_CURR], timespec_to_usec(&time));
+		wl_buffer_send_release(video_buffer_release[FRAME_CURR]->resource);
+		video_buffer_release[FRAME_CURR] = NULL;
+	}
+	release_cur = false;
+	release_pre = false;
+}
+
+static void buffer_send_release(struct weston_buffer_reference *ref)
+{
+	if (!is_video_buffer(ref->buffer)) {
+		wl_buffer_send_release(ref->buffer->resource);
+	} else {
+		int fence_rc = -1;
+		video_buffer_release[FRAME_FREE] = video_buffer_release[FRAME_PREV];
+		video_buffer_release[FRAME_PREV] = video_buffer_release[FRAME_CURR];
+		video_buffer_release[FRAME_CURR] = ref->buffer;
+		if (video_buffer_release[FRAME_FREE] != NULL && release_pre == false ) {
+			//no matter get fence or not,send release anyway
+			wl_buffer_send_release(video_buffer_release[FRAME_FREE]->resource);
+			video_buffer_release[FRAME_FREE] = NULL;
+		}
+		if (video_buffer_release[FRAME_PREV] != NULL && release_cur == true) {
+			release_pre = true;
+		}
+		if (video_buffer_release[FRAME_PREV] != NULL && release_cur == false) {
+			fence_rc = video_fence(video_buffer_release[FRAME_PREV]);
+			if (fence_rc == 1) {
+				wl_buffer_send_release(video_buffer_release[FRAME_PREV]->resource);
+				video_buffer_release[FRAME_PREV] = NULL;
+				release_pre = true;
+			} else {
+				release_pre = false;
+			}
+		}
+		if (video_buffer_release[FRAME_CURR] != NULL) {
+			fence_rc = -1;
+			fence_rc = video_fence(video_buffer_release[FRAME_CURR]);
+			if (fence_rc == 1) {
+				wl_buffer_send_release(video_buffer_release[FRAME_CURR]->resource);
+				video_buffer_release[FRAME_CURR] = NULL;
+				release_cur = true;
+			} else {
+				release_cur = false;
+			}
+		}
+		if (!release_cur && video_buffer_release[FRAME_CURR]->commit_fail) {
+			wl_buffer_send_release(video_buffer_release[FRAME_CURR]->resource);
+			video_buffer_release[FRAME_CURR]->commit_fail = false;
+			video_buffer_release[FRAME_CURR] = NULL;
+			release_cur = true;
+		}
+	}
+}
+
+static void weston_video_surface_attach(struct weston_surface *surface,
+			struct weston_buffer *buffer)
+{
+#if MESON_VIDEO_PLAN_SUPPORT
+	struct linux_dmabuf_buffer *dmabuf = NULL;
+	if (buffer) {
+		dmabuf = linux_dmabuf_buffer_get(buffer->resource);
+		if (dmabuf) {
+			switch (dmabuf->attributes.format) {
+				case DRM_FORMAT_NV12:
+				case DRM_FORMAT_NV21:
+				case DRM_FORMAT_YUV420:
+				case DRM_FORMAT_YVU420:
+				case DRM_FORMAT_YUYV:
+				case DRM_FORMAT_YVYU:
+					// add WESTON_FORCE_DRI env for dri yuv dmabuffer, if we not use weston_direct_display protocol
+					if (!dmabuf->direct_display) {
+						if (getenv("WESTON_FORCE_DRI"))
+							dmabuf->direct_display = true;
+					}
+					if (dmabuf->direct_display) {
+						if (surface->is_video_surface == false) {
+							video_buffer_release[FRAME_CURR] = NULL;
+							video_buffer_release[FRAME_PREV] = NULL;
+							video_buffer_release[FRAME_FREE] = NULL;
+							surface->is_video_surface = true;
+						}
+					}
+					break;
+				default:
+					weston_log_scope_printf(surface->compositor->debug_scene,
+							"[meson]===>dma buffer import drm format:%#x in [%s]%s:%d\n",
+							dmabuf->attributes.format, __func__ , __FILE__, __LINE__);
+					break;
+			}
+		}
+	}
+#endif
+	if (surface->is_video_surface && surface->video_plane == 255) {
+		surface->video_plane = surface->compositor->video_surface_count;
+		surface->compositor->video_surface_count++;
+		if (surface->compositor->video_surface_count >= MAX_VIDEO_SURFACE )
+			surface->compositor->video_surface_count = 0;
+	}
+}
+
+static void push_sub_surface_to_queue(struct weston_subsurface* sub)
+{
+	if (sub->surface ) {
+		if (!sub->surface->commit_queue)
+			sub->surface->commit_queue =
+				(struct weston_surface_state *)calloc(sub->surface->queue_capacity, sizeof(struct weston_surface_state));
+		if (sub->surface->queue_size + 1 > sub->surface->queue_capacity ) {
+			int orgCapacity = sub->surface->queue_capacity;
+			int newCapacity = 2 * sub->surface->queue_capacity + 1;
+			struct weston_surface_state *newStateQueue =
+					(struct weston_surface_state*)calloc( newCapacity, sizeof(struct weston_surface_state) );
+			if ( newStateQueue ) {
+				struct weston_surface_state *toFreeState = sub->surface->commit_queue;
+				memcpy( newStateQueue, sub->surface->commit_queue,
+						sub->surface->queue_size * sizeof(struct weston_surface_state) );
+				sub->surface->commit_queue = newStateQueue;
+				sub->surface->queue_capacity = newCapacity;
+				weston_log("\n expand queue capacity from %d to %d", orgCapacity, newCapacity);
+				free( toFreeState );
+			} else {
+				weston_log("\n queue full: no memory to expand, dropping frame");
+				return;
+			}
+		}
+		struct weston_surface_state* surface_state_queue = sub->surface->commit_queue;
+		int size = sub->surface->queue_size;
+		memcpy(&surface_state_queue[size], &sub->surface->pending, sizeof(struct weston_surface_state));
+		sub->surface->queue_size++;
+		int64_t pts = sub->surface->pending.buffer->pts;
+		struct timespec time;
+
+		weston_compositor_get_time(&time);
+		weston_log("\n push_sub_surface_to_queue %p queue_size:%d pts:%lld current:%lld buffer:%p\n",
+				sub->surface, sub->surface->queue_size, pts,
+				timespec_to_usec(&time), sub->surface->pending.buffer);
+	}
+}
+
+static struct weston_surface_state *
+pop_surface_state_from_queue(struct weston_surface *cur_surface, struct timespec now)
+{
+	struct weston_surface_state* surface_state_queue = cur_surface->commit_queue;
+	uint64_t frame_time = 0;
+	uint64_t real_repaint_time = 0;
+	uint64_t refresh_interval = 0;
+	uint64_t pts = 0;
+	uint64_t now_us = 0;
+	int expired_count = 0;
+	struct weston_output *output = NULL;
+	struct weston_buffer *buffer_drop = NULL;
+	if (cur_surface->queue_size < 1) {
+		weston_log("\n no surface in surface queue, return!!!\n");
+		return NULL;
+	}
+	wl_list_for_each(output, &cur_surface->compositor->output_list, link) {
+		if (output) {
+			cur_surface->compositor->backend->get_frame_time(output, &frame_time, &refresh_interval);
+			real_repaint_time = frame_time;
+			break;
+		}
+	}
+	now_us = ((uint64_t)(now.tv_sec)) * 1000000 + ((uint64_t)(now.tv_nsec)) / 1000;
+
+	if ((now_us - real_repaint_time) >= 16000)
+		real_repaint_time = real_repaint_time + refresh_interval;
+	// real_repaint_time = ((uint64_t)(now.tv_sec)) * 1000000 + ((uint64_t)(now.tv_nsec)) / 1000;
+
+	if (real_repaint_time <= 0) {
+		weston_log("\n invalid next_repaint_time, commit now!!!\n");
+		goto out;
+	}
+
+	for (int i = 0; i < cur_surface->queue_size; i++ ) {
+		pts = surface_state_queue[i].buffer->pts;
+		if (pts == 0) {
+			weston_log("\n pts == 0 commit now\n");
+			goto out;
+		}
+		if (pts < real_repaint_time -2000)
+			expired_count++;
+		else
+			break;
+	}
+	if (expired_count > 0) {
+		weston_log("\n pop expired_count~~:%d\n", expired_count);
+		uint64_t pts_drop = 0;
+		for (int k = 0; k < expired_count; k++) {
+			buffer_drop = surface_state_queue[k].buffer;
+			pts_drop = buffer_drop->pts;
+			if (buffer_drop->resource) {
+				weston_log("\n send buffer release and drop:%lld, real_repaint_time:%lld !buffer_drop:%p, resource :%p, \n",
+					pts_drop, real_repaint_time, buffer_drop, buffer_drop->resource);
+				wl_buffer_send_drop(buffer_drop->resource);
+			}
+		}
+		cur_surface->queue_size = cur_surface->queue_size - expired_count;
+		for (int j = 0; j < cur_surface->queue_size; j++ ) {
+			surface_state_queue[j] = surface_state_queue[j + expired_count];
+		}
+	}
+	if (cur_surface->queue_size < 1) {
+		weston_log("\n no surface in surface queue, return!!!\n");
+		return NULL;
+	}
+	pts = surface_state_queue[0].buffer->pts;
+	if (pts >= (real_repaint_time + refresh_interval)) {
+		weston_log("\n pop_surface_state_from_queue time is not up real_repaint_time:%lld refresh_interval:%lld!!!\n",
+			real_repaint_time, refresh_interval);
+		return NULL;
+	}
+out:
+	cur_surface->pending = surface_state_queue[0];
+	if (cur_surface->queue_size > 1) {
+		for (int j = 0; j < cur_surface->queue_size - 1; j++ ) {
+			surface_state_queue[j] = surface_state_queue[j + 1];
+		}
+	}
+	--cur_surface->queue_size;
+	weston_log("\n pop_surface_state_from_queue pop success:%lld buffer:%p, real_repaint_time:%lld refresh_interval:%lld!!!\n",
+		cur_surface->pending.buffer->pts, cur_surface->pending.buffer, real_repaint_time, refresh_interval);
+	return &cur_surface->pending;
+}
+
+static bool check_commit_video_surface(struct weston_compositor *compositor, struct timespec now)
+{
+	bool pts_exsit = false;
+	struct weston_surface *surface_tmp = NULL;
+	struct weston_surface *surface_pos = NULL;
+	wl_list_for_each_safe(surface_pos, surface_tmp, &compositor->video_surface_list, link) {
+		struct weston_subsurface *sub = NULL;
+		struct weston_surface_state *pending = NULL;
+		if ( surface_pos ) {
+			pts_exsit = true;
+			sub = weston_surface_to_subsurface(surface_pos);
+			if (sub) {
+				pending = pop_surface_state_from_queue(surface_pos, now);
+			}
+			if (pending) {
+				weston_subsurface_commit(sub);
+			}
+		}
+	}
+	return pts_exsit;
+}
+
+static void update_next_repaint_time(struct weston_compositor *compositor)
+{
+	int32_t refresh_nsec;
+	struct timespec now;
+	struct timespec vblank_monotonic;
+	int64_t msec_rel;
+	int64_t msec_diff;
+	uint64_t frame_time = 0;
+	uint64_t refresh_interval = 0;
+	struct weston_output *output;
+
+	wl_list_for_each(output, &compositor->output_list, link) {
+		compositor->backend->get_frame_time(output, &frame_time, &refresh_interval);
+		struct timespec stamp;
+		struct timespec repaint;
+		repaint = output->next_repaint;
+		stamp.tv_sec = frame_time / 1000000;
+		stamp.tv_nsec = frame_time % 1000000 * 1000;
+		weston_compositor_read_presentation_clock(compositor, &now);
+		output->frame_time = stamp;
+		refresh_nsec = refresh_interval * 1000;
+		timespec_add_nsec(&output->next_repaint, &stamp, refresh_nsec);
+		timespec_add_msec(&output->next_repaint, &output->next_repaint,
+				  -compositor->repaint_msec);
+		msec_rel = timespec_sub_to_msec(&output->next_repaint, &now);
+		if (msec_rel < -1000 || msec_rel > 1000) {
+			static bool warned;
+			if (!warned)
+				weston_log("Warning: computed repaint delay is "
+					   "insane: %lld msec\n", (long long) msec_rel);
+			warned = true;
+			output->next_repaint = now;
+			weston_log("\n set next repaint now\n");
+		}
+		if (msec_rel <= 0) {
+			while (timespec_sub_to_nsec(&output->next_repaint, &now) <= 0) {
+				timespec_add_nsec(&output->next_repaint,
+						  &output->next_repaint,
+						  refresh_nsec);
+			}
+		}
+		msec_diff = timespec_sub_to_msec(&output->next_repaint, &repaint);
+		if (msec_diff < 10)
+			timespec_add_nsec(&output->next_repaint,
+						  &output->next_repaint,
+						  refresh_nsec);
+		msec_rel = timespec_sub_to_msec(&output->next_repaint, &now);
+		if (msec_rel <= 0)
+			msec_rel = 1;
+		weston_log("\n update_next_repaint_time %d msec_rel:%lld, next(%d,%09ld)\n",
+			__LINE__, msec_rel, output->next_repaint.tv_sec, output->next_repaint.tv_nsec);
+		wl_event_source_timer_update(compositor->repaint_timer, (int)msec_rel);
+	}
+}
+
+static void surface_set_pts(struct wl_client *client,
+				 struct wl_resource *resource,
+				 uint32_t pts_hi, uint32_t pts_lo)
+{
+	struct weston_surface *surface = wl_resource_get_user_data(resource);
+	if (surface && surface->pending.buffer) {
+		surface->pending.buffer->pts = ((uint64_t)pts_hi << 32) | pts_lo;
+	} else {
+		weston_log("\n surface_set_pts invalid input\n");
+	}
+}
+
+static bool need_schedule_repaint(void* repaint_data, bool pts_exist)
+{
+	bool need_repaint = false;
+	struct drm_output_state *output_state;
+	struct drm_output_state *tmp;
+	struct drm_pending_state *pending_state = repaint_data;
+	bool pending_state_empty = true;
+
+	wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
+					  link) {
+		struct drm_plane_state *plane_state;
+		wl_list_for_each(plane_state, &output_state->plane_list, link) {
+			if (plane_state) {
+				pending_state_empty = false;
+				break;
+			}
+		}
+	}
+	if (pending_state_empty && pts_exist)
+		need_repaint = true;
+	return need_repaint;
+}
+
+static int output_repaint_timer_handler_aml(void *data)
+{
+	struct weston_compositor *compositor = data;
+	struct weston_output *output;
+	struct timespec now;
+	void *repaint_data = NULL;
+	int ret = 0;
+	bool dirty = false;
+	bool pts_exsit = false;
+	bool need_repaint = false;
+
+	struct timespec t1;
+	weston_compositor_read_presentation_clock(compositor, &now);
+	int64_t mdiff;
+	mdiff = timespec_sub_to_msec(&now, &compositor->last_repaint_start);
+	if (mdiff > 17)
+		weston_log("\n output_repaint_timer_handler %d now (%ld.%09ld) last (%ld.%09ld) diff:%lld\n", __LINE__,
+			now.tv_sec, now.tv_nsec, compositor->last_repaint_start.tv_sec, compositor->last_repaint_start.tv_nsec, mdiff);
+	compositor->last_repaint_start = now;
+	pts_exsit = check_commit_video_surface(compositor, now);
+
+	if (compositor->backend->repaint_begin)
+		repaint_data = compositor->backend->repaint_begin(compositor);
+
+#ifdef ENABLE_DRM_HELP
+	static int log_frame_count = 0;
+	bool log_client = false;
+	if (compositor->aml_log_enable) {
+		weston_compositor_debug_print_scene(compositor);
+	}
+#endif
+	wl_list_for_each(output, &compositor->output_list, link) {
+		ret = weston_output_maybe_repaint(output, &now, repaint_data);
+		if (ret)
+			break;
+	}
+
+#ifdef ENABLE_DRM_HELP
+	if (compositor->aml_log_enable && compositor->aml_log_start) {
+		compositor->backend->print_output_status(compositor, repaint_data, compositor->aml_logfile);
+		log_frame_count++;
+		if (log_frame_count >= compositor->aml_log_nframes) {
+			weston_compositor_print_node_info(compositor);
+			compositor->aml_log_enable = false;
+			compositor->aml_log_start = false;
+			compositor->aml_log_nframes = 0;
+			fclose(compositor->aml_logfile);
+			compositor->aml_logfile = NULL;
+		}
+	}
+#endif
+	need_repaint = need_schedule_repaint(repaint_data, pts_exsit);
+
+	if (ret == 0) {
+		if (compositor->backend->repaint_flush)
+			ret = compositor->backend->repaint_flush(compositor,
+							 repaint_data);
+	} else {
+		if (compositor->backend->repaint_cancel)
+			compositor->backend->repaint_cancel(compositor,
+							    repaint_data);
+	}
+
+	if (ret != 0) {
+		wl_list_for_each(output, &compositor->output_list, link) {
+			if (output->repainted)
+				weston_output_schedule_repaint_reset(output);
+		}
+	}
+
+	wl_list_for_each(output, &compositor->output_list, link)
+		output->repainted = false;
+
+	int64_t take;
+	weston_compositor_read_presentation_clock(compositor, &t1);
+	take =  timespec_sub_to_msec(&t1, &now);
+	if (take >= 10)
+		weston_log("\n timer_handler %d start (%ld.%09ld) end (%ld.%09ld) take:%lld\n", __LINE__,
+			now.tv_sec, now.tv_nsec, t1.tv_sec, t1.tv_nsec, take);
+	if ( need_repaint ) {
+		wl_list_for_each(output, &compositor->output_list, link) {
+			weston_log("\n %s %d ret:%d  need_repaint:%d\n", __FUNCTION__, __LINE__, ret, need_repaint);
+			weston_output_schedule_repaint_reset(output);
+			weston_output_schedule_repaint(output);
+			return 0;
+		}
+	}
+	output_repaint_timer_arm(compositor);
+	return 0;
+}
+
+static void surface_set_video_plane(struct wl_client *client,
+	       struct wl_resource *resource,
+	       int32_t video_plane)
+{
+	struct weston_surface *surface = wl_resource_get_user_data(resource);
+	if (video_plane < 0)
+		return;
+	surface->video_plane = video_plane;
+}
+
+static void surface_keep_last_frame(struct wl_client *client,
+	       struct wl_resource *resource,
+	       int32_t keep_last_frame)
+{
+	struct weston_surface *surface = wl_resource_get_user_data(resource);
+	if ( keep_last_frame < 0 )
+		return;
+	surface->keep_last_frame = true;
+	if ( keep_last_frame == 0 )
+		surface->keep_last_frame = false;
+	weston_log("\n surface_keep_last_frame:%d \n", surface->keep_last_frame);
+}
+
+static void
+surface_set_display_rate(struct wl_client *client,
+		struct wl_resource *resource,
+		int frame_rate_value, int frame_rate_scale)
+{
+	struct weston_surface *surface = wl_resource_get_user_data(resource);
+	struct weston_compositor *compositor = surface->compositor;
+	weston_log("\n  frame_rate_value:%d, frame_rate_scale:%d", frame_rate_value, frame_rate_scale);
+	if (compositor->backend->update_frame_rate)
+		compositor->backend->update_frame_rate(compositor, frame_rate_value, frame_rate_scale);
+}
+
+static FILE *
+file_create(const char *path, const char *prefix, const char *suffix,
+		  char *name_out, size_t name_len, FILE *msg_fp)
+{
+	int ret;
+	int fd;
+	int cnt = 0;
+	int with_path;
+
+	with_path = path && path[0];
+	ret = snprintf(name_out, name_len, "%s%s%s%s",
+		       with_path ? path : "", with_path ? "/" : "",
+		       prefix, suffix);
+	if (ret < 0 || (size_t)ret >= name_len) {
+		errno = ENOBUFS;
+		return NULL;
+	}
+	fd = open(name_out, O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL, 00666);
+	while (fd == -1 && errno == EEXIST) {
+		cnt++;
+		ret = snprintf(name_out, name_len, "%s%s%s_%d%s",
+			       with_path ? path : "", with_path ? "/" : "",
+			       prefix, cnt, suffix);
+		if (ret < 0 || (size_t)ret >= name_len) {
+			errno = ENOBUFS;
+			return NULL;
+		}
+		fd = open(name_out, O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL, 00666);
+	}
+	weston_log("\n file_create fd:%d name:%s line:%d\n", fd, name_out, __LINE__);
+	if (msg_fp)
+		fprintf(msg_fp, "\n \t\t file_create :%s line :%d fd:%d\n", name_out, __LINE__, fd );
+	if (fd == -1)
+		return NULL;
+	return fdopen(fd, "w");
+}
+
+WL_EXPORT void
+weston_debug_write_buffer_to_file(void* buffer,
+			int buffer_size, char* name_in, FILE *msg_fp )
+{
+	const char *suffix = ".bin";
+	char fname[1024];
+	FILE* fp;
+	const char *path = "/data";
+	fp = file_create(path, name_in, suffix, fname, sizeof(fname), msg_fp);
+	if (!fp) {
+		const char *msg;
+		switch (errno) {
+		case ETIME:
+			msg = "failure in datetime formatting";
+			break;
+		default:
+			msg = strerror(errno);
+		}
+		fprintf(msg_fp, "debug_write_buffer_to_file Cannot open '%s*%s' for writing: %s\n",
+			   name_in, suffix, msg);
+	}
+	fprintf(msg_fp, "\n \t\t line :%d size:%d fp:%p\n", __LINE__,buffer_size, fp);
+	weston_log("\n weston_debug_write_buffer_to_file line :%d size:%d fp:%p\n", __LINE__, buffer_size, fp);
+	if (fp) {
+		if (fwrite(buffer, 1, buffer_size, fp) != buffer_size)
+			fprintf(msg_fp, " fwrite fail!\n");
+		fclose(fp);
+	}
+}
+
+static void debug_write_shm_buffer_to_file(struct weston_view *view, struct wl_shm_buffer *shm)
+{
+	if (view->surface->compositor->aml_log_enable &&
+			view->surface->compositor->aml_log_start) {
+		FILE *fp = view->surface->compositor->aml_logfile;
+		fprintf(fp, "\t\t start to write shm buffer to file\n");
+		void* data = wl_shm_buffer_get_data(shm);
+		int size = wl_shm_buffer_get_height(shm) * wl_shm_buffer_get_stride(shm);
+		fprintf(fp, "\t\t width:%d height:%d stride:%d size:%d \n",
+			wl_shm_buffer_get_width(shm), wl_shm_buffer_get_height(shm), wl_shm_buffer_get_stride(shm),
+			size );
+		if (shm && data) {
+			weston_debug_write_buffer_to_file(data, size, view->surface->role_name, fp);
+		} else {
+			fprintf(fp, "\t\tshm data get fail\n");
+		}
+	}
+}
+
+static void debug_write_dma_buffer_to_file(struct weston_view *view, struct linux_dmabuf_buffer *dmabuf)
+{
+	if (view->surface->compositor->aml_log_enable &&
+			view->surface->compositor->aml_log_start) {
+		int size = dmabuf->attributes.height * dmabuf->attributes.width*4;
+		int dmabuffd = dmabuf->attributes.fd[0];
+		int offset = dmabuf->attributes.offset[0];
+		void *mapPtr = NULL;
+		FILE *fp = view->surface->compositor->aml_logfile;
+		mapPtr = mmap(NULL, size, PROT_READ, MAP_SHARED, dmabuffd, offset);
+		if ( mapPtr == MAP_FAILED || mapPtr == NULL) {
+			fprintf(fp," debug_write_dma_buffer_to_file failed to map buffer: %s\n", strerror(errno));
+		} else {
+			fprintf(fp, "\t\t !!!!start to write dma buffer to file view :%p dmabuffd:%d size:%d (%d * %d *4) offset:%d\n",
+			view, dmabuffd, size, dmabuf->attributes.height, dmabuf->attributes.width, offset);
+			weston_debug_write_buffer_to_file(mapPtr, size, view->surface->role_name, fp);
+			munmap(mapPtr, size);
+		}
+	}
+}
+
+#ifdef ENABLE_DRM_HELP
+#define OUTPUT_STATE                  "/sys/kernel/debug/dri/0/state"
+#define HDMITX_ATTR_DISPLAY_CAP       "/sys/class/amhdmitx/amhdmitx0/disp_cap"
+#define HDMITX_HDCPMODE               "/sys/class/amhdmitx/amhdmitx0/hdcp_mode"
+#define HDMITX_ATTR                   "/sys/class/amhdmitx/amhdmitx0/attr"
+#define DISPLAY_VINFO                 "/sys/class/display/vinfo"
+#define BUFFER_SIZE_SMALL 1024
+#define BUFFER_SIZE_BIG 10240
+
+static int weston_compositor_get_sysfs_str(const char *path, char *valstr, int size)
+{
+    int fd;
+    fd = open(path, O_RDONLY);
+    if (fd >= 0) {
+        memset(valstr, 0, size);
+        read(fd, valstr, size - 1);
+        valstr[strlen(valstr)] = '\0';
+        close(fd);
+    } else {
+        printf("unable to open file %s,err: %s\n", path, strerror(errno));
+        sprintf(valstr, "%s", "fail");
+        return -1;
+    }
+    return 0;
+}
+
+static void weston_compositor_print_node_info(struct weston_compositor *ec)
+{
+	FILE *fp = ec->aml_logfile;
+	if (fp) {
+		fprintf(fp, "node info: \n");
+		fprintf(fp, "node info:/sys/kernel/debug/dri/0/state \n");
+		char str_big_size[BUFFER_SIZE_BIG] = {'\0'};
+		weston_compositor_get_sysfs_str(OUTPUT_STATE, str_big_size, BUFFER_SIZE_BIG);
+		fprintf(fp, "%s", str_big_size);
+		fprintf(fp, "\n");
+		fprintf(fp, "node info:/sys/class/amhdmitx/amhdmitx0/disp_cap \n");
+		char str_small_size[BUFFER_SIZE_SMALL] = {'\0'};
+		weston_compositor_get_sysfs_str(HDMITX_ATTR_DISPLAY_CAP, str_small_size, BUFFER_SIZE_SMALL);
+		fprintf(fp, "%s", str_small_size);
+		fprintf(fp, "\n");
+		fprintf(fp, "node info:/sys/class/amhdmitx/amhdmitx0/hdcp_mode \n");
+		memset(str_small_size, '\0', BUFFER_SIZE_SMALL);
+		weston_compositor_get_sysfs_str(HDMITX_HDCPMODE, str_small_size, BUFFER_SIZE_SMALL);
+		fprintf(fp, "%s", str_small_size);
+		fprintf(fp, "\n");
+		fprintf(fp, "node info:/sys/class/amhdmitx/amhdmitx0/attr \n");
+		memset(str_small_size, '\0', BUFFER_SIZE_SMALL);
+		weston_compositor_get_sysfs_str(HDMITX_ATTR, str_small_size, BUFFER_SIZE_SMALL);
+		fprintf(fp, "%s", str_small_size);
+		fprintf(fp, "\n");
+		fprintf(fp, "node info:/sys/class/display/vinfo \n");
+		memset(str_big_size, '\0', BUFFER_SIZE_BIG);
+		weston_compositor_get_sysfs_str(DISPLAY_VINFO, str_big_size, BUFFER_SIZE_BIG);
+		fprintf(fp, "%s", str_big_size);
+		fprintf(fp, "\n");
+	}
+}
+
+static void weston_compositor_print_scene(struct weston_compositor *ec, FILE *fp)
+{
+	struct weston_output *output;
+	struct weston_layer *layer;
+	struct timespec now;
+	int layer_idx = 0;
+
+#ifdef MESON_DRM_FIX_UI_SIZE
+	struct drm_output *drm_output_p = NULL;
+#endif
+
+	weston_compositor_read_presentation_clock(ec, &now);
+	fprintf(fp, "Weston scene graph at %ld.%09ld:\n\n",
+		now.tv_sec, now.tv_nsec);
+
+	wl_list_for_each(output, &ec->output_list, link) {
+		struct weston_head *head;
+		int head_idx = 0;
+
+		fprintf(fp, "Output %d (%s):\n", output->id, output->name);
+		assert(output->enabled);
+
+		fprintf(fp, "\tposition: (%d, %d) -> (%d, %d)\n",
+			output->x, output->y,
+			output->x + output->width,
+			output->y + output->height);
+#ifdef MESON_DRM_FIX_UI_SIZE
+		drm_output_p = wl_container_of(output, drm_output_p, base);
+		if (drm_output_p) {
+			fprintf(fp, "\tmode: %dx%d@%.3fHz\n",
+				drm_output_p->display_size.width,
+				drm_output_p->display_size.height,
+				output->current_mode->refresh / 1000.0);
+		} else {
+			fprintf(fp, "\tmode: %dx%d@%.3fHz\n",
+				output->current_mode->width,
+				output->current_mode->height,
+				output->current_mode->refresh / 1000.0);
+		}
+#else
+		fprintf(fp, "\tmode: %dx%d@%.3fHz\n",
+			output->current_mode->width,
+			output->current_mode->height,
+			output->current_mode->refresh / 1000.0);
+#endif
+		fprintf(fp, "\tscale: %d\n", output->scale);
+
+		fprintf(fp, "\trepaint status: %s\n",
+			output_repaint_status_text(output));
+		if (output->repaint_status == REPAINT_SCHEDULED)
+			fprintf(fp, "\tnext repaint: %ld.%09ld\n",
+				output->next_repaint.tv_sec,
+				output->next_repaint.tv_nsec);
+
+		wl_list_for_each(head, &output->head_list, output_link) {
+			fprintf(fp, "\tHead %d (%s): %sconnected\n",
+				head_idx++, head->name,
+				(head->connected) ? "" : "not ");
+		}
+	}
+
+	fprintf(fp, "\n");
+
+	wl_list_for_each(layer, &ec->layer_list, link) {
+		struct weston_view *view;
+		int view_idx = 0;
+
+		fprintf(fp, "Layer %d (pos 0x%lx):\n", layer_idx++,
+			(unsigned long) layer->position);
+
+		if (!weston_layer_mask_is_infinite(layer)) {
+			fprintf(fp, "\t[mask: (%d, %d) -> (%d,%d)]\n\n",
+				layer->mask.x1, layer->mask.y1,
+				layer->mask.x2, layer->mask.y2);
+		}
+
+		wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
+			debug_scene_view_print_tree(view, fp, &view_idx);
+			view_idx++;
+		}
+
+		if (wl_list_empty(&layer->view_list.link))
+			fprintf(fp, "\t[no views]\n");
+
+		fprintf(fp, "\n");
+	}
+}
+
+static void weston_compositor_debug_print_scene(struct weston_compositor *ec)
+{
+	if (ec->aml_log_enable) {
+		const char *suffix = ".log";
+		char fname[1024];
+		const char *path = "/data";
+		const char *prefix = "aml_weston";
+		ec->aml_logfile = file_create(path, prefix, suffix, fname, sizeof(fname), NULL);
+		if (!ec->aml_logfile) {
+			weston_log("\n aml_logfile create fail, return \n");
+			return;
+		}
+		ec->aml_log_start = true;
+		fprintf(ec->aml_logfile, "\n aml_logfile start!\n");
+		weston_compositor_print_scene(ec, ec->aml_logfile);
+	}
+}
+#endif
+
+static void weston_compositor_aml_init(struct weston_compositor *ec)
+{
+	ec->last_keyboard_focus = NULL;
+#ifdef ENABLE_DRM_HELP
+	ec->aml_logfile = NULL;
+	ec->aml_log_enable = false;
+	ec->aml_log_nframes = 0;
+#endif
+	ec->use_gbm_modifiers = true;
+
+	ec->enable_video_debug = false;
+	char* env  = getenv("WESTON_ENABLE_VIDEO_DEBUG");
+	weston_log("\n WESTON_ENABLE_VIDEO_DEBUG :%s \n", env);
+	if (env) {
+		ec->enable_video_debug = true;
+		weston_log("\n enable video debug \n");
+	}
+}
+
+static void
+weston_video_subsurface_commit(struct weston_surface *surface,
+			struct weston_subsurface *sub)
+{
+	if (sub->surface
+			&& sub->surface->pending.buffer
+			&& sub->surface->pending.buffer->pts) {
+			if (wl_list_empty(&surface->compositor->video_surface_list)) {
+				wl_list_init(&surface->link);
+				wl_list_init(&surface->compositor->video_surface_list);
+				wl_list_insert(&surface->compositor->video_surface_list, &surface->link);
+				weston_log("\n surface insert first video surface success:%p (%p %p)\n",
+					sub->surface, &surface->compositor->video_surface_list, &surface->link);
+			} else {
+				struct weston_surface *surface_pos = NULL;
+				struct weston_surface *surface_tmp = NULL;
+				wl_list_for_each_safe(surface_pos, surface_tmp, &surface->compositor->video_surface_list, link) {
+					if (surface_pos == surface)
+						continue;
+					weston_log("\n surface insert video surface: %p\n", sub->surface);
+					wl_list_insert(&surface->compositor->video_surface_list, &sub->surface->link);
+					break;
+				}
+			}
+			push_sub_surface_to_queue(sub);
+		} else {
+			weston_subsurface_commit(sub);
+		}
+}
+
+void weston_surface_commit_time(struct weston_surface *surface)
+{
+	if (surface && surface->compositor->enable_video_debug) {
+		struct timespec time;
+
+		weston_compositor_get_time(&time);
+		uint64_t commit_time = timespec_to_usec(&time);
+		weston_log("%llu, surface_commit :%p\n", commit_time, surface);
+		if ((commit_time - surface->commit_time) > 18000)
+			weston_log("%llu, surface_commit :%p interval > 18ms\n", commit_time, surface);
+		surface->commit_time = commit_time;
+	}
+}
diff --git a/aml-weston/aml-main.c b/aml-weston/aml-main.c
new file mode 100644
index 0000000..4da40c1
--- /dev/null
+++ b/aml-weston/aml-main.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+static bool
+drm_head_should_force_enable(struct wet_compositor *wet,
+			     struct weston_head *head);
+static void
+drm_head_prepare_enable(struct wet_compositor *wet,
+			struct weston_head *head);
+static int
+drm_process_layoutput(struct wet_compositor *wet,
+			struct wet_layoutput *lo);
+static struct wet_compositor *
+to_wet_compositor(struct weston_compositor *compositor);
+static struct weston_config_section *
+drm_config_find_controlling_output_section(struct weston_config *config,
+			const char *head_name);
+static void
+drm_head_disable(struct weston_head *head);
+
+
+void weston_config_fixed_UIsize( struct weston_config *wc,
+		struct weston_drm_backend_config* config)
+{
+#ifdef MESON_DRM_FIX_UI_SIZE
+	if (wc && config) {
+		char* buffp = NULL;
+		struct weston_config_section *section = NULL;
+		section = weston_config_get_section(wc, "output", NULL, NULL);
+		weston_config_section_get_string(section,
+						 "ui-size", &buffp,
+						 NULL);
+		if (buffp != NULL)
+			sscanf(buffp, "%dx%d", &config->fixed_ui_size.width, &config->fixed_ui_size.height);
+
+		weston_log("%s, L%d, fixed UI size(%dX%d) %d\n",
+			__FUNCTION__, __LINE__, config->fixed_ui_size.width, config->fixed_ui_size.height);
+	}
+#endif
+}
+
+static void drm_head_changed(struct wet_compositor *wet, struct weston_head *head, bool should_enable)
+{
+	bool connected = false;
+	bool enabled = false;
+	bool changed = false;
+	bool forced = false;
+	connected = weston_head_is_connected(head);
+	enabled = weston_head_is_enabled(head);
+	changed = weston_head_is_device_changed(head);
+	forced = drm_head_should_force_enable(wet, head);
+	weston_log("\n %s %d head:%s connected:%d,enabled:%d,changed:%d forced:%d should_enable:%d\n",
+		__FUNCTION__, __LINE__, head->name, connected, enabled, changed, forced, should_enable);
+	if (((connected || forced) && should_enable) && !enabled) {
+		if (strcmp("HDMI-A-1", head->name) == 0) {
+			weston_log("\n enable HDMI  and release stranded buffers\n");
+			weston_release_stranded_buffers();
+		}
+		drm_head_prepare_enable(wet, head);
+	} else if (!((connected || forced) && should_enable) && enabled) {
+		if (strcmp("HDMI-A-1", head->name) == 0) {
+			weston_log("\n disable HDMI and release stranded buffers\n");
+			weston_release_stranded_buffers();
+		}
+		drm_head_disable(head);
+	} else if (enabled && changed) {
+		weston_log("Detected a monitor change on head '%s', "
+				"not bothering to do anything about it.\n",
+				weston_head_get_name(head));
+	}
+	weston_head_reset_device_changed(head);
+}
+
+static int drm_process_layoutputs_aml(struct wet_compositor *wet)
+{
+	struct wet_layoutput *lo;
+	int ret = 0;
+#if AML_MAX_OUTPUT_PIPLINE > 0
+	bool have_output = false; //any one could output as true
+#endif
+	wl_list_for_each(lo, &wet->layoutput_list, compositor_link) {
+		if (lo->add.n == 0)
+			continue;
+
+		if (drm_process_layoutput(wet, lo) < 0) {
+			lo->add = (struct wet_head_array){}; // main.c
+			ret = -1;
+		#if AML_MAX_OUTPUT_PIPLINE > 0
+			if (have_output)
+				ret = 0;
+			weston_log("%s, L%d, output have %d ret %d, name %s\n", __FUNCTION__, __LINE__, have_output, ret, lo->name);
+		#endif
+		}
+		#if AML_MAX_OUTPUT_PIPLINE > 0
+		else {
+			weston_log("%s, L%d, have output %s\n", __FUNCTION__, __LINE__, lo->name);
+			have_output = true;
+		}
+		#endif
+	}
+	weston_log("%s, L%d, return %d\n", __FUNCTION__, __LINE__, ret);
+	return ret;
+}
+
+static int drm_get_head_priority(struct wet_compositor *wet,
+		struct weston_head* head)
+{
+	const char *name = weston_head_get_name(head);
+	struct weston_config_section *section;
+	int priority = 0;
+
+	section = drm_config_find_controlling_output_section(wet->config, name);
+	if (section) {
+		weston_config_section_get_int(section, "priority", &priority, 0);
+	}
+	return priority;
+}
+
+static void drm_get_should_enable_heads_by_priority(struct weston_compositor *compositor,
+		struct weston_head** out, int out_size)
+{
+	int i, j;
+	struct weston_head *head = NULL;
+	bool connected;
+	bool forced;
+	int priority = 0;
+	bool enabled;
+	bool changed;
+	struct wet_compositor *wet = to_wet_compositor(compositor);
+	int *priority_array = (int *)zalloc(sizeof(int) * out_size);
+
+	if (!priority_array) {
+		perror("out of memory");
+		return;
+	}
+
+	memset(out, 0, sizeof(struct weston_head*) * out_size);
+
+	while ((head = weston_compositor_iterate_heads(compositor, head))) {
+		struct weston_config_section *section;
+		const char *name = weston_head_get_name(head);
+		section = drm_config_find_controlling_output_section(wet->config, name);
+		if (!section) {
+			weston_log("%s, L%d, the %s output in not in config, IGNORE it\n", __FUNCTION__, __LINE__, name);
+			continue;
+		}
+
+		/* When hdmi disconnect, set head as disconnect after sent head change.
+		   In this case, hdmi drm change handle may be lost,
+		   if signal handle after head state cheanged to disconnect.
+		   So add 'enabled' checking to avoid hdmi head be ignoed */
+		enabled = weston_head_is_enabled(head);
+		connected = weston_head_is_connected(head);
+		forced = drm_head_should_force_enable(wet, head);
+		priority = drm_get_head_priority(wet, head);
+		changed = weston_head_is_device_changed(head);
+
+		if (!(connected || forced || enabled)) {
+			continue;
+		}
+
+		if (strcmp(name, "HDMI-A-1") == 0 && !(connected || forced) && enabled) {
+			drm_head_disable(head);
+			weston_release_stranded_buffers();
+			continue;
+		}
+
+		for (i = 0; i < out_size; i++) {
+			if (priority > priority_array[i] || out[i] == NULL) {
+				for (j = out_size - 1; j > i; j--) {
+					out[j] = out[j - 1];
+					priority_array[j] = priority_array[j - 1];
+				}
+				out[i] = head;
+				priority_array[i] = priority;
+				break;
+			}
+		}
+	}
+	free(priority_array);
+
+	for (i = 0; i < out_size; i++) {
+		if (i == 0)
+			weston_log("Output pipline limited:%d, Enable connect by priority:", out_size);
+		if (out[i] != NULL) {
+			weston_log("[=>%s]", weston_head_get_name(out[i]));
+		}
+	}
+	weston_log("\n");
+}
+
+void drm_heads_changed_aml(struct wl_listener *listener, void *arg)
+{
+	struct weston_compositor *compositor = arg;
+	struct wet_compositor *wet = to_wet_compositor(compositor);
+	struct weston_head *head = NULL;
+
+#if AML_MAX_OUTPUT_PIPLINE > 0
+	struct weston_head* head_should_enable[AML_MAX_OUTPUT_PIPLINE] = {NULL};
+	drm_get_should_enable_heads_by_priority(compositor, head_should_enable, AML_MAX_OUTPUT_PIPLINE);
+	int i;
+	for (i = 0; i < AML_MAX_OUTPUT_PIPLINE; i++) {
+		if ( head_should_enable[i]) {
+			head = head_should_enable[i];
+			drm_head_changed(wet, head, true);
+		}
+	}
+#endif
+
+	while ((head = weston_compositor_iterate_heads(compositor, head))) {
+#if AML_MAX_OUTPUT_PIPLINE > 0
+		bool should_enable = false;
+		int i;
+		for (i = 0; i < AML_MAX_OUTPUT_PIPLINE; i++) {
+			if (head == head_should_enable[i]) {
+				should_enable = true;
+			}
+		}
+		if (should_enable == true)
+			continue;
+#else
+		bool should_enable = true;
+#endif
+		drm_head_changed(wet, head, should_enable);
+	}
+
+	if (drm_process_layoutputs_aml(wet) < 0)
+		wet->init_failed = true;
+}
diff --git a/aml-weston/aml-renderer.c b/aml-weston/aml-renderer.c
new file mode 100644
index 0000000..69e183f
--- /dev/null
+++ b/aml-weston/aml-renderer.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+#include "aml-renderer.h"
+
+static bool repaint_area_Empty(struct weston_paint_node *pnode,
+		pixman_region32_t *damage /* in global coordinates */)
+{
+	bool empty = false;
+	pixman_region32_t repaint;
+	pixman_region32_init(&repaint);
+	pixman_region32_intersect(&repaint,
+				  &pnode->view->transform.boundingbox, damage);
+	pixman_region32_subtract(&repaint, &repaint, &pnode->view->clip);
+	if (!pixman_region32_not_empty(&repaint))
+		empty = true;
+	return empty;
+}
+
+void repaint_views_aml(struct weston_output *output, pixman_region32_t *damage,
+			void (*draw_node)(struct weston_paint_node *, pixman_region32_t *))
+{
+	struct weston_compositor *compositor = output->compositor;
+	struct weston_paint_node *pnode;
+	bool haveOpaqueSurface = false;
+
+	wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list,
+				 z_order_link) {
+		if (pnode->view->plane == &compositor->primary_plane) {
+			if (pnode->view->alpha != 0.0 && !repaint_area_Empty(pnode, damage)) {
+				draw_node(pnode, damage);
+				haveOpaqueSurface = true;
+			}
+		}
+	}
+
+	if (haveOpaqueSurface == false) {
+		wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list,
+				 z_order_link) {
+			if (pnode->view->plane == &compositor->primary_plane) {
+				weston_log("\n %s %d %s view %p haveOpaqueSurface:%d alpha:%f~~~~~~~~~\n",
+					__FUNCTION__, __LINE__,
+					output->name, pnode->view, haveOpaqueSurface, pnode->view->alpha);
+				draw_node(pnode, damage);
+			}
+		}
+	}
+}
diff --git a/aml-weston/aml-renderer.h b/aml-weston/aml-renderer.h
new file mode 100644
index 0000000..6d3bca7
--- /dev/null
+++ b/aml-weston/aml-renderer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2022 Amlogic, Inc. All rights reserved.
+ *
+ * This source code is subject to the terms and conditions defined in the
+ * file 'LICENSE' which is part of this source code package.
+ *
+ * Description:
+ */
+#ifndef AML_RENDERER_H
+#define AML_RENDERER_H
+
+#include <libweston/libweston.h>
+#include "libweston-internal.h"
+
+void repaint_views_aml(struct weston_output *output, pixman_region32_t *damage,
+	void (*draw_node)(struct weston_paint_node *, pixman_region32_t *));
+#endif
diff --git a/aml-weston/aml_config.c b/aml-weston/aml_config.c
new file mode 100644
index 0000000..b3dd818
--- /dev/null
+++ b/aml-weston/aml_config.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2019 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <libweston/libweston.h>
+#include "aml-config-server-protocol.h"
+#include "libweston-internal.h"
+
+static void
+aml_config_destroy_resource(struct wl_client *client,
+		       struct wl_resource *global_resource)
+{
+	wl_resource_destroy(global_resource);
+}
+
+static const struct aml_config_interface
+	aml_config_interface_v1 = {
+		aml_config_destroy_resource
+};
+
+static void
+bind_aml_config(struct wl_client *client, void *data,
+		    uint32_t version, uint32_t id)
+{
+	struct wl_resource *resource;
+	struct weston_compositor *ec = data;
+
+	resource = wl_resource_create(client,
+			&aml_config_interface,
+			version, id);
+	if (!resource) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	wl_resource_set_implementation(resource,
+				       &aml_config_interface_v1,
+				       ec, NULL);
+	const char* aml_config_list = "set_video_plane, keep_last_frame";
+	aml_config_send_aml_config_list(resource, aml_config_list);
+}
+
+WL_EXPORT int
+aml_config_setup(struct weston_compositor *ec)
+{
+	if (!wl_global_create(ec->wl_display,
+			      &aml_config_interface, 1,
+			      ec, bind_aml_config))
+		return -1;
+
+	return 0;
+}
diff --git a/clients/arkadvb.c b/clients/arkadvb.c
new file mode 100644
index 0000000..13579b1
--- /dev/null
+++ b/clients/arkadvb.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright © 2011 Tim Wiederhake
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file arkadvb.c
+ * \brief Demonstrate the use of Wayland's toytoolkit.
+ *
+ * Heavily commented demo program that can report all events that are
+ * dispatched to the window. For other functionality, eg. opengl/egl,
+ * drag and drop, etc. have a look at the other demos.
+ * \author Tim Wiederhake
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+#include <cairo.h>
+
+#include "shared/helpers.h"
+#include "window.h"
+
+/*********** arka dvb app related content ***********/
+#include <dlfcn.h>
+typedef void (*OnArkaRun) (void);
+typedef void (*OnArkaStop) (void);
+OnArkaRun p_arka_run;
+OnArkaStop p_arka_stop;
+void *handle = NULL;
+pthread_t arka_thread_tid;
+
+static void arka_dvb_init() {
+  if (NULL == handle)
+    handle = dlopen("/usr/lib/libArka.so", RTLD_LAZY);
+  if (handle) {
+    p_arka_run = (OnArkaRun)dlsym(handle, "arka_run");
+    p_arka_stop = (OnArkaRun)dlsym(handle, "arka_stop");
+    if (!p_arka_run || !p_arka_stop) {
+      printf("arka dvb init failed\n");
+      return;
+    }
+  }
+}
+
+static void arka_dvb_run() {
+  printf("In %s() <--> line:%d\n", __func__, __LINE__);
+  p_arka_run();
+}
+
+static void arka_dvb_deinit() {
+  printf("In %s() <--> line:%d\n", __func__, __LINE__);
+  p_arka_stop();
+  if (handle) dlclose(handle);
+}
+
+static void *arka_thread(void *arg) {
+  arka_dvb_run();
+}
+/********************************************************/
+
+/** window title */
+static char *title = "EventDemo";
+static char *appid = "org.freedesktop.weston.arkadvb";
+
+/** window width */
+static int width = 1920;
+
+/** window height */
+static int height = 1080;
+
+/** set if window has no borders */
+static bool noborder = true;
+
+/** if non-zero, maximum window width */
+static int width_max = 0;
+
+/** if non-zero, maximum window height */
+static int height_max = 0;
+
+/** set to log redrawing */
+static bool log_redraw = false;
+
+/** set to log resizing */
+static bool log_resize = false;
+
+/** set to log keyboard focus */
+static bool log_focus = false;
+
+/** set to log key events */
+static bool log_key = false;
+
+/** set to log button events */
+static bool log_button = false;
+
+/** set to log axis events */
+static bool log_axis = false;
+
+/** set to log motion events */
+static bool log_motion = false;
+
+/**
+ * \struct arkadvb
+ * \brief Holds all data the program needs per window
+ *
+ * In this demo the struct holds the position of a
+ * red rectangle that is drawn in the window's area.
+ */
+struct arkadvb {
+	struct window *window;
+	struct widget *widget;
+	struct display *display;
+
+	int x, y, w, h;
+
+	bool print_pointer_frame;
+};
+
+/**
+ * \brief CALLBACK function, Wayland requests the window to redraw.
+ * \param widget widget to be redrawn
+ * \param data user data associated to the window
+ *
+ * Draws a red rectangle as demonstration of per-window data.
+ */
+static void
+redraw_handler(struct widget *widget, void *data)
+{
+	struct arkadvb *e = data;
+	cairo_surface_t *surface;
+	cairo_t *cr;
+	struct rectangle rect;
+
+	if (log_redraw)
+		printf("redraw\n");
+
+	widget_get_allocation(e->widget, &rect);
+	surface = window_get_surface(e->window);
+
+	cr = cairo_create(surface);
+	cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+
+	cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height);
+	cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
+	cairo_fill(cr);
+
+	cairo_rectangle(cr, e->x, e->y, e->w, e->h);
+	cairo_set_source_rgba(cr, 0, 0, 0, 0);
+	cairo_fill(cr);
+
+	cairo_destroy(cr);
+	cairo_surface_destroy(surface);
+}
+
+/**
+ * \brief CALLBACK function, Wayland requests the window to resize.
+ * \param widget widget to be resized
+ * \param width desired width
+ * \param height desired height
+ * \param data user data associated to the window
+ */
+
+static void
+resize_handler(struct widget *widget,
+	       int32_t width, int32_t height, void *data)
+{
+	struct arkadvb *e = data;
+	if (log_resize)
+		printf("resize width: %d, height: %d\n", width, height);
+
+	/* if a maximum width is set, constrain to it */
+	if (width_max && width_max < width)
+		width = width_max;
+
+	/* if a maximum height is set, constrain to it */
+	if (height_max && height_max < height)
+		height = height_max;
+
+	/* set the new window dimensions */
+	widget_set_size(e->widget, width, height);
+}
+
+/**
+ * \brief CALLBACK function, Wayland informs about keyboard focus change
+ * \param window window
+ * \param device device that caused the focus change
+ * \param data user data associated to the window
+ */
+static void
+keyboard_focus_handler(struct window *window,
+		       struct input *device, void *data)
+{
+	int32_t x, y;
+	struct arkadvb *e = data;
+
+	if (log_focus) {
+		if (device) {
+			input_get_position(device, &x, &y);
+			printf("focus x: %d, y: %d\n", x, y);
+		} else {
+			printf("focus lost\n");
+		}
+	}
+
+	window_schedule_redraw(e->window);
+}
+
+/**
+ * \brief CALLBACK function, Wayland informs about key event
+ * \param window window
+ * \param input input
+ * \param time time
+ * \param key keycode
+ * \param unicode associated character
+ * \param state pressed or released
+ * \param data user data associated to the window
+ */
+static void
+key_handler(struct window *window, struct input *input, uint32_t time,
+            uint32_t key, uint32_t unicode, enum wl_keyboard_key_state state,
+	    void *data)
+{
+	uint32_t modifiers = input_get_modifiers(input);
+
+	if (!log_key)
+		return;
+
+	printf("key key: %u, unicode: %u, state: %s, modifiers: 0x%x\n",
+	       key, unicode,
+	       (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? "pressed" :
+							  "released",
+	       modifiers);
+}
+
+/**
+ * \brief CALLBACK function, Wayland informs about button event
+ * \param widget widget
+ * \param input input device that caused the button event
+ * \param time time the event happened
+ * \param button button
+ * \param state pressed or released
+ * \param data user data associated to the window
+ */
+static void
+button_handler(struct widget *widget, struct input *input, uint32_t time,
+	       uint32_t button, enum wl_pointer_button_state state, void *data)
+{
+	struct arkadvb *e = data;
+	int32_t x, y;
+
+	if (!log_button)
+		return;
+
+	e->print_pointer_frame = true;
+
+	input_get_position(input, &x, &y);
+	printf("button time: %u, button: %u, state: %s, x: %d, y: %d\n",
+	       time, button,
+	       (state == WL_POINTER_BUTTON_STATE_PRESSED) ? "pressed" :
+							    "released",
+	       x, y);
+}
+
+/**
+ * \brief CALLBACK function, Wayland informs about axis event
+ * \param widget widget
+ * \param input input device that caused the axis event
+ * \param time time the event happened
+ * \param axis vertical or horizontal
+ * \param value amount of scrolling
+ * \param data user data associated to the widget
+ */
+static void
+axis_handler(struct widget *widget, struct input *input, uint32_t time,
+	     uint32_t axis, wl_fixed_t value, void *data)
+{
+	struct arkadvb *e = data;
+
+	if (!log_axis)
+		return;
+
+	e->print_pointer_frame = true;
+
+	printf("axis time: %u, axis: %s, value: %f\n",
+	       time,
+	       axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" :
+							 "horizontal",
+	       wl_fixed_to_double(value));
+}
+
+static void
+pointer_frame_handler(struct widget *widget, struct input *input, void *data)
+{
+	struct arkadvb *e = data;
+
+	if (!e->print_pointer_frame)
+		return;
+
+	printf("pointer frame\n");
+	e->print_pointer_frame = false;
+}
+
+static void
+axis_source_handler(struct widget *widget, struct input *input,
+		    uint32_t source, void *data)
+{
+	const char *axis_source;
+	struct arkadvb *e = data;
+
+	if (!log_axis)
+		return;
+
+	e->print_pointer_frame = true;
+
+	switch (source) {
+	case WL_POINTER_AXIS_SOURCE_WHEEL:
+		axis_source = "wheel";
+		break;
+	case WL_POINTER_AXIS_SOURCE_FINGER:
+		axis_source = "finger";
+		break;
+	case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
+		axis_source = "continuous";
+		break;
+	default:
+		axis_source = "<invalid source value>";
+		break;
+	}
+
+	printf("axis source: %s\n", axis_source);
+}
+
+static void
+axis_stop_handler(struct widget *widget, struct input *input,
+		  uint32_t time, uint32_t axis,
+		  void *data)
+{
+	struct arkadvb *e = data;
+
+	if (!log_axis)
+		return;
+
+	e->print_pointer_frame = true;
+	printf("axis stop time: %u, axis: %s\n",
+	       time,
+	       axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" :
+							 "horizontal");
+}
+
+static void
+axis_discrete_handler(struct widget *widget, struct input *input,
+		      uint32_t axis, int32_t discrete, void *data)
+{
+	struct arkadvb *e = data;
+
+	if (!log_axis)
+		return;
+
+	e->print_pointer_frame = true;
+	printf("axis discrete axis: %u value: %d\n", axis, discrete);
+}
+
+/**
+ * \brief CALLBACK function, Waylands informs about pointer motion
+ * \param widget widget
+ * \param input input device that caused the motion event
+ * \param time time the event happened
+ * \param x absolute x position
+ * \param y absolute y position
+ * \param x x position relative to the window
+ * \param y y position relative to the window
+ * \param data user data associated to the window
+ *
+ * Demonstrates the use of different cursors
+ */
+static int
+motion_handler(struct widget *widget, struct input *input, uint32_t time,
+	       float x, float y, void *data)
+{
+	struct arkadvb *e = data;
+
+	if (log_motion) {
+		printf("motion time: %u, x: %f, y: %f\n", time, x, y);
+		e->print_pointer_frame = true;
+	}
+
+	if (x > e->x && x < e->x + e->w)
+		if (y > e->y && y < e->y + e->h)
+			return CURSOR_HAND1;
+
+	return CURSOR_LEFT_PTR;
+}
+
+/**
+ * \brief Create and initialise a new arkadvb window.
+ * The returned arkadvb instance should be destroyed using \c arkadvb_destroy().
+ * \param d associated display
+ */
+static struct arkadvb *
+arkadvb_create(struct display *d)
+{
+	struct arkadvb *e;
+
+	e = zalloc(sizeof (struct arkadvb));
+	if (e == NULL)
+		return NULL;
+
+	e->window = window_create(d);
+
+	if (noborder) {
+		/* Demonstrate how to create a borderless window.
+		 * Move windows with META + left mouse button.
+		 */
+		e->widget = window_add_widget(e->window, e);
+	} else {
+		e->widget = window_frame_create(e->window, e);
+		//window_set_title(e->window, title);
+		//window_set_appid(e->window, appid);
+	}
+	e->display = d;
+
+	/* The arkadvb window draws a red rectangle as a demonstration
+	 * of per-window data. The dimensions of that rectangle are set
+	 * here.
+	 */
+	e->x = width * 1.0 / 4.0;
+	e->w = width * 2.0 / 4.0;
+	e->y = height * 1.0 / 4.0;
+	e->h = height * 2.0 / 4.0;
+
+	/* Connect the user data to the window */
+	window_set_user_data(e->window, e);
+
+	/* Set the callback redraw handler for the window */
+	widget_set_redraw_handler(e->widget, redraw_handler);
+
+	/* Set the callback resize handler for the window */
+	widget_set_resize_handler(e->widget, resize_handler);
+
+#if 0
+	/* Set the callback focus handler for the window */
+	window_set_keyboard_focus_handler(e->window,
+					  keyboard_focus_handler);
+
+	/* Set the callback key handler for the window */
+	window_set_key_handler(e->window, key_handler);
+
+	/* Set the callback button handler for the window */
+	widget_set_button_handler(e->widget, button_handler);
+
+	/* Set the callback motion handler for the window */
+	widget_set_motion_handler(e->widget, motion_handler);
+
+	/* Set the callback pointer frame handler for the window */
+	widget_set_pointer_frame_handler(e->widget, pointer_frame_handler);
+
+	/* Set the callback axis handler for the window */
+	widget_set_axis_handlers(e->widget,
+				 axis_handler,
+				 axis_source_handler,
+				 axis_stop_handler,
+				 axis_discrete_handler);
+#endif
+
+	/* Initial drawing of the window */
+	window_schedule_resize(e->window, width, height);
+
+	return e;
+}
+/**
+ * \brief Destroy arkadvb instance previously created by \c arkadvb_create().
+ * \param arkadvb arkadvb instance to destroy
+ */
+static void arkadvb_destroy(struct arkadvb * arkadvb)
+{
+	widget_destroy(arkadvb->widget);
+	window_destroy(arkadvb->window);
+	free(arkadvb);
+}
+/**
+ * \brief command line options for arkadvb
+ */
+static const struct weston_option arkadvb_options[] = {
+	{ WESTON_OPTION_STRING, "title", 0, &title },
+	{ WESTON_OPTION_INTEGER, "width", 'w', &width },
+	{ WESTON_OPTION_INTEGER, "height", 'h', &height },
+	{ WESTON_OPTION_INTEGER, "max-width", 0, &width_max },
+	{ WESTON_OPTION_INTEGER, "max-height", 0, &height_max },
+	{ WESTON_OPTION_BOOLEAN, "no-border", 'b', &noborder },
+	{ WESTON_OPTION_BOOLEAN, "log-redraw", 0, &log_redraw },
+	{ WESTON_OPTION_BOOLEAN, "log-resize", 0, &log_resize },
+	{ WESTON_OPTION_BOOLEAN, "log-focus", 0, &log_focus },
+	{ WESTON_OPTION_BOOLEAN, "log-key", 0, &log_key },
+	{ WESTON_OPTION_BOOLEAN, "log-button", 0, &log_button },
+	{ WESTON_OPTION_BOOLEAN, "log-axis", 0, &log_axis },
+	{ WESTON_OPTION_BOOLEAN, "log-motion", 0, &log_motion },
+};
+
+
+/**
+ * \brief Connects to the display, creates the window and hands over
+ * to the main loop.
+ */
+int
+main(int argc, char *argv[])
+{
+	struct display *d;
+	struct arkadvb *e;
+
+	if (parse_options(arkadvb_options,
+			  ARRAY_LENGTH(arkadvb_options), &argc, argv) > 1) {
+		unsigned k;
+		printf("Usage: %s [OPTIONS]\n\n", argv[0]);
+		for (k = 0; k < ARRAY_LENGTH(arkadvb_options); k++) {
+			const struct weston_option* p = &arkadvb_options[k];
+			if (p->name) {
+				printf("  --%s", p->name);
+				if (p->type != WESTON_OPTION_BOOLEAN)
+					printf("=VALUE");
+				putchar('\n');
+			}
+			if (p->short_name) {
+				printf("  -%c", p->short_name);
+				if (p->type != WESTON_OPTION_BOOLEAN)
+					printf("VALUE");
+				putchar('\n');
+			}
+		}
+		return 1;
+	}
+
+	if (!log_redraw && !log_resize && !log_focus && !log_key &&
+	    !log_button && !log_axis && !log_motion)
+	  log_redraw = log_resize = log_focus = log_key =
+	    log_button = log_axis = log_motion = true;
+
+	arka_dvb_init();
+
+	/* call libArka.so related interfaces */
+	int err;
+	err = pthread_create(&arka_thread_tid, NULL, &arka_thread, NULL);
+	if (err != 0) {
+		fprintf(stderr, "failed to create arka thread: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	/* Connect to the display and have the arguments parsed */
+
+	d = display_create(&argc, argv);
+	if (d == NULL) {
+		fprintf(stderr, "failed to create display: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	/* Create new arkadvb window */
+	e = arkadvb_create(d);
+	if (e == NULL) {
+		fprintf(stderr, "failed to create arkadvb: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	display_run(d);
+
+	/* Release resources */
+	arkadvb_destroy(e);
+	display_destroy(d);
+
+	pthread_join(arka_thread_tid, NULL);
+
+	return 0;
+}
diff --git a/clients/meson.build b/clients/meson.build
index 362f7fe..4cadd61 100644
--- a/clients/meson.build
+++ b/clients/meson.build
@@ -285,6 +285,9 @@
 		'deps': [ 'pangocairo', 'gobject-2.0' ]
 	},
 	{ 'basename': 'eventdemo' },
+	{
+	  'basename': 'arkadvb',
+	},
 	{ 'basename': 'flower' },
 	{
 		'basename': 'fullscreen',
@@ -327,6 +330,7 @@
 	{ 'basename': 'transformed' },
 ]
 
+lib_arka_dep = declare_dependency(link_args : ['-lpthread', '-ldl'])
 if get_option('demo-clients')
 	foreach t : demo_clients
 		t_name = 'weston-' + t.get('basename')
@@ -339,6 +343,9 @@
 			endif
 			t_deps += dep
 		endforeach
+		if t.get('basename') == 'arkadvb'
+			t_deps += lib_arka_dep
+		endif
 
 		executable(
 			t_name, t_srcs,
diff --git a/clients/simple-dmabuf-egl.c b/clients/simple-dmabuf-egl.c
index 33df4cf..c490288 100644
--- a/clients/simple-dmabuf-egl.c
+++ b/clients/simple-dmabuf-egl.c
@@ -1211,6 +1211,7 @@
 		goto error;
 	}
 
+#ifdef HAVE_GBM_MODIFIERS
 	if (weston_check_egl_extension(egl_extensions,
 				       "EGL_EXT_image_dma_buf_import_modifiers")) {
 		display->egl.has_dma_buf_import_modifiers = true;
@@ -1218,6 +1219,7 @@
 			(void *) eglGetProcAddress("eglQueryDmaBufModifiersEXT");
 		assert(display->egl.query_dma_buf_modifiers);
 	}
+#endif
 
 	display->egl.create_image =
 		(void *) eglGetProcAddress("eglCreateImageKHR");
diff --git a/clients/window.c b/clients/window.c
index a0d988f..81fc7af 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -392,6 +392,9 @@
 	uint32_t repeat_key;
 	uint32_t repeat_time;
 	int seat_version;
+
+	bool pointer_hidden;
+	uint32_t pointer_last_motion_time;
 };
 
 struct output {
@@ -2748,11 +2751,13 @@
 	input->pointer_focus = NULL;
 	input->current_cursor = CURSOR_UNSET;
 	cancel_pointer_image_update(input);
-	wl_surface_destroy(input->pointer_surface);
-	input->pointer_surface = NULL;
-	if (input->cursor_frame_cb) {
-		wl_callback_destroy(input->cursor_frame_cb);
-		input->cursor_frame_cb = NULL;
+	if (input->pointer_surface) {
+		wl_surface_destroy(input->pointer_surface);
+		input->pointer_surface = NULL;
+		if (input->cursor_frame_cb) {
+			wl_callback_destroy(input->cursor_frame_cb);
+			input->cursor_frame_cb = NULL;
+		}
 	}
 }
 
@@ -2846,6 +2851,8 @@
 	} else
 		cursor = CURSOR_LEFT_PTR;
 
+	input->pointer_last_motion_time = time;
+
 	input_set_pointer_image(input, cursor);
 }
 
@@ -3886,6 +3893,18 @@
 	wl_surface_commit(input->pointer_surface);
 }
 
+static bool
+hide_pointer_surface_needed(struct input* input) {
+	uint32_t duration;
+	if (input->pointer_last_motion_time == 0) {
+		//For remote with mouse support but not use motion
+		input->pointer_hidden = true;
+	} else {
+		input->pointer_hidden = false;
+	}
+	return input->pointer_hidden;
+}
+
 static void
 pointer_surface_frame_callback(void *data, struct wl_callback *callback,
 			       uint32_t time)
@@ -3911,6 +3930,9 @@
 	if (input_set_pointer_special(input))
 		return;
 
+	if (hide_pointer_surface_needed(input))
+		return;
+
 	cursor = input->display->cursors[input->current_cursor];
 	if (!cursor)
 		return;
@@ -5907,6 +5929,8 @@
 	input->pointer_focus = NULL;
 	input->keyboard_focus = NULL;
 	input->seat_version = seat_version;
+	input->pointer_hidden = true;
+	input->pointer_last_motion_time = 0;
 
 	wl_list_init(&input->touch_point_list);
 	wl_list_insert(d->input_list.prev, &input->link);
diff --git a/compositor/main.c b/compositor/main.c
index 63dba7f..4ddc11a 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -129,6 +129,7 @@
 	bool use_color_manager;
 };
 
+#include "../aml-weston/aml-main.c"
 static FILE *weston_logfile = NULL;
 static struct weston_log_scope *log_scope;
 static struct weston_log_scope *protocol_scope;
@@ -2150,9 +2151,11 @@
 			;
 
 		/* No heads left to undo and failed to enable. */
-		if (undo->heads[undo->n] == NULL)
+		if (undo->heads[undo->n] == NULL) {
+			weston_log("%s, L%d, No heads left to undo and failed to enablen",
+				__FUNCTION__, __LINE__);
 			return -1;
-
+		}
 		assert(failed->n < ARRAY_LENGTH(failed->heads));
 
 		/* undo one head */
@@ -2643,6 +2646,7 @@
 	};
 
 	parse_options(options, ARRAY_LENGTH(options), argc, argv);
+	weston_config_fixed_UIsize(wc, &config);
 
 	section = weston_config_get_section(wc, "core", NULL, NULL);
 	weston_config_section_get_string(section,
@@ -2659,7 +2663,7 @@
 	config.base.struct_size = sizeof(struct weston_drm_backend_config);
 	config.configure_device = configure_input_device;
 
-	wet->heads_changed_listener.notify = drm_heads_changed;
+	wet->heads_changed_listener.notify = drm_heads_changed_aml;
 	weston_compositor_add_heads_changed_listener(c,
 						&wet->heads_changed_listener);
 
diff --git a/compositor/meson.build b/compositor/meson.build
index 8a54ea9..7fc67c0 100644
--- a/compositor/meson.build
+++ b/compositor/meson.build
@@ -176,6 +176,9 @@
 	env_modmap += 'systemd-notify.so=@0@;'.format(plugin_systemd_notify.full_path())
 endif
 
+config_h.set('AML_MAX_OUTPUT_PIPLINE', get_option('WESTON_MAX_OUTPUT_PIPLINE'))
+config_h.set('HAVE_GBM_MODIFIERS', get_option('WESTON_HAVE_GBM_MODIFIERS'))
+
 weston_ini_config = configuration_data()
 weston_ini_config.set('bindir', dir_bin)
 weston_ini_config.set('libexecdir', dir_libexec)
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 4ca7897..9ade17a 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -1942,7 +1942,7 @@
 }
 
 static void
-weston_view_set_initial_position(struct weston_view *view,
+weston_view_set_initial_position(struct shell_surface *shsurf,
 				 struct desktop_shell *shell);
 
 static void
@@ -1960,7 +1960,7 @@
 		weston_view_set_position(shsurf->view,
 					 shsurf->saved_x, shsurf->saved_y);
 	else
-		weston_view_set_initial_position(shsurf->view, shsurf->shell);
+		weston_view_set_initial_position(shsurf, shsurf->shell);
 	shsurf->saved_position_valid = false;
 
 	if (shsurf->saved_rotation_valid) {
@@ -1983,7 +1983,7 @@
 		weston_view_set_position(shsurf->view,
 					 shsurf->saved_x, shsurf->saved_y);
 	else
-		weston_view_set_initial_position(shsurf->view, shsurf->shell);
+		weston_view_set_initial_position(shsurf, shsurf->shell);
 	shsurf->saved_position_valid = false;
 
 	if (shsurf->saved_rotation_valid) {
@@ -2439,7 +2439,7 @@
 	} else if (shsurf->xwayland.is_set) {
 		set_position_from_xwayland(shsurf);
 	} else {
-		weston_view_set_initial_position(shsurf->view, shell);
+		weston_view_set_initial_position(shsurf, shell);
 	}
 
 	/* Surface stacking order, see also activate(). */
@@ -2977,6 +2977,7 @@
 	wl_list_for_each_safe(view, next, &surface->views, surface_link)
 		weston_view_destroy(view);
 	view = weston_view_create(surface);
+	weston_view_opacity(view, 0.0);
 
 	surface->committed = background_committed;
 	surface->committed_private = shell;
@@ -4181,10 +4182,11 @@
 }
 
 static void
-weston_view_set_initial_position(struct weston_view *view,
+weston_view_set_initial_position(struct shell_surface *shsurf,
 				 struct desktop_shell *shell)
 {
 	struct weston_compositor *compositor = shell->compositor;
+	struct weston_view *view = shsurf->view;
 	int ix = 0, iy = 0;
 	int32_t range_x, range_y;
 	int32_t x, y;
@@ -4207,10 +4209,14 @@
 		}
 	}
 
-	wl_list_for_each(output, &compositor->output_list, link) {
-		if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
-			target_output = output;
-			break;
+	if (shsurf->fullscreen_output != NULL)
+		target_output = shsurf->fullscreen_output;
+	else{
+		wl_list_for_each(output, &compositor->output_list, link) {
+			if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
+				target_output = output;
+				break;
+			}
 		}
 	}
 
@@ -4717,6 +4723,8 @@
 		x = first_output->x + first_output->width / 4;
 		y = first_output->y + first_output->height / 4;
 
+		x = 0.0; // change default position to (0, 0) if not visible
+		y = 0.0;
 		weston_view_set_position(view, x, y);
 	} else {
 		weston_view_geometry_dirty(view);
diff --git a/include/libweston/backend-drm.h b/include/libweston/backend-drm.h
index af2da4a..27c1da9 100644
--- a/include/libweston/backend-drm.h
+++ b/include/libweston/backend-drm.h
@@ -37,6 +37,9 @@
 
 #define WESTON_DRM_BACKEND_CONFIG_VERSION 4
 
+//This patch enable MESON_DRM_FIX_UI_SIZE by default
+#define MESON_DRM_FIX_UI_SIZE 1
+
 struct libinput_device;
 
 enum weston_drm_backend_output_mode {
@@ -223,6 +226,14 @@
 
 	/** Use shadow buffer if using Pixman-renderer. */
 	bool use_pixman_shadow;
+
+#ifdef MESON_DRM_FIX_UI_SIZE
+	/** Set the logic window size
+	 * the current_mode 's w/h will not equal real display size any more
+	 * after enable fixed ui size.  */
+	struct weston_size  fixed_ui_size;
+#endif
+
 };
 
 #ifdef  __cplusplus
diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h
index d99dc76..db2fe01 100644
--- a/include/libweston/libweston.h
+++ b/include/libweston/libweston.h
@@ -43,6 +43,8 @@
 
 #include <libweston/matrix.h>
 #include <libweston/zalloc.h>
+#define MESON_VIDEO_PLAN_SUPPORT 1
+#define SURFACE_QUEUE_CAPACITY 10
 
 struct weston_geometry {
 	int32_t x, y;
@@ -933,6 +935,7 @@
 	pixman_region32_t clip;
 	int32_t x, y;
 	struct wl_list link;
+	bool keep_last_frame;
 };
 
 struct weston_drm_format_array;
@@ -1111,6 +1114,8 @@
 	struct wl_list touch_binding_list;
 	struct wl_list axis_binding_list;
 	struct wl_list debug_binding_list;
+	struct wl_list video_surface_list;
+
 
 	uint32_t state;
 	struct wl_event_source *idle_source;
@@ -1183,7 +1188,18 @@
 	struct weston_log_scope *debug_scene;
 	struct weston_log_scope *timeline;
 
+#ifdef ENABLE_DRM_HELP
+	FILE* aml_logfile;
+	bool aml_log_enable;
+	int aml_log_nframes;
+	bool aml_log_start;
+#endif
+	bool use_gbm_modifiers;
+
 	struct content_protection *content_protection;
+	struct weston_surface* last_keyboard_focus;
+	int video_surface_count;
+	bool enable_video_debug;
 };
 
 struct weston_buffer {
@@ -1199,6 +1215,8 @@
 	uint32_t busy_count;
 	int y_inverted;
 	void *backend_private;
+	uint64_t pts;
+	bool commit_fail;
 };
 
 struct weston_buffer_reference {
@@ -1349,6 +1367,9 @@
 		struct weston_matrix inverse;
 
 		struct weston_transform position; /* matrix from x, y */
+#ifdef MESON_VIDEO_PLAN_SUPPORT
+		pixman_region32_t transparent;
+#endif
 	} transform;
 
 	/*
@@ -1549,6 +1570,26 @@
 	enum weston_hdcp_protection desired_protection;
 	enum weston_hdcp_protection current_protection;
 	enum weston_surface_protection_mode protection_mode;
+
+#if MESON_VIDEO_PLAN_SUPPORT
+	/* use this flag to mark video surface of amlogic
+	 * which surface mark as video surface need full fit with:
+	 *  1. is dmabuffer which need dri, for avoid memory/bus bandwidth increase by buffer.
+	 *  2. is YUV format. (for amlogic video plane it below primary plane (zpos can't effect for this situation)
+	 */
+	bool is_video_surface;
+	//	client will assign video path for current video surface
+	int video_plane;
+
+#endif
+	struct wl_list link;
+	int queue_size;
+	int queue_capacity;
+	void* commit_queue;
+	bool keep_last_frame;
+	int frameN;
+	uint64_t commit_time;
+	struct weston_plane* plane;
 };
 
 struct weston_subsurface {
@@ -1758,6 +1799,12 @@
 struct weston_surface *
 weston_surface_create(struct weston_compositor *compositor);
 
+void
+weston_release_stranded_buffers();
+
+void
+weston_view_opacity(struct weston_view *view, float opacity);
+
 struct weston_view *
 weston_view_create(struct weston_surface *surface);
 
diff --git a/libweston/backend-drm/drm-gbm.c b/libweston/backend-drm/drm-gbm.c
index d0a4c6c..f4156dd 100644
--- a/libweston/backend-drm/drm-gbm.c
+++ b/libweston/backend-drm/drm-gbm.c
@@ -196,13 +196,15 @@
 	}
 
 #ifdef HAVE_GBM_MODIFIERS
-	if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
-		modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
-		output->gbm_surface =
-			gbm_surface_create_with_modifiers(gbm,
-							  mode->width, mode->height,
-							  output->gbm_format,
-							  modifiers, num_modifiers);
+	if (output->backend && output->backend->compositor->use_gbm_modifiers) {
+		if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
+			modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
+			output->gbm_surface =
+				gbm_surface_create_with_modifiers(gbm,
+								  mode->width, mode->height,
+								  output->gbm_format,
+								  modifiers, num_modifiers);
+		}
 	}
 #endif
 
@@ -294,8 +296,12 @@
 		return NULL;
 	}
 
+#if MESON_VIDEO_PLAN_SUPPORT
+	ret = drm_fb_get_from_bo(bo, b, false, BUFFER_GBM_SURFACE);
+#else
 	/* The renderer always produces an opaque image. */
 	ret = drm_fb_get_from_bo(bo, b, true, BUFFER_GBM_SURFACE);
+#endif
 	if (!ret) {
 		weston_log("failed to get drm_fb for bo\n");
 		gbm_surface_release_buffer(output->gbm_surface, bo);
diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h
index 55e9414..6cb1d5a 100644
--- a/libweston/backend-drm/drm-internal.h
+++ b/libweston/backend-drm/drm-internal.h
@@ -310,6 +310,17 @@
 	bool fb_modifiers;
 
 	struct weston_log_scope *debug;
+
+#ifdef MESON_DRM_FIX_UI_SIZE
+	/** Set the logic window size
+	 * the current_mode 's w/h will not equal real display mode size any more
+	 * after enable fixed ui size.	*/
+	struct weston_size	fixed_ui_size;
+#endif
+#ifdef BUILD_AML_TV
+	int vdin_detect_fd;
+#endif
+	bool allow_modeset;
 };
 
 struct drm_mode {
@@ -350,6 +361,7 @@
 
 	/* Used by dumb fbs */
 	void *map;
+	struct drm_plane *plane;
 };
 
 struct drm_buffer_fb {
@@ -478,6 +490,12 @@
 
 	struct wl_list link;
 
+	bool is_video_plane;
+	int video_plane;
+	bool keep_last_frame;
+	uint32_t last_fb_id;
+	struct drm_crtc *crtc;
+
 	struct weston_drm_format_array formats;
 };
 
@@ -527,6 +545,8 @@
 
 	/* Holds the properties for the CRTC */
 	struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
+	bool output_change;
+	struct drm_output *disable_output;
 };
 
 struct drm_output {
@@ -571,8 +591,17 @@
 	struct wl_event_source *pageflip_timer;
 
 	bool virtual;
+	int video_plane_count;
 
 	submit_frame_cb virtual_submit_frame;
+
+#ifdef MESON_DRM_FIX_UI_SIZE
+	bool current_mode_need_restore;
+
+	/* the real display mode size will saved out of the current mode */
+	struct weston_size display_size;
+#endif
+
 };
 
 static inline struct drm_head *
@@ -593,6 +622,12 @@
 	return container_of(base->backend, struct drm_backend, base);
 }
 
+static inline struct drm_plane *
+to_drm_plane(struct weston_plane *base)
+{
+	return container_of(base, struct drm_plane, base);
+}
+
 static inline struct drm_mode *
 to_drm_mode(struct weston_mode *base)
 {
@@ -639,6 +674,8 @@
 
 	return true;
 }
+struct weston_plane *
+drm_get_weston_plane(struct drm_backend *backend, struct drm_plane* drm_plane);
 
 int
 drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode);
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
index 4e408cb..9c90110 100644
--- a/libweston/backend-drm/drm.c
+++ b/libweston/backend-drm/drm.c
@@ -66,6 +66,8 @@
 #include "linux-dmabuf-unstable-v1-server-protocol.h"
 #include "linux-explicit-synchronization.h"
 
+#include "aml-weston/aml-backend.h"
+
 static const char default_seat[] = "seat0";
 
 static void
@@ -183,9 +185,10 @@
 		return false;
 
 	/* The plane is still active on another output. */
-	if (plane->state_cur->output && plane->state_cur->output != output)
-		return false;
-
+	if (plane->state_cur->output && plane->state_cur->output != output) {
+		//plane->state_cur->output = output;
+		//return false;
+	}
 	/* Check whether the plane can be used with this CRTC; possible_crtcs
 	 * is a bitmask of CRTC indices (pipe), rather than CRTC object ID. */
 	return !!(plane->possible_crtcs & (1 << output->crtc->pipe));
@@ -404,6 +407,8 @@
 	scanout_state->dest_w = output->base.current_mode->width;
 	scanout_state->dest_h = output->base.current_mode->height;
 
+	drm_output_render_aml_config(output, scanout_state);
+
 	pixman_region32_subtract(&c->primary_plane.damage,
 				 &c->primary_plane.damage, damage);
 
@@ -661,6 +666,9 @@
 
 	drm_debug(b, "[repaint] flushed pending_state %p\n", pending_state);
 	b->repaint_data = NULL;
+#ifdef ENABLE_DRM_HELP
+	help_do_repaint_cycle_completed();
+#endif
 
 	return (ret == -EACCES) ? -1 : 0;
 }
@@ -705,10 +713,14 @@
 
 	output->base.current_mode->flags = 0;
 
+	drm_switch_mode_aml_config_ui_size(output, output_base, drm_mode);
+
 	output->base.current_mode = &drm_mode->base;
 	output->base.current_mode->flags =
 		WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
 
+	drm_switch_mode_aml_config_help(output, output_base, drm_mode);
+
 	/* XXX: This drops our current buffer too early, before we've started
 	 *      displaying it. Ideally this should be much more atomic and
 	 *      integrated with a full repaint cycle, rather than doing a
@@ -717,6 +729,12 @@
 	 */
 	b->state_invalid = true;
 
+	b->allow_modeset = true;
+#ifdef MESON_DRM_FIX_UI_SIZE
+	// fixed ui mode needn't reset egl.
+	return 0;
+#endif
+
 	if (b->use_pixman) {
 		drm_output_fini_pixman(output);
 		if (drm_output_init_pixman(output, b) < 0) {
@@ -917,9 +935,9 @@
 			strerror(errno));
 		return;
 	}
+	for (i = kplane_res->count_planes; i >0; i--) {
+		kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i-1]);
 
-	for (i = 0; i < kplane_res->count_planes; i++) {
-		kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]);
 		if (!kplane)
 			continue;
 
@@ -1812,6 +1830,7 @@
 		goto err_planes;
 	}
 
+	drm_enable_aml_output_config(output, base, b);
 	drm_output_init_backlight(output);
 
 	output->base.start_repaint_loop = drm_output_start_repaint_loop;
@@ -1890,13 +1909,7 @@
 	struct drm_output *output = to_drm_output(base);
 
 	assert(!output->virtual);
-
-	if (output->page_flip_pending || output->atomic_complete_pending) {
-		output->disable_pending = true;
-		return -1;
-	}
-
-	weston_log("Disabling output %s\n", output->base.name);
+	drm_output_disable_aml(output, base);
 
 	if (output->base.enabled)
 		drm_output_deinit(&output->base);
@@ -2023,6 +2036,8 @@
 	if (drm_connector_update_properties(connector) < 0)
 		return -1;
 
+	drm_update_helper_connector(connector, conn);
+
 	if (connector->conn)
 		drmModeFreeConnector(connector->conn);
 	connector->conn = conn;
@@ -2167,6 +2182,7 @@
 
 	weston_compositor_add_head(backend->compositor, &head->base);
 	drm_head_log_info(head, "found");
+	drm_append_helper_connector(head);
 
 	return 0;
 
@@ -2181,6 +2197,7 @@
 static void
 drm_head_destroy(struct drm_head *head)
 {
+	drm_delete_helper_connector(head);
 	weston_head_release(&head->base);
 
 	drm_connector_fini(&head->connector);
@@ -2234,6 +2251,7 @@
 
 	output->state_cur = drm_output_state_alloc(output, NULL);
 
+	drm_init_aml_output_config(compositor, output);
 	weston_compositor_add_pending_output(&output->base, b->compositor);
 
 	return &output->base;
@@ -2544,6 +2562,11 @@
 			drm_backend_update_connectors(b, event);
 	}
 
+#ifdef BUILD_AML_TV
+	drm_backend_afr_update(b, udev_event_frame_rate_hint(event),
+			udev_event_is_vdin_event(event));
+#endif
+
 	udev_device_unref(event);
 
 	return 1;
@@ -2557,6 +2580,10 @@
 	struct drm_crtc *crtc, *crtc_tmp;
 	struct drm_writeback *writeback, *writeback_tmp;
 
+#ifdef ENABLE_DRM_HELP
+	stop_help_worker();
+#endif
+
 	udev_input_destroy(&b->input);
 
 	wl_event_source_remove(b->udev_drm_source);
@@ -2609,9 +2636,11 @@
 		weston_compositor_wake(compositor);
 		weston_compositor_damage_all(compositor);
 		b->state_invalid = true;
+		b->allow_modeset = true;
 		udev_input_enable(&b->input);
 	} else {
 		weston_log("deactivating session\n");
+		drm_change_to_dummy_mode(b->compositor);
 		udev_input_disable(&b->input);
 
 		weston_compositor_offscreen(compositor);
@@ -3003,8 +3032,13 @@
 		return NULL;
 
 	b->state_invalid = true;
+	b->allow_modeset = true;
 	b->drm.fd = -1;
 
+#ifdef BUILD_AML_TV
+	b->vdin_detect_fd = -1;
+#endif
+
 	b->compositor = compositor;
 	b->use_pixman = config->use_pixman;
 	b->pageflip_timeout = config->pageflip_timeout;
@@ -3038,6 +3072,8 @@
 	b->session_listener.notify = session_notify;
 	wl_signal_add(&compositor->session_signal, &b->session_listener);
 
+	drm_config_fixed_UIsize(b, config);
+
 	if (config->specific_device)
 		drm_device = open_specific_drm_device(b, config->specific_device);
 	else
@@ -3072,6 +3108,7 @@
 	b->base.device_changed = drm_device_changed;
 	b->base.can_scanout_dmabuf = drm_can_scanout_dmabuf;
 
+	drm_add_aml_callback(b);
 	weston_setup_vt_switch_bindings(compositor);
 
 	res = drmModeGetResources(b->drm.fd);
@@ -3096,6 +3133,11 @@
 		goto err_sprite;
 	}
 
+#ifdef ENABLE_DRM_HELP
+	weston_log("drm start_help_worker \n");
+	start_help_worker(b->drm.fd, b->atomic_modeset);
+#endif
+
 	wl_list_init(&b->writeback_connector_list);
 	if (drm_backend_discover_connectors(b, drm_device, res) < 0) {
 		weston_log("Failed to create heads for %s\n", b->drm.filename);
@@ -3124,6 +3166,13 @@
 	}
 	udev_monitor_filter_add_match_subsystem_devtype(b->udev_monitor,
 							"drm", NULL);
+#ifdef BUILD_AML_TV
+	udev_monitor_filter_add_match_subsystem_devtype(b->udev_monitor,
+							"vdin", NULL);
+	udev_monitor_filter_add_match_subsystem_devtype(b->udev_monitor,
+							"framerate_adapter", NULL);
+#endif
+
 	b->udev_drm_source =
 		wl_event_loop_add_fd(loop,
 				     udev_monitor_get_fd(b->udev_monitor),
@@ -3196,6 +3245,9 @@
 		weston_log("Failed to register virtual output API.\n");
 		goto err_udev_monitor;
 	}
+#ifdef ENABLE_DRM_HELP
+	help_set_printinfo_function(compositor, weston_print_info);
+#endif
 
 	return b;
 
diff --git a/libweston/backend-drm/fb.c b/libweston/backend-drm/fb.c
index ffe2cc5..01b1ee1 100644
--- a/libweston/backend-drm/fb.c
+++ b/libweston/backend-drm/fb.c
@@ -43,12 +43,12 @@
 #include "drm-internal.h"
 #include "linux-dmabuf.h"
 
+#include "aml-weston/aml-backend.h"
+
 static void
 drm_fb_destroy(struct drm_fb *fb)
 {
-	if (fb->fb_id != 0)
-		drmModeRmFB(fb->fd, fb->fb_id);
-	free(fb);
+	drm_fb_destroy_aml(fb);
 }
 
 static void
@@ -360,12 +360,19 @@
 	fb->size = 0;
 
 #ifdef HAVE_GBM_MODIFIERS
-	fb->modifier = gbm_bo_get_modifier(bo);
-	fb->num_planes = gbm_bo_get_plane_count(bo);
-	for (i = 0; i < fb->num_planes; i++) {
-		fb->strides[i] = gbm_bo_get_stride_for_plane(bo, i);
-		fb->handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
-		fb->offsets[i] = gbm_bo_get_offset(bo, i);
+	if (backend->compositor->use_gbm_modifiers) {
+		fb->modifier = gbm_bo_get_modifier(bo);
+		fb->num_planes = gbm_bo_get_plane_count(bo);
+		for (i = 0; i < fb->num_planes; i++) {
+			fb->strides[i] = gbm_bo_get_stride_for_plane(bo, i);
+			fb->handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
+			fb->offsets[i] = gbm_bo_get_offset(bo, i);
+		}
+	} else {
+		fb->num_planes = 1;
+		fb->strides[0] = gbm_bo_get_stride(bo);
+		fb->handles[0] = gbm_bo_get_handle(bo).u32;
+		fb->modifier = DRM_FORMAT_MOD_INVALID;
 	}
 #else
 	fb->num_planes = 1;
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
index 780d007..9ee50ab 100644
--- a/libweston/backend-drm/kms.c
+++ b/libweston/backend-drm/kms.c
@@ -42,6 +42,8 @@
 #include "pixel-formats.h"
 #include "presentation-time-server-protocol.h"
 
+#include "aml-weston/aml-backend.h"
+
 struct drm_property_enum_info plane_type_enums[] = {
 	[WDRM_PLANE_TYPE_PRIMARY] = {
 		.name = "Primary",
@@ -484,6 +486,10 @@
 
 		if (fmt->modifiers.size == 0)
 			weston_drm_format_array_remove_latest_format(&plane->formats);
+
+		if (fmt->format == DRM_FORMAT_NV12 ||
+			fmt->format == DRM_FORMAT_NV21)
+			plane->is_video_plane = true;
 	}
 
 out:
@@ -982,9 +988,13 @@
 	wl_list_for_each(plane_state, &state->plane_list, link) {
 		struct drm_plane *plane = plane_state->plane;
 		const struct pixel_format_info *pinfo = NULL;
+		if ( !plane_state->fb )
+			continue;
 
 		ret |= plane_add_prop(req, plane, WDRM_PLANE_FB_ID,
 				      plane_state->fb ? plane_state->fb->fb_id : 0);
+
+		drm_update_video_plane_info(plane_state, flags);
 		ret |= plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID,
 				      plane_state->fb ? crtc->crtc_id : 0);
 		ret |= plane_add_prop(req, plane, WDRM_PLANE_SRC_X,
@@ -1019,13 +1029,16 @@
 					      WDRM_PLANE_IN_FENCE_FD,
 					      plane_state->in_fence_fd);
 		}
-
+#ifdef USE_DEFAULT_Z_ORDER
+		//use drm default palne z-order
+#else
 		/* do note, that 'invented' zpos values are set as immutable */
 		if (plane_state->zpos != DRM_PLANE_ZPOS_INVALID_PLANE &&
 		    plane_state->plane->zpos_min != plane_state->plane->zpos_max)
 			ret |= plane_add_prop(req, plane,
 					      WDRM_PLANE_ZPOS,
 					      plane_state->zpos);
+#endif
 
 		if (ret != 0) {
 			weston_log("couldn't set plane state\n");
@@ -1079,6 +1092,8 @@
 		/* If we need to reset all our state (e.g. because we've
 		 * just started, or just been VT-switched in), explicitly
 		 * disable all the CRTCs and connectors we aren't using. */
+#if 0
+
 		wl_list_for_each(head_base,
 				 &b->compositor->head_list, compositor_link) {
 			struct drm_property_info *info;
@@ -1136,6 +1151,7 @@
 			ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 0);
 			ret |= crtc_add_prop(req, crtc, WDRM_CRTC_MODE_ID, 0);
 		}
+#endif
 
 		/* Disable all the planes; planes which are being used will
 		 * override this state in the output-state application. */
@@ -1146,7 +1162,8 @@
 			plane_add_prop(req, plane, WDRM_PLANE_FB_ID, 0);
 		}
 
-		flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
+		if (b->allow_modeset)
+			flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
 	}
 
 	wl_list_for_each(output_state, &pending_state->output_list, link) {
@@ -1161,10 +1178,15 @@
 		weston_log("atomic: couldn't compile atomic state\n");
 		goto out;
 	}
+#ifdef ENABLE_DRM_HELP
+	ret |= help_atomic_req_add_prop(req);
+#endif
 
 	ret = drmModeAtomicCommit(b->drm.fd, req, flags, b);
 	drm_debug(b, "[atomic] drmModeAtomicCommit\n");
 
+	drm_update_buffer_commit_result(ret, pending_state);
+
 	/* Test commits do not take ownership of the state; return
 	 * without freeing here. */
 	if (mode == DRM_STATE_TEST_ONLY) {
@@ -1184,6 +1206,9 @@
 
 	b->state_invalid = false;
 
+	if (b->allow_modeset)
+		b->allow_modeset = false;
+
 	assert(wl_list_empty(&pending_state->output_list));
 
 out:
@@ -1390,21 +1415,30 @@
 
 	output = crtc->output;
 
+	if (crtc->output_change) {
+		output = crtc->disable_output;
+	}
+
 	/* During the initial modeset, we can disable CRTCs which we don't
 	 * actually handle during normal operation; this will give us events
 	 * for unknown outputs. Ignore them. */
-	if (!output || !output->base.enabled)
+	if ( (!output || !output->base.enabled) && !crtc->output_change)
 		return;
 
 	drm_output_update_msc(output, frame);
 
-	drm_debug(b, "[atomic][CRTC:%u] flip processing started\n", crtc_id);
-	assert(b->atomic_modeset);
-	assert(output->atomic_complete_pending);
-	output->atomic_complete_pending = false;
+	drm_debug(b, "[atomic][CRTC:%u] flip processing started output_change:%d\n",
+		crtc_id,crtc->output_change );
+	if ( b->atomic_modeset && output->atomic_complete_pending) {
+		//assert(b->atomic_modeset);
+		//assert(output->atomic_complete_pending);
+		output->atomic_complete_pending = false;
+		drm_output_update_complete(output, flags, sec, usec);
+	}
 
-	drm_output_update_complete(output, flags, sec, usec);
+	crtc->output_change = false;
 	drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
+	atomic_flip_handler_time(b);
 }
 
 int
diff --git a/libweston/backend-drm/meson.build b/libweston/backend-drm/meson.build
index 23db912..27a3d8d 100644
--- a/libweston/backend-drm/meson.build
+++ b/libweston/backend-drm/meson.build
@@ -17,13 +17,20 @@
 	include_directories: include_directories('.')
 )
 
+dep_meson_display = dependency('libweston-drm-helper')
+config_h.set('ENABLE_DRM_HELP', '1')
 config_h.set('BUILD_DRM_COMPOSITOR', '1')
 
+if get_option('BUILD_AML_TV')
+        config_h.set('BUILD_AML_TV', '1')
+endif
+
 srcs_drm = [
 	'drm.c',
 	'fb.c',
 	'modes.c',
 	'kms.c',
+	'../../aml-weston/aml-backend.c',
 	'state-helpers.c',
 	'state-propose.c',
 	linux_dmabuf_unstable_v1_protocol_c,
@@ -38,7 +45,8 @@
 	dep_libdrm,
 	dep_libinput_backend,
 	dependency('libudev', version: '>= 136'),
-	dep_backlight
+	dep_backlight,
+	dep_meson_display
 ]
 
 if get_option('renderer-gl')
@@ -83,6 +91,8 @@
 	config_h.set('BUILD_DRM_VIRTUAL', '1')
 endif
 
+config_h.set('USE_DEFAULT_Z_ORDER', get_option('WESTON_USE_DEFAULT_Z_ORDER'))
+
 plugin_drm = shared_library(
 	'drm-backend',
 	srcs_drm,
diff --git a/libweston/backend-drm/modes.c b/libweston/backend-drm/modes.c
index a071375..e89061b 100644
--- a/libweston/backend-drm/modes.c
+++ b/libweston/backend-drm/modes.c
@@ -34,6 +34,9 @@
 
 #include "drm-internal.h"
 #include "shared/weston-drm-fourcc.h"
+#ifdef ENABLE_DRM_HELP
+#include "compositor-drm-help.h"
+#endif
 
 static const char *const aspect_ratio_as_string[] = {
 	[WESTON_MODE_PIC_AR_NONE] = "",
@@ -439,6 +442,18 @@
 		dm = to_drm_mode(m);
 
 		aspect_ratio = aspect_ratio_to_string(m->aspect_ratio);
+#ifdef MESON_DRM_FIX_UI_SIZE
+		if (m->flags & WL_OUTPUT_MODE_CURRENT)
+			weston_log_continue(STAMP_SPACE "%dx%d@%.1f%s%s%s, %.1f MHz(MESON_DRM_FIX_UI_SIZE)\n",
+				output->display_size.width, output->display_size.height, m->refresh / 1000.0,
+				aspect_ratio,
+				m->flags & WL_OUTPUT_MODE_PREFERRED ?
+				", preferred" : "",
+				m->flags & WL_OUTPUT_MODE_CURRENT ?
+				", current" : "",
+				dm->mode_info.clock / 1000.0);
+		else
+#endif
 		weston_log_continue(STAMP_SPACE "%dx%d@%.1f%s%s%s, %.1f MHz\n",
 				    m->width, m->height, m->refresh / 1000.0,
 				    aspect_ratio,
@@ -474,8 +489,16 @@
 	b = to_drm_backend(output->base.compositor);
 	target_aspect = target_mode->aspect_ratio;
 	src_aspect = output->base.current_mode->aspect_ratio;
-	if (output->base.current_mode->width == target_mode->width &&
+
+	if (
+#ifdef MESON_DRM_FIX_UI_SIZE
+	    output->display_size.width == target_mode->width &&
+	    output->display_size.height == target_mode->height &&
+#else
+	    output->base.current_mode->width == target_mode->width &&
 	    output->base.current_mode->height == target_mode->height &&
+#endif
+	    output->base.current_mode->flags == target_mode->flags &&
 	    (output->base.current_mode->refresh == target_mode->refresh ||
 	     target_mode->refresh == 0)) {
 		if (!b->aspect_ratio_supported || src_aspect == target_aspect)
@@ -486,7 +509,9 @@
 
 		src_aspect = mode->base.aspect_ratio;
 		if (mode->mode_info.hdisplay == target_mode->width &&
-		    mode->mode_info.vdisplay == target_mode->height) {
+		    mode->mode_info.vdisplay == target_mode->height &&
+		    ((mode->mode_info.flags & DRM_MODE_FLAG_INTERLACE) == (target_mode->flags & DRM_MODE_FLAG_INTERLACE))
+		    ) {
 			if (mode->base.refresh == target_mode->refresh ||
 			    target_mode->refresh == 0) {
 				if (!b->aspect_ratio_supported ||
@@ -809,5 +834,7 @@
 	output->base.native_mode = output->base.current_mode;
 	output->base.native_scale = output->base.current_scale;
 
+	drm_set_mode_update_aml_info(head, output, current);
+
 	return 0;
 }
diff --git a/libweston/backend-drm/state-helpers.c b/libweston/backend-drm/state-helpers.c
index 75a2a18..20c0034 100644
--- a/libweston/backend-drm/state-helpers.c
+++ b/libweston/backend-drm/state-helpers.c
@@ -34,6 +34,7 @@
 
 #include "drm-internal.h"
 #include "shared/weston-drm-fourcc.h"
+#include "aml-weston/aml-backend.h"
 
 /**
  * Allocate a new, empty, plane state.
@@ -223,12 +224,18 @@
 	state->dest_y = tbox.y1;
 	state->dest_w = tbox.x2 - tbox.x1;
 	state->dest_h = tbox.y2 - tbox.y1;
+
+	drm_update_aml_state_coords(output, state);
+
 	pixman_region32_fini(&dest_rect);
 
 	/* Now calculate the source rectangle, by finding the extents of the
 	 * view, and working backwards to source co-ordinates. */
 	pixman_region32_init(&src_rect);
-	pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
+	if (state->plane->is_video_plane)
+		src_rect = ev->transform.boundingbox;
+	else
+		pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
 				  &output->base.region);
 	box = pixman_region32_extents(&src_rect);
 	weston_view_from_global_float(ev, box->x1, box->y1, &sxf1, &syf1);
diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c
index 72e4db9..e5aca12 100644
--- a/libweston/backend-drm/state-propose.c
+++ b/libweston/backend-drm/state-propose.c
@@ -41,6 +41,7 @@
 #include "color.h"
 #include "linux-dmabuf.h"
 #include "presentation-time-server-protocol.h"
+#include "aml-weston/aml-backend.h"
 
 enum drm_output_propose_state_mode {
 	DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
@@ -421,8 +422,14 @@
 	}
 
 	if (state->dest_x != 0 || state->dest_y != 0 ||
+#ifdef MESON_DRM_FIX_UI_SIZE
+	    state->dest_w != (unsigned) output->display_size.width ||
+	    state->dest_h != (unsigned) output->display_size.height
+#else
 	    state->dest_w != (unsigned) output->base.current_mode->width ||
-	    state->dest_h != (unsigned) output->base.current_mode->height) {
+	    state->dest_h != (unsigned) output->base.current_mode->height
+#endif
+		) {
 		drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
 			     " invalid plane state\n", p_name, ev, p_name);
 		goto err;
@@ -484,12 +491,13 @@
 		scanout_has_view_assigned =
 			drm_output_check_plane_has_view_assigned(scanout_plane,
 								 state);
-
+#if 0
 		if (view_matches_entire_output && !scanout_has_view_assigned) {
 			availability = NO_PLANES_ACCEPTED;
 			goto out;
 		}
-
+#endif
+		drm_debug(b, "\t\t\t\t[overlay]  view %p WDRM_PLANE_TYPE_OVERLAY\n", ev);
 		ps = drm_output_prepare_overlay_view(plane, state, ev, mode,
 						     fb, zpos);
 		if (ps)
@@ -734,7 +742,15 @@
 
 		if (mode == DRM_OUTPUT_PROPOSE_STATE_MIXED) {
 			assert(scanout_state != NULL);
-			if (scanout_state->zpos >= plane->zpos_max) {
+#if MESON_VIDEO_PLAN_SUPPORT
+			/* we need transparent the region coverd by video,
+			 * so we can ignore zpos of scanout_state for video surface.
+			 */
+			if (!ev->surface->is_video_surface && scanout_state->zpos >= plane->zpos_max)
+#else
+			if (scanout_state->zpos >= plane->zpos_max)
+#endif
+			{
 				drm_debug(b, "\t\t\t\t[plane] not adding plane %d to "
 					     "candidate list: primary's zpos "
 					     "value (%"PRIu64") higher than "
@@ -797,6 +813,13 @@
 			     "from candidate list, type: %s\n",
 			     plane->plane_id, p_name);
 
+		if (drm_check_video_plane_destroy_zpos(b, ev, plane, p_name)) {
+			drm_output_destroy_zpos_plane(head_p_zpos);
+			continue;
+		}
+		drm_debug(b, "\t\t\t\t[plane] try view on plane %d \n",
+				plane->plane_id );
+
 		ps = drm_output_try_view_on_plane(plane, state, ev,
 						  mode, fb, zpos);
 		drm_output_destroy_zpos_plane(head_p_zpos);
@@ -812,6 +835,7 @@
 		drm_output_destroy_zpos_plane(p_zpos);
 
 	drm_fb_unref(fb);
+	drm_update_keep_frame_info(ev, fb, ps);
 	return ps;
 }
 
@@ -826,7 +850,7 @@
 	struct drm_output_state *state;
 	struct drm_plane_state *scanout_state = NULL;
 
-	pixman_region32_t renderer_region;
+	pixman_region32_t renderer_region, video_cover_region;
 	pixman_region32_t occluded_region;
 
 	bool renderer_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY);
@@ -862,7 +886,7 @@
 			return NULL;
 		}
 
-		if (scanout_fb->width != output_base->current_mode->width ||
+		/*if (scanout_fb->width != output_base->current_mode->width ||
 		    scanout_fb->height != output_base->current_mode->height) {
 			drm_debug(b, "\t\t[state] cannot propose mixed mode "
 			             "for output %s (%lu): previous fb has "
@@ -871,7 +895,7 @@
 				  (unsigned long) output->base.id);
 			drm_output_state_free(state);
 			return NULL;
-		}
+		}*/
 
 		scanout_state = drm_plane_state_duplicate(state,
 							  plane->state_cur);
@@ -896,6 +920,7 @@
 	 */
 	pixman_region32_init(&renderer_region);
 	pixman_region32_init(&occluded_region);
+	pixman_region32_init(&video_cover_region);
 
 	wl_list_for_each(pnode, &output->base.paint_node_z_order_list,
 			 z_order_link) {
@@ -906,6 +931,9 @@
 		pixman_region32_t surface_overlap;
 		bool totally_occluded = false;
 
+#if MESON_VIDEO_PLAN_SUPPORT
+		pixman_region32_init(&ev->clip);
+#endif
 		drm_debug(b, "\t\t\t[view] evaluating view %p for "
 		             "output %s (%lu)\n",
 		          ev, output->base.name,
@@ -940,14 +968,20 @@
 		 * view; includes the case where occluded_region covers
 		 * the entire output */
 		totally_occluded = !pixman_region32_not_empty(&surface_overlap);
+	if (!ev->surface->is_video_surface) {
 		if (totally_occluded) {
+#if MESON_VIDEO_PLAN_SUPPORT
+			// if occluded , we need set the clip, to make sure it will not draw when glrenderer.
+			// to avoid the video plane coverd by this  view.
+			pixman_region32_union(&ev->clip, &ev->clip, &clipped_view);
+#endif
 			drm_debug(b, "\t\t\t\t[view] ignoring view %p "
 			             "(occluded on our output)\n", ev);
 			pixman_region32_fini(&surface_overlap);
 			pixman_region32_fini(&clipped_view);
 			continue;
 		}
-
+	}
 		/* We only assign planes to views which are exclusively present
 		 * on our output. */
 		if (ev->output_mask != (1u << output->base.id)) {
@@ -975,10 +1009,39 @@
 		pixman_region32_intersect(&surface_overlap, &renderer_region,
 					  &clipped_view);
 		if (pixman_region32_not_empty(&surface_overlap)) {
+#if MESON_VIDEO_PLAN_SUPPORT
+			/* video overly zpos range on meson is huge (0-255) , but
+			 * big then primary plane zpos(65-128) part is not effect, the video
+			 * overly always below primary plane So if video view (NV21/NV21
+			 * format) occluded by renderer views (put into primary plane),
+			 * no need force to gpu composition.
+			 */
+			if (!ev->surface->is_video_surface) {
+				drm_debug(b, "\t\t\t\t[view]none-video surface not assigning view %p to plane "
+						"(occluded by renderer views)\n", ev);
+				force_renderer = true;
+			}
+#else
 			drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane "
 			             "(occluded by renderer views)\n", ev);
 			force_renderer = true;
+#endif
 		}
+
+#if MESON_VIDEO_PLAN_SUPPORT
+		pixman_region32_intersect(&surface_overlap, &video_cover_region,
+				&clipped_view);
+		if (pixman_region32_not_empty(&surface_overlap)) {
+			if (!ev->surface->is_video_surface) {
+				drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane "
+						"(block the video views)\n", ev);
+				force_renderer = true;
+				pixman_region32_copy(&ev->transform.transparent, &surface_overlap);
+			}
+		} else {
+			pixman_region32_clear(&ev->transform.transparent);
+		}
+#endif
 		pixman_region32_fini(&surface_overlap);
 
 		/* In case of enforced mode of content-protection do not
@@ -1011,6 +1074,13 @@
 				FAILURE_REASONS_FORCE_RENDERER;
 		}
 
+#if MESON_VIDEO_PLAN_SUPPORT
+		if (ps && ev->surface->is_video_surface) {
+			drm_debug(b, "meson set video cover region");
+			pixman_region32_copy(&video_cover_region, &clipped_view);
+		}
+#endif
+
 		if (ps) {
 			current_lowest_zpos = ps->zpos;
 			drm_debug(b, "\t\t\t[plane] next zpos to use %"PRIu64"\n",
@@ -1037,7 +1107,12 @@
 		 * entire clipped area if the whole view is known to be
 		 * opaque) does not necessarily occlude what's behind it, as
 		 * it could be alpha-blended. */
+#if MESON_VIDEO_PLAN_SUPPORT
+		// video layer need force to opaque
+		if (!weston_view_is_opaque(ev, &clipped_view) || ev->surface->is_video_surface)
+#else
 		if (!weston_view_is_opaque(ev, &clipped_view))
+#endif
 			pixman_region32_intersect(&clipped_view,
 						  &clipped_view,
 						  &ev->transform.opaque);
@@ -1050,6 +1125,7 @@
 
 	pixman_region32_fini(&renderer_region);
 	pixman_region32_fini(&occluded_region);
+	pixman_region32_fini(&video_cover_region);
 
 	/* In renderer-only mode, we can't test the state as we don't have a
 	 * renderer buffer yet. */
diff --git a/libweston/backend.h b/libweston/backend.h
index 3ae59a6..3939cff 100644
--- a/libweston/backend.h
+++ b/libweston/backend.h
@@ -107,6 +107,13 @@
 	 */
 	bool (*can_scanout_dmabuf)(struct weston_compositor *compositor,
 				   struct linux_dmabuf_buffer *buffer);
+
+	int (*print_output_status)(struct weston_compositor *compositor,
+			     void *repaint_data, FILE* fp);
+
+	int (*get_frame_time)(struct weston_output *output_base, uint64_t*frametime, uint64_t* refresh_interval);
+	void (*update_frame_rate)(struct weston_compositor *compositor, int frame_rate_value, int frame_rate_scale);
+	int (*close_video_plane)(struct weston_compositor *ec, struct weston_plane* plane);
 };
 
 /* weston_head */
@@ -253,4 +260,6 @@
 void
 notify_touch_calibrator_frame(struct weston_touch_device *device);
 
+void weston_debug_write_buffer_to_file(void* buffer, int buffer_size, char* name_in, FILE *msg_fp );
+
 #endif
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 66d4337..b90e02f 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -79,6 +79,7 @@
 
 #include "weston-log-internal.h"
 
+#include "../aml-weston/aml-compositor.c"
 /**
  * \defgroup head Head
  * \defgroup output Output
@@ -410,6 +411,9 @@
 	pixman_region32_init(&view->geometry.scissor);
 	pixman_region32_init(&view->transform.boundingbox);
 	view->transform.dirty = 1;
+#ifdef MESON_VIDEO_PLAN_SUPPORT
+	pixman_region32_init(&view->transform.transparent);
+#endif
 
 	return view;
 }
@@ -557,8 +561,6 @@
 	pixman_region32_fini(&state->damage_surface);
 	pixman_region32_fini(&state->damage_buffer);
 
-	if (state->buffer)
-		wl_list_remove(&state->buffer_destroy_listener.link);
 	state->buffer = NULL;
 
 	fd_clear(&state->acquire_fence_fd);
@@ -572,12 +574,12 @@
 	if (state->buffer == buffer)
 		return;
 
-	if (state->buffer)
-		wl_list_remove(&state->buffer_destroy_listener.link);
+	/*if (state->buffer)
+		wl_list_remove(&state->buffer_destroy_listener.link);*/
 	state->buffer = buffer;
-	if (state->buffer)
+	/*if (state->buffer)
 		wl_signal_add(&state->buffer->destroy_signal,
-			      &state->buffer_destroy_listener);
+			      &state->buffer_destroy_listener);*/
 }
 
 WL_EXPORT struct weston_surface *
@@ -626,6 +628,8 @@
 	surface->current_protection = WESTON_HDCP_DISABLE;
 	surface->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
 
+	weston_init_video_surface_info(surface);
+
 	return surface;
 }
 
@@ -2268,7 +2272,6 @@
 weston_view_destroy(struct weston_view *view)
 {
 	struct weston_paint_node *pnode, *pntmp;
-
 	weston_signal_emit_mutable(&view->destroy_signal, view);
 
 	assert(wl_list_empty(&view->geometry.child_list));
@@ -2289,6 +2292,9 @@
 	pixman_region32_fini(&view->geometry.scissor);
 	pixman_region32_fini(&view->transform.boundingbox);
 	pixman_region32_fini(&view->transform.opaque);
+#ifdef MESON_VIDEO_PLAN_SUPPORT
+	pixman_region32_fini(&view->transform.transparent);
+#endif
 
 	weston_view_set_transform_parent(view, NULL);
 	weston_view_set_output(view, NULL);
@@ -2301,6 +2307,7 @@
 WL_EXPORT void
 weston_surface_destroy(struct weston_surface *surface)
 {
+	weston_log("\n weston_surface_destroy :%p\n", surface);
 	struct wl_resource *cb, *next;
 	struct weston_view *ev, *nv;
 	struct weston_pointer_constraint *constraint, *next_constraint;
@@ -2348,7 +2355,9 @@
 
 	fd_clear(&surface->acquire_fence_fd);
 
+	weston_clear_video_surface_info(surface);
 	free(surface);
+	weston_log("\n weston_surface_destroy :%p end\n", surface);
 }
 
 static void
@@ -2380,6 +2389,7 @@
 	struct weston_buffer *buffer =
 		container_of(listener, struct weston_buffer, destroy_listener);
 
+	weston_log("\n weston_buffer_destroy_handler buffer:%p\n",buffer);
 	weston_signal_emit_mutable(&buffer->destroy_signal, buffer);
 	free(buffer);
 }
@@ -2430,7 +2440,7 @@
 		ref->buffer->busy_count--;
 		if (ref->buffer->busy_count == 0) {
 			assert(wl_resource_get_client(ref->buffer->resource));
-			wl_buffer_send_release(ref->buffer->resource);
+			buffer_send_release(ref);
 		}
 		wl_list_remove(&ref->destroy_listener.link);
 	}
@@ -2518,6 +2528,7 @@
 			weston_surface_unmap(surface);
 	}
 
+	weston_video_surface_attach(surface, buffer);
 	surface->compositor->renderer->attach(surface, buffer);
 
 	weston_surface_calculate_size_from_buffer(surface);
@@ -2588,7 +2599,11 @@
 	pixman_region32_union(&view->plane->damage,
 			      &view->plane->damage, &damage);
 	pixman_region32_fini(&damage);
+#if MESON_VIDEO_PLAN_SUPPORT
+	pixman_region32_union(&view->clip, &view->clip, opaque);
+#else
 	pixman_region32_copy(&view->clip, opaque);
+#endif
 	pixman_region32_union(opaque, opaque, &view->transform.opaque);
 }
 
@@ -2611,6 +2626,13 @@
 				 z_order_link) {
 			if (pnode->view->plane != plane)
 				continue;
+#if MESON_VIDEO_PLAN_SUPPORT
+			// meson platform video plane is below primary plane.(but the zpos may hight then primary plane.
+			// Avoid video plane region make the primary plane be occlude.
+
+			// We assume the overlay plane only have one surface, on weston just primary plane support glrender compositor.
+			if (!pnode->view->surface->is_video_surface)
+#endif
 
 			view_accumulate_damage(pnode->view, &opaque);
 		}
@@ -2951,7 +2973,12 @@
 	weston_compositor_repick(ec);
 
 	frame_time_msec = timespec_to_msec(&output->frame_time);
+	if (ec->enable_video_debug) {
+		struct timespec time;
 
+		weston_compositor_get_time(&time);
+		weston_log("%llu repaint send done\n", timespec_to_usec(&time));
+	}
 	wl_resource_for_each_safe(cb, cnext, &frame_callback_list) {
 		wl_callback_send_done(cb, frame_time_msec);
 		wl_resource_destroy(cb);
@@ -2988,19 +3015,24 @@
 		return ret;
 
 	msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
-	if (msec_to_repaint > 1)
+	if (msec_to_repaint > 1) {
+		weston_log("\n %s %d return ret:%d\n", __FUNCTION__,__LINE__,ret);
 		return ret;
+	}
 
 	/* If we're sleeping, drop the repaint machinery entirely; we will
 	 * explicitly repaint all outputs when we come back. */
 	if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
-	    compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
+		compositor->state == WESTON_COMPOSITOR_OFFSCREEN) {
+		weston_log("\n %s %d return ret:%d\n", __FUNCTION__,__LINE__,ret);
 		goto err;
-
+		}
 	/* We don't actually need to repaint this output; drop it from
 	 * repaint until something causes damage. */
-	if (!output->repaint_needed)
+	if (!output->repaint_needed) {
+		weston_log("\n %s %d return ret:%d\n", __FUNCTION__,__LINE__,ret);
 		goto err;
+	}
 
 	/* If repaint fails, we aren't going to get weston_output_finish_frame
 	 * to trigger a new repaint, so drop it from repaint and hope
@@ -3009,9 +3041,10 @@
 	 * output. */
 	ret = weston_output_repaint(output, repaint_data);
 	weston_compositor_read_presentation_clock(compositor, now);
-	if (ret != 0)
+	if (ret != 0) {
+		weston_log("\n %s %d return ret:%d\n", __FUNCTION__,__LINE__,ret);
 		goto err;
-
+	}
 	output->repainted = true;
 	return ret;
 
@@ -3501,6 +3534,7 @@
 	wl_resource_set_implementation(cb, NULL, NULL,
 				       destroy_frame_callback);
 
+	wl_list_init(&surface->pending.frame_callback_list);
 	wl_list_insert(surface->pending.frame_callback_list.prev,
 		       wl_resource_get_link(cb));
 }
@@ -3919,6 +3953,7 @@
 	struct weston_surface *surface = wl_resource_get_user_data(resource);
 	struct weston_subsurface *sub = weston_surface_to_subsurface(surface);
 
+	weston_surface_commit_time(surface);
 	if (!weston_surface_is_pending_viewport_source_valid(surface)) {
 		assert(surface->viewport_resource);
 
@@ -3980,7 +4015,7 @@
 	}
 
 	if (sub) {
-		weston_subsurface_commit(sub);
+		weston_video_subsurface_commit(surface, sub);
 		return;
 	}
 
@@ -4041,7 +4076,11 @@
 	surface_commit,
 	surface_set_buffer_transform,
 	surface_set_buffer_scale,
-	surface_damage_buffer
+	surface_damage_buffer,
+	surface_set_video_plane,
+	surface_set_pts,
+	surface_keep_last_frame,
+	surface_set_display_rate
 };
 
 static int
@@ -4782,6 +4821,7 @@
 static void
 weston_subsurface_destroy(struct weston_subsurface *sub)
 {
+	weston_log("\nweston_subsurface_destroy sub:%p ->%p\n", sub, sub->surface);
 	struct weston_view *view, *next;
 
 	assert(sub->surface);
@@ -4853,6 +4893,7 @@
 	weston_surface_state_init(&sub->cached);
 	sub->cached_buffer_ref.buffer = NULL;
 	sub->synchronized = 1;
+	weston_log("\n weston_subsurface_create :%p sub:%p\n",surface, sub );
 
 	return sub;
 }
@@ -5197,6 +5238,10 @@
 				    mode->height,
 				    mode->refresh);
 	}
+	struct drm_output *drm_output = to_drm_output(output);
+	int crtc_index = drm_output->crtc->pipe;
+	if (version >= WL_OUTPUT_CRTC_INDEX_SINCE_VERSION)
+	    wl_output_send_crtc_index(resource, crtc_index);
 
 	if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
 		wl_output_send_done(resource);
@@ -7479,6 +7524,9 @@
 		fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
 			(unsigned long) _format,
 			pixel_info ? pixel_info->drm_format_name : "UNKNOWN");
+#ifdef ENABLE_DRM_HELP
+		debug_write_shm_buffer_to_file(view, shm);
+#endif
 		return;
 	}
 
@@ -7495,6 +7543,9 @@
 		fprintf(fp, "\t\t\tmodifier: %s\n", modifier_name ? modifier_name :
 				"Failed to convert to a modifier name");
 		free(modifier_name);
+#ifdef ENABLE_DRM_HELP
+		debug_write_dma_buffer_to_file(view, dmabuf);
+#endif
 		return;
 	}
 
@@ -7508,6 +7559,7 @@
 	struct weston_output *output;
 	char desc[512];
 	pixman_box32_t *box;
+	pixman_box32_t *opaque_surface_box;
 	uint32_t surface_id = 0;
 	pid_t pid = 0;
 
@@ -7522,9 +7574,9 @@
 	    view->surface->get_label(view->surface, desc, sizeof(desc)) < 0) {
 		strcpy(desc, "[no description available]");
 	}
-	fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p):\n",
+	fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p %p video surface:%d):\n",
 		view_idx, view->surface->role_name, pid, surface_id,
-		desc, view);
+		desc, view, view->surface, view->surface->is_video_surface);
 
 	box = pixman_region32_extents(&view->transform.boundingbox);
 	fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n",
@@ -7539,6 +7591,9 @@
 		fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n",
 			box->x1, box->y1, box->x2, box->y2);
 	}
+	opaque_surface_box = pixman_region32_extents(&view->surface->opaque);
+	fprintf(fp, "\t\t[surface:%p opaque: (%d, %d) -> (%d, %d)]\n",
+			view->surface, opaque_surface_box->x1, opaque_surface_box->y1, opaque_surface_box->x2, opaque_surface_box->y2);
 
 	if (view->alpha < 1.0)
 		fprintf(fp, "\t\talpha: %f\n", view->alpha);
@@ -7802,6 +7857,10 @@
 	if (weston_input_init(ec) != 0)
 		goto fail;
 
+	if (aml_config_setup(ec) != 0 ) {
+		weston_log("\n aml config fail\n");
+	}
+
 	wl_list_init(&ec->view_list);
 	wl_list_init(&ec->plane_list);
 	wl_list_init(&ec->layer_list);
@@ -7815,6 +7874,7 @@
 	wl_list_init(&ec->touch_binding_list);
 	wl_list_init(&ec->axis_binding_list);
 	wl_list_init(&ec->debug_binding_list);
+	wl_list_init(&ec->video_surface_list);
 
 	wl_list_init(&ec->plugin_api_list);
 
@@ -7828,8 +7888,9 @@
 	loop = wl_display_get_event_loop(ec->wl_display);
 	ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
 	ec->repaint_timer =
-		wl_event_loop_add_timer(loop, output_repaint_timer_handler,
+		wl_event_loop_add_timer(loop, output_repaint_timer_handler_aml,
 					ec);
+	wl_event_source_timer_update(ec->repaint_timer, 16);
 
 	weston_layer_init(&ec->fade_layer, ec);
 	weston_layer_init(&ec->cursor_layer, ec);
@@ -7850,6 +7911,7 @@
 						weston_timeline_create_subscription,
 						weston_timeline_destroy_subscription,
 						ec);
+	weston_compositor_aml_init(ec);
 	return ec;
 
 fail:
diff --git a/libweston/input.c b/libweston/input.c
index 6fb4bed..74ac201 100644
--- a/libweston/input.c
+++ b/libweston/input.c
@@ -1525,6 +1525,18 @@
 	}
 }
 
+static bool weston_keyboard_need_enter_surface( struct weston_keyboard *keyboard,
+			  struct weston_surface *surface)
+{
+	bool enter = false;
+	if ( (find_resource_for_surface(&keyboard->resource_list, surface)
+		|| find_resource_for_surface(&keyboard->focus_resource_list, surface)) &&
+			keyboard->focus != surface ) {
+		enter = true;
+	}
+	weston_log("\n %s %d, enter surface:%p, enter:%d222\n", __FUNCTION__,__LINE__, surface, enter);
+	return enter;
+}
 WL_EXPORT void
 weston_keyboard_set_focus(struct weston_keyboard *keyboard,
 			  struct weston_surface *surface)
@@ -1545,48 +1557,58 @@
 
 	focus_resource_list = &keyboard->focus_resource_list;
 
-	if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
-		serial = wl_display_next_serial(display);
-		wl_resource_for_each(resource, focus_resource_list) {
-			wl_keyboard_send_leave(resource, serial,
-					keyboard->focus->resource);
+	if (weston_keyboard_need_enter_surface( keyboard, surface ) || surface == NULL)
+	{
+		if (!wl_list_empty(focus_resource_list) && keyboard->focus != surface) {
+			serial = wl_display_next_serial(display);
+			wl_resource_for_each(resource, focus_resource_list) {
+				if (surface && keyboard && keyboard->focus)
+					surface->compositor->last_keyboard_focus = keyboard->focus;
+				weston_log("\n %s %d, leave surface:%p\n", __FUNCTION__,__LINE__, keyboard->focus);
+				wl_keyboard_send_leave(resource, serial,
+						keyboard->focus->resource);
+			}
+			move_resources(&keyboard->resource_list, focus_resource_list);
+			}
+			if ( surface == NULL && keyboard && keyboard->focus) {
+				surface = keyboard->focus->compositor->last_keyboard_focus;
+				weston_log("\n %s %d, need	back to  surface:%p\n", __FUNCTION__,__LINE__, surface);
 		}
-		move_resources(&keyboard->resource_list, focus_resource_list);
+
+		if (find_resource_for_surface(&keyboard->resource_list, surface) &&
+		    keyboard->focus != surface) {
+			struct wl_client *surface_client =
+				wl_resource_get_client(surface->resource);
+
+			serial = wl_display_next_serial(display);
+
+			move_resources_for_client(focus_resource_list,
+						  &keyboard->resource_list,
+						  surface_client);
+			send_enter_to_resource_list(focus_resource_list,
+						    keyboard,
+						    surface,
+						    serial);
+			keyboard->focus_serial = serial;
+		}
+
+		/* Since this function gets called from the surface destroy handler
+		 * we can't just remove the kbd focus listener, or we might corrupt
+		 * the list it's in.
+		 * Instead, we'll just set a flag to ignore the focus when the
+		 * compositor regains kbd focus.
+		 */
+		seat->use_saved_kbd_focus = false;
+
+		wl_list_remove(&keyboard->focus_resource_listener.link);
+		wl_list_init(&keyboard->focus_resource_listener.link);
+		if (surface)
+			wl_resource_add_destroy_listener(surface->resource,
+							 &keyboard->focus_resource_listener);
+
+		keyboard->focus = surface;
+		wl_signal_emit(&keyboard->focus_signal, keyboard);
 	}
-
-	if (find_resource_for_surface(&keyboard->resource_list, surface) &&
-	    keyboard->focus != surface) {
-		struct wl_client *surface_client =
-			wl_resource_get_client(surface->resource);
-
-		serial = wl_display_next_serial(display);
-
-		move_resources_for_client(focus_resource_list,
-					  &keyboard->resource_list,
-					  surface_client);
-		send_enter_to_resource_list(focus_resource_list,
-					    keyboard,
-					    surface,
-					    serial);
-		keyboard->focus_serial = serial;
-	}
-
-	/* Since this function gets called from the surface destroy handler
-	 * we can't just remove the kbd focus listener, or we might corrupt
-	 * the list it's in.
-	 * Instead, we'll just set a flag to ignore the focus when the
-	 * compositor regains kbd focus.
-	 */
-	seat->use_saved_kbd_focus = false;
-
-	wl_list_remove(&keyboard->focus_resource_listener.link);
-	wl_list_init(&keyboard->focus_resource_listener.link);
-	if (surface)
-		wl_resource_add_destroy_listener(surface->resource,
-						 &keyboard->focus_resource_listener);
-
-	keyboard->focus = surface;
-	wl_signal_emit(&keyboard->focus_signal, keyboard);
 }
 
 /* Users of this function must manually manage the keyboard focus */
diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h
index 7c30706..38b1ed0 100644
--- a/libweston/libweston-internal.h
+++ b/libweston/libweston-internal.h
@@ -155,6 +155,9 @@
 
 /* weston_output */
 
+int
+aml_config_setup(struct weston_compositor *ec);
+
 void
 weston_output_disable_planes_incr(struct weston_output *output);
 
diff --git a/libweston/linux-dmabuf.c b/libweston/linux-dmabuf.c
index 66702a4..083f4e7 100644
--- a/libweston/linux-dmabuf.c
+++ b/libweston/linux-dmabuf.c
@@ -118,7 +118,7 @@
 	buffer->attributes.stride[plane_idx] = stride;
 
 	if (wl_resource_get_version(params_resource) < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
-		buffer->attributes.modifier[plane_idx] = DRM_FORMAT_MOD_INVALID;
+		buffer->attributes.modifier[plane_idx] = DRM_FORMAT_MOD_LINEAR;
 	else
 		buffer->attributes.modifier[plane_idx] = ((uint64_t)modifier_hi << 32) |
 							 modifier_lo;
@@ -232,6 +232,11 @@
 
 		/* Don't report an error as it might be caused
 		 * by the kernel not supporting seeking on dmabuf */
+		if (buffer->direct_display) {
+			weston_log("\n direct_display. remove parameter check and gpu import \n");
+			goto avoid_gpu_import;
+		}
+
 		size = lseek(buffer->attributes.fd[i], 0, SEEK_END);
 		if (size == -1)
 			continue;
@@ -251,7 +256,8 @@
 				buffer->attributes.stride[i], i);
 			goto err_out;
 		}
-
+		weston_log("\n %s %d offset:%d, stride:%d height:%d,size:%d\n", __FUNCTION__, __LINE__,
+			buffer->attributes.offset[i], buffer->attributes.stride[i], height, size);
 		/* Only valid for first plane as other planes might be
 		 * sub-sampled according to fourcc format */
 		if (i == 0 &&
@@ -995,6 +1001,13 @@
 
 	wl_array_for_each(fmt, &supported_formats->arr) {
 		modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
+		if (fmt->format == DRM_FORMAT_NV12 || fmt->format == DRM_FORMAT_NV21) {
+			if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
+				zwp_linux_dmabuf_v1_send_modifier(resource, fmt->format, 0, 0);
+			else
+				zwp_linux_dmabuf_v1_send_format(resource, fmt->format);
+			continue;
+		}
 		for (i = 0; i < num_modifiers; i++) {
 			if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
 				uint32_t modifier_lo = modifiers[i] & 0xFFFFFFFF;
diff --git a/libweston/meson.build b/libweston/meson.build
index 257d695..539b46e 100644
--- a/libweston/meson.build
+++ b/libweston/meson.build
@@ -36,6 +36,7 @@
 	'weston-log.c',
 	'weston-direct-display.c',
 	'zoom.c',
+	'../aml-weston/aml_config.c',
 	linux_dmabuf_unstable_v1_protocol_c,
 	linux_dmabuf_unstable_v1_server_protocol_h,
 	linux_explicit_synchronization_unstable_v1_protocol_c,
@@ -68,6 +69,8 @@
 	weston_debug_server_protocol_h,
 	weston_direct_display_protocol_c,
 	weston_direct_display_server_protocol_h,
+	aml_config_protocol_c,
+	aml_config_server_protocol_h,
 ]
 
 if get_option('renderer-gl')
@@ -230,16 +233,24 @@
 
 if get_option('deprecated-weston-launch')
 	warning('weston-launch is deprecated and will be removed in a future release. Please migrate to libseat and seatd-launch.')
-	dep_pam = cc.find_library('pam')
+	deps_weston_launch = [systemd_dep, dep_libdrm]
 
-	if not cc.has_function('pam_open_session', dependencies: dep_pam)
-		error('pam_open_session not found for weston-launch')
+	if get_option('pam')
+		dep_pam = cc.find_library('pam')
+		if not cc.has_function('pam_open_session', dependencies: dep_pam)
+			error('pam_open_session not found for weston-launch')
+		endif
+
+		if dep_pam.found()
+			deps_weston_launch += dep_pam
+			config_h.set('HAVE_PAM', '1')
+		endif
 	endif
 
 	executable(
 		'weston-launch',
 		'weston-launch.c',
-		dependencies: [dep_pam, systemd_dep, dep_libdrm],
+		dependencies: deps_weston_launch,
 		include_directories: common_inc,
 		install: true
 	)
@@ -247,6 +258,8 @@
 	meson.add_install_script('echo', 'REMINDER: You are installing weston-launch, please make it setuid-root.')
 endif
 
+config_h.set('FORCE_BACKGROUND_TRANSPARENT', get_option('WESTON_FORCE_BACKGROUND_TRANSPARENT'))
+
 subdir('color-lcms')
 subdir('renderer-gl')
 subdir('backend-drm')
diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c
index 8a40ac1..6819e13 100644
--- a/libweston/renderer-gl/gl-renderer.c
+++ b/libweston/renderer-gl/gl-renderer.c
@@ -61,6 +61,8 @@
 #include "shared/weston-drm-fourcc.h"
 #include "shared/weston-egl-ext.h"
 
+#include "aml-weston/aml-renderer.h"
+
 #define BUFFER_DAMAGE_COUNT 2
 
 enum gl_border_status {
@@ -1136,14 +1138,7 @@
 static void
 repaint_views(struct weston_output *output, pixman_region32_t *damage)
 {
-	struct weston_compositor *compositor = output->compositor;
-	struct weston_paint_node *pnode;
-
-	wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list,
-				 z_order_link) {
-		if (pnode->view->plane == &compositor->primary_plane)
-			draw_paint_node(pnode, damage);
-	}
+	repaint_views_aml(output, damage, draw_paint_node);
 }
 
 static int
@@ -1404,7 +1399,7 @@
 	EGLBoolean ret;
 	int i;
 
-	if (gr->has_egl_buffer_age || gr->has_egl_partial_update) {
+	if (gr->has_egl_buffer_age) {
 		ret = eglQuerySurface(gr->egl_display, go->egl_surface,
 				      EGL_BUFFER_AGE_EXT, &buffer_age);
 		if (ret == EGL_FALSE) {
@@ -1444,7 +1439,7 @@
 	struct gl_output_state *go = get_output_state(output);
 	struct gl_renderer *gr = get_renderer(output->compositor);
 
-	if (!gr->has_egl_buffer_age && !gr->has_egl_partial_update)
+	if (!gr->has_egl_buffer_age)
 		return;
 
 	go->buffer_damage_index += BUFFER_DAMAGE_COUNT - 1;
@@ -1623,6 +1618,12 @@
 	enum gl_border_status border_status = BORDER_STATUS_CLEAN;
 	struct weston_paint_node *pnode;
 
+	int64_t start, diff;
+	struct timespec time;
+
+	weston_compositor_get_time(&time);
+	start = timespec_to_usec(&time);
+
 	assert(output->from_blend_to_output_by_backend ||
 	       output->from_blend_to_output == NULL || shadow_exists(go));
 
@@ -1779,6 +1780,11 @@
 	update_buffer_release_fences(compositor, output);
 
 	gl_renderer_garbage_collect_programs(gr);
+
+	weston_compositor_get_time(&time);
+	diff = timespec_to_usec(&time) - start;
+	if (diff > 8000)
+		weston_log("\n %s %d take:%lld(us)\n", __FUNCTION__, __LINE__, diff);
 }
 
 static int
diff --git a/libweston/renderer-gl/meson.build b/libweston/renderer-gl/meson.build
index 4d9f64d..2e38acd 100644
--- a/libweston/renderer-gl/meson.build
+++ b/libweston/renderer-gl/meson.build
@@ -22,6 +22,7 @@
 	'egl-glue.c',
 	fragment_glsl,
 	'gl-renderer.c',
+	'../../aml-weston/aml-renderer.c',
 	'gl-shaders.c',
 	'gl-shader-config-color-transformation.c',
 	linux_dmabuf_unstable_v1_protocol_c,
diff --git a/libweston/weston-launch.c b/libweston/weston-launch.c
index c43ed7b..523a87d 100644
--- a/libweston/weston-launch.c
+++ b/libweston/weston-launch.c
@@ -51,7 +51,9 @@
 
 #include <pwd.h>
 #include <grp.h>
+#ifdef HAVE_PAM
 #include <security/pam_appl.h>
+#endif
 
 #ifdef HAVE_SYSTEMD_LOGIN
 #include <systemd/sd-login.h>
@@ -100,8 +102,10 @@
 #endif
 
 struct weston_launch {
+#ifdef HAVE_PAM
 	struct pam_conv pc;
 	pam_handle_t *ph;
+#endif
 	int tty;
 	int ttynr;
 	int sock[2];
@@ -192,6 +196,7 @@
 	return false;
 }
 
+#ifdef HAVE_PAM
 static int
 pam_conversation_fn(int msg_count,
 		    const struct pam_message **messages,
@@ -232,6 +237,7 @@
 
 	return 0;
 }
+#endif
 
 static int
 setup_launcher_socket(struct weston_launch *wl)
@@ -449,7 +455,7 @@
 		break;
 	case WESTON_LAUNCHER_DEACTIVATE_DONE:
 		close_input_fds(wl);
-		drmDropMaster(wl->drm_fd);
+		//drmDropMaster(wl->drm_fd);
 		ioctl(wl->tty, VT_RELDISP, 1);
 		break;
 	}
@@ -467,6 +473,7 @@
 	close(wl->signalfd);
 	close(wl->sock[0]);
 
+#ifdef HAVE_PAM
 	if (wl->new_user) {
 		err = pam_close_session(wl->ph, 0);
 		if (err)
@@ -474,6 +481,7 @@
 				err, pam_strerror(wl->ph, err));
 		pam_end(wl->ph, err);
 	}
+#endif
 
 	/*
 	 * Get a fresh handle to the tty as the previous one is in
@@ -560,7 +568,7 @@
 		break;
 	case SIGUSR2:
 		ioctl(wl->tty, VT_RELDISP, VT_ACKACQ);
-		drmSetMaster(wl->drm_fd);
+		//drmSetMaster(wl->drm_fd);
 		send_reply(wl, WESTON_LAUNCHER_ACTIVATE);
 		break;
 	default:
@@ -711,6 +719,7 @@
 	setenv("HOME", wl->pw->pw_dir, 1);
 	setenv("SHELL", wl->pw->pw_shell, 1);
 
+#ifdef HAVE_PAM
 	env = pam_getenvlist(wl->ph);
 	if (env) {
 		for (i = 0; env[i]; ++i) {
@@ -719,6 +728,7 @@
 		}
 		free(env);
 	}
+#endif
 
 	/*
 	 * We open a new session, so it makes sense
@@ -790,8 +800,10 @@
 help(const char *name)
 {
 	fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
+#ifdef HAVE_PAM
 	fprintf(stderr, "  -u, --user      Start session as specified username,\n"
 			"                  e.g. -u joe, requires root.\n");
+#endif
 	fprintf(stderr, "  -t, --tty       Start session on alternative tty,\n"
 			"                  e.g. -t /dev/tty4, requires -u option.\n");
 	fprintf(stderr, "  -v, --verbose   Be verbose\n");
@@ -805,7 +817,9 @@
 	int i, c;
 	char *tty = NULL;
 	struct option opts[] = {
+#ifdef HAVE_PAM
 		{ "user",    required_argument, NULL, 'u' },
+#endif
 		{ "tty",     required_argument, NULL, 't' },
 		{ "verbose", no_argument,       NULL, 'v' },
 		{ "help",    no_argument,       NULL, 'h' },
@@ -817,11 +831,16 @@
 	while ((c = getopt_long(argc, argv, "u:t:vh", opts, &i)) != -1) {
 		switch (c) {
 		case 'u':
+#ifdef HAVE_PAM
 			wl.new_user = optarg;
 			if (getuid() != 0) {
 				fprintf(stderr, "weston: Permission denied. -u allowed for root only\n");
 				exit(EXIT_FAILURE);
 			}
+#else
+			fprintf(stderr, "weston: -u is unsupported in this weston-launch build\n");
+			exit(EXIT_FAILURE);
+#endif
 			break;
 		case 't':
 			tty = optarg;
@@ -873,8 +892,10 @@
 	if (setup_tty(&wl, tty) < 0)
 		exit(EXIT_FAILURE);
 
+#ifdef HAVE_PAM
 	if (wl.new_user && setup_pam(&wl) < 0)
 		exit(EXIT_FAILURE);
+#endif
 
 	if (setup_launcher_socket(&wl) < 0)
 		exit(EXIT_FAILURE);
diff --git a/meson_options.txt b/meson_options.txt
index 8a527d7..11c0544 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -73,6 +73,13 @@
 )
 
 option(
+	'pam',
+	type: 'boolean',
+	value: true,
+	description: 'Define if PAM is available'
+)
+
+option(
 	'xwayland',
 	type: 'boolean',
 	value: true,
@@ -93,6 +100,13 @@
 )
 
 option(
+	'WESTON_MAX_OUTPUT_PIPLINE',
+	type: 'string',
+	value: '0',
+	description: 'limit output pipline (int): 0 is without limit'
+)
+
+option(
 	'remoting',
 	type: 'boolean',
 	value: true,
@@ -242,3 +256,27 @@
 	value: false,
 	description: 'Generate documentation'
 )
+option(
+	'WESTON_USE_DEFAULT_Z_ORDER',
+	type: 'boolean',
+	value: false,
+	description: 'weston use default drm z-order'
+)
+option(
+	'WESTON_HAVE_GBM_MODIFIERS',
+	type: 'boolean',
+	value: true,
+	description: 'weston have gbm modifiers'
+)
+option(
+	'WESTON_FORCE_BACKGROUND_TRANSPARENT',
+	type: 'boolean',
+	value: false,
+	description: 'weston force background view transparent'
+)
+option(
+        'BUILD_AML_TV',
+        type: 'boolean',
+        value: false,
+        description: 'support in TV'
+)
diff --git a/protocol/aml-config.xml b/protocol/aml-config.xml
new file mode 100644
index 0000000..de1900b
--- /dev/null
+++ b/protocol/aml-config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="aml_config">
+
+  <copyright>
+    Copyright © 2019 Collabora Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <interface name="aml_config" version="1">
+    <description summary="aml config for client">
+      Weston extension to inform the clients of the new interface added by amlogic.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy factory object">
+        Destroys the factory object, but does not affect any other objects.
+      </description>
+    </request>
+
+    <event name="aml_config_list">
+      <description summary="aml config list">
+	The aml_config_list event inform the clients of the new interface add by amlogic
+      </description>
+      <arg name="list" type="string"
+	   summary="the new interface added by amlogic"/>
+    </event>
+  </interface>
+</protocol>
diff --git a/protocol/meson.build b/protocol/meson.build
index 7d869da..d6f48de 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -34,6 +34,7 @@
 	[ 'weston-test', 'internal' ],
 	[ 'weston-touch-calibration', 'internal' ],
 	[ 'weston-direct-display', 'internal' ],
+	[ 'aml-config', 'internal' ],
 	[ 'xdg-output', 'v1' ],
 	[ 'xdg-shell', 'v6' ],
 	[ 'xdg-shell', 'stable' ],
diff --git a/shared/shell-utils.c b/shared/shell-utils.c
index a301eef..e8f1e2b 100644
--- a/shared/shell-utils.c
+++ b/shared/shell-utils.c
@@ -152,6 +152,8 @@
 		return NULL;
 	}
 	view = weston_view_create(surface);
+	weston_view_opacity(view, 0.0);
+
 	if (view == NULL) {
 		weston_log("no memory\n");
 		weston_surface_destroy(surface);