Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[cascardo/linux.git] / drivers / gpu / drm / drm_blend.c
index f3c0942..85172a9 100644 (file)
  */
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
-#include <drm/drm_crtc.h>
+#include <drm/drm_blend.h>
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
 
-#include "drm_internal.h"
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * The basic plane composition model supported by standard plane properties only
+ * has a source rectangle (in logical pixels within the &drm_framebuffer), with
+ * sub-pixel accuracy, which is scaled up to a pixel-aligned destination
+ * rectangle in the visible area of a &drm_crtc. The visible area of a CRTC is
+ * defined by the horizontal and vertical visible pixels (stored in @hdisplay
+ * and @vdisplay) of the requested mode (stored in @mode in the
+ * &drm_crtc_state). These two rectangles are both stored in the
+ * &drm_plane_state.
+ *
+ * For the atomic ioctl the following standard (atomic) properties on the plane object
+ * encode the basic plane composition model:
+ *
+ * SRC_X:
+ *     X coordinate offset for the source rectangle within the
+ *     &drm_framebuffer, in 16.16 fixed point. Must be positive.
+ * SRC_Y:
+ *     Y coordinate offset for the source rectangle within the
+ *     &drm_framebuffer, in 16.16 fixed point. Must be positive.
+ * SRC_W:
+ *     Width for the source rectangle within the &drm_framebuffer, in 16.16
+ *     fixed point. SRC_X plus SRC_W must be within the width of the source
+ *     framebuffer. Must be positive.
+ * SRC_H:
+ *     Height for the source rectangle within the &drm_framebuffer, in 16.16
+ *     fixed point. SRC_Y plus SRC_H must be within the height of the source
+ *     framebuffer. Must be positive.
+ * CRTC_X:
+ *     X coordinate offset for the destination rectangle. Can be negative.
+ * CRTC_Y:
+ *     Y coordinate offset for the destination rectangle. Can be negative.
+ * CRTC_W:
+ *     Width for the destination rectangle. CRTC_X plus CRTC_W can extend past
+ *     the currently visible horizontal area of the &drm_crtc.
+ * CRTC_H:
+ *     Height for the destination rectangle. CRTC_Y plus CRTC_H can extend past
+ *     the currently visible vertical area of the &drm_crtc.
+ * FB_ID:
+ *     Mode object ID of the &drm_framebuffer this plane should scan out.
+ * CRTC_ID:
+ *     Mode object ID of the &drm_crtc this plane should be connected to.
+ *
+ * Note that the source rectangle must fully lie within the bounds of the
+ * &drm_framebuffer. The destination rectangle can lie outside of the visible
+ * area of the current mode of the CRTC. It must be apprpriately clipped by the
+ * driver, which can be done by calling drm_plane_helper_check_update(). Drivers
+ * are also allowed to round the subpixel sampling positions appropriately, but
+ * only to the next full pixel. No pixel outside of the source rectangle may
+ * ever be sampled, which is important when applying more sophisticated
+ * filtering than just a bilinear one when scaling. The filtering mode when
+ * scaling is unspecified.
+ *
+ * On top of this basic transformation additional properties can be exposed by
+ * the driver:
+ *
+ * - Rotation is set up with drm_mode_create_rotation_property(). It adds a
+ *   rotation and reflection step between the source and destination rectangles.
+ *   Without this property the rectangle is only scaled, but not rotated or
+ *   reflected.
+ *
+ * - Z position is set up with drm_plane_create_zpos_immutable_property() and
+ *   drm_plane_create_zpos_property(). It controls the visibility of overlapping
+ *   planes. Without this property the primary plane is always below the cursor
+ *   plane, and ordering between all other planes is undefined.
+ *
+ * Note that all the property extensions described here apply either to the
+ * plane or the CRTC (e.g. for the background color, which currently is not
+ * exposed and assumed to be black).
+ */
+
+/**
+ * drm_mode_create_rotation_property - create a new rotation property
+ * @dev: DRM device
+ * @supported_rotations: bitmask of supported rotations and reflections
+ *
+ * This creates a new property with the selected support for transformations.
+ * The resulting property should be stored in @rotation_property in
+ * &drm_mode_config. It then must be attached to each plane which supports
+ * rotations using drm_object_attach_property().
+ *
+ * FIXME: Probably better if the rotation property is created on each plane,
+ * like the zpos property. Otherwise it's not possible to allow different
+ * rotation modes on different planes.
+ *
+ * Since a rotation by 180° degress is the same as reflecting both along the x
+ * and the y axis the rotation property is somewhat redundant. Drivers can use
+ * drm_rotation_simplify() to normalize values of this property.
+ *
+ * The property exposed to userspace is a bitmask property (see
+ * drm_property_create_bitmask()) called "rotation" and has the following
+ * bitmask enumaration values:
+ *
+ * DRM_ROTATE_0:
+ *     "rotate-0"
+ * DRM_ROTATE_90:
+ *     "rotate-90"
+ * DRM_ROTATE_180:
+ *     "rotate-180"
+ * DRM_ROTATE_270:
+ *     "rotate-270"
+ * DRM_REFLECT_X:
+ *     "reflect-x"
+ * DRM_REFELCT_Y:
+ *     "reflect-y"
+ *
+ * Rotation is the specified amount in degrees in counter clockwise direction,
+ * the X and Y axis are within the source rectangle, i.e.  the X/Y axis before
+ * rotation. After reflection, the rotation is applied to the image sampled from
+ * the source rectangle, before scaling it to fit the destination rectangle.
+ */
+struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
+                                                      unsigned int supported_rotations)
+{
+       static const struct drm_prop_enum_list props[] = {
+               { __builtin_ffs(DRM_ROTATE_0) - 1,   "rotate-0" },
+               { __builtin_ffs(DRM_ROTATE_90) - 1,  "rotate-90" },
+               { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" },
+               { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" },
+               { __builtin_ffs(DRM_REFLECT_X) - 1,  "reflect-x" },
+               { __builtin_ffs(DRM_REFLECT_Y) - 1,  "reflect-y" },
+       };
+
+       return drm_property_create_bitmask(dev, 0, "rotation",
+                                          props, ARRAY_SIZE(props),
+                                          supported_rotations);
+}
+EXPORT_SYMBOL(drm_mode_create_rotation_property);
+
+/**
+ * drm_rotation_simplify() - Try to simplify the rotation
+ * @rotation: Rotation to be simplified
+ * @supported_rotations: Supported rotations
+ *
+ * Attempt to simplify the rotation to a form that is supported.
+ * Eg. if the hardware supports everything except DRM_REFLECT_X
+ * one could call this function like this:
+ *
+ * drm_rotation_simplify(rotation, DRM_ROTATE_0 |
+ *                       DRM_ROTATE_90 | DRM_ROTATE_180 |
+ *                       DRM_ROTATE_270 | DRM_REFLECT_Y);
+ *
+ * to eliminate the DRM_ROTATE_X flag. Depending on what kind of
+ * transforms the hardware supports, this function may not
+ * be able to produce a supported transform, so the caller should
+ * check the result afterwards.
+ */
+unsigned int drm_rotation_simplify(unsigned int rotation,
+                                  unsigned int supported_rotations)
+{
+       if (rotation & ~supported_rotations) {
+               rotation ^= DRM_REFLECT_X | DRM_REFLECT_Y;
+               rotation = (rotation & DRM_REFLECT_MASK) |
+                          BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4);
+       }
+
+       return rotation;
+}
+EXPORT_SYMBOL(drm_rotation_simplify);
 
 /**
  * drm_plane_create_zpos_property - create mutable zpos property
  * If zpos of some planes cannot be changed (like fixed background or
  * cursor/topmost planes), driver should adjust min/max values and assign those
  * planes immutable zpos property with lower or higher values (for more
- * information, see drm_mode_create_zpos_immutable_property() function). In such
+ * information, see drm_plane_create_zpos_immutable_property() function). In such
  * case driver should also assign proper initial zpos values for all planes in
  * its plane_reset() callback, so the planes will be always sorted properly.
  *
+ * See also drm_atomic_normalize_zpos().
+ *
+ * The property exposed to userspace is called "zpos".
+ *
  * Returns:
  * Zero on success, negative errno on failure.
  */
@@ -88,7 +253,9 @@ EXPORT_SYMBOL(drm_plane_create_zpos_property);
  * support for it in drm core. Using this property driver lets userspace
  * to get the arrangement of the planes for blending operation and notifies
  * it that the hardware (or driver) doesn't support changing of the planes'
- * order.
+ * order. For mutable zpos see drm_plane_create_zpos_property().
+ *
+ * The property exposed to userspace is called "zpos".
  *
  * Returns:
  * Zero on success, negative errno on failure.
@@ -127,20 +294,6 @@ static int drm_atomic_state_zpos_cmp(const void *a, const void *b)
                return sa->plane->base.id - sb->plane->base.id;
 }
 
-/**
- * drm_atomic_helper_crtc_normalize_zpos - calculate normalized zpos values
- * @crtc: crtc with planes, which have to be considered for normalization
- * @crtc_state: new atomic state to apply
- *
- * This function checks new states of all planes assigned to given crtc and
- * calculates normalized zpos value for them. Planes are compared first by their
- * zpos values, then by plane id (if zpos equals). Plane with lowest zpos value
- * is at the bottom. The plane_state->normalized_zpos is then filled with unique
- * values from 0 to number of active planes in crtc minus one.
- *
- * RETURNS
- * Zero for success or -errno
- */
 static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
                                          struct drm_crtc_state *crtc_state)
 {
@@ -193,20 +346,25 @@ done:
 }
 
 /**
- * drm_atomic_helper_normalize_zpos - calculate normalized zpos values for all
- *                                   crtcs
+ * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs
  * @dev: DRM device
  * @state: atomic state of DRM device
  *
  * This function calculates normalized zpos value for all modified planes in
- * the provided atomic state of DRM device. For more information, see
- * drm_atomic_helper_crtc_normalize_zpos() function.
+ * the provided atomic state of DRM device.
+ *
+ * For every CRTC this function checks new states of all planes assigned to
+ * it and calculates normalized zpos value for these planes. Planes are compared
+ * first by their zpos values, then by plane id (if zpos is equal). The plane
+ * with lowest zpos value is at the bottom. The plane_state->normalized_zpos is
+ * then filled with unique values from 0 to number of active planes in crtc
+ * minus one.
  *
  * RETURNS
  * Zero for success or -errno
  */
-int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
-                                    struct drm_atomic_state *state)
+int drm_atomic_normalize_zpos(struct drm_device *dev,
+                             struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
@@ -236,3 +394,4 @@ int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
        }
        return 0;
 }
+EXPORT_SYMBOL(drm_atomic_normalize_zpos);