Beispiel #1
0
void X11XRenderBackend::init(bool createOverlay)
{
    if (m_front != XCB_RENDER_PICTURE_NONE)
        xcb_render_free_picture(connection(), m_front);
    bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE);
    if (haveOverlay) {
        m_overlayWindow->setup(XCB_WINDOW_NONE);
        ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(connection(),
            xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), NULL));
        if (!attribs) {
            setFailed("Failed getting window attributes for overlay window");
            return;
        }
        m_format = XRenderUtils::findPictFormat(attribs->visual);
        if (m_format == 0) {
            setFailed("Failed to find XRender format for overlay window");
            return;
        }
        m_front = xcb_generate_id(connection());
        xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, NULL);
    } else {
        // create XRender picture for the root window
        m_format = XRenderUtils::findPictFormat(defaultScreen()->root_visual);
        if (m_format == 0) {
            setFailed("Failed to find XRender format for root window");
            return; // error
        }
        m_front = xcb_generate_id(connection());
        const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS};
        xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values);
    }
    createBuffer();
}
Beispiel #2
0
void X11XRenderBackend::createBuffer()
{
    xcb_pixmap_t pixmap = xcb_generate_id(connection());
    xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displayWidth(), displayHeight());
    xcb_render_picture_t b = xcb_generate_id(connection());
    xcb_render_create_picture(connection(), b, pixmap, m_format, 0, NULL);
    xcb_free_pixmap(connection(), pixmap);   // The picture owns the pixmap now
    setBuffer(b);
}
Beispiel #3
0
// Create the compositing buffer. The root window is not double-buffered,
// so it is done manually using this buffer,
void SceneXrender::createBuffer()
{
    if (buffer != XCB_RENDER_PICTURE_NONE)
        xcb_render_free_picture(connection(), buffer);
    xcb_pixmap_t pixmap = xcb_generate_id(connection());
    xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displayWidth(), displayHeight());
    buffer = xcb_generate_id(connection());
    xcb_render_create_picture(connection(), buffer, pixmap, format, 0, NULL);
    xcb_free_pixmap(connection(), pixmap);   // The picture owns the pixmap now
}
Beispiel #4
0
void XRenderWindowPixmap::create()
{
    if (isValid()) {
        return;
    }
    KWin::WindowPixmap::create();
    if (!isValid()) {
        return;
    }
    m_picture = xcb_generate_id(connection());
    xcb_render_create_picture(connection(), m_picture, pixmap(), m_format, 0, NULL);
}
Beispiel #5
0
/**
 * Probe the X server.
 */
static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
                video_format_t *fmtp, vlc_video_context *ctx)
{
    vlc_object_t *obj = VLC_OBJECT(vd);

    vout_display_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    vd->sys = sys;

    /* Connect to X */
    xcb_connection_t *conn;
    const xcb_screen_t *screen;

    if (vlc_xcb_parent_Create(vd, cfg, &conn, &screen) == NULL)
        return VLC_EGENERIC;

    sys->conn = conn;
    sys->root = screen->root;
    sys->format.argb = 0;
    sys->format.alpha = 0;

    if (!CheckRender(vd, conn))
        goto error;

    xcb_render_query_pict_formats_cookie_t pic_fmt_ck =
        xcb_render_query_pict_formats(conn);
    xcb_render_query_pict_formats_reply_t *pic_fmt_r =
        xcb_render_query_pict_formats_reply(conn, pic_fmt_ck, NULL);
    if (pic_fmt_r == NULL)
        goto error;

    const xcb_setup_t *setup = xcb_get_setup(conn);
    const xcb_render_pictforminfo_t *const pic_fmts =
        xcb_render_query_pict_formats_formats(pic_fmt_r);
    xcb_visualid_t visual = 0;

    for (unsigned i = 0; i < pic_fmt_r->num_formats; i++) {
        const xcb_render_pictforminfo_t *const pic_fmt = pic_fmts + i;
        const xcb_render_directformat_t *const d = &pic_fmt->direct;

        if (pic_fmt->depth == 8 && pic_fmt->direct.alpha_mask == 0xff) {
            /* Alpha mask format */
            sys->format.alpha = pic_fmt->id;
            continue;
        }

        xcb_visualid_t vid = FindVisual(setup, screen, pic_fmt_r, pic_fmt->id);
        if (vid == 0)
            continue;

        /* Use only ARGB for now. 32-bits is guaranteed to work. */
        if (pic_fmt->depth != 32)
            continue;

        vlc_fourcc_t chroma = ParseFormat(setup, pic_fmt);
        if (chroma == 0)
            continue;

        fmtp->i_chroma = chroma;
        fmtp->i_rmask = ((uint32_t)d->red_mask) << d->red_shift;
        fmtp->i_gmask = ((uint32_t)d->green_mask) << d->green_shift;
        fmtp->i_bmask = ((uint32_t)d->blue_mask) << d->blue_shift;
        sys->format.argb = pic_fmt->id;
        visual = vid;
    }

    free(pic_fmt_r);

    if (unlikely(sys->format.argb == 0 || sys->format.alpha == 0))
        goto error; /* Buggy server */

    msg_Dbg(obj, "using RENDER picture format %u", sys->format.argb);
    msg_Dbg(obj, "using X11 visual 0x%"PRIx32, visual);

    char *filter = var_InheritString(obj, "x11-render-filter");
    if (filter != NULL) {
        msg_Dbg(obj, "using filter \"%s\"", filter);
        sys->filter = ToCharset("ISO 8859-1", filter, &(size_t){ 0 });
        free(filter);
    } else
        sys->filter = NULL;

    sys->drawable.source = xcb_generate_id(conn);
    sys->drawable.crop = xcb_generate_id(conn);
    sys->drawable.scale = xcb_generate_id(conn);
    sys->drawable.subpic = xcb_generate_id(conn);
    sys->drawable.alpha = xcb_generate_id(conn);
    sys->drawable.dest = xcb_generate_id(conn);
    sys->picture.source = xcb_generate_id(conn);
    sys->picture.crop = xcb_generate_id(conn);
    sys->picture.scale = xcb_generate_id(conn);
    sys->picture.subpic = xcb_generate_id(conn);
    sys->picture.alpha = xcb_generate_id(conn);
    sys->picture.dest = xcb_generate_id(conn);
    sys->gc = xcb_generate_id(conn);

    if (XCB_shm_Check(obj, conn))
        sys->segment = xcb_generate_id(conn);
    else
        sys->segment = 0;

    xcb_colormap_t cmap = xcb_generate_id(conn);
    uint32_t cw_mask =
        XCB_CW_BACK_PIXEL |
        XCB_CW_BORDER_PIXEL |
        XCB_CW_EVENT_MASK |
        XCB_CW_COLORMAP;
    const uint32_t cw_list[] = {
        /* XCB_CW_BACK_PIXEL */
        screen->black_pixel,
        /* XCB_CW_BORDER_PIXEL */
        screen->black_pixel,
        /* XCB_CW_EVENT_MASK */
        0,
        /* XCB_CW_COLORMAP */
        cmap,
    };

    xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, cmap, screen->root,
                        visual);
    xcb_create_pixmap(conn, 32, sys->drawable.source, screen->root,
                      vd->source.i_width, vd->source.i_height);
    xcb_create_gc(conn, sys->gc, sys->drawable.source, 0, NULL);
    xcb_create_window(conn, 32, sys->drawable.dest, cfg->window->handle.xid,
                      0, 0, cfg->display.width, cfg->display.height, 0,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, cw_mask, cw_list);
    xcb_render_create_picture(conn, sys->picture.source, sys->drawable.source,
                              sys->format.argb, 0, NULL);
    xcb_render_create_picture(conn, sys->picture.dest, sys->drawable.dest,
                              sys->format.argb, 0, NULL);
    CreateBuffers(vd, cfg);
    xcb_map_window(conn, sys->drawable.dest);

    sys->spu_chromas[0] = fmtp->i_chroma;
    sys->spu_chromas[1] = 0;

    vd->info.subpicture_chromas = sys->spu_chromas;
    vd->prepare = Prepare;
    vd->display = Display;
    vd->control = Control;

    (void) ctx;
    return VLC_SUCCESS;

error:
    xcb_disconnect(conn);
    return VLC_EGENERIC;
}
Beispiel #6
0
static void CreateBuffers(vout_display_t *vd, const vout_display_cfg_t *cfg)
{
    const video_format_t *fmt = &vd->source;
    vout_display_sys_t *sys = vd->sys;
    xcb_connection_t *conn = sys->conn;

    xcb_create_pixmap(conn, 32, sys->drawable.crop, sys->root,
                      fmt->i_visible_width, fmt->i_visible_height);
    xcb_create_pixmap(conn, 32, sys->drawable.scale, sys->root,
                      cfg->display.width, cfg->display.height);
    xcb_render_create_picture(conn, sys->picture.crop, sys->drawable.crop,
                              sys->format.argb, 0, NULL);
    xcb_render_create_picture(conn, sys->picture.scale, sys->drawable.scale,
                              sys->format.argb, 0, NULL);

    vout_display_place_t *place = &sys->place;
    vout_display_PlacePicture(place, fmt, cfg);

    /* Homogeneous coordinates transform from destination(place)
     * to source(fmt) */
    int32_t ax = place->height; /* multiply x instead of dividing y */
    int32_t ay = place->width; /* multiply y instead of dividing x */
    int32_t bx = 0;
    int32_t by = 0;

    switch (fmt->orientation) {
        case ORIENT_TOP_LEFT:
        case ORIENT_LEFT_TOP:
            break;
        case ORIENT_TOP_RIGHT:
        case ORIENT_RIGHT_TOP:
            ax *= -1;
            bx -= place->width;
            break;
        case ORIENT_BOTTOM_LEFT:
        case ORIENT_LEFT_BOTTOM:
            ay *= -1;
            by -= place->height;
            break;
        case ORIENT_BOTTOM_RIGHT:
        case ORIENT_RIGHT_BOTTOM:
            ax *= -1;
            ay *= -1;
            bx -= place->width;
            by -= place->height;
            break;
    }

    sys->src_x = bx;
    sys->src_y = by;

    xcb_render_transform_t transform = {
        0, 0, 0,
        0, 0, 0,
        /* Multiply z by width and height to compensate for x and y above */
        0, 0, place->width * place->height,
    };

    if (ORIENT_IS_SWAP(fmt->orientation)) {
        transform.matrix12 = ay * fmt->i_visible_width;
        transform.matrix21 = ax * fmt->i_visible_height;
    } else {
        transform.matrix11 = ax * fmt->i_visible_width;
        transform.matrix22 = ay * fmt->i_visible_height;
    }

    xcb_render_set_picture_transform(conn, sys->picture.crop, transform);

    if (likely(sys->filter != NULL))
        xcb_render_set_picture_filter(conn, sys->picture.crop,
                                      strlen(sys->filter), sys->filter,
                                      0, NULL);
}
Beispiel #7
0
static void RenderRegion(vout_display_t *vd, const subpicture_t *subpic,
                         const subpicture_region_t *reg)
{
    vout_display_sys_t *sys = vd->sys;
    xcb_connection_t *conn = sys->conn;
    const vout_display_place_t *place = &sys->place;
    picture_t *pic = reg->p_picture;
    unsigned sw = reg->fmt.i_width;
    unsigned sh = reg->fmt.i_height;
    xcb_rectangle_t rects[] = { { 0, 0, sw, sh }, };

    xcb_create_pixmap(conn, 32, sys->drawable.subpic, sys->root, sw, sh);
    xcb_create_pixmap(conn, 8, sys->drawable.alpha, sys->root, sw, sh);
    xcb_render_create_picture(conn, sys->picture.subpic, sys->drawable.subpic,
                              sys->format.argb, 0, NULL);
    xcb_render_create_picture(conn, sys->picture.alpha, sys->drawable.alpha,
                              sys->format.alpha, 0, NULL);

    /* Upload region (TODO: use FD passing for SPU?) */
    xcb_put_image(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, sys->drawable.subpic,
                  sys->gc, pic->p->i_pitch / pic->p->i_pixel_pitch,
                  pic->p->i_lines, 0, 0, 0, 32,
                  pic->p->i_pitch * pic->p->i_lines, pic->p->p_pixels);

    /* Copy alpha channel */
    xcb_render_composite(conn, XCB_RENDER_PICT_OP_SRC,
                         sys->picture.subpic, XCB_RENDER_PICTURE_NONE,
                         sys->picture.alpha, 0, 0, 0, 0, 0, 0, sw, sh);

    /* Force alpha channel to maximum (add 100% and clip).
     * This is to compensate RENDER expecting pre-multiplied RGB
     * while VLC uses straight RGB.
     */
    static const xcb_render_color_t alpha_one_color = { 0, 0, 0, 0xffff };

    xcb_render_fill_rectangles(conn, XCB_RENDER_PICT_OP_ADD,
                               sys->picture.subpic, alpha_one_color,
                               ARRAY_SIZE(rects), rects);

    /* Multiply by region and subpicture alpha factors */
    static const float alpha_fixed = 0xffffp0f / (0xffp0f * 0xffp0f);
    xcb_render_color_t alpha_color = {
        0, 0, 0, lroundf(reg->i_alpha * subpic->i_alpha * alpha_fixed) };

    xcb_render_fill_rectangles(conn, XCB_RENDER_PICT_OP_IN_REVERSE,
                               sys->picture.subpic, alpha_color,
                               ARRAY_SIZE(rects), rects);

    /* Mask in the original alpha channel then renver over the scaled pixmap.
     * Mask (pre)multiplies RGB channels and restores the alpha channel.
     */
    int_fast16_t dx = place->x + reg->i_x * place->width
                      / subpic->i_original_picture_width;
    int_fast16_t dy = place->y + reg->i_y * place->height
                      / subpic->i_original_picture_height;
    uint_fast16_t dw = (reg->i_x + reg->fmt.i_visible_width) * place->width
                       / subpic->i_original_picture_width;
    uint_fast16_t dh = (reg->i_y + reg->fmt.i_visible_height) * place->height
                       / subpic->i_original_picture_height;

    xcb_render_composite(conn, XCB_RENDER_PICT_OP_OVER,
                         sys->picture.subpic, sys->picture.alpha,
                         sys->picture.scale, 0, 0, 0, 0, dx, dy, dw, dh);

    xcb_render_free_picture(conn, sys->picture.alpha);
    xcb_render_free_picture(conn, sys->picture.subpic);
    xcb_free_pixmap(conn, sys->drawable.alpha);
    xcb_free_pixmap(conn, sys->drawable.subpic);
}
XR_Font_Surface *
_xre_xcb_font_surface_new(Ximage_Info *xinf, RGBA_Font_Glyph *fg)
{
   char             buf[256];
   char             buf2[256];
   uint32_t         values[3];
   XR_Font_Surface *fs;
   DATA8           *data;
   Ximage_Image    *xim;
   Eina_Hash       *pool;
   uint32_t         mask;
   int              w;
   int              h;
   int              pitch;

   data = fg->glyph_out->bitmap.buffer;
   w = fg->glyph_out->bitmap.width;
   h = fg->glyph_out->bitmap.rows;
   pitch = fg->glyph_out->bitmap.pitch;
   if (pitch < w) pitch = w;
   if ((w <= 0) || (h <= 0)) return NULL;

   if (fg->ext_dat)
     {
	fs = fg->ext_dat;
	if ((fs->xinf->x11.connection == xinf->x11.connection) &&
            (fs->xinf->x11.root == xinf->x11.root))
	  return fs;
	snprintf(buf, sizeof(buf), "@%p@/@%x@", fs->xinf->x11.connection, fs->xinf->x11.root);
	pool = eina_hash_find(_xr_fg_pool, buf);
	if (pool)
	  {
	     snprintf(buf, sizeof(buf), "%p", fg);
	     fs = eina_hash_find(pool, buf);
	     if (fs) return fs;
	  }
     }

   fs = calloc(1, sizeof(XR_Font_Surface));
   if (!fs) return NULL;

   fs->xinf = xinf;
   fs->fg = fg;
   fs->xinf->references++;
   fs->w = w;
   fs->h = h;

   snprintf(buf, sizeof(buf), "@%p@/@%x@", fs->xinf->x11.connection, fs->xinf->x11.root);
   pool = eina_hash_find(_xr_fg_pool, buf);
   if (!pool) pool = eina_hash_string_superfast_new(NULL);
   snprintf(buf2, sizeof(buf2), "%p", fg);
   eina_hash_add(pool, buf2, fs);
   if (!_xr_fg_pool) _xr_fg_pool = eina_hash_string_superfast_new(NULL);
   eina_hash_add(_xr_fg_pool, buf, pool);

   fs->draw = xcb_generate_id(xinf->x11.connection);
   xcb_create_pixmap(xinf->x11.connection, ((xcb_render_pictforminfo_t *)xinf->x11.fmt8)->depth, fs->draw, xinf->x11.root, w, h);

   mask = XCB_RENDER_CP_REPEAT | XCB_RENDER_CP_DITHER | XCB_RENDER_CP_COMPONENT_ALPHA;
   values[0] = 0;
   values[1] = 0;
   values[2] = 0;
   fs->pic = xcb_generate_id(xinf->x11.connection);
   xcb_render_create_picture(xinf->x11.connection, fs->pic, fs->draw, ((xcb_render_pictforminfo_t *)xinf->x11.fmt8)->id, mask, values);

   xim = _xr_xcb_image_new(fs->xinf, w, h, ((xcb_render_pictforminfo_t *)xinf->x11.fmt8)->depth);
   if ((fg->glyph_out->bitmap.num_grays == 256) &&
       (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
     {
	int x, y;
	DATA8 *p1, *p2;

	for (y = 0; y < h; y++)
	  {
	     p1 = data + (pitch * y);
	     p2 = ((DATA8 *)xim->data) + (xim->line_bytes * y);
	     for (x = 0; x < w; x++)
	       {
		  *p2 = *p1;
		  p1++;
		  p2++;
	       }
	  }

     }
   else
     {
        DATA8      *tmpbuf = NULL, *dp, *tp, bits;
	int         bi, bj, end;
	const DATA8 bitrepl[2] = {0x0, 0xff};

	tmpbuf = alloca(w);
	  {
	     int    x, y;
	     DATA8 *p1, *p2;

	     for (y = 0; y < h; y++)
	       {
		  p1 = tmpbuf;
		  p2 = ((DATA8 *)xim->data) + (xim->line_bytes * y);
		  tp = tmpbuf;
		  dp = data + (y * fg->glyph_out->bitmap.pitch);
		  for (bi = 0; bi < w; bi += 8)
		    {
		       bits = *dp;
		       if ((w - bi) < 8) end = w - bi;
		       else end = 8;
		       for (bj = 0; bj < end; bj++)
			 {
			    *tp = bitrepl[(bits >> (7 - bj)) & 0x1];
			    tp++;
			 }
		       dp++;
		    }
		  for (x = 0; x < w; x++)
		    {
		       *p2 = *p1;
		       p1++;
		       p2++;
		    }
	       }
	  }
     }
   _xr_xcb_image_put(xim, fs->draw, 0, 0, w, h);
   return fs;
}