On Sat, Mar 02, 2019 at 10:24:22PM +0200, Mihai Popescu wrote: > Hello, > > I am able to generate a segmentation fault on X with chromium help. > This is happening each time I visit the web page at [1]. Basically, > there is a picture of a product and whenever I hover the mouse over > it, X gets a segmentation fault and exits at xenodm login prompt. > Sometimes, if I repeat this procedure over and over, I get an offset > for the image on my display, making things hard to see. > > [1] > https://computers.woot.com/offers/lenovo-thinkcentre-m78-amd-a4-sff-desktop-1 > > I have inspected the web page in question with firefox, and I can tell > the page loads a special image cursor when I hover on the picture in > question. No segmentation fault for X this time. >
Hi, Thanks for the bug report. Can you try the attached patch (from upstream) ? Index: src/drmmode_display.c =================================================================== RCS file: /cvs/OpenBSD/xenocara/driver/xf86-video-ati/src/drmmode_display.c,v retrieving revision 1.18 diff -u -p -u -r1.18 drmmode_display.c --- src/drmmode_display.c 13 Jan 2019 07:16:48 -0000 1.18 +++ src/drmmode_display.c 4 Mar 2019 08:12:30 -0000 @@ -1038,29 +1038,62 @@ drmmode_cursor_src_offset(Rotation rotat #endif -static uint32_t -drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb) +static Bool +drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied, + Bool *apply_gamma) { - uint32_t alpha = argb >> 24; + uint32_t alpha = *argb >> 24; uint32_t rgb[3]; int i; - if (!alpha) - return 0; + if (premultiplied) { +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0) + if (alpha == 0 && (*argb & 0xffffff) != 0) { + /* Doesn't look like premultiplied alpha */ + *premultiplied = FALSE; + return FALSE; + } +#endif - if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) - return argb; + 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) { + *argb = 0; + return TRUE; + } - /* Un-premultiply alpha */ + /* Extract RGB */ for (i = 0; i < 3; i++) - rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha; + rgb[i] = (*argb >> (i * 8)) & 0xff; - /* Apply gamma correction and pre-multiply alpha */ - rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff; - rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff; - rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff; + if (premultiplied) { + /* Un-premultiply alpha */ + for (i = 0; i < 3; i++) + rgb[i] = rgb[i] * 0xff / alpha; + } + + 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; + } - return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; + /* Premultiply alpha */ + for (i = 0; i < 3; i++) + rgb[i] = rgb[i] * alpha / 0xff; + + *argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; + return TRUE; } static void @@ -1069,27 +1102,36 @@ drmmode_load_cursor_argb (xf86CrtcPtr cr ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + Bool premultiplied = TRUE; + Bool apply_gamma = TRUE; + uint32_t argb; uint32_t *ptr; /* cursor should be mapped already */ ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); + if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) + apply_gamma = FALSE; + #if XF86_CRTC_VERSION < 7 if (crtc->driverIsPerformingTransform) { uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h; int dstx, dsty; int srcoffset; +retry_transform: for (dsty = 0; dsty < cursor_h; dsty++) { for (dstx = 0; dstx < cursor_w; dstx++) { srcoffset = drmmode_cursor_src_offset(crtc->rotation, cursor_w, cursor_h, dstx, dsty); + argb = image[srcoffset]; + if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, + &apply_gamma)) + goto retry_transform; - ptr[dsty * info->cursor_w + dstx] = - cpu_to_le32(drmmode_cursor_gamma(crtc, - image[srcoffset])); + ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb); } } } else @@ -1098,8 +1140,15 @@ drmmode_load_cursor_argb (xf86CrtcPtr cr uint32_t cursor_size = info->cursor_w * info->cursor_h; int i; - for (i = 0; i < cursor_size; i++) - ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i])); +retry: + for (i = 0; i < cursor_size; i++) { + argb = image[i]; + if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, + &apply_gamma)) + goto retry; + + ptr[i] = cpu_to_le32(argb); + } } } -- Matthieu Herrb