x11/dri3: Store raw present completion mode
[mesa.git] / src / loader / loader_dri3_helper.c
index fbda3d635c75e4a3fc6e928a9885494b0b1267f1..426966a786afdbac5a7910846de9d63d49190e95 100644 (file)
@@ -33,6 +33,7 @@
 #include <X11/Xlib-xcb.h>
 
 #include "loader_dri3_helper.h"
+#include "util/macros.h"
 
 /* From xmlpool/options.h, user exposed so should be stable */
 #define DRI_CONF_VBLANK_NEVER 0
@@ -195,7 +196,7 @@ dri3_fence_await(xcb_connection_t *c, struct loader_dri3_drawable *draw,
 static void
 dri3_update_num_back(struct loader_dri3_drawable *draw)
 {
-   if (draw->flipping)
+   if (draw->last_present_mode == XCB_PRESENT_COMPLETE_MODE_FLIP)
       draw->num_back = 3;
    else
       draw->num_back = 2;
@@ -233,7 +234,7 @@ loader_dri3_drawable_fini(struct loader_dri3_drawable *draw)
 
    draw->ext->core->destroyDrawable(draw->dri_drawable);
 
-   for (i = 0; i < LOADER_DRI3_NUM_BUFFERS; i++) {
+   for (i = 0; i < ARRAY_SIZE(draw->buffers); i++) {
       if (draw->buffers[i])
          dri3_free_render_buffer(draw, draw->buffers[i]);
    }
@@ -368,14 +369,8 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw,
          draw->recv_sbc = (draw->send_sbc & 0xffffffff00000000LL) | ce->serial;
          if (draw->recv_sbc > draw->send_sbc)
             draw->recv_sbc -= 0x100000000;
-         switch (ce->mode) {
-         case XCB_PRESENT_COMPLETE_MODE_FLIP:
-            draw->flipping = true;
-            break;
-         case XCB_PRESENT_COMPLETE_MODE_COPY:
-            draw->flipping = false;
-            break;
-         }
+
+         draw->last_present_mode = ce->mode;
 
          if (draw->vtable->show_fps)
             draw->vtable->show_fps(draw, ce->ust);
@@ -392,7 +387,7 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw,
       xcb_present_idle_notify_event_t *ie = (void *) ge;
       int b;
 
-      for (b = 0; b < sizeof(draw->buffers) / sizeof(draw->buffers[0]); b++) {
+      for (b = 0; b < ARRAY_SIZE(draw->buffers); b++) {
          struct loader_dri3_buffer *buf = draw->buffers[b];
 
          if (buf && buf->pixmap == ie->pixmap)
@@ -993,6 +988,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 +1017,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 +1287,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 +1313,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 +1344,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;