1 /*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Daniel Vetter <[email protected]>
25 * Damien Lespiau <[email protected]>
26 */
27
28 #ifndef __IGT_KMS_H__
29 #define __IGT_KMS_H__
30
31 #include <stdbool.h>
32 #include <stdint.h>
33 #include <stddef.h>
34 #include <assert.h>
35
36 #include <xf86drmMode.h>
37
38 #include "igt_fb.h"
39 #include "ioctl_wrappers.h"
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /* Low-level helpers with kmstest_ prefix */
46
47 /**
48 * pipe:
49 * @PIPE_NONE: Invalid pipe, used for disconnecting a output from a pipe.
50 * @PIPE_ANY: Deprecated alias for @PIPE_NONE.
51 * @PIPE_A: First crtc.
52 * @PIPE_B: Second crtc.
53 * @PIPE_C: Third crtc.
54 * @PIPE_D: Fourth crtc.
55 * @PIPE_E: Fifth crtc.
56 * @PIPE_F: Sixth crtc.
57 * @IGT_MAX_PIPES: Max number of pipes allowed.
58 */
59 enum pipe
60 #ifdef __cplusplus
61 : int
62 #endif
63 {
64 PIPE_NONE = -1,
65 PIPE_ANY = PIPE_NONE,
66 PIPE_A = 0,
67 PIPE_B,
68 PIPE_C,
69 PIPE_D,
70 PIPE_E,
71 PIPE_F,
72 IGT_MAX_PIPES
73 };
74 const char *kmstest_pipe_name(enum pipe pipe);
75 int kmstest_pipe_to_index(char pipe);
76 const char *kmstest_plane_type_name(int plane_type);
77
78 enum port {
79 PORT_A = 0,
80 PORT_B,
81 PORT_C,
82 PORT_D,
83 PORT_E,
84 I915_MAX_PORTS
85 };
86
87 /**
88 * kmstest_port_name:
89 * @port: display plane
90 *
91 * Returns: String representing @port, e.g. "A".
92 */
93 #define kmstest_port_name(port) ((port) + 'A')
94
95 const char *kmstest_encoder_type_str(int type);
96 const char *kmstest_connector_status_str(int status);
97 const char *kmstest_connector_type_str(int type);
98
99 void kmstest_dump_mode(drmModeModeInfo *mode);
100
101 int kmstest_get_pipe_from_crtc_id(int fd, int crtc_id);
102 void kmstest_set_vt_graphics_mode(void);
103 void kmstest_restore_vt_mode(void);
104
105 enum igt_atomic_crtc_properties {
106 IGT_CRTC_BACKGROUND = 0,
107 IGT_CRTC_CTM,
108 IGT_CRTC_GAMMA_LUT,
109 IGT_CRTC_GAMMA_LUT_SIZE,
110 IGT_CRTC_DEGAMMA_LUT,
111 IGT_CRTC_DEGAMMA_LUT_SIZE,
112 IGT_CRTC_MODE_ID,
113 IGT_CRTC_ACTIVE,
114 IGT_CRTC_OUT_FENCE_PTR,
115 IGT_CRTC_VRR_ENABLED,
116 IGT_NUM_CRTC_PROPS
117 };
118
119 /**
120 * igt_crtc_prop_names
121 *
122 * igt_crtc_prop_names contains a list of crtc property names,
123 * as indexed by the igt_atomic_crtc_properties enum.
124 */
125 extern const char * const igt_crtc_prop_names[];
126
127 enum igt_atomic_connector_properties {
128 IGT_CONNECTOR_SCALING_MODE = 0,
129 IGT_CONNECTOR_CRTC_ID,
130 IGT_CONNECTOR_DPMS,
131 IGT_CONNECTOR_BROADCAST_RGB,
132 IGT_CONNECTOR_CONTENT_PROTECTION,
133 IGT_CONNECTOR_VRR_CAPABLE,
134 IGT_CONNECTOR_HDCP_CONTENT_TYPE,
135 IGT_CONNECTOR_LINK_STATUS,
136 IGT_NUM_CONNECTOR_PROPS
137 };
138
139 /**
140 * igt_connector_prop_names
141 *
142 * igt_connector_prop_names contains a list of crtc property names,
143 * as indexed by the igt_atomic_connector_properties enum.
144 */
145 extern const char * const igt_connector_prop_names[];
146
147 struct kmstest_connector_config {
148 drmModeCrtc *crtc;
149 drmModeConnector *connector;
150 drmModeEncoder *encoder;
151 drmModeModeInfo default_mode;
152
153 int pipe;
154 unsigned valid_crtc_idx_mask;
155 };
156
157 struct kmstest_plane {
158 int id;
159 int index;
160 int type;
161 int pos_x;
162 int pos_y;
163 int width;
164 int height;
165 };
166
167 struct kmstest_crtc {
168 int id;
169 int pipe;
170 bool active;
171 int width;
172 int height;
173 int n_planes;
174 struct kmstest_plane *planes;
175 };
176
177 /**
178 * kmstest_force_connector_state:
179 * @FORCE_CONNECTOR_UNSPECIFIED: Unspecified
180 * @FORCE_CONNECTOR_ON: On
181 * @FORCE_CONNECTOR_DIGITAL: Digital
182 * @FORCE_CONNECTOR_OFF: Off
183 */
184 enum kmstest_force_connector_state {
185 FORCE_CONNECTOR_UNSPECIFIED,
186 FORCE_CONNECTOR_ON,
187 FORCE_CONNECTOR_DIGITAL,
188 FORCE_CONNECTOR_OFF
189 };
190
191 /**
192 * intel_broadcast_rgb_mode:
193 * @BROADCAST_RGB_AUTO: Choose the color range to use automatically
194 * @BROADCAST_RGB_FULL: Force the connector to use full color range
195 * @BROADCAST_RGB_16_235: Force the connector to use a limited 16:235 color
196 * range
197 */
198 enum intel_broadcast_rgb_mode {
199 BROADCAST_RGB_AUTO = 0,
200 BROADCAST_RGB_FULL,
201 BROADCAST_RGB_16_235
202 };
203
204 struct edid;
205
206 bool kmstest_force_connector(int fd, drmModeConnector *connector,
207 enum kmstest_force_connector_state state);
208 void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
209 const struct edid *edid);
210
211 bool kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
212 drmModeModeInfo *mode);
213 bool kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
214 unsigned long crtc_idx_mask,
215 struct kmstest_connector_config *config);
216 bool kmstest_probe_connector_config(int drm_fd, uint32_t connector_id,
217 unsigned long crtc_idx_mask,
218 struct kmstest_connector_config *config);
219 void kmstest_free_connector_config(struct kmstest_connector_config *config);
220
221 void kmstest_set_connector_dpms(int fd, drmModeConnector *connector, int mode);
222 bool kmstest_get_property(int drm_fd, uint32_t object_id, uint32_t object_type,
223 const char *name, uint32_t *prop_id, uint64_t *value,
224 drmModePropertyPtr *prop);
225 void kmstest_unset_all_crtcs(int drm_fd, drmModeResPtr resources);
226 int kmstest_get_crtc_idx(drmModeRes *res, uint32_t crtc_id);
227 uint32_t kmstest_find_crtc_for_connector(int fd, drmModeRes *res,
228 drmModeConnector *connector,
229 uint32_t crtc_blacklist_idx_mask);
230
231 uint32_t kmstest_dumb_create(int fd, int width, int height, int bpp,
232 unsigned *stride, uint64_t *size);
233
234 void *kmstest_dumb_map_buffer(int fd, uint32_t handle, uint64_t size,
235 unsigned prot);
236 void kmstest_dumb_destroy(int fd, uint32_t handle);
237 void kmstest_wait_for_pageflip(int fd);
238 unsigned int kmstest_get_vblank(int fd, int pipe, unsigned int flags);
239 void igt_assert_plane_visible(int fd, enum pipe pipe, int plane_index, bool visibility);
240
241 bool kms_has_vblank(int fd);
242
243 /*
244 * A small modeset API
245 */
246
247 /* High-level kms api with igt_ prefix */
248
249 /**
250 * igt_commit_style:
251 * @COMMIT_LEGACY: Changes will be committed using the legacy API.
252 * @COMMIT_UNIVERSAL: Changes will be committed with the universal plane API, no modesets are allowed.
253 * @COMMIT_ATOMIC: Changes will be committed using the atomic API.
254 */
255 enum igt_commit_style {
256 COMMIT_LEGACY = 0,
257 COMMIT_UNIVERSAL,
258 COMMIT_ATOMIC,
259 };
260
261 enum igt_atomic_plane_properties {
262 IGT_PLANE_SRC_X = 0,
263 IGT_PLANE_SRC_Y,
264 IGT_PLANE_SRC_W,
265 IGT_PLANE_SRC_H,
266
267 IGT_PLANE_CRTC_X,
268 IGT_PLANE_CRTC_Y,
269 IGT_PLANE_CRTC_W,
270 IGT_PLANE_CRTC_H,
271
272 /* Append new properties after IGT_PLANE_COORD_CHANGED_MASK */
273 #define IGT_PLANE_COORD_CHANGED_MASK 0xff
274
275 IGT_PLANE_FB_ID,
276 IGT_PLANE_CRTC_ID,
277 IGT_PLANE_IN_FENCE_FD,
278 IGT_PLANE_TYPE,
279 IGT_PLANE_ROTATION,
280 IGT_PLANE_IN_FORMATS,
281 IGT_PLANE_COLOR_ENCODING,
282 IGT_PLANE_COLOR_RANGE,
283 IGT_PLANE_PIXEL_BLEND_MODE,
284 IGT_PLANE_ALPHA,
285 IGT_PLANE_ZPOS,
286 IGT_NUM_PLANE_PROPS
287 };
288
289 /**
290 * igt_plane_prop_names
291 *
292 * igt_plane_prop_names contains a list of crtc property names,
293 * as indexed by the igt_atomic_plane_properties enum.
294 */
295 extern const char * const igt_plane_prop_names[];
296
297 typedef struct igt_display igt_display_t;
298 typedef struct igt_pipe igt_pipe_t;
299 typedef uint32_t igt_fixed_t; /* 16.16 fixed point */
300
301 typedef enum {
302 /* this maps to the kernel API */
303 IGT_ROTATION_0 = 1 << 0,
304 IGT_ROTATION_90 = 1 << 1,
305 IGT_ROTATION_180 = 1 << 2,
306 IGT_ROTATION_270 = 1 << 3,
307 IGT_REFLECT_X = 1 << 4,
308 IGT_REFLECT_Y = 1 << 5,
309 } igt_rotation_t;
310
311 #define IGT_ROTATION_MASK \
312 (IGT_ROTATION_0 | IGT_ROTATION_90 | IGT_ROTATION_180 | IGT_ROTATION_270)
313
314 typedef struct igt_plane {
315 /*< private >*/
316 igt_pipe_t *pipe;
317 struct igt_plane *ref;
318 int index;
319 /* capabilities */
320 int type;
321
322 /*
323 * drm_plane can be NULL for primary and cursor planes (when not
324 * using the atomic modeset API)
325 */
326 drmModePlane *drm_plane;
327
328 /* gem handle for fb */
329 uint32_t gem_handle;
330
331 struct {
332 uint64_t values[IGT_NUM_COLOR_ENCODINGS];
333 } color_encoding;
334 struct {
335 uint64_t values[IGT_NUM_COLOR_RANGES];
336 } color_range;
337
338 uint64_t changed;
339 uint32_t props[IGT_NUM_PLANE_PROPS];
340 uint64_t values[IGT_NUM_PLANE_PROPS];
341
342 uint64_t *modifiers;
343 uint32_t *formats;
344 int format_mod_count;
345 } igt_plane_t;
346
347 struct igt_pipe {
348 igt_display_t *display;
349 enum pipe pipe;
350
351 int n_planes;
352 int plane_cursor;
353 int plane_primary;
354 igt_plane_t *planes;
355
356 uint64_t changed;
357 uint32_t props[IGT_NUM_CRTC_PROPS];
358 uint64_t values[IGT_NUM_CRTC_PROPS];
359
360 uint32_t crtc_id;
361
362 int32_t out_fence_fd;
363 };
364
365 typedef struct {
366 /*< private >*/
367 igt_display_t *display;
368 uint32_t id; /* KMS id */
369 struct kmstest_connector_config config;
370 char *name;
371 bool force_reprobe;
372 enum pipe pending_pipe;
373 bool use_override_mode;
374 drmModeModeInfo override_mode;
375
376 /* bitmask of changed properties */
377 uint64_t changed;
378
379 uint32_t props[IGT_NUM_CONNECTOR_PROPS];
380 uint64_t values[IGT_NUM_CONNECTOR_PROPS];
381 } igt_output_t;
382
383 struct igt_display {
384 int drm_fd;
385 int log_shift;
386 int n_pipes;
387 int n_planes;
388 int n_outputs;
389 igt_output_t *outputs;
390 igt_plane_t *planes;
391 igt_pipe_t *pipes;
392 bool has_cursor_plane;
393 bool is_atomic;
394 bool first_commit;
395
396 uint64_t *modifiers;
397 uint32_t *formats;
398 int format_mod_count;
399 };
400
401 void igt_display_require(igt_display_t *display, int drm_fd);
402 void igt_display_fini(igt_display_t *display);
403 void igt_display_reset(igt_display_t *display);
404 int igt_display_commit2(igt_display_t *display, enum igt_commit_style s);
405 int igt_display_commit(igt_display_t *display);
406 int igt_display_try_commit_atomic(igt_display_t *display, uint32_t flags, void *user_data);
407 void igt_display_commit_atomic(igt_display_t *display, uint32_t flags, void *user_data);
408 int igt_display_try_commit2(igt_display_t *display, enum igt_commit_style s);
409 int igt_display_drop_events(igt_display_t *display);
410 int igt_display_get_n_pipes(igt_display_t *display);
411 void igt_display_require_output(igt_display_t *display);
412 void igt_display_require_output_on_pipe(igt_display_t *display, enum pipe pipe);
413
414 const char *igt_output_name(igt_output_t *output);
415 drmModeModeInfo *igt_output_get_mode(igt_output_t *output);
416 void igt_output_override_mode(igt_output_t *output, const drmModeModeInfo *mode);
417 void igt_output_set_pipe(igt_output_t *output, enum pipe pipe);
418 igt_plane_t *igt_output_get_plane(igt_output_t *output, int plane_idx);
419 igt_plane_t *igt_output_get_plane_type(igt_output_t *output, int plane_type);
420 int igt_output_count_plane_type(igt_output_t *output, int plane_type);
421 igt_plane_t *igt_output_get_plane_type_index(igt_output_t *output,
422 int plane_type, int index);
423 igt_output_t *igt_output_from_connector(igt_display_t *display,
424 drmModeConnector *connector);
425 const drmModeModeInfo *igt_std_1024_mode_get(void);
426
427 igt_plane_t *igt_pipe_get_plane_type(igt_pipe_t *pipe, int plane_type);
428 int igt_pipe_count_plane_type(igt_pipe_t *pipe, int plane_type);
429 igt_plane_t *igt_pipe_get_plane_type_index(igt_pipe_t *pipe, int plane_type,
430 int index);
431 igt_output_t *igt_get_single_output_for_pipe(igt_display_t *display, enum pipe pipe);
432
433 void igt_pipe_request_out_fence(igt_pipe_t *pipe);
434
435 void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb);
436 void igt_plane_set_fence_fd(igt_plane_t *plane, int fence_fd);
437 void igt_plane_set_pipe(igt_plane_t *plane, igt_pipe_t *pipe);
438 void igt_plane_set_position(igt_plane_t *plane, int x, int y);
439 void igt_plane_set_size(igt_plane_t *plane, int w, int h);
440 void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation);
441 void igt_fb_set_position(struct igt_fb *fb, igt_plane_t *plane,
442 uint32_t x, uint32_t y);
443 void igt_fb_set_size(struct igt_fb *fb, igt_plane_t *plane,
444 uint32_t w, uint32_t h);
445
446 void igt_wait_for_vblank(int drm_fd, enum pipe pipe);
447 void igt_wait_for_vblank_count(int drm_fd, enum pipe pipe, int count);
448
igt_output_is_connected(igt_output_t * output)449 static inline bool igt_output_is_connected(igt_output_t *output)
450 {
451 /* Something went wrong during probe? */
452 if (!output->config.connector ||
453 !output->config.connector->count_modes)
454 return false;
455
456 if (output->config.connector->connection == DRM_MODE_CONNECTED)
457 return true;
458
459 return false;
460 }
461
462 /**
463 * igt_pipe_connector_valid:
464 * @pipe: pipe to check.
465 * @output: #igt_output_t to check.
466 *
467 * Checks whether the given pipe and output can be used together.
468 */
469 #define igt_pipe_connector_valid(pipe, output) \
470 (igt_output_is_connected((output)) && \
471 (output->config.valid_crtc_idx_mask & (1 << (pipe))))
472
473 #define for_each_if(condition) if (!(condition)) {} else
474
475 /**
476 * for_each_connected_output:
477 * @display: a pointer to an #igt_display_t structure
478 * @output: The output to iterate.
479 *
480 * This for loop iterates over all outputs.
481 */
482 #define for_each_connected_output(display, output) \
483 for (int i__ = 0; assert(igt_can_fail()), i__ < (display)->n_outputs; i__++) \
484 for_each_if ((((output) = &(display)->outputs[i__]), \
485 igt_output_is_connected((output))))
486
487 /**
488 * for_each_pipe_static:
489 * @pipe: The pipe to iterate.
490 *
491 * This for loop iterates over all pipes supported by IGT libraries.
492 *
493 * This should be used to enumerate per-pipe subtests since it has no runtime
494 * depencies.
495 */
496 #define for_each_pipe_static(pipe) \
497 for (pipe = 0; pipe < IGT_MAX_PIPES; pipe++)
498
499 /**
500 * for_each_pipe:
501 * @display: a pointer to an #igt_display_t structure
502 * @pipe: The pipe to iterate.
503 *
504 * This for loop iterates over all pipes.
505 *
506 * Note that this cannot be used to enumerate per-pipe subtest names since it
507 * depends upon runtime probing of the actual kms driver that is being tested.
508 * Use #for_each_pipe_static instead.
509 */
510 #ifdef __cplusplus
511 #define for_each_pipe(display, pipe_i) \
512 for (pipe_i = (enum pipe)0; assert(igt_can_fail()), pipe_i < igt_display_get_n_pipes(display); pipe_i = (enum pipe)((int)pipe_i + 1))
513 #else
514 #define for_each_pipe(display, pipe) \
515 for (pipe = 0; assert(igt_can_fail()), pipe < igt_display_get_n_pipes(display); pipe++)
516 #endif
517
518 /**
519 * for_each_pipe_with_valid_output:
520 * @display: a pointer to an #igt_display_t structure
521 * @pipe: The pipe for which this @pipe / @output combination is valid.
522 * @output: The output for which this @pipe / @output combination is valid.
523 *
524 * This for loop is called over all connected outputs. This function
525 * will try every combination of @pipe and @output.
526 *
527 * If you only need to test a single output for each pipe, use
528 * for_each_pipe_with_single_output(), if you only need an
529 * output for a single pipe, use igt_get_single_output_for_pipe().
530 */
531 #define for_each_pipe_with_valid_output(display, pipe, output) \
532 for (int con__ = (pipe) = 0; \
533 assert(igt_can_fail()), (pipe) < igt_display_get_n_pipes((display)) && con__ < (display)->n_outputs; \
534 con__ = (con__ + 1 < (display)->n_outputs) ? con__ + 1 : (pipe = pipe + 1, 0)) \
535 for_each_if ((((output) = &(display)->outputs[con__]), \
536 igt_pipe_connector_valid((pipe), (output))))
537
538 igt_output_t **__igt_pipe_populate_outputs(igt_display_t *display,
539 igt_output_t **chosen_outputs);
540
541 /**
542 * for_each_pipe_with_single_output:
543 * @display: a pointer to an #igt_display_t structure
544 * @pipe: The pipe for which this @pipe / @output combination is valid.
545 * @output: The output for which this @pipe / @output combination is valid.
546 *
547 * This loop is called over all pipes, and will try to find a compatible output
548 * for each pipe. Unlike for_each_pipe_with_valid_output(), this function will
549 * be called at most once for each pipe.
550 */
551 #define for_each_pipe_with_single_output(display, pipe, output) \
552 for (igt_output_t *__outputs[(display)->n_pipes], \
553 **__output = __igt_pipe_populate_outputs((display), __outputs); \
554 __output < &__outputs[(display)->n_pipes]; __output++) \
555 for_each_if (*__output && \
556 ((pipe) = (__output - __outputs), (output) = *__output, 1))
557
558 /**
559 * for_each_valid_output_on_pipe:
560 * @display: a pointer to an #igt_display_t structure
561 * @pipe: Pipe to enumerate valid outputs over
562 * @output: The enumerated output.
563 *
564 * This for loop is called over all connected @output that can be used
565 * on this @pipe . If there are no valid outputs for this pipe, nothing
566 * happens.
567 */
568 #define for_each_valid_output_on_pipe(display, pipe, output) \
569 for_each_connected_output((display), (output)) \
570 for_each_if (igt_pipe_connector_valid((pipe), (output)))
571
572 #define for_each_plane_on_pipe(display, pipe, plane) \
573 for (int j__ = 0; assert(igt_can_fail()), (plane) = &(display)->pipes[(pipe)].planes[j__], \
574 j__ < (display)->pipes[(pipe)].n_planes; j__++)
575
576 #define IGT_FIXED(i,f) ((i) << 16 | (f))
577
578 /**
579 * igt_plane_has_prop:
580 * @plane: Plane to check.
581 * @prop: Property to check.
582 *
583 * Check whether plane supports a given property.
584 *
585 * Returns: True if the property is supported, otherwise false.
586 */
587 static inline bool
igt_plane_has_prop(igt_plane_t * plane,enum igt_atomic_plane_properties prop)588 igt_plane_has_prop(igt_plane_t *plane, enum igt_atomic_plane_properties prop)
589 {
590 return plane->props[prop];
591 }
592
593 uint64_t igt_plane_get_prop(igt_plane_t *plane, enum igt_atomic_plane_properties prop);
594
595 #define igt_plane_is_prop_changed(plane, prop) \
596 (!!((plane)->changed & (1 << (prop))))
597
598 #define igt_plane_set_prop_changed(plane, prop) \
599 (plane)->changed |= 1 << (prop)
600
601 #define igt_plane_clear_prop_changed(plane, prop) \
602 (plane)->changed &= ~(1 << (prop))
603
604 #define igt_plane_set_prop_value(plane, prop, value) \
605 do { \
606 plane->values[prop] = value; \
607 igt_plane_set_prop_changed(plane, prop); \
608 } while (0)
609
610 extern bool igt_plane_try_prop_enum(igt_plane_t *plane,
611 enum igt_atomic_plane_properties prop,
612 const char *val);
613
614 extern void igt_plane_set_prop_enum(igt_plane_t *plane,
615 enum igt_atomic_plane_properties prop,
616 const char *val);
617
618 extern void igt_plane_replace_prop_blob(igt_plane_t *plane,
619 enum igt_atomic_plane_properties prop,
620 const void *ptr, size_t length);
621
622 /**
623 * igt_output_has_prop:
624 * @output: Output to check.
625 * @prop: Property to check.
626 *
627 * Check whether output supports a given property.
628 *
629 * Returns: True if the property is supported, otherwise false.
630 */
631 static inline bool
igt_output_has_prop(igt_output_t * output,enum igt_atomic_connector_properties prop)632 igt_output_has_prop(igt_output_t *output, enum igt_atomic_connector_properties prop)
633 {
634 return output->props[prop];
635 }
636
637 uint64_t igt_output_get_prop(igt_output_t *output, enum igt_atomic_connector_properties prop);
638
639 #define igt_output_is_prop_changed(output, prop) \
640 (!!((output)->changed & (1 << (prop))))
641 #define igt_output_set_prop_changed(output, prop) \
642 (output)->changed |= 1 << (prop)
643
644 #define igt_output_clear_prop_changed(output, prop) \
645 (output)->changed &= ~(1 << (prop))
646
647 #define igt_output_set_prop_value(output, prop, value) \
648 do { \
649 (output)->values[prop] = (value); \
650 igt_output_set_prop_changed(output, prop); \
651 } while (0)
652
653 extern bool igt_output_try_prop_enum(igt_output_t *output,
654 enum igt_atomic_connector_properties prop,
655 const char *val);
656
657 extern void igt_output_set_prop_enum(igt_output_t *output,
658 enum igt_atomic_connector_properties prop,
659 const char *val);
660
661 extern void igt_output_replace_prop_blob(igt_output_t *output,
662 enum igt_atomic_connector_properties prop,
663 const void *ptr, size_t length);
664 /**
665 * igt_pipe_obj_has_prop:
666 * @pipe: Pipe to check.
667 * @prop: Property to check.
668 *
669 * Check whether pipe supports a given property.
670 *
671 * Returns: True if the property is supported, otherwise false.
672 */
673 static inline bool
igt_pipe_obj_has_prop(igt_pipe_t * pipe,enum igt_atomic_crtc_properties prop)674 igt_pipe_obj_has_prop(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop)
675 {
676 return pipe->props[prop];
677 }
678
679 uint64_t igt_pipe_obj_get_prop(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop);
680
681 /**
682 * igt_pipe_get_prop:
683 * @display: Pointer to display.
684 * @pipe: Target pipe.
685 * @prop: Property to return.
686 *
687 * Return current value on a pipe for a given property.
688 *
689 * Returns: The value the property is set to, if this
690 * is a blob, the blob id is returned. This can be passed
691 * to drmModeGetPropertyBlob() to get the contents of the blob.
692 */
693 static inline uint64_t
igt_pipe_get_prop(igt_display_t * display,enum pipe pipe,enum igt_atomic_crtc_properties prop)694 igt_pipe_get_prop(igt_display_t *display, enum pipe pipe,
695 enum igt_atomic_crtc_properties prop)
696 {
697 return igt_pipe_obj_get_prop(&display->pipes[pipe], prop);
698 }
699
700 /**
701 * igt_pipe_has_prop:
702 * @display: Pointer to display.
703 * @pipe: Pipe to check.
704 * @prop: Property to check.
705 *
706 * Check whether pipe supports a given property.
707 *
708 * Returns: True if the property is supported, otherwise false.
709 */
710 static inline bool
igt_pipe_has_prop(igt_display_t * display,enum pipe pipe,enum igt_atomic_crtc_properties prop)711 igt_pipe_has_prop(igt_display_t *display, enum pipe pipe,
712 enum igt_atomic_crtc_properties prop)
713 {
714 return display->pipes[pipe].props[prop];
715 }
716
717 #define igt_pipe_obj_is_prop_changed(pipe_obj, prop) \
718 (!!((pipe_obj)->changed & (1 << (prop))))
719
720 #define igt_pipe_is_prop_changed(display, pipe, prop) \
721 igt_pipe_obj_is_prop_changed(&(display)->pipes[(pipe)], prop)
722
723 #define igt_pipe_obj_set_prop_changed(pipe_obj, prop) \
724 (pipe_obj)->changed |= 1 << (prop)
725
726 #define igt_pipe_set_prop_changed(display, pipe, prop) \
727 igt_pipe_obj_set_prop_changed(&(display)->pipes[(pipe)], prop)
728
729 #define igt_pipe_obj_clear_prop_changed(pipe_obj, prop) \
730 (pipe_obj)->changed &= ~(1 << (prop))
731
732 #define igt_pipe_clear_prop_changed(display, pipe, prop) \
733 igt_pipe_obj_clear_prop_changed(&(display)->pipes[(pipe)], prop)
734
735 #define igt_pipe_obj_set_prop_value(pipe_obj, prop, value) \
736 do { \
737 (pipe_obj)->values[prop] = (value); \
738 igt_pipe_obj_set_prop_changed(pipe_obj, prop); \
739 } while (0)
740
741 #define igt_pipe_set_prop_value(display, pipe, prop, value) \
742 igt_pipe_obj_set_prop_value(&(display)->pipes[(pipe)], prop, value)
743
744 extern bool igt_pipe_obj_try_prop_enum(igt_pipe_t *pipe,
745 enum igt_atomic_crtc_properties prop,
746 const char *val);
747
748 extern void igt_pipe_obj_set_prop_enum(igt_pipe_t *pipe,
749 enum igt_atomic_crtc_properties prop,
750 const char *val);
751
752 #define igt_pipe_try_prop_enum(display, pipe, prop, val) \
753 igt_pipe_obj_try_prop_enum(&(display)->pipes[(pipe)], prop, val)
754
755 #define igt_pipe_set_prop_enum(display, pipe, prop, val) \
756 igt_pipe_obj_set_prop_enum(&(display)->pipes[(pipe)], prop, val)
757
758 extern void igt_pipe_obj_replace_prop_blob(igt_pipe_t *pipe,
759 enum igt_atomic_crtc_properties prop,
760 const void *ptr, size_t length);
761
762 #define igt_pipe_replace_prop_blob(display, pipe, prop, ptr, length) \
763 igt_pipe_obj_replace_prop_blob(&(display)->pipes[(pipe)], prop, ptr, length)
764
765 void igt_pipe_refresh(igt_display_t *display, enum pipe pipe, bool force);
766
767 void igt_enable_connectors(int drm_fd);
768 void igt_reset_connectors(void);
769
770 uint32_t kmstest_get_vbl_flag(uint32_t pipe_id);
771
772 const struct edid *igt_kms_get_base_edid(void);
773 const struct edid *igt_kms_get_alt_edid(void);
774 const struct edid *igt_kms_get_hdmi_audio_edid(void);
775 const struct edid *igt_kms_get_dp_audio_edid(void);
776 const struct edid *igt_kms_get_4k_edid(void);
777 const struct edid *igt_kms_get_3d_edid(void);
778
779 struct udev_monitor *igt_watch_hotplug(void);
780 bool igt_hotplug_detected(struct udev_monitor *mon,
781 int timeout_secs);
782 bool igt_lease_change_detected(struct udev_monitor *mon,
783 int timeout_secs);
784 void igt_flush_hotplugs(struct udev_monitor *mon);
785 void igt_cleanup_hotplug(struct udev_monitor *mon);
786
787 bool igt_display_has_format_mod(igt_display_t *display, uint32_t format, uint64_t modifier);
788 bool igt_plane_has_format_mod(igt_plane_t *plane, uint32_t format, uint64_t modifier);
789
790 /**
791 * igt_vblank_after_eq:
792 * @a: First vblank sequence number.
793 * @b: Second vblank sequence number.
794 *
795 * Compare vblank sequence numbers,
796 * handling wraparound correctly.
797 *
798 * Returns: @a >= @b
799 */
igt_vblank_after_eq(uint32_t a,uint32_t b)800 static inline bool igt_vblank_after_eq(uint32_t a, uint32_t b)
801 {
802 return (int32_t)(a - b) >= 0;
803 }
804
805 /**
806 * igt_vblank_before_eq:
807 * @a: First vblank sequence number.
808 * @b: Second vblank sequence number.
809 *
810 * Compare vblank sequence numbers,
811 * handling wraparound correctly.
812 *
813 * Returns: @a <= @b
814 */
igt_vblank_before_eq(uint32_t a,uint32_t b)815 static inline bool igt_vblank_before_eq(uint32_t a, uint32_t b)
816 {
817 return igt_vblank_after_eq(b, a);
818 }
819
820 /**
821 * igt_vblank_after:
822 * @a: First vblank sequence number.
823 * @b: Second vblank sequence number.
824 *
825 * Compare vblank sequence numbers,
826 * handling wraparound correctly.
827 *
828 * Returns: @a > @b
829 */
igt_vblank_after(uint32_t a,uint32_t b)830 static inline bool igt_vblank_after(uint32_t a, uint32_t b)
831 {
832 return (int32_t)(b - a) < 0;
833 }
834
835 /**
836 * igt_vblank_before:
837 * @a: First vblank sequence number.
838 * @b: Second vblank sequence number.
839 *
840 * Compare vblank sequence numbers,
841 * handling wraparound correctly.
842 *
843 * Returns: @a < @b
844 */
igt_vblank_before(uint32_t a,uint32_t b)845 static inline bool igt_vblank_before(uint32_t a, uint32_t b)
846 {
847 return igt_vblank_after(b, a);
848 }
849
850 #ifdef __cplusplus
851 }
852 #endif
853
854 #endif /* __IGT_KMS_H__ */
855