mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 00:50:10 +01:00
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:
parent
b0624f4034
commit
08c6ba223b
23 changed files with 22 additions and 2682 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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``.
|
||||
|
||||
|
|
|
|||
|
|
@ -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``.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
11
meson.build
11
meson.build
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -783,7 +783,6 @@ option(
|
|||
value : [],
|
||||
description : 'Build legacy X11 support features.',
|
||||
choices : [
|
||||
'dri2'
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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,21 +1338,13 @@ 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)
|
||||
return EGL_FALSE;
|
||||
}
|
||||
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;
|
||||
if (dri2_initialize_x11_dri3(disp))
|
||||
return EGL_TRUE;
|
||||
#endif
|
||||
|
||||
return EGL_FALSE;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; };
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
564
src/glx/dri2.c
564
src/glx/dri2.c
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue