static void plane_primary(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; uint32_t format = plane_get_igt_format(&plane); drmModeAtomicReq *req = drmModeAtomicAlloc(); uint32_t *connectors; int num_connectors; struct igt_fb fb; int i; connectors = calloc(crtc->state->num_connectors, sizeof(*connectors)); igt_assert(connectors); for (i = 0; i < crtc->state->num_connectors; i++) { if (crtc->state->connectors[i].crtc_id == crtc->obj) connectors[num_connectors++] = crtc->state->connectors[i].obj; } igt_require(format != 0); plane.src_x = 0; plane.src_y = 0; plane.src_w = mode->hdisplay << 16; plane.src_h = mode->vdisplay << 16; plane.crtc_x = 0; plane.crtc_y = 0; plane.crtc_w = mode->hdisplay; plane.crtc_h = mode->vdisplay; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd, plane.crtc_w, plane.crtc_h, format, I915_TILING_NONE, &fb); /* Flip the primary plane using the atomic API, and double-check * state is what we think it should be. */ crtc_commit_atomic(crtc, &plane, req, ATOMIC_RELAX_NONE); /* Restore the primary plane and check the state matches the old. */ crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE); /* Re-enable the plane through the legacy CRTC/primary-plane API, and * verify through atomic. */ crtc_commit_legacy(crtc, &plane, CRTC_RELAX_MODE); /* Restore the plane to its original settings through the legacy CRTC * API, and verify through atomic. */ crtc_commit_legacy(crtc, plane_old, CRTC_RELAX_MODE); /* Finally, restore to the original state. */ crtc_commit_atomic(crtc, plane_old, req, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe, igt_plane_t *plane, drmModeModeInfo *mode, enum igt_commit_style s) { igt_display_t *display = &data->display; igt_output_set_pipe(output, pipe); /* create the pipe_crc object for this pipe */ igt_pipe_crc_free(data->pipe_crc); data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); /* before allocating, free if any older fb */ if (data->fb_id1) { igt_remove_fb(data->drm_fd, &data->fb1); data->fb_id1 = 0; } /* allocate fb for plane 1 */ data->fb_id1 = igt_create_pattern_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ &data->fb1); igt_assert(data->fb_id1); /* * We always set the primary plane to actually enable the pipe as * there's no way (that works) to light up a pipe with only a sprite * plane enabled at the moment. */ if (!plane->is_primary) { igt_plane_t *primary; primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); igt_plane_set_fb(primary, &data->fb1); } igt_plane_set_fb(plane, &data->fb1); if (s == COMMIT_LEGACY) { int ret; ret = drmModeSetCrtc(data->drm_fd, output->config.crtc->crtc_id, data->fb_id1, plane->pan_x, plane->pan_y, &output->id, 1, mode); igt_assert_eq(ret, 0); } else { igt_display_commit2(display, s); } }
static void plane_overlay(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; uint32_t format = plane_get_igt_format(&plane); drmModeAtomicReq *req = drmModeAtomicAlloc(); struct igt_fb fb; igt_require(req); igt_require(format != 0); plane.src_x = 0; plane.src_y = 0; plane.src_w = (mode->hdisplay / 2) << 16; plane.src_h = (mode->vdisplay / 2) << 16; plane.crtc_x = mode->hdisplay / 4; plane.crtc_y = mode->vdisplay / 4; plane.crtc_w = mode->hdisplay / 2; plane.crtc_h = mode->vdisplay / 2; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd, plane.crtc_w, plane.crtc_h, format, I915_TILING_NONE, &fb); /* Enable the overlay plane using the atomic API, and double-check * state is what we think it should be. */ plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Disable the plane and check the state matches the old. */ plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE); /* Re-enable the plane through the legacy plane API, and verify through * atomic. */ plane_commit_legacy(&plane, ATOMIC_RELAX_NONE); /* Restore the plane to its original settings through the legacy plane * API, and verify through atomic. */ plane_commit_legacy(plane_old, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void plane_invalid_params(struct kms_atomic_crtc_state *crtc, struct kms_atomic_plane_state *plane_old, struct kms_atomic_connector_state *conn) { struct drm_mode_modeinfo *mode = crtc->mode.data; struct kms_atomic_plane_state plane = *plane_old; uint32_t format = plane_get_igt_format(&plane); drmModeAtomicReq *req = drmModeAtomicAlloc(); struct igt_fb fb; /* Pass a series of invalid object IDs for the FB ID. */ plane.fb_id = plane.obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = crtc->obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = conn->obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = crtc->mode.id; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.fb_id = plane_old->fb_id; plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Pass a series of invalid object IDs for the CRTC ID. */ plane.crtc_id = plane.obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = plane.fb_id; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = conn->obj; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = crtc->mode.id; plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, EINVAL); plane.crtc_id = plane_old->crtc_id; plane_commit_atomic(&plane, req, ATOMIC_RELAX_NONE); /* Create a framebuffer too small for the plane configuration. */ igt_require(format != 0); plane.src_x = 0; plane.src_y = 0; plane.src_w = mode->hdisplay << 16; plane.src_h = mode->vdisplay << 16; plane.crtc_x = 0; plane.crtc_y = 0; plane.crtc_w = mode->hdisplay; plane.crtc_h = mode->vdisplay; plane.crtc_id = crtc->obj; plane.fb_id = igt_create_pattern_fb(plane.state->desc->fd, plane.crtc_w - 1, plane.crtc_h - 1, format, I915_TILING_NONE, &fb); plane_commit_atomic_err(&plane, plane_old, req, ATOMIC_RELAX_NONE, ENOSPC); /* Restore the primary plane and check the state matches the old. */ plane_commit_atomic(plane_old, req, ATOMIC_RELAX_NONE); drmModeAtomicFree(req); }
static void set_mode(struct connector *c) { unsigned int fb_id = 0; struct igt_fb fb_info[2] = { }; int j, test_mode_num, current_fb = 0, old_fb = -1; test_mode_num = 1; if (force_mode){ memcpy( &c->mode, &force_timing, sizeof(force_timing)); c->mode.vrefresh =(force_timing.clock*1e3)/(force_timing.htotal*force_timing.vtotal); c->mode_valid = 1; sprintf(c->mode.name, "%dx%d", force_timing.hdisplay, force_timing.vdisplay); } else if (test_all_modes) test_mode_num = c->connector->count_modes; for (j = 0; j < test_mode_num; j++) { if (test_all_modes) c->mode = c->connector->modes[j]; /* set_mode() only tests 2D modes */ if (c->mode.flags & DRM_MODE_FLAG_3D_MASK) continue; if (!c->mode_valid) continue; width = c->mode.hdisplay; height = c->mode.vdisplay; fb_id = igt_create_pattern_fb(drm_fd, width, height, igt_bpp_depth_to_drm_format(bpp, depth), tiling, &fb_info[current_fb]); paint_output_info(c, &fb_info[current_fb]); paint_color_key(&fb_info[current_fb]); igt_info("CRTC(%u):[%d]", c->crtc, j); kmstest_dump_mode(&c->mode); if (drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0, &c->id, 1, &c->mode)) { igt_warn("failed to set mode (%dx%d@%dHz): %s\n", width, height, c->mode.vrefresh, strerror(errno)); igt_remove_fb(drm_fd, &fb_info[current_fb]); continue; } if (old_fb != -1) igt_remove_fb(drm_fd, &fb_info[old_fb]); old_fb = current_fb; current_fb = 1 - current_fb; if (sleep_between_modes && test_all_modes && !qr_code) sleep(sleep_between_modes); if (do_dpms) { kmstest_set_connector_dpms(drm_fd, c->connector, do_dpms); sleep(sleep_between_modes); kmstest_set_connector_dpms(drm_fd, c->connector, DRM_MODE_DPMS_ON); } if (qr_code){ set_single(); pause(); } } if (test_all_modes && old_fb != -1) igt_remove_fb(drm_fd, &fb_info[old_fb]); drmModeFreeEncoder(c->encoder); drmModeFreeConnector(c->connector); }
static void test_plane_scaling(data_t *d) { igt_display_t *display = &d->display; igt_output_t *output; enum pipe pipe; int valid_tests = 0; int primary_plane_scaling = 0; /* For now */ igt_require(d->display.has_universal_planes); igt_require(d->num_scalers); for_each_connected_output(display, output) { drmModeModeInfo *mode; pipe = output->config.pipe; igt_output_set_pipe(output, pipe); mode = igt_output_get_mode(output); /* allocate fb2 with image size */ d->fb_id2 = igt_create_image_fb(d->drm_fd, 0, 0, DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ FILE_NAME, &d->fb2); igt_assert(d->fb_id2); d->fb_id3 = igt_create_pattern_fb(d->drm_fd, mode->hdisplay, mode->vdisplay, DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ &d->fb3); igt_assert(d->fb_id3); /* Set up display with plane 1 */ d->plane1 = igt_output_get_plane(output, IGT_PLANE_PRIMARY); prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_UNIVERSAL); if (primary_plane_scaling) { /* Primary plane upscaling */ igt_fb_set_position(&d->fb1, d->plane1, 100, 100); igt_fb_set_size(&d->fb1, d->plane1, 500, 500); igt_plane_set_position(d->plane1, 0, 0); igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); igt_display_commit2(display, COMMIT_UNIVERSAL); /* Primary plane 1:1 no scaling */ igt_fb_set_position(&d->fb1, d->plane1, 0, 0); igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width, d->fb1.height); igt_plane_set_position(d->plane1, 0, 0); igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); igt_display_commit2(display, COMMIT_UNIVERSAL); } /* Set up fb2->plane2 mapping. */ d->plane2 = igt_output_get_plane(output, IGT_PLANE_2); igt_plane_set_fb(d->plane2, &d->fb2); /* 2nd plane windowed */ igt_fb_set_position(&d->fb2, d->plane2, 100, 100); igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width-200, d->fb2.height-200); igt_plane_set_position(d->plane2, 100, 100); igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200); igt_display_commit2(display, COMMIT_UNIVERSAL); iterate_plane_scaling(d, mode); /* 2nd plane up scaling */ igt_fb_set_position(&d->fb2, d->plane2, 100, 100); igt_fb_set_size(&d->fb2, d->plane2, 500, 500); igt_plane_set_position(d->plane2, 10, 10); igt_plane_set_size(d->plane2, mode->hdisplay-20, mode->vdisplay-20); igt_display_commit2(display, COMMIT_UNIVERSAL); /* 2nd plane downscaling */ igt_fb_set_position(&d->fb2, d->plane2, 0, 0); igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width, d->fb2.height); igt_plane_set_position(d->plane2, 10, 10); igt_plane_set_size(d->plane2, 500, 500 * d->fb2.height/d->fb2.width); igt_display_commit2(display, COMMIT_UNIVERSAL); if (primary_plane_scaling) { /* Primary plane up scaling */ igt_fb_set_position(&d->fb1, d->plane1, 100, 100); igt_fb_set_size(&d->fb1, d->plane1, 500, 500); igt_plane_set_position(d->plane1, 0, 0); igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); igt_display_commit2(display, COMMIT_UNIVERSAL); } /* Set up fb3->plane3 mapping. */ d->plane3 = igt_output_get_plane(output, IGT_PLANE_3); igt_plane_set_fb(d->plane3, &d->fb3); /* 3rd plane windowed - no scaling */ igt_fb_set_position(&d->fb3, d->plane3, 100, 100); igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width-300, d->fb3.height-300); igt_plane_set_position(d->plane3, 100, 100); igt_plane_set_size(d->plane3, mode->hdisplay-300, mode->vdisplay-300); igt_display_commit2(display, COMMIT_UNIVERSAL); /* Switch scaler from plane 2 to plane 3 */ igt_fb_set_position(&d->fb2, d->plane2, 100, 100); igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width-200, d->fb2.height-200); igt_plane_set_position(d->plane2, 100, 100); igt_plane_set_size(d->plane2, d->fb2.width-200, d->fb2.height-200); igt_fb_set_position(&d->fb3, d->plane3, 100, 100); igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width-400, d->fb3.height-400); igt_plane_set_position(d->plane3, 10, 10); igt_plane_set_size(d->plane3, mode->hdisplay-300, mode->vdisplay-300); igt_display_commit2(display, COMMIT_UNIVERSAL); if (primary_plane_scaling) { /* Switch scaler from plane 1 to plane 2 */ igt_fb_set_position(&d->fb1, d->plane1, 0, 0); igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width, d->fb1.height); igt_plane_set_position(d->plane1, 0, 0); igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); igt_fb_set_position(&d->fb2, d->plane2, 100, 100); igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width-500,d->fb2.height-500); igt_plane_set_position(d->plane2, 100, 100); igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200); igt_display_commit2(display, COMMIT_UNIVERSAL); } /* back to single plane mode */ igt_plane_set_fb(d->plane2, NULL); igt_plane_set_fb(d->plane3, NULL); igt_display_commit2(display, COMMIT_UNIVERSAL); valid_tests++; cleanup_crtc(d, output, d->plane1); }