Skip to content

Commit f837297

Browse files
Michel Dänzeralexdeucher
authored andcommitted
drm: Add DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags v2
These flags allow userspace to explicitly specify the target vertical blank period when a flip should take effect. v2: * Add new struct drm_mode_crtc_page_flip_target instead of modifying struct drm_mode_crtc_page_flip, to make sure all existing userspace code keeps compiling (Daniel Vetter) Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 5dd20bb commit f837297

File tree

4 files changed

+86
-10
lines changed

4 files changed

+86
-10
lines changed

drivers/gpu/drm/drm_crtc.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5398,15 +5398,23 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
53985398
int drm_mode_page_flip_ioctl(struct drm_device *dev,
53995399
void *data, struct drm_file *file_priv)
54005400
{
5401-
struct drm_mode_crtc_page_flip *page_flip = data;
5401+
struct drm_mode_crtc_page_flip_target *page_flip = data;
54025402
struct drm_crtc *crtc;
54035403
struct drm_framebuffer *fb = NULL;
54045404
struct drm_pending_vblank_event *e = NULL;
5405-
u32 target_vblank = 0;
5405+
u32 target_vblank = page_flip->sequence;
54065406
int ret = -EINVAL;
54075407

5408-
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
5409-
page_flip->reserved != 0)
5408+
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
5409+
return -EINVAL;
5410+
5411+
if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
5412+
return -EINVAL;
5413+
5414+
/* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
5415+
* can be specified
5416+
*/
5417+
if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
54105418
return -EINVAL;
54115419

54125420
if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
@@ -5417,15 +5425,41 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
54175425
return -ENOENT;
54185426

54195427
if (crtc->funcs->page_flip_target) {
5428+
u32 current_vblank;
54205429
int r;
54215430

54225431
r = drm_crtc_vblank_get(crtc);
54235432
if (r)
54245433
return r;
54255434

5426-
target_vblank = drm_crtc_vblank_count(crtc) +
5427-
!(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
5428-
} else if (crtc->funcs->page_flip == NULL) {
5435+
current_vblank = drm_crtc_vblank_count(crtc);
5436+
5437+
switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
5438+
case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
5439+
if ((int)(target_vblank - current_vblank) > 1) {
5440+
DRM_DEBUG("Invalid absolute flip target %u, "
5441+
"must be <= %u\n", target_vblank,
5442+
current_vblank + 1);
5443+
drm_crtc_vblank_put(crtc);
5444+
return -EINVAL;
5445+
}
5446+
break;
5447+
case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
5448+
if (target_vblank != 0 && target_vblank != 1) {
5449+
DRM_DEBUG("Invalid relative flip target %u, "
5450+
"must be 0 or 1\n", target_vblank);
5451+
drm_crtc_vblank_put(crtc);
5452+
return -EINVAL;
5453+
}
5454+
target_vblank += current_vblank;
5455+
break;
5456+
default:
5457+
target_vblank = current_vblank +
5458+
!(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
5459+
break;
5460+
}
5461+
} else if (crtc->funcs->page_flip == NULL ||
5462+
(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
54295463
return -EINVAL;
54305464
}
54315465

drivers/gpu/drm/drm_ioctl.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ static int drm_getstats(struct drm_device *dev, void *data,
228228
static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
229229
{
230230
struct drm_get_cap *req = data;
231+
struct drm_crtc *crtc;
231232

232233
req->value = 0;
233234
switch (req->capability) {
@@ -254,6 +255,13 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
254255
case DRM_CAP_ASYNC_PAGE_FLIP:
255256
req->value = dev->mode_config.async_page_flip;
256257
break;
258+
case DRM_CAP_PAGE_FLIP_TARGET:
259+
req->value = 1;
260+
drm_for_each_crtc(crtc, dev) {
261+
if (!crtc->funcs->page_flip_target)
262+
req->value = 0;
263+
}
264+
break;
257265
case DRM_CAP_CURSOR_WIDTH:
258266
if (dev->mode_config.cursor_width)
259267
req->value = dev->mode_config.cursor_width;

include/uapi/drm/drm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ struct drm_gem_open {
646646
#define DRM_CAP_CURSOR_WIDTH 0x8
647647
#define DRM_CAP_CURSOR_HEIGHT 0x9
648648
#define DRM_CAP_ADDFB2_MODIFIERS 0x10
649+
#define DRM_CAP_PAGE_FLIP_TARGET 0x11
649650

650651
/** DRM_IOCTL_GET_CAP ioctl argument type */
651652
struct drm_get_cap {

include/uapi/drm/drm_mode.h

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,13 @@ struct drm_color_lut {
520520

521521
#define DRM_MODE_PAGE_FLIP_EVENT 0x01
522522
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
523-
#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC)
523+
#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
524+
#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8
525+
#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \
526+
DRM_MODE_PAGE_FLIP_TARGET_RELATIVE)
527+
#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \
528+
DRM_MODE_PAGE_FLIP_ASYNC | \
529+
DRM_MODE_PAGE_FLIP_TARGET)
524530

525531
/*
526532
* Request a page flip on the specified crtc.
@@ -543,8 +549,7 @@ struct drm_color_lut {
543549
* 'as soon as possible', meaning that it not delay waiting for vblank.
544550
* This may cause tearing on the screen.
545551
*
546-
* The reserved field must be zero until we figure out something
547-
* clever to use it for.
552+
* The reserved field must be zero.
548553
*/
549554

550555
struct drm_mode_crtc_page_flip {
@@ -555,6 +560,34 @@ struct drm_mode_crtc_page_flip {
555560
__u64 user_data;
556561
};
557562

563+
/*
564+
* Request a page flip on the specified crtc.
565+
*
566+
* Same as struct drm_mode_crtc_page_flip, but supports new flags and
567+
* re-purposes the reserved field:
568+
*
569+
* The sequence field must be zero unless either of the
570+
* DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When
571+
* the ABSOLUTE flag is specified, the sequence field denotes the absolute
572+
* vblank sequence when the flip should take effect. When the RELATIVE
573+
* flag is specified, the sequence field denotes the relative (to the
574+
* current one when the ioctl is called) vblank sequence when the flip
575+
* should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to
576+
* make sure the vblank sequence before the target one has passed before
577+
* calling this ioctl. The purpose of the
578+
* DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify
579+
* the target for when code dealing with a page flip runs during a
580+
* vertical blank period.
581+
*/
582+
583+
struct drm_mode_crtc_page_flip_target {
584+
__u32 crtc_id;
585+
__u32 fb_id;
586+
__u32 flags;
587+
__u32 sequence;
588+
__u64 user_data;
589+
};
590+
558591
/* create a dumb scanout buffer */
559592
struct drm_mode_create_dumb {
560593
__u32 height;

0 commit comments

Comments
 (0)