[Intel-gfx] [PATCH v2 1/1] tests/kms_rotate_crc: Test to verify rotation of planes through CRC
sagar.a.kamble at intel.com
sagar.a.kamble at intel.com
Fri Feb 7 14:48:00 CET 2014
From: Sagar Kamble <sagar.a.kamble at intel.com>
This test will verify 180 degree rotation of CRTC and sprite planes
by grabbing CRC for already rotated image and comparing with CRC calculated
after triggering rotation through DRM property.
v2: Using cairo_rotate to created reference rotated version of CRTC and
Sprite Image. Moved variable data above igt_main. Logging to stdout.
Created separate subtest for verifying CRTC alone and CRTC+Sprite combination.
Signed-off-by: Sagar Kamble <sagar.a.kamble at intel.com>
Tested-by: Sagar Kamble <sagar.a.kamble at intel.com>
---
tests/Makefile.sources | 1 +
tests/kms_rotate_crc.c | 586 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 587 insertions(+)
create mode 100644 tests/kms_rotate_crc.c
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index a8c0c96..c19fc88 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -59,6 +59,7 @@ TESTS_progs_M = \
kms_flip \
kms_pipe_crc_basic \
kms_render \
+ kms_rotate_crc \
kms_setmode \
pm_lpsp \
pm_pc8 \
diff --git a/tests/kms_rotate_crc.c b/tests/kms_rotate_crc.c
new file mode 100644
index 0000000..06d9611
--- /dev/null
+++ b/tests/kms_rotate_crc.c
@@ -0,0 +1,586 @@
+/*
+ * Copyright © 2013 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.
+ *
+ * Author:
+ * Sagar Kamble <sagar.a.kamble at intel.com>
+ */
+
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "drm_fourcc.h"
+
+#include "drmtest.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+
+#define DRM_ROTATE_0 0
+#define DRM_ROTATE_90 1
+#define DRM_ROTATE_180 2
+#define DRM_ROTATE_270 3
+#define DRM_REFLECT_X 4
+#define DRM_REFLECT_Y 5
+#define DRM_ROTATE_NUM 6
+
+#define BIT(x) (1 << x)
+
+typedef struct {
+ struct kmstest_connector_config config;
+ drmModeModeInfo mode;
+ struct kmstest_fb fb[DRM_ROTATE_NUM];
+ struct kmstest_fb sprite_fb[DRM_ROTATE_NUM]
+} connector_t;
+
+typedef struct {
+ int drm_fd;
+ igt_debugfs_t debugfs;
+ drmModeRes *resources;
+ igt_crc_t ref_crtc_crc[DRM_ROTATE_NUM];
+ igt_crc_t ref_sprite_crc[DRM_ROTATE_NUM];
+ igt_pipe_crc_t **pipe_crc;
+ uint32_t crtc_id;
+ uint32_t sprite_id;
+ uint32_t crtc_idx;
+ uint32_t crtc_fb_id[DRM_ROTATE_NUM];
+ uint32_t sprite_fb_id[DRM_ROTATE_NUM];
+} data_t;
+
+static void set_rotation(int drm_fd, bool is_sprite, uint32_t plane_id, uint64_t rotation)
+{
+ int i = 0, j = 0, ret = 0;
+ drmModeObjectPropertiesPtr props = NULL;
+
+ props = drmModeObjectGetProperties(drm_fd, plane_id,
+ is_sprite ? DRM_MODE_OBJECT_PLANE : DRM_MODE_OBJECT_CRTC);
+ fprintf(stdout, "\nPlane id: 0x%x, Count_props=%d ", plane_id, props->count_props);
+
+ for (i = 0; i < props->count_props; i++)
+ {
+ drmModePropertyPtr prop = drmModeGetProperty(drm_fd, props->props[i]);
+ fprintf(stdout, "\nProp->name=%s ", prop->name);
+
+ if (strcmp(prop->name, "rotation") == 0)
+ {
+ igt_assert(prop->flags & DRM_MODE_PROP_BITMASK);
+ fprintf(stdout, "\nRotation property enum count %d", prop->count_enums);
+ fprintf(stdout, "\nRotation type\tValue");
+ for (j = 0; j < prop->count_enums; j++)
+ fprintf(stdout, "\n%s: 0x%x", prop->enums[j].name, prop->enums[j].value);
+
+ ret = drmModeObjectSetProperty(drm_fd, plane_id, is_sprite ? DRM_MODE_OBJECT_PLANE : DRM_MODE_OBJECT_CRTC,
+ (uint32_t)prop->prop_id, rotation);
+ if (ret)
+ {
+ fprintf(stdout, "\nRotation setting\(0x%x\) failed !!!", rotation);
+ return;
+ }
+ else
+ fprintf(stdout, "\nPlane with id 0x%x is rotated with setting 0x%x", plane_id, rotation);
+ }
+ drmModeFreeProperty(prop);
+ }
+ drmModeFreeObjectProperties(props);
+}
+
+static uint32_t create_crtc_fb(data_t *data,
+ uint16_t w,
+ uint16_t h,
+ uint16_t rotation,
+ struct kmstest_fb *fb)
+{
+ uint32_t fb_id = 0, fb_id_0 = 0;
+ cairo_t *cr, *cr_0;
+ struct kmstest_fb fb_0;
+ cairo_surface_t *image_0;
+
+ fb_id_0 = kmstest_create_fb(data->drm_fd,
+ w, h,
+ 32 /* bpp */, 24 /* depth */,
+ false /* tiling */,
+ &fb_0);
+ igt_assert(fb_id_0);
+
+ cr_0 = kmstest_get_cairo_ctx(data->drm_fd, &fb_0);
+ /* Paint with 4 squares of Red, Green, White, Blue Clockwise */
+ kmstest_paint_color(cr_0, 0, 0, w/2, h/2, 1.0, 0.0, 0.0);
+ kmstest_paint_color(cr_0, (w/2)-1, 0, w/2, h/2, 0.0, 1.0, 0.0);
+ kmstest_paint_color(cr_0, 0, (h/2)-1, w/2, h/2, 0.0, 0.0, 1.0);
+ kmstest_paint_color(cr_0, (w/2)-1, (h/2)-1, w/2, h/2, 1.0, 1.0, 1.0);
+
+ image_0 = fb_0.cairo_surface;
+
+ if ((rotation == DRM_ROTATE_0) || (rotation == DRM_ROTATE_180))
+ {
+ fb_id = kmstest_create_fb(data->drm_fd,
+ w, h,
+ 32 /* bpp */, 24 /* depth */,
+ false /* tiling */,
+ fb);
+ }
+
+ igt_assert(fb_id);
+ cr = kmstest_get_cairo_ctx(data->drm_fd, fb);
+
+ switch (rotation)
+ {
+ case DRM_ROTATE_0:
+ cairo_set_source_surface (cr, image_0, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ break;
+ case DRM_ROTATE_180:
+ cairo_translate (cr, w * 0.5, h * 0.5);
+ cairo_rotate (cr, M_PI);
+ cairo_translate (cr, -w * 0.5, -h * 0.5);
+ cairo_set_source_surface (cr, image_0, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ break;
+ default:
+ fprintf(stdout, "\n %x Rotation not Supported !!!", rotation);
+ }
+
+ igt_assert(cairo_status(cr) == 0);
+ cairo_destroy(cr);
+ cairo_destroy(cr_0);
+
+ return fb_id;
+}
+
+static uint32_t create_sprite_fb(data_t *data,
+ uint16_t w,
+ uint16_t h,
+ uint16_t rotation,
+ struct kmstest_fb *fb)
+{
+ uint32_t fb_id = 0, fb_id_0 = 0;
+ cairo_t *cr, *cr_0;
+ struct kmstest_fb fb_0;
+ cairo_surface_t *image_0;
+
+ fb_id_0 = kmstest_create_fb2(data->drm_fd, w, h,
+ DRM_FORMAT_XRGB8888, false, &fb_0);
+
+ igt_assert(fb_id_0);
+
+ cr_0 = kmstest_get_cairo_ctx(data->drm_fd, &fb_0);
+ /* Paint with 4 squares of different colours */
+ kmstest_paint_color(cr_0, 0, 0, w/2, h/2, 1.0, 1.0, 0.0);
+ kmstest_paint_color(cr_0, (w/2)-1, 0, w/2, h/2, 0.0, 1.0, 1.0);
+ kmstest_paint_color(cr_0, 0, (h/2)-1, w/2, h/2, 1.0, 0.0, 1.0);
+ kmstest_paint_color(cr_0, (w/2)-1, (h/2)-1, w/2, h/2, 0.0, 0.0, 0.0);
+
+ image_0 = fb_0.cairo_surface;
+
+ if ((rotation == DRM_ROTATE_0) || (rotation == DRM_ROTATE_180))
+ {
+ fb_id = kmstest_create_fb2(data->drm_fd, w, h,
+ DRM_FORMAT_XRGB8888, false, fb);
+ }
+
+ igt_assert(fb_id);
+ cr = kmstest_get_cairo_ctx(data->drm_fd, fb);
+
+ switch (rotation)
+ {
+ case DRM_ROTATE_0:
+ cairo_set_source_surface (cr, image_0, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ break;
+ case DRM_ROTATE_180:
+ cairo_translate (cr, w * 0.5, h * 0.5);
+ cairo_rotate (cr, M_PI);
+ cairo_translate (cr, -w * 0.5, -h * 0.5);
+ cairo_set_source_surface (cr, image_0, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ break;
+ default:
+ fprintf(stdout, "\n %x Rotation not Supported !!!", rotation);
+ }
+
+ igt_assert(cairo_status(cr) == 0);
+ cairo_destroy(cr);
+ cairo_destroy(cr_0);
+
+ return fb_id;
+}
+
+static int connector_find_plane(int gfx_fd, uint32_t pipe)
+{
+ drmModePlaneRes *plane_resources;
+ drmModePlane *ovr;
+ uint32_t id = 0;
+ int i;
+
+ plane_resources = drmModeGetPlaneResources(gfx_fd);
+ if (!plane_resources) {
+ printf("drmModeGetPlaneResources failed: %s\n",
+ strerror(errno));
+ return 0;
+ }
+
+ for (i = 0; i < plane_resources->count_planes; i++) {
+ ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
+ if (!ovr) {
+ printf("drmModeGetPlane failed: %s\n",
+ strerror(errno));
+ continue;
+ }
+
+ if (ovr->possible_crtcs & (1 << pipe)) {
+ id = ovr->plane_id;
+ drmModeFreePlane(ovr);
+ break;
+ }
+ drmModeFreePlane(ovr);
+ }
+
+ return id;
+}
+
+static void sprite_set_mode(data_t *data, connector_t *connector,
+ uint16_t w, uint16_t h, uint32_t sprite_fb_id)
+{
+ struct drm_intel_sprite_colorkey set;
+ struct kmstest_connector_config *config = &connector->config;
+ int ret = 0;
+ uint16_t out_w = 0, out_h = 0, sprite_x = 0, sprite_y = 0;
+ uint32_t plane_flags = 0;
+
+ // Set the sprite colorkey state
+ set.plane_id = data->sprite_id;
+ set.min_value = 0;
+ set.max_value = 0;
+ set.flags = I915_SET_COLORKEY_NONE;
+ ret = drmCommandWrite(data->drm_fd, DRM_I915_SET_SPRITE_COLORKEY, &set, sizeof(set));
+ assert(ret == 0);
+
+ // Set up sprite output dimensions, initial position, etc.
+ out_w = w;
+ out_h = h;
+
+ sprite_x = w - w/2;
+ sprite_y = h - h/2;
+
+ /* i915 Set Mode */
+ if (drmModeSetPlane(data->drm_fd, data->sprite_id, config->crtc->crtc_id,
+ sprite_fb_id, plane_flags,
+ sprite_x, sprite_y,
+ out_w, out_h,
+ 0, 0,
+ out_w << 16, out_h << 16))
+ printf("Failed to enable sprite plane: %s\n", strerror(errno));
+}
+
+static bool
+connector_set_mode(data_t *data, connector_t *connector,
+ drmModeModeInfo *mode, uint32_t fb_id)
+{
+ struct kmstest_connector_config *config = &connector->config;
+ int ret;
+
+ ret = drmModeSetCrtc(data->drm_fd,
+ config->crtc->crtc_id,
+ fb_id,
+ 0, 0, /* x, y */
+ &config->connector->connector_id,
+ 1,
+ mode);
+ igt_assert(ret == 0);
+
+ return 0;
+}
+
+static void display_init(data_t *data)
+{
+ data->resources = drmModeGetResources(data->drm_fd);
+ igt_assert(data->resources);
+
+ data->pipe_crc = calloc(data->resources->count_crtcs, sizeof(data->pipe_crc[0]));
+}
+
+static void display_fini(data_t *data)
+{
+ free(data->pipe_crc);
+}
+
+static void test_crtc_crc(data_t *data, uint16_t rotation)
+{
+ igt_pipe_crc_t *pipe_crc = data->pipe_crc[data->crtc_idx];
+ igt_crc_t *crcs = NULL;
+
+ set_rotation(data->drm_fd, false, data->crtc_id, BIT(rotation));
+
+ usleep(5000000);
+
+ igt_wait_for_vblank(data->drm_fd, data->crtc_idx);
+
+ igt_pipe_crc_start(pipe_crc);
+ igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs);
+ igt_pipe_crc_stop(pipe_crc);
+ fprintf(stdout, "\n Output CRCS: %u %s ", crcs[0].frame, igt_crc_to_string(&crcs[0]));
+ fprintf(stdout, "\n Reference CRCS: %u %s ", data->ref_crtc_crc[rotation].frame, igt_crc_to_string(&data->ref_crtc_crc[rotation]));
+
+ igt_assert(!igt_crc_equal(&crcs[0], &data->ref_crtc_crc[rotation]));
+ free(crcs);
+}
+
+static void test_sprite_crc(data_t *data, uint16_t rotation)
+{
+ igt_pipe_crc_t *pipe_crc = data->pipe_crc[data->crtc_idx];
+ igt_crc_t *crcs = NULL;
+
+ set_rotation(data->drm_fd, true, data->sprite_id, BIT(rotation));
+
+ usleep(5000000);
+
+ igt_wait_for_vblank(data->drm_fd, data->crtc_idx);
+
+ igt_pipe_crc_start(pipe_crc);
+ igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs);
+ igt_pipe_crc_stop(pipe_crc);
+ fprintf(stdout, "\n Output CRCS: %u %s ", crcs[0].frame, igt_crc_to_string(&crcs[0]));
+ fprintf(stdout, "\n Reference CRCS: %u %s ", data->ref_sprite_crc[rotation].frame, igt_crc_to_string(&data->ref_sprite_crc[rotation]));
+
+ igt_assert(!igt_crc_equal(&crcs[0], &data->ref_sprite_crc[rotation]));
+ free(crcs);
+}
+
+static void get_ref_crtc_crcs(data_t *data, connector_t connector,
+ igt_pipe_crc_t *pipe_crc, uint16_t rotation)
+{
+ igt_crc_t *crcs = NULL;
+
+ igt_assert(rotation < DRM_ROTATE_NUM);
+
+ data->crtc_fb_id[rotation] = create_crtc_fb(data,
+ connector.config.default_mode.hdisplay,
+ connector.config.default_mode.vdisplay,
+ rotation, &connector.fb[rotation]);
+
+ igt_assert(data->crtc_fb_id[rotation]);
+
+ /* scanout = fb[rotation] */
+ connector_set_mode(data, &connector, &connector.config.default_mode,
+ data->crtc_fb_id[rotation]);
+ usleep(5000000);
+
+ igt_wait_for_vblank(data->drm_fd, data->crtc_idx);
+
+ /* get reference crc for fb[rotation] */
+ igt_pipe_crc_start(pipe_crc);
+ igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs);
+ data->ref_crtc_crc[rotation] = crcs[0];
+ igt_pipe_crc_stop(pipe_crc);
+ free(crcs);
+}
+
+static void get_ref_sprite_crcs(data_t *data, connector_t connector,
+ igt_pipe_crc_t *pipe_crc, uint16_t rotation)
+{
+ igt_crc_t *crcs = NULL;
+ uint16_t w = 0, h = 0;
+
+ igt_assert(rotation < DRM_ROTATE_NUM);
+
+ w = connector.config.default_mode.hdisplay / 2;
+ h = connector.config.default_mode.vdisplay / 2;
+
+ data->sprite_fb_id[rotation] = create_sprite_fb(data, w, h,
+ rotation, &connector.fb[rotation]);
+
+ igt_assert(data->sprite_fb_id[rotation]);
+
+ /* scanout = fb[rotation] */
+ sprite_set_mode(data, &connector, w, h, data->sprite_fb_id[rotation]);
+ usleep(5000000);
+
+ igt_wait_for_vblank(data->drm_fd, data->crtc_idx);
+
+ /* get reference crc for fb[rotation] */
+ igt_pipe_crc_start(pipe_crc);
+ igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs);
+ data->ref_sprite_crc[rotation] = crcs[0];
+ igt_pipe_crc_stop(pipe_crc);
+ free(crcs);
+}
+
+static bool prepare_sprite(data_t *data, uint32_t connector_id)
+{
+ uint32_t sprite_plane_id;
+ connector_t connector;
+ igt_pipe_crc_t *pipe_crc;
+ int ret;
+
+ ret = kmstest_get_connector_config(data->drm_fd,
+ connector_id,
+ 1 << data->crtc_idx,
+ &connector.config);
+ if (ret)
+ return false;
+
+ igt_pipe_crc_free(data->pipe_crc[data->crtc_idx]);
+ data->pipe_crc[data->crtc_idx] = NULL;
+
+ pipe_crc = igt_pipe_crc_new(&data->debugfs,
+ data->drm_fd, data->crtc_idx,
+ INTEL_PIPE_CRC_SOURCE_AUTO);
+ if (!pipe_crc) {
+ fprintf(stdout, "auto crc not supported on this connector with crtc %i\n",
+ data->crtc_idx);
+ return false;
+ }
+
+ data->pipe_crc[data->crtc_idx] = pipe_crc;
+
+ // Determine if sprite hardware is available on pipe
+ // associated with this connector.
+ sprite_plane_id = connector_find_plane(data->drm_fd, data->crtc_idx);
+ if (!sprite_plane_id) {
+ printf("Failed to find sprite plane on crtc\n");
+ return false;
+ }
+ data->sprite_id = sprite_plane_id;
+
+ get_ref_sprite_crcs(data, connector, pipe_crc, DRM_ROTATE_180);
+ get_ref_sprite_crcs(data, connector, pipe_crc, DRM_ROTATE_0);
+
+ kmstest_free_connector_config(&connector.config);
+
+ return true;
+}
+
+static bool prepare_crtc(data_t *data, uint32_t connector_id)
+{
+ connector_t connector;
+ igt_pipe_crc_t *pipe_crc;
+ int ret;
+
+ ret = kmstest_get_connector_config(data->drm_fd,
+ connector_id,
+ 1 << data->crtc_idx,
+ &connector.config);
+ if (ret)
+ return false;
+
+ if (!connector.config.crtc->mode_valid)
+ return false;
+
+ igt_pipe_crc_free(data->pipe_crc[data->crtc_idx]);
+ data->pipe_crc[data->crtc_idx] = NULL;
+
+ pipe_crc = igt_pipe_crc_new(&data->debugfs,
+ data->drm_fd, data->crtc_idx,
+ INTEL_PIPE_CRC_SOURCE_AUTO);
+ if (!pipe_crc) {
+ fprintf(stdout, "auto crc not supported on this connector with crtc %i\n",
+ data->crtc_idx);
+ return false;
+ }
+
+ data->pipe_crc[data->crtc_idx] = pipe_crc;
+
+ get_ref_crtc_crcs(data, connector, pipe_crc, DRM_ROTATE_180);
+ get_ref_crtc_crcs(data, connector, pipe_crc, DRM_ROTATE_0);
+
+ kmstest_free_connector_config(&connector.config);
+
+ return true;
+}
+
+static void finish_crtc(data_t *data)
+{
+ igt_pipe_crc_free(data->pipe_crc[data->crtc_idx]);
+ data->pipe_crc[data->crtc_idx] = NULL;
+}
+
+static void run_test(data_t *data, bool test_sprite)
+{
+ int i, n;
+
+ for (i = 0; i < data->resources->count_connectors; i++) {
+ uint32_t connector_id = data->resources->connectors[i];
+
+ for (n = 0; n < data->resources->count_crtcs; n++) {
+ data->crtc_idx = n;
+ data->crtc_id = data->resources->crtcs[n];
+
+ if (!prepare_crtc(data, connector_id))
+ continue;
+
+ fprintf(stdout, "\nBeginning crtc rotation test on crtc %d, connector %d\n",
+ data->crtc_id, connector_id);
+
+ test_crtc_crc(data, DRM_ROTATE_180);
+
+ fprintf(stdout, "\nCRTC Rotation test on crtc %d, connector %d: PASSED\n\n",
+ data->crtc_id, connector_id);
+
+ if (test_sprite) {
+ fprintf(stdout, "\nBeginning sprite rotation test on crtc %d, connector %d\n",
+ data->crtc_id, connector_id);
+
+ if (!prepare_sprite(data, connector_id))
+ continue;
+
+ test_sprite_crc(data, DRM_ROTATE_180);
+
+ fprintf(stdout, "\nSprite Rotation test on crtc %d, connector %d: PASSED\n\n",
+ data->crtc_id, connector_id);
+ }
+
+ finish_crtc(data);
+ }
+ }
+}
+
+data_t data = {0, };
+
+igt_main
+{
+ igt_skip_on_simulation();
+
+ igt_fixture {
+ data.drm_fd = drm_open_any();
+ igt_set_vt_graphics_mode();
+
+ igt_debugfs_init(&data.debugfs);
+ igt_pipe_crc_check(&data.debugfs);
+
+ display_init(&data);
+ }
+
+ igt_subtest("crtc")
+ run_test(&data, false);
+ igt_subtest("crtc-sprite")
+ run_test(&data, true);
+
+ igt_fixture {
+ display_fini(&data);
+ }
+
+}
--
1.8.5
More information about the Intel-gfx
mailing list