void X11BufferSurface::apply(const BufferGuard&) noexcept { if(!active_) { warning("ny::X11BufferSurface::apply: no currently active BufferGuard"); return; } active_ = false; //we use the checked versions here since those function are very error prone due to //the rather complex depth/visual/bpp x system. We catch invalid x request here //directly. auto depth = windowContext().visualDepth(); auto window = windowContext().xWindow(); if(shm_) { auto cookie = xcb_shm_put_image_checked(&xConnection(), window, gc_, size_.x, size_.y, 0, 0, size_.x, size_.y, 0, 0, depth, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, shmseg_, 0); windowContext().errorCategory().checkWarn(cookie, "ny::X11BufferSurface: shm_put_image"); } else { auto bpp = imageDataFormatSize(format_); //Bytes per pixel (XXX NOT bits!) auto length = size_.x * size_.y * bpp; auto cookie = xcb_put_image_checked(&xConnection(), XCB_IMAGE_FORMAT_Z_PIXMAP, window, gc_, size_.x, size_.y, 0, 0, 0, depth, length, data_); windowContext().errorCategory().checkWarn(cookie, "ny::X11BufferSurface: put_image"); } }
bool VlcWindowlessXCB::handle_event(void *event) { XEvent *xevent = static_cast<XEvent *>(event); switch (xevent->type) { case GraphicsExpose: xcb_gcontext_t gc; xcb_void_cookie_t cookie; xcb_generic_error_t *err; XGraphicsExposeEvent *xgeevent = reinterpret_cast<XGraphicsExposeEvent *>(xevent); /* Something went wrong during initialization */ if (!m_conn || !m_screen) break; drawBackground(xgeevent->drawable); /* Validate video size */ if (m_media_width == 0 || m_media_height == 0) break; /* Compute the position of the video */ int left = (npwindow.width - m_media_width) / 2; int top = (npwindow.height - m_media_height) / 2; gc = xcb_generate_id(m_conn); xcb_create_gc(m_conn, gc, xgeevent->drawable, 0, NULL); /* Push the frame in X11 */ cookie = xcb_put_image_checked( m_conn, XCB_IMAGE_FORMAT_Z_PIXMAP, xgeevent->drawable, gc, m_media_width, m_media_height, left, top, 0, 24, m_media_width * m_media_height * 4, (const uint8_t *)&m_frame_buf[0]); if (err = xcb_request_check(m_conn, cookie)) { fprintf(stderr, "Unable to put picture into drawable. Error %d\n", err->error_code); free(err); } /* Flush the the connection */ xcb_flush(m_conn); xcb_free_gc(m_conn, gc); } return VlcWindowlessBase::handle_event(event); }
/** * Sends an image to the X server. */ static void Display (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; xcb_shm_seg_t segment = XCB_picture_GetSegment(pic); xcb_void_cookie_t ck; if (!sys->visible) goto out; if (segment != 0) ck = xcb_shm_put_image_checked (sys->conn, sys->window, sys->gc, /* real width */ pic->p->i_pitch / pic->p->i_pixel_pitch, /* real height */ pic->p->i_lines, /* x */ vd->fmt.i_x_offset, /* y */ vd->fmt.i_y_offset, /* width */ vd->fmt.i_visible_width, /* height */ vd->fmt.i_visible_height, 0, 0, sys->depth, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, segment, 0); else { const size_t offset = vd->fmt.i_y_offset * pic->p->i_pitch; const unsigned lines = pic->p->i_lines - vd->fmt.i_y_offset; ck = xcb_put_image_checked (sys->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, sys->window, sys->gc, pic->p->i_pitch / pic->p->i_pixel_pitch, lines, -vd->fmt.i_x_offset, 0, 0, sys->depth, pic->p->i_pitch * lines, pic->p->p_pixels + offset); } /* Wait for reply. This makes sure that the X server gets CPU time to * display the picture. xcb_flush() is *not* sufficient: especially with * shared memory the PUT requests are so short that many of them can fit in * X11 socket output buffer before the kernel preempts VLC. */ xcb_generic_error_t *e = xcb_request_check (sys->conn, ck); if (e != NULL) { msg_Dbg (vd, "%s: X11 error %d", "cannot put image", e->error_code); free (e); } /* FIXME might be WAY better to wait in some case (be carefull with * VOUT_DISPLAY_RESET_PICTURES if done) + does not work with * vout_display wrapper. */ out: picture_Release (pic); (void)subpicture; }
void draw_gc(xcb_window_t win) { xcb_rectangle_t r = { 0, 0, 0,0 }; xcb_connection_t *c = G.conn; xcb_get_geometry_reply_t *geo; geo = xcb_get_geometry_reply(c, xcb_get_geometry(c, win), NULL); if(0)printf("get (%hdx%hd)@(%dx%d)\n", geo->x, geo->y, geo->width, geo->height); xcb_get_image_cookie_t cookie; xcb_get_image_reply_t *reply; xcb_generic_error_t *error; xcb_void_cookie_t ck; if(geo!=NULL){ r.width = geo->width ; r.height=geo->height; r.x=0; r.y=0; //printf("window depth=%d\n", geo->depth); if(geo->depth == 24 | geo->depth == 32) psize = r.width * r.height * 4; //correct else if(geo->depth==16) psize = r.width * r.height * 2; //correct else printf(" *** unsupported window depth\n"); }else psize = r.width * r.height * 4; //correct free(geo); static cairo_surface_t *cmask; if( pbuf == NULL){ // psize = geo->width *geo->height*4; //for test pbuf = malloc(psize); printf("malloc pbuf=0x%x size=%d\n",pbuf, psize); memset(pbuf, 0x18, psize); cmask = cairo_image_surface_create_for_data ((unsigned char *) pbuf, CAIRO_FORMAT_ARGB32, geo->width, geo->height, geo->width*4); // 12, 4, 48); if(cmask == NULL){ perror("cairo surface create"); exit(1); } } if(0)printf("width (%dx%d=%d\n", geo->width, geo->height, geo->width *geo->height*4); draw_cairo(cmask); //draw image with xcb_put_image // creat gc and draw to parent window xcb_gcontext_t g; g = xcb_generate_id(c); xcb_create_gc(c, g, win, 0,NULL); ck = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, win, g, r.width, r.height, r.x,r.y, 0, G.s->root_depth, psize, pbuf); xcb_flush(c); }
void draw_gc(xcb_window_t win) { // the only problem to draw bgr24 it bps=4 but 3, if depth=24, /* fmt depth bps 32 32 4 bgr24 24 4 16 16 2 8 8 1 0 0 0 */ //draw something in parent window for test //w = s->root; xcb_gcontext_t g_solid; uint32_t mask; uint32_t values[2]; xcb_rectangle_t r = { 0, 0, 10,10 }; xcb_rectangle_t r2 = { 20, 20, 100,100 }; xcb_connection_t *c = G.conn; if(win==0) { win=G.root; // atach to root will cause error=Resource temporary unavailable } xcb_map_window(c, win); xcb_flush(c); g_solid = xcb_generate_id(c); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; values[0] = G.s->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; xcb_create_gc(c, g_solid, win, 0,NULL); xcb_change_gc(c, g_solid, mask, values); xcb_poly_fill_rectangle(c, win, g_solid, 1, &r2); xcb_flush(c); xcb_free_gc(c,g_solid); if(1){ //getimage xcb_get_image_cookie_t cookie; xcb_get_image_reply_t *reply; xcb_generic_error_t *error; int psize= r.width * r.height * G.s->root_depth/8; psize = r.width * r.height * 4; //correct static uint8_t *pbuf = NULL; xcb_void_cookie_t ck; if( pbuf == NULL){ pbuf = malloc(psize); printf("malloc pbuf=0x%x size=%d\n",pbuf, psize); memset(pbuf, 0x18, psize); } #if 0 cookie = xcb_get_image (c, XCB_IMAGE_FORMAT_Z_PIXMAP, win, r.x, r.y, r.width, r.height, ~0); reply = xcb_get_image_reply (c, cookie, &error); if (reply == NULL){ perror("get_image_replay"); return; } if (error != NULL) { perror("error in xcb_get_image"); free(error); } else { uint32_t bytes = xcb_get_image_data_length(reply); uint8_t *idata = xcb_get_image_data(reply); printf("get_image size=%d p=%p\n", bytes, idata); memcpy(pbuf, idata, bytes); printf("root_depth=%d\n", G.s->root_depth); psize=bytes; } free(reply); #endif //draw image with xcb_put_image // creat gc and draw to parent window xcb_gcontext_t g; g = xcb_generate_id(c); xcb_create_gc(c, g, win, 0,NULL); memset(pbuf, 0xf8, psize); int i=0; uint8_t *p2=pbuf; //fmt = bgr24 for( i=0; i<psize; ){ *(p2+i)= 0; i++; //blue *(p2+i)= 0xff; i++; //green *(p2+i)= 0; i++; //red *(p2+i)= 0x80; i++; //?? } ck = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, win, g, r.width, r.height, r.x,r.y, 0, G.s->root_depth, psize, pbuf); xcb_flush(c); #if 0 //BadMatch=8 BadLength=16 xcb_generic_error_t *err; err = xcb_request_check (c, ck); if (err) { int code = err->error_code; free (err); printf("put image error %d\n", code); assert (code != 0); } xcb_free_gc(c, g); #endif } }
int main(void) { xcb_connection_t *c; xcb_screen_t *s; xcb_window_t w; xcb_gcontext_t g; xcb_generic_event_t *e; uint32_t mask; uint32_t values[2]; int done = 0; /* open connection with the server */ c = xcb_connect(NULL,NULL); if (xcb_connection_has_error(c)) { printf("Cannot open display\n"); exit(1); } /* get the first screen */ s = xcb_setup_roots_iterator( xcb_get_setup(c) ).data; G.conn = c; G.s= s; //enable mouse event xcb_cursor_t cursor; xcb_font_t cursor_font=0; short glyph = 0x34; //cross xcb_grab_pointer_cookie_t grab_cookie; xcb_grab_pointer_reply_t *grab_reply; xcb_generic_error_t *err; cursor = xcb_generate_id (c); if (!cursor_font) { cursor_font = xcb_generate_id (c); xcb_open_font (c, cursor_font, strlen ("cursor"), "cursor"); } xcb_create_glyph_cursor (c, cursor, cursor_font, cursor_font, glyph, glyph + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff); /* rgb, rgb */ grab_cookie = xcb_grab_pointer(c, 0, s->root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, s->root, cursor, XCB_TIME_CURRENT_TIME); assert(grab_reply!=NULL); grab_reply = xcb_grab_pointer_reply (c, grab_cookie, &err); if (grab_reply->status != XCB_GRAB_STATUS_SUCCESS) printf("Can't grab the mouse."); printf("grab pointer cookie=0x%x\n", grab_cookie); xcb_allow_events (c, XCB_ALLOW_ASYNC_POINTER, XCB_TIME_CURRENT_TIME); xcb_flush (c); // xcb_allow_events (c, XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); xcb_flush (c); while (!done ) { e = xcb_wait_for_event(c); if(e==NULL) printf("wait event error\n"); //printf("\revent=>%d", e->response_type); switch (e->response_type & ~0x80) { case XCB_EXPOSE: /* draw or redraw the window */ printf("XCB_EXPOSE\n"); draw_gc(w); break; case XCB_MOTION_NOTIFY: { static xcb_window_t oldw; xcb_button_press_event_t *bp = (xcb_button_press_event_t *)e; w = bp->child; /* window selected */ if(oldw!=w){ oldw = w; printf("windowid = %x\n", w); } //draw it draw_gc(w); } break; case XCB_BUTTON_PRESS: { xcb_button_press_event_t *bp = (xcb_button_press_event_t *)e; w = bp->child; /* window selected */ if (w== XCB_WINDOW_NONE){ printf("window select is root\n"); w=s->root; } else printf("window = %x\n", w); draw_gc(w); done=1; printf("grab a child\n"); break; } } free(e); } xcb_ungrab_pointer(c, XCB_TIME_CURRENT_TIME); draw_byxid(w); return 0; #if 0 /* create window */ w = xcb_generate_id(c); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = s->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; xcb_create_window(c, s->root_depth, w, s->root, 10, 10, 100, 100, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, s->root_visual, mask, values); /* map (show) the window */ xcb_map_window(c, w); xcb_flush(c); /* event loop */ while (!done && (e = xcb_wait_for_event(c))) { switch (e->response_type & ~0x80) { case XCB_EXPOSE: /* draw or redraw the window */ xcb_poly_fill_rectangle(c, w, g, 1, &r); xcb_flush(c); break; case XCB_KEY_PRESS: /* exit on key press */ //gwj done = 1; break; } free(e); } /* close connection to server */ xcb_disconnect(c); return 0; if(0){ //draw image with xcb_put_image // creat gc and draw to parent window xcb_gcontext_t g; g = xcb_generate_id(c); xcb_create_gc(c, g, child, 0,NULL); //xcb_poly_fill_rectangle(c, w, g, 1, &r); xcb_flush(c); int psize=geo->width * geo->height* (geo->depth/8); uint8_t *pbuf = malloc(psize); xcb_void_cookie_t ck; printf("malloc pbuf=0x%x size=%d\n",pbuf, psize); memset(pbuf, 0x18, psize); ck = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, child, g, geo->width, geo->height , 0, 0, 0, geo->depth, psize, pbuf); //BadMatch=8 BadLength=16 xcb_generic_error_t *err; err = xcb_request_check (c, ck); if (err) { int code = err->error_code; free (err); printf("put image error %d\n", code); assert (code != 0); } } printf("depth =%d\n", geo->depth); /* create black graphics context */ #endif }