Some background on this patch:
I've been trying to investigate why gnome-terminal doesn't render
correctly when running Ubuntu 14.04 LTS inside qemu (on Ubuntu 14.10).
The window is compressed in the X axis and has transparency (seems to
be a buffer somewhere that is being written in RGB and read as RGBA).
The issue seems to be GTK+ applications using the RGBA visual when
qemu/X/fb is providing a depth 24 root window. Playing around with
test cases showed the assertion mentioned in the patch. I'm not sure
if fb should be allowed to have a depth greater than the bpp and if
the bug is actually there but this patch allows correct rendering in
my test case now. I guess the Picture is being converted from RGBA to
RGB when it hits the root window?
Note this patch doesn't fix the gnome-terminal rendering issue, so
I'll continue down the rabbit hole. Any suggestions as to the causes
of this are greatly appreciated.
Attached is a program that doesn't render on the current master and
does with the applied patch.
--Robert
On Fri, Jun 6, 2014 at 4:36 PM, Robert Ancell
<[email protected]> wrote:
> When using the fb backend at 24bpp it allows a visual with 32 bit depth.
> This would cause RENDER to try and create an invalid pixman buffer and hit the
> following assertion when trying to render to it:
>
> *** BUG ***
> In create_bits_image_internal: The expression PIXMAN_FORMAT_BPP (format) >=
> PIXMAN_FORMAT_DEPTH (format) was false
> Set a breakpoint on '_pixman_log_error' to debug
>
> Fix is to ensure that the bpp is always at least as big as the drawable depth.
> ---
> render/picture.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/render/picture.c b/render/picture.c
> index 7da9310..f411521 100644
> --- a/render/picture.c
> +++ b/render/picture.c
> @@ -762,6 +762,7 @@ CreatePicture(Picture pid,
> {
> PicturePtr pPicture;
> PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen);
> + int bpp;
>
> pPicture = dixAllocateScreenObjectWithPrivates(pDrawable->pScreen,
> PictureRec,
> PRIVATE_PICTURE);
> @@ -773,7 +774,10 @@ CreatePicture(Picture pid,
> pPicture->id = pid;
> pPicture->pDrawable = pDrawable;
> pPicture->pFormat = pFormat;
> - pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
> + bpp = pDrawable->bitsPerPixel;
> + if (bpp < pFormat->depth)
> + bpp = BitsPerPixel (pFormat->depth);
> + pPicture->format = pFormat->format | (bpp << 24);
>
> /* security creation/labeling check */
> *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType,
> pPicture,
> --
> 2.0.0
>
// gcc -g -Wall test24.c -o test24 -lxcb -lxcb-render
#include <xcb/xcb.h>
#include <xcb/render.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 = 200;
uint16_t height = 100;
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 | XCB_EVENT_MASK_STRUCTURE_NOTIFY, 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_render_query_pict_formats_reply_t *r = xcb_render_query_pict_formats_reply (c, xcb_render_query_pict_formats (c), NULL);
xcb_render_pictforminfo_iterator_t format_iter = xcb_render_query_pict_formats_formats_iterator (r);
xcb_render_pictformat_t format;
while (format_iter.rem > 0)
{
if (format_iter.data->depth == depth)
{
format = format_iter.data->id;
break;
}
xcb_render_pictforminfo_next (&format_iter);
}
xcb_render_picture_t pf = xcb_generate_id (c);
xcb_render_color_t color = { 65535, 0, 0, 65535 };
xcb_render_create_solid_fill (c, pf, color);
xcb_render_picture_t p = xcb_generate_id (c);
xcb_render_create_picture (c, p, w, format, 0, NULL);
xcb_render_triangle_t triangle;
triangle.p1.x = (width / 2) << 16;
triangle.p1.y = 10 << 16;
triangle.p3.x = 10 << 16;
triangle.p3.y = (height - 10) << 16;
triangle.p2.x = (width - 10) << 16;
triangle.p2.y = (height - 10) << 16;
xcb_render_triangles (c, XCB_RENDER_PICT_OP_SRC, pf, p, 0, 0, 0, 1, &triangle);
xcb_flush (c);
while (xcb_wait_for_event (c) != NULL);
return 0;
}
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel