Skip to content

Commit 6fdaed8

Browse files
marcanThomas Zimmermann
authored andcommitted
drm/format-helper: Only advertise supported formats for conversion
drm_fb_build_fourcc_list() currently returns all emulated formats unconditionally as long as the native format is among them, even though not all combinations have conversion helpers. Although the list is arguably provided to userspace in precedence order, userspace can pick something out-of-order (and thus break when it shouldn't), or simply only support a format that is unsupported (and thus think it can work, which results in the appearance of a hang as FB blits fail later on, instead of the initialization error you'd expect in this case). Add checks to filter the list of emulated formats to only those supported for conversion to the native format. This presumes that there is a single native format (only the first is checked, if there are multiple). Refactoring this API to drop the native list or support it properly (by returning the appropriate emulated->native mapping table) is left for a future patch. The simpledrm driver is left as-is with a full table of emulated formats. This keeps all currently working conversions available and drops all the broken ones (i.e. this a strict bugfix patch, adding no new supported formats nor removing any actually working ones). In order to avoid proliferation of emulated formats, future drivers should advertise only XRGB8888 as the sole emulated format (since some userspace assumes its presence). This fixes a real user regression where the ?RGB2101010 support commit started advertising it unconditionally where not supported, and KWin decided to start to use it over the native format and broke, but also the fixes the spurious RGB565/RGB888 formats which have been wrongly unconditionally advertised since the dawn of simpledrm. Fixes: 6ea966f ("drm/simpledrm: Add [AX]RGB2101010 formats") Fixes: 11e8f5f ("drm: Add simpledrm driver") Cc: [email protected] Signed-off-by: Hector Martin <[email protected]> Acked-by: Pekka Paalanen <[email protected]> Reviewed-by: Thomas Zimmermann <[email protected]> Signed-off-by: Thomas Zimmermann <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 447fb14 commit 6fdaed8

File tree

1 file changed

+47
-19
lines changed

1 file changed

+47
-19
lines changed

drivers/gpu/drm/drm_format_helper.c

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,38 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t
807807
return false;
808808
}
809809

810+
static const uint32_t conv_from_xrgb8888[] = {
811+
DRM_FORMAT_XRGB8888,
812+
DRM_FORMAT_ARGB8888,
813+
DRM_FORMAT_XRGB2101010,
814+
DRM_FORMAT_ARGB2101010,
815+
DRM_FORMAT_RGB565,
816+
DRM_FORMAT_RGB888,
817+
};
818+
819+
static const uint32_t conv_from_rgb565_888[] = {
820+
DRM_FORMAT_XRGB8888,
821+
DRM_FORMAT_ARGB8888,
822+
};
823+
824+
static bool is_conversion_supported(uint32_t from, uint32_t to)
825+
{
826+
switch (from) {
827+
case DRM_FORMAT_XRGB8888:
828+
case DRM_FORMAT_ARGB8888:
829+
return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to);
830+
case DRM_FORMAT_RGB565:
831+
case DRM_FORMAT_RGB888:
832+
return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to);
833+
case DRM_FORMAT_XRGB2101010:
834+
return to == DRM_FORMAT_ARGB2101010;
835+
case DRM_FORMAT_ARGB2101010:
836+
return to == DRM_FORMAT_XRGB2101010;
837+
default:
838+
return false;
839+
}
840+
}
841+
810842
/**
811843
* drm_fb_build_fourcc_list - Filters a list of supported color formats against
812844
* the device's native formats
@@ -827,7 +859,9 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t
827859
* be handed over to drm_universal_plane_init() et al. Native formats
828860
* will go before emulated formats. Other heuristics might be applied
829861
* to optimize the order. Formats near the beginning of the list are
830-
* usually preferred over formats near the end of the list.
862+
* usually preferred over formats near the end of the list. Formats
863+
* without conversion helpers will be skipped. New drivers should only
864+
* pass in XRGB8888 and avoid exposing additional emulated formats.
831865
*
832866
* Returns:
833867
* The number of color-formats 4CC codes returned in @fourccs_out.
@@ -839,7 +873,7 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
839873
{
840874
u32 *fourccs = fourccs_out;
841875
const u32 *fourccs_end = fourccs_out + nfourccs_out;
842-
bool found_native = false;
876+
uint32_t native_format = 0;
843877
size_t i;
844878

845879
/*
@@ -858,26 +892,18 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
858892

859893
drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
860894

861-
if (!found_native)
862-
found_native = is_listed_fourcc(driver_fourccs, driver_nfourccs, fourcc);
895+
/*
896+
* There should only be one native format with the current API.
897+
* This API needs to be refactored to correctly support arbitrary
898+
* sets of native formats, since it needs to report which native
899+
* format to use for each emulated format.
900+
*/
901+
if (!native_format)
902+
native_format = fourcc;
863903
*fourccs = fourcc;
864904
++fourccs;
865905
}
866906

867-
/*
868-
* The plane's atomic_update helper converts the framebuffer's color format
869-
* to a native format when copying to device memory.
870-
*
871-
* If there is not a single format supported by both, device and
872-
* driver, the native formats are likely not supported by the conversion
873-
* helpers. Therefore *only* support the native formats and add a
874-
* conversion helper ASAP.
875-
*/
876-
if (!found_native) {
877-
drm_warn(dev, "Format conversion helpers required to add extra formats.\n");
878-
goto out;
879-
}
880-
881907
/*
882908
* The extra formats, emulated by the driver, go second.
883909
*/
@@ -890,6 +916,9 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
890916
} else if (fourccs == fourccs_end) {
891917
drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
892918
continue; /* end of available output buffer */
919+
} else if (!is_conversion_supported(fourcc, native_format)) {
920+
drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc);
921+
continue; /* format is not supported for conversion */
893922
}
894923

895924
drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
@@ -898,7 +927,6 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
898927
++fourccs;
899928
}
900929

901-
out:
902930
return fourccs - fourccs_out;
903931
}
904932
EXPORT_SYMBOL(drm_fb_build_fourcc_list);

0 commit comments

Comments
 (0)