drm_blend.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. * Copyright (C) 2016 Samsung Electronics Co.Ltd
  3. * Authors:
  4. * Marek Szyprowski <m.szyprowski@samsung.com>
  5. *
  6. * DRM core plane blending related functions
  7. *
  8. * Permission to use, copy, modify, distribute, and sell this software and its
  9. * documentation for any purpose is hereby granted without fee, provided that
  10. * the above copyright notice appear in all copies and that both that copyright
  11. * notice and this permission notice appear in supporting documentation, and
  12. * that the name of the copyright holders not be used in advertising or
  13. * publicity pertaining to distribution of the software without specific,
  14. * written prior permission. The copyright holders make no representations
  15. * about the suitability of this software for any purpose. It is provided "as
  16. * is" without express or implied warranty.
  17. *
  18. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  19. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  20. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  22. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  23. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  24. * OF THIS SOFTWARE.
  25. */
  26. #include <drm/drmP.h>
  27. #include <drm/drm_atomic.h>
  28. #include <drm/drm_blend.h>
  29. #include <linux/export.h>
  30. #include <linux/slab.h>
  31. #include <linux/sort.h>
  32. #include "drm_crtc_internal.h"
  33. /**
  34. * DOC: overview
  35. *
  36. * The basic plane composition model supported by standard plane properties only
  37. * has a source rectangle (in logical pixels within the &drm_framebuffer), with
  38. * sub-pixel accuracy, which is scaled up to a pixel-aligned destination
  39. * rectangle in the visible area of a &drm_crtc. The visible area of a CRTC is
  40. * defined by the horizontal and vertical visible pixels (stored in @hdisplay
  41. * and @vdisplay) of the requested mode (stored in @mode in the
  42. * &drm_crtc_state). These two rectangles are both stored in the
  43. * &drm_plane_state.
  44. *
  45. * For the atomic ioctl the following standard (atomic) properties on the plane object
  46. * encode the basic plane composition model:
  47. *
  48. * SRC_X:
  49. * X coordinate offset for the source rectangle within the
  50. * &drm_framebuffer, in 16.16 fixed point. Must be positive.
  51. * SRC_Y:
  52. * Y coordinate offset for the source rectangle within the
  53. * &drm_framebuffer, in 16.16 fixed point. Must be positive.
  54. * SRC_W:
  55. * Width for the source rectangle within the &drm_framebuffer, in 16.16
  56. * fixed point. SRC_X plus SRC_W must be within the width of the source
  57. * framebuffer. Must be positive.
  58. * SRC_H:
  59. * Height for the source rectangle within the &drm_framebuffer, in 16.16
  60. * fixed point. SRC_Y plus SRC_H must be within the height of the source
  61. * framebuffer. Must be positive.
  62. * CRTC_X:
  63. * X coordinate offset for the destination rectangle. Can be negative.
  64. * CRTC_Y:
  65. * Y coordinate offset for the destination rectangle. Can be negative.
  66. * CRTC_W:
  67. * Width for the destination rectangle. CRTC_X plus CRTC_W can extend past
  68. * the currently visible horizontal area of the &drm_crtc.
  69. * CRTC_H:
  70. * Height for the destination rectangle. CRTC_Y plus CRTC_H can extend past
  71. * the currently visible vertical area of the &drm_crtc.
  72. * FB_ID:
  73. * Mode object ID of the &drm_framebuffer this plane should scan out.
  74. * CRTC_ID:
  75. * Mode object ID of the &drm_crtc this plane should be connected to.
  76. *
  77. * Note that the source rectangle must fully lie within the bounds of the
  78. * &drm_framebuffer. The destination rectangle can lie outside of the visible
  79. * area of the current mode of the CRTC. It must be apprpriately clipped by the
  80. * driver, which can be done by calling drm_plane_helper_check_update(). Drivers
  81. * are also allowed to round the subpixel sampling positions appropriately, but
  82. * only to the next full pixel. No pixel outside of the source rectangle may
  83. * ever be sampled, which is important when applying more sophisticated
  84. * filtering than just a bilinear one when scaling. The filtering mode when
  85. * scaling is unspecified.
  86. *
  87. * On top of this basic transformation additional properties can be exposed by
  88. * the driver:
  89. *
  90. * - Rotation is set up with drm_mode_create_rotation_property(). It adds a
  91. * rotation and reflection step between the source and destination rectangles.
  92. * Without this property the rectangle is only scaled, but not rotated or
  93. * reflected.
  94. *
  95. * - Z position is set up with drm_plane_create_zpos_immutable_property() and
  96. * drm_plane_create_zpos_property(). It controls the visibility of overlapping
  97. * planes. Without this property the primary plane is always below the cursor
  98. * plane, and ordering between all other planes is undefined.
  99. *
  100. * Note that all the property extensions described here apply either to the
  101. * plane or the CRTC (e.g. for the background color, which currently is not
  102. * exposed and assumed to be black).
  103. */
  104. /**
  105. * drm_mode_create_rotation_property - create a new rotation property
  106. * @dev: DRM device
  107. * @supported_rotations: bitmask of supported rotations and reflections
  108. *
  109. * This creates a new property with the selected support for transformations.
  110. * The resulting property should be stored in @rotation_property in
  111. * &drm_mode_config. It then must be attached to each plane which supports
  112. * rotations using drm_object_attach_property().
  113. *
  114. * FIXME: Probably better if the rotation property is created on each plane,
  115. * like the zpos property. Otherwise it's not possible to allow different
  116. * rotation modes on different planes.
  117. *
  118. * Since a rotation by 180° degress is the same as reflecting both along the x
  119. * and the y axis the rotation property is somewhat redundant. Drivers can use
  120. * drm_rotation_simplify() to normalize values of this property.
  121. *
  122. * The property exposed to userspace is a bitmask property (see
  123. * drm_property_create_bitmask()) called "rotation" and has the following
  124. * bitmask enumaration values:
  125. *
  126. * DRM_ROTATE_0:
  127. * "rotate-0"
  128. * DRM_ROTATE_90:
  129. * "rotate-90"
  130. * DRM_ROTATE_180:
  131. * "rotate-180"
  132. * DRM_ROTATE_270:
  133. * "rotate-270"
  134. * DRM_REFLECT_X:
  135. * "reflect-x"
  136. * DRM_REFELCT_Y:
  137. * "reflect-y"
  138. *
  139. * Rotation is the specified amount in degrees in counter clockwise direction,
  140. * the X and Y axis are within the source rectangle, i.e. the X/Y axis before
  141. * rotation. After reflection, the rotation is applied to the image sampled from
  142. * the source rectangle, before scaling it to fit the destination rectangle.
  143. */
  144. struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
  145. unsigned int supported_rotations)
  146. {
  147. static const struct drm_prop_enum_list props[] = {
  148. { __builtin_ffs(DRM_ROTATE_0) - 1, "rotate-0" },
  149. { __builtin_ffs(DRM_ROTATE_90) - 1, "rotate-90" },
  150. { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" },
  151. { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" },
  152. { __builtin_ffs(DRM_REFLECT_X) - 1, "reflect-x" },
  153. { __builtin_ffs(DRM_REFLECT_Y) - 1, "reflect-y" },
  154. };
  155. return drm_property_create_bitmask(dev, 0, "rotation",
  156. props, ARRAY_SIZE(props),
  157. supported_rotations);
  158. }
  159. EXPORT_SYMBOL(drm_mode_create_rotation_property);
  160. /**
  161. * drm_rotation_simplify() - Try to simplify the rotation
  162. * @rotation: Rotation to be simplified
  163. * @supported_rotations: Supported rotations
  164. *
  165. * Attempt to simplify the rotation to a form that is supported.
  166. * Eg. if the hardware supports everything except DRM_REFLECT_X
  167. * one could call this function like this:
  168. *
  169. * drm_rotation_simplify(rotation, DRM_ROTATE_0 |
  170. * DRM_ROTATE_90 | DRM_ROTATE_180 |
  171. * DRM_ROTATE_270 | DRM_REFLECT_Y);
  172. *
  173. * to eliminate the DRM_ROTATE_X flag. Depending on what kind of
  174. * transforms the hardware supports, this function may not
  175. * be able to produce a supported transform, so the caller should
  176. * check the result afterwards.
  177. */
  178. unsigned int drm_rotation_simplify(unsigned int rotation,
  179. unsigned int supported_rotations)
  180. {
  181. if (rotation & ~supported_rotations) {
  182. rotation ^= DRM_REFLECT_X | DRM_REFLECT_Y;
  183. rotation = (rotation & DRM_REFLECT_MASK) |
  184. BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4);
  185. }
  186. return rotation;
  187. }
  188. EXPORT_SYMBOL(drm_rotation_simplify);
  189. /**
  190. * drm_plane_create_zpos_property - create mutable zpos property
  191. * @plane: drm plane
  192. * @zpos: initial value of zpos property
  193. * @min: minimal possible value of zpos property
  194. * @max: maximal possible value of zpos property
  195. *
  196. * This function initializes generic mutable zpos property and enables support
  197. * for it in drm core. Drivers can then attach this property to planes to enable
  198. * support for configurable planes arrangement during blending operation.
  199. * Once mutable zpos property has been enabled, the DRM core will automatically
  200. * calculate drm_plane_state->normalized_zpos values. Usually min should be set
  201. * to 0 and max to maximal number of planes for given crtc - 1.
  202. *
  203. * If zpos of some planes cannot be changed (like fixed background or
  204. * cursor/topmost planes), driver should adjust min/max values and assign those
  205. * planes immutable zpos property with lower or higher values (for more
  206. * information, see drm_plane_create_zpos_immutable_property() function). In such
  207. * case driver should also assign proper initial zpos values for all planes in
  208. * its plane_reset() callback, so the planes will be always sorted properly.
  209. *
  210. * See also drm_atomic_normalize_zpos().
  211. *
  212. * The property exposed to userspace is called "zpos".
  213. *
  214. * Returns:
  215. * Zero on success, negative errno on failure.
  216. */
  217. int drm_plane_create_zpos_property(struct drm_plane *plane,
  218. unsigned int zpos,
  219. unsigned int min, unsigned int max)
  220. {
  221. struct drm_property *prop;
  222. prop = drm_property_create_range(plane->dev, 0, "zpos", min, max);
  223. if (!prop)
  224. return -ENOMEM;
  225. drm_object_attach_property(&plane->base, prop, zpos);
  226. plane->zpos_property = prop;
  227. if (plane->state) {
  228. plane->state->zpos = zpos;
  229. plane->state->normalized_zpos = zpos;
  230. }
  231. return 0;
  232. }
  233. EXPORT_SYMBOL(drm_plane_create_zpos_property);
  234. /**
  235. * drm_plane_create_zpos_immutable_property - create immuttable zpos property
  236. * @plane: drm plane
  237. * @zpos: value of zpos property
  238. *
  239. * This function initializes generic immutable zpos property and enables
  240. * support for it in drm core. Using this property driver lets userspace
  241. * to get the arrangement of the planes for blending operation and notifies
  242. * it that the hardware (or driver) doesn't support changing of the planes'
  243. * order. For mutable zpos see drm_plane_create_zpos_property().
  244. *
  245. * The property exposed to userspace is called "zpos".
  246. *
  247. * Returns:
  248. * Zero on success, negative errno on failure.
  249. */
  250. int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
  251. unsigned int zpos)
  252. {
  253. struct drm_property *prop;
  254. prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE,
  255. "zpos", zpos, zpos);
  256. if (!prop)
  257. return -ENOMEM;
  258. drm_object_attach_property(&plane->base, prop, zpos);
  259. plane->zpos_property = prop;
  260. if (plane->state) {
  261. plane->state->zpos = zpos;
  262. plane->state->normalized_zpos = zpos;
  263. }
  264. return 0;
  265. }
  266. EXPORT_SYMBOL(drm_plane_create_zpos_immutable_property);
  267. static int drm_atomic_state_zpos_cmp(const void *a, const void *b)
  268. {
  269. const struct drm_plane_state *sa = *(struct drm_plane_state **)a;
  270. const struct drm_plane_state *sb = *(struct drm_plane_state **)b;
  271. if (sa->zpos != sb->zpos)
  272. return sa->zpos - sb->zpos;
  273. else
  274. return sa->plane->base.id - sb->plane->base.id;
  275. }
  276. static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
  277. struct drm_crtc_state *crtc_state)
  278. {
  279. struct drm_atomic_state *state = crtc_state->state;
  280. struct drm_device *dev = crtc->dev;
  281. int total_planes = dev->mode_config.num_total_plane;
  282. struct drm_plane_state **states;
  283. struct drm_plane *plane;
  284. int i, n = 0;
  285. int ret = 0;
  286. DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
  287. crtc->base.id, crtc->name);
  288. states = kmalloc_array(total_planes, sizeof(*states), GFP_TEMPORARY);
  289. if (!states)
  290. return -ENOMEM;
  291. /*
  292. * Normalization process might create new states for planes which
  293. * normalized_zpos has to be recalculated.
  294. */
  295. drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
  296. struct drm_plane_state *plane_state =
  297. drm_atomic_get_plane_state(state, plane);
  298. if (IS_ERR(plane_state)) {
  299. ret = PTR_ERR(plane_state);
  300. goto done;
  301. }
  302. states[n++] = plane_state;
  303. DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n",
  304. plane->base.id, plane->name,
  305. plane_state->zpos);
  306. }
  307. sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL);
  308. for (i = 0; i < n; i++) {
  309. plane = states[i]->plane;
  310. states[i]->normalized_zpos = i;
  311. DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n",
  312. plane->base.id, plane->name, i);
  313. }
  314. crtc_state->zpos_changed = true;
  315. done:
  316. kfree(states);
  317. return ret;
  318. }
  319. /**
  320. * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs
  321. * @dev: DRM device
  322. * @state: atomic state of DRM device
  323. *
  324. * This function calculates normalized zpos value for all modified planes in
  325. * the provided atomic state of DRM device.
  326. *
  327. * For every CRTC this function checks new states of all planes assigned to
  328. * it and calculates normalized zpos value for these planes. Planes are compared
  329. * first by their zpos values, then by plane id (if zpos is equal). The plane
  330. * with lowest zpos value is at the bottom. The plane_state->normalized_zpos is
  331. * then filled with unique values from 0 to number of active planes in crtc
  332. * minus one.
  333. *
  334. * RETURNS
  335. * Zero for success or -errno
  336. */
  337. int drm_atomic_normalize_zpos(struct drm_device *dev,
  338. struct drm_atomic_state *state)
  339. {
  340. struct drm_crtc *crtc;
  341. struct drm_crtc_state *crtc_state;
  342. struct drm_plane *plane;
  343. struct drm_plane_state *plane_state;
  344. int i, ret = 0;
  345. for_each_plane_in_state(state, plane, plane_state, i) {
  346. crtc = plane_state->crtc;
  347. if (!crtc)
  348. continue;
  349. if (plane->state->zpos != plane_state->zpos) {
  350. crtc_state =
  351. drm_atomic_get_existing_crtc_state(state, crtc);
  352. crtc_state->zpos_changed = true;
  353. }
  354. }
  355. for_each_crtc_in_state(state, crtc, crtc_state, i) {
  356. if (crtc_state->plane_mask != crtc->state->plane_mask ||
  357. crtc_state->zpos_changed) {
  358. ret = drm_atomic_helper_crtc_normalize_zpos(crtc,
  359. crtc_state);
  360. if (ret)
  361. return ret;
  362. }
  363. }
  364. return 0;
  365. }
  366. EXPORT_SYMBOL(drm_atomic_normalize_zpos);