void Window::_InitOSWindow()
{
	// create connection to X11 server
	const xcb_setup_t		*	setup		= nullptr;
	xcb_screen_iterator_t		iter;
	int							screen		= 0;

	_xcb_connection			=	xcb_connect( nullptr, &screen );
	if( _xcb_connection == nullptr ) {
		std::cout << "Cannot find a compatible Vulkan ICD.\n";
		exit( -1 );
	}

	setup		= xcb_get_setup( _xcb_connection );
	iter		= xcb_setup_roots_iterator( setup );
	while( screen-- > 0 ) {
		xcb_screen_next( &iter );
	}
	_xcb_screen = iter.data;

	// create window
	VkRect2D dimensions = { { 0, 0 }, { _surface_size_x, _surface_size_y } };

	assert( dimensions.extent.width > 0 );
	assert( dimensions.extent.height > 0 );

	uint32_t value_mask, value_list[ 32 ];

	_xcb_window = xcb_generate_id( _xcb_connection );

	value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	value_list[ 0 ] = _xcb_screen->black_pixel;
	value_list[ 1 ] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE;

	xcb_create_window( _xcb_connection, XCB_COPY_FROM_PARENT, _xcb_window,
		_xcb_screen->root, dimensions.offset.x, dimensions.offset.y,
		dimensions.extent.width, dimensions.extent.height, 0,
		XCB_WINDOW_CLASS_INPUT_OUTPUT, _xcb_screen->root_visual,
		value_mask, value_list );

	/* Magic code that will send notification when window is destroyed */
	xcb_intern_atom_cookie_t cookie =
		xcb_intern_atom( _xcb_connection, 1, 12, "WM_PROTOCOLS" );
	xcb_intern_atom_reply_t *reply =
		xcb_intern_atom_reply( _xcb_connection, cookie, 0 );

	xcb_intern_atom_cookie_t cookie2 =
		xcb_intern_atom( _xcb_connection, 0, 16, "WM_DELETE_WINDOW" );
	_xcb_atom_window_reply =
		xcb_intern_atom_reply( _xcb_connection, cookie2, 0 );

	xcb_change_property( _xcb_connection, XCB_PROP_MODE_REPLACE, _xcb_window,
		( *reply ).atom, 4, 32, 1,
		&( *_xcb_atom_window_reply ).atom );
	free( reply );

	xcb_map_window( _xcb_connection, _xcb_window );

	// Force the x/y coordinates to 100,100 results are identical in consecutive
	// runs
	const uint32_t coords[] = { 100, 100 };
	xcb_configure_window( _xcb_connection, _xcb_window,
		XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords );
	xcb_flush( _xcb_connection );

	/*
	xcb_generic_event_t *e;
	while( ( e = xcb_wait_for_event( _xcb_connection ) ) ) {
		if( ( e->response_type & ~0x80 ) == XCB_EXPOSE )
			break;
	}
	*/
}
Exemple #2
0
static struct vl_dri3_buffer *
dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
{
   struct vl_dri3_buffer *buffer;
   xcb_pixmap_t pixmap;
   xcb_sync_fence_t sync_fence;
   struct xshmfence *shm_fence;
   int buffer_fd, fence_fd;
   struct pipe_resource templ;
   struct winsys_handle whandle;
   unsigned usage;

   buffer = CALLOC_STRUCT(vl_dri3_buffer);
   if (!buffer)
      return NULL;

   fence_fd = xshmfence_alloc_shm();
   if (fence_fd < 0)
      goto free_buffer;

   shm_fence = xshmfence_map_shm(fence_fd);
   if (!shm_fence)
      goto close_fd;

   memset(&templ, 0, sizeof(templ));
   templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
                PIPE_BIND_SCANOUT | PIPE_BIND_SHARED;
   templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
   templ.target = PIPE_TEXTURE_2D;
   templ.last_level = 0;
   templ.width0 = scrn->width;
   templ.height0 = scrn->height;
   templ.depth0 = 1;
   templ.array_size = 1;
   buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen,
                                                         &templ);
   if (!buffer->texture)
      goto unmap_shm;

   memset(&whandle, 0, sizeof(whandle));
   whandle.type= DRM_API_HANDLE_TYPE_FD;
   usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
   scrn->base.pscreen->resource_get_handle(scrn->base.pscreen,
                                           buffer->texture, &whandle,
                                           usage);
   buffer_fd = whandle.handle;
   buffer->pitch = whandle.stride;
   xcb_dri3_pixmap_from_buffer(scrn->conn,
                               (pixmap = xcb_generate_id(scrn->conn)),
                               scrn->drawable,
                               0,
                               scrn->width, scrn->height, buffer->pitch,
                               scrn->depth, 32,
                               buffer_fd);
   xcb_dri3_fence_from_fd(scrn->conn,
                          pixmap,
                          (sync_fence = xcb_generate_id(scrn->conn)),
                          false,
                          fence_fd);

   buffer->pixmap = pixmap;
   buffer->sync_fence = sync_fence;
   buffer->shm_fence = shm_fence;
   buffer->width = scrn->width;
   buffer->height = scrn->height;

   xshmfence_trigger(buffer->shm_fence);

   return buffer;

unmap_shm:
   xshmfence_unmap_shm(shm_fence);
close_fd:
   close(fence_fd);
free_buffer:
   FREE(buffer);
   return NULL;
}
Exemple #3
0
////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Error code
///
////////////////////////////////////////////////////////////
int main()
{
    // Open a connection with the X server
    Display* display = XOpenDisplay(NULL);
    if (!display)
        return EXIT_FAILURE;

    // Get the XCB connection for the opened display.
    xcb_connection_t* xcbConnection = XGetXCBConnection(display);

    if (!xcbConnection)
    {
        sf::err() << "Failed to get the XCB connection for opened display." << std::endl;
        return EXIT_FAILURE;
    }

    // Get XCB screen.
    const xcb_setup_t* xcbSetup = xcb_get_setup(xcbConnection);
    xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(xcbSetup);
    xcb_screen_t* screen = xcbScreenIter.data;

    if (!screen)
    {
        sf::err() << "Failed to get the XCB screen." << std::endl;
        return EXIT_FAILURE;
    }

    // Generate the XCB window IDs.
    xcb_window_t rootWindowId = xcb_generate_id(xcbConnection);
    xcb_window_t view1WindowId = xcb_generate_id(xcbConnection);
    xcb_window_t view2WindowId = xcb_generate_id(xcbConnection);

    // Create the root window with a black background.
    uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t attributes[2] = {screen->black_pixel, XCB_EVENT_MASK_KEY_PRESS};

    xcb_create_window(xcbConnection,
                      XCB_COPY_FROM_PARENT,
                      rootWindowId,
                      screen->root,
                      0, 0, 650, 330,
                      0,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      screen->root_visual,
                      mask, attributes);

    // Create windows for the SFML views.
    xcb_create_window(xcbConnection,
                      XCB_COPY_FROM_PARENT,
                      view1WindowId,
                      rootWindowId,
                      10, 10, 310, 310,
                      0,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      screen->root_visual,
                      mask, attributes);

    xcb_create_window(xcbConnection,
                      XCB_COPY_FROM_PARENT,
                      view2WindowId,
                      rootWindowId,
                      330, 10, 310, 310,
                      0,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      screen->root_visual,
                      mask, attributes);

    // Map windows to screen.
    xcb_map_window(xcbConnection, rootWindowId);
    xcb_map_window(xcbConnection, view1WindowId);
    xcb_map_window(xcbConnection, view2WindowId);

    // Flush commands.
    xcb_flush(xcbConnection);

    // Create our SFML views
    sf::Window sfmlView1(view1WindowId);
    sf::Window sfmlView2(view2WindowId);

    // Create a clock for measuring elapsed time
    sf::Clock clock;

    // Initialize our views
    initialize(sfmlView1);
    initialize(sfmlView2);

    // Start the event loop
    bool running = true;
    xcb_generic_event_t* event = NULL;

    while (running)
    {
        while ((event = xcb_poll_for_event(xcbConnection)))
        {
            running = false;
        }

        // Draw something into our views
        draw(sfmlView1, clock.getElapsedTime().asSeconds());
        draw(sfmlView2, clock.getElapsedTime().asSeconds() * 0.3f);

        // Display the views on screen
        sfmlView1.display();
        sfmlView2.display();
    }

    return EXIT_SUCCESS;
}
/** dri3_get_pixmap_buffer
 *
 * Get the DRM object for a pixmap from the X server and
 * wrap that with a __DRIimage structure using createImageFromFds
 */
static struct loader_dri3_buffer *
dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
                       enum loader_dri3_buffer_type buffer_type,
                       struct loader_dri3_drawable *draw)
{
   int                                  buf_id = loader_dri3_pixmap_buf_id(buffer_type);
   struct loader_dri3_buffer            *buffer = draw->buffers[buf_id];
   xcb_drawable_t                       pixmap;
   xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
   xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
   xcb_sync_fence_t                     sync_fence;
   struct xshmfence                     *shm_fence;
   int                                  fence_fd;

   if (buffer)
      return buffer;

   pixmap = draw->drawable;

   buffer = calloc(1, sizeof *buffer);
   if (!buffer)
      goto no_buffer;

   fence_fd = xshmfence_alloc_shm();
   if (fence_fd < 0)
      goto no_fence;
   shm_fence = xshmfence_map_shm(fence_fd);
   if (shm_fence == NULL) {
      close (fence_fd);
      goto no_fence;
   }

   xcb_dri3_fence_from_fd(draw->conn,
                          pixmap,
                          (sync_fence = xcb_generate_id(draw->conn)),
                          false,
                          fence_fd);

   bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap);
   bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie, NULL);
   if (!bp_reply)
      goto no_image;

   buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format,
                                            draw->dri_screen, draw->ext->image,
                                            buffer);
   if (!buffer->image)
      goto no_image;

   buffer->pixmap = pixmap;
   buffer->own_pixmap = false;
   buffer->width = bp_reply->width;
   buffer->height = bp_reply->height;
   buffer->buffer_type = buffer_type;
   buffer->shm_fence = shm_fence;
   buffer->sync_fence = sync_fence;

   draw->buffers[buf_id] = buffer;

   free(bp_reply);

   return buffer;

no_image:
   free(bp_reply);
   xcb_sync_destroy_fence(draw->conn, sync_fence);
   xshmfence_unmap_shm(shm_fence);
no_fence:
   free(buffer);
no_buffer:
   return NULL;
}
/** loader_dri3_update_drawable
 *
 * Called the first time we use the drawable and then
 * after we receive present configure notify events to
 * track the geometry of the drawable
 */
static int
dri3_update_drawable(__DRIdrawable *driDrawable,
                     struct loader_dri3_drawable *draw)
{
   if (draw->first_init) {
      xcb_get_geometry_cookie_t                 geom_cookie;
      xcb_get_geometry_reply_t                  *geom_reply;
      xcb_void_cookie_t                         cookie;
      xcb_generic_error_t                       *error;
      xcb_present_query_capabilities_cookie_t   present_capabilities_cookie;
      xcb_present_query_capabilities_reply_t    *present_capabilities_reply;

      draw->first_init = false;

      /* Try to select for input on the window.
       *
       * If the drawable is a window, this will get our events
       * delivered.
       *
       * Otherwise, we'll get a BadWindow error back from this request which
       * will let us know that the drawable is a pixmap instead.
       */

      draw->eid = xcb_generate_id(draw->conn);
      cookie =
         xcb_present_select_input_checked(draw->conn, draw->eid, draw->drawable,
                                          XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
                                          XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
                                          XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);

      present_capabilities_cookie =
         xcb_present_query_capabilities(draw->conn, draw->drawable);

      /* Create an XCB event queue to hold present events outside of the usual
       * application event queue
       */
      draw->special_event = xcb_register_for_special_xge(draw->conn,
                                                         &xcb_present_id,
                                                         draw->eid,
                                                         draw->stamp);
      geom_cookie = xcb_get_geometry(draw->conn, draw->drawable);

      geom_reply = xcb_get_geometry_reply(draw->conn, geom_cookie, NULL);

      if (!geom_reply)
         return false;

      draw->width = geom_reply->width;
      draw->height = geom_reply->height;
      draw->depth = geom_reply->depth;
      draw->vtable->set_drawable_size(draw, draw->width, draw->height);

      free(geom_reply);

      draw->is_pixmap = false;

      /* Check to see if our select input call failed. If it failed with a
       * BadWindow error, then assume the drawable is a pixmap. Destroy the
       * special event queue created above and mark the drawable as a pixmap
       */

      error = xcb_request_check(draw->conn, cookie);

      present_capabilities_reply =
          xcb_present_query_capabilities_reply(draw->conn,
                                               present_capabilities_cookie,
                                               NULL);

      if (present_capabilities_reply) {
         draw->present_capabilities = present_capabilities_reply->capabilities;
         free(present_capabilities_reply);
      } else
         draw->present_capabilities = 0;

      if (error) {
         if (error->error_code != BadWindow) {
            free(error);
            return false;
         }
         draw->is_pixmap = true;
         xcb_unregister_for_special_event(draw->conn, draw->special_event);
         draw->special_event = NULL;
      }
   }
   dri3_flush_present_events(draw);
   return true;
}
Exemple #6
0
int main(int arg, char **argv)
{
	srand(time(NULL));
	xcb_connection_t *connection = xcb_connect(NULL, NULL);

	xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;

	xcb_colormap_t colormap = screen->default_colormap;

	xcb_drawable_t window = xcb_generate_id(connection);
	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	uint32_t values[] = {screen->black_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS};
	xcb_create_window(connection,
			/*screen->root_depth,*/
			24,
			window,
			screen->root,
			0, 0,
			WIDTH, HEIGHT,
			1,
			XCB_WINDOW_CLASS_INPUT_OUTPUT,
			screen->root_visual,
			mask, values);

	xcb_pixmap_t pixmap = xcb_generate_id(connection);
	xcb_create_pixmap(connection,
			24,
			pixmap,
			window,
			WIDTH, HEIGHT);

	uint8_t *img = malloc(WIDTH * HEIGHT * 4);

	uint8_t *limg = img;
	/*for (int y = 0; y < HEIGHT; y++)*/
	/*for (int x = 0; x < WIDTH; x++) {*/
	/**(limg++) = 128;*/
	/**(limg++) = 128;*/
	/**(limg++) = 128;*/
	/*limg++;*/
	/*}*/
	perlin(img, WIDTH, HEIGHT);

	xcb_image_t *image = xcb_image_create(WIDTH, HEIGHT,
			XCB_IMAGE_FORMAT_Z_PIXMAP,
			8, 24, 32,
			0,
			/*xcb_get_setup(connection)->image_byte_order,*/
			XCB_IMAGE_ORDER_MSB_FIRST,
			XCB_IMAGE_ORDER_LSB_FIRST,
			img,
			WIDTH * HEIGHT * 4,
			img);

	xcb_gcontext_t gc = xcb_generate_id(connection);
	xcb_create_gc(connection,
			gc,
			pixmap,
			0, NULL);

	xcb_image_put(connection, pixmap, gc, image, 0, 0, 0);

	xif_write(image, "test.xif");

	xcb_map_window(connection, window);
	xcb_flush(connection);

	xcb_generic_event_t *event;
	xcb_expose_event_t *expose;
	while ((event = xcb_wait_for_event(connection))) {
		switch (event->response_type & ~0x80) {
			case XCB_EXPOSE:
					expose = (xcb_expose_event_t *)event;
					xcb_copy_area(connection,
							pixmap,
							window,
							gc,
							expose->x, expose->y,
							expose->x, expose->y,
							expose->width, expose->height);
					xcb_flush(connection);
					break;
			case XCB_BUTTON_PRESS:
					goto end;
					break;
			default:
					break;
		}
		free(event);
	}
end:

	xcb_free_pixmap(connection, pixmap);
	xcb_disconnect(connection);

	xcb_image_destroy(image);

	return 0;
}
Exemple #7
0
/**
 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
 */
static _EGLSurface *
dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
		    _EGLConfig *conf, EGLNativeWindowType native_window,
		    const EGLint *attrib_list)
{
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
   struct dri2_egl_surface *dri2_surf;
   xcb_get_geometry_cookie_t cookie;
   xcb_get_geometry_reply_t *reply;
   xcb_screen_iterator_t s;
   xcb_generic_error_t *error;
   xcb_drawable_t window = (uintptr_t )native_window;

   (void) drv;

   dri2_surf = malloc(sizeof *dri2_surf);
   if (!dri2_surf) {
      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
      return NULL;
   }
   
   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
      goto cleanup_surf;

   dri2_surf->region = XCB_NONE;
   if (type == EGL_PBUFFER_BIT) {
      dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
      s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
      xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
			dri2_surf->drawable, s.data->root,
			dri2_surf->base.Width, dri2_surf->base.Height);
   } else {
      dri2_surf->drawable = window;
   }

   if (dri2_dpy->dri2) {
      dri2_surf->dri_drawable = 
	 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
					       type == EGL_WINDOW_BIT ?
					       dri2_conf->dri_double_config : 
					       dri2_conf->dri_single_config,
					       dri2_surf);
   } else {
      assert(dri2_dpy->swrast);
      dri2_surf->dri_drawable = 
	 (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
						 dri2_conf->dri_double_config,
						 dri2_surf);
   }

   if (dri2_surf->dri_drawable == NULL) {
      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
      goto cleanup_pixmap;
   }
   
   if (dri2_dpy->dri2) {
      xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
   } else {
      swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE));
   }

   if (type != EGL_PBUFFER_BIT) {
      cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
      reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
      if (reply == NULL || error != NULL) {
	 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
	 free(error);
	 goto cleanup_dri_drawable;
      }

      dri2_surf->base.Width = reply->width;
      dri2_surf->base.Height = reply->height;
      free(reply);
   }

   /* we always copy the back buffer to front */
   dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE;

   return &dri2_surf->base;

 cleanup_dri_drawable:
   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
 cleanup_pixmap:
   if (type == EGL_PBUFFER_BIT)
      xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
 cleanup_surf:
   free(dri2_surf);

   return NULL;
}
Exemple #8
0
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) {
    xcb_pixmap_t bitmap;
    xcb_pixmap_t mask;
    xcb_cursor_t cursor;

    unsigned char *curs_bits;
    unsigned char *mask_bits;
    int curs_w, curs_h;

    switch (choice) {
        case CURS_NONE:
            curs_bits = curs_invisible_bits;
            mask_bits = curs_invisible_bits;
            curs_w = curs_invisible_width;
            curs_h = curs_invisible_height;
            break;
        case CURS_WIN:
            curs_bits = curs_windows_bits;
            mask_bits = mask_windows_bits;
            curs_w = curs_windows_width;
            curs_h = curs_windows_height;
            break;
        case CURS_DEFAULT:
        default:
            return XCB_NONE; /* XCB_NONE is xcb's way of saying "don't change the cursor" */
    }

    bitmap = xcb_create_pixmap_from_bitmap_data(conn,
                                                win,
                                                curs_bits,
                                                curs_w,
                                                curs_h,
                                                1,
                                                screen->white_pixel,
                                                screen->black_pixel,
                                                NULL);

    mask = xcb_create_pixmap_from_bitmap_data(conn,
                                              win,
                                              mask_bits,
                                              curs_w,
                                              curs_h,
                                              1,
                                              screen->white_pixel,
                                              screen->black_pixel,
                                              NULL);

    cursor = xcb_generate_id(conn);

    xcb_create_cursor(conn,
                      cursor,
                      bitmap,
                      mask,
                      65535, 65535, 65535,
                      0, 0, 0,
                      0, 0);

    xcb_free_pixmap(conn, bitmap);
    xcb_free_pixmap(conn, mask);

    return cursor;
}
Exemple #9
0
int main()
{
	/* Open the connection to the X server */
	xcb_connection_t *connection = xcb_connect(NULL, NULL);

	/* Get the first screen */
	xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;

	/* Create the window */
	xcb_window_t window = xcb_generate_id(connection);

	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	uint32_t values[2] = { screen->white_pixel,
		XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
		    XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
		    XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
		    XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE
	};

	xcb_create_window(connection, 0,			/* depth               */
			  window, screen->root,				/* parent window       */
			  0, 0,								/* x, y                */
			  150, 150,							/* width, height       */
			  10,								/* border_width        */
			  XCB_WINDOW_CLASS_INPUT_OUTPUT,	/* class               */
			  screen->root_visual,				/* visual              */
			  mask, values);					/* masks */

	/* Map the window on the screen */
	xcb_map_window(connection, window);

	xcb_flush(connection);

	xcb_generic_event_t *event;
	while ((event = xcb_wait_for_event(connection))) {
		switch (event->response_type & ~0x80) {
		case XCB_EXPOSE:{
				xcb_expose_event_t *expose = (xcb_expose_event_t *) event;

				printf("Window %"PRIu32" exposed. Region to be redrawn at location (%"PRIu16", %"PRIu16"), "
						"with dimension (%"PRIu16", %"PRIu16")\n",
						expose->window, expose->x, expose->y, expose->width, expose->height);
				break;
			} 
		case XCB_BUTTON_PRESS:{
				xcb_button_press_event_t *bp = (xcb_button_press_event_t *) event;
				print_modifiers(bp->state);

				switch (bp->detail) {
				case 4:
					printf("Wheel Button up in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")\n",
							bp->event, bp->event_x, bp->event_y);
					break;
				case 5:
					printf("Wheel Button down in window %"PRIu32", at coordinates (%"PRIi16", %"PRIi16")\n",
							bp->event, bp->event_x, bp->event_y);
					break;
				default:
					printf("Button %"PRIu8"pressed in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")\n",
							bp->detail, bp->event, bp->event_x, bp->event_y);
					break;
				}
				break;
			}
		case XCB_BUTTON_RELEASE:{
				xcb_button_release_event_t *br = (xcb_button_release_event_t *) event;
				print_modifiers(br->state);

				printf("Button %"PRIu8"released in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")\n",
						br->detail, br->event, br->event_x, br->event_y);
				break;
			}
		case XCB_MOTION_NOTIFY:{
				xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *) event;

				printf("Mouse moved in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")\n",
						motion->event, motion->event_x, motion->event_y);
				break;
			}
		case XCB_ENTER_NOTIFY:{
				xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *) event;

				printf("Mouse entered window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")\n",
						enter->event, enter->event_x, enter->event_y);
				break;
			}
		case XCB_LEAVE_NOTIFY:{
				xcb_leave_notify_event_t *leave = (xcb_leave_notify_event_t *) event;

				printf("Mouse left window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")\n",
						leave->event, leave->event_x, leave->event_y);
				break;
			} 
		case XCB_KEY_PRESS:{
				xcb_key_press_event_t *kp = (xcb_key_press_event_t *) event;
				print_modifiers(kp->state);

				printf("Key pressed in window %"PRIu32"\n", kp->event);
				break;
			}
		case XCB_KEY_RELEASE:{
				xcb_key_release_event_t *kr = (xcb_key_release_event_t *) event;
				print_modifiers(kr->state);

				printf("Key released in window %"PRIu32"\n", kr->event);
				break;
			}
		default:
			/* Unknown event type, ignore it */
			printf("Unknown event: %"PRIu8"\n", event->response_type);
			break;
		}

		free(event);
	}

	return 0;
}
Exemple #10
0
//Output
X11Output::X11Output(X11Backend& backend, unsigned int id, const nytl::Vec2i& pos,
		const nytl::Vec2ui& size) : Output(backend.compositor(), id, pos, size), backend_(&backend)
{
    xcb_connection_t* connection = backend.xConnection();
    xcb_screen_t* screen = backend.xScreen();

    unsigned int mask = XCB_CW_EVENT_MASK;
    unsigned int values = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
		XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS |
        XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
		XCB_EVENT_MASK_FOCUS_CHANGE;

    xWindow_ = xcb_generate_id(connection);
    xcb_create_window(connection, XCB_COPY_FROM_PARENT, xWindow_, screen->root, 0, 0, size_.x,
			size_.y ,10, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, &values);

    if(!xWindow_)
    {
        throw std::runtime_error("could not create xcb window");
        return;
    }

    xcb_change_property(connection, XCB_PROP_MODE_REPLACE, xWindow_, atoms::protocols,
			XCB_ATOM_ATOM, 32, 1, &atoms::deleteWindow);

    //cant be resized
    xcb_size_hints_t sizeHints;

    sizeHints.max_width = size_.x;
    sizeHints.max_height = size_.y;

    sizeHints.min_width = size_.x;
    sizeHints.min_height = size_.y;

    sizeHints.flags = XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_P_MAX_SIZE;

    xcb_icccm_set_wm_size_hints(connection, xWindow_, XCB_ATOM_WM_NORMAL_HINTS, &sizeHints);

    //no mouse cursor
    xcb_pixmap_t cursorPixmap = xcb_generate_id(connection);
    xcb_create_pixmap(connection, 1, cursorPixmap, xWindow_, 1, 1);

    xcb_cursor_t hiddenCursor = xcb_generate_id(connection);

    xcb_create_cursor(connection, hiddenCursor, cursorPixmap, cursorPixmap,
			0, 0, 0, 0, 0, 0, 0, 0);
    xcb_free_pixmap(connection, cursorPixmap);

    xcb_change_window_attributes(connection, xWindow_, XCB_CW_CURSOR, &hiddenCursor);
    xcb_map_window(connection, xWindow_);

	//EGL
	if(!backend.eglContext())
	{
		throw std::runtime_error("x11Output::x11Output: backend ha no valid eglcontext");
		return;
	}

	eglSurface_ = backend.eglContext()->createSurface(xWindow_);
	if(!eglSurface_)
	{
		throw std::runtime_error("x11Output::x11Output: failed to create egl surface");
		return;
	}

	drawContext_ = std::make_unique<ny::GlDrawContext>();
	if(!drawContext_)
	{
		throw std::runtime_error("x11Output::x11Output: failed to create ny::GlesDC");
		return;
	}
}
Exemple #11
0
xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
{
    xcb_cursor_t cursor = 0;
    xcb_connection_t *conn = xcb_connection();

    if (cshape == Qt::BlankCursor) {
        xcb_pixmap_t cp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
                                                             1, 0, 0, 0);
        xcb_pixmap_t mp = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(), cur_blank_bits, 16, 16,
                                                             1, 0, 0, 0);
        cursor = xcb_generate_id(conn);
        xcb_create_cursor(conn, cursor, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
    } else if (cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor) {
        int i = (cshape - Qt::SizeVerCursor) * 2;
        xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                             const_cast<uint8_t*>(cursor_bits16[i]),
                                                             16, 16, 1, 0, 0, 0);
        xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                              const_cast<uint8_t*>(cursor_bits16[i + 1]),
                                                              16, 16, 1, 0, 0, 0);
        cursor = xcb_generate_id(conn);
        xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
    } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
               || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
        int i = (cshape - Qt::SplitVCursor) * 2;
        xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                             const_cast<uint8_t*>(cursor_bits32[i]),
                                                             32, 32, 1, 0, 0, 0);
        xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                              const_cast<uint8_t*>(cursor_bits32[i + 1]),
                                                              32, 32, 1, 0, 0, 0);
        int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
                  || cshape == Qt::BusyCursor) ? 0 : 16;
        cursor = xcb_generate_id(conn);
        xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, hs, hs);
    } else if (cshape == Qt::ForbiddenCursor) {
        int i = (cshape - Qt::ForbiddenCursor) * 2;
        xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                             const_cast<uint8_t*>(cursor_bits20[i]),
                                                             20, 20, 1, 0, 0, 0);
        xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                              const_cast<uint8_t*>(cursor_bits20[i + 1]),
                                                              20, 20, 1, 0, 0, 0);
        cursor = xcb_generate_id(conn);
        xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 10, 10);
    } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
        bool open = cshape == Qt::OpenHandCursor;
        xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                             const_cast<uint8_t*>(open ? openhand_bits : closedhand_bits),
                                                             16, 16, 1, 0, 0, 0);
        xcb_pixmap_t pmm = xcb_create_pixmap_from_bitmap_data(conn, m_screen->root(),
                                                             const_cast<uint8_t*>(open ? openhandm_bits : closedhandm_bits),
                                                             16, 16, 1, 0, 0, 0);
        cursor = xcb_generate_id(conn);
        xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
    } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
               || cshape == Qt::DragLinkCursor) {
        QImage image = QGuiApplicationPrivate::instance()->getPixmapCursor(static_cast<Qt::CursorShape>(cshape)).toImage();
        if (!image.isNull()) {
            xcb_pixmap_t pm = qt_xcb_XPixmapFromBitmap(m_screen, image);
            xcb_pixmap_t pmm = qt_xcb_XPixmapFromBitmap(m_screen, image.createAlphaMask());
            cursor = xcb_generate_id(conn);
            xcb_create_cursor(conn, cursor, pm, pmm, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 8, 8);
            xcb_free_pixmap(conn, pm);
            xcb_free_pixmap(conn, pmm);
        }
    }

    return cursor;
}
int
main()
{

    hhxcb_state state = {};
    hhxcb_get_binary_name(&state);

    char source_game_code_library_path[HHXCB_STATE_FILE_NAME_LENGTH];
    char *game_code_filename = (char *) _HHXCB_QUOTE(GAME_CODE_FILENAME);
    hhxcb_build_full_filename(&state, game_code_filename,
            sizeof(source_game_code_library_path),
            source_game_code_library_path);
    hhxcb_game_code game_code = {};
    hhxcb_load_game(&game_code, source_game_code_library_path);

    hhxcb_context context = {};

    /* Open the connection to the X server. Use the DISPLAY environment variable */
    int screenNum;
    context.connection = xcb_connect (NULL, &screenNum);

    context.key_symbols = xcb_key_symbols_alloc(context.connection);

    /*
     * TODO(nbm): This is X-wide, so it really isn't a good option in reality.
     * We have to be careful and clean up at the end.  If we crash, auto-repeat
     * is left off.
     */
    {
        uint32_t values[1] = {XCB_AUTO_REPEAT_MODE_OFF};
        xcb_change_keyboard_control(context.connection, XCB_KB_AUTO_REPEAT_MODE, values);
    }

    load_atoms(&context);
    context.setup = xcb_get_setup(context.connection);
    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(context.setup);
    xcb_screen_t *screen = iter.data;
    context.fmt = hhxcb_find_format(&context, 32, 24, 32);

    int monitor_refresh_hz = 60;
    real32 game_update_hz = (monitor_refresh_hz / 2.0f); // Should almost always be an int...
    long target_nanoseconds_per_frame = (1000 * 1000 * 1000) / game_update_hz;


    uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t values[2] =
    {
        0x0000ffff, //screen->black_pixel,
        0
            | XCB_EVENT_MASK_POINTER_MOTION
            | XCB_EVENT_MASK_KEY_PRESS
            | XCB_EVENT_MASK_KEY_RELEASE
            ,
    };

#define START_WIDTH 960
#define START_HEIGHT 540

    context.window = xcb_generate_id(context.connection);
	// NOTE: changed to not have a border width, so the min/max/close
	// buttons align on compiz, maybe other window managers
    xcb_create_window(context.connection, XCB_COPY_FROM_PARENT, context.window,
            screen->root, 0, 0, START_WIDTH, START_HEIGHT, 0,
            XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values);

    xcb_icccm_set_wm_name(context.connection, context.window, XCB_ATOM_STRING,
            8, strlen("hello"), "hello");

    load_and_set_cursor(&context);

    xcb_map_window(context.connection, context.window);
    xcb_atom_t protocols[] =
    {
        context.wm_delete_window,
    };
    xcb_icccm_set_wm_protocols(context.connection, context.window,
            context.wm_protocols, 1, protocols);

    xcb_size_hints_t hints = {};
    xcb_icccm_size_hints_set_max_size(&hints, START_WIDTH, START_HEIGHT);
    xcb_icccm_size_hints_set_min_size(&hints, START_WIDTH, START_HEIGHT);
    xcb_icccm_set_wm_size_hints(context.connection, context.window,
            XCB_ICCCM_WM_STATE_NORMAL, &hints);

    hhxcb_offscreen_buffer buffer = {};
    hhxcb_resize_backbuffer(&context, &buffer, START_WIDTH, START_HEIGHT);

    xcb_flush(context.connection);

    hhxcb_sound_output sound_output = {};
    sound_output.samples_per_second = 48000;
    sound_output.bytes_per_sample = sizeof(int16) * 2;
    sound_output.secondary_buffer_size = sound_output.samples_per_second * sound_output.bytes_per_sample;
    hhxcb_init_alsa(&context, &sound_output);

    int16 *sample_buffer = (int16 *)malloc(sound_output.secondary_buffer_size);

    thread_context t = {};

    game_memory m = {};
    m.PermanentStorageSize = 256 * 1024 * 1024;
    m.TransientStorageSize = 256 * 1024 * 1024;
    state.total_size = m.PermanentStorageSize + m.TransientStorageSize;
    state.game_memory_block = calloc(state.total_size, sizeof(uint8));
    m.PermanentStorage = (uint8 *)state.game_memory_block;
    m.TransientStorage =
        (uint8_t *)m.PermanentStorage + m.TransientStorageSize;
#ifdef HANDMADE_INTERNAL
    m.DEBUGPlatformFreeFileMemory = debug_xcb_free_file_memory;
    m.DEBUGPlatformReadEntireFile = debug_xcb_read_entire_file;
    m.DEBUGPlatformWriteEntireFile = debug_xcb_write_entire_file;
#endif

    hhxcb_init_replays(&state);

    bool ending = 0;
    timespec last_counter = {};
    timespec flip_wall_clock = {}; // Actually monotonic clock
    clock_gettime(HHXCB_CLOCK, &last_counter);
    clock_gettime(HHXCB_CLOCK, &flip_wall_clock);

    game_input input[2] = {};
    game_input *new_input = &input[0];
    game_input *old_input = &input[1];

    int64_t next_controller_refresh = 0;

    while(!ending)
    {
        if (last_counter.tv_sec >= next_controller_refresh)
        {
            hhxcb_refresh_controllers(&context);
            next_controller_refresh = last_counter.tv_sec + 1;
        }

        struct stat library_statbuf = {};
        stat(source_game_code_library_path, &library_statbuf);
        if (library_statbuf.st_mtime != game_code.library_mtime)
        {
            hhxcb_unload_game(&game_code);
            hhxcb_load_game(&game_code, source_game_code_library_path);
        }

        new_input->dtForFrame = target_nanoseconds_per_frame / (1024.0 * 1024 * 1024);

        hhxcb_process_events(&context, &state, new_input, old_input);

        if (context.ending_flag)
        {
            break;
        }

		// NOTE: setup game_buffer.Memory upside down and set
		// game_buffer.pitch negative, so the game would fill the
		// backbuffer upside down. XCB doesn't seem to have an
		// option to flip the image.
		
        game_offscreen_buffer game_buffer = {};
        game_buffer.Memory = ((uint8*)buffer.xcb_image->data)+
			(buffer.width*(buffer.height-1)*buffer.bytes_per_pixel);
        game_buffer.Width = buffer.width;
        game_buffer.Height = buffer.height;
        game_buffer.Pitch = -buffer.pitch;

        if (state.recording_index)
        {
            hhxcb_record_input(&state, new_input);
        }
        if (state.playback_index)
        {
            hhxcb_playback_input(&state, new_input);
        }
        if (game_code.UpdateAndRender)
        {
            game_code.UpdateAndRender(&t, &m, new_input, &game_buffer);
            HandleDebugCycleCounter(&m);
        }
	
        game_sound_output_buffer sound_buffer;
        sound_buffer.SamplesPerSecond = sound_output.samples_per_second;
        sound_buffer.SampleCount = sound_output.samples_per_second / 30;
        sound_buffer.Samples = sample_buffer;

        int err, frames;
        snd_pcm_sframes_t delay, avail;
        snd_pcm_avail_delay(context.handle, &avail, &delay);
        if (avail == sound_output.secondary_buffer_size)
        {
            // NOTE(nbm): Full available buffer, starting with ~60ms of silence
            bzero(sample_buffer, sound_buffer.SampleCount * sound_output.bytes_per_sample);
            snd_pcm_writei(context.handle, sample_buffer, sound_buffer.SampleCount);
            snd_pcm_writei(context.handle, sample_buffer, sound_buffer.SampleCount);
            snd_pcm_writei(context.handle, sample_buffer, sound_buffer.SampleCount);
            snd_pcm_writei(context.handle, sample_buffer, sound_buffer.SampleCount);
        }
        else
        {
            uint32 target_available_frames = sound_output.secondary_buffer_size;
            target_available_frames -= (sound_buffer.SampleCount * 1);
            if (avail - target_available_frames < sound_buffer.SampleCount)
            {
                sound_buffer.SampleCount += avail - target_available_frames;
            }
        }
        game_code.GetSoundSamples(&t, &m, &sound_buffer);
        if (sound_buffer.SampleCount > 0) {
            frames = snd_pcm_writei(context.handle, sample_buffer, sound_buffer.SampleCount);

            if (frames < 0)
            {
                frames = snd_pcm_recover(context.handle, frames, 0);
            }
            if (frames < 0) {
                printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
                break;
            }
            if (frames > 0 && frames < sound_buffer.SampleCount)
            {
                printf("Short write (expected %i, wrote %i)\n", sound_buffer.SampleCount, frames);
            }
        }

        xcb_image_put(context.connection, buffer.xcb_pixmap_id,
                buffer.xcb_gcontext_id, buffer.xcb_image, 0, 0, 0);
        xcb_flush(context.connection);
		
        timespec target_counter = {};
        target_counter.tv_sec = last_counter.tv_sec;
        target_counter.tv_nsec = last_counter.tv_nsec + target_nanoseconds_per_frame;
        if (target_counter.tv_nsec > (1000 * 1000 * 1000))
        {
            target_counter.tv_sec++;
            target_counter.tv_nsec %= (1000 * 1000 * 1000);
        }

        timespec work_counter = {};
        clock_gettime(HHXCB_CLOCK, &work_counter);

        bool32 might_need_sleep = 0;
        if (work_counter.tv_sec < target_counter.tv_sec)
        {
            might_need_sleep = 1;
        }
        else if ((work_counter.tv_sec == target_counter.tv_sec) && (work_counter.tv_nsec < target_counter.tv_nsec))
        {
            might_need_sleep = 1;
        }
        if (might_need_sleep) {
            timespec sleep_counter = {};
            sleep_counter.tv_nsec = target_counter.tv_nsec - work_counter.tv_nsec;
            if (sleep_counter.tv_nsec < 0) {
                sleep_counter.tv_nsec += (1000 * 1000 * 1000);
            }
            // To closest ms
            sleep_counter.tv_nsec -= sleep_counter.tv_nsec % (1000 * 1000);
            if (sleep_counter.tv_nsec > 0) {
                timespec remaining_sleep_counter = {};
                nanosleep(&sleep_counter, &remaining_sleep_counter);
            }
            else
            {
                // TODO(nbm): Log missed sleep
            }
        }

        timespec spin_counter = {};
        clock_gettime(HHXCB_CLOCK, &spin_counter);
        while (spin_counter.tv_sec <= target_counter.tv_sec && spin_counter.tv_nsec < target_counter.tv_nsec) {
            clock_gettime(HHXCB_CLOCK, &spin_counter);
        }

        timespec end_counter = {};
        clock_gettime(HHXCB_CLOCK, &end_counter);

        long ns_per_frame = end_counter.tv_nsec - last_counter.tv_nsec;
        if (ns_per_frame < 0)
        {
            ns_per_frame += (1000 * 1000 * 1000) * (end_counter.tv_sec - last_counter.tv_sec);
        }
        last_counter = end_counter;
        real32 ms_per_frame = ns_per_frame / (1000 * 1000.0);

        xcb_copy_area(context.connection, buffer.xcb_pixmap_id, context.window,
                buffer.xcb_gcontext_id, 0,0, 0, 0, buffer.xcb_image->width,
                buffer.xcb_image->height);
        xcb_flush(context.connection);

        game_input *temp_input = new_input;
        new_input = old_input;
        old_input = temp_input;
    }

    snd_pcm_close(context.handle);

    // NOTE(nbm): Since auto-repeat seems to be a X-wide thing, let's be nice
    // and return it to where it was before?
    {
        uint32_t values[1] = {XCB_AUTO_REPEAT_MODE_DEFAULT};
        xcb_change_keyboard_control(context.connection, XCB_KB_AUTO_REPEAT_MODE, values);
    }

    xcb_flush(context.connection);
    xcb_disconnect(context.connection);
}
Exemple #13
0
int main ()
{
  xcb_screen_iterator_t screen_iter;
  xcb_connection_t     *c;
  const xcb_setup_t    *setup;
  xcb_screen_t         *screen;
  xcb_generic_event_t  *e;
  xcb_generic_error_t  *error;
  xcb_void_cookie_t     cookie_window;
  xcb_void_cookie_t     cookie_map;
  xcb_window_t          window;
  uint32_t              mask;
  uint32_t              values[2];
  int                   screen_number;
  uint8_t               is_hand = 0;

  /* getting the connection */
  c = xcb_connect (NULL, &screen_number);
  if (!c) {
    fprintf (stderr, "ERROR: can't connect to an X server\n");
    return -1;
  }

  /* getting the current screen */
  setup = xcb_get_setup (c);

  screen = NULL;
  screen_iter = xcb_setup_roots_iterator (setup);
  for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
    if (screen_number == 0)
      {
        screen = screen_iter.data;
        break;
      }
  if (!screen) {
    fprintf (stderr, "ERROR: can't get the current screen\n");
    xcb_disconnect (c);
    return -1;
  }

  /* creating the window */
  window = xcb_generate_id (c);
  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
  values[0] = screen->white_pixel;
  values[1] =
    XCB_EVENT_MASK_KEY_RELEASE |
    XCB_EVENT_MASK_BUTTON_PRESS |
    XCB_EVENT_MASK_EXPOSURE |
    XCB_EVENT_MASK_POINTER_MOTION;
  cookie_window = xcb_create_window_checked (c,
                                             screen->root_depth,
                                             window, screen->root,
                                             20, 200, WIDTH, HEIGHT,
                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                             screen->root_visual,
                                             mask, values);
  cookie_map = xcb_map_window_checked (c, window);

  /* error managing */
  error = xcb_request_check (c, cookie_window);
  if (error) {
    fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
    xcb_disconnect (c);
    return -1;
  }
  error = xcb_request_check (c, cookie_map);
  if (error) {
    fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
    xcb_disconnect (c);
    return -1;
  }

  cursor_set (c, screen, window, 68);

  xcb_flush(c);

  while (1) {
    e = xcb_poll_for_event(c);
    if (e) {
      switch (e->response_type & ~0x80) {
      case XCB_EXPOSE: {
        char *text;

        text = "click here to change cursor";
        button_draw (c, screen, window,
                     (WIDTH - 7 * strlen(text)) / 2,
                     (HEIGHT - 16) / 2, text);

        text = "Press ESC key to exit...";
        text_draw (c, screen, window, 10, HEIGHT - 10, text);
        break;
      }
      case XCB_BUTTON_PRESS: {
        xcb_button_press_event_t *ev;
        int                       length;

        ev = (xcb_button_press_event_t *)e;
        length = strlen ("click here to change cursor");

        if ((ev->event_x >= (WIDTH - 7 * length) / 2) &&
            (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) &&
            (ev->event_y >= (HEIGHT - 16) / 2 - 19) &&
            (ev->event_y <= ((HEIGHT - 16) / 2)))
          is_hand = 1 - is_hand;

        is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68);
      }
      case XCB_KEY_RELEASE: {
        xcb_key_release_event_t *ev;

        ev = (xcb_key_release_event_t *)e;

        switch (ev->detail) {
          /* ESC */
        case 9:
          free (e);
          xcb_disconnect (c);
          return 0;
        }
      }
      }
      free (e);
    }
  }

  return 0;
}
/** Get the current X selection buffer.
 * \param L The Lua VM state.
 * \return The number of elements pushed on stack.
 * \luastack
 * \lreturn A string with the current X selection buffer.
 */
int
luaA_selection_get(lua_State *L)
{
    if(selection_window == XCB_NONE)
    {
        xcb_screen_t *screen = xutil_screen_get(globalconf.connection, globalconf.default_screen);
        uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
        uint32_t values[] = { screen->black_pixel, 1, XCB_EVENT_MASK_PROPERTY_CHANGE };

        selection_window = xcb_generate_id(globalconf.connection);

        xcb_create_window(globalconf.connection, screen->root_depth, selection_window, screen->root,
                          0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT, screen->root_visual,
                          mask, values);
    }

    xcb_convert_selection(globalconf.connection, selection_window,
                          XCB_ATOM_PRIMARY, UTF8_STRING, XSEL_DATA, globalconf.timestamp);
    xcb_flush(globalconf.connection);

    xcb_generic_event_t *event;

    while(true)
    {
        event = xcb_wait_for_event(globalconf.connection);

        if(!event)
            return 0;

        if(XCB_EVENT_RESPONSE_TYPE(event) != XCB_SELECTION_NOTIFY)
        {
            /* \todo Eventually, this may be rewritten with adding a static
             * buffer, then a event handler for XCB_SELECTION_NOTIFY, then call
             * xcb_event_poll_for_event_loop() and awesome_refresh(),
             * then check if some static buffer has been filled with data.
             * If yes, that'd be the xsel data, otherwise, re-loop.
             * Anyway that's still brakes the socket or D-Bus, so maybe using
             * ev_loop() would be even better.
             */
            event_handle(event);
            p_delete(&event);
            awesome_refresh();
            continue;
        }

        xcb_selection_notify_event_t *event_notify =
            (xcb_selection_notify_event_t *) event;

        if(event_notify->selection == XCB_ATOM_PRIMARY
           && event_notify->property != XCB_NONE)
        {
            xcb_icccm_get_text_property_reply_t prop;
            xcb_get_property_cookie_t cookie =
                xcb_icccm_get_text_property(globalconf.connection,
                                            event_notify->requestor,
                                            event_notify->property);

            if(xcb_icccm_get_text_property_reply(globalconf.connection,
                                                 cookie, &prop, NULL))
            {
                lua_pushlstring(L, prop.name, prop.name_len);

                xcb_icccm_get_text_property_reply_wipe(&prop);

                xcb_delete_property(globalconf.connection,
                                    event_notify->requestor,
                                    event_notify->property);

                p_delete(&event);

                return 1;
            }
            else
                break;
        }
    }

    p_delete(&event);
    return 0;
}
Exemple #15
0
int main(int argc, char **argv)
{
	xcb_connection_t *connection = xcb_connect(NULL, NULL);

	xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;

	uint32_t mask = XCB_CW_BACK_PIXEL;
	uint32_t values[] = {screen->black_pixel};

	xcb_drawable_t window = xcb_generate_id(connection);
	xcb_create_window(connection,
			24,
			window,
			screen->root,
			0, 0,
			WIDTH, HEIGHT,
			1,
			XCB_WINDOW_CLASS_INPUT_OUTPUT,
			screen->root_visual,
			mask, values);
	xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window,
			XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
			strlen(argv[0]), argv[0]);

	xcb_pixmap_t pixmap = xcb_generate_id(connection);
	xcb_create_pixmap(connection,
			24,
			pixmap,
			window,
			WIDTH, HEIGHT);

	uint8_t *img = malloc(WIDTH * HEIGHT * 4);
	xcb_image_t *image = xcb_image_create(WIDTH, HEIGHT,
			XCB_IMAGE_FORMAT_Z_PIXMAP,
			8, 24, 32,
			0,
			XCB_IMAGE_ORDER_MSB_FIRST,
			XCB_IMAGE_ORDER_LSB_FIRST,
			img,
			WIDTH * HEIGHT * 4,
			img);

	mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
	values[0] = screen->black_pixel;
	values[1] = 0xFFFFFF;

	xcb_gcontext_t gc = xcb_generate_id(connection);
	xcb_create_gc(connection,
			gc,
			pixmap,
			mask, values);

	xcb_image_put(connection, pixmap, gc, image, 0, 0, 0);

	xcb_map_window(connection, window);
	xcb_flush(connection);

	uint8_t value = 0;

	uint32_t *limg;

	Gol *gol = gol_new(BOARD_WIDTH, BOARD_HEIGHT);
	gol_random(gol, time(NULL));

	while (1) {
		limg = (uint32_t *)image->data;

		for (int i = 0; i < BOARD_WIDTH * BOARD_HEIGHT; i++)
			*(limg++) = gol->buffers[gol->front][i] ? 0x00FFFF00 : 0x00000000;

		xcb_image_put(connection, pixmap, gc, image, 0, 0, 0);

		xcb_copy_area(connection,
				pixmap,
				window,
				gc,
				0, 0,
				0, 0,
				WIDTH, HEIGHT);
		xcb_flush(connection);
		value++;

		gol_simulate(gol);
	}
	return 0;
}
Exemple #16
0
void
x_client_icon::update_wm_hints_icon(void)
{
  xcb_free_pixmap(m_c(), m_wm_hints_icon);
  m_wm_hints_icon = XCB_NONE;

  xcb_generic_error_t * error;

  xcb_get_property_cookie_t c =
    xcb_icccm_get_wm_hints(m_c(), m_x_client.window());
  xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error);

  if (error) {
    std::free(error);

  } else {
    xcb_icccm_wm_hints_t wm_hints;
    xcb_icccm_get_wm_hints_from_reply(&wm_hints, r);

    if (wm_hints.flags & XCB_ICCCM_WM_HINT_ICON_PIXMAP) {
      unsigned int width, height;

      {
        Window root;
        int x, y;
        unsigned int border_width, depth;
        XGetGeometry(m_c.dpy(), wm_hints.icon_pixmap, &root,
            &x, &y, &width, &height, &border_width, &depth);
        m_icon_geometry.first = width;
        m_icon_geometry.second = height;
      }

      xcb_image_t * icon_rgb = xcb_image_get(m_c(), wm_hints.icon_pixmap,
          0, 0, width, height, 0xffffffff, XCB_IMAGE_FORMAT_XY_PIXMAP);

      xcb_image_t * icon_mask;
      if (wm_hints.flags & XCB_ICCCM_WM_HINT_ICON_MASK) {
        icon_mask = xcb_image_get(m_c(), wm_hints.icon_mask,
            0, 0, width, height, 0xffffffff, XCB_IMAGE_FORMAT_XY_PIXMAP);

      } else {
        icon_mask = xcb_image_create_native(
            m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL);
        std::memset(icon_mask->data, 0xff,
                    width * height * (icon_mask->bpp / icon_mask->stride));
      }

      xcb_image_t * icon_rgba = xcb_image_create_native(
          m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL);

      for (std::size_t x = 0; x < width; ++x) {
        for (std::size_t y = 0; y < height; ++y) {
          uint32_t rgba = 0;

          if (xcb_image_get_pixel(icon_mask, x, y)) {
            uint32_t rgb = xcb_image_get_pixel(icon_rgb, x, y);
            uint8_t * s = (uint8_t *)&rgb;
            uint8_t * d = (uint8_t *)&rgba;

            d[0] = s[0];
            d[1] = s[1];
            d[2] = s[2];
            d[3] = 0xff;
          }

          xcb_image_put_pixel(icon_rgba, x, y, rgba);
        }
      }

      m_wm_hints_icon = xcb_generate_id(m_c());
      xcb_create_pixmap(
          m_c(), 32, m_wm_hints_icon, m_c.root_window(), width, height);

      xcb_gcontext_t gc = xcb_generate_id(m_c());
      xcb_create_gc(m_c(), gc, m_wm_hints_icon, 0, NULL);

      xcb_image_put(m_c(), m_wm_hints_icon, gc, icon_rgba, 0, 0, 0);

      xcb_image_destroy(icon_rgb);
      xcb_image_destroy(icon_mask);
      xcb_image_destroy(icon_rgba);
      xcb_free_gc(m_c(), gc);
    }
  }

  if (r) std::free(r);
}
Exemple #17
0
/**
 * Probes and initializes.
 */
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *p_sys = malloc (sizeof (*p_sys));

    if (p_sys == NULL)
        return VLC_ENOMEM;
    demux->p_sys = p_sys;

    /* Connect to X server */
    char *display = var_InheritString (obj, "x11-display");
    int snum;
    xcb_connection_t *conn = xcb_connect (display, &snum);
    free (display);
    if (xcb_connection_has_error (conn))
    {
        free (p_sys);
        return VLC_EGENERIC;
    }
    p_sys->conn = conn;

   /* Find configured screen */
    if (!strcmp (demux->psz_access, "screen"))
    {
        const xcb_setup_t *setup = xcb_get_setup (conn);
        const xcb_screen_t *scr = NULL;
        for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
             i.rem > 0; xcb_screen_next (&i))
        {
            if (snum == 0)
            {
               scr = i.data;
                break;
            }
            snum--;
        }
        if (scr == NULL)
        {
            msg_Err (obj, "bad X11 screen number");
            goto error;
        }
        p_sys->window = scr->root;
    }
    else
    /* Determine capture window */
    if (!strcmp (demux->psz_access, "window"))
    {
        char *end;
        unsigned long ul = strtoul (demux->psz_location, &end, 0);
        if (*end || ul > 0xffffffff)
        {
            msg_Err (obj, "bad X11 drawable %s", demux->psz_location);
            goto error;
        }
        p_sys->window = ul;

        xcb_composite_query_version_reply_t *r =
            xcb_composite_query_version_reply (conn,
                xcb_composite_query_version (conn, 0, 4), NULL);
        if (r == NULL || r->minor_version < 2)
        {
            msg_Err (obj, "X Composite extension not available");
            free (r);
            goto error;
        }
        msg_Dbg (obj, "using Composite extension v%"PRIu32".%"PRIu32,
                 r->major_version, r->minor_version);
        free (r);

        xcb_composite_redirect_window (conn, p_sys->window,
                                       XCB_COMPOSITE_REDIRECT_AUTOMATIC);
    }
    else
        goto error;

    /* Window properties */
    p_sys->pixmap = xcb_generate_id (conn);
    p_sys->segment = xcb_generate_id (conn);
    p_sys->shm = CheckSHM (conn);
    p_sys->w = var_InheritInteger (obj, "screen-width");
    p_sys->h = var_InheritInteger (obj, "screen-height");
    if (p_sys->w != 0 || p_sys->h != 0)
        p_sys->follow_mouse = var_InheritBool (obj, "screen-follow-mouse");
    else /* Following mouse is meaningless if width&height are dynamic. */
        p_sys->follow_mouse = false;
    if (!p_sys->follow_mouse) /* X and Y are meaningless if following mouse */
    {
        p_sys->x = var_InheritInteger (obj, "screen-left");
        p_sys->y = var_InheritInteger (obj, "screen-top");
    }

    /* Initializes format */
    p_sys->rate = var_InheritFloat (obj, "screen-fps");
    if (!p_sys->rate)
        goto error;

    mtime_t interval = (float)CLOCK_FREQ / p_sys->rate;
    if (!interval)
        goto error;

    p_sys->cur_w = 0;
    p_sys->cur_h = 0;
    p_sys->bpp = 0;
    p_sys->es = NULL;
    if (vlc_timer_create (&p_sys->timer, Demux, demux))
        goto error;
    vlc_timer_schedule (p_sys->timer, false, 1, interval);

    /* Initializes demux */
    demux->pf_demux   = NULL;
    demux->pf_control = Control;
    return VLC_SUCCESS;

error:
    xcb_disconnect (p_sys->conn);
    free (p_sys);
    return VLC_EGENERIC;
}
Exemple #18
0
/** dri3_get_pixmap_buffer
 *
 * Get the DRM object for a pixmap from the X server and
 * wrap that with a __DRIimage structure using createImageFromFds
 */
static struct loader_dri3_buffer *
dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
                       enum loader_dri3_buffer_type buffer_type,
                       struct loader_dri3_drawable *draw)
{
    int                                  buf_id = loader_dri3_pixmap_buf_id(buffer_type);
    struct loader_dri3_buffer            *buffer = draw->buffers[buf_id];
    xcb_drawable_t                       pixmap;
    xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
    xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
    xcb_sync_fence_t                     sync_fence;
    struct xshmfence                     *shm_fence;
    int                                  fence_fd;
    __DRIscreen                          *cur_screen;

    if (buffer)
        return buffer;

    pixmap = draw->drawable;

    buffer = calloc(1, sizeof *buffer);
    if (!buffer)
        goto no_buffer;

    fence_fd = xshmfence_alloc_shm();
    if (fence_fd < 0)
        goto no_fence;
    shm_fence = xshmfence_map_shm(fence_fd);
    if (shm_fence == NULL) {
        close (fence_fd);
        goto no_fence;
    }

    xcb_dri3_fence_from_fd(draw->conn,
                           pixmap,
                           (sync_fence = xcb_generate_id(draw->conn)),
                           false,
                           fence_fd);

    bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap);
    bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie, NULL);
    if (!bp_reply)
        goto no_image;

    /* Get the currently-bound screen or revert to using the drawable's screen if
     * no contexts are currently bound. The latter case is at least necessary for
     * obs-studio, when using Window Capture (Xcomposite) as a Source.
     */
    cur_screen = draw->vtable->get_dri_screen(draw);
    if (!cur_screen) {
        cur_screen = draw->dri_screen;
    }

    buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format,
                    cur_screen, draw->ext->image,
                    buffer);
    if (!buffer->image)
        goto no_image;

    buffer->pixmap = pixmap;
    buffer->own_pixmap = false;
    buffer->width = bp_reply->width;
    buffer->height = bp_reply->height;
    buffer->buffer_type = buffer_type;
    buffer->shm_fence = shm_fence;
    buffer->sync_fence = sync_fence;

    draw->buffers[buf_id] = buffer;

    free(bp_reply);

    return buffer;

no_image:
    free(bp_reply);
    xcb_sync_destroy_fence(draw->conn, sync_fence);
    xshmfence_unmap_shm(shm_fence);
no_fence:
    free(buffer);
no_buffer:
    return NULL;
}
Exemple #19
0
/**
 * Probe the X server.
 */
static int Open (vlc_object_t *obj)
{
    vout_display_t *vd = (vout_display_t *)obj;
    vout_display_sys_t *sys = malloc (sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    vd->sys = sys;
    sys->pool = NULL;

    /* Get window, connect to X server */
    xcb_connection_t *conn;
    const xcb_screen_t *scr;
    sys->embed = vlc_xcb_parent_Create(vd, &conn, &scr);
    if (sys->embed == NULL)
    {
        free (sys);
        return VLC_EGENERIC;
    }
    sys->conn = conn;

    const xcb_setup_t *setup = xcb_get_setup (conn);

    /* Determine our pixel format */
    video_format_t fmt_pic;
    xcb_visualid_t vid = 0;
    sys->depth = 0;

    for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup),
             *end = fmt + xcb_setup_pixmap_formats_length (setup);
         fmt < end;
         fmt++)
    {
        if (fmt->depth <= sys->depth)
            continue; /* no better than earlier format */

        video_format_ApplyRotation(&fmt_pic, &vd->fmt);

        /* Check that the pixmap format is supported by VLC. */
        switch (fmt->depth)
        {
          case 32:
            if (fmt->bits_per_pixel != 32)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_ARGB;
            break;
          case 24:
            if (fmt->bits_per_pixel == 32)
                fmt_pic.i_chroma = VLC_CODEC_RGB32;
            else if (fmt->bits_per_pixel == 24)
                fmt_pic.i_chroma = VLC_CODEC_RGB24;
            else
                continue;
            break;
          case 16:
            if (fmt->bits_per_pixel != 16)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB16;
            break;
          case 15:
            if (fmt->bits_per_pixel != 16)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB15;
            break;
          case 8:
            if (fmt->bits_per_pixel != 8)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB8;
            break;
          default:
            continue;
        }

        /* Byte sex is a non-issue for 8-bits. It can be worked around with
         * RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */
        if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER)
            continue;

        /* Make sure the X server is sane */
        assert (fmt->bits_per_pixel > 0);
        if (unlikely(fmt->scanline_pad % fmt->bits_per_pixel))
            continue;

        /* Check that the selected screen supports this depth */
        const xcb_depth_t *d = FindDepth (scr, fmt->depth);
        if (d == NULL)
            continue;

        /* Find a visual type for the selected depth */
        const xcb_visualtype_t *vt = xcb_depth_visuals (d);

        /* First try True Color class */
        for (int i = xcb_depth_visuals_length (d); i > 0; i--)
        {
            if (vt->_class == XCB_VISUAL_CLASS_TRUE_COLOR)
            {
                fmt_pic.i_rmask = vt->red_mask;
                fmt_pic.i_gmask = vt->green_mask;
                fmt_pic.i_bmask = vt->blue_mask;
            found_visual:
                vid = vt->visual_id;
                msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid);
                sys->depth = fmt->depth;
                msg_Dbg (vd, " %"PRIu8" bits depth", sys->depth);
                msg_Dbg (vd, " %"PRIu8" bits per pixel", fmt->bits_per_pixel);
                msg_Dbg (vd, " %"PRIu8" bits line pad", fmt->scanline_pad);
                goto found_format;
            }
            vt++;
        }

        /* Then try Static Gray class */
        if (fmt->depth != 8)
            continue;
        vt = xcb_depth_visuals (d);
        for (int i = xcb_depth_visuals_length (d); i > 0 && !vid; i--)
        {
            if (vt->_class == XCB_VISUAL_CLASS_STATIC_GRAY)
            {
                fmt_pic.i_chroma = VLC_CODEC_GREY;
                goto found_visual;
            }
            vt++;
        }
    }

    msg_Err (obj, "no supported pixel format & visual");
    goto error;

found_format:;
    /* Create colormap (needed to select non-default visual) */
    xcb_colormap_t cmap;
    if (vid != scr->root_visual)
    {
        cmap = xcb_generate_id (conn);
        xcb_create_colormap (conn, XCB_COLORMAP_ALLOC_NONE,
                             cmap, scr->root, vid);
    }
    else
        cmap = scr->default_colormap;

    /* Create window */
    sys->window = xcb_generate_id (conn);
    sys->gc = xcb_generate_id (conn);
    xcb_pixmap_t pixmap = xcb_generate_id (conn);
    {
        const uint32_t mask =
            XCB_CW_BACK_PIXMAP |
            XCB_CW_BACK_PIXEL |
            XCB_CW_BORDER_PIXMAP |
            XCB_CW_BORDER_PIXEL |
            XCB_CW_EVENT_MASK |
            XCB_CW_COLORMAP;
        const uint32_t values[] = {
            /* XCB_CW_BACK_PIXMAP */
            pixmap,
            /* XCB_CW_BACK_PIXEL */
            scr->black_pixel,
            /* XCB_CW_BORDER_PIXMAP */
            pixmap,
            /* XCB_CW_BORDER_PIXEL */
            scr->black_pixel,
            /* XCB_CW_EVENT_MASK */
            XCB_EVENT_MASK_VISIBILITY_CHANGE,
            /* XCB_CW_COLORMAP */
            cmap,
        };
        xcb_void_cookie_t c;

        xcb_create_pixmap (conn, sys->depth, pixmap, scr->root, 1, 1);
        c = xcb_create_window_checked (conn, sys->depth, sys->window,
                                       sys->embed->handle.xid, 0, 0,
                                       vd->cfg->display.width,
                                       vd->cfg->display.height, 0,
                                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                       vid, mask, values);
        xcb_map_window (conn, sys->window);
        /* Create graphic context (I wonder why the heck do we need this) */
        xcb_create_gc (conn, sys->gc, sys->window, 0, NULL);

        if (vlc_xcb_error_Check(vd, conn, "cannot create X11 window", c))
            goto error;
    }
    msg_Dbg (vd, "using X11 window %08"PRIx32, sys->window);
    msg_Dbg (vd, "using X11 graphic context %08"PRIx32, sys->gc);

    sys->cursor = vlc_xcb_cursor_Create(conn, scr);
    sys->visible = false;
    if (XCB_shm_Check (obj, conn))
    {
        sys->seg_base = xcb_generate_id (conn);
        for (unsigned i = 1; i < MAX_PICTURES; i++)
             xcb_generate_id (conn);
    }
    else
        sys->seg_base = 0;

    /* Setup vout_display_t once everything is fine */
    vd->info.has_pictures_invalid = true;
    vd->info.has_event_thread = true;

    vd->fmt = fmt_pic;
    vd->pool = Pool;
    vd->prepare = NULL;
    vd->display = Display;
    vd->control = Control;
    vd->manage = Manage;

    return VLC_SUCCESS;

error:
    Close (obj);
    return VLC_EGENERIC;
}
int vkDisplay::create_window(const unsigned int width, const unsigned int height)
{
#if defined(PLATFORM_LINUX)
#if defined(ANDROID)
    return 0;
#else

    uint32_t value_mask, value_list[32];
    m_XcbWindow = xcb_generate_id(m_pXcbConnection);

    value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    value_list[0] = m_pXcbScreen->black_pixel;
    value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
                    XCB_EVENT_MASK_EXPOSURE;

    xcb_create_window(m_pXcbConnection,
            XCB_COPY_FROM_PARENT,
            m_XcbWindow, m_pXcbScreen->root,
            0, 0, width, height, 0,
            XCB_WINDOW_CLASS_INPUT_OUTPUT,
            m_pXcbScreen->root_visual,
            value_mask, value_list);

    xcb_map_window(m_pXcbConnection, m_XcbWindow);
    xcb_flush(m_pXcbConnection);
    // TODO : Not sure of best place to put this, but I have all the info I need here so just setting it all here for now
    //m_XcbPlatformHandle.connection = m_pXcbConnection;
    //m_XcbPlatformHandle.root = m_pXcbScreen->root;
    m_surface.base.platform = VK_ICD_WSI_PLATFORM_XCB;
    m_surface.connection = m_pXcbConnection;
    m_surface.window = m_XcbWindow;
    return 0;
#endif
#elif defined(WIN32)
    // Register Window class
    WNDCLASSEX wcex = {};
	m_connection = GetModuleHandle(0);
    wcex.cbSize = sizeof( WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WindowProcVk;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = m_connection;
    wcex.hIcon = LoadIcon(wcex.hInstance, MAKEINTRESOURCE( IDI_ICON));
    wcex.hCursor = LoadCursor( NULL, IDC_ARROW);
    wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = APP_NAME;
    wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE( IDI_ICON));
    if( !RegisterClassEx( &wcex))
    {
        vktrace_LogError("Failed to register windows class");
        return -1;
    }

    // create the window
    RECT wr = {0,0,width,height};
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
    m_windowHandle = CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
                                  0, 0, wr.right-wr.left, wr.bottom-wr.top,
                                  NULL, NULL, wcex.hInstance, NULL);

    if (m_windowHandle)
    {
        ShowWindow( m_windowHandle, SW_SHOWDEFAULT);
        m_windowWidth = width;
        m_windowHeight = height;
    } else {
        vktrace_LogError("Failed to create window");
        return -1;
    }
    // TODO : Not sure of best place to put this, but I have all the info I need here so just setting it all here for now
    m_surface.base.platform = VK_ICD_WSI_PLATFORM_WIN32;
    m_surface.hinstance = wcex.hInstance;
    m_surface.hwnd = m_windowHandle;
    return 0;
#endif
}
Exemple #21
0
QXcbWindow::QXcbWindow(QWidget *tlw)
    : QPlatformWindow(tlw)
    , m_context(0)
{
    m_screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(tlw));

    setConnection(m_screen->connection());

    const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK;
    const quint32 values[] = {
        // XCB_CW_BACK_PIXMAP
        XCB_NONE,
        // XCB_CW_EVENT_MASK
        XCB_EVENT_MASK_EXPOSURE
        | XCB_EVENT_MASK_STRUCTURE_NOTIFY
        | XCB_EVENT_MASK_KEY_PRESS
        | XCB_EVENT_MASK_KEY_RELEASE
        | XCB_EVENT_MASK_BUTTON_PRESS
        | XCB_EVENT_MASK_BUTTON_RELEASE
        | XCB_EVENT_MASK_BUTTON_MOTION
        | XCB_EVENT_MASK_ENTER_WINDOW
        | XCB_EVENT_MASK_LEAVE_WINDOW
        | XCB_EVENT_MASK_PROPERTY_CHANGE
        | XCB_EVENT_MASK_FOCUS_CHANGE
    };

#if defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
    if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
            && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)
            || tlw->platformWindowFormat().alpha())
    {
#if defined(XCB_USE_GLX)
        XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat());
#elif defined(XCB_USE_EGL)
        EGLDisplay eglDisplay = connection()->egl_display();
        EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true);
        VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);

        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        visualInfoTemplate.visualid = id;

        XVisualInfo *visualInfo;
        int matchingCount = 0;
        visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
#endif //XCB_USE_GLX
        if (visualInfo) {
            m_depth = visualInfo->depth;
            m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
            Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone);

            XSetWindowAttributes a;
            a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
            a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
            a.colormap = cmap;
            m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(),
                                     0, visualInfo->depth, InputOutput, visualInfo->visual,
                                     CWBackPixel|CWBorderPixel|CWColormap, &a);

            printf("created GL window: %d\n", m_window);
        } else {
            qFatal("no window!");
        }
    } else
#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
    {
        m_window = xcb_generate_id(xcb_connection());
        m_depth = m_screen->screen()->root_depth;
        m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;

        Q_XCB_CALL(xcb_create_window(xcb_connection(),
                                     XCB_COPY_FROM_PARENT,            // depth -- same as root
                                     m_window,                        // window id
                                     m_screen->root(),                // parent window id
                                     tlw->x(),
                                     tlw->y(),
                                     tlw->width(),
                                     tlw->height(),
                                     0,                               // border width
                                     XCB_WINDOW_CLASS_INPUT_OUTPUT,   // window class
                                     m_screen->screen()->root_visual, // visual
                                     0,                               // value mask
                                     0));                             // value list

        printf("created regular window: %d\n", m_window);
    }

    Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));

    xcb_atom_t properties[4];
    int propertyCount = 0;
    properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW);
    properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
    properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);

    if (m_screen->syncRequestSupported())
        properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);

    if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint)
        properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);

    Q_XCB_CALL(xcb_change_property(xcb_connection(),
                                   XCB_PROP_MODE_REPLACE,
                                   m_window,
                                   atom(QXcbAtom::WM_PROTOCOLS),
                                   XCB_ATOM_ATOM,
                                   32,
                                   propertyCount,
                                   properties));
    m_syncValue.hi = 0;
    m_syncValue.lo = 0;

    if (m_screen->syncRequestSupported()) {
        m_syncCounter = xcb_generate_id(xcb_connection());
        Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));

        Q_XCB_CALL(xcb_change_property(xcb_connection(),
                                       XCB_PROP_MODE_REPLACE,
                                       m_window,
                                       atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
                                       XCB_ATOM_CARDINAL,
                                       32,
                                       1,
                                       &m_syncCounter));
    }

    if (isTransient(tlw) && tlw->parentWidget()) {
        // ICCCM 4.1.2.6
        QWidget *p = tlw->parentWidget()->window();
        xcb_window_t parentWindow = p->winId();
        Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
                                       XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
                                       1, &parentWindow));

    }

    // set the PID to let the WM kill the application if unresponsive
    long pid = getpid();
    Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
                                   atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
                                   1, &pid));
}
Exemple #22
0
static VkResult
x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
               const VkSwapchainCreateInfoKHR *pCreateInfo,
               const VkAllocationCallbacks* pAllocator,
               struct x11_image *image)
{
   xcb_void_cookie_t cookie;
   VkResult result;
   uint32_t row_pitch;
   uint32_t offset;
   uint32_t bpp = 32;
   int fd;
   uint32_t size;

   result = chain->base.image_fns->create_wsi_image(device_h,
                                                    pCreateInfo,
                                                    pAllocator,
                                                    &image->image,
                                                    &image->memory,
                                                    &size,
                                                    &offset,
                                                    &row_pitch,
                                                    &fd);
   if (result != VK_SUCCESS)
      return result;

   image->pixmap = xcb_generate_id(chain->conn);

   cookie =
      xcb_dri3_pixmap_from_buffer_checked(chain->conn,
                                          image->pixmap,
                                          chain->window,
                                          size,
                                          pCreateInfo->imageExtent.width,
                                          pCreateInfo->imageExtent.height,
                                          row_pitch,
                                          chain->depth, bpp, fd);
   xcb_discard_reply(chain->conn, cookie.sequence);

   int fence_fd = xshmfence_alloc_shm();
   if (fence_fd < 0)
      goto fail_pixmap;

   image->shm_fence = xshmfence_map_shm(fence_fd);
   if (image->shm_fence == NULL)
      goto fail_shmfence_alloc;

   image->sync_fence = xcb_generate_id(chain->conn);
   xcb_dri3_fence_from_fd(chain->conn,
                          image->pixmap,
                          image->sync_fence,
                          false,
                          fence_fd);

   image->busy = false;
   xshmfence_trigger(image->shm_fence);

   return VK_SUCCESS;

fail_shmfence_alloc:
   close(fence_fd);

fail_pixmap:
   cookie = xcb_free_pixmap(chain->conn, image->pixmap);
   xcb_discard_reply(chain->conn, cookie.sequence);

   chain->base.image_fns->free_wsi_image(device_h, pAllocator,
                                        image->image, image->memory);

   return result;
}
/** loader_dri3_alloc_render_buffer
 *
 * Use the driver createImage function to construct a __DRIimage, then
 * get a file descriptor for that and create an X pixmap from that
 *
 * Allocate an xshmfence for synchronization
 */
static struct loader_dri3_buffer *
dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
                         int width, int height, int depth)
{
   struct loader_dri3_buffer *buffer;
   __DRIimage *pixmap_buffer;
   xcb_pixmap_t pixmap;
   xcb_sync_fence_t sync_fence;
   struct xshmfence *shm_fence;
   int buffer_fd, fence_fd;
   int stride;

   /* Create an xshmfence object and
    * prepare to send that to the X server
    */

   fence_fd = xshmfence_alloc_shm();
   if (fence_fd < 0)
      return NULL;

   shm_fence = xshmfence_map_shm(fence_fd);
   if (shm_fence == NULL)
      goto no_shm_fence;

   /* Allocate the image from the driver
    */
   buffer = calloc(1, sizeof *buffer);
   if (!buffer)
      goto no_buffer;

   buffer->cpp = dri3_cpp_for_format(format);
   if (!buffer->cpp)
      goto no_image;

   if (!draw->is_different_gpu) {
      buffer->image = (draw->ext->image->createImage)(draw->dri_screen,
                                                      width, height,
                                                      format,
                                                      __DRI_IMAGE_USE_SHARE |
                                                      __DRI_IMAGE_USE_SCANOUT |
                                                      __DRI_IMAGE_USE_BACKBUFFER,
                                                      buffer);
      pixmap_buffer = buffer->image;

      if (!buffer->image)
         goto no_image;
   } else {
      buffer->image = (draw->ext->image->createImage)(draw->dri_screen,
                                                      width, height,
                                                      format,
                                                      0,
                                                      buffer);

      if (!buffer->image)
         goto no_image;

      buffer->linear_buffer =
        (draw->ext->image->createImage)(draw->dri_screen,
                                        width, height, format,
                                        __DRI_IMAGE_USE_SHARE |
                                        __DRI_IMAGE_USE_LINEAR |
                                        __DRI_IMAGE_USE_BACKBUFFER,
                                        buffer);
      pixmap_buffer = buffer->linear_buffer;

      if (!buffer->linear_buffer)
         goto no_linear_buffer;
   }

   /* X wants the stride, so ask the image for it
    */
   if (!(draw->ext->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_STRIDE,
                                       &stride))
      goto no_buffer_attrib;

   buffer->pitch = stride;

   if (!(draw->ext->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD,
                                       &buffer_fd))
      goto no_buffer_attrib;

   xcb_dri3_pixmap_from_buffer(draw->conn,
                               (pixmap = xcb_generate_id(draw->conn)),
                               draw->drawable,
                               buffer->size,
                               width, height, buffer->pitch,
                               depth, buffer->cpp * 8,
                               buffer_fd);

   xcb_dri3_fence_from_fd(draw->conn,
                          pixmap,
                          (sync_fence = xcb_generate_id(draw->conn)),
                          false,
                          fence_fd);

   buffer->pixmap = pixmap;
   buffer->own_pixmap = true;
   buffer->sync_fence = sync_fence;
   buffer->shm_fence = shm_fence;
   buffer->width = width;
   buffer->height = height;

   /* Mark the buffer as idle
    */
   dri3_fence_set(buffer);

   return buffer;

no_buffer_attrib:
   (draw->ext->image->destroyImage)(pixmap_buffer);
no_linear_buffer:
   if (draw->is_different_gpu)
      (draw->ext->image->destroyImage)(buffer->image);
no_image:
   free(buffer);
no_buffer:
   xshmfence_unmap_shm(shm_fence);
no_shm_fence:
   close(fence_fd);
   return NULL;
}
Exemple #24
0
static VkResult
x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                             VkDevice device,
                             struct wsi_device *wsi_device,
                             const VkSwapchainCreateInfoKHR *pCreateInfo,
                             const VkAllocationCallbacks* pAllocator,
                             const struct wsi_image_fns *image_fns,
                             struct wsi_swapchain **swapchain_out)
{
   struct x11_swapchain *chain;
   xcb_void_cookie_t cookie;
   VkResult result;

   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);

   const unsigned num_images = pCreateInfo->minImageCount;

   size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
   chain = vk_alloc(pAllocator, size, 8,
                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
   if (chain == NULL)
      return VK_ERROR_OUT_OF_HOST_MEMORY;

   xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
   xcb_window_t window = x11_surface_get_window(icd_surface);
   xcb_get_geometry_reply_t *geometry =
      xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL);

   if (geometry == NULL)
      return VK_ERROR_SURFACE_LOST_KHR;

   chain->base.device = device;
   chain->base.destroy = x11_swapchain_destroy;
   chain->base.get_images = x11_get_images;
   chain->base.acquire_next_image = x11_acquire_next_image;
   chain->base.queue_present = x11_queue_present;
   chain->base.image_fns = image_fns;
   chain->base.present_mode = pCreateInfo->presentMode;
   chain->conn = conn;
   chain->window = window;
   chain->depth = geometry->depth;
   chain->extent = pCreateInfo->imageExtent;
   chain->image_count = num_images;
   chain->send_sbc = 0;
   chain->last_present_msc = 0;
   chain->threaded = false;
   chain->status = VK_SUCCESS;

   free(geometry);

   chain->event_id = xcb_generate_id(chain->conn);
   xcb_present_select_input(chain->conn, chain->event_id, chain->window,
                            XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
                            XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
                            XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);

   /* Create an XCB event queue to hold present events outside of the usual
    * application event queue
    */
   chain->special_event =
      xcb_register_for_special_xge(chain->conn, &xcb_present_id,
                                   chain->event_id, NULL);

   chain->gc = xcb_generate_id(chain->conn);
   if (!chain->gc) {
      /* FINISHME: Choose a better error. */
      result = VK_ERROR_OUT_OF_HOST_MEMORY;
      goto fail_register;
   }

   cookie = xcb_create_gc(chain->conn,
                          chain->gc,
                          chain->window,
                          XCB_GC_GRAPHICS_EXPOSURES,
                          (uint32_t []) { 0 });
   xcb_discard_reply(chain->conn, cookie.sequence);

   uint32_t image = 0;
   for (; image < chain->image_count; image++) {
      result = x11_image_init(device, chain, pCreateInfo, pAllocator,
                              &chain->images[image]);
      if (result != VK_SUCCESS)
         goto fail_init_images;
   }

   if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
      chain->threaded = true;

      /* Initialize our queues.  We make them image_count + 1 because we will
       * occasionally use UINT32_MAX to signal the other thread that an error
       * has occurred and we don't want an overflow.
       */
      int ret;
      ret = wsi_queue_init(&chain->acquire_queue, chain->image_count + 1);
      if (ret) {
         goto fail_init_images;
      }

      ret = wsi_queue_init(&chain->present_queue, chain->image_count + 1);
      if (ret) {
         wsi_queue_destroy(&chain->acquire_queue);
         goto fail_init_images;
      }

      for (unsigned i = 0; i < chain->image_count; i++)
         wsi_queue_push(&chain->acquire_queue, i);

      ret = pthread_create(&chain->queue_manager, NULL,
                           x11_manage_fifo_queues, chain);
      if (ret) {
         wsi_queue_destroy(&chain->present_queue);
         wsi_queue_destroy(&chain->acquire_queue);
         goto fail_init_images;
      }
   }

   *swapchain_out = &chain->base;

   return VK_SUCCESS;

fail_init_images:
   for (uint32_t j = 0; j < image; j++)
      x11_image_finish(chain, pAllocator, &chain->images[j]);

fail_register:
   xcb_unregister_for_special_event(chain->conn, chain->special_event);

   vk_free(pAllocator, chain);

   return result;
}
Exemple #25
0
/**
 * Create an X11 window.
 */
static int Open (vout_window_t *wnd, const vout_window_cfg_t *cfg)
{
    xcb_generic_error_t *err;
    xcb_void_cookie_t ck;

    vout_window_sys_t *p_sys = malloc (sizeof (*p_sys));
    if (p_sys == NULL)
        return VLC_ENOMEM;
    p_sys->embedded = false;

    /* Connect to X */
    char *display = var_InheritString (wnd, "x11-display");
    int snum;

    xcb_connection_t *conn = xcb_connect (display, &snum);
    if (xcb_connection_has_error (conn) /*== NULL*/)
        goto error;

    /* Find configured screen */
    const xcb_setup_t *setup = xcb_get_setup (conn);
    const xcb_screen_t *scr = NULL;
    for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
         i.rem > 0; xcb_screen_next (&i))
    {
        if (snum == 0)
        {
            scr = i.data;
            break;
        }
        snum--;
    }
    if (scr == NULL)
    {
        msg_Err (wnd, "bad X11 screen number");
        goto error;
    }

    /* Create window */
    const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t values[2] = {
        /* XCB_CW_BACK_PIXEL */
        scr->black_pixel,
        /* XCB_CW_EVENT_MASK */
        XCB_EVENT_MASK_KEY_PRESS,
    };

    xcb_window_t window = xcb_generate_id (conn);
    ck = xcb_create_window_checked (conn, scr->root_depth, window, scr->root,
                                    cfg->x, cfg->y, cfg->width, cfg->height, 0,
                                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                    scr->root_visual, mask, values);
    err = xcb_request_check (conn, ck);
    if (err)
    {
        msg_Err (wnd, "creating window: X11 error %d", err->error_code);
        free (err);
        goto error;
    }

    wnd->handle.xid = window;
    wnd->display.x11 = display;
    wnd->control = Control;
    wnd->sys = p_sys;

    p_sys->conn = conn;
    if (var_InheritBool (wnd, "keyboard-events"))
        p_sys->keys = CreateKeyHandler (VLC_OBJECT(wnd), conn);
    else
        p_sys->keys = NULL;
    p_sys->root = scr->root;

    /* ICCCM
     * No cut&paste nor drag&drop, only Window Manager communication. */
    set_ascii_prop (conn, window, XA_WM_NAME,
    /* xgettext: This is a plain ASCII spelling of "VLC media player"
       for the ICCCM window name. This must be pure ASCII.
       The limitation is partially with ICCCM and partially with VLC.
       For Latin script languages, you may need to strip accents.
       For other scripts, you will need to transliterate into Latin. */
                    vlc_pgettext ("ASCII", "VLC media player"));

    set_ascii_prop (conn, window, XA_WM_ICON_NAME,
    /* xgettext: This is a plain ASCII spelling of "VLC"
       for the ICCCM window name. This must be pure ASCII. */
                    vlc_pgettext ("ASCII", "VLC"));
    set_wm_hints (conn, window);
    xcb_change_property (conn, XCB_PROP_MODE_REPLACE, window, XA_WM_CLASS,
                         XA_STRING, 8, 8, "vlc\0Vlc");
    set_hostname_prop (conn, window);

    /* EWMH */
    xcb_intern_atom_cookie_t utf8_string_ck
        = intern_string (conn, "UTF8_STRING");;
    xcb_intern_atom_cookie_t net_wm_name_ck
        = intern_string (conn, "_NET_WM_NAME");
    xcb_intern_atom_cookie_t net_wm_icon_name_ck
        = intern_string (conn, "_NET_WM_ICON_NAME");
    xcb_intern_atom_cookie_t wm_window_role_ck
        = intern_string (conn, "WM_WINDOW_ROLE");

    xcb_atom_t utf8 = get_atom (conn, utf8_string_ck);

    xcb_atom_t net_wm_name = get_atom (conn, net_wm_name_ck);
    char *title = var_InheritString (wnd, "video-title");
    if (title)
    {
        set_string (conn, window, utf8, net_wm_name, title);
        free (title);
    }
    else
        set_string (conn, window, utf8, net_wm_name, _("VLC media player"));

    xcb_atom_t net_wm_icon_name = get_atom (conn, net_wm_icon_name_ck);
    set_string (conn, window, utf8, net_wm_icon_name, _("VLC"));

    xcb_atom_t wm_window_role = get_atom (conn, wm_window_role_ck);
    set_ascii_prop (conn, window, wm_window_role, "vlc-video");

    /* Cache any EWMH atom we may need later */
    CacheAtoms (p_sys);
#ifdef MATCHBOX_HACK
    if (p_sys->mb_current_app_window)
    {
        uint32_t value = XCB_EVENT_MASK_PROPERTY_CHANGE;
        xcb_change_window_attributes (conn, scr->root,
                                      XCB_CW_EVENT_MASK, &value);
    }
#endif

    /* Make the window visible */
    xcb_map_window (conn, window);

    if (var_InheritBool (wnd, "video-wallpaper"))
    {
        vout_window_SetState (wnd, VOUT_WINDOW_STATE_BELOW);
        vout_window_SetFullScreen (wnd, true);
    }

    /* Create the event thread. It will dequeue all events, so any checked
     * request from this thread must be completed at this point. */
    if ((p_sys->keys != NULL)
     && vlc_clone (&p_sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW))
        DestroyKeyHandler (p_sys->keys);

#ifdef MATCHBOX_HACK
    if (p_sys->mb_current_app_window)
        xcb_set_input_focus (p_sys->conn, XCB_INPUT_FOCUS_POINTER_ROOT,
                             wnd->handle.xid, XCB_CURRENT_TIME);
#endif
    xcb_flush (conn); /* Make sure map_window is sent (should be useless) */
    return VLC_SUCCESS;

error:
    xcb_disconnect (conn);
    free (display);
    free (p_sys);
    return VLC_EGENERIC;
}
int setup_and_run(Display *display, xcb_connection_t *connection, int default_screen, xcb_screen_t *screen)
{
    int visualID = 0;

    /*Query framebuffer configurations */
    GLXFBConfig *fb_configs = 0;
    int num_fb_configs = 0;
    fb_configs = glXGetFBConfigs(display, default_screen, &num_fb_configs);
    if (!fb_configs || num_fb_configs == 0)
    {
        fprintf(stderr, "glXGetFBConfigs failed\n");
        return -1;
    }

    /* Select first framebuffer config and query visualID */
    GLXFBConfig fb_config = fb_configs[0];
    glXGetFBConfigAttrib(display, fb_config, GLX_VISUAL_ID, &visualID);

    GLXContext context;

    /* Create OpenGL context */
    context = glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True);
    if (!context)
    {
        fprintf(stderr, "glXCreateNewContext failed\n");
        return -1;
    }

    /* Create XID's for colormap and window */
    xcb_colormap_t colormap = xcb_generate_id(connection);
    xcb_window_t window  = xcb_generate_id(connection);

    /* Create colormap */
    xcb_create_colormap(
        connection,
        XCB_COLORMAP_ALLOC_NONE,
        colormap,
        screen->root,
        visualID);

    /* Create window */
    uint32_t eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
    uint32_t valuelist[] = {eventmask, colormap, 0};
    uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;

    xcb_create_window(
        connection,
        XCB_COPY_FROM_PARENT,
        window,
        screen->root,
        0, 0,
        window_width, window_height,
        0,
        XCB_WINDOW_CLASS_INPUT_OUTPUT,
        visualID,
        valuemask,
        valuelist);

    /* NOTE: window must be mapped before glXMakeContextCurrent */
    xcb_map_window(connection, window);

    /* Create GLX window */
    GLXDrawable drawable = 0;
    GLXWindow glxwindow = glXCreateWindow(display, fb_config, window, 0);
    if (!glxwindow)
    {
        xcb_destroy_window(connection, window);
        glXDestroyContext(display, context);
        fprintf(stderr, "glXCreateWindow failed\n");
        return -1;
    }

    drawable = glxwindow;

    /* make OpenGL context current */
    #if 1
    if (!glXMakeContextCurrent(display, drawable, drawable, context))
    {
        xcb_destroy_window(connection, window);
        glXDestroyContext(display, context);
        fprintf(stderr, "glXMakeContextCurrent failed\n");
        return -1;
    }
    #else
    if (!glXMakeCurrent(display, drawable, context))
    {
        xcb_destroy_window(connection, window);
        glXDestroyContext(display, context);
        fprintf(stderr, "glXMakeContextCurrent failed\n");
        return -1;
    }
    #endif

    /* run main loop */
    int retval = main_loop (display, connection, screen, window, drawable);

    /* Cleanup */
    glXDestroyWindow(display, glxwindow);
    xcb_destroy_window(connection, window);
    glXDestroyContext(display, context);
    return retval;
}
Exemple #27
0
static struct vl_dri3_buffer *
dri3_get_front_buffer(struct vl_dri3_screen *scrn)
{
   xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
   xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
   xcb_sync_fence_t sync_fence;
   struct xshmfence *shm_fence;
   int fence_fd, *fds;
   struct winsys_handle whandle;
   struct pipe_resource templ, *texture = NULL;

   if (scrn->front_buffer) {
      pipe_resource_reference(&texture, scrn->front_buffer->texture);
      return scrn->front_buffer;
   }

   scrn->front_buffer = CALLOC_STRUCT(vl_dri3_buffer);
   if (!scrn->front_buffer)
      return NULL;

   fence_fd = xshmfence_alloc_shm();
   if (fence_fd < 0)
      goto free_buffer;

   shm_fence = xshmfence_map_shm(fence_fd);
   if (!shm_fence)
      goto close_fd;

   bp_cookie = xcb_dri3_buffer_from_pixmap(scrn->conn, scrn->drawable);
   bp_reply = xcb_dri3_buffer_from_pixmap_reply(scrn->conn, bp_cookie, NULL);
   if (!bp_reply)
      goto unmap_shm;

   fds = xcb_dri3_buffer_from_pixmap_reply_fds(scrn->conn, bp_reply);
   if (fds[0] < 0)
      goto free_reply;

   memset(&whandle, 0, sizeof(whandle));
   whandle.type = DRM_API_HANDLE_TYPE_FD;
   whandle.handle = (unsigned)fds[0];
   whandle.stride = bp_reply->stride;
   memset(&templ, 0, sizeof(templ));
   templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
   templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
   templ.target = PIPE_TEXTURE_2D;
   templ.last_level = 0;
   templ.width0 = bp_reply->width;
   templ.height0 = bp_reply->height;
   templ.depth0 = 1;
   templ.array_size = 1;
   scrn->front_buffer->texture =
      scrn->base.pscreen->resource_from_handle(scrn->base.pscreen,
                                               &templ, &whandle,
                                               PIPE_HANDLE_USAGE_READ_WRITE);
   close(fds[0]);
   if (!scrn->front_buffer->texture)
      goto free_reply;

   xcb_dri3_fence_from_fd(scrn->conn,
                          scrn->drawable,
                          (sync_fence = xcb_generate_id(scrn->conn)),
                          false,
                          fence_fd);

   pipe_resource_reference(&texture, scrn->front_buffer->texture);
   scrn->front_buffer->pixmap = scrn->drawable;
   scrn->front_buffer->width = bp_reply->width;
   scrn->front_buffer->height = bp_reply->height;
   scrn->front_buffer->shm_fence = shm_fence;
   scrn->front_buffer->sync_fence = sync_fence;
   free(bp_reply);

   return scrn->front_buffer;

free_reply:
   free(bp_reply);
unmap_shm:
   xshmfence_unmap_shm(shm_fence);
close_fd:
   close(fence_fd);
free_buffer:
   FREE(scrn->front_buffer);
   return NULL;
}
void draw(xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window) {
    if (NULL != testcase) {
        DRAW_FUNC pf = (DRAW_FUNC)dlsym(0, testcase);
        if (NULL != pf) {
            fprintf(stderr, "call %s \n", testcase);
            pf();
            return;
        }
    }

    //get_version();
   
    xcb_font_t font = xcb_generate_id(connection);
    xcb_void_cookie_t cookie_font = xcb_open_font_checked(connection, font, strlen(font_name_pattern), font_name_pattern);
    xcb_generic_error_t *error = xcb_request_check(connection, cookie_font);
    if (error) {
        fprintf(stderr, "ERROR: can't open font :%d\n", error->error_code);
        xcb_disconnect(connection);
        exit(0);
    }
    
    xcb_gcontext_t gc = xcb_generate_id(connection);
    uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
    uint32_t value_list[3];
    value_list[0] = screen->black_pixel;
    value_list[1] = screen->white_pixel;
    value_list[2] = font;
    xcb_void_cookie_t cookie_gc = xcb_create_gc_checked(connection, gc, window, mask, value_list);
    error = xcb_request_check(connection, cookie_gc);
    if (error) {
        fprintf(stderr, "ERROR: can't create gc: %d\n", error->error_code);
        xcb_disconnect(connection);
        exit(0);
    }

    cookie_font = xcb_close_font_checked(connection, font);
    error = xcb_request_check(connection, cookie_font);
    if (error) {
        fprintf(stderr, "ERROR: can't close font: %d\n", error->error_code);
        xcb_disconnect(connection);
        exit(0);
    }
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();

    glColor3f(1.0f, 0.0f, 0.0f);
    glRasterPos2f(0.0f, 0.0f);
    glPushAttrib(GL_LIST_BIT);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    static int isFirstCall = 1;
    static GLuint lists;
    if (isFirstCall) {
        lists = glGenLists(128);
    }
#if 1 
    //for (i = 0; i < sizeof(letters)
    glNewList(lists + 'A', GL_COMPILE);
    glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, letters[0]);
    glEndList();
    GLubyte *str = (GLubyte*)"A";
#else
    glXUseXFont(font, 0, 128, lists);
    GLubyte *str = (GLubyte*)"Hello, world.";
#endif
    glListBase(lists);
    glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
    glPopAttrib();
    glFlush();


/*    static int isFirstCall = 1;
    static GLuint lists;
    //load font
    //gen list
    if (isFirstCall) {
        lists = glGenLists(128);
    }

    glXUseXFont(font, 0, 128, lists);
    glListBase(lists);
    char *str = "Hello, world";
    for (; *str!='\0';++str) {
        glCallList(lists + *str);
    }
    glFlush();
    //glDeleteLists(lists, 256);
    //use font
    //draw text
    //unuse font?
    //delete list
    //unload font*/

    cookie_gc = xcb_free_gc(connection, gc);
    error = xcb_request_check(connection, cookie_gc);
    if (error) {
        fprintf(stderr, "ERROR: can't free gc: %d\n", error->error_code);
        xcb_disconnect(connection);
        exit(0);
    }
}
Exemple #29
0
extern bool gl_platform_init_swapchain(struct gs_swap_chain *swap)
{
	Display *display = swap->device->plat->display;
	struct gs_init_data *info = &swap->info;
	xcb_connection_t *xcb_conn = XGetXCBConnection(display);
	xcb_window_t wid = xcb_generate_id(xcb_conn);
	xcb_window_t parent = swap->info.window.id;
	xcb_get_geometry_reply_t *geometry =
		get_window_geometry(xcb_conn, parent);
	bool status = false;

	int screen_num;
	int visual;
	GLXFBConfig *fb_config;

	if (!geometry) goto fail_geometry_request;

	screen_num = get_screen_num_from_root(xcb_conn, geometry->root);
	if (screen_num == -1) {
		goto fail_screen;
	}

	/* NOTE:
	 * So GLX is odd. You can have different extensions per screen,
	 * not just per video card or visual.
	 *
	 * Because of this, it makes sense to call LoadGLX everytime
	 * we open a frackin' window. In Windows, entry points can change
	 * so it makes more sense there. Here, despite it virtually never
	 * having the possibility of changing unless the user is intentionally
	 * being an asshole to cause this behavior, we still have to give it
	 * the correct screen num just out of good practice. *sigh*
	 */
	if (!gladLoadGLX(display, screen_num)) {
		blog(LOG_ERROR, "Unable to load GLX entry functions.");
		goto fail_load_glx;
	}

	/* Define our FBConfig hints for GLX... */
	const int fb_attribs[] = {
		GLX_STENCIL_SIZE, get_stencil_format_bits(info->zsformat),
		GLX_DEPTH_SIZE, get_depth_format_bits(info->zsformat),
		GLX_BUFFER_SIZE, get_color_format_bits(info->format),
		GLX_DOUBLEBUFFER, true,
		GLX_X_RENDERABLE, true,
		None
	};

	/* ...fetch the best match... */
	{
		int num_configs;
		fb_config = glXChooseFBConfig(display, screen_num,
			                      fb_attribs, &num_configs);

		if (!fb_config || !num_configs) {
			blog(LOG_ERROR, "Failed to find FBConfig!");
			goto fail_fb_config;
		}
	}

	/* ...then fetch matching visual info for xcb. */
	{
		int error = glXGetFBConfigAttrib(display, fb_config[0], GLX_VISUAL_ID, &visual);

		if (error) {
			blog(LOG_ERROR, "Bad call to GetFBConfigAttrib!");
			goto fail_visual_id;
		}
	}


	xcb_colormap_t colormap = xcb_generate_id(xcb_conn);
	uint32_t mask = XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
	uint32_t mask_values[] = { 0, colormap, 0 };

	xcb_create_colormap(xcb_conn,
		XCB_COLORMAP_ALLOC_NONE,
		colormap,
		parent,
		visual
	);

	xcb_create_window(
		xcb_conn, 24 /* Hardcoded? */,
		wid, parent,
		0, 0,
		geometry->width,
		geometry->height,
		0, 0,
		visual, mask, mask_values
	);

	swap->wi->config = fb_config[0];
	swap->wi->window = wid;

	xcb_map_window(xcb_conn, wid);

	XFree(fb_config);
	status = true;
	goto success;

fail_visual_id:
	XFree(fb_config);
fail_fb_config:
fail_load_glx:
fail_screen:
fail_geometry_request:
success:
	free(geometry);
	return status;
}
Exemple #30
0
static void PRESENTForceReleases(PRESENTpriv *present_priv)
{
    PRESENTPixmapPriv *current = NULL;

    if (!present_priv->window)
        return;

    /* There should be no other thread listening for events here.
     * This can happen when hDestWindowOverride changes without reset.
     * This case should never happen, but can happen in theory.*/
    if (present_priv->xcb_wait) {
        xcb_present_notify_msc(present_priv->xcb_connection, present_priv->window, 0, 0, 0, 0);
        xcb_flush(present_priv->xcb_connection);
        pthread_mutex_lock(&present_priv->mutex_xcb_wait);
        pthread_mutex_unlock(&present_priv->mutex_xcb_wait);
        /* the problem here is that we don't have access to the event the other thread got.
         * It is either presented event, idle event or notify event.
         */
        while (present_priv->pixmap_present_pending >= 2)
            PRESENTwait_events(present_priv, FALSE);
        PRESENTflush_events(present_priv, TRUE);
        /* Remaining events to come can be a pair of present/idle,
         * or an idle, or nothing. To be sure we are after all pixmaps
         * have been presented, add an event to the queue that can only
         * be after the present event, then if we receive an event more,
         * we are sure all pixmaps were presented */
        present_priv->notify_with_serial_pending = TRUE;
        xcb_present_notify_msc(present_priv->xcb_connection, present_priv->window, 1, present_priv->last_target + 5, 0, 0);
        xcb_flush(present_priv->xcb_connection);
        while (present_priv->notify_with_serial_pending)
            PRESENTwait_events(present_priv, FALSE);
        /* Now we are sure we are not expecting any new event */
    } else {
        while (present_priv->pixmap_present_pending) /* wait all sent pixmaps are presented */
            PRESENTwait_events(present_priv, FALSE);
        PRESENTflush_events(present_priv, TRUE); /* may be remaining idle event */
        /* Since idle events are send with the complete events when it is not flips,
         * we are not expecting any new event here */
    }

    current = present_priv->first_present_priv;
    while (current) {
        if (!current->released) {
            if (!current->last_present_was_flip && !present_priv->xcb_wait) {
                ERR("ERROR: a pixmap seems not released by PRESENT for no reason. Code bug.\n");
            } else {
                /* Present the same pixmap with a non-valid part to force the copy mode and the releases */
                xcb_xfixes_region_t valid, update;
                xcb_rectangle_t rect_update;
                rect_update.x = 0;
                rect_update.y = 0;
                rect_update.width = 8;
                rect_update.height = 1;
                valid = xcb_generate_id(present_priv->xcb_connection);
                update = xcb_generate_id(present_priv->xcb_connection);
                xcb_xfixes_create_region(present_priv->xcb_connection, valid, 1, &rect_update);
                xcb_xfixes_create_region(present_priv->xcb_connection, update, 1, &rect_update);
                /* here we know the pixmap has been presented. Thus if it is on screen,
                 * the following request can only make it released by the server if it is not */
                xcb_present_pixmap(present_priv->xcb_connection, present_priv->window,
                                   current->pixmap, 0, valid, update, 0, 0, None, None,
                                   None, XCB_PRESENT_OPTION_COPY | XCB_PRESENT_OPTION_ASYNC, 0, 0, 0, 0, NULL);
                xcb_flush(present_priv->xcb_connection);
                PRESENTwait_events(present_priv, FALSE); /* by assumption this can only be idle event */
                PRESENTflush_events(present_priv, TRUE); /* Shoudln't be needed */
            }
        }
        current = current->next;
    }
    /* Now all pixmaps are released (possibility if xcb_wait is true that one is not aware yet),
     * and we don't expect any new Present event to come from Xserver */
}