This fixes gnome-terminal not showing in qemu [1] and can be triggered
by the attached test case.
I haven't combined this with the patch in [2] because this patch is
internally coherent with the fb logic; I still don't know if fb is
doing the right thing here by allowing depth=32 bpp=24. The RENDER
patch is not required for gnome-terminal (and I suspect any
application using depth 32 visual and cairo/GTK+ to render) but
follows the same logic.
--Robert
[1] http://lists.x.org/archives/xorg-devel/2014-June/042723.html
[2] http://lists.x.org/archives/xorg-devel/2014-June/042721.html
On Fri, Jun 6, 2014 at 11:52 PM, Robert Ancell
<[email protected]> wrote:
> When using the fb backend at 24bpp it allows a visual with 32 bit depth.
> When using CopyArea from a 32bpp pixmap to a window with a 32 bit depth it
> would
> read the ARGB as RGB.
>
> Fix is to correctly ignore the alpha channel in the pixmap when copying.
> ---
> fb/fbcopy.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/fb/fbcopy.c b/fb/fbcopy.c
> index 541ef71..5455947 100644
> --- a/fb/fbcopy.c
> +++ b/fb/fbcopy.c
> @@ -242,8 +242,16 @@ fbCopyArea(DrawablePtr pSrcDrawable,
> int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut)
> {
> miCopyProc copy;
> + int src_bpp, dst_bpp;
>
> - if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
> + src_bpp = pSrcDrawable->bitsPerPixel;
> + if (src_bpp < pSrcDrawable->depth)
> + src_bpp = BitsPerPixel (pSrcDrawable->depth);
> + dst_bpp = pDstDrawable->bitsPerPixel;
> + if (dst_bpp < pDstDrawable->depth)
> + dst_bpp = BitsPerPixel (pDstDrawable->depth);
> +
> + if (src_bpp != dst_bpp)
> copy = fb24_32CopyMtoN;
> else
> copy = fbCopyNtoN;
> --
> 2.0.0
>
// gcc -g -Wall copy-area.c -o copy-area -lxcb
#include <stdlib.h>
#include <xcb/xcb.h>
int main (int argc, char **argv)
{
xcb_connection_t *c = xcb_connect (NULL, NULL);
xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
xcb_visualtype_t *visual = NULL;
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator (screen);
int depth = 32;
while (depth_iter.rem > 0)
{
if (depth_iter.data->depth == depth)
{
visual = xcb_depth_visuals (depth_iter.data);
break;
}
xcb_depth_next (&depth_iter);
}
uint16_t width = 50;
uint16_t height = 50;
xcb_colormap_t cmap = xcb_generate_id (c);
xcb_create_colormap (c, 0, cmap, screen->root, visual->visual_id);
xcb_window_t w = xcb_generate_id (c);
uint32_t value_list[4] = { screen->black_pixel, screen->black_pixel, XCB_EVENT_MASK_EXPOSURE, cmap };
xcb_create_window (c, depth,
w, screen->root,
0, 0, width, height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id,
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP,
value_list);
xcb_map_window (c, w);
xcb_pixmap_t p = xcb_generate_id (c);
xcb_create_pixmap (c, depth, p, w, width, height);
uint32_t data_length = width * height * sizeof (uint32_t);
uint32_t *data = malloc (data_length);
int x, y, i = 0;
// Asuming ARGB
for (x = 0; x < width; x++)
for (y = 0; y < height; y++)
data[i++] = (0xFF << 24) | ((x * 0xFF / width) << 16) | ((y * 0xFF / height) << 8);
xcb_gcontext_t gc = xcb_generate_id (c);
xcb_create_gc (c, gc, p, 0, NULL);
xcb_put_image (c, XCB_IMAGE_FORMAT_Z_PIXMAP, p, gc, width, height, 0, 0, 0, depth, data_length, (uint8_t *) data);
xcb_free_gc (c, gc);
xcb_flush (c);
gc = xcb_generate_id (c);
xcb_create_gc (c, gc, w, 0, NULL);
while (1)
{
xcb_generic_event_t *event = xcb_wait_for_event (c);
if (event == NULL)
break;
if (event->response_type == XCB_EXPOSE)
{
xcb_copy_area (c, p, w, gc, 0, 0, 0, 0, width, height);
xcb_flush (c);
}
}
return 0;
}
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel