![]() |
|
|||
0001 /* 0002 * Copyright (C) 2016 Samsung Electronics Co.Ltd 0003 * Authors: 0004 * Marek Szyprowski <m.szyprowski@samsung.com> 0005 * 0006 * DRM core plane blending related functions 0007 * 0008 * Permission to use, copy, modify, distribute, and sell this software and its 0009 * documentation for any purpose is hereby granted without fee, provided that 0010 * the above copyright notice appear in all copies and that both that copyright 0011 * notice and this permission notice appear in supporting documentation, and 0012 * that the name of the copyright holders not be used in advertising or 0013 * publicity pertaining to distribution of the software without specific, 0014 * written prior permission. The copyright holders make no representations 0015 * about the suitability of this software for any purpose. It is provided "as 0016 * is" without express or implied warranty. 0017 * 0018 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 0019 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 0020 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 0021 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 0022 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 0023 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 0024 * OF THIS SOFTWARE. 0025 */ 0026 0027 #include <linux/export.h> 0028 #include <linux/slab.h> 0029 #include <linux/sort.h> 0030 0031 #include <drm/drm_atomic.h> 0032 #include <drm/drm_blend.h> 0033 #include <drm/drm_device.h> 0034 #include <drm/drm_print.h> 0035 0036 #include "drm_crtc_internal.h" 0037 0038 /** 0039 * DOC: overview 0040 * 0041 * The basic plane composition model supported by standard plane properties only 0042 * has a source rectangle (in logical pixels within the &drm_framebuffer), with 0043 * sub-pixel accuracy, which is scaled up to a pixel-aligned destination 0044 * rectangle in the visible area of a &drm_crtc. The visible area of a CRTC is 0045 * defined by the horizontal and vertical visible pixels (stored in @hdisplay 0046 * and @vdisplay) of the requested mode (stored in &drm_crtc_state.mode). These 0047 * two rectangles are both stored in the &drm_plane_state. 0048 * 0049 * For the atomic ioctl the following standard (atomic) properties on the plane object 0050 * encode the basic plane composition model: 0051 * 0052 * SRC_X: 0053 * X coordinate offset for the source rectangle within the 0054 * &drm_framebuffer, in 16.16 fixed point. Must be positive. 0055 * SRC_Y: 0056 * Y coordinate offset for the source rectangle within the 0057 * &drm_framebuffer, in 16.16 fixed point. Must be positive. 0058 * SRC_W: 0059 * Width for the source rectangle within the &drm_framebuffer, in 16.16 0060 * fixed point. SRC_X plus SRC_W must be within the width of the source 0061 * framebuffer. Must be positive. 0062 * SRC_H: 0063 * Height for the source rectangle within the &drm_framebuffer, in 16.16 0064 * fixed point. SRC_Y plus SRC_H must be within the height of the source 0065 * framebuffer. Must be positive. 0066 * CRTC_X: 0067 * X coordinate offset for the destination rectangle. Can be negative. 0068 * CRTC_Y: 0069 * Y coordinate offset for the destination rectangle. Can be negative. 0070 * CRTC_W: 0071 * Width for the destination rectangle. CRTC_X plus CRTC_W can extend past 0072 * the currently visible horizontal area of the &drm_crtc. 0073 * CRTC_H: 0074 * Height for the destination rectangle. CRTC_Y plus CRTC_H can extend past 0075 * the currently visible vertical area of the &drm_crtc. 0076 * FB_ID: 0077 * Mode object ID of the &drm_framebuffer this plane should scan out. 0078 * CRTC_ID: 0079 * Mode object ID of the &drm_crtc this plane should be connected to. 0080 * 0081 * Note that the source rectangle must fully lie within the bounds of the 0082 * &drm_framebuffer. The destination rectangle can lie outside of the visible 0083 * area of the current mode of the CRTC. It must be appropriately clipped by the 0084 * driver, which can be done by calling drm_plane_helper_check_update(). Drivers 0085 * are also allowed to round the subpixel sampling positions appropriately, but 0086 * only to the next full pixel. No pixel outside of the source rectangle may 0087 * ever be sampled, which is important when applying more sophisticated 0088 * filtering than just a bilinear one when scaling. The filtering mode when 0089 * scaling is unspecified. 0090 * 0091 * On top of this basic transformation additional properties can be exposed by 0092 * the driver: 0093 * 0094 * alpha: 0095 * Alpha is setup with drm_plane_create_alpha_property(). It controls the 0096 * plane-wide opacity, from transparent (0) to opaque (0xffff). It can be 0097 * combined with pixel alpha. 0098 * The pixel values in the framebuffers are expected to not be 0099 * pre-multiplied by the global alpha associated to the plane. 0100 * 0101 * rotation: 0102 * Rotation is set up with drm_plane_create_rotation_property(). It adds a 0103 * rotation and reflection step between the source and destination rectangles. 0104 * Without this property the rectangle is only scaled, but not rotated or 0105 * reflected. 0106 * 0107 * Possbile values: 0108 * 0109 * "rotate-<degrees>": 0110 * Signals that a drm plane is rotated <degrees> degrees in counter 0111 * clockwise direction. 0112 * 0113 * "reflect-<axis>": 0114 * Signals that the contents of a drm plane is reflected along the 0115 * <axis> axis, in the same way as mirroring. 0116 * 0117 * reflect-x:: 0118 * 0119 * |o | | o| 0120 * | | -> | | 0121 * | v| |v | 0122 * 0123 * reflect-y:: 0124 * 0125 * |o | | ^| 0126 * | | -> | | 0127 * | v| |o | 0128 * 0129 * zpos: 0130 * Z position is set up with drm_plane_create_zpos_immutable_property() and 0131 * drm_plane_create_zpos_property(). It controls the visibility of overlapping 0132 * planes. Without this property the primary plane is always below the cursor 0133 * plane, and ordering between all other planes is undefined. The positive 0134 * Z axis points towards the user, i.e. planes with lower Z position values 0135 * are underneath planes with higher Z position values. Two planes with the 0136 * same Z position value have undefined ordering. Note that the Z position 0137 * value can also be immutable, to inform userspace about the hard-coded 0138 * stacking of planes, see drm_plane_create_zpos_immutable_property(). If 0139 * any plane has a zpos property (either mutable or immutable), then all 0140 * planes shall have a zpos property. 0141 * 0142 * pixel blend mode: 0143 * Pixel blend mode is set up with drm_plane_create_blend_mode_property(). 0144 * It adds a blend mode for alpha blending equation selection, describing 0145 * how the pixels from the current plane are composited with the 0146 * background. 0147 * 0148 * Three alpha blending equations are defined: 0149 * 0150 * "None": 0151 * Blend formula that ignores the pixel alpha:: 0152 * 0153 * out.rgb = plane_alpha * fg.rgb + 0154 * (1 - plane_alpha) * bg.rgb 0155 * 0156 * "Pre-multiplied": 0157 * Blend formula that assumes the pixel color values 0158 * have been already pre-multiplied with the alpha 0159 * channel values:: 0160 * 0161 * out.rgb = plane_alpha * fg.rgb + 0162 * (1 - (plane_alpha * fg.alpha)) * bg.rgb 0163 * 0164 * "Coverage": 0165 * Blend formula that assumes the pixel color values have not 0166 * been pre-multiplied and will do so when blending them to the 0167 * background color values:: 0168 * 0169 * out.rgb = plane_alpha * fg.alpha * fg.rgb + 0170 * (1 - (plane_alpha * fg.alpha)) * bg.rgb 0171 * 0172 * Using the following symbols: 0173 * 0174 * "fg.rgb": 0175 * Each of the RGB component values from the plane's pixel 0176 * "fg.alpha": 0177 * Alpha component value from the plane's pixel. If the plane's 0178 * pixel format has no alpha component, then this is assumed to be 0179 * 1.0. In these cases, this property has no effect, as all three 0180 * equations become equivalent. 0181 * "bg.rgb": 0182 * Each of the RGB component values from the background 0183 * "plane_alpha": 0184 * Plane alpha value set by the plane "alpha" property. If the 0185 * plane does not expose the "alpha" property, then this is 0186 * assumed to be 1.0 0187 * 0188 * Note that all the property extensions described here apply either to the 0189 * plane or the CRTC (e.g. for the background color, which currently is not 0190 * exposed and assumed to be black). 0191 * 0192 * SCALING_FILTER: 0193 * Indicates scaling filter to be used for plane scaler 0194 * 0195 * The value of this property can be one of the following: 0196 * 0197 * Default: 0198 * Driver's default scaling filter 0199 * Nearest Neighbor: 0200 * Nearest Neighbor scaling filter 0201 * 0202 * Drivers can set up this property for a plane by calling 0203 * drm_plane_create_scaling_filter_property 0204 */ 0205 0206 /** 0207 * drm_plane_create_alpha_property - create a new alpha property 0208 * @plane: drm plane 0209 * 0210 * This function creates a generic, mutable, alpha property and enables support 0211 * for it in the DRM core. It is attached to @plane. 0212 * 0213 * The alpha property will be allowed to be within the bounds of 0 0214 * (transparent) to 0xffff (opaque). 0215 * 0216 * Returns: 0217 * 0 on success, negative error code on failure. 0218 */ 0219 int drm_plane_create_alpha_property(struct drm_plane *plane) 0220 { 0221 struct drm_property *prop; 0222 0223 prop = drm_property_create_range(plane->dev, 0, "alpha", 0224 0, DRM_BLEND_ALPHA_OPAQUE); 0225 if (!prop) 0226 return -ENOMEM; 0227 0228 drm_object_attach_property(&plane->base, prop, DRM_BLEND_ALPHA_OPAQUE); 0229 plane->alpha_property = prop; 0230 0231 if (plane->state) 0232 plane->state->alpha = DRM_BLEND_ALPHA_OPAQUE; 0233 0234 return 0; 0235 } 0236 EXPORT_SYMBOL(drm_plane_create_alpha_property); 0237 0238 /** 0239 * drm_plane_create_rotation_property - create a new rotation property 0240 * @plane: drm plane 0241 * @rotation: initial value of the rotation property 0242 * @supported_rotations: bitmask of supported rotations and reflections 0243 * 0244 * This creates a new property with the selected support for transformations. 0245 * 0246 * Since a rotation by 180° degress is the same as reflecting both along the x 0247 * and the y axis the rotation property is somewhat redundant. Drivers can use 0248 * drm_rotation_simplify() to normalize values of this property. 0249 * 0250 * The property exposed to userspace is a bitmask property (see 0251 * drm_property_create_bitmask()) called "rotation" and has the following 0252 * bitmask enumaration values: 0253 * 0254 * DRM_MODE_ROTATE_0: 0255 * "rotate-0" 0256 * DRM_MODE_ROTATE_90: 0257 * "rotate-90" 0258 * DRM_MODE_ROTATE_180: 0259 * "rotate-180" 0260 * DRM_MODE_ROTATE_270: 0261 * "rotate-270" 0262 * DRM_MODE_REFLECT_X: 0263 * "reflect-x" 0264 * DRM_MODE_REFLECT_Y: 0265 * "reflect-y" 0266 * 0267 * Rotation is the specified amount in degrees in counter clockwise direction, 0268 * the X and Y axis are within the source rectangle, i.e. the X/Y axis before 0269 * rotation. After reflection, the rotation is applied to the image sampled from 0270 * the source rectangle, before scaling it to fit the destination rectangle. 0271 */ 0272 int drm_plane_create_rotation_property(struct drm_plane *plane, 0273 unsigned int rotation, 0274 unsigned int supported_rotations) 0275 { 0276 static const struct drm_prop_enum_list props[] = { 0277 { __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" }, 0278 { __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" }, 0279 { __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" }, 0280 { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" }, 0281 { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" }, 0282 { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" }, 0283 }; 0284 struct drm_property *prop; 0285 0286 WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0); 0287 WARN_ON(!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK)); 0288 WARN_ON(rotation & ~supported_rotations); 0289 0290 prop = drm_property_create_bitmask(plane->dev, 0, "rotation", 0291 props, ARRAY_SIZE(props), 0292 supported_rotations); 0293 if (!prop) 0294 return -ENOMEM; 0295 0296 drm_object_attach_property(&plane->base, prop, rotation); 0297 0298 if (plane->state) 0299 plane->state->rotation = rotation; 0300 0301 plane->rotation_property = prop; 0302 0303 return 0; 0304 } 0305 EXPORT_SYMBOL(drm_plane_create_rotation_property); 0306 0307 /** 0308 * drm_rotation_simplify() - Try to simplify the rotation 0309 * @rotation: Rotation to be simplified 0310 * @supported_rotations: Supported rotations 0311 * 0312 * Attempt to simplify the rotation to a form that is supported. 0313 * Eg. if the hardware supports everything except DRM_MODE_REFLECT_X 0314 * one could call this function like this: 0315 * 0316 * drm_rotation_simplify(rotation, DRM_MODE_ROTATE_0 | 0317 * DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | 0318 * DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_Y); 0319 * 0320 * to eliminate the DRM_MODE_REFLECT_X flag. Depending on what kind of 0321 * transforms the hardware supports, this function may not 0322 * be able to produce a supported transform, so the caller should 0323 * check the result afterwards. 0324 */ 0325 unsigned int drm_rotation_simplify(unsigned int rotation, 0326 unsigned int supported_rotations) 0327 { 0328 if (rotation & ~supported_rotations) { 0329 rotation ^= DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; 0330 rotation = (rotation & DRM_MODE_REFLECT_MASK) | 0331 BIT((ffs(rotation & DRM_MODE_ROTATE_MASK) + 1) 0332 % 4); 0333 } 0334 0335 return rotation; 0336 } 0337 EXPORT_SYMBOL(drm_rotation_simplify); 0338 0339 /** 0340 * drm_plane_create_zpos_property - create mutable zpos property 0341 * @plane: drm plane 0342 * @zpos: initial value of zpos property 0343 * @min: minimal possible value of zpos property 0344 * @max: maximal possible value of zpos property 0345 * 0346 * This function initializes generic mutable zpos property and enables support 0347 * for it in drm core. Drivers can then attach this property to planes to enable 0348 * support for configurable planes arrangement during blending operation. 0349 * Drivers that attach a mutable zpos property to any plane should call the 0350 * drm_atomic_normalize_zpos() helper during their implementation of 0351 * &drm_mode_config_funcs.atomic_check(), which will update the normalized zpos 0352 * values and store them in &drm_plane_state.normalized_zpos. Usually min 0353 * should be set to 0 and max to maximal number of planes for given crtc - 1. 0354 * 0355 * If zpos of some planes cannot be changed (like fixed background or 0356 * cursor/topmost planes), drivers shall adjust the min/max values and assign 0357 * those planes immutable zpos properties with lower or higher values (for more 0358 * information, see drm_plane_create_zpos_immutable_property() function). In such 0359 * case drivers shall also assign proper initial zpos values for all planes in 0360 * its plane_reset() callback, so the planes will be always sorted properly. 0361 * 0362 * See also drm_atomic_normalize_zpos(). 0363 * 0364 * The property exposed to userspace is called "zpos". 0365 * 0366 * Returns: 0367 * Zero on success, negative errno on failure. 0368 */ 0369 int drm_plane_create_zpos_property(struct drm_plane *plane, 0370 unsigned int zpos, 0371 unsigned int min, unsigned int max) 0372 { 0373 struct drm_property *prop; 0374 0375 prop = drm_property_create_range(plane->dev, 0, "zpos", min, max); 0376 if (!prop) 0377 return -ENOMEM; 0378 0379 drm_object_attach_property(&plane->base, prop, zpos); 0380 0381 plane->zpos_property = prop; 0382 0383 if (plane->state) { 0384 plane->state->zpos = zpos; 0385 plane->state->normalized_zpos = zpos; 0386 } 0387 0388 return 0; 0389 } 0390 EXPORT_SYMBOL(drm_plane_create_zpos_property); 0391 0392 /** 0393 * drm_plane_create_zpos_immutable_property - create immuttable zpos property 0394 * @plane: drm plane 0395 * @zpos: value of zpos property 0396 * 0397 * This function initializes generic immutable zpos property and enables 0398 * support for it in drm core. Using this property driver lets userspace 0399 * to get the arrangement of the planes for blending operation and notifies 0400 * it that the hardware (or driver) doesn't support changing of the planes' 0401 * order. For mutable zpos see drm_plane_create_zpos_property(). 0402 * 0403 * The property exposed to userspace is called "zpos". 0404 * 0405 * Returns: 0406 * Zero on success, negative errno on failure. 0407 */ 0408 int drm_plane_create_zpos_immutable_property(struct drm_plane *plane, 0409 unsigned int zpos) 0410 { 0411 struct drm_property *prop; 0412 0413 prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE, 0414 "zpos", zpos, zpos); 0415 if (!prop) 0416 return -ENOMEM; 0417 0418 drm_object_attach_property(&plane->base, prop, zpos); 0419 0420 plane->zpos_property = prop; 0421 0422 if (plane->state) { 0423 plane->state->zpos = zpos; 0424 plane->state->normalized_zpos = zpos; 0425 } 0426 0427 return 0; 0428 } 0429 EXPORT_SYMBOL(drm_plane_create_zpos_immutable_property); 0430 0431 static int drm_atomic_state_zpos_cmp(const void *a, const void *b) 0432 { 0433 const struct drm_plane_state *sa = *(struct drm_plane_state **)a; 0434 const struct drm_plane_state *sb = *(struct drm_plane_state **)b; 0435 0436 if (sa->zpos != sb->zpos) 0437 return sa->zpos - sb->zpos; 0438 else 0439 return sa->plane->base.id - sb->plane->base.id; 0440 } 0441 0442 static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc, 0443 struct drm_crtc_state *crtc_state) 0444 { 0445 struct drm_atomic_state *state = crtc_state->state; 0446 struct drm_device *dev = crtc->dev; 0447 int total_planes = dev->mode_config.num_total_plane; 0448 struct drm_plane_state **states; 0449 struct drm_plane *plane; 0450 int i, n = 0; 0451 int ret = 0; 0452 0453 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n", 0454 crtc->base.id, crtc->name); 0455 0456 states = kmalloc_array(total_planes, sizeof(*states), GFP_KERNEL); 0457 if (!states) 0458 return -ENOMEM; 0459 0460 /* 0461 * Normalization process might create new states for planes which 0462 * normalized_zpos has to be recalculated. 0463 */ 0464 drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) { 0465 struct drm_plane_state *plane_state = 0466 drm_atomic_get_plane_state(state, plane); 0467 if (IS_ERR(plane_state)) { 0468 ret = PTR_ERR(plane_state); 0469 goto done; 0470 } 0471 states[n++] = plane_state; 0472 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n", 0473 plane->base.id, plane->name, 0474 plane_state->zpos); 0475 } 0476 0477 sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL); 0478 0479 for (i = 0; i < n; i++) { 0480 plane = states[i]->plane; 0481 0482 states[i]->normalized_zpos = i; 0483 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n", 0484 plane->base.id, plane->name, i); 0485 } 0486 crtc_state->zpos_changed = true; 0487 0488 done: 0489 kfree(states); 0490 return ret; 0491 } 0492 0493 /** 0494 * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs 0495 * @dev: DRM device 0496 * @state: atomic state of DRM device 0497 * 0498 * This function calculates normalized zpos value for all modified planes in 0499 * the provided atomic state of DRM device. 0500 * 0501 * For every CRTC this function checks new states of all planes assigned to 0502 * it and calculates normalized zpos value for these planes. Planes are compared 0503 * first by their zpos values, then by plane id (if zpos is equal). The plane 0504 * with lowest zpos value is at the bottom. The &drm_plane_state.normalized_zpos 0505 * is then filled with unique values from 0 to number of active planes in crtc 0506 * minus one. 0507 * 0508 * RETURNS 0509 * Zero for success or -errno 0510 */ 0511 int drm_atomic_normalize_zpos(struct drm_device *dev, 0512 struct drm_atomic_state *state) 0513 { 0514 struct drm_crtc *crtc; 0515 struct drm_crtc_state *old_crtc_state, *new_crtc_state; 0516 struct drm_plane *plane; 0517 struct drm_plane_state *old_plane_state, *new_plane_state; 0518 int i, ret = 0; 0519 0520 for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { 0521 crtc = new_plane_state->crtc; 0522 if (!crtc) 0523 continue; 0524 if (old_plane_state->zpos != new_plane_state->zpos) { 0525 new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 0526 new_crtc_state->zpos_changed = true; 0527 } 0528 } 0529 0530 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 0531 if (old_crtc_state->plane_mask != new_crtc_state->plane_mask || 0532 new_crtc_state->zpos_changed) { 0533 ret = drm_atomic_helper_crtc_normalize_zpos(crtc, 0534 new_crtc_state); 0535 if (ret) 0536 return ret; 0537 } 0538 } 0539 return 0; 0540 } 0541 EXPORT_SYMBOL(drm_atomic_normalize_zpos); 0542 0543 /** 0544 * drm_plane_create_blend_mode_property - create a new blend mode property 0545 * @plane: drm plane 0546 * @supported_modes: bitmask of supported modes, must include 0547 * BIT(DRM_MODE_BLEND_PREMULTI). Current DRM assumption is 0548 * that alpha is premultiplied, and old userspace can break if 0549 * the property defaults to anything else. 0550 * 0551 * This creates a new property describing the blend mode. 0552 * 0553 * The property exposed to userspace is an enumeration property (see 0554 * drm_property_create_enum()) called "pixel blend mode" and has the 0555 * following enumeration values: 0556 * 0557 * "None": 0558 * Blend formula that ignores the pixel alpha. 0559 * 0560 * "Pre-multiplied": 0561 * Blend formula that assumes the pixel color values have been already 0562 * pre-multiplied with the alpha channel values. 0563 * 0564 * "Coverage": 0565 * Blend formula that assumes the pixel color values have not been 0566 * pre-multiplied and will do so when blending them to the background color 0567 * values. 0568 * 0569 * RETURNS: 0570 * Zero for success or -errno 0571 */ 0572 int drm_plane_create_blend_mode_property(struct drm_plane *plane, 0573 unsigned int supported_modes) 0574 { 0575 struct drm_device *dev = plane->dev; 0576 struct drm_property *prop; 0577 static const struct drm_prop_enum_list props[] = { 0578 { DRM_MODE_BLEND_PIXEL_NONE, "None" }, 0579 { DRM_MODE_BLEND_PREMULTI, "Pre-multiplied" }, 0580 { DRM_MODE_BLEND_COVERAGE, "Coverage" }, 0581 }; 0582 unsigned int valid_mode_mask = BIT(DRM_MODE_BLEND_PIXEL_NONE) | 0583 BIT(DRM_MODE_BLEND_PREMULTI) | 0584 BIT(DRM_MODE_BLEND_COVERAGE); 0585 int i; 0586 0587 if (WARN_ON((supported_modes & ~valid_mode_mask) || 0588 ((supported_modes & BIT(DRM_MODE_BLEND_PREMULTI)) == 0))) 0589 return -EINVAL; 0590 0591 prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, 0592 "pixel blend mode", 0593 hweight32(supported_modes)); 0594 if (!prop) 0595 return -ENOMEM; 0596 0597 for (i = 0; i < ARRAY_SIZE(props); i++) { 0598 int ret; 0599 0600 if (!(BIT(props[i].type) & supported_modes)) 0601 continue; 0602 0603 ret = drm_property_add_enum(prop, props[i].type, 0604 props[i].name); 0605 0606 if (ret) { 0607 drm_property_destroy(dev, prop); 0608 0609 return ret; 0610 } 0611 } 0612 0613 drm_object_attach_property(&plane->base, prop, DRM_MODE_BLEND_PREMULTI); 0614 plane->blend_mode_property = prop; 0615 0616 return 0; 0617 } 0618 EXPORT_SYMBOL(drm_plane_create_blend_mode_property);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |