Add support for pixel_source property to drm_plane and related documentation. In addition, force pixel_source to DRM_PLANE_PIXEL_SOURCE_FB in DRM_IOCTL_MODE_SETPLANE as to not break legacy userspace. This enum property will allow user to specify a pixel source for the plane. Possible pixel sources will be defined in the drm_plane_pixel_source enum. Currently, the only pixel sources are DRM_PLANE_PIXEL_SOURCE_FB (the default value) and DRM_PLANE_PIXEL_SOURCE_NONE.
Unified · Split
| @@ -252,6 +252,7 @@ void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state, · 251 unmodified lines | |||
| 252 | 252 | ||
| 253 | plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; | 253 | plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; |
| 254 | plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; | 254 | plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; |
| 255 | plane_state->pixel_source = DRM_PLANE_PIXEL_SOURCE_FB; | ||
| 255 | 256 | ||
| 256 | if (plane->color_encoding_property) { | 257 | if (plane->color_encoding_property) { |
| 257 | if (!drm_object_property_get_default_value(&plane->base, | 258 | if (!drm_object_property_get_default_value(&plane->base, |
| @@ -562,6 +562,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, · 561 unmodified lines | |||
| 562 | state->src_w = val; | 562 | state->src_w = val; |
| 563 | } else if (property == config->prop_src_h) { | 563 | } else if (property == config->prop_src_h) { |
| 564 | state->src_h = val; | 564 | state->src_h = val; |
| 565 | } else if (property == plane->pixel_source_property) { | ||
| 566 | state->pixel_source = val; | ||
| 565 | } else if (property == plane->alpha_property) { | 567 | } else if (property == plane->alpha_property) { |
| 566 | state->alpha = val; | 568 | state->alpha = val; |
| 567 | } else if (property == plane->blend_mode_property) { | 569 | } else if (property == plane->blend_mode_property) { |
| @@ -650,6 +652,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, · 82 unmodified lines | |||
| 650 | *val = state->src_w; | 652 | *val = state->src_w; |
| 651 | } else if (property == config->prop_src_h) { | 653 | } else if (property == config->prop_src_h) { |
| 652 | *val = state->src_h; | 654 | *val = state->src_h; |
| 655 | } else if (property == plane->pixel_source_property) { | ||
| 656 | *val = state->pixel_source; | ||
| 653 | } else if (property == plane->alpha_property) { | 657 | } else if (property == plane->alpha_property) { |
| 654 | *val = state->alpha; | 658 | *val = state->alpha; |
| 655 | } else if (property == plane->blend_mode_property) { | 659 | } else if (property == plane->blend_mode_property) { |
| @@ -185,6 +185,25 @@ · 184 unmodified lines | |||
| 185 | * plane does not expose the "alpha" property, then this is | 185 | * plane does not expose the "alpha" property, then this is |
| 186 | * assumed to be 1.0 | 186 | * assumed to be 1.0 |
| 187 | * | 187 | * |
| 188 | * pixel_source: | ||
| 189 | * pixel_source is set up with drm_plane_create_pixel_source_property(). | ||
| 190 | * It is used to toggle the active source of pixel data for the plane. | ||
| 191 | * The plane will only display data from the set pixel_source -- any | ||
| 192 | * data from other sources will be ignored. | ||
| 193 | * | ||
| 194 | * For non-framebuffer sources, if pixel_source is set to a non-framebuffer | ||
| 195 | * and non-NONE source, and the corresponding source property is NULL, then | ||
| 196 | * the atomic commit should return an error. | ||
| 197 | * | ||
| 198 | * Possible values: | ||
| 199 | * | ||
| 200 | * "NONE": | ||
| 201 | * No active pixel source. | ||
| 202 | * Committing with a NONE pixel source will disable the plane. | ||
| 203 | * | ||
| 204 | * "FB": | ||
| 205 | * Framebuffer source set by the "FB_ID" property. | ||
| 206 | * | ||
| 188 | * Note that all the property extensions described here apply either to the | 207 | * Note that all the property extensions described here apply either to the |
| 189 | * plane or the CRTC (e.g. for the background color, which currently is not | 208 | * plane or the CRTC (e.g. for the background color, which currently is not |
| 190 | * exposed and assumed to be black). | 209 | * exposed and assumed to be black). |
| @@ -615,3 +634,78 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane, · 424 unmodified lines | |||
| 615 | return 0; | 634 | return 0; |
| 616 | } | 635 | } |
| 617 | EXPORT_SYMBOL(drm_plane_create_blend_mode_property); | 636 | EXPORT_SYMBOL(drm_plane_create_blend_mode_property); |
| 637 | |||
| 638 | static const struct drm_prop_enum_list drm_pixel_source_enum_list[] = { | ||
| 639 | { DRM_PLANE_PIXEL_SOURCE_NONE, "NONE" }, | ||
| 640 | { DRM_PLANE_PIXEL_SOURCE_FB, "FB" }, | ||
| 641 | }; | ||
| 642 | |||
| 643 | /** | ||
| 644 | * drm_plane_create_pixel_source_property - create a new pixel source property | ||
| 645 | * @plane: DRM plane | ||
| 646 | * @extra_sources: Bitmask of additional supported pixel_sources for the driver. | ||
| 647 | * DRM_PLANE_PIXEL_SOURCE_FB and DRM_PLANE_PIXEL_SOURCE_NONE will | ||
| 648 | * always be enabled as supported sources. | ||
| 649 | * | ||
| 650 | * This creates a new property describing the current source of pixel data for the | ||
| 651 | * plane. The pixel_source will be initialized as DRM_PLANE_PIXEL_SOURCE_FB by default. | ||
| 652 | * | ||
| 653 | * Drivers can set a custom default source by overriding the pixel_source value in | ||
| 654 | * drm_plane_funcs.reset() | ||
| 655 | * | ||
| 656 | * The property is exposed to userspace as an enumeration property called | ||
| 657 | * "pixel_source" and has the following enumeration values: | ||
| 658 | * | ||
| 659 | * "NONE": | ||
| 660 | * No active pixel source | ||
| 661 | * | ||
| 662 | * "FB": | ||
| 663 | * Framebuffer pixel source | ||
| 664 | * | ||
| 665 | * Returns: | ||
| 666 | * Zero on success, negative errno on failure. | ||
| 667 | */ | ||
| 668 | int drm_plane_create_pixel_source_property(struct drm_plane *plane, | ||
| 669 | unsigned long extra_sources) | ||
| 670 | { | ||
| 671 | struct drm_device *dev = plane->dev; | ||
| 672 | struct drm_property *prop; | ||
| 673 | static const unsigned int valid_source_mask = BIT(DRM_PLANE_PIXEL_SOURCE_FB) | | ||
| 674 | BIT(DRM_PLANE_PIXEL_SOURCE_NONE); | ||
| 675 | int i; | ||
| 676 | |||
| 677 | /* FB is supported by default */ | ||
| 678 | unsigned long supported_sources = extra_sources | | ||
| 679 | BIT(DRM_PLANE_PIXEL_SOURCE_FB) | | ||
| 680 | BIT(DRM_PLANE_PIXEL_SOURCE_NONE); | ||
| 681 | |||
| 682 | if (WARN_ON(supported_sources & ~valid_source_mask)) | ||
| 683 | return -EINVAL; | ||
| 684 | |||
| 685 | prop = drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_ATOMIC, "pixel_source", | ||
| 686 | hweight32(supported_sources)); | ||
| 687 | |||
| 688 | if (!prop) | ||
| 689 | return -ENOMEM; | ||
| 690 | |||
| 691 | for (i = 0; i < ARRAY_SIZE(drm_pixel_source_enum_list); i++) { | ||
| 692 | int ret; | ||
| 693 | |||
| 694 | if (!test_bit(drm_pixel_source_enum_list[i].type, &supported_sources)) | ||
| 695 | continue; | ||
| 696 | |||
| 697 | ret = drm_property_add_enum(prop, drm_pixel_source_enum_list[i].type, | ||
| 698 | drm_pixel_source_enum_list[i].name); | ||
| 699 | if (ret) { | ||
| 700 | drm_property_destroy(dev, prop); | ||
| 701 | |||
| 702 | return ret; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | drm_object_attach_property(&plane->base, prop, DRM_PLANE_PIXEL_SOURCE_FB); | ||
| 707 | plane->pixel_source_property = prop; | ||
| 708 | |||
| 709 | return 0; | ||
| 710 | } | ||
| 711 | EXPORT_SYMBOL(drm_plane_create_pixel_source_property); | ||
| @@ -953,6 +953,14 @@ bool drm_any_plane_has_format(struct drm_device *dev, · 952 unmodified lines | |||
| 953 | } | 953 | } |
| 954 | EXPORT_SYMBOL(drm_any_plane_has_format); | 954 | EXPORT_SYMBOL(drm_any_plane_has_format); |
| 955 | 955 | ||
| 956 | static bool drm_plane_needs_disable(struct drm_plane_state *state, struct drm_framebuffer *fb) | ||
| 957 | { | ||
| 958 | if (state->pixel_source == DRM_PLANE_PIXEL_SOURCE_NONE) | ||
| 959 | return true; | ||
| 960 | |||
| 961 | return state->pixel_source == DRM_PLANE_PIXEL_SOURCE_FB && fb == NULL; | ||
| 962 | } | ||
| 963 | |||
| 956 | /* | 964 | /* |
| 957 | * __setplane_internal - setplane handler for internal callers | 965 | * __setplane_internal - setplane handler for internal callers |
| 958 | * | 966 | * |
| @@ -975,8 +983,8 @@ static int __setplane_internal(struct drm_plane *plane, · 16 unmodified lines | |||
| 975 | 983 | ||
| 976 | WARN_ON(drm_drv_uses_atomic_modeset(plane->dev)); | 984 | WARN_ON(drm_drv_uses_atomic_modeset(plane->dev)); |
| 977 | 985 | ||
| 978 | /* No fb means shut it down */ | 986 | /* No visible data means shut it down */ |
| 979 | if (!fb) { | 987 | if (drm_plane_needs_disable(plane->state, fb)) { |
| 980 | plane->old_fb = plane->fb; | 988 | plane->old_fb = plane->fb; |
| 981 | ret = plane->funcs->disable_plane(plane, ctx); | 989 | ret = plane->funcs->disable_plane(plane, ctx); |
| 982 | if (!ret) { | 990 | if (!ret) { |
| @@ -1027,8 +1035,8 @@ static int __setplane_atomic(struct drm_plane *plane, · 44 unmodified lines | |||
| 1027 | 1035 | ||
| 1028 | WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev)); | 1036 | WARN_ON(!drm_drv_uses_atomic_modeset(plane->dev)); |
| 1029 | 1037 | ||
| 1030 | /* No fb means shut it down */ | 1038 | /* No visible data means shut it down */ |
| 1031 | if (!fb) | 1039 | if (drm_plane_needs_disable(plane->state, fb)) |
| 1032 | return plane->funcs->disable_plane(plane, ctx); | 1040 | return plane->funcs->disable_plane(plane, ctx); |
| 1033 | 1041 | ||
| 1034 | /* | 1042 | /* |
| @@ -1101,6 +1109,9 @@ int drm_mode_setplane(struct drm_device *dev, void *data, · 66 unmodified lines | |||
| 1101 | return -ENOENT; | 1109 | return -ENOENT; |
| 1102 | } | 1110 | } |
| 1103 | 1111 | ||
| 1112 | if (plane->state) | ||
| 1113 | plane->state->pixel_source = DRM_PLANE_PIXEL_SOURCE_FB; | ||
| 1114 | |||
| 1104 | if (plane_req->fb_id) { | 1115 | if (plane_req->fb_id) { |
| 1105 | fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id); | 1116 | fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id); |
| 1106 | if (!fb) { | 1117 | if (!fb) { |
| @@ -58,4 +58,6 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, · 57 unmodified lines | |||
| 58 | struct drm_atomic_state *state); | 58 | struct drm_atomic_state *state); |
| 59 | int drm_plane_create_blend_mode_property(struct drm_plane *plane, | 59 | int drm_plane_create_blend_mode_property(struct drm_plane *plane, |
| 60 | unsigned int supported_modes); | 60 | unsigned int supported_modes); |
| 61 | int drm_plane_create_pixel_source_property(struct drm_plane *plane, | ||
| 62 | unsigned long extra_sources); | ||
| 61 | #endif | 63 | #endif |
| @@ -40,6 +40,12 @@ enum drm_scaling_filter { · 39 unmodified lines | |||
| 40 | DRM_SCALING_FILTER_NEAREST_NEIGHBOR, | 40 | DRM_SCALING_FILTER_NEAREST_NEIGHBOR, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | enum drm_plane_pixel_source { | ||
| 44 | DRM_PLANE_PIXEL_SOURCE_NONE, | ||
| 45 | DRM_PLANE_PIXEL_SOURCE_FB, | ||
| 46 | DRM_PLANE_PIXEL_SOURCE_MAX | ||
| 47 | }; | ||
| 48 | |||
| 43 | /** | 49 | /** |
| 44 | * struct drm_plane_state - mutable plane state | 50 | * struct drm_plane_state - mutable plane state |
| 45 | * | 51 | * |
| @@ -120,6 +126,14 @@ struct drm_plane_state { · 74 unmodified lines | |||
| 120 | /** @hotspot_y: y offset to mouse cursor hotspot */ | 126 | /** @hotspot_y: y offset to mouse cursor hotspot */ |
| 121 | int32_t hotspot_x, hotspot_y; | 127 | int32_t hotspot_x, hotspot_y; |
| 122 | 128 | ||
| 129 | /** | ||
| 130 | * @pixel_source: | ||
| 131 | * | ||
| 132 | * Source of pixel information for the plane. See | ||
| 133 | * drm_plane_create_pixel_source_property() for more details. | ||
| 134 | */ | ||
| 135 | enum drm_plane_pixel_source pixel_source; | ||
| 136 | |||
| 123 | /** | 137 | /** |
| 124 | * @alpha: | 138 | * @alpha: |
| 125 | * Opacity of the plane with 0 as completely transparent and 0xffff as | 139 | * Opacity of the plane with 0 as completely transparent and 0xffff as |
| @@ -713,6 +727,13 @@ struct drm_plane { · 587 unmodified lines | |||
| 713 | */ | 727 | */ |
| 714 | struct drm_plane_state *state; | 728 | struct drm_plane_state *state; |
| 715 | 729 | ||
| 730 | /* | ||
| 731 | * @pixel_source_property: | ||
| 732 | * Optional pixel_source property for this plane. See | ||
| 733 | * drm_plane_create_pixel_source_property(). | ||
| 734 | */ | ||
| 735 | struct drm_property *pixel_source_property; | ||
| 736 | |||
| 716 | /** | 737 | /** |
| 717 | * @alpha_property: | 738 | * @alpha_property: |
| 718 | * Optional alpha property for this plane. See | 739 | * Optional alpha property for this plane. See |