From: arsharma <ankitprasad.r.sharma@xxxxxxxxx> v1: This test currently tests constant alpha setting of sprite planes. It verifies alpha setting of 0 and 255 with CRC. Signed-off-by: Sharma, Ankitprasad R <ankitprasad.r.sharma@xxxxxxxxx> Signed-off-by: Sagar Kamble <sagar.a.kamble@xxxxxxxxx> --- tests/Makefile.sources | 1 + tests/kms_blend.c | 560 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 561 insertions(+) create mode 100644 tests/kms_blend.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 88866ac..b8a19cd 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -55,6 +55,7 @@ TESTS_progs_M = \ gem_tiled_partial_pwrite_pread \ gem_write_read_ring_switch \ kms_addfb \ + kms_blend \ kms_cursor_crc \ kms_fbc_crc \ kms_flip \ diff --git a/tests/kms_blend.c b/tests/kms_blend.c new file mode 100644 index 0000000..1990c52 --- /dev/null +++ b/tests/kms_blend.c @@ -0,0 +1,560 @@ +/* + * Copyright © 2014 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: + * Ankitprasad Sharma <ankitprasad.r.sharma at intel.com> + * Sagar Kamble <sagar.a.kamble@xxxxxxxxx> + */ + + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <cairo.h> +#include <math.h> +#include "drm_fourcc.h" +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" + +#define DRM_BLEND_NUM 24 +#define DRM_BLEND_PROP_SRC_COLOR 2 +#define DRM_BLEND_PROP_CONST_ALPHA 12 +#define BIT(x) (1 << x) + +typedef struct { + struct kmstest_connector_config config; + drmModeModeInfo mode; + struct kmstest_fb fb[DRM_BLEND_NUM]; + struct kmstest_fb sprite_fb[DRM_BLEND_NUM] +} connector_t; + +typedef struct { + int drm_fd; + igt_debugfs_t debugfs; + drmModeRes *resources; + igt_crc_t ref_crtc_crc[DRM_BLEND_NUM]; + igt_crc_t ref_sprite_crc[DRM_BLEND_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_BLEND_NUM]; + uint32_t sprite_fb_id[DRM_BLEND_NUM]; +} data_t; + +static void set_blend(int drm_fd, uint32_t plane_id, uint64_t blend_prop, double blend_val) +{ + int i = 0, j = 0, ret = 0; + uint64_t prop_blend; + uint64_t value, blend_val_int; + double blend_val_ex; + drmModeObjectPropertiesPtr props = NULL; + + props = drmModeObjectGetProperties(drm_fd, plane_id, DRM_MODE_OBJECT_PLANE); + + switch(blend_prop) + { + case BIT(DRM_BLEND_PROP_CONST_ALPHA): + blend_val_ex = blend_val * 255; + blend_val_int = (uint64_t) blend_val_ex; + value = (blend_val_int << 32); + prop_blend = value | blend_prop; + fprintf(stdout, "blend_val_ex = %f, blend_val_int = %d, value = %016llx, blend_prop = %016llx\n", + blend_val_ex, blend_val_int, value, blend_prop); + break; + case BIT(DRM_BLEND_PROP_SRC_COLOR): + prop_blend = blend_prop; + break; + default: + fprintf(stdout, "Blend Type not supported\n"); + return; + } + + 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, "blend") == 0) + { + igt_assert(prop->flags & (DRM_MODE_PROP_BITMASK | DRM_MODE_PROP_32BIT_PAIR)); + fprintf(stdout, "\nBlending property enum count %d", prop->count_enums); + fprintf(stdout, "\nBlending 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, DRM_MODE_OBJECT_PLANE, + (uint32_t)prop->prop_id, (uint64_t)prop_blend); + if (ret) + { + fprintf(stdout, "\nAlpha blending \(0x%016llx\) failed returning -- %d !!!", prop_blend, ret); + return; + } + else + fprintf(stdout, "\nPlane with id 0x%x is blended with setting 0x%016llx", plane_id, prop_blend); + } + drmModeFreeProperty(prop); + } + drmModeFreeObjectProperties(props); +} + +static uint32_t create_crtc_fb(data_t *data, + uint16_t w, + uint16_t h, + uint64_t blend_prop, + 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); + + kmstest_paint_color(cr_0, 0, 0, w, h, 0.0, 0.0, 0.0); + + image_0 = fb_0.cairo_surface; + + 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); + + cairo_set_source_surface (cr, image_0, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + 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, + uint64_t blend_prop, + struct kmstest_fb *fb, double blend_val) +{ + 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); + + kmstest_paint_color(cr_0, 0, 0, w, h, 1.0, 1.0, 1.0); + + image_0 = fb_0.cairo_surface; + + 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); + cairo_set_source_surface (cr, image_0, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + 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, uint64_t blend_prop) +{ + igt_pipe_crc_t *pipe_crc = data->pipe_crc[data->crtc_idx]; + igt_crc_t *crcs = NULL; + + usleep(200000); + + 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[blend_prop].frame, igt_crc_to_string(&data->ref_crtc_crc[blend_prop])); + + igt_assert(!igt_crc_equal(&crcs[0], &data->ref_crtc_crc[blend_prop])); + free(crcs); +} + +static void test_sprite_crc(data_t *data, uint64_t blend_prop, double blend_val) +{ + igt_pipe_crc_t *pipe_crc = data->pipe_crc[data->crtc_idx]; + igt_crc_t *crcs = NULL; + + set_blend(data->drm_fd, data->sprite_id, BIT(blend_prop), blend_val); + + usleep(200000); + + 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); + + if (blend_val == 1.0) + { + 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[blend_prop].frame, igt_crc_to_string(&data->ref_sprite_crc[blend_prop])); + + igt_assert(!igt_crc_equal(&crcs[0], &data->ref_sprite_crc[blend_prop])); + } + + free(crcs); +} + +static void get_ref_crtc_crcs(data_t *data, connector_t connector, + igt_pipe_crc_t *pipe_crc, uint64_t blend_prop) +{ + igt_crc_t *crcs = NULL; + + igt_assert(blend_prop < DRM_BLEND_NUM); + + data->crtc_fb_id[blend_prop] = create_crtc_fb(data, + connector.config.default_mode.hdisplay, + connector.config.default_mode.vdisplay, + blend_prop, &connector.fb[blend_prop]); + + igt_assert(data->crtc_fb_id[blend_prop]); + + /* scanout = fb[blend_prop] */ + connector_set_mode(data, &connector, &connector.config.default_mode, + data->crtc_fb_id[blend_prop]); + usleep(200000); + + igt_wait_for_vblank(data->drm_fd, data->crtc_idx); + + /* get reference crc for fb[blend_prop] */ + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs); + data->ref_crtc_crc[blend_prop] = 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, uint64_t blend_prop, double blend_val) +{ + igt_crc_t *crcs = NULL; + uint16_t w = 0, h = 0; + + igt_assert(blend_prop < DRM_BLEND_NUM); + + w = connector.config.default_mode.hdisplay / 2; + h = connector.config.default_mode.vdisplay / 2; + + data->sprite_fb_id[blend_prop] = create_sprite_fb(data, w, h, + blend_prop, &connector.fb[blend_prop], blend_val); + + igt_assert(data->sprite_fb_id[blend_prop]); + + /* scanout = fb[blend_prop] */ + sprite_set_mode(data, &connector, w, h, data->sprite_fb_id[blend_prop]); + usleep(200000); + + igt_wait_for_vblank(data->drm_fd, data->crtc_idx); + + /* get reference crc for fb[blend_prop] */ + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_crcs(pipe_crc, 1, &crcs); + data->ref_sprite_crc[blend_prop] = crcs[0]; + igt_pipe_crc_stop(pipe_crc); + free(crcs); +} + +static bool prepare_sprite(data_t *data, uint32_t connector_id, + double blend_val, uint64_t blend_prop) +{ + 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, blend_prop, blend_val); + + kmstest_free_connector_config(&connector.config); + + return true; +} + +static bool prepare_crtc(data_t *data, uint32_t connector_id, uint64_t blend_prop) +{ + 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, blend_prop); + + 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, double blend_val, uint64_t blend_prop) +{ + 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, blend_prop)) + continue; + + fprintf(stdout, "\nBeginning blending test type(%08llx) on crtc %d, connector %d\n", + blend_prop, data->crtc_id, connector_id); + + if (!prepare_sprite(data, connector_id, blend_val, blend_prop)) + continue; + + test_sprite_crc(data, blend_prop, blend_val); + if (blend_val == 0.0) + { + test_crtc_crc(data, blend_prop); + } + + fprintf(stdout, "\nBlending test type(%08llx) on crtc %d, connector %d: PASSED\n\n", + blend_prop, data->crtc_id, connector_id); + + finish_crtc(data); + } + } +} + +data_t data = {0, }; + +igt_main +{ + double i = 0.0; + 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); + } + + for(i = 0; i <= 1.01; i += 0.025) + { + igt_subtest("sprite-constant-alpha") + run_test(&data, i, DRM_BLEND_PROP_CONST_ALPHA); + } + + + igt_subtest("sprite-src-color") + run_test(&data, i, DRM_BLEND_PROP_SRC_COLOR); + + igt_fixture { + display_fini(&data); + } + +} -- 1.8.5
_______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx