Exemplo n.º 1
0
static bool
dri3_set_drawable(struct vl_dri3_screen *scrn, Drawable drawable)
{
   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_event_t peid;
   bool ret = true;

   assert(drawable);

   if (scrn->drawable == drawable)
      return true;

   scrn->drawable = drawable;

   geom_cookie = xcb_get_geometry(scrn->conn, scrn->drawable);
   geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL);
   if (!geom_reply)
      return false;

   scrn->width = geom_reply->width;
   scrn->height = geom_reply->height;
   scrn->depth = geom_reply->depth;
   free(geom_reply);

   if (scrn->special_event) {
      xcb_unregister_for_special_event(scrn->conn, scrn->special_event);
      scrn->special_event = NULL;
   }

   scrn->is_pixmap = false;
   peid = xcb_generate_id(scrn->conn);
   cookie =
      xcb_present_select_input_checked(scrn->conn, peid, scrn->drawable,
                      XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
                      XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
                      XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);

   error = xcb_request_check(scrn->conn, cookie);
   if (error) {
      if (error->error_code != BadWindow)
         ret = false;
      else {
         scrn->is_pixmap = true;
         if (scrn->front_buffer) {
            dri3_free_front_buffer(scrn, scrn->front_buffer);
            scrn->front_buffer = NULL;
         }
      }
      free(error);
   } else
      scrn->special_event =
         xcb_register_for_special_xge(scrn->conn, &xcb_present_id, peid, 0);

   dri3_flush_present_events(scrn);

   return ret;
}
Exemplo n.º 2
0
Arquivo: dri3.c Projeto: sarnex/wine
static BOOL PRESENTPrivChangeWindow(PRESENTpriv *present_priv, XID window)
{
    xcb_void_cookie_t cookie;
    xcb_generic_error_t *error;
    xcb_present_event_t eid;

    PRESENTForceReleases(present_priv);
    PRESENTFreeXcbQueue(present_priv);
    present_priv->window = window;

    if (window) {
        cookie = xcb_present_select_input_checked(present_priv->xcb_connection,
                                                  (eid = xcb_generate_id(present_priv->xcb_connection)),
                                                  window,
                                                  XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
                                                  XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
        present_priv->special_event = xcb_register_for_special_xge(present_priv->xcb_connection,
                                                                   &xcb_present_id,
                                                                   eid, NULL);
        error = xcb_request_check(present_priv->xcb_connection, cookie); /* performs a flush */
        if (error || !present_priv->special_event) {
            ERR("FAILED to use the X PRESENT extension. Was the destination a window ?\n");
            if (present_priv->special_event)
                xcb_unregister_for_special_event(present_priv->xcb_connection, present_priv->special_event);
            present_priv->special_event = NULL;
            present_priv->window = 0;
        }
    }
    return (present_priv->window != 0);
}
Exemplo n.º 3
0
Arquivo: core.hpp Projeto: jotrk/xpp
 // xcb_special_event_t has incomplete type -> no std::shared_ptr
 virtual
 xcb_special_event_t *
 register_for_special_xge(xcb_extension_t * ext,
                          uint32_t eid,
                          uint32_t * stamp) const
 {
   return xcb_register_for_special_xge(m_c.get(), ext, eid, stamp);
 }
Exemplo n.º 4
0
/** 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;
}
Exemplo n.º 5
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;
}