diff options
author | Rob Clark <robdclark@gmail.com> | 2015-02-05 09:41:52 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-02-13 17:28:12 -0500 |
commit | e3eb3250d84ef97b766312345774367b6a310db8 (patch) | |
tree | 7220c957097ad78df34d6d2aeacc8afdadb1a9d4 /drivers/gpu/drm | |
parent | 17d5538d54c9f9d6e2b44e07d4d577304e22c17a (diff) |
drm: add support for tiled/compressed/etc modifier in addfb2
In DRM/KMS we are lacking a good way to deal with tiled/compressed
formats. Especially in the case of dmabuf/prime buffer sharing, where
we cannot always rely on under-the-hood flags passed to driver specific
gem-create ioctl to pass around these extra flags.
The proposal is to add a per-plane format modifier. This allows to, if
necessary, use different tiling patters for sub-sampled planes, etc.
The format modifiers are added at the end of the ioctl struct, so for
legacy userspace it will be zero padded.
v1: original
v1.5: increase modifier to 64b
v2: Incorporate review comments from the big thread, plus a few more.
- Add a getcap so that userspace doesn't have to jump through hoops.
- Allow modifiers only when a flag is set. That way drivers know when
they're dealing with old userspace and need to fish out e.g. tiling
from other information.
- After rolling out checks for ->modifier to all drivers I've decided
that this is way too fragile and needs an explicit opt-in flag. So
do that instead.
- Add a define (just for documentation really) for the "NONE"
modifier. Imo we don't need to add mask #defines since drivers
really should only do exact matches against values defined with
fourcc_mod_code.
- Drop the Samsung tiling modifier on Rob's request since he's not yet
sure whether that one is accurate.
v3:
- Also add a new ->modifier[] array to struct drm_framebuffer and fill
it in drm_helper_mode_fill_fb_struct. Requested by Tvrkto Uruslin.
- Remove TODO in comment and add code comment that modifiers should be
properly documented, requested by Rob.
Cc: Rob Clark <robdclark@gmail.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Daniel Stone <daniel@fooishbar.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Michel Dänzer <michel@daenzer.net>
Signed-off-by: Rob Clark <robdclark@gmail.com> (v1.5)
Reviewed-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 3 |
3 files changed, 17 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index ad2934ba0bd2..b15d720eda4c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -3314,6 +3314,12 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
3314 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); | 3314 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); |
3315 | return -EINVAL; | 3315 | return -EINVAL; |
3316 | } | 3316 | } |
3317 | |||
3318 | if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) { | ||
3319 | DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n", | ||
3320 | r->modifier[i], i); | ||
3321 | return -EINVAL; | ||
3322 | } | ||
3317 | } | 3323 | } |
3318 | 3324 | ||
3319 | return 0; | 3325 | return 0; |
@@ -3327,7 +3333,7 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, | |||
3327 | struct drm_framebuffer *fb; | 3333 | struct drm_framebuffer *fb; |
3328 | int ret; | 3334 | int ret; |
3329 | 3335 | ||
3330 | if (r->flags & ~DRM_MODE_FB_INTERLACED) { | 3336 | if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) { |
3331 | DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); | 3337 | DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); |
3332 | return ERR_PTR(-EINVAL); | 3338 | return ERR_PTR(-EINVAL); |
3333 | } | 3339 | } |
@@ -3343,6 +3349,12 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, | |||
3343 | return ERR_PTR(-EINVAL); | 3349 | return ERR_PTR(-EINVAL); |
3344 | } | 3350 | } |
3345 | 3351 | ||
3352 | if (r->flags & DRM_MODE_FB_MODIFIERS && | ||
3353 | !dev->mode_config.allow_fb_modifiers) { | ||
3354 | DRM_DEBUG_KMS("driver does not support fb modifiers\n"); | ||
3355 | return ERR_PTR(-EINVAL); | ||
3356 | } | ||
3357 | |||
3346 | ret = framebuffer_check(r); | 3358 | ret = framebuffer_check(r); |
3347 | if (ret) | 3359 | if (ret) |
3348 | return ERR_PTR(ret); | 3360 | return ERR_PTR(ret); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b1979e7bdc88..3053aab968f9 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -837,6 +837,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | |||
837 | for (i = 0; i < 4; i++) { | 837 | for (i = 0; i < 4; i++) { |
838 | fb->pitches[i] = mode_cmd->pitches[i]; | 838 | fb->pitches[i] = mode_cmd->pitches[i]; |
839 | fb->offsets[i] = mode_cmd->offsets[i]; | 839 | fb->offsets[i] = mode_cmd->offsets[i]; |
840 | fb->modifier[i] = mode_cmd->modifier[i]; | ||
840 | } | 841 | } |
841 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, | 842 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
842 | &fb->bits_per_pixel); | 843 | &fb->bits_per_pixel); |
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 3785d66721f2..a6d773a61c2d 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c | |||
@@ -321,6 +321,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ | |||
321 | else | 321 | else |
322 | req->value = 64; | 322 | req->value = 64; |
323 | break; | 323 | break; |
324 | case DRM_CAP_ADDFB2_MODIFIERS: | ||
325 | req->value = dev->mode_config.allow_fb_modifiers; | ||
326 | break; | ||
324 | default: | 327 | default: |
325 | return -EINVAL; | 328 | return -EINVAL; |
326 | } | 329 | } |