[PATCH] Add drm ioctl DRM_IOCTL_MODE_GETFB2 & associated helpers.
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Tue Aug 1 20:46:18 UTC 2017
Hi Joe,
On Tuesday 01 Aug 2017 10:24:25 Joe Kniss wrote:
> On Tue, Aug 1, 2017 at 5:09 AM, Laurent Pinchart wrote:
> > On Monday 31 Jul 2017 11:29:13 Joe Kniss wrote:
> >> New getfb2 functionality uses drm_mode_fb_cmd2 struct to be symmetric
> >> with addfb2.
> >
> > What's the use case for this ? We haven't needed such an ioctl for so long
> > that it seemed to me that userspace doesn't really need it, but I could be
> > wrong.
>
> Sorry, I failed to reference the original email. Here it is:
>
> <snip>
> I am a recent addition to Google's ChromeOS gfx team. I am currently
> working on display testing and reporting. An important part of this is
> our screen capture tool, which works by querying drm for crtcs, planes, and
> fbs. Unfortunately, there is only limited information available via
> drmModeGetFB(), which often wrong information when drmModeAddFB2() was used
> to create the fbs. For example, if the pixel format is NV12 or YUV420,
> the fb returned knows nothing about the additional buffer planes required
> by these formats. Ideally, we would like a function (e.g. drmModeGetFB2)
> to return information symmetric with drmModeAddFB2 including the pixel
> format id, buffer plane information etc.
> </snip>
>
> ChromeOS has needed this functionality from the start, for both testing and
> error reporting. We got away with guessing the buffer's format (32bit
> xrgb) until now. We are now enabling overlays and more formats including
> multi-planar (e.g. NV12). Current getfb() reports neither the pixel format
> nor planar information. Without this information, going forward, our gfx
> testing is going to break. It would be great if we had access to higher
> level buffer structs (like gbm), but we generally don't since they would be
> created by other apps (chrome browser, android apps, etc...).
How is screen capture implemented ? Do you enumerate the framebuffers being
scanned out, dump their contents and compose them manually based on the active
plane configuration ? If so, isn't this very race-prone ?
> >> Also modifies *_fb_create_handle() calls to accept a
> >> format_plane_index so that handles for each plane can be generated.
> >> Previously, many *_fb_create_handle() calls simply defaulted to plane 0
> >> only.
> >
> > And with this patch the amd/amdgpu, armada, gma500, i915, mediatek, msm,
> > nouveau and radeon drivers still do. Do none of them support multi-planar
> > formats ?
>
> I would imagine that some of these do support multi-planar formats, but
> they don't appear to have them implemented yet (except perhaps as offsets
> into a single buffer). I will certainly be looking into this soon, but any
> changes will come in future patches.
>
> >> Signed-off-by: Joe Kniss <djmk at google.com>
> >> ---
> >>
> >> drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 5 +-
> >> drivers/gpu/drm/armada/armada_fb.c | 1 +
> >> drivers/gpu/drm/drm_crtc_internal.h | 2 +
> >> drivers/gpu/drm/drm_fb_cma_helper.c | 11 ++--
> >> drivers/gpu/drm/drm_framebuffer.c | 79 +++++++++++++++++++-
> >> drivers/gpu/drm/drm_ioctl.c | 1 +
> >> drivers/gpu/drm/exynos/exynos_drm_fb.c | 7 ++-
> >> drivers/gpu/drm/gma500/framebuffer.c | 2 +
> >> drivers/gpu/drm/i915/intel_display.c | 1 +
> >> drivers/gpu/drm/mediatek/mtk_drm_fb.c | 1 +
> >> drivers/gpu/drm/msm/msm_fb.c | 5 +-
> >> drivers/gpu/drm/nouveau/nouveau_display.c | 1 +
> >> drivers/gpu/drm/omapdrm/omap_fb.c | 5 +-
> >> drivers/gpu/drm/radeon/radeon_display.c | 5 +-
> >> drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 6 ++-
> >> drivers/gpu/drm/tegra/fb.c | 9 +++-
> >> include/drm/drm_framebuffer.h | 1 +
> >> include/uapi/drm/drm.h | 2 +
> >> 18 files changed, 127 insertions(+), 17 deletions(-)
> >
> > [snip]
> >
> >> diff --git a/drivers/gpu/drm/drm_framebuffer.c
> >> b/drivers/gpu/drm/drm_framebuffer.c index 28a0108a1ab8..67b3be1bedbc
> >> 100644
> >> --- a/drivers/gpu/drm/drm_framebuffer.c
> >> +++ b/drivers/gpu/drm/drm_framebuffer.c
> >> @@ -24,6 +24,7 @@
[snip]
> >> +/**
> >> + * drm_mode_getfb2 - get FB info
> >> + * @dev: drm device for the ioctl
> >> + * @data: data pointer for the ioctl
> >> + * @file_priv: drm file for the ioctl call
> >> + *
> >> + * Lookup the FB given its ID and return info about it.
> >> + *
> >> + * Called by the user via ioctl.
> >> + *
> >> + * Returns:
> >> + * Zero on success, negative errno on failure.
> >> + */
> >> +int drm_mode_getfb2(struct drm_device *dev,
> >> + void *data, struct drm_file *file_priv)
> >> +{
> >> + struct drm_mode_fb_cmd2 *r = data;
> >> + struct drm_framebuffer *fb;
> >> + int ret, i;
> >> +
> >> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> >> + return -EINVAL;
> >> +
> >> + fb = drm_framebuffer_lookup(dev, r->fb_id);
> >> + if (!fb)
> >> + return -ENOENT;
> >> +
> >> + r->height = fb->height;
> >> + r->width = fb->width;
> >> + r->pixel_format = fb->format->format;
> >> + for (i = 0; i < 4; ++i) {
> >> + r->pitches[i] = fb->pitches[i];
> >> + r->offsets[i] = fb->offsets[i];
> >> + r->modifier[i] = fb->modifier;
> >> + r->handles[i] = 0;
> >> + }
> >> +
> >> + for (i = 0; i < fb->format->num_planes; ++i) {
> >> + if (fb->funcs->create_handle) {
> >> + if (drm_is_current_master(file_priv) ||
> >> + capable(CAP_SYS_ADMIN) ||
> >> + drm_is_control_client(file_priv)) {
> >> + ret = fb->funcs->create_handle(fb, i,
> >> file_priv,
> >> +
> >> &r->handles[i]);
> >> + if (ret)
> >> + break;
> >> + } else {
> >> + /* GET_FB() is an unprivileged ioctl so we
> >> must
> >> + * not return a buffer-handle to
> >> non-master
> >> + * processes! For backwards-compatibility
> >> + * reasons, we cannot make GET_FB()
> >> privileged,
> >> + * so just return an invalid handle for
> >> + * non-masters. */
> >
> > There's no backward compatibility to handle here, just make it privileged
> > if it has to be.
>
> Sure thing, sounds good.
>
> > > + r->handles[i] = 0;
> > > + ret = 0;
> > > + }
> > > + } else {
> > > + ret = -ENODEV;
> > > + break;
> > > + }
> > > + }
> > > +
> > > + /* If handle creation failed, delete/dereference any that were
> >
> > made.
> > */
> >
> > > + if (ret) {
> > > + for (i = 0; i < 4; ++i) {
> > > + if (r->handles[i])
> > > + drm_gem_handle_delete(file_priv, r-
> > >handles[i]);
> >
> > My initial reaction to this was to reply that not all drivers use GEM, but
> > after some investigation it seems they actually do. If that's really the
> > case, we could get rid of the .create_handle() operation completely, which
> > should simplify the implementation of both DRM_IOCTL_MODE_GETFB and
> > DRM_IOCTL_MODE_GETFB2.
>
> Deleting the handle is the same in all cases, but creating the handle
> isn't consistent across the drivers. I didn't see a clean way to simplify
> this.
Creating the handle seems to be fairly consistent, except for a very small
number of special cases. If we stored the GEM object pointers in the
drm_framebuffer structure, the common case would be simplified. Or maybe I've
missed something :-)
> >> + r->handles[i] = 0;
> >> + }
> >> + }
> >> +
> >> + drm_framebuffer_unreference(fb);
> >> +
> >> + return ret;
> >> +}
[snip]
> >> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> >> index b2c52843bc70..c81c75335cca 100644
> >> --- a/include/uapi/drm/drm.h
> >> +++ b/include/uapi/drm/drm.h
> >> @@ -814,6 +814,8 @@ extern "C" {
> >>
> >> #define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct
> >> drm_mode_create_blob)
> >> #define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct
> >> drm_mode_destroy_blob)
> >>
> >> +#define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xC4, struct drm_mode_fb_cmd2)
> >> +
> >
> > Which tree is this based on ? The last defined ioctl
> > (DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE) is 0xC2 in drm-next and drm-misc-next.
>
> I just did a quick search for "DRM_IOWR 0xC*" and picked the first unused
> one, there was a patch in-flight from last month that used 0xC3 (
> https://lists.freedesktop.org/archives/amd-gfx/2017-June/010153.html).
> Naturally, I'll set this to whatever is appropriate.
The best is to base your patch on top of the drm-misc-next branch of the drm-
misc tree. Whoever is merged first will win the ioctl number :-) Of course it
means rebasing if someone else wins the race, but that shouldn't be a big
deal.
> > > /**
> > >
> > > * Device specific ioctls should only be in their respective headers
> > > * The device specific ioctl range is from 0x40 to 0x9f.
--
Regards,
Laurent Pinchart
More information about the amd-gfx
mailing list