From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Tue, 29 May 2018 10:11:03 +0300 From: Ville =?iso-8859-1?Q?Syrj=E4l=E4?= To: Dmitry Osipenko Cc: Laurent Pinchart , Thierry Reding , Neil Armstrong , Maxime Ripard , dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Alexandru Gheorghe , Russell King , Ben Skeggs , Sinclair Yeh , Thomas Hellstrom , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [RFC PATCH v2 1/2] drm: Add generic colorkey properties Message-ID: <20180529071103.GL23723@intel.com> References: <20180526155623.12610-1-digetx@gmail.com> <20180526155623.12610-2-digetx@gmail.com> <20180528131501.GK23723@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Sender: linux-media-owner@vger.kernel.org List-ID: On Tue, May 29, 2018 at 02:48:22AM +0300, Dmitry Osipenko wrote: > On 28.05.2018 16:15, Ville Syrj�l� wrote: > > On Sat, May 26, 2018 at 06:56:22PM +0300, Dmitry Osipenko wrote: > >> Color keying is the action of replacing pixels matching a given color > >> (or range of colors) with transparent pixels in an overlay when > >> performing blitting. Depending on the hardware capabilities, the > >> matching pixel can either become fully transparent or gain adjustment > >> of the pixels component values. > >> > >> Color keying is found in a large number of devices whose capabilities > >> often differ, but they still have enough common features in range to > >> standardize color key properties. This commit adds nine generic DRM plane > >> properties related to the color keying to cover various HW capabilities. > >> > >> This patch is based on the initial work done by Laurent Pinchart, most of > >> credits for this patch goes to him. > >> > >> Signed-off-by: Dmitry Osipenko > >> --- > >> drivers/gpu/drm/drm_atomic.c | 36 ++++++ > >> drivers/gpu/drm/drm_blend.c | 229 +++++++++++++++++++++++++++++++++++ > >> include/drm/drm_blend.h | 3 + > >> include/drm/drm_plane.h | 77 ++++++++++++ > >> 4 files changed, 345 insertions(+) > >> > >> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c > >> index 895741e9cd7d..5b808cb68654 100644 > >> --- a/drivers/gpu/drm/drm_atomic.c > >> +++ b/drivers/gpu/drm/drm_atomic.c > >> @@ -799,6 +799,24 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, > >> state->rotation = val; > >> } else if (property == plane->zpos_property) { > >> state->zpos = val; > >> + } else if (property == plane->colorkey.mode_property) { > >> + state->colorkey.mode = val; > >> + } else if (property == plane->colorkey.min_property) { > >> + state->colorkey.min = val; > >> + } else if (property == plane->colorkey.max_property) { > >> + state->colorkey.max = val; > >> + } else if (property == plane->colorkey.format_property) { > >> + state->colorkey.format = val; > >> + } else if (property == plane->colorkey.mask_property) { > >> + state->colorkey.mask = val; > >> + } else if (property == plane->colorkey.inverted_match_property) { > >> + state->colorkey.inverted_match = val; > >> + } else if (property == plane->colorkey.replacement_mask_property) { > >> + state->colorkey.replacement_mask = val; > >> + } else if (property == plane->colorkey.replacement_value_property) { > >> + state->colorkey.replacement_value = val; > >> + } else if (property == plane->colorkey.replacement_format_property) { > >> + state->colorkey.replacement_format = val; > >> } else if (property == plane->color_encoding_property) { > >> state->color_encoding = val; > >> } else if (property == plane->color_range_property) { > >> @@ -864,6 +882,24 @@ drm_atomic_plane_get_property(struct drm_plane *plane, > >> *val = state->rotation; > >> } else if (property == plane->zpos_property) { > >> *val = state->zpos; > >> + } else if (property == plane->colorkey.mode_property) { > >> + *val = state->colorkey.mode; > >> + } else if (property == plane->colorkey.min_property) { > >> + *val = state->colorkey.min; > >> + } else if (property == plane->colorkey.max_property) { > >> + *val = state->colorkey.max; > >> + } else if (property == plane->colorkey.format_property) { > >> + *val = state->colorkey.format; > >> + } else if (property == plane->colorkey.mask_property) { > >> + *val = state->colorkey.mask; > >> + } else if (property == plane->colorkey.inverted_match_property) { > >> + *val = state->colorkey.inverted_match; > >> + } else if (property == plane->colorkey.replacement_mask_property) { > >> + *val = state->colorkey.replacement_mask; > >> + } else if (property == plane->colorkey.replacement_value_property) { > >> + *val = state->colorkey.replacement_value; > >> + } else if (property == plane->colorkey.replacement_format_property) { > >> + *val = state->colorkey.replacement_format; > >> } else if (property == plane->color_encoding_property) { > >> *val = state->color_encoding; > >> } else if (property == plane->color_range_property) { > >> diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c > >> index a16a74d7e15e..05e5632ce375 100644 > >> --- a/drivers/gpu/drm/drm_blend.c > >> +++ b/drivers/gpu/drm/drm_blend.c > >> @@ -107,6 +107,11 @@ > >> * planes. Without this property the primary plane is always below the cursor > >> * plane, and ordering between all other planes is undefined. > >> * > >> + * colorkey: > >> + * Color keying is set up with drm_plane_create_colorkey_properties(). > >> + * It adds support for replacing a range of colors with a transparent > >> + * color in the plane. > >> + * > >> * 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). > >> @@ -448,3 +453,227 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, > >> return 0; > >> } > >> EXPORT_SYMBOL(drm_atomic_normalize_zpos); > >> + > >> +static const char * const plane_colorkey_mode_name[] = { > >> + [DRM_PLANE_COLORKEY_MODE_DISABLED] = "disabled", > >> + [DRM_PLANE_COLORKEY_MODE_SRC] = "src-match-src-replace", > >> + [DRM_PLANE_COLORKEY_MODE_DST] = "dst-match-src-replace", > > > > This list seems way more limited than I was expecting, at least when > > compared to all the different props you're proposing to add. > > > > What else are you expecting to see in the list? Prerry much all kinds of modes for the funky replacement values and whanot. > > >> +}; > >> + > >> +/** > >> + * drm_plane_create_colorkey_properties - create colorkey properties > >> + * @plane: drm plane > >> + * @supported_modes: bitmask of supported color keying modes > >> + * > >> + * This function creates the generic color keying properties and attach them to > >> + * the plane to enable color keying control for blending operations. > >> + * > >> + * Color keying is controlled through nine properties: > >> + * > >> + * colorkey.mode: > >> + * The mode is an enumerated property that controls how color keying > >> + * operates. The "disabled" mode that disables color keying and is > >> + * very likely to exist if color keying is supported, it should be the > >> + * default mode. > >> + * > >> + * colorkey.min, colorkey.max: > >> + * These two properties specify the colors that are treated as the color > >> + * key. Pixel whose value is in the [min, max] range is the color key > >> + * matching pixel. The minimum and maximum values are expressed as a > >> + * 64-bit integer in AXYZ16161616 format, where A is the alpha value and > >> + * X, Y and Z correspond to the color components of the colorkey.format. > >> + * In most cases XYZ will be either RGB or YUV. > >> + * > >> + * When a single color key is desired instead of a range, userspace shall > >> + * set the min and max properties to the same value. > >> + * > >> + * Drivers return an error from their plane atomic check if range can't be > >> + * handled. > >> + * > >> + * colorkey.format: > >> + * This property specifies the pixel format for the colorkey.min / max > >> + * properties. The format is given in a form of DRM fourcc code. > > > > Umm. Why we do even need this? This seems incompatible with your earlier > > "min/max are specified in 16bpc format" statement. > > > > AXYZ16161616 is just an abstraction of a pixel format, at least that's how I'm > interpreting the AXYZ16161616. > > Previously Laurent specified that min/max values should be given in the format > of the planes framebuffer. This doesn't work for a case of setting property for > a disabled plane because disabled plane doesn't have a framebuffer. This also > doesn't work for Tegra that can take only XRGB8888 format for a color key, AFAIK > HW internally converts all pixel formats to ARGB8888 and RGB part participates > in the color matching (later Tegra's support alpha channel matching as well). > Hence I added the format property that explicitly tells in what format the color > key integer value is given. > > I'm now thinking that format property should be exposed to userspace in a form > of a ENUM-list, because otherwise userspace doesn't know what color key formats > are supported by the DRM driver. I'm not sure that'll help particularly much. Generally you can't choose the format anyway, and it may just depends on the fb format or some other related factors. So not really sure how much benefit such an enum would have. And for hw where eg. the colorkey is always RGB even for YUV data (or vice versa) we could just do the YUV<->RGB conversion in the driver for the colorkey value provided by the user. The driver is in the best position to know the exact YUV<->RGB conversion formula used by the hardware anyway. > > And probably somehow userspace should be informed about that colorkey format > should match the framebuffers format if that's what driver expects. Maybe a > read-only property? > > >> + * > >> + * Drivers return an error from their plane atomic check if pixel format > >> + * is unsupported. > >> + * > >> + * colorkey.mask: > >> + * This property specifies the pixel components mask. Unmasked pixel > >> + * components are not participating in the matching. This mask value is > >> + * applied to colorkey.min / max values. The mask value is given in a > >> + * form of DRM fourcc code corresponding to the colorkey.format property. > >> + * > >> + * For example: userspace shall set the colorkey.mask to 0x0000ff00 > >> + * to match only the green component if colorkey.format is set to > >> + * DRM_FORMAT_XRGB8888. > >> + * > >> + * Drivers return an error from their plane atomic check if mask value > >> + * can't be handled. > >> + * > >> + * colorkey.inverted-match: > >> + * This property specifies whether the matching min-max range should > >> + * be inverted, i.e. pixels outside of the given color range become > >> + * the color key match. > >> + * > >> + * Drivers return an error from their plane atomic check if inversion > >> + * mode can't be handled. > > > > Hmm. I'm trying to figure out what this means for the src vs. dst > > colorkey modes. Those pretty much already have an inverted meaning when > > compared to each other. So I can't figure out from these docs whether > > you're supposed to use this when you want a normal dst ckey or normal > > src key semantics. > > > > I also couldn't understand what initial semantic to src/dst was given by Laurent. > > In a case of this patch: > > The src/dst-match specifies the "source" plane for which the color matching is > performed. Src means the plane to which the colorkey properties are applied. Dst > means planes other than plane X to which the colorkey properties are applied, in > particular the planes that are Z-positioned under the plane X. Hope that's more > clear now. > > The src-replace part specifies that pixels of the plane to which the colorkey > properties are applied will be replaced. > > I'll try to re-work the doc if the above sounds good. > > The inverted-match property controls whether given color-match range shall be > inverted, like for example: if given color key is a red color, then all colors > expect the red will be matched as a color key. > > Actually maybe inversion could be expressed using the mask solely. Like we could > add a helper that converts "value+mask" into "value=(value & ~mask), > inversion=true" if mask has form of 0x11000111, though this could be not > applicable to all possible pixel formats.. not sure. > > >> + * > >> + * colorkey.replacement-value: > >> + * This property specifies the color value that replaces pixels matching > >> + * the color key. The value is expressed in AXYZ16161616 format, where A > >> + * is the alpha value and X, Y and Z correspond to the color components > >> + * of the colorkey.replacement-format. > >> + * > >> + * Drivers return an error from their plane atomic check if replacement > >> + * value can't be handled. > >> + * > >> + * colorkey.replacement-format: > >> + * This property specifies the pixel format for the > >> + * colorkey.replacement-value property. The format is given in a form of > >> + * DRM fourcc code. > > > > Again this seems at odds with the 16bpc replacement-value. > > > >> + * > >> + * Drivers return an error from their plane atomic check if replacement > >> + * pixel format is unsupported. > >> + * > >> + * colorkey.replacement-mask: > >> + * This property specifies the pixel components mask that defines > >> + * what components of the colorkey.replacement-value will participate in > >> + * replacement of the pixels color. Unmasked pixel components are not > >> + * participating in the replacement. > > > > Does that mean that the data for the unmasked bits will be coming > > from the source? > > > > Yeah, I see that "source" is vaguely defined. > > Yes, the unmasked bits are coming from the source. The "source" is defined by > the mode. > > src-match- -->SRC<-- -replace > dst-match- -->SRC<-- -replace > > Src means the plane to which the colorkey properties are applied, as I stated above. > > >> The mask value is given in a form of > >> + * DRM fourcc code corresponding to the colorkey.replacement-format > >> + * property. > >> + * > >> + * For example: userspace shall set the colorkey.replacement-mask to > >> + * 0x0000ff00 to replace only the green component if > >> + * colorkey.replacement-format is set to DRM_FORMAT_XRGB8888. > >> + * > >> + * Userspace shall set colorkey.replacement-mask to 0 to disable the color > >> + * replacement. In this case matching pixels become transparent. > >> + * > >> + * Drivers return an error from their plane atomic check if replacement > >> + * mask value can't be handled. > >> + * > >> + * Returns: > >> + * Zero on success, negative errno on failure. > >> + */ > >> +int drm_plane_create_colorkey_properties(struct drm_plane *plane, > >> + u32 supported_modes) > >> +{ > >> + struct drm_prop_enum_list modes_list[DRM_PLANE_COLORKEY_MODES_NUM]; > >> + struct drm_property *replacement_format_prop; > >> + struct drm_property *replacement_value_prop; > >> + struct drm_property *replacement_mask_prop; > >> + struct drm_property *inverted_match_prop; > >> + struct drm_property *format_prop; > >> + struct drm_property *mask_prop; > >> + struct drm_property *mode_prop; > >> + struct drm_property *min_prop; > >> + struct drm_property *max_prop; > >> + unsigned int modes_num = 0; > >> + unsigned int i; > >> + > >> + /* at least two modes should be supported */ > >> + if (!supported_modes) > >> + return -EINVAL; > >> + > >> + /* modes are driver-specific, build the list of supported modes */ > >> + for (i = 0; i < DRM_PLANE_COLORKEY_MODES_NUM; i++) { > >> + if (!(supported_modes & BIT(i))) > >> + continue; > >> + > >> + modes_list[modes_num].name = plane_colorkey_mode_name[i]; > >> + modes_list[modes_num].type = i; > >> + modes_num++; > >> + } > >> + > >> + mode_prop = drm_property_create_enum(plane->dev, 0, "colorkey.mode", > >> + modes_list, modes_num); > >> + if (!mode_prop) > >> + return -ENOMEM; > >> + > >> + mask_prop = drm_property_create_range(plane->dev, 0, "colorkey.mask", > >> + 0, U64_MAX); > >> + if (!mask_prop) > >> + goto err_destroy_mode_prop; > >> + > >> + min_prop = drm_property_create_range(plane->dev, 0, "colorkey.min", > >> + 0, U64_MAX); > >> + if (!min_prop) > >> + goto err_destroy_mask_prop; > >> + > >> + max_prop = drm_property_create_range(plane->dev, 0, "colorkey.max", > >> + 0, U64_MAX); > >> + if (!max_prop) > >> + goto err_destroy_min_prop; > >> + > >> + format_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.format", > >> + 0, U32_MAX); > >> + if (!format_prop) > >> + goto err_destroy_max_prop; > >> + > >> + inverted_match_prop = drm_property_create_bool(plane->dev, 0, > >> + "colorkey.inverted-match"); > >> + if (!inverted_match_prop) > >> + goto err_destroy_format_prop; > >> + > >> + replacement_mask_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.replacement-mask", > >> + 0, U64_MAX); > >> + if (!replacement_mask_prop) > >> + goto err_destroy_inverted_match_prop; > >> + > >> + replacement_value_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.replacement-value", > >> + 0, U64_MAX); > >> + if (!replacement_value_prop) > >> + goto err_destroy_replacement_mask_prop; > >> + > >> + replacement_format_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.replacement-format", > >> + 0, U64_MAX); > >> + if (!replacement_format_prop) > >> + goto err_destroy_replacement_value_prop; > > > > I don't think we want to add all these props for every driver/hardware. > > IMO the set of props we expose should depend on the supported set of > > colorkeying modes. > > > > Probably, I don't mind. This should be documented then, I can address that in > the next iteration. > > /I think/ all of the currently-defined properties are relevant to the defined > color keying modes. i915 will want just value/mask or min/max, depending on whether we're dealing with rgb or yuv. And I've seen a lot of hardware with just the value/mask approach over the years. > Later, if the list of modes will be extended with new modes, > the creation of properties could be conditionalized. > > Though maybe "color components replacement" and "replacement with a complete > transparency" could be factored out into a specific color keying modes. Yes. I've never seen those in any hardware. In fact I'm wondering where is the userspace for all these complex modes? Ie. should we even bother with them at this time? -- Ville Syrj�l� Intel From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ville =?iso-8859-1?Q?Syrj=E4l=E4?= Subject: Re: [RFC PATCH v2 1/2] drm: Add generic colorkey properties Date: Tue, 29 May 2018 10:11:03 +0300 Message-ID: <20180529071103.GL23723@intel.com> References: <20180526155623.12610-1-digetx@gmail.com> <20180526155623.12610-2-digetx@gmail.com> <20180528131501.GK23723@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Content-Disposition: inline In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Dmitry Osipenko Cc: Thomas Hellstrom , Laurent Pinchart , Neil Armstrong , Russell King , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-tegra@vger.kernel.org, Thierry Reding , Ben Skeggs , Rodrigo Vivi , Maxime Ripard , Alexandru Gheorghe , linux-media@vger.kernel.org List-Id: linux-tegra@vger.kernel.org T24gVHVlLCBNYXkgMjksIDIwMTggYXQgMDI6NDg6MjJBTSArMDMwMCwgRG1pdHJ5IE9zaXBlbmtv IHdyb3RlOgo+IE9uIDI4LjA1LjIwMTggMTY6MTUsIFZpbGxlIFN5cmrDpGzDpCB3cm90ZToKPiA+ IE9uIFNhdCwgTWF5IDI2LCAyMDE4IGF0IDA2OjU2OjIyUE0gKzAzMDAsIERtaXRyeSBPc2lwZW5r byB3cm90ZToKPiA+PiBDb2xvciBrZXlpbmcgaXMgdGhlIGFjdGlvbiBvZiByZXBsYWNpbmcgcGl4 ZWxzIG1hdGNoaW5nIGEgZ2l2ZW4gY29sb3IKPiA+PiAob3IgcmFuZ2Ugb2YgY29sb3JzKSB3aXRo IHRyYW5zcGFyZW50IHBpeGVscyBpbiBhbiBvdmVybGF5IHdoZW4KPiA+PiBwZXJmb3JtaW5nIGJs aXR0aW5nLiBEZXBlbmRpbmcgb24gdGhlIGhhcmR3YXJlIGNhcGFiaWxpdGllcywgdGhlCj4gPj4g bWF0Y2hpbmcgcGl4ZWwgY2FuIGVpdGhlciBiZWNvbWUgZnVsbHkgdHJhbnNwYXJlbnQgb3IgZ2Fp biBhZGp1c3RtZW50Cj4gPj4gb2YgdGhlIHBpeGVscyBjb21wb25lbnQgdmFsdWVzLgo+ID4+Cj4g Pj4gQ29sb3Iga2V5aW5nIGlzIGZvdW5kIGluIGEgbGFyZ2UgbnVtYmVyIG9mIGRldmljZXMgd2hv c2UgY2FwYWJpbGl0aWVzCj4gPj4gb2Z0ZW4gZGlmZmVyLCBidXQgdGhleSBzdGlsbCBoYXZlIGVu b3VnaCBjb21tb24gZmVhdHVyZXMgaW4gcmFuZ2UgdG8KPiA+PiBzdGFuZGFyZGl6ZSBjb2xvciBr ZXkgcHJvcGVydGllcy4gVGhpcyBjb21taXQgYWRkcyBuaW5lIGdlbmVyaWMgRFJNIHBsYW5lCj4g Pj4gcHJvcGVydGllcyByZWxhdGVkIHRvIHRoZSBjb2xvciBrZXlpbmcgdG8gY292ZXIgdmFyaW91 cyBIVyBjYXBhYmlsaXRpZXMuCj4gPj4KPiA+PiBUaGlzIHBhdGNoIGlzIGJhc2VkIG9uIHRoZSBp bml0aWFsIHdvcmsgZG9uZSBieSBMYXVyZW50IFBpbmNoYXJ0LCBtb3N0IG9mCj4gPj4gY3JlZGl0 cyBmb3IgdGhpcyBwYXRjaCBnb2VzIHRvIGhpbS4KPiA+Pgo+ID4+IFNpZ25lZC1vZmYtYnk6IERt aXRyeSBPc2lwZW5rbyA8ZGlnZXR4QGdtYWlsLmNvbT4KPiA+PiAtLS0KPiA+PiAgZHJpdmVycy9n cHUvZHJtL2RybV9hdG9taWMuYyB8ICAzNiArKysrKysKPiA+PiAgZHJpdmVycy9ncHUvZHJtL2Ry bV9ibGVuZC5jICB8IDIyOSArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ID4+ ICBpbmNsdWRlL2RybS9kcm1fYmxlbmQuaCAgICAgIHwgICAzICsKPiA+PiAgaW5jbHVkZS9kcm0v ZHJtX3BsYW5lLmggICAgICB8ICA3NyArKysrKysrKysrKysKPiA+PiAgNCBmaWxlcyBjaGFuZ2Vk LCAzNDUgaW5zZXJ0aW9ucygrKQo+ID4+Cj4gPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2Ry bS9kcm1fYXRvbWljLmMgYi9kcml2ZXJzL2dwdS9kcm0vZHJtX2F0b21pYy5jCj4gPj4gaW5kZXgg ODk1NzQxZTljZDdkLi41YjgwOGNiNjg2NTQgMTAwNjQ0Cj4gPj4gLS0tIGEvZHJpdmVycy9ncHUv ZHJtL2RybV9hdG9taWMuYwo+ID4+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9kcm1fYXRvbWljLmMK PiA+PiBAQCAtNzk5LDYgKzc5OSwyNCBAQCBzdGF0aWMgaW50IGRybV9hdG9taWNfcGxhbmVfc2V0 X3Byb3BlcnR5KHN0cnVjdCBkcm1fcGxhbmUgKnBsYW5lLAo+ID4+ICAJCXN0YXRlLT5yb3RhdGlv biA9IHZhbDsKPiA+PiAgCX0gZWxzZSBpZiAocHJvcGVydHkgPT0gcGxhbmUtPnpwb3NfcHJvcGVy dHkpIHsKPiA+PiAgCQlzdGF0ZS0+enBvcyA9IHZhbDsKPiA+PiArCX0gZWxzZSBpZiAocHJvcGVy dHkgPT0gcGxhbmUtPmNvbG9ya2V5Lm1vZGVfcHJvcGVydHkpIHsKPiA+PiArCQlzdGF0ZS0+Y29s b3JrZXkubW9kZSA9IHZhbDsKPiA+PiArCX0gZWxzZSBpZiAocHJvcGVydHkgPT0gcGxhbmUtPmNv bG9ya2V5Lm1pbl9wcm9wZXJ0eSkgewo+ID4+ICsJCXN0YXRlLT5jb2xvcmtleS5taW4gPSB2YWw7 Cj4gPj4gKwl9IGVsc2UgaWYgKHByb3BlcnR5ID09IHBsYW5lLT5jb2xvcmtleS5tYXhfcHJvcGVy dHkpIHsKPiA+PiArCQlzdGF0ZS0+Y29sb3JrZXkubWF4ID0gdmFsOwo+ID4+ICsJfSBlbHNlIGlm IChwcm9wZXJ0eSA9PSBwbGFuZS0+Y29sb3JrZXkuZm9ybWF0X3Byb3BlcnR5KSB7Cj4gPj4gKwkJ c3RhdGUtPmNvbG9ya2V5LmZvcm1hdCA9IHZhbDsKPiA+PiArCX0gZWxzZSBpZiAocHJvcGVydHkg PT0gcGxhbmUtPmNvbG9ya2V5Lm1hc2tfcHJvcGVydHkpIHsKPiA+PiArCQlzdGF0ZS0+Y29sb3Jr ZXkubWFzayA9IHZhbDsKPiA+PiArCX0gZWxzZSBpZiAocHJvcGVydHkgPT0gcGxhbmUtPmNvbG9y a2V5LmludmVydGVkX21hdGNoX3Byb3BlcnR5KSB7Cj4gPj4gKwkJc3RhdGUtPmNvbG9ya2V5Lmlu dmVydGVkX21hdGNoID0gdmFsOwo+ID4+ICsJfSBlbHNlIGlmIChwcm9wZXJ0eSA9PSBwbGFuZS0+ Y29sb3JrZXkucmVwbGFjZW1lbnRfbWFza19wcm9wZXJ0eSkgewo+ID4+ICsJCXN0YXRlLT5jb2xv cmtleS5yZXBsYWNlbWVudF9tYXNrID0gdmFsOwo+ID4+ICsJfSBlbHNlIGlmIChwcm9wZXJ0eSA9 PSBwbGFuZS0+Y29sb3JrZXkucmVwbGFjZW1lbnRfdmFsdWVfcHJvcGVydHkpIHsKPiA+PiArCQlz dGF0ZS0+Y29sb3JrZXkucmVwbGFjZW1lbnRfdmFsdWUgPSB2YWw7Cj4gPj4gKwl9IGVsc2UgaWYg KHByb3BlcnR5ID09IHBsYW5lLT5jb2xvcmtleS5yZXBsYWNlbWVudF9mb3JtYXRfcHJvcGVydHkp IHsKPiA+PiArCQlzdGF0ZS0+Y29sb3JrZXkucmVwbGFjZW1lbnRfZm9ybWF0ID0gdmFsOwo+ID4+ ICAJfSBlbHNlIGlmIChwcm9wZXJ0eSA9PSBwbGFuZS0+Y29sb3JfZW5jb2RpbmdfcHJvcGVydHkp IHsKPiA+PiAgCQlzdGF0ZS0+Y29sb3JfZW5jb2RpbmcgPSB2YWw7Cj4gPj4gIAl9IGVsc2UgaWYg KHByb3BlcnR5ID09IHBsYW5lLT5jb2xvcl9yYW5nZV9wcm9wZXJ0eSkgewo+ID4+IEBAIC04NjQs NiArODgyLDI0IEBAIGRybV9hdG9taWNfcGxhbmVfZ2V0X3Byb3BlcnR5KHN0cnVjdCBkcm1fcGxh bmUgKnBsYW5lLAo+ID4+ICAJCSp2YWwgPSBzdGF0ZS0+cm90YXRpb247Cj4gPj4gIAl9IGVsc2Ug aWYgKHByb3BlcnR5ID09IHBsYW5lLT56cG9zX3Byb3BlcnR5KSB7Cj4gPj4gIAkJKnZhbCA9IHN0 YXRlLT56cG9zOwo+ID4+ICsJfSBlbHNlIGlmIChwcm9wZXJ0eSA9PSBwbGFuZS0+Y29sb3JrZXku bW9kZV9wcm9wZXJ0eSkgewo+ID4+ICsJCSp2YWwgPSBzdGF0ZS0+Y29sb3JrZXkubW9kZTsKPiA+ PiArCX0gZWxzZSBpZiAocHJvcGVydHkgPT0gcGxhbmUtPmNvbG9ya2V5Lm1pbl9wcm9wZXJ0eSkg ewo+ID4+ICsJCSp2YWwgPSBzdGF0ZS0+Y29sb3JrZXkubWluOwo+ID4+ICsJfSBlbHNlIGlmIChw cm9wZXJ0eSA9PSBwbGFuZS0+Y29sb3JrZXkubWF4X3Byb3BlcnR5KSB7Cj4gPj4gKwkJKnZhbCA9 IHN0YXRlLT5jb2xvcmtleS5tYXg7Cj4gPj4gKwl9IGVsc2UgaWYgKHByb3BlcnR5ID09IHBsYW5l LT5jb2xvcmtleS5mb3JtYXRfcHJvcGVydHkpIHsKPiA+PiArCQkqdmFsID0gc3RhdGUtPmNvbG9y a2V5LmZvcm1hdDsKPiA+PiArCX0gZWxzZSBpZiAocHJvcGVydHkgPT0gcGxhbmUtPmNvbG9ya2V5 Lm1hc2tfcHJvcGVydHkpIHsKPiA+PiArCQkqdmFsID0gc3RhdGUtPmNvbG9ya2V5Lm1hc2s7Cj4g Pj4gKwl9IGVsc2UgaWYgKHByb3BlcnR5ID09IHBsYW5lLT5jb2xvcmtleS5pbnZlcnRlZF9tYXRj aF9wcm9wZXJ0eSkgewo+ID4+ICsJCSp2YWwgPSBzdGF0ZS0+Y29sb3JrZXkuaW52ZXJ0ZWRfbWF0 Y2g7Cj4gPj4gKwl9IGVsc2UgaWYgKHByb3BlcnR5ID09IHBsYW5lLT5jb2xvcmtleS5yZXBsYWNl bWVudF9tYXNrX3Byb3BlcnR5KSB7Cj4gPj4gKwkJKnZhbCA9IHN0YXRlLT5jb2xvcmtleS5yZXBs YWNlbWVudF9tYXNrOwo+ID4+ICsJfSBlbHNlIGlmIChwcm9wZXJ0eSA9PSBwbGFuZS0+Y29sb3Jr ZXkucmVwbGFjZW1lbnRfdmFsdWVfcHJvcGVydHkpIHsKPiA+PiArCQkqdmFsID0gc3RhdGUtPmNv bG9ya2V5LnJlcGxhY2VtZW50X3ZhbHVlOwo+ID4+ICsJfSBlbHNlIGlmIChwcm9wZXJ0eSA9PSBw bGFuZS0+Y29sb3JrZXkucmVwbGFjZW1lbnRfZm9ybWF0X3Byb3BlcnR5KSB7Cj4gPj4gKwkJKnZh bCA9IHN0YXRlLT5jb2xvcmtleS5yZXBsYWNlbWVudF9mb3JtYXQ7Cj4gPj4gIAl9IGVsc2UgaWYg KHByb3BlcnR5ID09IHBsYW5lLT5jb2xvcl9lbmNvZGluZ19wcm9wZXJ0eSkgewo+ID4+ICAJCSp2 YWwgPSBzdGF0ZS0+Y29sb3JfZW5jb2Rpbmc7Cj4gPj4gIAl9IGVsc2UgaWYgKHByb3BlcnR5ID09 IHBsYW5lLT5jb2xvcl9yYW5nZV9wcm9wZXJ0eSkgewo+ID4+IGRpZmYgLS1naXQgYS9kcml2ZXJz L2dwdS9kcm0vZHJtX2JsZW5kLmMgYi9kcml2ZXJzL2dwdS9kcm0vZHJtX2JsZW5kLmMKPiA+PiBp bmRleCBhMTZhNzRkN2UxNWUuLjA1ZTU2MzJjZTM3NSAxMDA2NDQKPiA+PiAtLS0gYS9kcml2ZXJz L2dwdS9kcm0vZHJtX2JsZW5kLmMKPiA+PiArKysgYi9kcml2ZXJzL2dwdS9kcm0vZHJtX2JsZW5k LmMKPiA+PiBAQCAtMTA3LDYgKzEwNywxMSBAQAo+ID4+ICAgKglwbGFuZXMuIFdpdGhvdXQgdGhp cyBwcm9wZXJ0eSB0aGUgcHJpbWFyeSBwbGFuZSBpcyBhbHdheXMgYmVsb3cgdGhlIGN1cnNvcgo+ ID4+ICAgKglwbGFuZSwgYW5kIG9yZGVyaW5nIGJldHdlZW4gYWxsIG90aGVyIHBsYW5lcyBpcyB1 bmRlZmluZWQuCj4gPj4gICAqCj4gPj4gKyAqIGNvbG9ya2V5Ogo+ID4+ICsgKglDb2xvciBrZXlp bmcgaXMgc2V0IHVwIHdpdGggZHJtX3BsYW5lX2NyZWF0ZV9jb2xvcmtleV9wcm9wZXJ0aWVzKCku Cj4gPj4gKyAqCUl0IGFkZHMgc3VwcG9ydCBmb3IgcmVwbGFjaW5nIGEgcmFuZ2Ugb2YgY29sb3Jz IHdpdGggYSB0cmFuc3BhcmVudAo+ID4+ICsgKgljb2xvciBpbiB0aGUgcGxhbmUuCj4gPj4gKyAq Cj4gPj4gICAqIE5vdGUgdGhhdCBhbGwgdGhlIHByb3BlcnR5IGV4dGVuc2lvbnMgZGVzY3JpYmVk IGhlcmUgYXBwbHkgZWl0aGVyIHRvIHRoZQo+ID4+ICAgKiBwbGFuZSBvciB0aGUgQ1JUQyAoZS5n LiBmb3IgdGhlIGJhY2tncm91bmQgY29sb3IsIHdoaWNoIGN1cnJlbnRseSBpcyBub3QKPiA+PiAg ICogZXhwb3NlZCBhbmQgYXNzdW1lZCB0byBiZSBibGFjaykuCj4gPj4gQEAgLTQ0OCwzICs0NTMs MjI3IEBAIGludCBkcm1fYXRvbWljX25vcm1hbGl6ZV96cG9zKHN0cnVjdCBkcm1fZGV2aWNlICpk ZXYsCj4gPj4gIAlyZXR1cm4gMDsKPiA+PiAgfQo+ID4+ICBFWFBPUlRfU1lNQk9MKGRybV9hdG9t aWNfbm9ybWFsaXplX3pwb3MpOwo+ID4+ICsKPiA+PiArc3RhdGljIGNvbnN0IGNoYXIgKiBjb25z dCBwbGFuZV9jb2xvcmtleV9tb2RlX25hbWVbXSA9IHsKPiA+PiArCVtEUk1fUExBTkVfQ09MT1JL RVlfTU9ERV9ESVNBQkxFRF0gPSAiZGlzYWJsZWQiLAo+ID4+ICsJW0RSTV9QTEFORV9DT0xPUktF WV9NT0RFX1NSQ10gPSAic3JjLW1hdGNoLXNyYy1yZXBsYWNlIiwKPiA+PiArCVtEUk1fUExBTkVf Q09MT1JLRVlfTU9ERV9EU1RdID0gImRzdC1tYXRjaC1zcmMtcmVwbGFjZSIsCj4gPiAKPiA+IFRo aXMgbGlzdCBzZWVtcyB3YXkgbW9yZSBsaW1pdGVkIHRoYW4gSSB3YXMgZXhwZWN0aW5nLCBhdCBs ZWFzdCB3aGVuCj4gPiBjb21wYXJlZCB0byBhbGwgdGhlIGRpZmZlcmVudCBwcm9wcyB5b3UncmUg cHJvcG9zaW5nIHRvIGFkZC4KPiA+IAo+IAo+IFdoYXQgZWxzZSBhcmUgeW91IGV4cGVjdGluZyB0 byBzZWUgaW4gdGhlIGxpc3Q/CgpQcmVycnkgbXVjaCBhbGwga2luZHMgb2YgbW9kZXMgZm9yIHRo ZSBmdW5reSByZXBsYWNlbWVudCB2YWx1ZXMKYW5kIHdoYW5vdC4KCj4gCj4gPj4gK307Cj4gPj4g Kwo+ID4+ICsvKioKPiA+PiArICogZHJtX3BsYW5lX2NyZWF0ZV9jb2xvcmtleV9wcm9wZXJ0aWVz IC0gY3JlYXRlIGNvbG9ya2V5IHByb3BlcnRpZXMKPiA+PiArICogQHBsYW5lOiBkcm0gcGxhbmUK PiA+PiArICogQHN1cHBvcnRlZF9tb2RlczogYml0bWFzayBvZiBzdXBwb3J0ZWQgY29sb3Iga2V5 aW5nIG1vZGVzCj4gPj4gKyAqCj4gPj4gKyAqIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyB0aGUgZ2Vu ZXJpYyBjb2xvciBrZXlpbmcgcHJvcGVydGllcyBhbmQgYXR0YWNoIHRoZW0gdG8KPiA+PiArICog dGhlIHBsYW5lIHRvIGVuYWJsZSBjb2xvciBrZXlpbmcgY29udHJvbCBmb3IgYmxlbmRpbmcgb3Bl cmF0aW9ucy4KPiA+PiArICoKPiA+PiArICogQ29sb3Iga2V5aW5nIGlzIGNvbnRyb2xsZWQgdGhy b3VnaCBuaW5lIHByb3BlcnRpZXM6Cj4gPj4gKyAqCj4gPj4gKyAqIGNvbG9ya2V5Lm1vZGU6Cj4g Pj4gKyAqCVRoZSBtb2RlIGlzIGFuIGVudW1lcmF0ZWQgcHJvcGVydHkgdGhhdCBjb250cm9scyBo b3cgY29sb3Iga2V5aW5nCj4gPj4gKyAqCW9wZXJhdGVzLiBUaGUgImRpc2FibGVkIiBtb2RlIHRo YXQgZGlzYWJsZXMgY29sb3Iga2V5aW5nIGFuZCBpcwo+ID4+ICsgKgl2ZXJ5IGxpa2VseSB0byBl eGlzdCBpZiBjb2xvciBrZXlpbmcgaXMgc3VwcG9ydGVkLCBpdCBzaG91bGQgYmUgdGhlCj4gPj4g KyAqCWRlZmF1bHQgbW9kZS4KPiA+PiArICoKPiA+PiArICogY29sb3JrZXkubWluLCBjb2xvcmtl eS5tYXg6Cj4gPj4gKyAqCVRoZXNlIHR3byBwcm9wZXJ0aWVzIHNwZWNpZnkgdGhlIGNvbG9ycyB0 aGF0IGFyZSB0cmVhdGVkIGFzIHRoZSBjb2xvcgo+ID4+ICsgKglrZXkuIFBpeGVsIHdob3NlIHZh bHVlIGlzIGluIHRoZSBbbWluLCBtYXhdIHJhbmdlIGlzIHRoZSBjb2xvciBrZXkKPiA+PiArICoJ bWF0Y2hpbmcgcGl4ZWwuIFRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcyBhcmUgZXhwcmVz c2VkIGFzIGEKPiA+PiArICoJNjQtYml0IGludGVnZXIgaW4gQVhZWjE2MTYxNjE2IGZvcm1hdCwg d2hlcmUgQSBpcyB0aGUgYWxwaGEgdmFsdWUgYW5kCj4gPj4gKyAqCVgsIFkgYW5kIFogY29ycmVz cG9uZCB0byB0aGUgY29sb3IgY29tcG9uZW50cyBvZiB0aGUgY29sb3JrZXkuZm9ybWF0Lgo+ID4+ ICsgKglJbiBtb3N0IGNhc2VzIFhZWiB3aWxsIGJlIGVpdGhlciBSR0Igb3IgWVVWLgo+ID4+ICsg Kgo+ID4+ICsgKglXaGVuIGEgc2luZ2xlIGNvbG9yIGtleSBpcyBkZXNpcmVkIGluc3RlYWQgb2Yg YSByYW5nZSwgdXNlcnNwYWNlIHNoYWxsCj4gPj4gKyAqCXNldCB0aGUgbWluIGFuZCBtYXggcHJv cGVydGllcyB0byB0aGUgc2FtZSB2YWx1ZS4KPiA+PiArICoKPiA+PiArICoJRHJpdmVycyByZXR1 cm4gYW4gZXJyb3IgZnJvbSB0aGVpciBwbGFuZSBhdG9taWMgY2hlY2sgaWYgcmFuZ2UgY2FuJ3Qg YmUKPiA+PiArICoJaGFuZGxlZC4KPiA+PiArICoKPiA+PiArICogY29sb3JrZXkuZm9ybWF0Ogo+ ID4+ICsgKglUaGlzIHByb3BlcnR5IHNwZWNpZmllcyB0aGUgcGl4ZWwgZm9ybWF0IGZvciB0aGUg Y29sb3JrZXkubWluIC8gbWF4Cj4gPj4gKyAqCXByb3BlcnRpZXMuIFRoZSBmb3JtYXQgaXMgZ2l2 ZW4gaW4gYSBmb3JtIG9mIERSTSBmb3VyY2MgY29kZS4KPiA+IAo+ID4gVW1tLiBXaHkgd2UgZG8g ZXZlbiBuZWVkIHRoaXM/IFRoaXMgc2VlbXMgaW5jb21wYXRpYmxlIHdpdGggeW91ciBlYXJsaWVy Cj4gPiAibWluL21heCBhcmUgc3BlY2lmaWVkIGluIDE2YnBjIGZvcm1hdCIgc3RhdGVtZW50Lgo+ ID4gCj4gCj4gQVhZWjE2MTYxNjE2IGlzIGp1c3QgYW4gYWJzdHJhY3Rpb24gb2YgYSBwaXhlbCBm b3JtYXQsIGF0IGxlYXN0IHRoYXQncyBob3cgSSdtCj4gaW50ZXJwcmV0aW5nIHRoZSBBWFlaMTYx NjE2MTYuCj4gCj4gUHJldmlvdXNseSBMYXVyZW50IHNwZWNpZmllZCB0aGF0IG1pbi9tYXggdmFs dWVzIHNob3VsZCBiZSBnaXZlbiBpbiB0aGUgZm9ybWF0Cj4gb2YgdGhlIHBsYW5lcyBmcmFtZWJ1 ZmZlci4gVGhpcyBkb2Vzbid0IHdvcmsgZm9yIGEgY2FzZSBvZiBzZXR0aW5nIHByb3BlcnR5IGZv cgo+IGEgZGlzYWJsZWQgcGxhbmUgYmVjYXVzZSBkaXNhYmxlZCBwbGFuZSBkb2Vzbid0IGhhdmUg YSBmcmFtZWJ1ZmZlci4gVGhpcyBhbHNvCj4gZG9lc24ndCB3b3JrIGZvciBUZWdyYSB0aGF0IGNh biB0YWtlIG9ubHkgWFJHQjg4ODggZm9ybWF0IGZvciBhIGNvbG9yIGtleSwgQUZBSUsKPiBIVyBp bnRlcm5hbGx5IGNvbnZlcnRzIGFsbCBwaXhlbCBmb3JtYXRzIHRvIEFSR0I4ODg4IGFuZCBSR0Ig cGFydCBwYXJ0aWNpcGF0ZXMKPiBpbiB0aGUgY29sb3IgbWF0Y2hpbmcgKGxhdGVyIFRlZ3JhJ3Mg c3VwcG9ydCBhbHBoYSBjaGFubmVsIG1hdGNoaW5nIGFzIHdlbGwpLgo+IEhlbmNlIEkgYWRkZWQg dGhlIGZvcm1hdCBwcm9wZXJ0eSB0aGF0IGV4cGxpY2l0bHkgdGVsbHMgaW4gd2hhdCBmb3JtYXQg dGhlIGNvbG9yCj4ga2V5IGludGVnZXIgdmFsdWUgaXMgZ2l2ZW4uCj4gCj4gSSdtIG5vdyB0aGlu a2luZyB0aGF0IGZvcm1hdCBwcm9wZXJ0eSBzaG91bGQgYmUgZXhwb3NlZCB0byB1c2Vyc3BhY2Ug aW4gYSBmb3JtCj4gb2YgYSBFTlVNLWxpc3QsIGJlY2F1c2Ugb3RoZXJ3aXNlIHVzZXJzcGFjZSBk b2Vzbid0IGtub3cgd2hhdCBjb2xvciBrZXkgZm9ybWF0cwo+IGFyZSBzdXBwb3J0ZWQgYnkgdGhl IERSTSBkcml2ZXIuCgpJJ20gbm90IHN1cmUgdGhhdCdsbCBoZWxwIHBhcnRpY3VsYXJseSBtdWNo LiBHZW5lcmFsbHkgeW91IGNhbid0IApjaG9vc2UgdGhlIGZvcm1hdCBhbnl3YXksIGFuZCBpdCBt YXkganVzdCBkZXBlbmRzIG9uIHRoZSBmYiBmb3JtYXQKb3Igc29tZSBvdGhlciByZWxhdGVkIGZh Y3RvcnMuIFNvIG5vdCByZWFsbHkgc3VyZSBob3cgbXVjaCBiZW5lZml0CnN1Y2ggYW4gZW51bSB3 b3VsZCBoYXZlLgoKQW5kIGZvciBodyB3aGVyZSBlZy4gdGhlIGNvbG9ya2V5IGlzIGFsd2F5cyBS R0IgZXZlbiBmb3IgWVVWIGRhdGEKKG9yIHZpY2UgdmVyc2EpIHdlIGNvdWxkIGp1c3QgZG8gdGhl IFlVVjwtPlJHQiBjb252ZXJzaW9uIGluIHRoZQpkcml2ZXIgZm9yIHRoZSBjb2xvcmtleSB2YWx1 ZSBwcm92aWRlZCBieSB0aGUgdXNlci4gVGhlIGRyaXZlciBpcwppbiB0aGUgYmVzdCBwb3NpdGlv biB0byBrbm93IHRoZSBleGFjdCBZVVY8LT5SR0IgY29udmVyc2lvbiBmb3JtdWxhCnVzZWQgYnkg dGhlIGhhcmR3YXJlIGFueXdheS4KCj4gCj4gQW5kIHByb2JhYmx5IHNvbWVob3cgdXNlcnNwYWNl IHNob3VsZCBiZSBpbmZvcm1lZCBhYm91dCB0aGF0IGNvbG9ya2V5IGZvcm1hdAo+IHNob3VsZCBt YXRjaCB0aGUgZnJhbWVidWZmZXJzIGZvcm1hdCBpZiB0aGF0J3Mgd2hhdCBkcml2ZXIgZXhwZWN0 cy4gTWF5YmUgYQo+IHJlYWQtb25seSBwcm9wZXJ0eT8KPiAKPiA+PiArICoKPiA+PiArICoJRHJp dmVycyByZXR1cm4gYW4gZXJyb3IgZnJvbSB0aGVpciBwbGFuZSBhdG9taWMgY2hlY2sgaWYgcGl4 ZWwgZm9ybWF0Cj4gPj4gKyAqCWlzIHVuc3VwcG9ydGVkLgo+ID4+ICsgKgo+ID4+ICsgKiBjb2xv cmtleS5tYXNrOgo+ID4+ICsgKglUaGlzIHByb3BlcnR5IHNwZWNpZmllcyB0aGUgcGl4ZWwgY29t cG9uZW50cyBtYXNrLiBVbm1hc2tlZCBwaXhlbAo+ID4+ICsgKgljb21wb25lbnRzIGFyZSBub3Qg cGFydGljaXBhdGluZyBpbiB0aGUgbWF0Y2hpbmcuIFRoaXMgbWFzayB2YWx1ZSBpcwo+ID4+ICsg KglhcHBsaWVkIHRvIGNvbG9ya2V5Lm1pbiAvIG1heCB2YWx1ZXMuIFRoZSBtYXNrIHZhbHVlIGlz IGdpdmVuIGluIGEKPiA+PiArICoJZm9ybSBvZiBEUk0gZm91cmNjIGNvZGUgY29ycmVzcG9uZGlu ZyB0byB0aGUgY29sb3JrZXkuZm9ybWF0IHByb3BlcnR5Lgo+ID4+ICsgKgo+ID4+ICsgKglGb3Ig ZXhhbXBsZTogdXNlcnNwYWNlIHNoYWxsIHNldCB0aGUgY29sb3JrZXkubWFzayB0byAweDAwMDBm ZjAwCj4gPj4gKyAqCXRvIG1hdGNoIG9ubHkgdGhlIGdyZWVuIGNvbXBvbmVudCBpZiBjb2xvcmtl eS5mb3JtYXQgaXMgc2V0IHRvCj4gPj4gKyAqCURSTV9GT1JNQVRfWFJHQjg4ODguCj4gPj4gKyAq Cj4gPj4gKyAqCURyaXZlcnMgcmV0dXJuIGFuIGVycm9yIGZyb20gdGhlaXIgcGxhbmUgYXRvbWlj IGNoZWNrIGlmIG1hc2sgdmFsdWUKPiA+PiArICoJY2FuJ3QgYmUgaGFuZGxlZC4KPiA+PiArICoK PiA+PiArICogY29sb3JrZXkuaW52ZXJ0ZWQtbWF0Y2g6Cj4gPj4gKyAqCVRoaXMgcHJvcGVydHkg c3BlY2lmaWVzIHdoZXRoZXIgdGhlIG1hdGNoaW5nIG1pbi1tYXggcmFuZ2Ugc2hvdWxkCj4gPj4g KyAqCWJlIGludmVydGVkLCBpLmUuIHBpeGVscyBvdXRzaWRlIG9mIHRoZSBnaXZlbiBjb2xvciBy YW5nZSBiZWNvbWUKPiA+PiArICoJdGhlIGNvbG9yIGtleSBtYXRjaC4KPiA+PiArICoKPiA+PiAr ICoJRHJpdmVycyByZXR1cm4gYW4gZXJyb3IgZnJvbSB0aGVpciBwbGFuZSBhdG9taWMgY2hlY2sg aWYgaW52ZXJzaW9uCj4gPj4gKyAqCW1vZGUgY2FuJ3QgYmUgaGFuZGxlZC4KPiA+IAo+ID4gSG1t LiBJJ20gdHJ5aW5nIHRvIGZpZ3VyZSBvdXQgd2hhdCB0aGlzIG1lYW5zIGZvciB0aGUgc3JjIHZz LiBkc3QKPiA+IGNvbG9ya2V5IG1vZGVzLiBUaG9zZSBwcmV0dHkgbXVjaCBhbHJlYWR5IGhhdmUg YW4gaW52ZXJ0ZWQgbWVhbmluZyB3aGVuCj4gPiBjb21wYXJlZCB0byBlYWNoIG90aGVyLiBTbyBJ IGNhbid0IGZpZ3VyZSBvdXQgZnJvbSB0aGVzZSBkb2NzIHdoZXRoZXIgCj4gPiB5b3UncmUgc3Vw cG9zZWQgdG8gdXNlIHRoaXMgd2hlbiB5b3Ugd2FudCBhIG5vcm1hbCBkc3QgY2tleSBvciBub3Jt YWwKPiA+IHNyYyBrZXkgc2VtYW50aWNzLgo+ID4gCj4gCj4gSSBhbHNvIGNvdWxkbid0IHVuZGVy c3RhbmQgd2hhdCBpbml0aWFsIHNlbWFudGljIHRvIHNyYy9kc3Qgd2FzIGdpdmVuIGJ5IExhdXJl bnQuCj4gCj4gSW4gYSBjYXNlIG9mIHRoaXMgcGF0Y2g6Cj4gCj4gVGhlIHNyYy9kc3QtbWF0Y2gg c3BlY2lmaWVzIHRoZSAic291cmNlIiBwbGFuZSBmb3Igd2hpY2ggdGhlIGNvbG9yIG1hdGNoaW5n IGlzCj4gcGVyZm9ybWVkLiBTcmMgbWVhbnMgdGhlIHBsYW5lIHRvIHdoaWNoIHRoZSBjb2xvcmtl eSBwcm9wZXJ0aWVzIGFyZSBhcHBsaWVkLiBEc3QKPiBtZWFucyBwbGFuZXMgb3RoZXIgdGhhbiBw bGFuZSBYIHRvIHdoaWNoIHRoZSBjb2xvcmtleSBwcm9wZXJ0aWVzIGFyZSBhcHBsaWVkLCBpbgo+ IHBhcnRpY3VsYXIgdGhlIHBsYW5lcyB0aGF0IGFyZSBaLXBvc2l0aW9uZWQgdW5kZXIgdGhlIHBs YW5lIFguIEhvcGUgdGhhdCdzIG1vcmUKPiBjbGVhciBub3cuCj4gCj4gVGhlIHNyYy1yZXBsYWNl IHBhcnQgc3BlY2lmaWVzIHRoYXQgcGl4ZWxzIG9mIHRoZSBwbGFuZSB0byB3aGljaCB0aGUgY29s b3JrZXkKPiBwcm9wZXJ0aWVzIGFyZSBhcHBsaWVkIHdpbGwgYmUgcmVwbGFjZWQuCj4gCj4gSSds bCB0cnkgdG8gcmUtd29yayB0aGUgZG9jIGlmIHRoZSBhYm92ZSBzb3VuZHMgZ29vZC4KPiAKPiBU aGUgaW52ZXJ0ZWQtbWF0Y2ggcHJvcGVydHkgY29udHJvbHMgd2hldGhlciBnaXZlbiBjb2xvci1t YXRjaCByYW5nZSBzaGFsbCBiZQo+IGludmVydGVkLCBsaWtlIGZvciBleGFtcGxlOiBpZiBnaXZl biBjb2xvciBrZXkgaXMgYSByZWQgY29sb3IsIHRoZW4gYWxsIGNvbG9ycwo+IGV4cGVjdCB0aGUg cmVkIHdpbGwgYmUgbWF0Y2hlZCBhcyBhIGNvbG9yIGtleS4KPiAKPiBBY3R1YWxseSBtYXliZSBp bnZlcnNpb24gY291bGQgYmUgZXhwcmVzc2VkIHVzaW5nIHRoZSBtYXNrIHNvbGVseS4gTGlrZSB3 ZSBjb3VsZAo+IGFkZCBhIGhlbHBlciB0aGF0IGNvbnZlcnRzICJ2YWx1ZSttYXNrIiBpbnRvICJ2 YWx1ZT0odmFsdWUgJiB+bWFzayksCj4gaW52ZXJzaW9uPXRydWUiIGlmIG1hc2sgaGFzIGZvcm0g b2YgMHgxMTAwMDExMSwgdGhvdWdoIHRoaXMgY291bGQgYmUgbm90Cj4gYXBwbGljYWJsZSB0byBh bGwgcG9zc2libGUgcGl4ZWwgZm9ybWF0cy4uIG5vdCBzdXJlLgo+IAo+ID4+ICsgKgo+ID4+ICsg KiBjb2xvcmtleS5yZXBsYWNlbWVudC12YWx1ZToKPiA+PiArICoJVGhpcyBwcm9wZXJ0eSBzcGVj aWZpZXMgdGhlIGNvbG9yIHZhbHVlIHRoYXQgcmVwbGFjZXMgcGl4ZWxzIG1hdGNoaW5nCj4gPj4g KyAqCXRoZSBjb2xvciBrZXkuIFRoZSB2YWx1ZSBpcyBleHByZXNzZWQgaW4gQVhZWjE2MTYxNjE2 IGZvcm1hdCwgd2hlcmUgQQo+ID4+ICsgKglpcyB0aGUgYWxwaGEgdmFsdWUgYW5kIFgsIFkgYW5k IFogY29ycmVzcG9uZCB0byB0aGUgY29sb3IgY29tcG9uZW50cwo+ID4+ICsgKglvZiB0aGUgY29s b3JrZXkucmVwbGFjZW1lbnQtZm9ybWF0Lgo+ID4+ICsgKgo+ID4+ICsgKglEcml2ZXJzIHJldHVy biBhbiBlcnJvciBmcm9tIHRoZWlyIHBsYW5lIGF0b21pYyBjaGVjayBpZiByZXBsYWNlbWVudAo+ ID4+ICsgKgl2YWx1ZSBjYW4ndCBiZSBoYW5kbGVkLgo+ID4+ICsgKgo+ID4+ICsgKiBjb2xvcmtl eS5yZXBsYWNlbWVudC1mb3JtYXQ6Cj4gPj4gKyAqCVRoaXMgcHJvcGVydHkgc3BlY2lmaWVzIHRo ZSBwaXhlbCBmb3JtYXQgZm9yIHRoZQo+ID4+ICsgKgljb2xvcmtleS5yZXBsYWNlbWVudC12YWx1 ZSBwcm9wZXJ0eS4gVGhlIGZvcm1hdCBpcyBnaXZlbiBpbiBhIGZvcm0gb2YKPiA+PiArICoJRFJN IGZvdXJjYyBjb2RlLgo+ID4gCj4gPiBBZ2FpbiB0aGlzIHNlZW1zIGF0IG9kZHMgd2l0aCB0aGUg MTZicGMgcmVwbGFjZW1lbnQtdmFsdWUuCj4gPiAKPiA+PiArICoKPiA+PiArICoJRHJpdmVycyBy ZXR1cm4gYW4gZXJyb3IgZnJvbSB0aGVpciBwbGFuZSBhdG9taWMgY2hlY2sgaWYgcmVwbGFjZW1l bnQKPiA+PiArICoJcGl4ZWwgZm9ybWF0IGlzIHVuc3VwcG9ydGVkLgo+ID4+ICsgKgo+ID4+ICsg KiBjb2xvcmtleS5yZXBsYWNlbWVudC1tYXNrOgo+ID4+ICsgKglUaGlzIHByb3BlcnR5IHNwZWNp ZmllcyB0aGUgcGl4ZWwgY29tcG9uZW50cyBtYXNrIHRoYXQgZGVmaW5lcwo+ID4+ICsgKgl3aGF0 IGNvbXBvbmVudHMgb2YgdGhlIGNvbG9ya2V5LnJlcGxhY2VtZW50LXZhbHVlIHdpbGwgcGFydGlj aXBhdGUgaW4KPiA+PiArICoJcmVwbGFjZW1lbnQgb2YgdGhlIHBpeGVscyBjb2xvci4gVW5tYXNr ZWQgcGl4ZWwgY29tcG9uZW50cyBhcmUgbm90Cj4gPj4gKyAqCXBhcnRpY2lwYXRpbmcgaW4gdGhl IHJlcGxhY2VtZW50Lgo+ID4gCj4gPiBEb2VzIHRoYXQgbWVhbiB0aGF0IHRoZSBkYXRhIGZvciB0 aGUgdW5tYXNrZWQgYml0cyB3aWxsIGJlIGNvbWluZwo+ID4gZnJvbSB0aGUgc291cmNlPwo+ID4g Cj4gCj4gWWVhaCwgSSBzZWUgdGhhdCAic291cmNlIiBpcyB2YWd1ZWx5IGRlZmluZWQuCj4gCj4g WWVzLCB0aGUgdW5tYXNrZWQgYml0cyBhcmUgY29taW5nIGZyb20gdGhlIHNvdXJjZS4gVGhlICJz b3VyY2UiIGlzIGRlZmluZWQgYnkKPiB0aGUgbW9kZS4KPiAKPiBzcmMtbWF0Y2gtIC0tPlNSQzwt LSAtcmVwbGFjZQo+IGRzdC1tYXRjaC0gLS0+U1JDPC0tIC1yZXBsYWNlCj4gCj4gU3JjIG1lYW5z IHRoZSBwbGFuZSB0byB3aGljaCB0aGUgY29sb3JrZXkgcHJvcGVydGllcyBhcmUgYXBwbGllZCwg YXMgSSBzdGF0ZWQgYWJvdmUuCj4gCj4gPj4gVGhlIG1hc2sgdmFsdWUgaXMgZ2l2ZW4gaW4gYSBm b3JtIG9mCj4gPj4gKyAqCURSTSBmb3VyY2MgY29kZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBjb2xv cmtleS5yZXBsYWNlbWVudC1mb3JtYXQKPiA+PiArICoJcHJvcGVydHkuCj4gPj4gKyAqCj4gPj4g KyAqCUZvciBleGFtcGxlOiB1c2Vyc3BhY2Ugc2hhbGwgc2V0IHRoZSBjb2xvcmtleS5yZXBsYWNl bWVudC1tYXNrIHRvCj4gPj4gKyAqCTB4MDAwMGZmMDAgdG8gcmVwbGFjZSBvbmx5IHRoZSBncmVl biBjb21wb25lbnQgaWYKPiA+PiArICoJY29sb3JrZXkucmVwbGFjZW1lbnQtZm9ybWF0IGlzIHNl dCB0byBEUk1fRk9STUFUX1hSR0I4ODg4Lgo+ID4+ICsgKgo+ID4+ICsgKglVc2Vyc3BhY2Ugc2hh bGwgc2V0IGNvbG9ya2V5LnJlcGxhY2VtZW50LW1hc2sgdG8gMCB0byBkaXNhYmxlIHRoZSBjb2xv cgo+ID4+ICsgKglyZXBsYWNlbWVudC4gSW4gdGhpcyBjYXNlIG1hdGNoaW5nIHBpeGVscyBiZWNv bWUgdHJhbnNwYXJlbnQuCj4gPj4gKyAqCj4gPj4gKyAqCURyaXZlcnMgcmV0dXJuIGFuIGVycm9y IGZyb20gdGhlaXIgcGxhbmUgYXRvbWljIGNoZWNrIGlmIHJlcGxhY2VtZW50Cj4gPj4gKyAqCW1h c2sgdmFsdWUgY2FuJ3QgYmUgaGFuZGxlZC4KPiA+PiArICoKPiA+PiArICogUmV0dXJuczoKPiA+ PiArICogWmVybyBvbiBzdWNjZXNzLCBuZWdhdGl2ZSBlcnJubyBvbiBmYWlsdXJlLgo+ID4+ICsg Ki8KPiA+PiAraW50IGRybV9wbGFuZV9jcmVhdGVfY29sb3JrZXlfcHJvcGVydGllcyhzdHJ1Y3Qg ZHJtX3BsYW5lICpwbGFuZSwKPiA+PiArCQkJCQkgdTMyIHN1cHBvcnRlZF9tb2RlcykKPiA+PiAr ewo+ID4+ICsJc3RydWN0IGRybV9wcm9wX2VudW1fbGlzdCBtb2Rlc19saXN0W0RSTV9QTEFORV9D T0xPUktFWV9NT0RFU19OVU1dOwo+ID4+ICsJc3RydWN0IGRybV9wcm9wZXJ0eSAqcmVwbGFjZW1l bnRfZm9ybWF0X3Byb3A7Cj4gPj4gKwlzdHJ1Y3QgZHJtX3Byb3BlcnR5ICpyZXBsYWNlbWVudF92 YWx1ZV9wcm9wOwo+ID4+ICsJc3RydWN0IGRybV9wcm9wZXJ0eSAqcmVwbGFjZW1lbnRfbWFza19w cm9wOwo+ID4+ICsJc3RydWN0IGRybV9wcm9wZXJ0eSAqaW52ZXJ0ZWRfbWF0Y2hfcHJvcDsKPiA+ PiArCXN0cnVjdCBkcm1fcHJvcGVydHkgKmZvcm1hdF9wcm9wOwo+ID4+ICsJc3RydWN0IGRybV9w cm9wZXJ0eSAqbWFza19wcm9wOwo+ID4+ICsJc3RydWN0IGRybV9wcm9wZXJ0eSAqbW9kZV9wcm9w Owo+ID4+ICsJc3RydWN0IGRybV9wcm9wZXJ0eSAqbWluX3Byb3A7Cj4gPj4gKwlzdHJ1Y3QgZHJt X3Byb3BlcnR5ICptYXhfcHJvcDsKPiA+PiArCXVuc2lnbmVkIGludCBtb2Rlc19udW0gPSAwOwo+ ID4+ICsJdW5zaWduZWQgaW50IGk7Cj4gPj4gKwo+ID4+ICsJLyogYXQgbGVhc3QgdHdvIG1vZGVz IHNob3VsZCBiZSBzdXBwb3J0ZWQgKi8KPiA+PiArCWlmICghc3VwcG9ydGVkX21vZGVzKQo+ID4+ ICsJCXJldHVybiAtRUlOVkFMOwo+ID4+ICsKPiA+PiArCS8qIG1vZGVzIGFyZSBkcml2ZXItc3Bl Y2lmaWMsIGJ1aWxkIHRoZSBsaXN0IG9mIHN1cHBvcnRlZCBtb2RlcyAqLwo+ID4+ICsJZm9yIChp ID0gMDsgaSA8IERSTV9QTEFORV9DT0xPUktFWV9NT0RFU19OVU07IGkrKykgewo+ID4+ICsJCWlm ICghKHN1cHBvcnRlZF9tb2RlcyAmIEJJVChpKSkpCj4gPj4gKwkJCWNvbnRpbnVlOwo+ID4+ICsK PiA+PiArCQltb2Rlc19saXN0W21vZGVzX251bV0ubmFtZSA9IHBsYW5lX2NvbG9ya2V5X21vZGVf bmFtZVtpXTsKPiA+PiArCQltb2Rlc19saXN0W21vZGVzX251bV0udHlwZSA9IGk7Cj4gPj4gKwkJ bW9kZXNfbnVtKys7Cj4gPj4gKwl9Cj4gPj4gKwo+ID4+ICsJbW9kZV9wcm9wID0gZHJtX3Byb3Bl cnR5X2NyZWF0ZV9lbnVtKHBsYW5lLT5kZXYsIDAsICJjb2xvcmtleS5tb2RlIiwKPiA+PiArCQkJ CQkgICAgIG1vZGVzX2xpc3QsIG1vZGVzX251bSk7Cj4gPj4gKwlpZiAoIW1vZGVfcHJvcCkKPiA+ PiArCQlyZXR1cm4gLUVOT01FTTsKPiA+PiArCj4gPj4gKwltYXNrX3Byb3AgPSBkcm1fcHJvcGVy dHlfY3JlYXRlX3JhbmdlKHBsYW5lLT5kZXYsIDAsICJjb2xvcmtleS5tYXNrIiwKPiA+PiArCQkJ CQkgICAgICAwLCBVNjRfTUFYKTsKPiA+PiArCWlmICghbWFza19wcm9wKQo+ID4+ICsJCWdvdG8g ZXJyX2Rlc3Ryb3lfbW9kZV9wcm9wOwo+ID4+ICsKPiA+PiArCW1pbl9wcm9wID0gZHJtX3Byb3Bl cnR5X2NyZWF0ZV9yYW5nZShwbGFuZS0+ZGV2LCAwLCAiY29sb3JrZXkubWluIiwKPiA+PiArCQkJ CQkgICAgIDAsIFU2NF9NQVgpOwo+ID4+ICsJaWYgKCFtaW5fcHJvcCkKPiA+PiArCQlnb3RvIGVy cl9kZXN0cm95X21hc2tfcHJvcDsKPiA+PiArCj4gPj4gKwltYXhfcHJvcCA9IGRybV9wcm9wZXJ0 eV9jcmVhdGVfcmFuZ2UocGxhbmUtPmRldiwgMCwgImNvbG9ya2V5Lm1heCIsCj4gPj4gKwkJCQkJ ICAgICAwLCBVNjRfTUFYKTsKPiA+PiArCWlmICghbWF4X3Byb3ApCj4gPj4gKwkJZ290byBlcnJf ZGVzdHJveV9taW5fcHJvcDsKPiA+PiArCj4gPj4gKwlmb3JtYXRfcHJvcCA9IGRybV9wcm9wZXJ0 eV9jcmVhdGVfcmFuZ2UocGxhbmUtPmRldiwgMCwKPiA+PiArCQkJCQkiY29sb3JrZXkuZm9ybWF0 IiwKPiA+PiArCQkJCQkwLCBVMzJfTUFYKTsKPiA+PiArCWlmICghZm9ybWF0X3Byb3ApCj4gPj4g KwkJZ290byBlcnJfZGVzdHJveV9tYXhfcHJvcDsKPiA+PiArCj4gPj4gKwlpbnZlcnRlZF9tYXRj aF9wcm9wID0gZHJtX3Byb3BlcnR5X2NyZWF0ZV9ib29sKHBsYW5lLT5kZXYsIDAsCj4gPj4gKwkJ CQkJImNvbG9ya2V5LmludmVydGVkLW1hdGNoIik7Cj4gPj4gKwlpZiAoIWludmVydGVkX21hdGNo X3Byb3ApCj4gPj4gKwkJZ290byBlcnJfZGVzdHJveV9mb3JtYXRfcHJvcDsKPiA+PiArCj4gPj4g KwlyZXBsYWNlbWVudF9tYXNrX3Byb3AgPSBkcm1fcHJvcGVydHlfY3JlYXRlX3JhbmdlKHBsYW5l LT5kZXYsIDAsCj4gPj4gKwkJCQkJImNvbG9ya2V5LnJlcGxhY2VtZW50LW1hc2siLAo+ID4+ICsJ CQkJCTAsIFU2NF9NQVgpOwo+ID4+ICsJaWYgKCFyZXBsYWNlbWVudF9tYXNrX3Byb3ApCj4gPj4g KwkJZ290byBlcnJfZGVzdHJveV9pbnZlcnRlZF9tYXRjaF9wcm9wOwo+ID4+ICsKPiA+PiArCXJl cGxhY2VtZW50X3ZhbHVlX3Byb3AgPSBkcm1fcHJvcGVydHlfY3JlYXRlX3JhbmdlKHBsYW5lLT5k ZXYsIDAsCj4gPj4gKwkJCQkJImNvbG9ya2V5LnJlcGxhY2VtZW50LXZhbHVlIiwKPiA+PiArCQkJ CQkwLCBVNjRfTUFYKTsKPiA+PiArCWlmICghcmVwbGFjZW1lbnRfdmFsdWVfcHJvcCkKPiA+PiAr CQlnb3RvIGVycl9kZXN0cm95X3JlcGxhY2VtZW50X21hc2tfcHJvcDsKPiA+PiArCj4gPj4gKwly ZXBsYWNlbWVudF9mb3JtYXRfcHJvcCA9IGRybV9wcm9wZXJ0eV9jcmVhdGVfcmFuZ2UocGxhbmUt PmRldiwgMCwKPiA+PiArCQkJCQkiY29sb3JrZXkucmVwbGFjZW1lbnQtZm9ybWF0IiwKPiA+PiAr CQkJCQkwLCBVNjRfTUFYKTsKPiA+PiArCWlmICghcmVwbGFjZW1lbnRfZm9ybWF0X3Byb3ApCj4g Pj4gKwkJZ290byBlcnJfZGVzdHJveV9yZXBsYWNlbWVudF92YWx1ZV9wcm9wOwo+ID4gCj4gPiBJ IGRvbid0IHRoaW5rIHdlIHdhbnQgdG8gYWRkIGFsbCB0aGVzZSBwcm9wcyBmb3IgZXZlcnkgZHJp dmVyL2hhcmR3YXJlLgo+ID4gSU1PIHRoZSBzZXQgb2YgcHJvcHMgd2UgZXhwb3NlIHNob3VsZCBk ZXBlbmQgb24gdGhlIHN1cHBvcnRlZCBzZXQgb2YKPiA+IGNvbG9ya2V5aW5nIG1vZGVzLgo+ID4g Cj4gCj4gUHJvYmFibHksIEkgZG9uJ3QgbWluZC4gVGhpcyBzaG91bGQgYmUgZG9jdW1lbnRlZCB0 aGVuLCBJIGNhbiBhZGRyZXNzIHRoYXQgaW4KPiB0aGUgbmV4dCBpdGVyYXRpb24uCj4gCj4gL0kg dGhpbmsvIGFsbCBvZiB0aGUgY3VycmVudGx5LWRlZmluZWQgcHJvcGVydGllcyBhcmUgcmVsZXZh bnQgdG8gdGhlIGRlZmluZWQKPiBjb2xvciBrZXlpbmcgbW9kZXMuCgppOTE1IHdpbGwgd2FudCBq dXN0IHZhbHVlL21hc2sgb3IgbWluL21heCwgZGVwZW5kaW5nIG9uIHdoZXRoZXIgd2UncmUKZGVh bGluZyB3aXRoIHJnYiBvciB5dXYuIEFuZCBJJ3ZlIHNlZW4gYSBsb3Qgb2YgaGFyZHdhcmUgd2l0 aCBqdXN0IHRoZQp2YWx1ZS9tYXNrIGFwcHJvYWNoIG92ZXIgdGhlIHllYXJzLgoKPiBMYXRlciwg aWYgdGhlIGxpc3Qgb2YgbW9kZXMgd2lsbCBiZSBleHRlbmRlZCB3aXRoIG5ldyBtb2RlcywKPiB0 aGUgY3JlYXRpb24gb2YgcHJvcGVydGllcyBjb3VsZCBiZSBjb25kaXRpb25hbGl6ZWQuCj4gCj4g VGhvdWdoIG1heWJlICJjb2xvciBjb21wb25lbnRzIHJlcGxhY2VtZW50IiBhbmQgInJlcGxhY2Vt ZW50IHdpdGggYSBjb21wbGV0ZQo+IHRyYW5zcGFyZW5jeSIgY291bGQgYmUgZmFjdG9yZWQgb3V0 IGludG8gYSBzcGVjaWZpYyBjb2xvciBrZXlpbmcgbW9kZXMuCgpZZXMuIEkndmUgbmV2ZXIgc2Vl biB0aG9zZSBpbiBhbnkgaGFyZHdhcmUuIEluIGZhY3QgSSdtIHdvbmRlcmluZyB3aGVyZQppcyB0 aGUgdXNlcnNwYWNlIGZvciBhbGwgdGhlc2UgY29tcGxleCBtb2Rlcz8gSWUuIHNob3VsZCB3ZSBl dmVuIGJvdGhlcgp3aXRoIHRoZW0gYXQgdGhpcyB0aW1lPwoKLS0gClZpbGxlIFN5cmrDpGzDpApJ bnRlbApfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkcmkt ZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6 Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWwK From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mga04.intel.com ([192.55.52.120]:42696 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751444AbeE2HLK (ORCPT ); Tue, 29 May 2018 03:11:10 -0400 Date: Tue, 29 May 2018 10:11:03 +0300 From: Ville =?iso-8859-1?Q?Syrj=E4l=E4?= To: Dmitry Osipenko Cc: Laurent Pinchart , Thierry Reding , Neil Armstrong , Maxime Ripard , dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Alexandru Gheorghe , Russell King , Ben Skeggs , Sinclair Yeh , Thomas Hellstrom , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [RFC PATCH v2 1/2] drm: Add generic colorkey properties Message-ID: <20180529071103.GL23723@intel.com> References: <20180526155623.12610-1-digetx@gmail.com> <20180526155623.12610-2-digetx@gmail.com> <20180528131501.GK23723@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Sender: linux-media-owner@vger.kernel.org List-ID: On Tue, May 29, 2018 at 02:48:22AM +0300, Dmitry Osipenko wrote: > On 28.05.2018 16:15, Ville Syrjälä wrote: > > On Sat, May 26, 2018 at 06:56:22PM +0300, Dmitry Osipenko wrote: > >> Color keying is the action of replacing pixels matching a given color > >> (or range of colors) with transparent pixels in an overlay when > >> performing blitting. Depending on the hardware capabilities, the > >> matching pixel can either become fully transparent or gain adjustment > >> of the pixels component values. > >> > >> Color keying is found in a large number of devices whose capabilities > >> often differ, but they still have enough common features in range to > >> standardize color key properties. This commit adds nine generic DRM plane > >> properties related to the color keying to cover various HW capabilities. > >> > >> This patch is based on the initial work done by Laurent Pinchart, most of > >> credits for this patch goes to him. > >> > >> Signed-off-by: Dmitry Osipenko > >> --- > >> drivers/gpu/drm/drm_atomic.c | 36 ++++++ > >> drivers/gpu/drm/drm_blend.c | 229 +++++++++++++++++++++++++++++++++++ > >> include/drm/drm_blend.h | 3 + > >> include/drm/drm_plane.h | 77 ++++++++++++ > >> 4 files changed, 345 insertions(+) > >> > >> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c > >> index 895741e9cd7d..5b808cb68654 100644 > >> --- a/drivers/gpu/drm/drm_atomic.c > >> +++ b/drivers/gpu/drm/drm_atomic.c > >> @@ -799,6 +799,24 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, > >> state->rotation = val; > >> } else if (property == plane->zpos_property) { > >> state->zpos = val; > >> + } else if (property == plane->colorkey.mode_property) { > >> + state->colorkey.mode = val; > >> + } else if (property == plane->colorkey.min_property) { > >> + state->colorkey.min = val; > >> + } else if (property == plane->colorkey.max_property) { > >> + state->colorkey.max = val; > >> + } else if (property == plane->colorkey.format_property) { > >> + state->colorkey.format = val; > >> + } else if (property == plane->colorkey.mask_property) { > >> + state->colorkey.mask = val; > >> + } else if (property == plane->colorkey.inverted_match_property) { > >> + state->colorkey.inverted_match = val; > >> + } else if (property == plane->colorkey.replacement_mask_property) { > >> + state->colorkey.replacement_mask = val; > >> + } else if (property == plane->colorkey.replacement_value_property) { > >> + state->colorkey.replacement_value = val; > >> + } else if (property == plane->colorkey.replacement_format_property) { > >> + state->colorkey.replacement_format = val; > >> } else if (property == plane->color_encoding_property) { > >> state->color_encoding = val; > >> } else if (property == plane->color_range_property) { > >> @@ -864,6 +882,24 @@ drm_atomic_plane_get_property(struct drm_plane *plane, > >> *val = state->rotation; > >> } else if (property == plane->zpos_property) { > >> *val = state->zpos; > >> + } else if (property == plane->colorkey.mode_property) { > >> + *val = state->colorkey.mode; > >> + } else if (property == plane->colorkey.min_property) { > >> + *val = state->colorkey.min; > >> + } else if (property == plane->colorkey.max_property) { > >> + *val = state->colorkey.max; > >> + } else if (property == plane->colorkey.format_property) { > >> + *val = state->colorkey.format; > >> + } else if (property == plane->colorkey.mask_property) { > >> + *val = state->colorkey.mask; > >> + } else if (property == plane->colorkey.inverted_match_property) { > >> + *val = state->colorkey.inverted_match; > >> + } else if (property == plane->colorkey.replacement_mask_property) { > >> + *val = state->colorkey.replacement_mask; > >> + } else if (property == plane->colorkey.replacement_value_property) { > >> + *val = state->colorkey.replacement_value; > >> + } else if (property == plane->colorkey.replacement_format_property) { > >> + *val = state->colorkey.replacement_format; > >> } else if (property == plane->color_encoding_property) { > >> *val = state->color_encoding; > >> } else if (property == plane->color_range_property) { > >> diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c > >> index a16a74d7e15e..05e5632ce375 100644 > >> --- a/drivers/gpu/drm/drm_blend.c > >> +++ b/drivers/gpu/drm/drm_blend.c > >> @@ -107,6 +107,11 @@ > >> * planes. Without this property the primary plane is always below the cursor > >> * plane, and ordering between all other planes is undefined. > >> * > >> + * colorkey: > >> + * Color keying is set up with drm_plane_create_colorkey_properties(). > >> + * It adds support for replacing a range of colors with a transparent > >> + * color in the plane. > >> + * > >> * 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). > >> @@ -448,3 +453,227 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, > >> return 0; > >> } > >> EXPORT_SYMBOL(drm_atomic_normalize_zpos); > >> + > >> +static const char * const plane_colorkey_mode_name[] = { > >> + [DRM_PLANE_COLORKEY_MODE_DISABLED] = "disabled", > >> + [DRM_PLANE_COLORKEY_MODE_SRC] = "src-match-src-replace", > >> + [DRM_PLANE_COLORKEY_MODE_DST] = "dst-match-src-replace", > > > > This list seems way more limited than I was expecting, at least when > > compared to all the different props you're proposing to add. > > > > What else are you expecting to see in the list? Prerry much all kinds of modes for the funky replacement values and whanot. > > >> +}; > >> + > >> +/** > >> + * drm_plane_create_colorkey_properties - create colorkey properties > >> + * @plane: drm plane > >> + * @supported_modes: bitmask of supported color keying modes > >> + * > >> + * This function creates the generic color keying properties and attach them to > >> + * the plane to enable color keying control for blending operations. > >> + * > >> + * Color keying is controlled through nine properties: > >> + * > >> + * colorkey.mode: > >> + * The mode is an enumerated property that controls how color keying > >> + * operates. The "disabled" mode that disables color keying and is > >> + * very likely to exist if color keying is supported, it should be the > >> + * default mode. > >> + * > >> + * colorkey.min, colorkey.max: > >> + * These two properties specify the colors that are treated as the color > >> + * key. Pixel whose value is in the [min, max] range is the color key > >> + * matching pixel. The minimum and maximum values are expressed as a > >> + * 64-bit integer in AXYZ16161616 format, where A is the alpha value and > >> + * X, Y and Z correspond to the color components of the colorkey.format. > >> + * In most cases XYZ will be either RGB or YUV. > >> + * > >> + * When a single color key is desired instead of a range, userspace shall > >> + * set the min and max properties to the same value. > >> + * > >> + * Drivers return an error from their plane atomic check if range can't be > >> + * handled. > >> + * > >> + * colorkey.format: > >> + * This property specifies the pixel format for the colorkey.min / max > >> + * properties. The format is given in a form of DRM fourcc code. > > > > Umm. Why we do even need this? This seems incompatible with your earlier > > "min/max are specified in 16bpc format" statement. > > > > AXYZ16161616 is just an abstraction of a pixel format, at least that's how I'm > interpreting the AXYZ16161616. > > Previously Laurent specified that min/max values should be given in the format > of the planes framebuffer. This doesn't work for a case of setting property for > a disabled plane because disabled plane doesn't have a framebuffer. This also > doesn't work for Tegra that can take only XRGB8888 format for a color key, AFAIK > HW internally converts all pixel formats to ARGB8888 and RGB part participates > in the color matching (later Tegra's support alpha channel matching as well). > Hence I added the format property that explicitly tells in what format the color > key integer value is given. > > I'm now thinking that format property should be exposed to userspace in a form > of a ENUM-list, because otherwise userspace doesn't know what color key formats > are supported by the DRM driver. I'm not sure that'll help particularly much. Generally you can't choose the format anyway, and it may just depends on the fb format or some other related factors. So not really sure how much benefit such an enum would have. And for hw where eg. the colorkey is always RGB even for YUV data (or vice versa) we could just do the YUV<->RGB conversion in the driver for the colorkey value provided by the user. The driver is in the best position to know the exact YUV<->RGB conversion formula used by the hardware anyway. > > And probably somehow userspace should be informed about that colorkey format > should match the framebuffers format if that's what driver expects. Maybe a > read-only property? > > >> + * > >> + * Drivers return an error from their plane atomic check if pixel format > >> + * is unsupported. > >> + * > >> + * colorkey.mask: > >> + * This property specifies the pixel components mask. Unmasked pixel > >> + * components are not participating in the matching. This mask value is > >> + * applied to colorkey.min / max values. The mask value is given in a > >> + * form of DRM fourcc code corresponding to the colorkey.format property. > >> + * > >> + * For example: userspace shall set the colorkey.mask to 0x0000ff00 > >> + * to match only the green component if colorkey.format is set to > >> + * DRM_FORMAT_XRGB8888. > >> + * > >> + * Drivers return an error from their plane atomic check if mask value > >> + * can't be handled. > >> + * > >> + * colorkey.inverted-match: > >> + * This property specifies whether the matching min-max range should > >> + * be inverted, i.e. pixels outside of the given color range become > >> + * the color key match. > >> + * > >> + * Drivers return an error from their plane atomic check if inversion > >> + * mode can't be handled. > > > > Hmm. I'm trying to figure out what this means for the src vs. dst > > colorkey modes. Those pretty much already have an inverted meaning when > > compared to each other. So I can't figure out from these docs whether > > you're supposed to use this when you want a normal dst ckey or normal > > src key semantics. > > > > I also couldn't understand what initial semantic to src/dst was given by Laurent. > > In a case of this patch: > > The src/dst-match specifies the "source" plane for which the color matching is > performed. Src means the plane to which the colorkey properties are applied. Dst > means planes other than plane X to which the colorkey properties are applied, in > particular the planes that are Z-positioned under the plane X. Hope that's more > clear now. > > The src-replace part specifies that pixels of the plane to which the colorkey > properties are applied will be replaced. > > I'll try to re-work the doc if the above sounds good. > > The inverted-match property controls whether given color-match range shall be > inverted, like for example: if given color key is a red color, then all colors > expect the red will be matched as a color key. > > Actually maybe inversion could be expressed using the mask solely. Like we could > add a helper that converts "value+mask" into "value=(value & ~mask), > inversion=true" if mask has form of 0x11000111, though this could be not > applicable to all possible pixel formats.. not sure. > > >> + * > >> + * colorkey.replacement-value: > >> + * This property specifies the color value that replaces pixels matching > >> + * the color key. The value is expressed in AXYZ16161616 format, where A > >> + * is the alpha value and X, Y and Z correspond to the color components > >> + * of the colorkey.replacement-format. > >> + * > >> + * Drivers return an error from their plane atomic check if replacement > >> + * value can't be handled. > >> + * > >> + * colorkey.replacement-format: > >> + * This property specifies the pixel format for the > >> + * colorkey.replacement-value property. The format is given in a form of > >> + * DRM fourcc code. > > > > Again this seems at odds with the 16bpc replacement-value. > > > >> + * > >> + * Drivers return an error from their plane atomic check if replacement > >> + * pixel format is unsupported. > >> + * > >> + * colorkey.replacement-mask: > >> + * This property specifies the pixel components mask that defines > >> + * what components of the colorkey.replacement-value will participate in > >> + * replacement of the pixels color. Unmasked pixel components are not > >> + * participating in the replacement. > > > > Does that mean that the data for the unmasked bits will be coming > > from the source? > > > > Yeah, I see that "source" is vaguely defined. > > Yes, the unmasked bits are coming from the source. The "source" is defined by > the mode. > > src-match- -->SRC<-- -replace > dst-match- -->SRC<-- -replace > > Src means the plane to which the colorkey properties are applied, as I stated above. > > >> The mask value is given in a form of > >> + * DRM fourcc code corresponding to the colorkey.replacement-format > >> + * property. > >> + * > >> + * For example: userspace shall set the colorkey.replacement-mask to > >> + * 0x0000ff00 to replace only the green component if > >> + * colorkey.replacement-format is set to DRM_FORMAT_XRGB8888. > >> + * > >> + * Userspace shall set colorkey.replacement-mask to 0 to disable the color > >> + * replacement. In this case matching pixels become transparent. > >> + * > >> + * Drivers return an error from their plane atomic check if replacement > >> + * mask value can't be handled. > >> + * > >> + * Returns: > >> + * Zero on success, negative errno on failure. > >> + */ > >> +int drm_plane_create_colorkey_properties(struct drm_plane *plane, > >> + u32 supported_modes) > >> +{ > >> + struct drm_prop_enum_list modes_list[DRM_PLANE_COLORKEY_MODES_NUM]; > >> + struct drm_property *replacement_format_prop; > >> + struct drm_property *replacement_value_prop; > >> + struct drm_property *replacement_mask_prop; > >> + struct drm_property *inverted_match_prop; > >> + struct drm_property *format_prop; > >> + struct drm_property *mask_prop; > >> + struct drm_property *mode_prop; > >> + struct drm_property *min_prop; > >> + struct drm_property *max_prop; > >> + unsigned int modes_num = 0; > >> + unsigned int i; > >> + > >> + /* at least two modes should be supported */ > >> + if (!supported_modes) > >> + return -EINVAL; > >> + > >> + /* modes are driver-specific, build the list of supported modes */ > >> + for (i = 0; i < DRM_PLANE_COLORKEY_MODES_NUM; i++) { > >> + if (!(supported_modes & BIT(i))) > >> + continue; > >> + > >> + modes_list[modes_num].name = plane_colorkey_mode_name[i]; > >> + modes_list[modes_num].type = i; > >> + modes_num++; > >> + } > >> + > >> + mode_prop = drm_property_create_enum(plane->dev, 0, "colorkey.mode", > >> + modes_list, modes_num); > >> + if (!mode_prop) > >> + return -ENOMEM; > >> + > >> + mask_prop = drm_property_create_range(plane->dev, 0, "colorkey.mask", > >> + 0, U64_MAX); > >> + if (!mask_prop) > >> + goto err_destroy_mode_prop; > >> + > >> + min_prop = drm_property_create_range(plane->dev, 0, "colorkey.min", > >> + 0, U64_MAX); > >> + if (!min_prop) > >> + goto err_destroy_mask_prop; > >> + > >> + max_prop = drm_property_create_range(plane->dev, 0, "colorkey.max", > >> + 0, U64_MAX); > >> + if (!max_prop) > >> + goto err_destroy_min_prop; > >> + > >> + format_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.format", > >> + 0, U32_MAX); > >> + if (!format_prop) > >> + goto err_destroy_max_prop; > >> + > >> + inverted_match_prop = drm_property_create_bool(plane->dev, 0, > >> + "colorkey.inverted-match"); > >> + if (!inverted_match_prop) > >> + goto err_destroy_format_prop; > >> + > >> + replacement_mask_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.replacement-mask", > >> + 0, U64_MAX); > >> + if (!replacement_mask_prop) > >> + goto err_destroy_inverted_match_prop; > >> + > >> + replacement_value_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.replacement-value", > >> + 0, U64_MAX); > >> + if (!replacement_value_prop) > >> + goto err_destroy_replacement_mask_prop; > >> + > >> + replacement_format_prop = drm_property_create_range(plane->dev, 0, > >> + "colorkey.replacement-format", > >> + 0, U64_MAX); > >> + if (!replacement_format_prop) > >> + goto err_destroy_replacement_value_prop; > > > > I don't think we want to add all these props for every driver/hardware. > > IMO the set of props we expose should depend on the supported set of > > colorkeying modes. > > > > Probably, I don't mind. This should be documented then, I can address that in > the next iteration. > > /I think/ all of the currently-defined properties are relevant to the defined > color keying modes. i915 will want just value/mask or min/max, depending on whether we're dealing with rgb or yuv. And I've seen a lot of hardware with just the value/mask approach over the years. > Later, if the list of modes will be extended with new modes, > the creation of properties could be conditionalized. > > Though maybe "color components replacement" and "replacement with a complete > transparency" could be factored out into a specific color keying modes. Yes. I've never seen those in any hardware. In fact I'm wondering where is the userspace for all these complex modes? Ie. should we even bother with them at this time? -- Ville Syrjälä Intel