drm_blend.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  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 <linux/export.h>
  27. #include <linux/slab.h>
  28. #include <linux/sort.h>
  29. #include <drm/drm_atomic.h>
  30. #include <drm/drm_blend.h>
  31. #include <drm/drm_device.h>
  32. #include <drm/drm_print.h>
  33. #include "drm_crtc_internal.h"
  34. /**
  35. * DOC: overview
  36. *
  37. * The basic plane composition model supported by standard plane properties only
  38. * has a source rectangle (in logical pixels within the &drm_framebuffer), with
  39. * sub-pixel accuracy, which is scaled up to a pixel-aligned destination
  40. * rectangle in the visible area of a &drm_crtc. The visible area of a CRTC is
  41. * defined by the horizontal and vertical visible pixels (stored in @hdisplay
  42. * and @vdisplay) of the requested mode (stored in &drm_crtc_state.mode). These
  43. * two rectangles are both stored in the &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. *
  75. * When a KMS client is performing front-buffer rendering, it should set
  76. * FB_ID to the same front-buffer FB on each atomic commit. This implies
  77. * to the driver that it needs to re-read the same FB again. Otherwise
  78. * drivers which do not employ continuously repeated scanout cycles might
  79. * not update the screen.
  80. * CRTC_ID:
  81. * Mode object ID of the &drm_crtc this plane should be connected to.
  82. *
  83. * Note that the source rectangle must fully lie within the bounds of the
  84. * &drm_framebuffer. The destination rectangle can lie outside of the visible
  85. * area of the current mode of the CRTC. It must be appropriately clipped by the
  86. * driver, which can be done by calling drm_plane_helper_check_update(). Drivers
  87. * are also allowed to round the subpixel sampling positions appropriately, but
  88. * only to the next full pixel. No pixel outside of the source rectangle may
  89. * ever be sampled, which is important when applying more sophisticated
  90. * filtering than just a bilinear one when scaling. The filtering mode when
  91. * scaling is unspecified.
  92. *
  93. * On top of this basic transformation additional properties can be exposed by
  94. * the driver:
  95. *
  96. * alpha:
  97. * Alpha is setup with drm_plane_create_alpha_property(). It controls the
  98. * plane-wide opacity, from transparent (0) to opaque (0xffff). It can be
  99. * combined with pixel alpha.
  100. * The pixel values in the framebuffers are expected to not be
  101. * pre-multiplied by the global alpha associated to the plane.
  102. *
  103. * rotation:
  104. * Rotation is set up with drm_plane_create_rotation_property(). It adds a
  105. * rotation and reflection step between the source and destination rectangles.
  106. * Without this property the rectangle is only scaled, but not rotated or
  107. * reflected.
  108. *
  109. * Possbile values:
  110. *
  111. * "rotate-<degrees>":
  112. * Signals that a drm plane is rotated <degrees> degrees in counter
  113. * clockwise direction.
  114. *
  115. * "reflect-<axis>":
  116. * Signals that the contents of a drm plane is reflected along the
  117. * <axis> axis, in the same way as mirroring.
  118. *
  119. * reflect-x::
  120. *
  121. * |o | | o|
  122. * | | -> | |
  123. * | v| |v |
  124. *
  125. * reflect-y::
  126. *
  127. * |o | | ^|
  128. * | | -> | |
  129. * | v| |o |
  130. *
  131. * zpos:
  132. * Z position is set up with drm_plane_create_zpos_immutable_property() and
  133. * drm_plane_create_zpos_property(). It controls the visibility of overlapping
  134. * planes. Without this property the primary plane is always below the cursor
  135. * plane, and ordering between all other planes is undefined. The positive
  136. * Z axis points towards the user, i.e. planes with lower Z position values
  137. * are underneath planes with higher Z position values. Two planes with the
  138. * same Z position value have undefined ordering. Note that the Z position
  139. * value can also be immutable, to inform userspace about the hard-coded
  140. * stacking of planes, see drm_plane_create_zpos_immutable_property(). If
  141. * any plane has a zpos property (either mutable or immutable), then all
  142. * planes shall have a zpos property.
  143. *
  144. * pixel blend mode:
  145. * Pixel blend mode is set up with drm_plane_create_blend_mode_property().
  146. * It adds a blend mode for alpha blending equation selection, describing
  147. * how the pixels from the current plane are composited with the
  148. * background.
  149. *
  150. * Three alpha blending equations are defined:
  151. *
  152. * "None":
  153. * Blend formula that ignores the pixel alpha::
  154. *
  155. * out.rgb = plane_alpha * fg.rgb +
  156. * (1 - plane_alpha) * bg.rgb
  157. *
  158. * "Pre-multiplied":
  159. * Blend formula that assumes the pixel color values
  160. * have been already pre-multiplied with the alpha
  161. * channel values::
  162. *
  163. * out.rgb = plane_alpha * fg.rgb +
  164. * (1 - (plane_alpha * fg.alpha)) * bg.rgb
  165. *
  166. * "Coverage":
  167. * Blend formula that assumes the pixel color values have not
  168. * been pre-multiplied and will do so when blending them to the
  169. * background color values::
  170. *
  171. * out.rgb = plane_alpha * fg.alpha * fg.rgb +
  172. * (1 - (plane_alpha * fg.alpha)) * bg.rgb
  173. *
  174. * Using the following symbols:
  175. *
  176. * "fg.rgb":
  177. * Each of the RGB component values from the plane's pixel
  178. * "fg.alpha":
  179. * Alpha component value from the plane's pixel. If the plane's
  180. * pixel format has no alpha component, then this is assumed to be
  181. * 1.0. In these cases, this property has no effect, as all three
  182. * equations become equivalent.
  183. * "bg.rgb":
  184. * Each of the RGB component values from the background
  185. * "plane_alpha":
  186. * Plane alpha value set by the plane "alpha" property. If the
  187. * plane does not expose the "alpha" property, then this is
  188. * assumed to be 1.0
  189. *
  190. * Note that all the property extensions described here apply either to the
  191. * plane or the CRTC (e.g. for the background color, which currently is not
  192. * exposed and assumed to be black).
  193. *
  194. * SCALING_FILTER:
  195. * Indicates scaling filter to be used for plane scaler
  196. *
  197. * The value of this property can be one of the following:
  198. *
  199. * Default:
  200. * Driver's default scaling filter
  201. * Nearest Neighbor:
  202. * Nearest Neighbor scaling filter
  203. *
  204. * Drivers can set up this property for a plane by calling
  205. * drm_plane_create_scaling_filter_property
  206. */
  207. /**
  208. * drm_plane_create_alpha_property - create a new alpha property
  209. * @plane: drm plane
  210. *
  211. * This function creates a generic, mutable, alpha property and enables support
  212. * for it in the DRM core. It is attached to @plane.
  213. *
  214. * The alpha property will be allowed to be within the bounds of 0
  215. * (transparent) to 0xffff (opaque).
  216. *
  217. * Returns:
  218. * 0 on success, negative error code on failure.
  219. */
  220. int drm_plane_create_alpha_property(struct drm_plane *plane)
  221. {
  222. struct drm_property *prop;
  223. prop = drm_property_create_range(plane->dev, 0, "alpha",
  224. 0, DRM_BLEND_ALPHA_OPAQUE);
  225. if (!prop)
  226. return -ENOMEM;
  227. drm_object_attach_property(&plane->base, prop, DRM_BLEND_ALPHA_OPAQUE);
  228. plane->alpha_property = prop;
  229. if (plane->state)
  230. plane->state->alpha = DRM_BLEND_ALPHA_OPAQUE;
  231. return 0;
  232. }
  233. EXPORT_SYMBOL(drm_plane_create_alpha_property);
  234. /**
  235. * drm_plane_create_rotation_property - create a new rotation property
  236. * @plane: drm plane
  237. * @rotation: initial value of the rotation property
  238. * @supported_rotations: bitmask of supported rotations and reflections
  239. *
  240. * This creates a new property with the selected support for transformations.
  241. *
  242. * Since a rotation by 180° degress is the same as reflecting both along the x
  243. * and the y axis the rotation property is somewhat redundant. Drivers can use
  244. * drm_rotation_simplify() to normalize values of this property.
  245. *
  246. * The property exposed to userspace is a bitmask property (see
  247. * drm_property_create_bitmask()) called "rotation" and has the following
  248. * bitmask enumaration values:
  249. *
  250. * DRM_MODE_ROTATE_0:
  251. * "rotate-0"
  252. * DRM_MODE_ROTATE_90:
  253. * "rotate-90"
  254. * DRM_MODE_ROTATE_180:
  255. * "rotate-180"
  256. * DRM_MODE_ROTATE_270:
  257. * "rotate-270"
  258. * DRM_MODE_REFLECT_X:
  259. * "reflect-x"
  260. * DRM_MODE_REFLECT_Y:
  261. * "reflect-y"
  262. *
  263. * Rotation is the specified amount in degrees in counter clockwise direction,
  264. * the X and Y axis are within the source rectangle, i.e. the X/Y axis before
  265. * rotation. After reflection, the rotation is applied to the image sampled from
  266. * the source rectangle, before scaling it to fit the destination rectangle.
  267. */
  268. int drm_plane_create_rotation_property(struct drm_plane *plane,
  269. unsigned int rotation,
  270. unsigned int supported_rotations)
  271. {
  272. static const struct drm_prop_enum_list props[] = {
  273. { __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" },
  274. { __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" },
  275. { __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" },
  276. { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" },
  277. { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" },
  278. { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" },
  279. };
  280. struct drm_property *prop;
  281. WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0);
  282. WARN_ON(!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK));
  283. WARN_ON(rotation & ~supported_rotations);
  284. prop = drm_property_create_bitmask(plane->dev, 0, "rotation",
  285. props, ARRAY_SIZE(props),
  286. supported_rotations);
  287. if (!prop)
  288. return -ENOMEM;
  289. drm_object_attach_property(&plane->base, prop, rotation);
  290. if (plane->state)
  291. plane->state->rotation = rotation;
  292. plane->rotation_property = prop;
  293. return 0;
  294. }
  295. EXPORT_SYMBOL(drm_plane_create_rotation_property);
  296. /**
  297. * drm_rotation_simplify() - Try to simplify the rotation
  298. * @rotation: Rotation to be simplified
  299. * @supported_rotations: Supported rotations
  300. *
  301. * Attempt to simplify the rotation to a form that is supported.
  302. * Eg. if the hardware supports everything except DRM_MODE_REFLECT_X
  303. * one could call this function like this:
  304. *
  305. * drm_rotation_simplify(rotation, DRM_MODE_ROTATE_0 |
  306. * DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
  307. * DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_Y);
  308. *
  309. * to eliminate the DRM_MODE_REFLECT_X flag. Depending on what kind of
  310. * transforms the hardware supports, this function may not
  311. * be able to produce a supported transform, so the caller should
  312. * check the result afterwards.
  313. */
  314. unsigned int drm_rotation_simplify(unsigned int rotation,
  315. unsigned int supported_rotations)
  316. {
  317. if (rotation & ~supported_rotations) {
  318. rotation ^= DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
  319. rotation = (rotation & DRM_MODE_REFLECT_MASK) |
  320. BIT((ffs(rotation & DRM_MODE_ROTATE_MASK) + 1)
  321. % 4);
  322. }
  323. return rotation;
  324. }
  325. EXPORT_SYMBOL(drm_rotation_simplify);
  326. /**
  327. * drm_plane_create_zpos_property - create mutable zpos property
  328. * @plane: drm plane
  329. * @zpos: initial value of zpos property
  330. * @min: minimal possible value of zpos property
  331. * @max: maximal possible value of zpos property
  332. *
  333. * This function initializes generic mutable zpos property and enables support
  334. * for it in drm core. Drivers can then attach this property to planes to enable
  335. * support for configurable planes arrangement during blending operation.
  336. * Drivers that attach a mutable zpos property to any plane should call the
  337. * drm_atomic_normalize_zpos() helper during their implementation of
  338. * &drm_mode_config_funcs.atomic_check(), which will update the normalized zpos
  339. * values and store them in &drm_plane_state.normalized_zpos. Usually min
  340. * should be set to 0 and max to maximal number of planes for given crtc - 1.
  341. *
  342. * If zpos of some planes cannot be changed (like fixed background or
  343. * cursor/topmost planes), drivers shall adjust the min/max values and assign
  344. * those planes immutable zpos properties with lower or higher values (for more
  345. * information, see drm_plane_create_zpos_immutable_property() function). In such
  346. * case drivers shall also assign proper initial zpos values for all planes in
  347. * its plane_reset() callback, so the planes will be always sorted properly.
  348. *
  349. * See also drm_atomic_normalize_zpos().
  350. *
  351. * The property exposed to userspace is called "zpos".
  352. *
  353. * Returns:
  354. * Zero on success, negative errno on failure.
  355. */
  356. int drm_plane_create_zpos_property(struct drm_plane *plane,
  357. unsigned int zpos,
  358. unsigned int min, unsigned int max)
  359. {
  360. struct drm_property *prop;
  361. prop = drm_property_create_range(plane->dev, 0, "zpos", min, max);
  362. if (!prop)
  363. return -ENOMEM;
  364. drm_object_attach_property(&plane->base, prop, zpos);
  365. plane->zpos_property = prop;
  366. if (plane->state) {
  367. plane->state->zpos = zpos;
  368. plane->state->normalized_zpos = zpos;
  369. }
  370. return 0;
  371. }
  372. EXPORT_SYMBOL(drm_plane_create_zpos_property);
  373. /**
  374. * drm_plane_create_zpos_immutable_property - create immuttable zpos property
  375. * @plane: drm plane
  376. * @zpos: value of zpos property
  377. *
  378. * This function initializes generic immutable zpos property and enables
  379. * support for it in drm core. Using this property driver lets userspace
  380. * to get the arrangement of the planes for blending operation and notifies
  381. * it that the hardware (or driver) doesn't support changing of the planes'
  382. * order. For mutable zpos see drm_plane_create_zpos_property().
  383. *
  384. * The property exposed to userspace is called "zpos".
  385. *
  386. * Returns:
  387. * Zero on success, negative errno on failure.
  388. */
  389. int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
  390. unsigned int zpos)
  391. {
  392. struct drm_property *prop;
  393. prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE,
  394. "zpos", zpos, zpos);
  395. if (!prop)
  396. return -ENOMEM;
  397. drm_object_attach_property(&plane->base, prop, zpos);
  398. plane->zpos_property = prop;
  399. if (plane->state) {
  400. plane->state->zpos = zpos;
  401. plane->state->normalized_zpos = zpos;
  402. }
  403. return 0;
  404. }
  405. EXPORT_SYMBOL(drm_plane_create_zpos_immutable_property);
  406. static int drm_atomic_state_zpos_cmp(const void *a, const void *b)
  407. {
  408. const struct drm_plane_state *sa = *(struct drm_plane_state **)a;
  409. const struct drm_plane_state *sb = *(struct drm_plane_state **)b;
  410. if (sa->zpos != sb->zpos)
  411. return sa->zpos - sb->zpos;
  412. else
  413. return sa->plane->base.id - sb->plane->base.id;
  414. }
  415. static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
  416. struct drm_crtc_state *crtc_state)
  417. {
  418. struct drm_atomic_state *state = crtc_state->state;
  419. struct drm_device *dev = crtc->dev;
  420. int total_planes = dev->mode_config.num_total_plane;
  421. struct drm_plane_state **states;
  422. struct drm_plane *plane;
  423. int i, n = 0;
  424. int ret = 0;
  425. drm_dbg_atomic(dev, "[CRTC:%d:%s] calculating normalized zpos values\n",
  426. crtc->base.id, crtc->name);
  427. states = kmalloc_objs(*states, total_planes);
  428. if (!states)
  429. return -ENOMEM;
  430. /*
  431. * Normalization process might create new states for planes which
  432. * normalized_zpos has to be recalculated.
  433. */
  434. drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
  435. struct drm_plane_state *plane_state =
  436. drm_atomic_get_plane_state(state, plane);
  437. if (IS_ERR(plane_state)) {
  438. ret = PTR_ERR(plane_state);
  439. goto done;
  440. }
  441. states[n++] = plane_state;
  442. drm_dbg_atomic(dev, "[PLANE:%d:%s] processing zpos value %d\n",
  443. plane->base.id, plane->name, plane_state->zpos);
  444. }
  445. sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL);
  446. for (i = 0; i < n; i++) {
  447. plane = states[i]->plane;
  448. states[i]->normalized_zpos = i;
  449. drm_dbg_atomic(dev, "[PLANE:%d:%s] normalized zpos value %d\n",
  450. plane->base.id, plane->name, i);
  451. }
  452. crtc_state->zpos_changed = true;
  453. done:
  454. kfree(states);
  455. return ret;
  456. }
  457. /**
  458. * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs
  459. * @dev: DRM device
  460. * @state: atomic state of DRM device
  461. *
  462. * This function calculates normalized zpos value for all modified planes in
  463. * the provided atomic state of DRM device.
  464. *
  465. * For every CRTC this function checks new states of all planes assigned to
  466. * it and calculates normalized zpos value for these planes. Planes are compared
  467. * first by their zpos values, then by plane id (if zpos is equal). The plane
  468. * with lowest zpos value is at the bottom. The &drm_plane_state.normalized_zpos
  469. * is then filled with unique values from 0 to number of active planes in crtc
  470. * minus one.
  471. *
  472. * RETURNS
  473. * Zero for success or -errno
  474. */
  475. int drm_atomic_normalize_zpos(struct drm_device *dev,
  476. struct drm_atomic_state *state)
  477. {
  478. struct drm_crtc *crtc;
  479. struct drm_crtc_state *old_crtc_state, *new_crtc_state;
  480. struct drm_plane *plane;
  481. struct drm_plane_state *old_plane_state, *new_plane_state;
  482. int i, ret = 0;
  483. for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
  484. crtc = new_plane_state->crtc;
  485. if (!crtc)
  486. continue;
  487. if (old_plane_state->zpos != new_plane_state->zpos) {
  488. new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  489. new_crtc_state->zpos_changed = true;
  490. }
  491. }
  492. for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
  493. if (old_crtc_state->plane_mask != new_crtc_state->plane_mask ||
  494. new_crtc_state->zpos_changed) {
  495. ret = drm_atomic_helper_crtc_normalize_zpos(crtc,
  496. new_crtc_state);
  497. if (ret)
  498. return ret;
  499. }
  500. }
  501. return 0;
  502. }
  503. EXPORT_SYMBOL(drm_atomic_normalize_zpos);
  504. /**
  505. * drm_plane_create_blend_mode_property - create a new blend mode property
  506. * @plane: drm plane
  507. * @supported_modes: bitmask of supported modes, must include
  508. * BIT(DRM_MODE_BLEND_PREMULTI). Current DRM assumption is
  509. * that alpha is premultiplied, and old userspace can break if
  510. * the property defaults to anything else.
  511. *
  512. * This creates a new property describing the blend mode.
  513. *
  514. * The property exposed to userspace is an enumeration property (see
  515. * drm_property_create_enum()) called "pixel blend mode" and has the
  516. * following enumeration values:
  517. *
  518. * "None":
  519. * Blend formula that ignores the pixel alpha.
  520. *
  521. * "Pre-multiplied":
  522. * Blend formula that assumes the pixel color values have been already
  523. * pre-multiplied with the alpha channel values.
  524. *
  525. * "Coverage":
  526. * Blend formula that assumes the pixel color values have not been
  527. * pre-multiplied and will do so when blending them to the background color
  528. * values.
  529. *
  530. * RETURNS:
  531. * Zero for success or -errno
  532. */
  533. int drm_plane_create_blend_mode_property(struct drm_plane *plane,
  534. unsigned int supported_modes)
  535. {
  536. struct drm_device *dev = plane->dev;
  537. struct drm_property *prop;
  538. static const struct drm_prop_enum_list props[] = {
  539. { DRM_MODE_BLEND_PIXEL_NONE, "None" },
  540. { DRM_MODE_BLEND_PREMULTI, "Pre-multiplied" },
  541. { DRM_MODE_BLEND_COVERAGE, "Coverage" },
  542. };
  543. unsigned int valid_mode_mask = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
  544. BIT(DRM_MODE_BLEND_PREMULTI) |
  545. BIT(DRM_MODE_BLEND_COVERAGE);
  546. int i;
  547. if (WARN_ON((supported_modes & ~valid_mode_mask) ||
  548. ((supported_modes & BIT(DRM_MODE_BLEND_PREMULTI)) == 0)))
  549. return -EINVAL;
  550. prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
  551. "pixel blend mode",
  552. hweight32(supported_modes));
  553. if (!prop)
  554. return -ENOMEM;
  555. for (i = 0; i < ARRAY_SIZE(props); i++) {
  556. int ret;
  557. if (!(BIT(props[i].type) & supported_modes))
  558. continue;
  559. ret = drm_property_add_enum(prop, props[i].type,
  560. props[i].name);
  561. if (ret) {
  562. drm_property_destroy(dev, prop);
  563. return ret;
  564. }
  565. }
  566. drm_object_attach_property(&plane->base, prop, DRM_MODE_BLEND_PREMULTI);
  567. plane->blend_mode_property = prop;
  568. return 0;
  569. }
  570. EXPORT_SYMBOL(drm_plane_create_blend_mode_property);