x11: Remove DRI2 support

DRI2 was hidden behind a legacy-x11 build option back in the 24.2
release. It's now been a year, so let's get on with removing it so we
can simplify our winsys interactions.

Signed-off-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35885>
This commit is contained in:
Daniel Stone 2025-07-02 13:21:28 +01:00 committed by Marge Bot
parent b0624f4034
commit 08c6ba223b
23 changed files with 22 additions and 2682 deletions

View file

@ -188,7 +188,6 @@ debian-build-x86_64:
-D egl=enabled
-D glvnd=disabled
-D platforms=x11,wayland
-D legacy-x11=dri2
GALLIUM_ST: >
-D gallium-extra-hud=true
-D gallium-vdpau=enabled

View file

@ -153,8 +153,7 @@ EGL Drivers
This driver supports several platforms: ``android``, ``device``,
``drm``, ``surfaceless``, ``wayland`` and ``x11``. It functions as
a DRI driver loader. For ``x11`` support, it talks to the X server
directly using (XCB-)DRI3 protocol when available, and falls back to
DRI2 if necessary (can be forced with ``LIBGL_DRI3_DISABLE``).
directly using (XCB-)DRI3 protocol when available.
This driver can share DRI drivers with ``libGL``.

View file

@ -26,14 +26,6 @@ LibGL environment variables
if set to ``true``, do not use DrawArrays GLX protocol (for
debugging)
.. envvar:: LIBGL_DRI2_DISABLE
disable DRI2 if set to ``true``.
.. envvar:: LIBGL_DRI3_DISABLE
disable DRI3 if set to ``true``.
.. envvar:: LIBGL_KOPPER_DISABLE
disable Vulkan swapchains with Zink if set to ``true``.

View file

@ -63,3 +63,4 @@ timestamps on panvk/v10+
VK_KHR_calibrated_timestamps on panvk/v10+
VK_EXT_non_seamless_cube_map on panvk
VK_ARM_shader_core_properties on panvk/v10+
removed X11 DRI2 support

View file

@ -581,8 +581,6 @@ endif
with_dri2 = (with_dri or with_any_vk) and (with_dri_platform == 'drm' or with_dri_platform == 'apple')
with_x11_dri2 = with_dri2 and get_option('legacy-x11').contains('dri2')
if with_dri
if with_glx == 'disabled' and not with_egl and not with_gbm
error('building dri drivers require at least one windowing system')
@ -2020,7 +2018,6 @@ endif
dep_x11 = null_dep
dep_xext = null_dep
dep_xfixes = null_dep
dep_x11_xcb = null_dep
dep_xcb = null_dep
dep_xcb_keysyms = null_dep
@ -2044,7 +2041,6 @@ dep_xcb_dri2_version = '>= 1.8'
dep_xcb_dri3_version = '>= 1.13'
dep_xcb_glx_version = '>= 1.8.1'
dep_xcb_present_version = '>= 1.13'
dep_xfixes_version = '>= 2.0'
dep_xlib_xrandr_version = '>= 1.3'
dep_xshmfence_version = '>= 1.1'
@ -2059,7 +2055,6 @@ if with_platform_x11
elif with_glx == 'dri'
dep_x11 = dependency('x11')
dep_xext = dependency('xext')
dep_xfixes = dependency('xfixes', version : dep_xfixes_version)
dep_xcb_glx = dependency('xcb-glx', version : dep_xcb_glx_version)
dep_xcb_shm = dependency('xcb-shm')
elif with_gallium_rusticl
@ -2075,14 +2070,11 @@ if with_platform_x11
pre_args += '-DXCB_KEYSYMS_AVAILABLE'
endif
dep_x11_xcb = dependency('x11-xcb')
dep_xcb_dri2 = dependency('xcb-dri2', version : dep_xcb_dri2_version, required : with_x11_dri2)
if with_dri_platform == 'drm' and not dep_libdrm.found()
error('libdrm required for gallium video statetrackers when using x11')
endif
endif
if with_dri_platform == 'drm'
dep_xcb_dri2 = dependency('xcb-dri2', version : dep_xcb_dri2_version, required : with_x11_dri2)
dep_xcb_dri3 = dependency('xcb-dri3', version : dep_xcb_dri3_version)
dep_xcb_present = dependency('xcb-present', version : dep_xcb_present_version)
if (dep_xcb_dri3.version().version_compare('>= 1.17') and
@ -2131,9 +2123,6 @@ endif
if with_dri2
pre_args += '-DHAVE_DRI2'
endif
if with_x11_dri2
pre_args += '-DHAVE_X11_DRI2'
endif
if with_dri3_explicit_sync
pre_args += '-DHAVE_DRI3_EXPLICIT_SYNC'
endif

View file

@ -783,7 +783,6 @@ option(
value : [],
description : 'Build legacy X11 support features.',
choices : [
'dri2'
],
)

View file

@ -886,7 +886,6 @@ dri2_initialize(_EGLDisplay *disp)
loader_set_logger(_eglLog);
bool allow_dri2 = false;
switch (disp->Platform) {
case _EGL_PLATFORM_SURFACELESS:
ret = dri2_initialize_surfaceless(disp);
@ -896,17 +895,7 @@ dri2_initialize(_EGLDisplay *disp)
break;
case _EGL_PLATFORM_X11:
case _EGL_PLATFORM_XCB:
ret = dri2_initialize_x11(disp, &allow_dri2);
/* platform_x11 detects dri2 availability */
if (!ret && allow_dri2) {
/* this is a fallthrough using the same dri2_dpy from dri3,
* so the existing one must be destroyed and a new one created
* the caller will switch to the new display automatically
*/
dri2_display_destroy(disp);
dri2_display_create(disp);
ret = dri2_initialize_x11_dri2(disp);
}
ret = dri2_initialize_x11(disp);
break;
case _EGL_PLATFORM_DRM:
ret = dri2_initialize_drm(disp);

View file

@ -33,9 +33,6 @@
#ifdef HAVE_X11_PLATFORM
#include <X11/Xlib-xcb.h>
#ifdef HAVE_X11_DRI2
#include <xcb/dri2.h>
#endif
#include <xcb/randr.h>
#include <xcb/xcb.h>
#include <xcb/xfixes.h>
@ -502,21 +499,14 @@ dri2_create_image_from_dri(_EGLDisplay *disp, struct dri_image *dri_image);
#ifdef HAVE_X11_PLATFORM
EGLBoolean
dri2_initialize_x11_dri2(_EGLDisplay *disp);
EGLBoolean
dri2_initialize_x11(_EGLDisplay *disp, bool *allow_dri2);
dri2_initialize_x11(_EGLDisplay *disp);
void
dri2_teardown_x11(struct dri2_egl_display *dri2_dpy);
unsigned int
dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth);
#else
static inline EGLBoolean
dri2_initialize_x11_dri2(_EGLDisplay *disp)
{
return _eglError(EGL_NOT_INITIALIZED, "X11 platform not built");
}
static inline EGLBoolean
dri2_initialize_x11(_EGLDisplay *disp, bool *allow_dri2)
dri2_initialize_x11(_EGLDisplay *disp)
{
return _eglError(EGL_NOT_INITIALIZED, "X11 platform not built");
}

View file

@ -476,36 +476,10 @@ dri2_x11_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
goto cleanup_pixmap;
#ifdef HAVE_X11_DRI2
if (!dri2_dpy->swrast) {
xcb_void_cookie_t cookie;
int conn_error;
cookie =
xcb_dri2_create_drawable_checked(dri2_dpy->conn, dri2_surf->drawable);
error = xcb_request_check(dri2_dpy->conn, cookie);
conn_error = xcb_connection_has_error(dri2_dpy->conn);
if (conn_error || error != NULL) {
if (type == EGL_PBUFFER_BIT || conn_error ||
error->error_code == BadAlloc)
_eglError(EGL_BAD_ALLOC, "xcb_dri2_create_drawable_checked");
else if (type == EGL_WINDOW_BIT)
_eglError(EGL_BAD_NATIVE_WINDOW,
"xcb_dri2_create_drawable_checked");
else
_eglError(EGL_BAD_NATIVE_PIXMAP,
"xcb_dri2_create_drawable_checked");
free(error);
goto cleanup_dri_drawable;
}
} else
#endif
{
if (type == EGL_PBUFFER_BIT) {
dri2_surf->depth = conf->BufferSize;
}
swrastCreateDrawable(dri2_dpy, dri2_surf);
}
return &dri2_surf->base;
@ -569,13 +543,8 @@ dri2_x11_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
driDestroyDrawable(dri2_surf->dri_drawable);
if (!dri2_dpy->swrast) {
#ifdef HAVE_X11_DRI2
xcb_dri2_destroy_drawable(dri2_dpy->conn, dri2_surf->drawable);
#endif
} else {
if (dri2_dpy->swrast)
swrastDestroyDrawable(dri2_dpy, dri2_surf);
}
if (surf->Type == EGL_PBUFFER_BIT)
xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
@ -621,299 +590,6 @@ dri2_query_surface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
return _eglQuerySurface(disp, surf, attribute, value);
}
#ifdef HAVE_X11_DRI2
/**
* Process list of buffer received from the server
*
* Processes the list of buffers received in a reply from the server to either
* \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
*/
static void
dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf,
xcb_dri2_dri2_buffer_t *buffers, unsigned count)
{
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
xcb_rectangle_t rectangle;
dri2_surf->have_fake_front = false;
/* This assumes the DRI2 buffer attachment tokens matches the
* __DRIbuffer tokens. */
for (unsigned i = 0; i < count; i++) {
dri2_surf->buffers[i].attachment = buffers[i].attachment;
dri2_surf->buffers[i].name = buffers[i].name;
dri2_surf->buffers[i].pitch = buffers[i].pitch;
dri2_surf->buffers[i].cpp = buffers[i].cpp;
dri2_surf->buffers[i].flags = buffers[i].flags;
/* We only use the DRI drivers single buffer configs. This
* means that if we try to render to a window, DRI2 will give us
* the fake front buffer, which we'll use as a back buffer.
* Note that EGL doesn't require that several clients rendering
* to the same window must see the same aux buffers. */
if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
dri2_surf->have_fake_front = true;
}
if (dri2_surf->region != XCB_NONE)
xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
rectangle.x = 0;
rectangle.y = 0;
rectangle.width = dri2_surf->base.Width;
rectangle.height = dri2_surf->base.Height;
dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
}
static __DRIbuffer *
dri2_x11_get_buffers(struct dri_drawable *driDrawable, int *width, int *height,
unsigned int *attachments, int count, int *out_count,
void *loaderPrivate)
{
struct dri2_egl_surface *dri2_surf = loaderPrivate;
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
xcb_dri2_dri2_buffer_t *buffers;
xcb_dri2_get_buffers_reply_t *reply;
xcb_dri2_get_buffers_cookie_t cookie;
(void)driDrawable;
cookie = xcb_dri2_get_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable,
count, count, attachments);
reply = xcb_dri2_get_buffers_reply(dri2_dpy->conn, cookie, NULL);
if (reply == NULL)
return NULL;
buffers = xcb_dri2_get_buffers_buffers(reply);
if (buffers == NULL) {
free(reply);
return NULL;
}
*out_count = reply->count;
dri2_surf->base.Width = *width = reply->width;
dri2_surf->base.Height = *height = reply->height;
dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
free(reply);
return dri2_surf->buffers;
}
static __DRIbuffer *
dri2_x11_get_buffers_with_format(struct dri_drawable *driDrawable, int *width,
int *height, unsigned int *attachments,
int count, int *out_count, void *loaderPrivate)
{
struct dri2_egl_surface *dri2_surf = loaderPrivate;
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
xcb_dri2_dri2_buffer_t *buffers;
xcb_dri2_get_buffers_with_format_reply_t *reply;
xcb_dri2_get_buffers_with_format_cookie_t cookie;
xcb_dri2_attach_format_t *format_attachments;
(void)driDrawable;
format_attachments = (xcb_dri2_attach_format_t *)attachments;
cookie = xcb_dri2_get_buffers_with_format_unchecked(
dri2_dpy->conn, dri2_surf->drawable, count, count, format_attachments);
reply = xcb_dri2_get_buffers_with_format_reply(dri2_dpy->conn, cookie, NULL);
if (reply == NULL)
return NULL;
buffers = xcb_dri2_get_buffers_with_format_buffers(reply);
dri2_surf->base.Width = *width = reply->width;
dri2_surf->base.Height = *height = reply->height;
*out_count = reply->count;
dri2_x11_process_buffers(dri2_surf, buffers, *out_count);
free(reply);
return dri2_surf->buffers;
}
static void
dri2_x11_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
{
(void)driDrawable;
/* FIXME: Does EGL support front buffer rendering at all? */
#if 0
struct dri2_egl_surface *dri2_surf = loaderPrivate;
dri2WaitGL(dri2_surf);
#else
(void)loaderPrivate;
#endif
}
static int
dri2_x11_do_authenticate(struct dri2_egl_display *dri2_dpy, uint32_t id)
{
xcb_dri2_authenticate_reply_t *authenticate;
xcb_dri2_authenticate_cookie_t authenticate_cookie;
int ret = 0;
authenticate_cookie = xcb_dri2_authenticate_unchecked(
dri2_dpy->conn, dri2_dpy->screen->root, id);
authenticate =
xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
if (authenticate == NULL || !authenticate->authenticated)
ret = -1;
free(authenticate);
return ret;
}
static EGLBoolean
dri2_x11_local_authenticate(struct dri2_egl_display *dri2_dpy)
{
#ifdef HAVE_LIBDRM
drm_magic_t magic;
if (drmGetMagic(dri2_dpy->fd_render_gpu, &magic)) {
_eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
return EGL_FALSE;
}
if (dri2_x11_do_authenticate(dri2_dpy, magic) < 0) {
_eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
return EGL_FALSE;
}
#endif
return EGL_TRUE;
}
static EGLBoolean
dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
{
xcb_xfixes_query_version_reply_t *xfixes_query;
xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
xcb_dri2_query_version_reply_t *dri2_query;
xcb_dri2_query_version_cookie_t dri2_query_cookie;
xcb_dri2_connect_reply_t *connect;
xcb_dri2_connect_cookie_t connect_cookie;
xcb_generic_error_t *error;
char *driver_name, *loader_driver_name, *device_name;
const xcb_query_extension_reply_t *extension;
xcb_prefetch_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
xcb_prefetch_extension_data(dri2_dpy->conn, &xcb_dri2_id);
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
if (!(extension && extension->present))
return EGL_FALSE;
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id);
if (!(extension && extension->present))
return EGL_FALSE;
xfixes_query_cookie = xcb_xfixes_query_version(
dri2_dpy->conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
dri2_query_cookie = xcb_dri2_query_version(
dri2_dpy->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION);
connect_cookie = xcb_dri2_connect_unchecked(
dri2_dpy->conn, dri2_dpy->screen->root, XCB_DRI2_DRIVER_TYPE_DRI);
xfixes_query = xcb_xfixes_query_version_reply(dri2_dpy->conn,
xfixes_query_cookie, &error);
if (xfixes_query == NULL || error != NULL ||
xfixes_query->major_version < 2) {
_eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
free(error);
free(xfixes_query);
return EGL_FALSE;
}
free(xfixes_query);
dri2_query =
xcb_dri2_query_version_reply(dri2_dpy->conn, dri2_query_cookie, &error);
if (dri2_query == NULL || error != NULL) {
_eglLog(_EGL_WARNING, "DRI2: failed to query version");
free(error);
free(dri2_query);
return EGL_FALSE;
}
dri2_dpy->dri2_major = dri2_query->major_version;
dri2_dpy->dri2_minor = dri2_query->minor_version;
free(dri2_query);
connect = xcb_dri2_connect_reply(dri2_dpy->conn, connect_cookie, NULL);
if (connect == NULL ||
connect->driver_name_length + connect->device_name_length == 0) {
_eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
free(connect);
return EGL_FALSE;
}
device_name = xcb_dri2_connect_device_name(connect);
dri2_dpy->fd_render_gpu = loader_open_device(device_name);
if (dri2_dpy->fd_render_gpu == -1) {
_eglLog(_EGL_WARNING, "DRI2: could not open %s (%s)", device_name,
strerror(errno));
free(connect);
return EGL_FALSE;
}
if (!dri2_x11_local_authenticate(dri2_dpy)) {
close(dri2_dpy->fd_render_gpu);
free(connect);
return EGL_FALSE;
}
driver_name = xcb_dri2_connect_driver_name(connect);
/* If Mesa knows about the appropriate driver for this fd, then trust it.
* Otherwise, default to the server's value.
*/
loader_driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu);
if (loader_driver_name) {
dri2_dpy->driver_name = loader_driver_name;
} else {
dri2_dpy->driver_name =
strndup(driver_name, xcb_dri2_connect_driver_name_length(connect));
}
if (!strcmp(dri2_dpy->driver_name, "zink")) {
close(dri2_dpy->fd_render_gpu);
return EGL_FALSE;
}
if (dri2_dpy->driver_name == NULL) {
close(dri2_dpy->fd_render_gpu);
free(connect);
return EGL_FALSE;
}
#ifdef HAVE_WAYLAND_PLATFORM
dri2_dpy->device_name =
strndup(device_name, xcb_dri2_connect_device_name_length(connect));
#endif
free(connect);
return EGL_TRUE;
}
static int
dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
return dri2_x11_do_authenticate(dri2_dpy, id);
}
#endif
static void
dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
_EGLDisplay *disp, bool supports_preserved)
@ -1014,86 +690,6 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
}
}
#ifdef HAVE_X11_DRI2
static EGLBoolean
dri2_copy_region(_EGLDisplay *disp, _EGLSurface *draw,
xcb_xfixes_region_t region)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
enum xcb_dri2_attachment_t render_attachment;
xcb_dri2_copy_region_cookie_t cookie;
/* No-op for a pixmap or pbuffer surface */
if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
return EGL_TRUE;
assert(!dri2_dpy->kopper);
dri_flush_drawable(dri2_surf->dri_drawable);
if (dri2_surf->have_fake_front)
render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
else
render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
cookie = xcb_dri2_copy_region_unchecked(
dri2_dpy->conn, dri2_surf->drawable, region,
XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, render_attachment);
free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
return EGL_TRUE;
}
static int64_t
dri2_x11_swap_buffers_msc(_EGLDisplay *disp, _EGLSurface *draw, int64_t msc,
int64_t divisor, int64_t remainder)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
uint32_t msc_hi = msc >> 32;
uint32_t msc_lo = msc & 0xffffffff;
uint32_t divisor_hi = divisor >> 32;
uint32_t divisor_lo = divisor & 0xffffffff;
uint32_t remainder_hi = remainder >> 32;
uint32_t remainder_lo = remainder & 0xffffffff;
xcb_dri2_swap_buffers_cookie_t cookie;
xcb_dri2_swap_buffers_reply_t *reply;
int64_t swap_count = -1;
if (draw->SwapBehavior == EGL_BUFFER_PRESERVED ||
!dri2_dpy->swap_available) {
swap_count = dri2_copy_region(disp, draw, dri2_surf->region) ? 0 : -1;
} else {
dri2_flush_drawable_for_swapbuffers(disp, draw);
cookie = xcb_dri2_swap_buffers_unchecked(
dri2_dpy->conn, dri2_surf->drawable, msc_hi, msc_lo, divisor_hi,
divisor_lo, remainder_hi, remainder_lo);
reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL);
if (reply) {
swap_count = combine_u32_into_u64(reply->swap_hi, reply->swap_lo);
free(reply);
}
}
/* Since we aren't watching for the server's invalidate events like we're
* supposed to (due to XCB providing no mechanism for filtering the events
* the way xlib does), and SwapBuffers is a common cause of invalidate
* events, just shove one down to the driver, even though we haven't told
* the driver that we're the kind of loader that provides reliable
* invalidate events. This causes the driver to request buffers again at
* its next draw, so that we get the correct buffers if a pageflip
* happened. The driver should still be using the viewport hack to catch
* window resizes.
*/
dri_invalidate_drawable(dri2_surf->dri_drawable);
return swap_count;
}
#endif
static EGLBoolean
dri2_x11_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
{
@ -1124,12 +720,6 @@ dri2_x11_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
return EGL_TRUE;
}
#ifdef HAVE_X11_DRI2
if (dri2_x11_swap_buffers_msc(disp, draw, 0, 0, 0) == -1) {
/* Swap failed with a window drawable. */
return _eglError(EGL_BAD_NATIVE_WINDOW, __func__);
}
#endif
return EGL_TRUE;
}
@ -1187,11 +777,6 @@ dri2_x11_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
return EGL_TRUE;
}
#ifdef HAVE_X11_DRI2
if (dri2_dpy->swap_available)
xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval);
#endif
return EGL_TRUE;
}
@ -1249,120 +834,6 @@ dri2_fourcc_for_depth(struct dri2_egl_display *dri2_dpy, uint32_t depth)
}
}
#ifdef HAVE_X11_DRI2
static _EGLImage *
dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
EGLClientBuffer buffer, const EGLint *attr_list)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_image *dri2_img;
unsigned int attachments[1];
xcb_drawable_t drawable;
xcb_dri2_get_buffers_cookie_t buffers_cookie;
xcb_dri2_get_buffers_reply_t *buffers_reply;
xcb_dri2_dri2_buffer_t *buffers;
xcb_get_geometry_cookie_t geometry_cookie;
xcb_get_geometry_reply_t *geometry_reply;
xcb_generic_error_t *error;
int fourcc;
(void)ctx;
drawable = (xcb_drawable_t)(uintptr_t)buffer;
xcb_dri2_create_drawable(dri2_dpy->conn, drawable);
attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
buffers_cookie = xcb_dri2_get_buffers_unchecked(dri2_dpy->conn, drawable, 1,
1, attachments);
geometry_cookie = xcb_get_geometry(dri2_dpy->conn, drawable);
buffers_reply =
xcb_dri2_get_buffers_reply(dri2_dpy->conn, buffers_cookie, NULL);
if (buffers_reply == NULL)
return NULL;
buffers = xcb_dri2_get_buffers_buffers(buffers_reply);
if (buffers == NULL) {
free(buffers_reply);
return NULL;
}
geometry_reply =
xcb_get_geometry_reply(dri2_dpy->conn, geometry_cookie, &error);
if (geometry_reply == NULL || error != NULL) {
_eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
free(error);
free(buffers_reply);
free(geometry_reply);
return NULL;
}
fourcc = dri2_fourcc_for_depth(dri2_dpy, geometry_reply->depth);
if (fourcc == DRM_FORMAT_INVALID) {
_eglError(EGL_BAD_PARAMETER,
"dri2_create_image_khr: unsupported pixmap depth");
free(buffers_reply);
free(geometry_reply);
return NULL;
}
dri2_img = malloc(sizeof *dri2_img);
if (!dri2_img) {
free(buffers_reply);
free(geometry_reply);
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
return EGL_NO_IMAGE_KHR;
}
_eglInitImage(&dri2_img->base, disp);
int offset = 0;
dri2_img->dri_image = dri2_from_names(
dri2_dpy->dri_screen_render_gpu, buffers_reply->width,
buffers_reply->height, fourcc, (int *) &buffers[0].name, 1,
(int *) &buffers[0].pitch, &offset, dri2_img);
free(buffers_reply);
free(geometry_reply);
return &dri2_img->base;
}
static _EGLImage *
dri2_x11_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
EGLClientBuffer buffer, const EGLint *attr_list)
{
switch (target) {
case EGL_NATIVE_PIXMAP_KHR:
return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
default:
return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
}
}
static EGLBoolean
dri2_x11_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
EGLuint64KHR *ust, EGLuint64KHR *msc,
EGLuint64KHR *sbc)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(display);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
xcb_dri2_get_msc_cookie_t cookie;
xcb_dri2_get_msc_reply_t *reply;
cookie = xcb_dri2_get_msc(dri2_dpy->conn, dri2_surf->drawable);
reply = xcb_dri2_get_msc_reply(dri2_dpy->conn, cookie, NULL);
if (!reply)
return _eglError(EGL_BAD_ACCESS, __func__);
*ust = ((EGLuint64KHR)reply->ust_hi << 32) | reply->ust_lo;
*msc = ((EGLuint64KHR)reply->msc_hi << 32) | reply->msc_lo;
*sbc = ((EGLuint64KHR)reply->sbc_hi << 32) | reply->sbc_lo;
free(reply);
return EGL_TRUE;
}
#endif
static int
box_intersection_area(int16_t a_x, int16_t a_y, int16_t a_width,
int16_t a_height, int16_t b_x, int16_t b_y,
@ -1541,24 +1012,6 @@ static const struct dri2_egl_display_vtbl dri2_x11_kopper_display_vtbl = {
.get_dri_drawable = dri2_surface_get_dri_drawable,
};
#ifdef HAVE_X11_DRI2
static const struct dri2_egl_display_vtbl dri2_x11_display_vtbl = {
.authenticate = dri2_x11_authenticate,
.create_window_surface = dri2_x11_create_window_surface,
.create_pixmap_surface = dri2_x11_create_pixmap_surface,
.create_pbuffer_surface = dri2_x11_create_pbuffer_surface,
.destroy_surface = dri2_x11_destroy_surface,
.create_image = dri2_x11_create_image_khr,
.swap_interval = dri2_x11_swap_interval,
.swap_buffers = dri2_x11_swap_buffers,
.copy_buffers = dri2_x11_copy_buffers,
.query_surface = dri2_query_surface,
.get_sync_values = dri2_x11_get_sync_values,
.get_msc_rate = dri2_x11_get_msc_rate,
.get_dri_drawable = dri2_surface_get_dri_drawable,
};
#endif
static const __DRIswrastLoaderExtension swrast_loader_extension = {
.base = {__DRI_SWRAST_LOADER, 1},
@ -1864,108 +1317,11 @@ dri2_initialize_x11_dri3(_EGLDisplay *disp)
}
#endif
#ifdef HAVE_X11_DRI2
static const __DRIdri2LoaderExtension dri2_loader_extension_old = {
.base = {__DRI_DRI2_LOADER, 2},
.getBuffers = dri2_x11_get_buffers,
.flushFrontBuffer = dri2_x11_flush_front_buffer,
.getBuffersWithFormat = NULL,
};
static const __DRIdri2LoaderExtension dri2_loader_extension = {
.base = {__DRI_DRI2_LOADER, 3},
.getBuffers = dri2_x11_get_buffers,
.flushFrontBuffer = dri2_x11_flush_front_buffer,
.getBuffersWithFormat = dri2_x11_get_buffers_with_format,
};
static const __DRIextension *dri2_loader_extensions_old[] = {
&dri2_loader_extension_old.base,
&image_lookup_extension.base,
&background_callable_extension.base,
NULL,
};
static const __DRIextension *dri2_loader_extensions[] = {
&dri2_loader_extension.base,
&image_lookup_extension.base,
&background_callable_extension.base,
NULL,
};
/* don't consolidate any of this, it's a separate codepath */
EGLBoolean
dri2_initialize_x11_dri2(_EGLDisplay *disp)
dri2_initialize_x11(_EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
if (!dri2_get_xcb_connection(disp, dri2_dpy))
return EGL_FALSE;
if (!dri2_x11_connect(dri2_dpy))
goto cleanup;
dri2_detect_swrast(disp);
if (dri2_dpy->dri2_minor >= 1)
dri2_dpy->loader_extensions = dri2_loader_extensions;
else
dri2_dpy->loader_extensions = dri2_loader_extensions_old;
dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
if (!dri2_x11_check_multibuffers(disp))
goto cleanup;
if (!dri2_create_screen(disp))
goto cleanup;
if (!dri2_setup_device(disp, false)) {
_eglError(EGL_NOT_INITIALIZED, "DRI2: failed to setup EGLDevice");
goto cleanup;
}
dri2_setup_screen(disp);
dri2_x11_setup_swap_interval(disp);
disp->Extensions.KHR_image_pixmap = EGL_TRUE;
disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
disp->Extensions.CHROMIUM_sync_control = EGL_TRUE;
disp->Extensions.ANGLE_sync_control_rate = EGL_TRUE;
dri2_set_WL_bind_wayland_display(disp);
dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true);
/* Fill vtbl last to prevent accidentally calling virtual function during
* initialization.
*/
dri2_dpy->vtbl = &dri2_x11_display_vtbl;
_eglLog(_EGL_INFO, "Using DRI2");
return EGL_TRUE;
cleanup:
return EGL_FALSE;
}
#else
EGLBoolean
dri2_initialize_x11_dri2(_EGLDisplay *disp)
{
return _eglError(EGL_NOT_INITIALIZED, "legacy-x11 dri2 not built");
}
#endif
EGLBoolean
dri2_initialize_x11(_EGLDisplay *disp, bool *allow_dri2)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
bool dri3_disable = debug_get_bool_option("LIBGL_DRI3_DISABLE", false);
/*
* Every hardware driver_name is set using strdup. Doing the same in
* here will allow is to simply free the memory at dri2_terminate().
@ -1982,22 +1338,14 @@ dri2_initialize_x11(_EGLDisplay *disp, bool *allow_dri2)
/* kopper_without_modifiers really means (zink && LIBGL_DRI3_DISABLE=true),
* so this conditional is effectively "is dri3 enabled"
*/
if (!dri3_disable &&
(!disp->Options.Zink || !debug_get_bool_option("LIBGL_KOPPER_DRI2", false))) {
if (!disp->Options.Zink || !debug_get_bool_option("LIBGL_KOPPER_DRI2", false)) {
bool status = dri3_x11_connect(dri2_dpy, disp->Options.Zink, disp->Options.ForceSoftware);
/* the status here is ignored for zink-with-kopper and swrast,
* otherwise return whatever error/fallback status as failure
*/
if (!dri2_dpy->kopper && !disp->Options.ForceSoftware) {
#ifdef HAVE_X11_DRI2
*allow_dri2 = !debug_get_bool_option("LIBGL_DRI2_DISABLE", false);
#else
*allow_dri2 = false;
#endif
if (!status)
if (!status && !dri2_dpy->kopper && !disp->Options.ForceSoftware)
return EGL_FALSE;
}
}
#endif
dri2_detect_swrast(disp);
@ -2005,16 +1353,8 @@ dri2_initialize_x11(_EGLDisplay *disp, bool *allow_dri2)
return dri2_initialize_x11_swrast(disp);
#ifdef HAVE_LIBDRM
if (!dri3_disable) {
if (dri2_initialize_x11_dri3(disp))
return EGL_TRUE;
}
#endif
#ifdef HAVE_X11_DRI2
*allow_dri2 = !debug_get_bool_option("LIBGL_DRI2_DISABLE", false);
#else
*allow_dri2 = false;
#endif
return EGL_FALSE;

View file

@ -529,12 +529,8 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy, bool zink, bool swrast)
if (dri2_dpy->fd_render_gpu < 0) {
int conn_error = xcb_connection_has_error(dri2_dpy->conn);
if (!swrast) {
#ifdef HAVE_X11_DRI2
_eglLog(_EGL_INFO, "DRI3: Could not get DRI3 device");
#else
_eglLog(_EGL_WARNING, "DRI3 error: Could not get DRI3 device");
_eglLog(_EGL_WARNING, "Activate DRI3 at Xorg or build mesa with DRI2");
#endif
_eglLog(_EGL_WARNING, "Ensure your X server supports DRI3 to get accelerated rendering");
if (conn_error)
_eglLog(_EGL_WARNING, "DRI3: Failed to initialize");
}

View file

@ -88,9 +88,6 @@ xcb_screen_t *
vl_dri_get_screen_for_root(xcb_connection_t *conn, xcb_window_t root);
uint32_t
vl_dri2_format_for_depth(struct vl_screen *vscreen, int depth);
struct vl_screen *
vl_dri2_screen_create(Display *display, int screen);
#else
static inline struct vl_screen *
vl_dri2_screen_create(void *display, int screen) { return NULL; };

View file

@ -31,10 +31,6 @@
#include <sys/stat.h>
#include <X11/Xlib-xcb.h>
#include <X11/extensions/dri2tokens.h>
#ifdef HAVE_X11_DRI2
#include <xcb/dri2.h>
#endif
#include <xf86drm.h>
#include <errno.h>
@ -56,274 +52,6 @@
#include "drm-uapi/drm_fourcc.h"
struct vl_dri_screen
{
struct vl_screen base;
xcb_connection_t *conn;
xcb_drawable_t drawable;
unsigned width, height;
bool current_buffer;
uint32_t buffer_names[2];
struct u_rect dirty_areas[2];
bool flushed;
#ifdef HAVE_X11_DRI2
xcb_dri2_swap_buffers_cookie_t swap_cookie;
xcb_dri2_wait_sbc_cookie_t wait_cookie;
xcb_dri2_get_buffers_cookie_t buffers_cookie;
#endif
int64_t last_ust, ns_frame, last_msc, next_msc;
};
#ifdef HAVE_X11_DRI2
static const unsigned attachments[1] = { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT };
static void vl_dri2_screen_destroy(struct vl_screen *vscreen);
static void
vl_dri2_handle_stamps(struct vl_dri_screen *scrn,
uint32_t ust_hi, uint32_t ust_lo,
uint32_t msc_hi, uint32_t msc_lo)
{
int64_t ust = ((((uint64_t)ust_hi) << 32) | ust_lo) * 1000;
int64_t msc = (((uint64_t)msc_hi) << 32) | msc_lo;
if (scrn->last_ust && (ust > scrn->last_ust) &&
scrn->last_msc && (msc > scrn->last_msc))
scrn->ns_frame = (ust - scrn->last_ust) / (msc - scrn->last_msc);
scrn->last_ust = ust;
scrn->last_msc = msc;
}
static xcb_dri2_get_buffers_reply_t *
vl_dri2_get_flush_reply(struct vl_dri_screen *scrn)
{
xcb_dri2_wait_sbc_reply_t *wait_sbc_reply;
assert(scrn);
if (!scrn->flushed)
return NULL;
scrn->flushed = false;
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL));
wait_sbc_reply = xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL);
if (!wait_sbc_reply)
return NULL;
vl_dri2_handle_stamps(scrn, wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo,
wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo);
free(wait_sbc_reply);
return xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL);
}
static void
vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private, unsigned nboxes, struct pipe_box *sub_box)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen *)context_private;
uint32_t msc_hi, msc_lo;
assert(screen);
assert(resource);
assert(context_private);
free(vl_dri2_get_flush_reply(scrn));
msc_hi = scrn->next_msc >> 32;
msc_lo = scrn->next_msc & 0xFFFFFFFF;
scrn->swap_cookie = xcb_dri2_swap_buffers_unchecked(scrn->conn, scrn->drawable,
msc_hi, msc_lo, 0, 0, 0, 0);
scrn->wait_cookie = xcb_dri2_wait_sbc_unchecked(scrn->conn, scrn->drawable, 0, 0);
scrn->buffers_cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, scrn->drawable,
1, 1, attachments);
scrn->flushed = true;
scrn->current_buffer = !scrn->current_buffer;
}
static void
vl_dri2_destroy_drawable(struct vl_dri_screen *scrn)
{
xcb_void_cookie_t destroy_cookie;
if (scrn->drawable) {
free(vl_dri2_get_flush_reply(scrn));
destroy_cookie = xcb_dri2_destroy_drawable_checked(scrn->conn, scrn->drawable);
/* ignore any error here, since the drawable can be destroyed long ago */
free(xcb_request_check(scrn->conn, destroy_cookie));
}
}
static void
vl_dri2_set_drawable(struct vl_dri_screen *scrn, Drawable drawable)
{
assert(scrn);
assert(drawable);
if (scrn->drawable == drawable)
return;
vl_dri2_destroy_drawable(scrn);
xcb_dri2_create_drawable(scrn->conn, drawable);
scrn->current_buffer = false;
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);
scrn->drawable = drawable;
}
static struct pipe_resource *
vl_dri2_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen *)vscreen;
struct winsys_handle dri2_handle;
struct pipe_resource templ, *tex;
xcb_dri2_get_buffers_reply_t *reply;
xcb_dri2_dri2_buffer_t *buffers, *back_left = NULL;
unsigned depth = ((xcb_screen_t *)(vscreen->xcb_screen))->root_depth;
unsigned i;
assert(scrn);
vl_dri2_set_drawable(scrn, (Drawable)drawable);
reply = vl_dri2_get_flush_reply(scrn);
if (!reply) {
xcb_dri2_get_buffers_cookie_t cookie;
cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, (Drawable)drawable,
1, 1, attachments);
reply = xcb_dri2_get_buffers_reply(scrn->conn, cookie, NULL);
}
if (!reply)
return NULL;
buffers = xcb_dri2_get_buffers_buffers(reply);
if (!buffers) {
free(reply);
return NULL;
}
for (i = 0; i < reply->count; ++i) {
if (buffers[i].attachment == XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT) {
back_left = &buffers[i];
break;
}
}
if (i == reply->count || !back_left) {
free(reply);
return NULL;
}
if (reply->width != scrn->width || reply->height != scrn->height) {
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);
scrn->width = reply->width;
scrn->height = reply->height;
} else if (back_left->name != scrn->buffer_names[scrn->current_buffer]) {
vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->current_buffer]);
scrn->buffer_names[scrn->current_buffer] = back_left->name;
}
memset(&dri2_handle, 0, sizeof(dri2_handle));
dri2_handle.type = WINSYS_HANDLE_TYPE_SHARED;
dri2_handle.handle = back_left->name;
dri2_handle.stride = back_left->pitch;
dri2_handle.modifier = DRM_FORMAT_MOD_INVALID;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = vl_dri2_format_for_depth(vscreen, depth);
templ.last_level = 0;
templ.width0 = reply->width;
templ.height0 = reply->height;
templ.depth0 = 1;
templ.array_size = 1;
templ.usage = PIPE_USAGE_DEFAULT;
templ.bind = PIPE_BIND_RENDER_TARGET;
templ.flags = 0;
tex = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &templ,
&dri2_handle,
PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
free(reply);
return tex;
}
static struct u_rect *
vl_dri2_screen_get_dirty_area(struct vl_screen *vscreen)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen *)vscreen;
assert(scrn);
return &scrn->dirty_areas[scrn->current_buffer];
}
static uint64_t
vl_dri2_screen_get_timestamp(struct vl_screen *vscreen, void *drawable)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen *)vscreen;
xcb_dri2_get_msc_cookie_t cookie;
xcb_dri2_get_msc_reply_t *reply;
assert(scrn);
vl_dri2_set_drawable(scrn, (Drawable)drawable);
if (!scrn->last_ust) {
cookie = xcb_dri2_get_msc_unchecked(scrn->conn, (Drawable)drawable);
reply = xcb_dri2_get_msc_reply(scrn->conn, cookie, NULL);
if (reply) {
vl_dri2_handle_stamps(scrn, reply->ust_hi, reply->ust_lo,
reply->msc_hi, reply->msc_lo);
free(reply);
}
}
return scrn->last_ust;
}
static void
vl_dri2_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen *)vscreen;
assert(scrn);
if (stamp && scrn->last_ust && scrn->ns_frame && scrn->last_msc)
scrn->next_msc = ((int64_t)stamp - scrn->last_ust + scrn->ns_frame/2) /
scrn->ns_frame + scrn->last_msc;
else
scrn->next_msc = 0;
}
static void *
vl_dri2_screen_get_private(struct vl_screen *vscreen)
{
return vscreen;
}
static xcb_screen_t *
get_xcb_screen(xcb_screen_iterator_t iter, int screen)
{
for (; iter.rem; --screen, xcb_screen_next(&iter))
if (screen == 0)
return iter.data;
return NULL;
}
#endif
static xcb_visualtype_t *
get_xcb_visualtype_for_depth(struct vl_screen *vscreen, int depth)
{
@ -389,156 +117,3 @@ vl_dri_get_screen_for_root(xcb_connection_t *conn, xcb_window_t root)
return NULL;
}
#ifdef HAVE_X11_DRI2
struct vl_screen *
vl_dri2_screen_create(Display *display, int screen)
{
struct vl_dri_screen *scrn;
const xcb_query_extension_reply_t *extension;
xcb_dri2_query_version_cookie_t dri2_query_cookie;
xcb_dri2_query_version_reply_t *dri2_query = NULL;
xcb_dri2_connect_cookie_t connect_cookie;
xcb_dri2_connect_reply_t *connect = NULL;
xcb_dri2_authenticate_cookie_t authenticate_cookie;
xcb_dri2_authenticate_reply_t *authenticate = NULL;
xcb_screen_iterator_t s;
xcb_generic_error_t *error = NULL;
char *device_name;
int fd, device_name_length;
unsigned driverType;
drm_magic_t magic;
assert(display);
scrn = CALLOC_STRUCT(vl_dri_screen);
if (!scrn)
return NULL;
scrn->conn = XGetXCBConnection(display);
if (!scrn->conn)
goto free_screen;
xcb_prefetch_extension_data(scrn->conn, &xcb_dri2_id);
extension = xcb_get_extension_data(scrn->conn, &xcb_dri2_id);
if (!(extension && extension->present))
goto free_screen;
dri2_query_cookie = xcb_dri2_query_version (scrn->conn,
XCB_DRI2_MAJOR_VERSION,
XCB_DRI2_MINOR_VERSION);
dri2_query = xcb_dri2_query_version_reply (scrn->conn, dri2_query_cookie, &error);
if (dri2_query == NULL || error != NULL || dri2_query->minor_version < 2)
goto free_query;
s = xcb_setup_roots_iterator(xcb_get_setup(scrn->conn));
scrn->base.xcb_screen = get_xcb_screen(s, screen);
if (!scrn->base.xcb_screen)
goto free_query;
driverType = XCB_DRI2_DRIVER_TYPE_DRI;
{
char *prime = getenv("DRI_PRIME");
if (prime) {
unsigned primeid;
errno = 0;
primeid = strtoul(prime, NULL, 0);
if (errno == 0)
driverType |=
((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
}
}
connect_cookie = xcb_dri2_connect_unchecked(
scrn->conn, ((xcb_screen_t *)(scrn->base.xcb_screen))->root, driverType);
connect = xcb_dri2_connect_reply(scrn->conn, connect_cookie, NULL);
if (connect == NULL ||
connect->driver_name_length + connect->device_name_length == 0)
goto free_connect;
device_name_length = xcb_dri2_connect_device_name_length(connect);
device_name = CALLOC(1, device_name_length + 1);
if (!device_name)
goto free_connect;
memcpy(device_name, xcb_dri2_connect_device_name(connect), device_name_length);
fd = loader_open_device(device_name);
free(device_name);
if (fd < 0)
goto free_connect;
if (drmGetMagic(fd, &magic))
goto close_fd;
authenticate_cookie = xcb_dri2_authenticate_unchecked(
scrn->conn, ((xcb_screen_t *)(scrn->base.xcb_screen))->root, magic);
authenticate = xcb_dri2_authenticate_reply(scrn->conn, authenticate_cookie, NULL);
if (authenticate == NULL || !authenticate->authenticated)
goto free_authenticate;
if (pipe_loader_drm_probe_fd(&scrn->base.dev, fd, false))
scrn->base.pscreen = pipe_loader_create_screen(scrn->base.dev, false);
if (!scrn->base.pscreen)
goto release_pipe;
scrn->base.destroy = vl_dri2_screen_destroy;
scrn->base.texture_from_drawable = vl_dri2_screen_texture_from_drawable;
scrn->base.get_dirty_area = vl_dri2_screen_get_dirty_area;
scrn->base.get_timestamp = vl_dri2_screen_get_timestamp;
scrn->base.set_next_timestamp = vl_dri2_screen_set_next_timestamp;
scrn->base.get_private = vl_dri2_screen_get_private;
scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);
/* The pipe loader duplicates the fd */
close(fd);
free(authenticate);
free(connect);
free(dri2_query);
free(error);
return &scrn->base;
release_pipe:
if (scrn->base.dev)
pipe_loader_release(&scrn->base.dev, 1);
free_authenticate:
free(authenticate);
close_fd:
close(fd);
free_connect:
free(connect);
free_query:
free(dri2_query);
free(error);
free_screen:
FREE(scrn);
return NULL;
}
static void
vl_dri2_screen_destroy(struct vl_screen *vscreen)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen *)vscreen;
assert(vscreen);
if (scrn->flushed) {
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL));
free(xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL));
free(xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL));
}
vl_dri2_destroy_drawable(scrn);
scrn->base.pscreen->destroy(scrn->base.pscreen);
pipe_loader_release(&scrn->base.dev, 1);
/* There is no user provided fd */
FREE(scrn);
}
#endif

View file

@ -159,10 +159,6 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
#endif
if (!drv->vscreen)
drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen);
#ifdef HAVE_X11_DRI2
if (!drv->vscreen)
drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen);
#endif
if (!drv->vscreen)
drv->vscreen = vl_xlib_swrast_screen_create(ctx->native_dpy, ctx->x11_screen);
break;

View file

@ -64,10 +64,6 @@ vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device,
pipe_reference_init(&dev->reference, 1);
dev->vscreen = vl_dri3_screen_create(display, screen);
#ifdef HAVE_X11_DRI2
if (!dev->vscreen)
dev->vscreen = vl_dri2_screen_create(display, screen);
#endif
if (!dev->vscreen)
dev->vscreen = vl_xlib_swrast_screen_create(display, screen);
if (!dev->vscreen) {

View file

@ -1,564 +0,0 @@
/*
* Copyright © 2008 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Authors:
* Kristian Høgsberg (krh@redhat.com)
*/
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
#include <stdio.h>
#include <X11/Xlibint.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <X11/extensions/dri2proto.h>
#include "dri2.h"
#include "glxclient.h"
#include "GL/glxext.h"
#if defined(__APPLE__) || defined(__MACOSX)
#include "apple/appledri.h"
#include "apple/appledristr.h"
#endif
/* Allow the build to work with an older versions of dri2proto.h and
* dri2tokens.h.
*/
#if DRI2_MINOR < 1
#undef DRI2_MINOR
#define DRI2_MINOR 1
#define X_DRI2GetBuffersWithFormat 7
#endif
#if defined(__APPLE__) || defined(__MACOSX)
static char dri2ExtensionName[] = APPLEDRINAME;
#else
static char dri2ExtensionName[] = DRI2_NAME;
#endif
static XExtensionInfo _dri2Info_data;
static XExtensionInfo *dri2Info = &_dri2Info_data;
static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
static Bool
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
static Status
DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
static int
DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
static /* const */ XExtensionHooks dri2ExtensionHooks = {
NULL, /* create_gc */
NULL, /* copy_gc */
NULL, /* flush_gc */
NULL, /* free_gc */
NULL, /* create_font */
NULL, /* free_font */
DRI2CloseDisplay, /* close_display */
DRI2WireToEvent, /* wire_to_event */
DRI2EventToWire, /* event_to_wire */
DRI2Error, /* error */
NULL, /* error_string */
};
static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
dri2Info,
dri2ExtensionName,
&dri2ExtensionHooks,
0, NULL)
static Bool
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
{
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
struct glx_drawable *glxDraw;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
case DRI2_BufferSwapComplete:
{
GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire;
__GLXDRIdrawable *pdraw;
pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable);
if (pdraw == NULL)
return False;
/* Ignore swap events if we're not looking for them */
aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
if(!aevent->type)
return False;
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->drawable = awire->drawable;
switch (awire->event_type) {
case DRI2_EXCHANGE_COMPLETE:
aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
break;
case DRI2_BLIT_COMPLETE:
aevent->event_type = GLX_COPY_COMPLETE_INTEL;
break;
case DRI2_FLIP_COMPLETE:
aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
break;
default:
/* unknown swap completion type */
return False;
}
aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
glxDraw = GetGLXDrawable(dpy, pdraw->drawable);
if (glxDraw != NULL) {
if (awire->sbc < glxDraw->lastEventSbc)
glxDraw->eventSbcWrap += 0x100000000;
glxDraw->lastEventSbc = awire->sbc;
aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
} else {
aevent->sbc = awire->sbc;
}
return True;
}
case DRI2_InvalidateBuffers:
{
xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
dri2InvalidateBuffers(dpy, awire->drawable);
return False;
}
default:
/* client doesn't support server event */
break;
}
#endif
return False;
}
/* We don't actually support this. It doesn't make sense for clients to
* send each other DRI2 events.
*/
static Status
DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
XextCheckExtension(dpy, info, dri2ExtensionName, False);
switch (event->type) {
default:
/* client doesn't support server event */
break;
}
return Success;
}
static int
DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
{
if (err->majorCode == codes->major_opcode &&
err->errorCode == BadDrawable &&
err->minorCode == X_DRI2CopyRegion)
return True;
/* If the X drawable was destroyed before the GLX drawable, the
* DRI2 drawble will be gone by the time we call
* DRI2DestroyDrawable. So just ignore BadDrawable here. */
if (err->majorCode == codes->major_opcode &&
err->errorCode == BadDrawable &&
err->minorCode == X_DRI2DestroyDrawable)
return True;
/* If the server is non-local DRI2Connect will raise BadRequest.
* Swallow this so that DRI2Connect can signal this in its return code */
if (err->majorCode == codes->major_opcode &&
err->minorCode == X_DRI2Connect &&
err->errorCode == BadRequest) {
*ret_code = False;
return True;
}
return False;
}
Bool
DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
{
#if defined(__APPLE__) || defined(__MACOSX)
return XAppleDRIQueryExtension(dpy, eventBase, errorBase);
#else
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
if (XextHasExtension(info)) {
*eventBase = info->codes->first_event;
*errorBase = info->codes->first_error;
return True;
}
return False;
#endif
}
Bool
DRI2QueryVersion(Display * dpy, int *major, int *minor)
{
#if defined(__APPLE__) || defined(__MACOSX)
int patch;
return XAppleDRIQueryVersion(dpy, major, minor, &patch);
#else
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2QueryVersionReply rep;
xDRI2QueryVersionReq *req;
int i, nevents;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2QueryVersion, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2QueryVersion;
req->majorVersion = DRI2_MAJOR;
req->minorVersion = DRI2_MINOR;
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*major = rep.majorVersion;
*minor = rep.minorVersion;
UnlockDisplay(dpy);
SyncHandle();
switch (rep.minorVersion) {
case 1:
nevents = 0;
break;
case 2:
nevents = 1;
break;
case 3:
default:
nevents = 2;
break;
}
for (i = 0; i < nevents; i++) {
XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
}
return True;
#endif
}
Bool
DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2ConnectReply rep;
xDRI2ConnectReq *req;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2Connect, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2Connect;
req->window = window;
req->driverType = DRI2DriverDRI;
{
char *prime = getenv("DRI_PRIME");
if (prime) {
uint32_t primeid;
errno = 0;
primeid = strtoul(prime, NULL, 0);
if (errno == 0)
req->driverType |=
((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
}
}
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
*driverName = malloc(rep.driverNameLength + 1);
if (*driverName == NULL) {
_XEatData(dpy,
((rep.driverNameLength + 3) & ~3) +
((rep.deviceNameLength + 3) & ~3));
UnlockDisplay(dpy);
SyncHandle();
return False;
}
_XReadPad(dpy, *driverName, rep.driverNameLength);
(*driverName)[rep.driverNameLength] = '\0';
*deviceName = malloc(rep.deviceNameLength + 1);
if (*deviceName == NULL) {
free(*driverName);
_XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
UnlockDisplay(dpy);
SyncHandle();
return False;
}
_XReadPad(dpy, *deviceName, rep.deviceNameLength);
(*deviceName)[rep.deviceNameLength] = '\0';
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Bool
DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2AuthenticateReq *req;
xDRI2AuthenticateReply rep;
XextCheckExtension(dpy, info, dri2ExtensionName, False);
LockDisplay(dpy);
GetReq(DRI2Authenticate, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2Authenticate;
req->window = window;
req->magic = magic;
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return False;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.authenticated;
}
void
DRI2CreateDrawable(Display * dpy, XID drawable)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2CreateDrawableReq *req;
XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
LockDisplay(dpy);
GetReq(DRI2CreateDrawable, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2CreateDrawable;
req->drawable = drawable;
UnlockDisplay(dpy);
SyncHandle();
}
void
DRI2DestroyDrawable(Display * dpy, XID drawable)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2DestroyDrawableReq *req;
XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
XSync(dpy, False);
LockDisplay(dpy);
GetReq(DRI2DestroyDrawable, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2DestroyDrawable;
req->drawable = drawable;
UnlockDisplay(dpy);
SyncHandle();
}
DRI2Buffer *
DRI2GetBuffers(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments, int count, int *outCount)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2GetBuffersReply rep;
xDRI2GetBuffersReq *req;
DRI2Buffer *buffers;
xDRI2Buffer repBuffer;
CARD32 *p;
int i;
XextCheckExtension(dpy, info, dri2ExtensionName, NULL);
LockDisplay(dpy);
GetReqExtra(DRI2GetBuffers, count * 4, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2GetBuffers;
req->drawable = drawable;
req->count = count;
p = (CARD32 *) & req[1];
for (i = 0; i < count; i++)
p[i] = attachments[i];
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
*width = rep.width;
*height = rep.height;
*outCount = rep.count;
buffers = malloc(rep.count * sizeof buffers[0]);
if (buffers == NULL) {
_XEatData(dpy, rep.count * sizeof repBuffer);
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
for (i = 0; i < rep.count; i++) {
_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
buffers[i].attachment = repBuffer.attachment;
buffers[i].name = repBuffer.name;
buffers[i].pitch = repBuffer.pitch;
buffers[i].cpp = repBuffer.cpp;
buffers[i].flags = repBuffer.flags;
}
UnlockDisplay(dpy);
SyncHandle();
return buffers;
}
DRI2Buffer *
DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments, int count, int *outCount)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2GetBuffersReply rep;
xDRI2GetBuffersReq *req;
DRI2Buffer *buffers;
xDRI2Buffer repBuffer;
CARD32 *p;
int i;
XextCheckExtension(dpy, info, dri2ExtensionName, NULL);
LockDisplay(dpy);
GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2GetBuffersWithFormat;
req->drawable = drawable;
req->count = count;
p = (CARD32 *) & req[1];
for (i = 0; i < (count * 2); i++)
p[i] = attachments[i];
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
*width = rep.width;
*height = rep.height;
*outCount = rep.count;
buffers = malloc(rep.count * sizeof buffers[0]);
if (buffers == NULL) {
_XEatData(dpy, rep.count * sizeof repBuffer);
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
for (i = 0; i < rep.count; i++) {
_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
buffers[i].attachment = repBuffer.attachment;
buffers[i].name = repBuffer.name;
buffers[i].pitch = repBuffer.pitch;
buffers[i].cpp = repBuffer.cpp;
buffers[i].flags = repBuffer.flags;
}
UnlockDisplay(dpy);
SyncHandle();
return buffers;
}
void
DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
CARD32 dest, CARD32 src)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2CopyRegionReq *req;
xDRI2CopyRegionReply rep;
XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
LockDisplay(dpy);
GetReq(DRI2CopyRegion, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2CopyRegion;
req->drawable = drawable;
req->region = region;
req->dest = dest;
req->src = src;
_XReply(dpy, (xReply *) & rep, 0, xFalse);
UnlockDisplay(dpy);
SyncHandle();
}
#endif /* GLX_DIRECT_RENDERING */

View file

@ -1,91 +0,0 @@
/*
* Copyright © 2007,2008 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Authors:
* Kristian Høgsberg (krh@redhat.com)
*/
#ifndef _DRI2_H_
#define _DRI2_H_
#include "util/libdrm.h"
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/dri2tokens.h>
typedef struct
{
unsigned int attachment;
unsigned int name;
unsigned int pitch;
unsigned int cpp;
unsigned int flags;
} DRI2Buffer;
struct glx_screen;
extern Bool
DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
extern Bool
DRI2QueryVersion(Display * display, int *major, int *minor);
extern Bool
DRI2Connect(Display * display, XID window,
char **driverName, char **deviceName);
extern Bool
DRI2Authenticate(Display * display, XID window, drm_magic_t magic);
extern void
DRI2CreateDrawable(Display * display, XID drawable);
extern void
DRI2DestroyDrawable(Display * display, XID handle);
extern DRI2Buffer*
DRI2GetBuffers(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments, int count,
int *outCount);
/**
* \note
* This function is only supported with DRI2 version 1.1 or later.
*/
extern DRI2Buffer*
DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
int *width, int *height,
unsigned int *attachments,
int count, int *outCount);
extern void
DRI2CopyRegion(Display * dpy, XID drawable,
XserverRegion region,
CARD32 dest, CARD32 src);
#endif

View file

@ -1,781 +0,0 @@
/*
* Copyright © 2008 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Authors:
* Kristian Høgsberg (krh@redhat.com)
*/
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#include <xcb/dri2.h>
#include "glxclient.h"
#include <X11/extensions/dri2proto.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/time.h>
#include "dri2.h"
#include "dri_common.h"
#include "dri2_priv.h"
#include "loader.h"
#include "loader_dri_helper.h"
#include "dri_util.h"
#include "mapi/glapi/glapi.h"
#include "dispatch.h"
#undef DRI2_MINOR
#define DRI2_MINOR 1
struct dri2_drawable
{
__GLXDRIdrawable base;
__DRIbuffer buffers[5];
int bufferCount;
int width, height;
int have_back;
int have_fake_front;
int swap_interval;
uint64_t previous_time;
unsigned frames;
};
static const struct glx_context_vtable dri2_context_vtable;
/* For XCB's handling of ust/msc/sbc counters, we have to hand it the high and
* low halves separately. This helps you split them.
*/
static void
split_counter(uint64_t counter, uint32_t *hi, uint32_t *lo)
{
*hi = (counter >> 32);
*lo = counter & 0xffffffff;
}
static uint64_t
merge_counter(uint32_t hi, uint32_t lo)
{
return ((uint64_t)hi << 32) | lo;
}
static void
dri2DestroyDrawable(__GLXDRIdrawable *base)
{
struct dri2_screen *psc = (struct dri2_screen *) base->psc;
struct glx_display *dpyPriv = psc->base.display;
__glxHashDelete(dpyPriv->dri2Hash, base->xDrawable);
driDestroyDrawable(base->dri_drawable);
/* If it's a GLX 1.3 drawables, we can destroy the DRI2 drawable
* now, as the application explicitly asked to destroy the GLX
* drawable. Otherwise, for legacy drawables, we let the DRI2
* drawable linger on the server, since there's no good way of
* knowing when the application is done with it. The server will
* destroy the DRI2 drawable when it destroys the X drawable or the
* client exits anyway. */
if (base->xDrawable != base->drawable)
DRI2DestroyDrawable(psc->base.dpy, base->xDrawable);
free(base);
}
static __GLXDRIdrawable *
dri2CreateDrawable(struct glx_screen *base, XID xDrawable,
GLXDrawable drawable, int type,
struct glx_config *config_base)
{
struct dri2_drawable *pdraw;
struct dri2_screen *psc = (struct dri2_screen *) base;
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
struct glx_display *dpyPriv;
dpyPriv = __glXInitialize(psc->base.dpy);
if (dpyPriv == NULL)
return NULL;
pdraw = calloc(1, sizeof(*pdraw));
if (!pdraw)
return NULL;
pdraw->base.destroyDrawable = dri2DestroyDrawable;
pdraw->base.xDrawable = xDrawable;
pdraw->base.drawable = drawable;
pdraw->base.psc = &psc->base;
pdraw->bufferCount = 0;
pdraw->swap_interval = dri_get_initial_swap_interval(psc->base.frontend_screen);
pdraw->have_back = 0;
DRI2CreateDrawable(psc->base.dpy, xDrawable);
/* Create a new drawable */
pdraw->base.dri_drawable =
dri_create_drawable(psc->base.frontend_screen, config->driConfig, false, pdraw);
if (!pdraw->base.dri_drawable) {
DRI2DestroyDrawable(psc->base.dpy, xDrawable);
free(pdraw);
return NULL;
}
if (__glxHashInsert(dpyPriv->dri2Hash, xDrawable, pdraw)) {
driDestroyDrawable(pdraw->base.dri_drawable);
DRI2DestroyDrawable(psc->base.dpy, xDrawable);
free(pdraw);
return None;
}
/*
* Make sure server has the same swap interval we do for the new
* drawable.
*/
if (base->driScreen.setSwapInterval)
base->driScreen.setSwapInterval(&pdraw->base, pdraw->swap_interval);
return &pdraw->base;
}
static int
dri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
int64_t *ust, int64_t *msc, int64_t *sbc)
{
xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
xcb_dri2_get_msc_cookie_t get_msc_cookie;
xcb_dri2_get_msc_reply_t *get_msc_reply;
get_msc_cookie = xcb_dri2_get_msc_unchecked(c, pdraw->xDrawable);
get_msc_reply = xcb_dri2_get_msc_reply(c, get_msc_cookie, NULL);
if (!get_msc_reply)
return 0;
*ust = merge_counter(get_msc_reply->ust_hi, get_msc_reply->ust_lo);
*msc = merge_counter(get_msc_reply->msc_hi, get_msc_reply->msc_lo);
*sbc = merge_counter(get_msc_reply->sbc_hi, get_msc_reply->sbc_lo);
free(get_msc_reply);
return 1;
}
static int
dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
{
xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
xcb_dri2_wait_msc_cookie_t wait_msc_cookie;
xcb_dri2_wait_msc_reply_t *wait_msc_reply;
uint32_t target_msc_hi, target_msc_lo;
uint32_t divisor_hi, divisor_lo;
uint32_t remainder_hi, remainder_lo;
split_counter(target_msc, &target_msc_hi, &target_msc_lo);
split_counter(divisor, &divisor_hi, &divisor_lo);
split_counter(remainder, &remainder_hi, &remainder_lo);
wait_msc_cookie = xcb_dri2_wait_msc_unchecked(c, pdraw->xDrawable,
target_msc_hi, target_msc_lo,
divisor_hi, divisor_lo,
remainder_hi, remainder_lo);
wait_msc_reply = xcb_dri2_wait_msc_reply(c, wait_msc_cookie, NULL);
if (!wait_msc_reply)
return 0;
*ust = merge_counter(wait_msc_reply->ust_hi, wait_msc_reply->ust_lo);
*msc = merge_counter(wait_msc_reply->msc_hi, wait_msc_reply->msc_lo);
*sbc = merge_counter(wait_msc_reply->sbc_hi, wait_msc_reply->sbc_lo);
free(wait_msc_reply);
return 1;
}
static int
dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
int64_t *msc, int64_t *sbc)
{
xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
xcb_dri2_wait_sbc_cookie_t wait_sbc_cookie;
xcb_dri2_wait_sbc_reply_t *wait_sbc_reply;
uint32_t target_sbc_hi, target_sbc_lo;
split_counter(target_sbc, &target_sbc_hi, &target_sbc_lo);
wait_sbc_cookie = xcb_dri2_wait_sbc_unchecked(c, pdraw->xDrawable,
target_sbc_hi, target_sbc_lo);
wait_sbc_reply = xcb_dri2_wait_sbc_reply(c, wait_sbc_cookie, NULL);
if (!wait_sbc_reply)
return 0;
*ust = merge_counter(wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo);
*msc = merge_counter(wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo);
*sbc = merge_counter(wait_sbc_reply->sbc_hi, wait_sbc_reply->sbc_lo);
free(wait_sbc_reply);
return 1;
}
static struct dri_context *
dri2GetCurrentContext()
{
struct glx_context *gc = __glXGetCurrentContext();
return (gc != &dummyContext) ? gc->driContext : NULL;
}
/**
* dri2Throttle - Request driver throttling
*
* This function uses the DRI2 throttle extension to give the
* driver the opportunity to throttle on flush front, copysubbuffer
* and swapbuffers.
*/
static void
dri2Throttle(struct dri2_screen *psc,
struct dri2_drawable *draw,
enum __DRI2throttleReason reason)
{
struct dri_context *ctx = dri2GetCurrentContext();
dri_throttle(ctx, draw->base.dri_drawable, reason);
}
/**
* Asks the driver to flush any queued work necessary for serializing with the
* X command stream, and optionally the slightly more strict requirement of
* glFlush() equivalence (which would require flushing even if nothing had
* been drawn to a window system framebuffer, for example).
*/
static void
dri2Flush(struct dri2_screen *psc,
struct dri_context *ctx,
struct dri2_drawable *draw,
unsigned flags,
enum __DRI2throttleReason throttle_reason)
{
if (ctx) {
dri_flush(ctx, draw->base.dri_drawable, flags, throttle_reason);
} else {
if (flags & __DRI2_FLUSH_CONTEXT)
CALL_Flush(GET_DISPATCH(), ());
dri_flush_drawable(draw->base.dri_drawable);
dri2Throttle(psc, draw, throttle_reason);
}
}
static void
__dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
int width, int height,
enum __DRI2throttleReason reason, Bool flush)
{
struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
XRectangle xrect;
XserverRegion region;
struct dri_context *ctx = dri2GetCurrentContext();
unsigned flags;
/* Check we have the right attachments */
if (!priv->have_back)
return;
xrect.x = x;
xrect.y = priv->height - y - height;
xrect.width = width;
xrect.height = height;
flags = __DRI2_FLUSH_DRAWABLE;
if (flush)
flags |= __DRI2_FLUSH_CONTEXT;
dri2Flush(psc, ctx, priv, flags, __DRI2_THROTTLE_COPYSUBBUFFER);
region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
DRI2BufferFrontLeft, DRI2BufferBackLeft);
/* Refresh the fake front (if present) after we just damaged the real
* front.
*/
if (priv->have_fake_front)
DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
XFixesDestroyRegion(psc->base.dpy, region);
}
static void
dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
int width, int height, Bool flush)
{
__dri2CopySubBuffer(pdraw, x, y, width, height,
__DRI2_THROTTLE_COPYSUBBUFFER, flush);
}
static void
dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src)
{
XRectangle xrect;
XserverRegion region;
struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
xrect.x = 0;
xrect.y = 0;
xrect.width = priv->width;
xrect.height = priv->height;
dri_flush_drawable(priv->base.dri_drawable);
region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src);
XFixesDestroyRegion(psc->base.dpy, region);
}
static void
dri2_wait_x(struct glx_context *gc)
{
struct dri2_drawable *priv = (struct dri2_drawable *)
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
if (priv == NULL || !priv->have_fake_front)
return;
dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
}
static void
dri2_wait_gl(struct glx_context *gc)
{
struct dri2_drawable *priv = (struct dri2_drawable *)
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
if (priv == NULL || !priv->have_fake_front)
return;
dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
}
/**
* Called by the driver when it needs to update the real front buffer with the
* contents of its fake front buffer.
*/
static void
dri2FlushFrontBuffer(struct dri_drawable *driDrawable, void *loaderPrivate)
{
struct glx_display *priv;
struct glx_context *gc;
struct dri2_drawable *pdraw = loaderPrivate;
struct dri2_screen *psc;
if (!pdraw)
return;
if (!pdraw->base.psc)
return;
psc = (struct dri2_screen *) pdraw->base.psc;
priv = __glXInitialize(psc->base.dpy);
if (priv == NULL)
return;
gc = __glXGetCurrentContext();
dri2Throttle(psc, pdraw, __DRI2_THROTTLE_FLUSHFRONT);
dri2_wait_gl(gc);
}
static void
dri2DeinitScreen(struct glx_screen *base)
{
struct dri2_screen *psc = (struct dri2_screen *) base;
close(psc->fd);
}
/**
* Process list of buffer received from the server
*
* Processes the list of buffers received in a reply from the server to either
* \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
*/
static void
process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
unsigned count)
{
int i;
pdraw->bufferCount = count;
pdraw->have_fake_front = 0;
pdraw->have_back = 0;
/* This assumes the DRI2 buffer attachment tokens matches the
* __DRIbuffer tokens. */
for (i = 0; i < count; i++) {
pdraw->buffers[i].attachment = buffers[i].attachment;
pdraw->buffers[i].name = buffers[i].name;
pdraw->buffers[i].pitch = buffers[i].pitch;
pdraw->buffers[i].cpp = buffers[i].cpp;
pdraw->buffers[i].flags = buffers[i].flags;
if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
pdraw->have_fake_front = 1;
if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
pdraw->have_back = 1;
}
}
unsigned dri2GetSwapEventType(Display* dpy, XID drawable)
{
struct glx_display *glx_dpy = __glXInitialize(dpy);
__GLXDRIdrawable *pdraw;
pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
if (!pdraw || !(pdraw->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
return 0;
return glx_dpy->codes.first_event + GLX_BufferSwapComplete;
}
static int64_t
dri2XcbSwapBuffers(Display *dpy,
__GLXDRIdrawable *pdraw,
int64_t target_msc,
int64_t divisor,
int64_t remainder)
{
xcb_dri2_swap_buffers_cookie_t swap_buffers_cookie;
xcb_dri2_swap_buffers_reply_t *swap_buffers_reply;
uint32_t target_msc_hi, target_msc_lo;
uint32_t divisor_hi, divisor_lo;
uint32_t remainder_hi, remainder_lo;
int64_t ret = 0;
xcb_connection_t *c = XGetXCBConnection(dpy);
split_counter(target_msc, &target_msc_hi, &target_msc_lo);
split_counter(divisor, &divisor_hi, &divisor_lo);
split_counter(remainder, &remainder_hi, &remainder_lo);
swap_buffers_cookie =
xcb_dri2_swap_buffers_unchecked(c, pdraw->xDrawable,
target_msc_hi, target_msc_lo,
divisor_hi, divisor_lo,
remainder_hi, remainder_lo);
/* Immediately wait on the swapbuffers reply. If we didn't, we'd have
* to do so some time before reusing a (non-pageflipped) backbuffer.
* Otherwise, the new rendering could get ahead of the X Server's
* dispatch of the swapbuffer and you'd display garbage.
*
* We use XSync() first to reap the invalidate events through the event
* filter, to ensure that the next drawing doesn't use an invalidated
* buffer.
*/
XSync(dpy, False);
swap_buffers_reply =
xcb_dri2_swap_buffers_reply(c, swap_buffers_cookie, NULL);
if (swap_buffers_reply) {
ret = merge_counter(swap_buffers_reply->swap_hi,
swap_buffers_reply->swap_lo);
free(swap_buffers_reply);
}
return ret;
}
static int64_t
dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
int64_t remainder, Bool flush)
{
struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
int64_t ret = 0;
/* Check we have the right attachments */
if (!priv->have_back)
return ret;
struct dri_context *ctx = dri2GetCurrentContext();
unsigned flags = __DRI2_FLUSH_DRAWABLE;
if (flush)
flags |= __DRI2_FLUSH_CONTEXT;
dri2Flush(psc, ctx, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
ret = dri2XcbSwapBuffers(pdraw->psc->dpy, pdraw,
target_msc, divisor, remainder);
return ret;
}
static __DRIbuffer *
dri2GetBuffers(struct dri_drawable * driDrawable,
int *width, int *height,
unsigned int *attachments, int count,
int *out_count, void *loaderPrivate)
{
struct dri2_drawable *pdraw = loaderPrivate;
DRI2Buffer *buffers;
buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
width, height, attachments, count, out_count);
if (buffers == NULL)
return NULL;
pdraw->width = *width;
pdraw->height = *height;
process_buffers(pdraw, buffers, *out_count);
free(buffers);
return pdraw->buffers;
}
static __DRIbuffer *
dri2GetBuffersWithFormat(struct dri_drawable * driDrawable,
int *width, int *height,
unsigned int *attachments, int count,
int *out_count, void *loaderPrivate)
{
struct dri2_drawable *pdraw = loaderPrivate;
DRI2Buffer *buffers;
buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
pdraw->base.xDrawable,
width, height, attachments,
count, out_count);
if (buffers == NULL)
return NULL;
pdraw->width = *width;
pdraw->height = *height;
process_buffers(pdraw, buffers, *out_count);
free(buffers);
return pdraw->buffers;
}
static int
dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
{
xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
if (!dri_valid_swap_interval(psc->base.frontend_screen, interval))
return GLX_BAD_VALUE;
xcb_dri2_swap_interval(c, priv->base.xDrawable, interval);
priv->swap_interval = interval;
return 0;
}
static int
dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
{
struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
return priv->swap_interval;
}
static const __DRIdri2LoaderExtension dri2LoaderExtension = {
.base = { __DRI_DRI2_LOADER, 3 },
.getBuffers = dri2GetBuffers,
.flushFrontBuffer = dri2FlushFrontBuffer,
.getBuffersWithFormat = dri2GetBuffersWithFormat,
};
void
dri2InvalidateBuffers(Display *dpy, XID drawable)
{
__GLXDRIdrawable *pdraw =
dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
if (!pdraw)
return;
dri_invalidate_drawable(pdraw->dri_drawable);
}
static const struct glx_context_vtable dri2_context_vtable = {
.destroy = dri_destroy_context,
.bind = dri_bind_context,
.unbind = dri_unbind_context,
.wait_gl = dri2_wait_gl,
.wait_x = dri2_wait_x,
};
static const __DRIextension *loader_extensions[] = {
&dri2LoaderExtension.base,
&driBackgroundCallable.base,
NULL
};
struct glx_screen *
dri2CreateScreen(int screen, struct glx_display * priv, bool driver_name_is_inferred)
{
struct dri2_screen *psc;
__GLXDRIscreen *psp;
char *driverName = NULL, *loader_driverName, *deviceName, *tmp;
drm_magic_t magic;
psc = calloc(1, sizeof *psc);
if (psc == NULL)
return NULL;
psc->fd = -1;
if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen),
&driverName, &deviceName)) {
glx_screen_cleanup(&psc->base);
free(psc);
InfoMessageF("screen %d does not appear to be DRI2 capable\n", screen);
return NULL;
}
psc->fd = loader_open_device(deviceName);
if (psc->fd < 0) {
ErrorMessageF("failed to open %s: %s\n", deviceName, strerror(errno));
goto handle_error;
}
if (drmGetMagic(psc->fd, &magic)) {
ErrorMessageF("failed to get magic\n");
goto handle_error;
}
if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) {
ErrorMessageF("failed to authenticate magic %d\n", magic);
goto handle_error;
}
/* If Mesa knows about the appropriate driver for this fd, then trust it.
* Otherwise, default to the server's value.
*/
loader_driverName = loader_get_driver_for_fd(psc->fd);
if (loader_driverName) {
free(driverName);
driverName = loader_driverName;
}
psc->base.driverName = driverName;
priv->driver = GLX_DRIVER_DRI2;
if (!dri_screen_init(&psc->base, priv, screen, psc->fd, loader_extensions, driver_name_is_inferred)) {
ErrorMessageF("glx: failed to create dri2 screen\n");
goto handle_error;
}
psc->base.context_vtable = &dri2_context_vtable;
psp = &psc->base.driScreen;
psp->deinitScreen = dri2DeinitScreen;
psp->createDrawable = dri2CreateDrawable;
psp->swapBuffers = dri2SwapBuffers;
psp->getDrawableMSC = NULL;
psp->waitForMSC = NULL;
psp->waitForSBC = NULL;
psp->setSwapInterval = NULL;
psp->getSwapInterval = NULL;
psp->getDrawableMSC = dri2DrawableGetMSC;
psp->waitForMSC = dri2WaitForMSC;
psp->waitForSBC = dri2WaitForSBC;
psp->setSwapInterval = dri2SetSwapInterval;
psp->getSwapInterval = dri2GetSwapInterval;
psp->maxSwapInterval = INT_MAX;
psc->base.can_EXT_texture_from_pixmap = true;
/* DRI2 supports SubBuffer through DRI2CopyRegion, so it's always
* available.*/
psp->copySubBuffer = dri2CopySubBuffer;
free(deviceName);
tmp = getenv("LIBGL_SHOW_FPS");
psc->show_fps_interval = (tmp) ? atoi(tmp) : 0;
if (psc->show_fps_interval < 0)
psc->show_fps_interval = 0;
InfoMessageF("Using DRI2 for screen %d\n", screen);
return &psc->base;
handle_error:
CriticalErrorMessageF("failed to load driver: %s\n", driverName);
if (psc->fd >= 0)
close(psc->fd);
free(deviceName);
glx_screen_cleanup(&psc->base);
free(psc);
return NULL;
}
__GLXDRIdrawable *
dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id)
{
struct glx_display *d = __glXInitialize(dpy);
__GLXDRIdrawable *pdraw;
if (__glxHashLookup(d->dri2Hash, id, (void *) &pdraw) == 0)
return pdraw;
return NULL;
}
bool
dri2CheckSupport(Display *dpy)
{
int eventBase, errorBase;
int driMajor, driMinor;
if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
return false;
if (!DRI2QueryVersion(dpy, &driMajor, &driMinor) ||
driMinor < 3) {
return false;
}
return true;
}
#endif /* GLX_DIRECT_RENDERING */

View file

@ -1,56 +0,0 @@
/*
* Copyright © 2008 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, provided that the above copyright
* notice(s) and this permission notice appear in all copies of the Soft-
* ware and that both the above copyright notice(s) and this permission
* notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
* QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
* MANCE OF THIS SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder shall
* not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization of
* the copyright holder.
*
* Authors:
* Kristian Høgsberg (krh@redhat.com)
*/
#ifndef DRI2_PRIV_H
#define DRI2_PRIV_H
#ifdef __cplusplus
extern "C" {
#endif
#include "mesa_interface.h"
struct dri2_screen {
struct glx_screen base;
const struct dri_config **driver_configs;
int fd;
int show_fps_interval;
};
#ifdef __cplusplus
}
#endif
#endif

View file

@ -58,7 +58,6 @@
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xlib-xcb.h>
#include <X11/xshmfence.h>
#include <xcb/xcb.h>
@ -78,7 +77,6 @@
#include "loader.h"
#include "loader_x11.h"
#include "loader_dri_helper.h"
#include "dri2.h"
#include "util/u_debug.h"
#include "dri_util.h"

View file

@ -975,7 +975,6 @@ dri_screen_init(struct glx_screen *psc, struct glx_display *priv, int screen, in
enum dri_screen_type type;
switch (psc->display->driver) {
case GLX_DRIVER_DRI3:
case GLX_DRIVER_DRI2:
type = DRI_SCREEN_DRI3;
break;
case GLX_DRIVER_ZINK_YES:

View file

@ -40,10 +40,9 @@ enum glx_driver {
GLX_DRIVER_NONE = 0,
GLX_DRIVER_ZINK_INFER = (1<<0),
GLX_DRIVER_SW = (1<<1),
GLX_DRIVER_DRI2 = (1<<2),
GLX_DRIVER_DRI3 = (1<<3),
GLX_DRIVER_WINDOWS = (1<<4),
GLX_DRIVER_ZINK_YES = (1<<5),
GLX_DRIVER_DRI3 = (1<<2),
GLX_DRIVER_WINDOWS = (1<<3),
GLX_DRIVER_ZINK_YES = (1<<4),
};
#if USE_LIBGLVND

View file

@ -885,13 +885,6 @@ AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv, enum glx_dr
driver_name_is_inferred = false;
}
}
#if defined(HAVE_X11_DRI2)
if (psc == NULL && glx_driver & GLX_DRIVER_DRI2 && dri2CheckSupport(dpy)) {
psc = dri2CreateScreen(i, priv, driver_name_is_inferred);
if (psc)
priv->dri2Hash = __glxHashCreate();
}
#endif
#endif /* GLX_USE_DRM */
#ifdef GLX_USE_WINDOWSGL
@ -1030,12 +1023,8 @@ __glXInitialize(Display * dpy)
glx_driver |= GLX_DRIVER_ZINK_INFER;
}
}
#if defined(HAVE_X11_DRI2)
if (!debug_get_bool_option("LIBGL_DRI2_DISABLE", false))
glx_driver |= GLX_DRIVER_DRI2;
#endif
#if defined(HAVE_ZINK)
if (!(glx_driver & (GLX_DRIVER_DRI2 | GLX_DRIVER_DRI3)))
if (!(glx_driver & GLX_DRIVER_DRI3))
if (kopper && !getenv("GALLIUM_DRIVER"))
glx_driver |= GLX_DRIVER_ZINK_INFER;
#endif /* HAVE_ZINK */

View file

@ -58,16 +58,6 @@ extra_libs_libglx = []
extra_deps_libgl = []
extra_ld_args_libgl = []
# dri2
if with_x11_dri2
files_libglx += files(
'dri2.c',
'dri2_glx.c',
'dri2.h',
'dri2_priv.h',
)
endif
if with_dri_platform == 'drm'
files_libglx += files('dri3_glx.c', 'dri3_priv.h')
endif
@ -122,7 +112,7 @@ libglx = static_library(
],
dependencies : [
idep_mesautil, idep_xmlconfig,
dep_libdrm, dep_dri2proto, dep_glproto, dep_x11, dep_xext, dep_glvnd, dep_xxf86vm, dep_xshmfence, dep_xfixes,
dep_libdrm, dep_glproto, dep_x11, dep_xext, dep_glvnd, dep_xxf86vm, dep_xshmfence,
],
)
@ -137,8 +127,7 @@ libgl = shared_library(
link_args : [ld_args_bsymbolic, ld_args_gc_sections, extra_ld_args_libgl],
dependencies : [
dep_libdrm, dep_dl, dep_m, dep_thread, dep_x11, dep_xcb_glx, dep_xcb,
dep_x11_xcb, dep_xcb_dri2, dep_xext, dep_xfixes, dep_xxf86vm,
dep_xcb_shm, extra_deps_libgl,
dep_x11_xcb, dep_xext, dep_xxf86vm, dep_xcb_shm, extra_deps_libgl,
],
version : gl_lib_version,
darwin_versions : '4.0.0',