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(); }
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); }
// 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 }
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); }
/** * 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; }
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); }
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; }