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

Reply via email to