egl/dri3: implement query surface hook
[mesa.git] / src / loader / loader_dri3_helper.c
index 67d0c2c2f3a1521112cb160067805ae331a5dd15..493a7f5218cd1c76bca8edd93dd3710cdb4b1794 100644 (file)
@@ -68,15 +68,10 @@ dri3_fence_await(xcb_connection_t *c, struct loader_dri3_buffer *buffer)
 static void
 dri3_update_num_back(struct loader_dri3_drawable *draw)
 {
-   draw->num_back = 1;
-   if (draw->flipping) {
-      if (!draw->is_pixmap &&
-          !(draw->present_capabilities & XCB_PRESENT_CAPABILITY_ASYNC))
-         draw->num_back++;
-      draw->num_back++;
-   }
-   if (draw->vtable->get_swap_interval(draw) == 0)
-      draw->num_back++;
+   if (draw->flipping)
+      draw->num_back = 3;
+   else
+      draw->num_back = 2;
 }
 
 void
@@ -100,9 +95,9 @@ dri3_free_render_buffer(struct loader_dri3_drawable *draw,
       xcb_free_pixmap(draw->conn, buffer->pixmap);
    xcb_sync_destroy_fence(draw->conn, buffer->sync_fence);
    xshmfence_unmap_shm(buffer->shm_fence);
-   (draw->ext->image->destroyImage)(buffer->image);
+   draw->ext->image->destroyImage(buffer->image);
    if (buffer->linear_buffer)
-      (draw->ext->image->destroyImage)(buffer->linear_buffer);
+      draw->ext->image->destroyImage(buffer->linear_buffer);
    free(buffer);
 }
 
@@ -111,15 +106,21 @@ loader_dri3_drawable_fini(struct loader_dri3_drawable *draw)
 {
    int i;
 
-   (draw->ext->core->destroyDrawable)(draw->dri_drawable);
+   draw->ext->core->destroyDrawable(draw->dri_drawable);
 
    for (i = 0; i < LOADER_DRI3_NUM_BUFFERS; i++) {
       if (draw->buffers[i])
          dri3_free_render_buffer(draw, draw->buffers[i]);
    }
 
-   if (draw->special_event)
+   if (draw->special_event) {
+      xcb_void_cookie_t cookie =
+         xcb_present_select_input_checked(draw->conn, draw->eid, draw->drawable,
+                                          XCB_PRESENT_EVENT_MASK_NO_EVENT);
+
+      xcb_discard_reply(draw->conn, cookie.sequence);
       xcb_unregister_for_special_event(draw->conn, draw->special_event);
+   }
 }
 
 int
@@ -129,7 +130,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
                           bool is_different_gpu,
                           const __DRIconfig *dri_config,
                           struct loader_dri3_extensions *ext,
-                          struct loader_dri3_vtable *vtable,
+                          const struct loader_dri3_vtable *vtable,
                           struct loader_dri3_drawable *draw)
 {
    xcb_get_geometry_cookie_t cookie;
@@ -170,9 +171,9 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
 
    /* Create a new drawable */
    draw->dri_drawable =
-      (draw->ext->image_driver->createNewDrawable)(dri_screen,
-                                                   dri_config,
-                                                   draw);
+      draw->ext->image_driver->createNewDrawable(dri_screen,
+                                                 dri_config,
+                                                 draw);
 
    if (!draw->dri_drawable)
       return 1;
@@ -739,7 +740,7 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
          ++(*draw->stamp);
    }
 
-   (draw->ext->flush->invalidate)(draw->dri_drawable);
+   draw->ext->flush->invalidate(draw->dri_drawable);
 
    return ret;
 }
@@ -855,34 +856,34 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
       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);
+      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);
+      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);
+        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)
@@ -891,14 +892,14 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
 
    /* X wants the stride, so ask the image for it
     */
-   if (!(draw->ext->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_STRIDE,
-                                       &stride))
+   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))
+   if (!draw->ext->image->queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD,
+                                     &buffer_fd))
       goto no_buffer_attrib;
 
    xcb_dri3_pixmap_from_buffer(draw->conn,
@@ -929,10 +930,10 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
    return buffer;
 
 no_buffer_attrib:
-   (draw->ext->image->destroyImage)(pixmap_buffer);
+   draw->ext->image->destroyImage(pixmap_buffer);
 no_linear_buffer:
    if (draw->is_different_gpu)
-      (draw->ext->image->destroyImage)(buffer->image);
+      draw->ext->image->destroyImage(buffer->image);
 no_image:
    free(buffer);
 no_buffer:
@@ -1081,19 +1082,19 @@ loader_dri3_create_image(xcb_connection_t *c,
     * we've gotten the planar wrapper, pull the single plane out of it and
     * discard the wrapper.
     */
-   image_planar = (image->createImageFromFds)(dri_screen,
-                                              bp_reply->width,
-                                              bp_reply->height,
-                                              image_format_to_fourcc(format),
-                                              fds, 1,
-                                              &stride, &offset, loaderPrivate);
+   image_planar = image->createImageFromFds(dri_screen,
+                                            bp_reply->width,
+                                            bp_reply->height,
+                                            image_format_to_fourcc(format),
+                                            fds, 1,
+                                            &stride, &offset, loaderPrivate);
    close(fds[0]);
    if (!image_planar)
       return NULL;
 
-   ret = (image->fromPlanar)(image_planar, 0, loaderPrivate);
+   ret = image->fromPlanar(image_planar, 0, loaderPrivate);
 
-   (image->destroyImage)(image_planar);
+   image->destroyImage(image_planar);
 
    return ret;
 }
@@ -1116,6 +1117,7 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
    xcb_sync_fence_t                     sync_fence;
    struct xshmfence                     *shm_fence;
    int                                  fence_fd;
+   __DRIscreen                          *cur_screen;
 
    if (buffer)
       return buffer;
@@ -1146,8 +1148,17 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format,
    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,
-                                            draw->dri_screen, draw->ext->image,
+                                            cur_screen, draw->ext->image,
                                             buffer);
    if (!buffer->image)
       goto no_image;
@@ -1397,3 +1408,26 @@ loader_dri3_get_buffers(__DRIdrawable *driDrawable,
 
    return true;
 }
+
+/** loader_dri3_update_drawable_geometry
+ *
+ * Get the current drawable geometry.
+ */
+void
+loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw)
+{
+   xcb_get_geometry_cookie_t geom_cookie;
+   xcb_get_geometry_reply_t *geom_reply;
+
+   geom_cookie = xcb_get_geometry(draw->conn, draw->drawable);
+
+   geom_reply = xcb_get_geometry_reply(draw->conn, geom_cookie, NULL);
+
+   if (geom_reply) {
+      draw->width = geom_reply->width;
+      draw->height = geom_reply->height;
+      draw->vtable->set_drawable_size(draw, draw->width, draw->height);
+
+      free(geom_reply);
+   }
+}