loader_dri3/glx/egl: Reinstate the loader_dri3_vtable get_dri_screen callback
[mesa.git] / src / loader / loader_dri3_helper.c
index cc890bc923d56a39e0d575f7c6dbcc96da707b65..30ea133f7e57b508cd7e429e06c1b3b98be7931f 100644 (file)
@@ -205,7 +205,6 @@ void
 loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
 {
    draw->swap_interval = interval;
-   dri3_update_num_back(draw);
 }
 
 /** dri3_free_render_buffer
@@ -377,15 +376,13 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw,
             draw->flipping = false;
             break;
          }
-         dri3_update_num_back(draw);
 
          if (draw->vtable->show_fps)
             draw->vtable->show_fps(draw, ce->ust);
 
          draw->ust = ce->ust;
          draw->msc = ce->msc;
-      } else {
-         draw->recv_msc_serial = ce->serial;
+      } else if (ce->serial == draw->eid) {
          draw->notify_ust = ce->ust;
          draw->notify_msc = ce->msc;
       }
@@ -402,7 +399,8 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw,
             buf->busy = 0;
 
          if (buf && draw->num_back <= b && b < LOADER_DRI3_MAX_BACK &&
-             draw->cur_blit_source != b) {
+             draw->cur_blit_source != b &&
+             !buf->busy) {
             dri3_free_render_buffer(draw, buf);
             draw->buffers[b] = NULL;
          }
@@ -453,28 +451,29 @@ loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw,
                          int64_t divisor, int64_t remainder,
                          int64_t *ust, int64_t *msc, int64_t *sbc)
 {
-   uint32_t msc_serial;
-
-   msc_serial = ++draw->send_msc_serial;
-   xcb_present_notify_msc(draw->conn,
-                          draw->drawable,
-                          msc_serial,
-                          target_msc,
-                          divisor,
-                          remainder);
+   xcb_void_cookie_t cookie = xcb_present_notify_msc(draw->conn,
+                                                     draw->drawable,
+                                                     draw->eid,
+                                                     target_msc,
+                                                     divisor,
+                                                     remainder);
+   xcb_generic_event_t *ev;
+   unsigned full_sequence;
 
    mtx_lock(&draw->mtx);
    xcb_flush(draw->conn);
 
    /* Wait for the event */
-   if (draw->special_event) {
-      while ((int32_t) (msc_serial - draw->recv_msc_serial) > 0) {
-         if (!dri3_wait_for_event_locked(draw)) {
-            mtx_unlock(&draw->mtx);
-            return false;
-         }
+   do {
+      ev = xcb_wait_for_special_event(draw->conn, draw->special_event);
+      if (!ev) {
+         mtx_unlock(&draw->mtx);
+         return false;
       }
-   }
+
+      full_sequence = ev->full_sequence;
+      dri3_handle_present_event(draw, (void *) ev);
+   } while (full_sequence != cookie.sequence || draw->notify_msc < target_msc);
 
    *ust = draw->notify_ust;
    *msc = draw->notify_msc;
@@ -537,6 +536,7 @@ dri3_find_back(struct loader_dri3_drawable *draw)
    /* Check whether we need to reuse the current back buffer as new back.
     * In that case, wait until it's not busy anymore.
     */
+   dri3_update_num_back(draw);
    num_to_consider = draw->num_back;
    if (!loader_dri3_have_image_blit(draw) && draw->cur_blit_source != -1) {
       num_to_consider = 1;
@@ -993,6 +993,8 @@ dri3_cpp_for_format(uint32_t format) {
    case  __DRI_IMAGE_FORMAT_XBGR8888:
    case  __DRI_IMAGE_FORMAT_XRGB2101010:
    case  __DRI_IMAGE_FORMAT_ARGB2101010:
+   case  __DRI_IMAGE_FORMAT_XBGR2101010:
+   case  __DRI_IMAGE_FORMAT_ABGR2101010:
    case  __DRI_IMAGE_FORMAT_SARGB8:
       return 4;
    case  __DRI_IMAGE_FORMAT_NONE:
@@ -1020,6 +1022,8 @@ image_format_to_fourcc(int format)
    case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
    case __DRI_IMAGE_FORMAT_XRGB2101010: return __DRI_IMAGE_FOURCC_XRGB2101010;
    case __DRI_IMAGE_FORMAT_ARGB2101010: return __DRI_IMAGE_FOURCC_ARGB2101010;
+   case __DRI_IMAGE_FORMAT_XBGR2101010: return __DRI_IMAGE_FOURCC_XBGR2101010;
+   case __DRI_IMAGE_FORMAT_ABGR2101010: return __DRI_IMAGE_FOURCC_ABGR2101010;
    }
    return 0;
 }
@@ -1288,7 +1292,10 @@ loader_dri3_create_image(xcb_connection_t *c,
 
    ret = image->fromPlanar(image_planar, 0, loaderPrivate);
 
-   image->destroyImage(image_planar);
+   if (!ret)
+      ret = image_planar;
+   else
+      image->destroyImage(image_planar);
 
    return ret;
 }
@@ -1311,6 +1318,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;
@@ -1341,8 +1349,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();
+   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;