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
loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
{
- interval = draw->vtable->clamp_swap_interval(draw, interval);
draw->vtable->set_swap_interval(draw, interval);
dri3_update_num_back(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);
}
{
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
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;
/* 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;
x, y, width, height, __BLIT_FLAG_FLUSH);
}
+ loader_dri3_swapbuffer_barrier(draw);
dri3_fence_reset(draw->conn, back);
dri3_copy_area(draw->conn,
dri3_back_buffer(draw)->pixmap,
front->height,
0, 0, front->width,
front->height, __BLIT_FLAG_FLUSH);
+ loader_dri3_swapbuffer_barrier(draw);
loader_dri3_copy_drawable(draw, draw->drawable, front->pixmap);
}
draw->vtable->flush_drawable(draw, flush_flags);
- back = draw->buffers[LOADER_DRI3_BACK_ID(draw->cur_back)];
+ back = draw->buffers[dri3_find_back(draw)];
if (draw->is_different_gpu && back) {
/* Update the linear buffer before presenting the pixmap */
draw->ext->image->blitImage(dri_context,
++(*draw->stamp);
}
- (draw->ext->flush->invalidate)(draw->dri_drawable);
+ draw->ext->flush->invalidate(draw->dri_drawable);
return ret;
}
}
fd = xcb_dri3_open_reply_fds(conn, reply)[0];
+ free(reply);
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
return fd;
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)
/* 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,
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:
* 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;
}
xcb_sync_fence_t sync_fence;
struct xshmfence *shm_fence;
int fence_fd;
+ __DRIscreen *cur_screen;
if (buffer)
return buffer;
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;
}
break;
case loader_dri3_buffer_front:
+ loader_dri3_swapbuffer_barrier(draw);
dri3_fence_reset(draw->conn, new_buffer);
dri3_copy_area(draw->conn,
draw->drawable,
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);
+ }
+}
+
+
+/**
+ * Make sure the server has flushed all pending swap buffers to hardware
+ * for this drawable. Ideally we'd want to send an X protocol request to
+ * have the server block our connection until the swaps are complete. That
+ * would avoid the potential round-trip here.
+ */
+void
+loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw)
+{
+ int64_t ust, msc, sbc;
+
+ (void) loader_dri3_wait_for_sbc(draw, 0, &ust, &msc, &sbc);
+}