diff mbox

[igt] tests: add kms_fbcon_fbt

Message ID 1436461715-1684-1-git-send-email-przanoni@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulo Zanoni July 9, 2015, 5:08 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This test should test the interactions between fbcon and the
frontbuffer tracking infrastructure.

Right now the PSR test fails, but as soon as we merge the following
kernel patches, the test wills tart passing:
 - drm/i915: PSR: Flush means invalidate + flush
 - drm/i915: fbdev restore mode needs to invalidate frontbuffer
 - drm/i915: fbdev_set_par reliably invalidating frontbuffer

I didn't want to make this a subtest of kms_frontbuffer_tracking just
because when I wrote it, I really didn't have in mind the fact that
someone might just close the DRM fd in the middle of a subtest.

After this commit we'll have a little bit of duplicated code among
tests. I'll clean this up later.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 tests/.gitignore       |   1 +
 tests/Makefile.sources |   1 +
 tests/kms_fbcon_fbt.c  | 333 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 335 insertions(+)
 create mode 100644 tests/kms_fbcon_fbt.c
diff mbox

Patch

diff --git a/tests/.gitignore b/tests/.gitignore
index c31b22a..0af0899 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -131,6 +131,7 @@  kms_addfb
 kms_cursor_crc
 kms_draw_crc
 kms_fbc_crc
+kms_fbcon_fbt
 kms_fence_pin_leak
 kms_flip
 kms_flip_event_leak
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index b9479cc..c94714b 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -65,6 +65,7 @@  TESTS_progs_M = \
 	kms_cursor_crc \
 	kms_draw_crc \
 	kms_fbc_crc \
+	kms_fbcon_fbt \
 	kms_flip \
 	kms_flip_event_leak \
 	kms_flip_tiling \
diff --git a/tests/kms_fbcon_fbt.c b/tests/kms_fbcon_fbt.c
new file mode 100644
index 0000000..e5d2d33
--- /dev/null
+++ b/tests/kms_fbcon_fbt.c
@@ -0,0 +1,333 @@ 
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "drmtest.h"
+#include "igt_aux.h"
+#include "igt_debugfs.h"
+#include "igt_draw.h"
+#include "igt_kms.h"
+
+IGT_TEST_DESCRIPTION("Test the relationship between fbcon and the frontbuffer "
+		     "tracking infrastructure.");
+
+#define MAX_CONNECTORS 32
+#define DEBUGFS_MSG_SIZE 256
+
+static bool do_wait_user = false;
+
+struct drm_info {
+	int fd;
+	drmModeResPtr res;
+	drmModeConnectorPtr connectors[MAX_CONNECTORS];
+};
+
+struct fbc_info {
+	int fd;
+};
+
+struct psr_info {
+	int fd;
+};
+
+enum feature_status {
+	ENABLED,
+	DISABLED,
+};
+
+static void wait_user(const char *msg)
+{
+	if (!do_wait_user)
+		return;
+
+	igt_info("%s Press enter...\n", msg);
+	while (getchar() != '\n')
+		;
+}
+
+static void setup_drm(struct drm_info *drm)
+{
+	int i;
+
+	drm->fd = drm_open_any_master();
+
+	drm->res = drmModeGetResources(drm->fd);
+	igt_assert(drm->res->count_connectors <= MAX_CONNECTORS);
+
+	for (i = 0; i < drm->res->count_connectors; i++)
+		drm->connectors[i] = drmModeGetConnector(drm->fd,
+						drm->res->connectors[i]);
+
+	kmstest_set_vt_graphics_mode();
+}
+
+static void teardown_drm(struct drm_info *drm)
+{
+	int i;
+
+	kmstest_restore_vt_mode();
+
+	for (i = 0; i < drm->res->count_connectors; i++)
+		drmModeFreeConnector(drm->connectors[i]);
+
+	drmModeFreeResources(drm->res);
+	igt_assert(close(drm->fd) == 0);
+}
+
+static void get_debugfs_string(int fd, char *buf)
+{
+	ssize_t n_read;
+
+	lseek(fd, 0, SEEK_SET);
+
+	n_read = read(fd, buf, DEBUGFS_MSG_SIZE -1);
+	igt_assert(n_read >= 0);
+	buf[n_read] = '\0';
+}
+
+static bool fbc_supported_on_chipset(int fd)
+{
+	char buf[DEBUGFS_MSG_SIZE];
+
+	get_debugfs_string(fd, buf);
+	return !strstr(buf, "FBC unsupported on this chipset\n");
+}
+
+static void setup_fbc(struct fbc_info *fbc)
+{
+	fbc->fd = igt_debugfs_open("i915_fbc_status", O_RDONLY);
+	igt_assert(fbc->fd >= 0);
+
+	igt_require_f(fbc_supported_on_chipset(fbc->fd),
+		      "Can't test FBC: not supported on this chipset\n");
+
+	igt_set_module_param_int("enable_fbc", 1);
+}
+
+static void teardown_fbc(struct fbc_info *fbc)
+{
+	igt_assert(close(fbc->fd) == 0);
+}
+
+static bool connector_can_fbc(drmModeConnectorPtr connector)
+{
+	return true;
+}
+
+static bool fbc_get_status(int fd)
+{
+	char buf[DEBUGFS_MSG_SIZE];
+
+	get_debugfs_string(fd, buf);
+
+	if (strstr(buf, "FBC enabled\n"))
+		return ENABLED;
+	else
+		return DISABLED;
+}
+
+static bool fbc_wait_for_status(struct fbc_info *fbc,
+				enum feature_status status)
+{
+	return igt_wait(fbc_get_status(fbc->fd) == status, 5000, 1);
+}
+
+typedef bool (*connector_possible_fn)(drmModeConnectorPtr connector);
+
+static void set_mode_for_one_screen(struct drm_info *drm, struct igt_fb *fb,
+				    connector_possible_fn connector_possible)
+{
+	int i, rc;
+	uint32_t connector_id = 0, crtc_id;
+	drmModeModeInfoPtr mode;
+	uint32_t buffer_id;
+	drmModeConnectorPtr c = NULL;
+
+	for (i = 0; i < drm->res->count_connectors; i++) {
+		c = drm->connectors[i];
+
+		if (c->connection == DRM_MODE_CONNECTED && c->count_modes &&
+		    connector_possible(c)) {
+			connector_id = c->connector_id;
+			mode = &c->modes[0];
+			break;
+		}
+	}
+	igt_require_f(connector_id, "No connector available\n");
+
+	crtc_id = drm->res->crtcs[0];
+
+	buffer_id = igt_create_fb(drm->fd, mode->hdisplay, mode->vdisplay,
+				  DRM_FORMAT_XRGB8888,
+				  LOCAL_I915_FORMAT_MOD_X_TILED, fb);
+	igt_draw_fill_fb(drm->fd, fb, 0xFF);
+
+	igt_info("Setting %dx%d mode for %s connector\n",
+		 mode->hdisplay, mode->vdisplay,
+		 kmstest_connector_type_str(c->connector_type));
+
+	rc = drmModeSetCrtc(drm->fd, crtc_id, buffer_id, 0, 0, &connector_id, 1,
+			    mode);
+	igt_assert_eq(rc, 0);
+}
+
+static void fbc_subtest(void)
+{
+	struct drm_info drm;
+	struct fbc_info fbc;
+	struct igt_fb fb;
+
+	setup_fbc(&fbc);
+
+	setup_drm(&drm);
+
+	kmstest_unset_all_crtcs(drm.fd, drm.res);
+	wait_user("Modes unset.");
+	igt_assert(fbc_wait_for_status(&fbc, DISABLED));
+
+	set_mode_for_one_screen(&drm, &fb, connector_can_fbc);
+	wait_user("FBC screen set.");
+	igt_assert(fbc_wait_for_status(&fbc, ENABLED));
+
+	igt_remove_fb(drm.fd, &fb);
+	teardown_drm(&drm);
+
+	/* Wait for fbcon to restore itself. */
+	sleep(5);
+
+	wait_user("Back to fbcon.");
+	igt_assert(fbc_wait_for_status(&fbc, DISABLED));
+
+	teardown_fbc(&fbc);
+}
+
+static bool psr_supported_on_chipset(int fd)
+{
+	char buf[DEBUGFS_MSG_SIZE];
+
+	get_debugfs_string(fd, buf);
+
+	return strstr(buf, "Sink_Support: yes\n");
+}
+
+static void setup_psr(struct psr_info *psr)
+{
+	psr->fd = igt_debugfs_open("i915_edp_psr_status", O_RDONLY);
+	igt_assert(psr->fd >= 0);
+
+	igt_require_f(psr_supported_on_chipset(psr->fd),
+		      "Can't test PSR: not supported on this chipset\n");
+
+	igt_set_module_param_int("enable_psr", 1);
+}
+
+static void teardown_psr(struct psr_info *psr)
+{
+	igt_assert(close(psr->fd) == 0);
+}
+
+static bool connector_can_psr(drmModeConnectorPtr connector)
+{
+	return (connector->connector_type == DRM_MODE_CONNECTOR_eDP);
+}
+
+static bool psr_get_status(int fd)
+{
+	char buf[DEBUGFS_MSG_SIZE];
+
+	get_debugfs_string(fd, buf);
+
+	if (strstr(buf, "\nActive: yes\n"))
+		return ENABLED;
+	else
+		return DISABLED;
+}
+
+static bool psr_wait_for_status(struct psr_info *psr,
+				enum feature_status status)
+{
+	return igt_wait(psr_get_status(psr->fd) == status, 5000, 1);
+}
+
+static void psr_subtest(void)
+{
+	struct drm_info drm;
+	struct psr_info psr;
+	struct igt_fb fb;
+
+	setup_psr(&psr);
+
+	setup_drm(&drm);
+
+	kmstest_unset_all_crtcs(drm.fd, drm.res);
+	wait_user("Modes unset.");
+	igt_assert(psr_wait_for_status(&psr, DISABLED));
+
+	set_mode_for_one_screen(&drm, &fb, connector_can_psr);
+	wait_user("PSR screen set.");
+	igt_assert(psr_wait_for_status(&psr, ENABLED));
+
+	igt_remove_fb(drm.fd, &fb);
+	teardown_drm(&drm);
+
+	/* Wait for fbcon to restore itself. */
+	sleep(5);
+
+	wait_user("Back to fbcon.");
+	igt_assert(psr_wait_for_status(&psr, DISABLED));
+
+	teardown_psr(&psr);
+}
+
+static void setup_environment(void)
+{
+	int drm_fd;
+
+	drm_fd = drm_open_any_master();
+	igt_require(drm_fd >= 0);
+	igt_assert(close(drm_fd) == 0);
+}
+
+static void teardown_environment(void)
+{
+}
+
+igt_main
+{
+	igt_fixture
+		setup_environment();
+
+	igt_subtest("fbc")
+		fbc_subtest();
+	igt_subtest("psr")
+		psr_subtest();
+
+	igt_fixture
+		teardown_environment();
+}