mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-27 08:20:12 +01:00
egl/x11: Implement dri3 support with loader's dri3 helper
v2: From Martin Peres - Tell we are compiling the dri3 backend in configure.ac - Update the Makefile.am - get rid of the LIBDRM_HAS_RENDERNODE_SUPPORT macro - fix some warnings related to EGLuint64KHR to int64_t conversions - use dri2_get_dri_config to get the __DRIconfig instead of open-coding it - replace the occasional tabs with spaces v3: From Martin Peres - fix and indent problem (Matt Turner) - drop the authenticate function, use NULL in the vtable instead (Emil) - drop some useless includes (Emil Velikov) - mandate libdrm (Emil Velikov) - link to xcb-dri3 (Kristian Høgsberg) - convert to the new loader interface for drwable (Kristian) - remove some dead code after the dropping of some vfuncs (Kristian) - add a comment on the topic of rendering to the frontbuffer v4: From Martin Peres - do not expose the preserved swap behavior (Acked by Eric Anholt) Signed-off-by: Boyan Ding <boyan.j.ding@gmail.com> Signed-off-by: Martin Peres <martin.peres@linux.intel.com> Reviewed-by: Kristian Høgsberg <krh@bitplanet.net> Reviewed-by: Emil Velikov <emil.velikov@collabora.co.uk>
This commit is contained in:
parent
a25df54571
commit
f35198bade
7 changed files with 714 additions and 15 deletions
|
|
@ -1568,6 +1568,12 @@ if test "x$enable_egl" = xyes; then
|
|||
if test "x$enable_shared_glapi" = xno; then
|
||||
AC_MSG_ERROR([egl_dri2 requires --enable-shared-glapi])
|
||||
fi
|
||||
if test "x$enable_dri3" = xyes; then
|
||||
HAVE_EGL_DRIVER_DRI3=1
|
||||
if test "x$enable_shared_glapi" = xno; then
|
||||
AC_MSG_ERROR([egl_dri3 requires --enable-shared-glapi])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Avoid building an "empty" libEGL. Drop/update this
|
||||
# when other backends (haiku?) come along.
|
||||
|
|
@ -2520,6 +2526,9 @@ if test "$enable_egl" = yes; then
|
|||
if test "x$HAVE_EGL_DRIVER_DRI2" != "x"; then
|
||||
egl_drivers="$egl_drivers builtin:egl_dri2"
|
||||
fi
|
||||
if test "x$HAVE_EGL_DRIVER_DRI3" != "x"; then
|
||||
egl_drivers="$egl_drivers builtin:egl_dri3"
|
||||
fi
|
||||
|
||||
echo " EGL drivers: $egl_drivers"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -47,12 +47,19 @@ libEGL_la_LDFLAGS = \
|
|||
$(LD_NO_UNDEFINED)
|
||||
|
||||
dri2_backend_FILES =
|
||||
dri3_backend_FILES =
|
||||
|
||||
if HAVE_EGL_PLATFORM_X11
|
||||
AM_CFLAGS += -DHAVE_X11_PLATFORM
|
||||
AM_CFLAGS += $(XCB_DRI2_CFLAGS)
|
||||
libEGL_la_LIBADD += $(XCB_DRI2_LIBS)
|
||||
dri2_backend_FILES += drivers/dri2/platform_x11.c
|
||||
|
||||
if HAVE_DRI3
|
||||
dri3_backend_FILES += \
|
||||
drivers/dri2/platform_x11_dri3.c
|
||||
libEGL_la_LIBADD += $(top_builddir)/src/loader/libloader_dri3_helper.la
|
||||
endif
|
||||
endif
|
||||
|
||||
if HAVE_EGL_PLATFORM_WAYLAND
|
||||
|
|
@ -88,7 +95,8 @@ AM_CFLAGS += \
|
|||
|
||||
libEGL_la_SOURCES += \
|
||||
$(dri2_backend_core_FILES) \
|
||||
$(dri2_backend_FILES)
|
||||
$(dri2_backend_FILES) \
|
||||
$(dri3_backend_FILES)
|
||||
|
||||
libEGL_la_LIBADD += $(top_builddir)/src/loader/libloader.la
|
||||
libEGL_la_LIBADD += $(DLOPEN_LIBS) $(LIBDRM_LIBS)
|
||||
|
|
|
|||
|
|
@ -352,6 +352,12 @@ struct dri2_extension_match {
|
|||
int offset;
|
||||
};
|
||||
|
||||
static struct dri2_extension_match dri3_driver_extensions[] = {
|
||||
{ __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
|
||||
{ __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static struct dri2_extension_match dri2_driver_extensions[] = {
|
||||
{ __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
|
||||
{ __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
|
||||
|
|
@ -493,6 +499,25 @@ dri2_open_driver(_EGLDisplay *disp)
|
|||
return extensions;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri2_load_driver_dri3(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = disp->DriverData;
|
||||
const __DRIextension **extensions;
|
||||
|
||||
extensions = dri2_open_driver(disp);
|
||||
if (!extensions)
|
||||
return EGL_FALSE;
|
||||
|
||||
if (!dri2_bind_extensions(dri2_dpy, dri3_driver_extensions, extensions)) {
|
||||
dlclose(dri2_dpy->driver);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
dri2_dpy->driver_extensions = extensions;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri2_load_driver(_EGLDisplay *disp)
|
||||
{
|
||||
|
|
@ -550,7 +575,9 @@ dri2_setup_screen(_EGLDisplay *disp)
|
|||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
unsigned int api_mask;
|
||||
|
||||
if (dri2_dpy->dri2) {
|
||||
if (dri2_dpy->image_driver) {
|
||||
api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen);
|
||||
} else if (dri2_dpy->dri2) {
|
||||
api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
|
||||
} else {
|
||||
assert(dri2_dpy->swrast);
|
||||
|
|
@ -570,7 +597,7 @@ dri2_setup_screen(_EGLDisplay *disp)
|
|||
if (api_mask & (1 << __DRI_API_GLES3))
|
||||
disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
|
||||
|
||||
assert(dri2_dpy->dri2 || dri2_dpy->swrast);
|
||||
assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast);
|
||||
disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
|
||||
disp->Extensions.MESA_configless_context = EGL_TRUE;
|
||||
|
||||
|
|
@ -578,7 +605,8 @@ dri2_setup_screen(_EGLDisplay *disp)
|
|||
__DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB))
|
||||
disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
|
||||
|
||||
if ((dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) ||
|
||||
if (dri2_dpy->image_driver ||
|
||||
(dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) ||
|
||||
(dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) {
|
||||
disp->Extensions.KHR_create_context = EGL_TRUE;
|
||||
|
||||
|
|
@ -641,7 +669,14 @@ dri2_create_screen(_EGLDisplay *disp)
|
|||
|
||||
dri2_dpy = disp->DriverData;
|
||||
|
||||
if (dri2_dpy->dri2) {
|
||||
if (dri2_dpy->image_driver) {
|
||||
dri2_dpy->dri_screen =
|
||||
dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd,
|
||||
dri2_dpy->extensions,
|
||||
dri2_dpy->driver_extensions,
|
||||
&dri2_dpy->driver_configs,
|
||||
disp);
|
||||
} else if (dri2_dpy->dri2) {
|
||||
if (dri2_dpy->dri2->base.version >= 4) {
|
||||
dri2_dpy->dri_screen =
|
||||
dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
|
||||
|
|
@ -677,7 +712,7 @@ dri2_create_screen(_EGLDisplay *disp)
|
|||
|
||||
extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
|
||||
|
||||
if (dri2_dpy->dri2) {
|
||||
if (dri2_dpy->image_driver || dri2_dpy->dri2) {
|
||||
if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
|
||||
goto cleanup_dri_screen;
|
||||
} else {
|
||||
|
|
@ -1024,7 +1059,26 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
|
|||
else
|
||||
dri_config = NULL;
|
||||
|
||||
if (dri2_dpy->dri2) {
|
||||
if (dri2_dpy->image_driver) {
|
||||
unsigned error;
|
||||
unsigned num_attribs = 8;
|
||||
uint32_t ctx_attribs[8];
|
||||
|
||||
if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs,
|
||||
&num_attribs))
|
||||
goto cleanup;
|
||||
|
||||
dri2_ctx->dri_context =
|
||||
dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen,
|
||||
api,
|
||||
dri_config,
|
||||
shared,
|
||||
num_attribs / 2,
|
||||
ctx_attribs,
|
||||
& error,
|
||||
dri2_ctx);
|
||||
dri2_create_context_attribs_error(error);
|
||||
} else if (dri2_dpy->dri2) {
|
||||
if (dri2_dpy->dri2->base.version >= 3) {
|
||||
unsigned error;
|
||||
unsigned num_attribs = 8;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@
|
|||
#include <xcb/dri2.h>
|
||||
#include <xcb/xfixes.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
|
||||
#ifdef HAVE_DRI3
|
||||
#include "loader_dri3_helper.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
|
|
@ -160,6 +164,7 @@ struct dri2_egl_display
|
|||
const __DRIconfig **driver_configs;
|
||||
void *driver;
|
||||
const __DRIcoreExtension *core;
|
||||
const __DRIimageDriverExtension *image_driver;
|
||||
const __DRIdri2Extension *dri2;
|
||||
const __DRIswrastExtension *swrast;
|
||||
const __DRI2flushExtension *flush;
|
||||
|
|
@ -192,6 +197,9 @@ struct dri2_egl_display
|
|||
#ifdef HAVE_X11_PLATFORM
|
||||
xcb_connection_t *conn;
|
||||
int screen;
|
||||
#ifdef HAVE_DRI3
|
||||
struct loader_dri3_extensions loader_dri3_ext;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
|
|
@ -205,8 +213,9 @@ struct dri2_egl_display
|
|||
int formats;
|
||||
uint32_t capabilities;
|
||||
int is_render_node;
|
||||
int is_different_gpu;
|
||||
#endif
|
||||
|
||||
int is_different_gpu;
|
||||
};
|
||||
|
||||
struct dri2_egl_context
|
||||
|
|
@ -326,6 +335,9 @@ dri2_setup_screen(_EGLDisplay *disp);
|
|||
EGLBoolean
|
||||
dri2_load_driver_swrast(_EGLDisplay *disp);
|
||||
|
||||
EGLBoolean
|
||||
dri2_load_driver_dri3(_EGLDisplay *disp);
|
||||
|
||||
EGLBoolean
|
||||
dri2_create_screen(_EGLDisplay *disp);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@
|
|||
#include "egl_dri2_fallbacks.h"
|
||||
#include "loader.h"
|
||||
|
||||
#ifdef HAVE_DRI3
|
||||
#include "platform_x11_dri3.h"
|
||||
#endif
|
||||
|
||||
static EGLBoolean
|
||||
dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
|
||||
EGLint interval);
|
||||
|
|
@ -703,7 +707,7 @@ dri2_x11_local_authenticate(_EGLDisplay *disp)
|
|||
|
||||
static EGLBoolean
|
||||
dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
|
||||
_EGLDisplay *disp)
|
||||
_EGLDisplay *disp, bool supports_preserved)
|
||||
{
|
||||
xcb_screen_iterator_t s;
|
||||
xcb_depth_iterator_t d;
|
||||
|
|
@ -724,8 +728,10 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
|
|||
surface_type =
|
||||
EGL_WINDOW_BIT |
|
||||
EGL_PIXMAP_BIT |
|
||||
EGL_PBUFFER_BIT |
|
||||
EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
|
||||
EGL_PBUFFER_BIT;
|
||||
|
||||
if (supports_preserved)
|
||||
surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
|
||||
|
||||
while (d.rem > 0) {
|
||||
EGLBoolean class_added[6] = { 0, };
|
||||
|
|
@ -1181,7 +1187,7 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
if (!dri2_create_screen(disp))
|
||||
goto cleanup_driver;
|
||||
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp))
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
|
||||
goto cleanup_configs;
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
|
|
@ -1252,6 +1258,96 @@ dri2_x11_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DRI3
|
||||
static EGLBoolean
|
||||
dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy;
|
||||
|
||||
dri2_dpy = calloc(1, sizeof *dri2_dpy);
|
||||
if (!dri2_dpy)
|
||||
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
|
||||
|
||||
disp->DriverData = (void *) dri2_dpy;
|
||||
if (disp->PlatformDisplay == NULL) {
|
||||
dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen);
|
||||
dri2_dpy->own_device = true;
|
||||
} else {
|
||||
Display *dpy = disp->PlatformDisplay;
|
||||
|
||||
dri2_dpy->conn = XGetXCBConnection(dpy);
|
||||
dri2_dpy->screen = DefaultScreen(dpy);
|
||||
}
|
||||
|
||||
if (xcb_connection_has_error(dri2_dpy->conn)) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
|
||||
goto cleanup_dpy;
|
||||
}
|
||||
|
||||
if (dri2_dpy->conn) {
|
||||
if (!dri3_x11_connect(dri2_dpy))
|
||||
goto cleanup_conn;
|
||||
}
|
||||
|
||||
if (!dri2_load_driver_dri3(disp))
|
||||
goto cleanup_conn;
|
||||
|
||||
dri2_dpy->extensions[0] = &dri3_image_loader_extension.base;
|
||||
dri2_dpy->extensions[1] = &use_invalidate.base;
|
||||
dri2_dpy->extensions[2] = &image_lookup_extension.base;
|
||||
dri2_dpy->extensions[3] = NULL;
|
||||
|
||||
dri2_dpy->swap_available = true;
|
||||
dri2_dpy->invalidate_available = true;
|
||||
|
||||
if (!dri2_create_screen(disp))
|
||||
goto cleanup_fd;
|
||||
|
||||
dri2_x11_setup_swap_interval(dri2_dpy);
|
||||
|
||||
disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
|
||||
disp->Extensions.CHROMIUM_sync_control = EGL_TRUE;
|
||||
disp->Extensions.EXT_buffer_age = EGL_TRUE;
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
|
||||
#endif
|
||||
|
||||
if (dri2_dpy->conn) {
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false))
|
||||
goto cleanup_configs;
|
||||
}
|
||||
|
||||
dri2_dpy->loader_dri3_ext.core = dri2_dpy->core;
|
||||
dri2_dpy->loader_dri3_ext.image_driver = dri2_dpy->image_driver;
|
||||
dri2_dpy->loader_dri3_ext.flush = dri2_dpy->flush;
|
||||
dri2_dpy->loader_dri3_ext.tex_buffer = dri2_dpy->tex_buffer;
|
||||
dri2_dpy->loader_dri3_ext.image = dri2_dpy->image;
|
||||
dri2_dpy->loader_dri3_ext.config = dri2_dpy->config;
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
* initialization.
|
||||
*/
|
||||
dri2_dpy->vtbl = &dri3_x11_display_vtbl;
|
||||
|
||||
return EGL_TRUE;
|
||||
|
||||
cleanup_configs:
|
||||
_eglCleanupDisplay(disp);
|
||||
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
|
||||
dlclose(dri2_dpy->driver);
|
||||
cleanup_fd:
|
||||
close(dri2_dpy->fd);
|
||||
cleanup_conn:
|
||||
if (disp->PlatformDisplay == NULL)
|
||||
xcb_disconnect(dri2_dpy->conn);
|
||||
cleanup_dpy:
|
||||
free(dri2_dpy);
|
||||
|
||||
return EGL_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static EGLBoolean
|
||||
dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
{
|
||||
|
|
@ -1323,7 +1419,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
|
||||
#endif
|
||||
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp))
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
|
||||
goto cleanup_configs;
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
|
|
@ -1357,9 +1453,16 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
|
||||
|
||||
if (x11_dri2_accel) {
|
||||
if (!dri2_initialize_x11_dri2(drv, disp)) {
|
||||
initialized = dri2_initialize_x11_swrast(drv, disp);
|
||||
#ifdef HAVE_DRI3
|
||||
if (getenv("LIBGL_DRI3_DISABLE") != NULL ||
|
||||
!dri2_initialize_x11_dri3(drv, disp)) {
|
||||
#endif
|
||||
if (!dri2_initialize_x11_dri2(drv, disp)) {
|
||||
initialized = dri2_initialize_x11_swrast(drv, disp);
|
||||
}
|
||||
#ifdef HAVE_DRI3
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
initialized = dri2_initialize_x11_swrast(drv, disp);
|
||||
}
|
||||
|
|
|
|||
472
src/egl/drivers/dri2/platform_x11_dri3.c
Normal file
472
src/egl/drivers/dri2/platform_x11_dri3.c
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* Copyright © 2015 Boyan Ding
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL 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 PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri3.h>
|
||||
#include <xcb/present.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "egl_dri2.h"
|
||||
#include "egl_dri2_fallbacks.h"
|
||||
#include "platform_x11_dri3.h"
|
||||
|
||||
#include "loader.h"
|
||||
#include "loader_dri3_helper.h"
|
||||
|
||||
static struct dri3_egl_surface *
|
||||
loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
|
||||
size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
|
||||
return (struct dri3_egl_surface *)(((void*) draw) - offset);
|
||||
}
|
||||
|
||||
static int
|
||||
egl_dri3_get_swap_interval(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
|
||||
return dri3_surf->base.SwapInterval;
|
||||
}
|
||||
|
||||
static int
|
||||
egl_dri3_clamp_swap_interval(struct loader_dri3_drawable *draw, int interval)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
|
||||
if (interval > dri3_surf->base.Config->MaxSwapInterval)
|
||||
interval = dri3_surf->base.Config->MaxSwapInterval;
|
||||
else if (interval < dri3_surf->base.Config->MinSwapInterval)
|
||||
interval = dri3_surf->base.Config->MinSwapInterval;
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
static void
|
||||
egl_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
|
||||
dri3_surf->base.SwapInterval = interval;
|
||||
}
|
||||
|
||||
static void
|
||||
egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
|
||||
int width, int height)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
|
||||
dri3_surf->base.Width = width;
|
||||
dri3_surf->base.Height = height;
|
||||
}
|
||||
|
||||
static bool
|
||||
egl_dri3_in_current_context(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
|
||||
return ctx->Resource.Display == dri3_surf->base.Resource.Display;
|
||||
}
|
||||
|
||||
static __DRIcontext *
|
||||
egl_dri3_get_dri_context(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
||||
|
||||
return dri2_ctx->dri_context;
|
||||
}
|
||||
|
||||
static void
|
||||
egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
_EGLDisplay *disp = dri3_surf->base.Resource.Display;
|
||||
|
||||
dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->base);
|
||||
}
|
||||
|
||||
static struct loader_dri3_vtable egl_dri3_vtable = {
|
||||
.get_swap_interval = egl_dri3_get_swap_interval,
|
||||
.clamp_swap_interval = egl_dri3_clamp_swap_interval,
|
||||
.set_swap_interval = egl_dri3_set_swap_interval,
|
||||
.set_drawable_size = egl_dri3_set_drawable_size,
|
||||
.in_current_context = egl_dri3_in_current_context,
|
||||
.get_dri_context = egl_dri3_get_dri_context,
|
||||
.flush_drawable = egl_dri3_flush_drawable,
|
||||
.show_fps = NULL,
|
||||
};
|
||||
|
||||
static EGLBoolean
|
||||
dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
(void) drv;
|
||||
|
||||
if (!_eglPutSurface(surf))
|
||||
return EGL_TRUE;
|
||||
|
||||
loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
|
||||
|
||||
free(surf);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_set_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
|
||||
EGLint interval)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
|
||||
_EGLConfig *conf, void *native_surface,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
|
||||
struct dri3_egl_surface *dri3_surf;
|
||||
const __DRIconfig *dri_config;
|
||||
xcb_drawable_t drawable;
|
||||
xcb_screen_iterator_t s;
|
||||
xcb_screen_t *screen;
|
||||
|
||||
STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
|
||||
drawable = (uintptr_t) native_surface;
|
||||
|
||||
(void) drv;
|
||||
|
||||
dri3_surf = calloc(1, sizeof *dri3_surf);
|
||||
if (!dri3_surf) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_create_surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitSurface(&dri3_surf->base, disp, type, conf, attrib_list))
|
||||
goto cleanup_surf;
|
||||
|
||||
if (type == EGL_PBUFFER_BIT) {
|
||||
s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
|
||||
screen = get_xcb_screen(s, dri2_dpy->screen);
|
||||
if (!screen) {
|
||||
_eglError(EGL_BAD_NATIVE_WINDOW, "dri3_create_surface");
|
||||
goto cleanup_surf;
|
||||
}
|
||||
|
||||
drawable = xcb_generate_id(dri2_dpy->conn);
|
||||
xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
|
||||
drawable, screen->root,
|
||||
dri3_surf->base.Width, dri3_surf->base.Height);
|
||||
}
|
||||
|
||||
dri_config = dri2_get_dri_config(dri2_conf, type,
|
||||
dri3_surf->base.GLColorspace);
|
||||
|
||||
if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
|
||||
dri2_dpy->dri_screen,
|
||||
dri2_dpy->is_different_gpu, dri_config,
|
||||
&dri2_dpy->loader_dri3_ext,
|
||||
&egl_dri3_vtable,
|
||||
&dri3_surf->loader_drawable)) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_surface_create");
|
||||
goto cleanup_pixmap;
|
||||
}
|
||||
|
||||
return &dri3_surf->base;
|
||||
|
||||
cleanup_pixmap:
|
||||
if (type == EGL_PBUFFER_BIT)
|
||||
xcb_free_pixmap(dri2_dpy->conn, drawable);
|
||||
cleanup_surf:
|
||||
free(dri3_surf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
|
||||
*/
|
||||
static _EGLSurface *
|
||||
dri3_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
|
||||
_EGLConfig *conf, void *native_window,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
_EGLSurface *surf;
|
||||
|
||||
surf = dri3_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
|
||||
native_window, attrib_list);
|
||||
if (surf != NULL)
|
||||
dri3_set_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri3_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
|
||||
_EGLConfig *conf, void *native_pixmap,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
return dri3_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
|
||||
native_pixmap, attrib_list);
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri3_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
|
||||
_EGLConfig *conf, const EGLint *attrib_list)
|
||||
{
|
||||
return dri3_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
|
||||
XCB_WINDOW_NONE, attrib_list);
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
|
||||
EGLuint64KHR *ust, EGLuint64KHR *msc,
|
||||
EGLuint64KHR *sbc)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface);
|
||||
|
||||
return loader_dri3_wait_for_msc(&dri3_surf->loader_drawable, 0, 0, 0,
|
||||
(int64_t *) ust, (int64_t *) msc,
|
||||
(int64_t *) sbc) ? EGL_TRUE : EGL_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the driver when it needs to update the real front buffer with the
|
||||
* contents of its fake front buffer.
|
||||
*/
|
||||
static void
|
||||
dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
/* There does not seem to be any kind of consensus on whether we should
|
||||
* support front-buffer rendering or not:
|
||||
* http://lists.freedesktop.org/archives/mesa-dev/2013-June/040129.html
|
||||
*/
|
||||
_eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
|
||||
(void) driDrawable;
|
||||
(void) loaderPrivate;
|
||||
}
|
||||
|
||||
const __DRIimageLoaderExtension dri3_image_loader_extension = {
|
||||
.base = { __DRI_IMAGE_LOADER, 1 },
|
||||
|
||||
.getBuffers = loader_dri3_get_buffers,
|
||||
.flushFrontBuffer = dri3_flush_front_buffer,
|
||||
};
|
||||
|
||||
static EGLBoolean
|
||||
dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
|
||||
|
||||
/* No-op for a pixmap or pbuffer surface */
|
||||
if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
|
||||
return 0;
|
||||
|
||||
return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
|
||||
0, 0, 0, 0,
|
||||
draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
|
||||
void *native_pixmap_target)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
xcb_pixmap_t target;
|
||||
|
||||
STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
|
||||
target = (uintptr_t) native_pixmap_target;
|
||||
|
||||
loader_dri3_copy_drawable(&dri3_surf->loader_drawable, target,
|
||||
dri3_surf->loader_drawable.drawable);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
|
||||
}
|
||||
|
||||
static __DRIdrawable *
|
||||
dri3_get_dri_drawable(_EGLSurface *surf)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
return dri3_surf->loader_drawable.dri_drawable;
|
||||
}
|
||||
|
||||
struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
|
||||
.authenticate = NULL,
|
||||
.create_window_surface = dri3_create_window_surface,
|
||||
.create_pixmap_surface = dri3_create_pixmap_surface,
|
||||
.create_pbuffer_surface = dri3_create_pbuffer_surface,
|
||||
.destroy_surface = dri3_destroy_surface,
|
||||
.create_image = dri2_create_image_khr,
|
||||
.swap_interval = dri3_set_swap_interval,
|
||||
.swap_buffers = dri3_swap_buffers,
|
||||
.swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
|
||||
.swap_buffers_region = dri2_fallback_swap_buffers_region,
|
||||
.post_sub_buffer = dri2_fallback_post_sub_buffer,
|
||||
.copy_buffers = dri3_copy_buffers,
|
||||
.query_buffer_age = dri3_query_buffer_age,
|
||||
.create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
|
||||
.get_sync_values = dri3_get_sync_values,
|
||||
.get_dri_drawable = dri3_get_dri_drawable,
|
||||
};
|
||||
|
||||
static char *
|
||||
dri3_get_device_name(int fd)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
ret = drmGetRenderDeviceNameFromFd(fd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* For dri3, render node support is required for WL_bind_wayland_display.
|
||||
* In order not to regress on older systems without kernel or libdrm
|
||||
* support, fall back to dri2. User can override it with environment
|
||||
* variable if they don't need to use that extension.
|
||||
*/
|
||||
if (getenv("EGL_FORCE_DRI3") == NULL) {
|
||||
_eglLog(_EGL_WARNING, "Render node support not available, falling back to dri2");
|
||||
_eglLog(_EGL_WARNING, "If you want to force dri3, set EGL_FORCE_DRI3 environment variable");
|
||||
} else
|
||||
ret = loader_get_device_name_for_fd(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
|
||||
{
|
||||
xcb_dri3_query_version_reply_t *dri3_query;
|
||||
xcb_dri3_query_version_cookie_t dri3_query_cookie;
|
||||
xcb_present_query_version_reply_t *present_query;
|
||||
xcb_present_query_version_cookie_t present_query_cookie;
|
||||
xcb_generic_error_t *error;
|
||||
xcb_screen_iterator_t s;
|
||||
xcb_screen_t *screen;
|
||||
const xcb_query_extension_reply_t *extension;
|
||||
|
||||
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
|
||||
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
|
||||
|
||||
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri3_id);
|
||||
if (!(extension && extension->present))
|
||||
return EGL_FALSE;
|
||||
|
||||
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_present_id);
|
||||
if (!(extension && extension->present))
|
||||
return EGL_FALSE;
|
||||
|
||||
dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
|
||||
XCB_DRI3_MAJOR_VERSION,
|
||||
XCB_DRI3_MINOR_VERSION);
|
||||
|
||||
present_query_cookie = xcb_present_query_version(dri2_dpy->conn,
|
||||
XCB_PRESENT_MAJOR_VERSION,
|
||||
XCB_PRESENT_MINOR_VERSION);
|
||||
|
||||
dri3_query =
|
||||
xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
|
||||
if (dri3_query == NULL || error != NULL) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: failed to query dri3 version");
|
||||
free(dri3_query);
|
||||
free(error);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
free(dri3_query);
|
||||
|
||||
present_query =
|
||||
xcb_present_query_version_reply(dri2_dpy->conn,
|
||||
present_query_cookie, &error);
|
||||
if (present_query == NULL || error != NULL) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: failed to query Present version");
|
||||
free(present_query);
|
||||
free(error);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
free(present_query);
|
||||
|
||||
s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
|
||||
screen = get_xcb_screen(s, dri2_dpy->screen);
|
||||
if (!screen) {
|
||||
_eglError(EGL_BAD_NATIVE_WINDOW, "dri3_x11_connect");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, screen->root, 0);
|
||||
if (dri2_dpy->fd < 0) {
|
||||
int conn_error = xcb_connection_has_error(dri2_dpy->conn);
|
||||
_eglLog(_EGL_WARNING, "DRI2: Screen seem not DRI3 capable");
|
||||
|
||||
if (conn_error)
|
||||
_eglLog(_EGL_WARNING, "DRI2: Failed to initialize DRI3");
|
||||
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
|
||||
|
||||
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
|
||||
if (!dri2_dpy->driver_name) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: No driver found");
|
||||
close(dri2_dpy->fd);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
dri2_dpy->device_name = dri3_get_device_name(dri2_dpy->fd);
|
||||
if (!dri2_dpy->device_name) {
|
||||
close(dri2_dpy->fd);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
41
src/egl/drivers/dri2/platform_x11_dri3.h
Normal file
41
src/egl/drivers/dri2/platform_x11_dri3.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright © 2015 Boyan Ding
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL 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 PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EGL_X11_DRI3_INCLUDED
|
||||
#define EGL_X11_DRI3_INCLUDED
|
||||
|
||||
#include "egl_dri2.h"
|
||||
|
||||
_EGL_DRIVER_TYPECAST(dri3_egl_surface, _EGLSurface, obj)
|
||||
|
||||
struct dri3_egl_surface {
|
||||
_EGLSurface base;
|
||||
struct loader_dri3_drawable loader_drawable;
|
||||
};
|
||||
|
||||
extern const __DRIimageLoaderExtension dri3_image_loader_extension;
|
||||
extern struct dri2_egl_display_vtbl dri3_x11_display_vtbl;
|
||||
|
||||
EGLBoolean
|
||||
dri3_x11_connect(struct dri2_egl_display *dri2_dpy);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue