summaryrefslogtreecommitdiff
path: root/src/drmmode_display.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2018-11-15 16:40:46 +0100
committerMichel Dänzer <michel@daenzer.net>2018-11-20 10:14:37 +0100
commit13c94a373b4858a2d2aa14c22b5f98d53c84c0d9 (patch)
tree8d38cab64ebc51787c9e1ec0755415f2b4afedfc /src/drmmode_display.c
parent51ba6dddee40c3688d4c7b12eabeab516ed153b7 (diff)
Skip gamma correction of cursor data if premultiplied R/G/B > alpha
The un-premultiplied R/G/B values would overflow the gamma LUT, so just pass through the data unchanged, and leave it up to the HW how to interpret such weird premultiplied alpha pixels. Bugzilla: https://bugs.freedesktop.org/108355
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r--src/drmmode_display.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 23c7349..1c62186 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1501,8 +1501,8 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height,
#endif
static Bool
-drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
- Bool apply_gamma)
+drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied,
+ Bool *apply_gamma)
{
uint32_t alpha = *argb >> 24;
uint32_t rgb[3];
@@ -1510,13 +1510,23 @@ drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
if (premultiplied) {
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0)
- if (alpha == 0 && (*argb & 0xffffff) != 0)
+ if (alpha == 0 && (*argb & 0xffffff) != 0) {
/* Doesn't look like premultiplied alpha */
+ *premultiplied = FALSE;
return FALSE;
+ }
#endif
- if (!apply_gamma)
+ if (!(*apply_gamma))
return TRUE;
+
+ if (*argb > (alpha | alpha << 8 | alpha << 16 | alpha << 24)) {
+ /* Un-premultiplied R/G/B would overflow gamma LUT,
+ * don't apply gamma correction
+ */
+ *apply_gamma = FALSE;
+ return FALSE;
+ }
}
if (!alpha) {
@@ -1534,7 +1544,7 @@ drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
rgb[i] = rgb[i] * 0xff / alpha;
}
- if (apply_gamma) {
+ if (*apply_gamma) {
rgb[0] = crtc->gamma_blue[rgb[0]] >> 8;
rgb[1] = crtc->gamma_green[rgb[1]] >> 8;
rgb[2] = crtc->gamma_red[rgb[2]] >> 8;
@@ -1574,11 +1584,10 @@ retry_transform:
cursor_h,
dstx, dsty);
argb = image[srcoffset];
- if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
- apply_gamma)) {
- premultiplied = FALSE;
+ if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied,
+ &apply_gamma))
goto retry_transform;
- }
+
ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb);
}
}
@@ -1591,11 +1600,10 @@ retry_transform:
retry:
for (i = 0; i < cursor_size; i++) {
argb = image[i];
- if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
- apply_gamma)) {
- premultiplied = FALSE;
+ if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied,
+ &apply_gamma))
goto retry;
- }
+
ptr[i] = cpu_to_le32(argb);
}
}