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);