2011-08-24 16:54:32 +08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2010 Intel Corporation.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person
|
|
|
|
|
* obtaining a copy of this software and associated documentation
|
|
|
|
|
* files (the "Software"), to deal in the Software without
|
|
|
|
|
* restriction, including without limitation the rights to use, copy,
|
|
|
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
|
|
|
* of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including
|
|
|
|
|
* the next paragraph) shall be included in all copies or substantial
|
|
|
|
|
* portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
|
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*
|
|
|
|
|
* Authors:
|
|
|
|
|
* Zhigang Gong <zhigang.gong@linux.intel.com>
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2013-10-30 11:30:23 -04:00
|
|
|
#include "dix-config.h"
|
2012-01-05 14:26:01 +08:00
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
#define GLAMOR_FOR_XORG
|
2011-08-24 16:54:32 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
#include <errno.h>
|
2019-10-14 12:48:24 +02:00
|
|
|
#include <xf86.h>
|
|
|
|
|
#include <xf86Priv.h>
|
2011-08-24 16:54:32 +08:00
|
|
|
#include <xf86drm.h>
|
|
|
|
|
#define EGL_DISPLAY_NO_X_MESA
|
|
|
|
|
|
2011-09-20 15:14:49 +08:00
|
|
|
#include <gbm.h>
|
2013-12-05 08:49:15 +01:00
|
|
|
#include <drm_fourcc.h>
|
2011-09-20 15:14:49 +08:00
|
|
|
|
2016-10-05 12:34:34 -04:00
|
|
|
#include "glamor_egl.h"
|
2011-08-24 16:54:32 +08:00
|
|
|
|
2011-12-12 07:09:03 +08:00
|
|
|
#include "glamor.h"
|
2013-12-18 15:27:52 -08:00
|
|
|
#include "glamor_priv.h"
|
2022-07-21 00:49:13 +03:00
|
|
|
#include "glamor_glx_provider.h"
|
2013-12-31 00:07:42 -08:00
|
|
|
#include "dri3.h"
|
2011-12-12 07:09:03 +08:00
|
|
|
|
2011-09-08 15:16:01 +08:00
|
|
|
struct glamor_egl_screen_private {
|
2013-12-18 11:59:07 -08:00
|
|
|
EGLDisplay display;
|
|
|
|
|
EGLContext context;
|
2013-12-31 00:07:42 -08:00
|
|
|
char *device_path;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
CreateScreenResourcesProcPtr CreateScreenResources;
|
|
|
|
|
CloseScreenProcPtr CloseScreen;
|
2013-12-18 11:59:07 -08:00
|
|
|
int fd;
|
|
|
|
|
struct gbm_device *gbm;
|
2018-02-28 01:19:43 +00:00
|
|
|
int dmabuf_capable;
|
2025-11-07 14:44:55 +02:00
|
|
|
char *glvnd_vendor; /* GLVND vendor if forced from options or NULL otherwise */
|
2013-12-18 11:59:07 -08:00
|
|
|
|
|
|
|
|
CloseScreenProcPtr saved_close_screen;
|
2015-10-18 19:26:14 -07:00
|
|
|
DestroyPixmapProcPtr saved_destroy_pixmap;
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86FreeScreenProc *saved_free_screen;
|
2011-08-24 16:54:32 +08:00
|
|
|
};
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
int xf86GlamorEGLPrivateIndex = -1;
|
|
|
|
|
|
2013-12-18 15:27:52 -08:00
|
|
|
|
GLX: Enable glx support.
If we are using MESA as our GL library, then both xserver's
GLX and glamor are link to the same library. As xserver's
GLX has its own _glapi_get/set_context/dispatch etc, and it
is a simplified version derived from mesa thus is not
sufficient for mesa/egl's dri loader which is used by glamor.
Then if glx module is loaded before glamoregl module, the
initialization of mesa/egl/opengl will not be correct, and
will fail at a very early stage, most likely fail to map
the element buffer.
Two methodis to fix this problem, first is to modify the xserver's
glx's glapi.c to fit mesa's requirement. The second is to put
a glamor.conf as below, to the system's xorg.conf path.
Section "Module"
Load "glamoregl"
EndSection
Then glamor will be loaded firstly, and the mesa's libglapi.so
will be used. As current xserver's dispatch table is the same
as mesa's, then the glx's dri loader can work without problem.
We took the second method as it don't need any change to xorg.:)
Although this is not a graceful implementation as it depends
on the xserver's dispatch table and the mesa's dispatch table
is the same and the context set and get is using the same method.
Anyway it works.
As by default, xserver will enable GLX_USE_TLS. But mesa will not
enable it, you may need to enable that when build mesa.
Three pre-requirements to make this glamor version work:
0. Make sure xserver has commit 66e603, if not please pull the latest
master branch.
1. Rebuild mesa by enable GLX_USE_TLS.
2. Put the glamor.conf to your system's xorg.conf path and make sure
it loaded prior to glx module.
Preliminary testing shows indirect glxgears works fine.
If user want to use GLES2 for glamor by using MESA, GLX will not
work correctly.
If you are not using normal MESA, for example PVR's private GLES
implementation, then it should be ok to use GLES2 glamor and the
GLX should work as expected. In this commit, I use gbm to check
whether we are using MESA or non-mesa. Maybe not the best way.
Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
2012-02-10 16:04:07 +08:00
|
|
|
static struct glamor_egl_screen_private *
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(ScrnInfoPtr scrn)
|
2011-08-24 16:54:32 +08:00
|
|
|
{
|
2019-10-14 12:48:24 +02:00
|
|
|
return (struct glamor_egl_screen_private *)
|
|
|
|
|
scrn->privates[xf86GlamorEGLPrivateIndex].ptr;
|
2011-08-24 16:54:32 +08:00
|
|
|
}
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2013-12-18 15:27:52 -08:00
|
|
|
static void
|
2014-03-14 17:31:18 -07:00
|
|
|
glamor_egl_make_current(struct glamor_context *glamor_ctx)
|
GLX: Enable glx support.
If we are using MESA as our GL library, then both xserver's
GLX and glamor are link to the same library. As xserver's
GLX has its own _glapi_get/set_context/dispatch etc, and it
is a simplified version derived from mesa thus is not
sufficient for mesa/egl's dri loader which is used by glamor.
Then if glx module is loaded before glamoregl module, the
initialization of mesa/egl/opengl will not be correct, and
will fail at a very early stage, most likely fail to map
the element buffer.
Two methodis to fix this problem, first is to modify the xserver's
glx's glapi.c to fit mesa's requirement. The second is to put
a glamor.conf as below, to the system's xorg.conf path.
Section "Module"
Load "glamoregl"
EndSection
Then glamor will be loaded firstly, and the mesa's libglapi.so
will be used. As current xserver's dispatch table is the same
as mesa's, then the glx's dri loader can work without problem.
We took the second method as it don't need any change to xorg.:)
Although this is not a graceful implementation as it depends
on the xserver's dispatch table and the mesa's dispatch table
is the same and the context set and get is using the same method.
Anyway it works.
As by default, xserver will enable GLX_USE_TLS. But mesa will not
enable it, you may need to enable that when build mesa.
Three pre-requirements to make this glamor version work:
0. Make sure xserver has commit 66e603, if not please pull the latest
master branch.
1. Rebuild mesa by enable GLX_USE_TLS.
2. Put the glamor.conf to your system's xorg.conf path and make sure
it loaded prior to glx module.
Preliminary testing shows indirect glxgears works fine.
If user want to use GLES2 for glamor by using MESA, GLX will not
work correctly.
If you are not using normal MESA, for example PVR's private GLES
implementation, then it should be ok to use GLES2 glamor and the
GLX should work as expected. In this commit, I use gbm to check
whether we are using MESA or non-mesa. Maybe not the best way.
Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
2012-02-10 16:04:07 +08:00
|
|
|
{
|
2014-04-04 07:03:31 +01:00
|
|
|
/* There's only a single global dispatch table in Mesa. EGL, GLX,
|
|
|
|
|
* and AIGLX's direct dispatch table manipulation don't talk to
|
|
|
|
|
* each other. We need to set the context to NULL first to avoid
|
|
|
|
|
* EGL's no-op context change fast path when switching back to
|
|
|
|
|
* EGL.
|
|
|
|
|
*/
|
2014-03-14 17:20:12 -07:00
|
|
|
eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
|
|
|
|
|
EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
2014-04-04 07:03:31 +01:00
|
|
|
|
2014-03-14 17:20:12 -07:00
|
|
|
if (!eglMakeCurrent(glamor_ctx->display,
|
|
|
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
|
|
|
|
glamor_ctx->ctx)) {
|
|
|
|
|
FatalError("Failed to make EGL context current\n");
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
GLX: Enable glx support.
If we are using MESA as our GL library, then both xserver's
GLX and glamor are link to the same library. As xserver's
GLX has its own _glapi_get/set_context/dispatch etc, and it
is a simplified version derived from mesa thus is not
sufficient for mesa/egl's dri loader which is used by glamor.
Then if glx module is loaded before glamoregl module, the
initialization of mesa/egl/opengl will not be correct, and
will fail at a very early stage, most likely fail to map
the element buffer.
Two methodis to fix this problem, first is to modify the xserver's
glx's glapi.c to fit mesa's requirement. The second is to put
a glamor.conf as below, to the system's xorg.conf path.
Section "Module"
Load "glamoregl"
EndSection
Then glamor will be loaded firstly, and the mesa's libglapi.so
will be used. As current xserver's dispatch table is the same
as mesa's, then the glx's dri loader can work without problem.
We took the second method as it don't need any change to xorg.:)
Although this is not a graceful implementation as it depends
on the xserver's dispatch table and the mesa's dispatch table
is the same and the context set and get is using the same method.
Anyway it works.
As by default, xserver will enable GLX_USE_TLS. But mesa will not
enable it, you may need to enable that when build mesa.
Three pre-requirements to make this glamor version work:
0. Make sure xserver has commit 66e603, if not please pull the latest
master branch.
1. Rebuild mesa by enable GLX_USE_TLS.
2. Put the glamor.conf to your system's xorg.conf path and make sure
it loaded prior to glx module.
Preliminary testing shows indirect glxgears works fine.
If user want to use GLES2 for glamor by using MESA, GLX will not
work correctly.
If you are not using normal MESA, for example PVR's private GLES
implementation, then it should be ok to use GLES2 glamor and the
GLX should work as expected. In this commit, I use gbm to check
whether we are using MESA or non-mesa. Maybe not the best way.
Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
2012-02-10 16:04:07 +08:00
|
|
|
}
|
|
|
|
|
|
2011-09-08 15:16:01 +08:00
|
|
|
static int
|
|
|
|
|
glamor_get_flink_name(int fd, int handle, int *name)
|
|
|
|
|
{
|
2013-12-18 11:59:07 -08:00
|
|
|
struct drm_gem_flink flink;
|
|
|
|
|
|
|
|
|
|
flink.handle = handle;
|
2018-06-20 19:23:48 +02:00
|
|
|
if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Assume non-GEM kernels have names identical to the handle
|
|
|
|
|
*/
|
|
|
|
|
if (errno == ENODEV) {
|
|
|
|
|
*name = handle;
|
|
|
|
|
return TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-12-18 11:59:07 -08:00
|
|
|
*name = flink.name;
|
|
|
|
|
return TRUE;
|
2011-09-08 15:16:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Bool
|
2014-04-16 16:16:21 -07:00
|
|
|
glamor_create_texture_from_image(ScreenPtr screen,
|
2013-12-18 11:59:07 -08:00
|
|
|
EGLImageKHR image, GLuint * texture)
|
2011-09-08 15:16:01 +08:00
|
|
|
{
|
2014-04-16 16:16:21 -07:00
|
|
|
struct glamor_screen_private *glamor_priv =
|
|
|
|
|
glamor_get_screen_private(screen);
|
|
|
|
|
|
2014-03-14 17:31:18 -07:00
|
|
|
glamor_make_current(glamor_priv);
|
2014-04-16 16:16:21 -07:00
|
|
|
|
2013-12-18 12:18:20 -08:00
|
|
|
glGenTextures(1, texture);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, *texture);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
|
|
|
|
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
2014-04-16 16:16:21 -07:00
|
|
|
|
2013-12-18 11:59:07 -08:00
|
|
|
return TRUE;
|
2011-08-24 16:54:32 +08:00
|
|
|
}
|
|
|
|
|
|
2015-06-18 11:21:10 -07:00
|
|
|
struct gbm_device *
|
2014-12-09 12:28:38 -08:00
|
|
|
glamor_egl_get_gbm_device(ScreenPtr screen)
|
|
|
|
|
{
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
2014-12-09 12:28:38 -08:00
|
|
|
return glamor_egl->gbm;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-24 16:54:32 +08:00
|
|
|
Bool
|
2011-11-02 13:44:50 +08:00
|
|
|
glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride)
|
2011-08-24 16:54:32 +08:00
|
|
|
{
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2013-12-18 11:59:07 -08:00
|
|
|
PixmapPtr screen_pixmap;
|
|
|
|
|
|
|
|
|
|
screen_pixmap = screen->GetScreenPixmap(screen);
|
|
|
|
|
|
|
|
|
|
if (!glamor_egl_create_textured_pixmap(screen_pixmap, handle, stride)) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2013-12-18 11:59:07 -08:00
|
|
|
"Failed to create textured screen.");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
2012-02-17 16:56:05 +08:00
|
|
|
}
|
|
|
|
|
|
2014-12-08 12:59:31 -08:00
|
|
|
static void
|
2018-04-04 16:16:34 +01:00
|
|
|
glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image,
|
|
|
|
|
Bool used_modifiers)
|
2014-12-08 12:59:31 -08:00
|
|
|
{
|
|
|
|
|
struct glamor_pixmap_private *pixmap_priv =
|
|
|
|
|
glamor_get_pixmap_private(pixmap);
|
|
|
|
|
EGLImageKHR old;
|
|
|
|
|
|
2014-10-29 23:08:57 -07:00
|
|
|
old = pixmap_priv->image;
|
2014-12-08 12:59:31 -08:00
|
|
|
if (old) {
|
|
|
|
|
ScreenPtr screen = pixmap->drawable.pScreen;
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn);
|
2014-12-08 12:59:31 -08:00
|
|
|
|
|
|
|
|
eglDestroyImageKHR(glamor_egl->display, old);
|
|
|
|
|
}
|
2014-10-29 23:08:57 -07:00
|
|
|
pixmap_priv->image = image;
|
2018-04-04 16:16:34 +01:00
|
|
|
pixmap_priv->used_modifiers = used_modifiers;
|
2014-12-08 12:59:31 -08:00
|
|
|
}
|
|
|
|
|
|
2011-09-08 15:16:01 +08:00
|
|
|
Bool
|
2011-11-02 13:44:50 +08:00
|
|
|
glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
|
2011-09-08 15:16:01 +08:00
|
|
|
{
|
2013-12-18 11:59:07 -08:00
|
|
|
ScreenPtr screen = pixmap->drawable.pScreen;
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2017-05-16 11:37:20 -07:00
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(scrn);
|
2017-05-16 11:37:20 -07:00
|
|
|
int ret, fd;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2017-05-16 11:37:20 -07:00
|
|
|
/* GBM doesn't have an import path from handles, so we make a
|
|
|
|
|
* dma-buf fd from it and then go through that.
|
|
|
|
|
*/
|
|
|
|
|
ret = drmPrimeHandleToFD(glamor_egl->fd, handle, O_CLOEXEC, &fd);
|
|
|
|
|
if (ret) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2017-05-16 11:37:20 -07:00
|
|
|
"Failed to make prime FD for handle: %d\n", errno);
|
2017-05-16 11:37:15 -07:00
|
|
|
return FALSE;
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
|
|
|
|
|
2017-05-16 11:37:20 -07:00
|
|
|
if (!glamor_back_pixmap_from_fd(pixmap, fd,
|
|
|
|
|
pixmap->drawable.width,
|
|
|
|
|
pixmap->drawable.height,
|
|
|
|
|
stride,
|
|
|
|
|
pixmap->drawable.depth,
|
|
|
|
|
pixmap->drawable.bitsPerPixel)) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2017-05-16 11:37:20 -07:00
|
|
|
"Failed to make import prime FD as pixmap: %d\n", errno);
|
|
|
|
|
close(fd);
|
|
|
|
|
return FALSE;
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
|
|
|
|
|
2017-05-16 11:37:20 -07:00
|
|
|
close(fd);
|
|
|
|
|
return TRUE;
|
2011-11-02 13:44:50 +08:00
|
|
|
}
|
|
|
|
|
|
2013-11-18 22:52:22 +01:00
|
|
|
Bool
|
2015-06-18 11:21:10 -07:00
|
|
|
glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
|
2018-04-04 16:16:34 +01:00
|
|
|
struct gbm_bo *bo,
|
|
|
|
|
Bool used_modifiers)
|
2013-11-18 22:52:22 +01:00
|
|
|
{
|
2013-12-18 11:59:07 -08:00
|
|
|
ScreenPtr screen = pixmap->drawable.pScreen;
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2013-12-18 15:27:52 -08:00
|
|
|
struct glamor_screen_private *glamor_priv =
|
|
|
|
|
glamor_get_screen_private(screen);
|
2013-12-18 11:59:07 -08:00
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
EGLImageKHR image;
|
|
|
|
|
GLuint texture;
|
|
|
|
|
Bool ret = FALSE;
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl = glamor_egl_get_screen_private(scrn);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2014-03-14 17:31:18 -07:00
|
|
|
glamor_make_current(glamor_priv);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2013-12-18 12:18:20 -08:00
|
|
|
image = eglCreateImageKHR(glamor_egl->display,
|
2018-12-13 19:15:01 +01:00
|
|
|
EGL_NO_CONTEXT,
|
2013-12-18 12:18:20 -08:00
|
|
|
EGL_NATIVE_PIXMAP_KHR, bo, NULL);
|
2013-12-18 11:59:07 -08:00
|
|
|
if (image == EGL_NO_IMAGE_KHR) {
|
|
|
|
|
glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY);
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
2014-04-16 16:16:21 -07:00
|
|
|
glamor_create_texture_from_image(screen, image, &texture);
|
2013-12-18 11:59:07 -08:00
|
|
|
glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
|
|
|
|
|
glamor_set_pixmap_texture(pixmap, texture);
|
2018-04-04 16:16:34 +01:00
|
|
|
glamor_egl_set_pixmap_image(pixmap, image, used_modifiers);
|
2013-12-18 11:59:07 -08:00
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
return ret;
|
2013-11-18 22:52:22 +01:00
|
|
|
}
|
|
|
|
|
|
2015-10-15 13:25:12 -07:00
|
|
|
static void
|
2013-12-18 11:59:07 -08:00
|
|
|
glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
|
2013-12-05 08:49:15 +01:00
|
|
|
{
|
2013-12-18 11:59:07 -08:00
|
|
|
union gbm_bo_handle handle;
|
2013-12-05 08:49:15 +01:00
|
|
|
|
2013-12-18 11:59:07 -08:00
|
|
|
handle = gbm_bo_get_handle(bo);
|
|
|
|
|
if (!glamor_get_flink_name(gbm_fd, handle.u32, name))
|
|
|
|
|
*name = -1;
|
2013-12-05 08:49:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-18 11:14:41 -07:00
|
|
|
static Bool
|
2018-04-04 16:16:36 +01:00
|
|
|
glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok)
|
2015-01-13 17:00:28 -08:00
|
|
|
{
|
2015-06-18 11:14:41 -07:00
|
|
|
ScreenPtr screen = pixmap->drawable.pScreen;
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2015-06-18 11:14:41 -07:00
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(scrn);
|
2013-12-27 18:45:44 -08:00
|
|
|
struct glamor_pixmap_private *pixmap_priv =
|
|
|
|
|
glamor_get_pixmap_private(pixmap);
|
2015-06-18 11:14:41 -07:00
|
|
|
unsigned width = pixmap->drawable.width;
|
|
|
|
|
unsigned height = pixmap->drawable.height;
|
2018-02-28 01:19:45 +00:00
|
|
|
uint32_t format;
|
2018-04-04 16:16:37 +01:00
|
|
|
struct gbm_bo *bo = NULL;
|
2018-04-04 16:16:34 +01:00
|
|
|
Bool used_modifiers = FALSE;
|
2015-06-18 11:14:41 -07:00
|
|
|
PixmapPtr exported;
|
|
|
|
|
GCPtr scratch_gc;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2018-04-04 16:16:36 +01:00
|
|
|
if (pixmap_priv->image &&
|
|
|
|
|
(modifiers_ok || !pixmap_priv->used_modifiers))
|
2015-06-18 11:14:41 -07:00
|
|
|
return TRUE;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2018-09-04 20:52:57 -07:00
|
|
|
switch (pixmap->drawable.depth) {
|
|
|
|
|
case 30:
|
|
|
|
|
format = GBM_FORMAT_ARGB2101010;
|
|
|
|
|
break;
|
|
|
|
|
case 32:
|
|
|
|
|
case 24:
|
|
|
|
|
format = GBM_FORMAT_ARGB8888;
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
|
|
|
|
format = GBM_FORMAT_RGB565;
|
|
|
|
|
break;
|
2018-10-05 12:24:23 +02:00
|
|
|
case 15:
|
|
|
|
|
format = GBM_FORMAT_ARGB1555;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
format = GBM_FORMAT_R8;
|
|
|
|
|
break;
|
2018-09-04 20:52:57 -07:00
|
|
|
default:
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2018-09-04 20:52:57 -07:00
|
|
|
"Failed to make %d depth, %dbpp pixmap exportable\n",
|
|
|
|
|
pixmap->drawable.depth, pixmap->drawable.bitsPerPixel);
|
2015-06-18 11:14:41 -07:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2018-02-28 01:19:45 +00:00
|
|
|
#ifdef GBM_BO_WITH_MODIFIERS
|
2018-04-04 16:16:36 +01:00
|
|
|
if (modifiers_ok && glamor_egl->dmabuf_capable) {
|
2018-02-28 01:19:45 +00:00
|
|
|
uint32_t num_modifiers;
|
|
|
|
|
uint64_t *modifiers = NULL;
|
|
|
|
|
|
|
|
|
|
glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
|
|
|
|
|
|
|
|
|
|
bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height,
|
|
|
|
|
format, modifiers, num_modifiers);
|
2018-04-04 16:16:34 +01:00
|
|
|
if (bo)
|
|
|
|
|
used_modifiers = TRUE;
|
2018-02-28 01:19:45 +00:00
|
|
|
free(modifiers);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2018-04-04 16:16:37 +01:00
|
|
|
|
|
|
|
|
if (!bo)
|
2018-02-28 01:19:45 +00:00
|
|
|
{
|
|
|
|
|
bo = gbm_bo_create(glamor_egl->gbm, width, height, format,
|
2015-06-18 11:14:41 -07:00
|
|
|
#ifdef GLAMOR_HAS_GBM_LINEAR
|
2018-02-28 01:19:45 +00:00
|
|
|
(pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ?
|
|
|
|
|
GBM_BO_USE_LINEAR : 0) |
|
2015-06-18 11:14:41 -07:00
|
|
|
#endif
|
2018-02-28 01:19:45 +00:00
|
|
|
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-18 11:14:41 -07:00
|
|
|
if (!bo) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2015-06-18 11:14:41 -07:00
|
|
|
"Failed to make %dx%dx%dbpp GBM bo\n",
|
|
|
|
|
width, height, pixmap->drawable.bitsPerPixel);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2015-06-18 11:14:41 -07:00
|
|
|
exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0);
|
|
|
|
|
screen->ModifyPixmapHeader(exported, width, height, 0, 0,
|
|
|
|
|
gbm_bo_get_stride(bo), NULL);
|
2018-04-04 16:16:34 +01:00
|
|
|
if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo,
|
|
|
|
|
used_modifiers)) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2015-06-18 11:14:41 -07:00
|
|
|
"Failed to make %dx%dx%dbpp pixmap from GBM bo\n",
|
|
|
|
|
width, height, pixmap->drawable.bitsPerPixel);
|
2025-06-11 17:44:28 -07:00
|
|
|
screen->DestroyPixmap(exported);
|
2015-06-18 11:14:41 -07:00
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
return FALSE;
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
2015-06-18 11:14:41 -07:00
|
|
|
gbm_bo_destroy(bo);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2015-06-18 11:14:41 -07:00
|
|
|
scratch_gc = GetScratchGC(pixmap->drawable.depth, screen);
|
|
|
|
|
ValidateGC(&pixmap->drawable, scratch_gc);
|
2024-08-20 18:23:48 +02:00
|
|
|
(void) scratch_gc->ops->CopyArea(&pixmap->drawable, &exported->drawable,
|
2015-06-18 11:14:41 -07:00
|
|
|
scratch_gc,
|
|
|
|
|
0, 0, width, height, 0, 0);
|
|
|
|
|
FreeScratchGC(scratch_gc);
|
2015-01-13 17:00:28 -08:00
|
|
|
|
2015-06-18 11:14:41 -07:00
|
|
|
/* Now, swap the tex/gbm/EGLImage/etc. of the exported pixmap into
|
|
|
|
|
* the original pixmap struct.
|
|
|
|
|
*/
|
|
|
|
|
glamor_egl_exchange_buffers(pixmap, exported);
|
2015-01-13 17:00:28 -08:00
|
|
|
|
2020-10-05 18:19:52 -05:00
|
|
|
/* Swap the devKind into the original pixmap, reflecting the bo's stride */
|
|
|
|
|
screen->ModifyPixmapHeader(pixmap, 0, 0, 0, 0, exported->devKind, NULL);
|
|
|
|
|
|
2025-06-11 17:44:28 -07:00
|
|
|
screen->DestroyPixmap(exported);
|
2015-06-18 11:14:41 -07:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2015-01-13 17:00:28 -08:00
|
|
|
|
2019-04-26 13:37:09 +02:00
|
|
|
static struct gbm_bo *
|
|
|
|
|
glamor_gbm_bo_from_pixmap_internal(ScreenPtr screen, PixmapPtr pixmap)
|
2015-01-13 17:00:28 -08:00
|
|
|
{
|
2015-06-18 11:14:41 -07:00
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
2015-06-18 11:14:41 -07:00
|
|
|
struct glamor_pixmap_private *pixmap_priv =
|
2015-01-13 17:00:28 -08:00
|
|
|
glamor_get_pixmap_private(pixmap);
|
|
|
|
|
|
2018-04-04 16:16:35 +01:00
|
|
|
if (!pixmap_priv->image)
|
2015-01-13 17:00:28 -08:00
|
|
|
return NULL;
|
2015-06-18 11:14:41 -07:00
|
|
|
|
|
|
|
|
return gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE,
|
|
|
|
|
pixmap_priv->image, 0);
|
2015-01-13 17:00:28 -08:00
|
|
|
}
|
|
|
|
|
|
2019-04-26 13:37:09 +02:00
|
|
|
struct gbm_bo *
|
|
|
|
|
glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap)
|
|
|
|
|
{
|
|
|
|
|
if (!glamor_make_pixmap_exportable(pixmap, TRUE))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-13 17:00:28 -08:00
|
|
|
int
|
2018-02-28 01:19:43 +00:00
|
|
|
glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
|
|
|
|
|
uint32_t *strides, uint32_t *offsets,
|
|
|
|
|
uint64_t *modifier)
|
|
|
|
|
{
|
|
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
|
int num_fds;
|
|
|
|
|
#ifdef GBM_BO_WITH_MODIFIERS
|
2022-07-10 19:35:43 +02:00
|
|
|
#ifndef GBM_BO_FD_FOR_PLANE
|
|
|
|
|
int32_t first_handle;
|
|
|
|
|
#endif
|
2018-02-28 01:19:43 +00:00
|
|
|
int i;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-04-04 16:16:36 +01:00
|
|
|
if (!glamor_make_pixmap_exportable(pixmap, TRUE))
|
2018-02-28 01:19:43 +00:00
|
|
|
return 0;
|
|
|
|
|
|
2019-04-26 13:37:09 +02:00
|
|
|
bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
|
2018-02-28 01:19:43 +00:00
|
|
|
if (!bo)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
#ifdef GBM_BO_WITH_MODIFIERS
|
|
|
|
|
num_fds = gbm_bo_get_plane_count(bo);
|
|
|
|
|
for (i = 0; i < num_fds; i++) {
|
2022-07-10 19:35:43 +02:00
|
|
|
#ifdef GBM_BO_FD_FOR_PLANE
|
|
|
|
|
fds[i] = gbm_bo_get_fd_for_plane(bo, i);
|
|
|
|
|
#else
|
|
|
|
|
union gbm_bo_handle plane_handle = gbm_bo_get_handle_for_plane(bo, i);
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
first_handle = plane_handle.s32;
|
|
|
|
|
|
|
|
|
|
/* If all planes point to the same object as the first plane, i.e. they
|
|
|
|
|
* all have the same handle, we can fall back to the non-planar
|
|
|
|
|
* gbm_bo_get_fd without losing information. If they point to different
|
|
|
|
|
* objects we are out of luck and need to give up.
|
|
|
|
|
*/
|
|
|
|
|
if (first_handle == plane_handle.s32)
|
|
|
|
|
fds[i] = gbm_bo_get_fd(bo);
|
|
|
|
|
else
|
|
|
|
|
fds[i] = -1;
|
|
|
|
|
#endif
|
2022-07-28 22:52:15 +02:00
|
|
|
if (fds[i] == -1) {
|
|
|
|
|
while (--i >= 0)
|
|
|
|
|
close(fds[i]);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-02-28 01:19:43 +00:00
|
|
|
strides[i] = gbm_bo_get_stride_for_plane(bo, i);
|
|
|
|
|
offsets[i] = gbm_bo_get_offset(bo, i);
|
|
|
|
|
}
|
|
|
|
|
*modifier = gbm_bo_get_modifier(bo);
|
|
|
|
|
#else
|
|
|
|
|
num_fds = 1;
|
|
|
|
|
fds[0] = gbm_bo_get_fd(bo);
|
2022-07-28 22:52:15 +02:00
|
|
|
if (fds[0] == -1)
|
|
|
|
|
return 0;
|
2018-02-28 01:19:43 +00:00
|
|
|
strides[0] = gbm_bo_get_stride(bo);
|
|
|
|
|
offsets[0] = 0;
|
|
|
|
|
*modifier = DRM_FORMAT_MOD_INVALID;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
return num_fds;
|
|
|
|
|
#else
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
int
|
2018-04-04 16:16:38 +01:00
|
|
|
glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
|
|
|
|
|
CARD16 *stride, CARD32 *size)
|
|
|
|
|
{
|
|
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
|
|
if (!glamor_make_pixmap_exportable(pixmap, FALSE))
|
|
|
|
|
return -1;
|
|
|
|
|
|
2019-04-26 13:37:09 +02:00
|
|
|
bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
|
2018-04-04 16:16:38 +01:00
|
|
|
if (!bo)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
fd = gbm_bo_get_fd(bo);
|
|
|
|
|
*stride = gbm_bo_get_stride(bo);
|
|
|
|
|
*size = *stride * gbm_bo_get_height(bo);
|
|
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
|
#else
|
|
|
|
|
return -1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-28 01:19:43 +00:00
|
|
|
int
|
|
|
|
|
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
|
|
|
|
PixmapPtr pixmap,
|
|
|
|
|
CARD16 *stride, CARD32 *size)
|
2015-01-13 17:00:28 -08:00
|
|
|
{
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
|
int fd = -1;
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
2015-01-13 17:00:28 -08:00
|
|
|
|
2018-04-04 16:16:36 +01:00
|
|
|
if (!glamor_make_pixmap_exportable(pixmap, FALSE))
|
2018-04-04 16:16:35 +01:00
|
|
|
goto failure;
|
|
|
|
|
|
2019-04-26 13:37:09 +02:00
|
|
|
bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
|
2013-12-18 11:59:07 -08:00
|
|
|
if (!bo)
|
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
|
|
pixmap->devKind = gbm_bo_get_stride(bo);
|
|
|
|
|
|
2018-02-28 01:19:43 +00:00
|
|
|
glamor_get_name_from_bo(glamor_egl->fd, bo, &fd);
|
2013-12-30 18:41:57 -08:00
|
|
|
*stride = pixmap->devKind;
|
|
|
|
|
*size = pixmap->devKind * gbm_bo_get_height(bo);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
|
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
failure:
|
|
|
|
|
return fd;
|
2013-12-05 08:49:15 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-15 18:32:46 +01:00
|
|
|
static bool
|
|
|
|
|
gbm_format_for_depth(CARD8 depth, uint32_t *format)
|
|
|
|
|
{
|
|
|
|
|
switch (depth) {
|
|
|
|
|
case 15:
|
|
|
|
|
*format = GBM_FORMAT_ARGB1555;
|
|
|
|
|
return true;
|
|
|
|
|
case 16:
|
|
|
|
|
*format = GBM_FORMAT_RGB565;
|
|
|
|
|
return true;
|
|
|
|
|
case 24:
|
|
|
|
|
*format = GBM_FORMAT_XRGB8888;
|
|
|
|
|
return true;
|
|
|
|
|
case 30:
|
|
|
|
|
*format = GBM_FORMAT_ARGB2101010;
|
|
|
|
|
return true;
|
|
|
|
|
case 32:
|
|
|
|
|
*format = GBM_FORMAT_ARGB8888;
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
ErrorF("unexpected depth: %d\n", depth);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
Bool
|
2015-06-10 13:38:39 +10:00
|
|
|
glamor_back_pixmap_from_fd(PixmapPtr pixmap,
|
|
|
|
|
int fd,
|
|
|
|
|
CARD16 width,
|
|
|
|
|
CARD16 height,
|
|
|
|
|
CARD16 stride, CARD8 depth, CARD8 bpp)
|
2013-12-05 08:49:15 +01:00
|
|
|
{
|
2015-06-10 13:38:39 +10:00
|
|
|
ScreenPtr screen = pixmap->drawable.pScreen;
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2013-12-18 11:59:07 -08:00
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
struct gbm_bo *bo;
|
2015-06-18 11:26:46 -07:00
|
|
|
struct gbm_import_fd_data import_data = { 0 };
|
2015-06-18 11:14:41 -07:00
|
|
|
Bool ret;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl = glamor_egl_get_screen_private(scrn);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2025-01-15 18:34:27 +01:00
|
|
|
if (!gbm_format_for_depth(depth, &import_data.format) ||
|
|
|
|
|
width == 0 || height == 0)
|
2015-06-10 13:38:39 +10:00
|
|
|
return FALSE;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2015-06-18 11:26:46 -07:00
|
|
|
import_data.fd = fd;
|
|
|
|
|
import_data.width = width;
|
|
|
|
|
import_data.height = height;
|
|
|
|
|
import_data.stride = stride;
|
|
|
|
|
bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, 0);
|
2013-12-18 11:59:07 -08:00
|
|
|
if (!bo)
|
2015-06-10 13:38:39 +10:00
|
|
|
return FALSE;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
|
|
|
|
screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
|
|
|
|
|
|
2018-04-04 16:16:34 +01:00
|
|
|
ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, FALSE);
|
2013-12-18 11:59:07 -08:00
|
|
|
gbm_bo_destroy(bo);
|
2015-06-18 11:14:41 -07:00
|
|
|
return ret;
|
2015-06-10 13:38:39 +10:00
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
PixmapPtr
|
2018-02-28 01:19:43 +00:00
|
|
|
glamor_pixmap_from_fds(ScreenPtr screen,
|
2018-04-02 16:41:14 +01:00
|
|
|
CARD8 num_fds, const int *fds,
|
2018-02-28 01:19:43 +00:00
|
|
|
CARD16 width, CARD16 height,
|
2018-04-02 16:41:14 +01:00
|
|
|
const CARD32 *strides, const CARD32 *offsets,
|
2018-02-28 01:19:43 +00:00
|
|
|
CARD8 depth, CARD8 bpp,
|
|
|
|
|
uint64_t modifier)
|
2015-06-10 13:38:39 +10:00
|
|
|
{
|
|
|
|
|
PixmapPtr pixmap;
|
2018-02-28 01:19:43 +00:00
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
Bool ret = FALSE;
|
|
|
|
|
int i;
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
2015-06-10 13:38:39 +10:00
|
|
|
|
|
|
|
|
pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
|
2018-02-28 01:19:43 +00:00
|
|
|
|
|
|
|
|
#ifdef GBM_BO_WITH_MODIFIERS
|
|
|
|
|
if (glamor_egl->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) {
|
|
|
|
|
struct gbm_import_fd_modifier_data import_data = { 0 };
|
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
|
|
2025-01-15 18:32:46 +01:00
|
|
|
if (!gbm_format_for_depth(depth, &import_data.format) ||
|
|
|
|
|
width == 0 || height == 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
2018-02-28 01:19:43 +00:00
|
|
|
import_data.width = width;
|
|
|
|
|
import_data.height = height;
|
|
|
|
|
import_data.num_fds = num_fds;
|
|
|
|
|
import_data.modifier = modifier;
|
|
|
|
|
for (i = 0; i < num_fds; i++) {
|
|
|
|
|
import_data.fds[i] = fds[i];
|
|
|
|
|
import_data.strides[i] = strides[i];
|
|
|
|
|
import_data.offsets[i] = offsets[i];
|
|
|
|
|
}
|
|
|
|
|
bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0);
|
|
|
|
|
if (bo) {
|
|
|
|
|
screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL);
|
2018-04-04 16:16:34 +01:00
|
|
|
ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, TRUE);
|
2018-02-28 01:19:43 +00:00
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
if (num_fds == 1) {
|
|
|
|
|
ret = glamor_back_pixmap_from_fd(pixmap, fds[0], width, height,
|
|
|
|
|
strides[0], depth, bpp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-15 18:32:46 +01:00
|
|
|
error:
|
2015-06-10 13:38:39 +10:00
|
|
|
if (ret == FALSE) {
|
2025-06-11 17:44:28 -07:00
|
|
|
screen->DestroyPixmap(pixmap);
|
2018-03-06 10:53:19 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return pixmap;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
PixmapPtr
|
2018-03-06 10:53:19 +01:00
|
|
|
glamor_pixmap_from_fd(ScreenPtr screen,
|
|
|
|
|
int fd,
|
|
|
|
|
CARD16 width,
|
|
|
|
|
CARD16 height,
|
|
|
|
|
CARD16 stride, CARD8 depth, CARD8 bpp)
|
|
|
|
|
{
|
|
|
|
|
PixmapPtr pixmap;
|
|
|
|
|
Bool ret;
|
|
|
|
|
|
|
|
|
|
pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
|
|
|
|
|
|
|
|
|
|
ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height,
|
|
|
|
|
stride, depth, bpp);
|
|
|
|
|
|
|
|
|
|
if (ret == FALSE) {
|
2025-06-11 17:44:28 -07:00
|
|
|
screen->DestroyPixmap(pixmap);
|
2013-12-18 11:59:07 -08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-06-10 13:38:39 +10:00
|
|
|
return pixmap;
|
2013-12-05 08:49:15 +01:00
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
Bool
|
2018-02-28 01:19:44 +00:00
|
|
|
glamor_get_formats(ScreenPtr screen,
|
|
|
|
|
CARD32 *num_formats, CARD32 **formats)
|
|
|
|
|
{
|
|
|
|
|
#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
EGLint num;
|
|
|
|
|
|
2018-04-02 16:41:23 +01:00
|
|
|
/* Explicitly zero the count as the caller may ignore the return value */
|
|
|
|
|
*num_formats = 0;
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
2018-02-28 01:19:44 +00:00
|
|
|
|
|
|
|
|
if (!glamor_egl->dmabuf_capable)
|
2018-04-30 09:06:09 +02:00
|
|
|
return TRUE;
|
2018-02-28 01:19:44 +00:00
|
|
|
|
2018-04-02 16:41:23 +01:00
|
|
|
if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, 0, NULL, &num))
|
2018-02-28 01:19:44 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2018-04-02 16:41:23 +01:00
|
|
|
if (num == 0)
|
2018-02-28 01:19:44 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
*formats = calloc(num, sizeof(CARD32));
|
2018-04-02 16:41:23 +01:00
|
|
|
if (*formats == NULL)
|
2018-02-28 01:19:44 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num,
|
|
|
|
|
(EGLint *) *formats, &num)) {
|
|
|
|
|
free(*formats);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*num_formats = num;
|
|
|
|
|
return TRUE;
|
|
|
|
|
#else
|
|
|
|
|
*num_formats = 0;
|
|
|
|
|
return TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
Bool
|
2018-05-07 16:46:18 -07:00
|
|
|
glamor_get_modifiers(ScreenPtr screen, uint32_t format,
|
|
|
|
|
uint32_t *num_modifiers, uint64_t **modifiers)
|
2018-02-28 01:19:44 +00:00
|
|
|
{
|
|
|
|
|
#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
EGLint num;
|
|
|
|
|
|
2018-04-02 16:41:19 +01:00
|
|
|
/* Explicitly zero the count as the caller may ignore the return value */
|
|
|
|
|
*num_modifiers = 0;
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
2018-02-28 01:19:44 +00:00
|
|
|
|
|
|
|
|
if (!glamor_egl->dmabuf_capable)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, 0, NULL,
|
2018-04-02 16:41:19 +01:00
|
|
|
NULL, &num))
|
2018-02-28 01:19:44 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2018-04-02 16:41:19 +01:00
|
|
|
if (num == 0)
|
2018-02-28 01:19:44 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
*modifiers = calloc(num, sizeof(uint64_t));
|
2018-04-02 16:41:19 +01:00
|
|
|
if (*modifiers == NULL)
|
2018-02-28 01:19:44 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, num,
|
|
|
|
|
(EGLuint64KHR *) *modifiers, NULL, &num)) {
|
|
|
|
|
free(*modifiers);
|
2025-11-02 12:16:56 -08:00
|
|
|
*modifiers = NULL;
|
2018-02-28 01:19:44 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*num_modifiers = num;
|
|
|
|
|
return TRUE;
|
|
|
|
|
#else
|
|
|
|
|
*num_modifiers = 0;
|
|
|
|
|
return TRUE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
const char *
|
2019-11-21 23:01:28 -08:00
|
|
|
glamor_egl_get_driver_name(ScreenPtr screen)
|
|
|
|
|
{
|
|
|
|
|
#ifdef GLAMOR_HAS_EGL_QUERY_DRIVER
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
|
|
|
|
|
glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
|
|
|
|
|
|
|
|
|
|
if (epoxy_has_egl_extension(glamor_egl->display, "EGL_MESA_query_driver"))
|
|
|
|
|
return eglGetDisplayDriverName(glamor_egl->display);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-10-18 19:26:14 -07:00
|
|
|
static Bool
|
|
|
|
|
glamor_egl_destroy_pixmap(PixmapPtr pixmap)
|
2011-11-02 13:44:50 +08:00
|
|
|
{
|
2015-10-18 19:26:14 -07:00
|
|
|
ScreenPtr screen = pixmap->drawable.pScreen;
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2015-10-18 19:26:14 -07:00
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(scrn);
|
2024-10-02 17:23:10 +02:00
|
|
|
Bool ret = TRUE;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2015-10-18 19:26:14 -07:00
|
|
|
if (pixmap->refcnt == 1) {
|
|
|
|
|
struct glamor_pixmap_private *pixmap_priv =
|
|
|
|
|
glamor_get_pixmap_private(pixmap);
|
2014-12-05 10:58:28 -08:00
|
|
|
|
2015-10-18 19:26:14 -07:00
|
|
|
if (pixmap_priv->image)
|
|
|
|
|
eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image);
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
2015-10-18 19:26:14 -07:00
|
|
|
|
|
|
|
|
screen->DestroyPixmap = glamor_egl->saved_destroy_pixmap;
|
2024-10-02 17:23:10 +02:00
|
|
|
if (screen->DestroyPixmap)
|
|
|
|
|
ret = screen->DestroyPixmap(pixmap);
|
2015-10-18 19:26:14 -07:00
|
|
|
glamor_egl->saved_destroy_pixmap = screen->DestroyPixmap;
|
|
|
|
|
screen->DestroyPixmap = glamor_egl_destroy_pixmap;
|
|
|
|
|
|
|
|
|
|
return ret;
|
2012-01-31 18:16:58 +08:00
|
|
|
}
|
|
|
|
|
|
2024-02-06 16:30:08 +01:00
|
|
|
void
|
2012-02-17 16:56:05 +08:00
|
|
|
glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
|
|
|
|
|
{
|
2018-04-04 16:16:34 +01:00
|
|
|
EGLImageKHR temp_img;
|
|
|
|
|
Bool temp_mod;
|
2013-12-27 18:45:44 -08:00
|
|
|
struct glamor_pixmap_private *front_priv =
|
|
|
|
|
glamor_get_pixmap_private(front);
|
|
|
|
|
struct glamor_pixmap_private *back_priv =
|
|
|
|
|
glamor_get_pixmap_private(back);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
|
|
|
|
glamor_pixmap_exchange_fbos(front, back);
|
2013-12-27 18:45:44 -08:00
|
|
|
|
2018-04-04 16:16:34 +01:00
|
|
|
temp_img = back_priv->image;
|
|
|
|
|
temp_mod = back_priv->used_modifiers;
|
2014-10-29 23:08:57 -07:00
|
|
|
back_priv->image = front_priv->image;
|
2018-04-04 16:16:34 +01:00
|
|
|
back_priv->used_modifiers = front_priv->used_modifiers;
|
|
|
|
|
front_priv->image = temp_img;
|
|
|
|
|
front_priv->used_modifiers = temp_mod;
|
2013-12-27 18:45:44 -08:00
|
|
|
|
2013-12-18 11:59:07 -08:00
|
|
|
glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
|
|
|
|
|
glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);
|
2012-02-17 16:56:05 +08:00
|
|
|
}
|
|
|
|
|
|
2012-01-31 18:16:58 +08:00
|
|
|
static Bool
|
2013-12-17 16:32:17 -08:00
|
|
|
glamor_egl_close_screen(ScreenPtr screen)
|
2011-08-24 16:54:32 +08:00
|
|
|
{
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn;
|
2013-12-18 11:59:07 -08:00
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
2013-12-27 18:45:44 -08:00
|
|
|
struct glamor_pixmap_private *pixmap_priv;
|
2013-12-18 11:59:07 -08:00
|
|
|
PixmapPtr screen_pixmap;
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
scrn = xf86ScreenToScrn(screen);
|
|
|
|
|
glamor_egl = glamor_egl_get_screen_private(scrn);
|
2013-12-18 11:59:07 -08:00
|
|
|
screen_pixmap = screen->GetScreenPixmap(screen);
|
2013-12-27 18:45:44 -08:00
|
|
|
pixmap_priv = glamor_get_pixmap_private(screen_pixmap);
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image);
|
|
|
|
|
pixmap_priv->image = NULL;
|
2013-12-27 18:45:44 -08:00
|
|
|
|
2013-12-18 11:59:07 -08:00
|
|
|
screen->CloseScreen = glamor_egl->saved_close_screen;
|
|
|
|
|
|
2013-12-17 16:32:17 -08:00
|
|
|
return screen->CloseScreen(screen);
|
2011-08-24 16:54:32 +08:00
|
|
|
}
|
|
|
|
|
|
2015-04-15 21:29:58 +10:00
|
|
|
#ifdef DRI3
|
2013-12-31 00:07:42 -08:00
|
|
|
static int
|
2014-04-04 16:28:43 -07:00
|
|
|
glamor_dri3_open_client(ClientPtr client,
|
|
|
|
|
ScreenPtr screen,
|
|
|
|
|
RRProviderPtr provider,
|
|
|
|
|
int *fdp)
|
2013-12-31 00:07:42 -08:00
|
|
|
{
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2013-12-31 00:07:42 -08:00
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(scrn);
|
2013-12-31 00:07:42 -08:00
|
|
|
int fd;
|
|
|
|
|
drm_magic_t magic;
|
|
|
|
|
|
|
|
|
|
fd = open(glamor_egl->device_path, O_RDWR|O_CLOEXEC);
|
|
|
|
|
if (fd < 0)
|
|
|
|
|
return BadAlloc;
|
|
|
|
|
|
|
|
|
|
/* Before FD passing in the X protocol with DRI3 (and increased
|
|
|
|
|
* security of rendering with per-process address spaces on the
|
|
|
|
|
* GPU), the kernel had to come up with a way to have the server
|
|
|
|
|
* decide which clients got to access the GPU, which was done by
|
|
|
|
|
* each client getting a unique (magic) number from the kernel,
|
|
|
|
|
* passing it to the server, and the server then telling the
|
|
|
|
|
* kernel which clients were authenticated for using the device.
|
|
|
|
|
*
|
|
|
|
|
* Now that we have FD passing, the server can just set up the
|
|
|
|
|
* authentication on its own and hand the prepared FD off to the
|
|
|
|
|
* client.
|
|
|
|
|
*/
|
|
|
|
|
if (drmGetMagic(fd, &magic) < 0) {
|
|
|
|
|
if (errno == EACCES) {
|
|
|
|
|
/* Assume that we're on a render node, and the fd is
|
|
|
|
|
* already as authenticated as it should be.
|
|
|
|
|
*/
|
|
|
|
|
*fdp = fd;
|
|
|
|
|
return Success;
|
|
|
|
|
} else {
|
|
|
|
|
close(fd);
|
|
|
|
|
return BadMatch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (drmAuthMagic(glamor_egl->fd, magic) < 0) {
|
|
|
|
|
close(fd);
|
|
|
|
|
return BadMatch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*fdp = fd;
|
|
|
|
|
return Success;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-02 16:41:12 +01:00
|
|
|
static const dri3_screen_info_rec glamor_dri3_info = {
|
2018-02-28 01:19:43 +00:00
|
|
|
.version = 2,
|
2014-04-04 16:28:43 -07:00
|
|
|
.open_client = glamor_dri3_open_client,
|
2018-02-28 01:19:43 +00:00
|
|
|
.pixmap_from_fds = glamor_pixmap_from_fds,
|
2018-04-04 16:16:38 +01:00
|
|
|
.fd_from_pixmap = glamor_egl_fd_from_pixmap,
|
2018-02-28 01:19:43 +00:00
|
|
|
.fds_from_pixmap = glamor_egl_fds_from_pixmap,
|
2018-02-28 01:19:44 +00:00
|
|
|
.get_formats = glamor_get_formats,
|
|
|
|
|
.get_modifiers = glamor_get_modifiers,
|
|
|
|
|
.get_drawable_modifiers = glamor_get_drawable_modifiers,
|
2013-12-31 00:07:42 -08:00
|
|
|
};
|
2015-04-15 21:29:58 +10:00
|
|
|
#endif /* DRI3 */
|
2013-12-31 00:07:42 -08:00
|
|
|
|
2012-01-31 18:16:58 +08:00
|
|
|
void
|
2013-12-18 15:27:52 -08:00
|
|
|
glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
|
2012-01-31 18:16:58 +08:00
|
|
|
{
|
2019-10-14 12:48:24 +02:00
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
2013-12-18 11:59:07 -08:00
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_get_screen_private(scrn);
|
2017-05-16 11:37:16 -07:00
|
|
|
#ifdef DRI3
|
|
|
|
|
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
|
2022-07-21 00:49:13 +03:00
|
|
|
#endif
|
|
|
|
|
#ifdef GLXEXT
|
|
|
|
|
static Bool vendor_initialized = FALSE;
|
2017-05-16 11:37:16 -07:00
|
|
|
#endif
|
2022-07-21 00:46:07 +03:00
|
|
|
const char *gbm_backend_name;
|
2012-01-31 18:16:58 +08:00
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl->saved_close_screen = screen->CloseScreen;
|
|
|
|
|
screen->CloseScreen = glamor_egl_close_screen;
|
|
|
|
|
|
|
|
|
|
glamor_egl->saved_destroy_pixmap = screen->DestroyPixmap;
|
|
|
|
|
screen->DestroyPixmap = glamor_egl_destroy_pixmap;
|
|
|
|
|
|
2013-12-18 15:27:52 -08:00
|
|
|
glamor_ctx->ctx = glamor_egl->context;
|
|
|
|
|
glamor_ctx->display = glamor_egl->display;
|
|
|
|
|
|
2014-03-14 17:31:18 -07:00
|
|
|
glamor_ctx->make_current = glamor_egl_make_current;
|
2013-12-31 00:07:42 -08:00
|
|
|
|
2023-10-10 17:36:50 +03:00
|
|
|
/* Use dynamic logic only if vendor is not forced via xorg.conf */
|
2025-11-07 14:44:55 +02:00
|
|
|
if (!glamor_egl->glvnd_vendor) {
|
2023-10-10 17:36:50 +03:00
|
|
|
gbm_backend_name = gbm_device_get_backend_name(glamor_egl->gbm);
|
|
|
|
|
/* Mesa uses "drm" as backend name, in that case, just do nothing */
|
|
|
|
|
if (gbm_backend_name && strcmp(gbm_backend_name, "drm") != 0)
|
|
|
|
|
glamor_set_glvnd_vendor(screen, gbm_backend_name);
|
2025-11-07 14:44:55 +02:00
|
|
|
} else {
|
|
|
|
|
glamor_set_glvnd_vendor(screen, glamor_egl->glvnd_vendor);
|
2023-10-10 17:36:50 +03:00
|
|
|
}
|
2015-04-15 21:29:58 +10:00
|
|
|
#ifdef DRI3
|
2017-05-16 11:37:16 -07:00
|
|
|
/* Tell the core that we have the interfaces for import/export
|
|
|
|
|
* of pixmaps.
|
|
|
|
|
*/
|
|
|
|
|
glamor_enable_dri3(screen);
|
2013-12-31 00:07:42 -08:00
|
|
|
|
2017-05-16 11:37:16 -07:00
|
|
|
/* If the driver wants to do its own auth dance (e.g. Xwayland
|
|
|
|
|
* on pre-3.15 kernels that don't have render nodes and thus
|
|
|
|
|
* has the wayland compositor as a master), then it needs us
|
|
|
|
|
* to stay out of the way and let it init DRI3 on its own.
|
|
|
|
|
*/
|
|
|
|
|
if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) {
|
|
|
|
|
/* To do DRI3 device FD generation, we need to open a new fd
|
|
|
|
|
* to the same device we were handed in originally.
|
2013-12-31 00:07:42 -08:00
|
|
|
*/
|
2022-02-05 13:34:27 +07:00
|
|
|
glamor_egl->device_path = drmGetRenderDeviceNameFromFd(glamor_egl->fd);
|
|
|
|
|
if (!glamor_egl->device_path)
|
|
|
|
|
glamor_egl->device_path = drmGetDeviceNameFromFd2(glamor_egl->fd);
|
2013-12-31 00:07:42 -08:00
|
|
|
|
2017-05-16 11:37:16 -07:00
|
|
|
if (!dri3_screen_init(screen, &glamor_dri3_info)) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2017-05-16 11:37:16 -07:00
|
|
|
"Failed to initialize DRI3.\n");
|
2013-12-31 00:07:42 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-04-15 21:29:58 +10:00
|
|
|
#endif
|
2022-07-21 00:49:13 +03:00
|
|
|
#ifdef GLXEXT
|
|
|
|
|
if (!vendor_initialized) {
|
|
|
|
|
GlxPushProvider(&glamor_provider);
|
|
|
|
|
xorgGlxCreateVendor();
|
|
|
|
|
vendor_initialized = TRUE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2012-01-31 18:16:58 +08:00
|
|
|
}
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
static void glamor_egl_cleanup(struct glamor_egl_screen_private *glamor_egl)
|
|
|
|
|
{
|
|
|
|
|
if (glamor_egl->display != EGL_NO_DISPLAY) {
|
|
|
|
|
eglMakeCurrent(glamor_egl->display,
|
|
|
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
|
|
|
/*
|
|
|
|
|
* Force the next glamor_make_current call to update the context
|
|
|
|
|
* (on hot unplug another GPU may still be using glamor)
|
|
|
|
|
*/
|
|
|
|
|
lastGLContext = NULL;
|
|
|
|
|
eglTerminate(glamor_egl->display);
|
|
|
|
|
}
|
|
|
|
|
if (glamor_egl->gbm)
|
|
|
|
|
gbm_device_destroy(glamor_egl->gbm);
|
|
|
|
|
free(glamor_egl->device_path);
|
2025-11-07 14:44:55 +02:00
|
|
|
free(glamor_egl->glvnd_vendor);
|
2019-10-14 12:48:24 +02:00
|
|
|
free(glamor_egl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
glamor_egl_free_screen(ScrnInfoPtr scrn)
|
|
|
|
|
{
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
|
|
|
|
|
|
|
|
|
glamor_egl = glamor_egl_get_screen_private(scrn);
|
|
|
|
|
if (glamor_egl != NULL) {
|
|
|
|
|
scrn->FreeScreen = glamor_egl->saved_free_screen;
|
|
|
|
|
glamor_egl_cleanup(glamor_egl);
|
|
|
|
|
scrn->FreeScreen(scrn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-31 19:52:07 +03:00
|
|
|
static Bool
|
|
|
|
|
glamor_egl_try_big_gl_api(ScrnInfoPtr scrn)
|
|
|
|
|
{
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
|
|
|
|
glamor_egl_get_screen_private(scrn);
|
|
|
|
|
|
|
|
|
|
if (eglBindAPI(EGL_OPENGL_API)) {
|
|
|
|
|
static const EGLint config_attribs_core[] = {
|
|
|
|
|
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
|
|
|
|
|
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
|
|
|
|
|
EGL_CONTEXT_MAJOR_VERSION_KHR,
|
|
|
|
|
GLAMOR_GL_CORE_VER_MAJOR,
|
|
|
|
|
EGL_CONTEXT_MINOR_VERSION_KHR,
|
|
|
|
|
GLAMOR_GL_CORE_VER_MINOR,
|
|
|
|
|
EGL_NONE
|
|
|
|
|
};
|
|
|
|
|
static const EGLint config_attribs[] = {
|
|
|
|
|
EGL_NONE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
glamor_egl->context = eglCreateContext(glamor_egl->display,
|
|
|
|
|
EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
|
|
|
|
|
config_attribs_core);
|
|
|
|
|
|
|
|
|
|
if (glamor_egl->context == EGL_NO_CONTEXT)
|
|
|
|
|
glamor_egl->context = eglCreateContext(glamor_egl->display,
|
|
|
|
|
EGL_NO_CONFIG_KHR,
|
|
|
|
|
EGL_NO_CONTEXT,
|
|
|
|
|
config_attribs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (glamor_egl->context != EGL_NO_CONTEXT) {
|
|
|
|
|
if (!eglMakeCurrent(glamor_egl->display,
|
|
|
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) {
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
|
|
|
"Failed to make GL context current\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (epoxy_gl_version() < 21) {
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
|
"glamor: Ignoring GL < 2.1, falling back to GLES.\n");
|
|
|
|
|
eglDestroyContext(glamor_egl->display, glamor_egl->context);
|
|
|
|
|
glamor_egl->context = EGL_NO_CONTEXT;
|
|
|
|
|
}
|
2023-09-21 17:07:43 +03:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
|
"glamor: Using OpenGL %d.%d context.\n",
|
|
|
|
|
epoxy_gl_version() / 10,
|
|
|
|
|
epoxy_gl_version() % 10);
|
2023-10-31 19:52:07 +03:00
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
|
glamor_egl_try_gles_api(ScrnInfoPtr scrn)
|
|
|
|
|
{
|
|
|
|
|
struct glamor_egl_screen_private *glamor_egl =
|
|
|
|
|
glamor_egl_get_screen_private(scrn);
|
2025-10-05 11:56:48 -07:00
|
|
|
|
2023-10-31 19:52:07 +03:00
|
|
|
static const EGLint config_attribs[] = {
|
|
|
|
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
|
|
|
EGL_NONE
|
|
|
|
|
};
|
|
|
|
|
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
|
|
|
"glamor: Failed to bind GLES API.\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glamor_egl->context = eglCreateContext(glamor_egl->display,
|
|
|
|
|
EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
|
|
|
|
|
config_attribs);
|
|
|
|
|
|
|
|
|
|
if (glamor_egl->context != EGL_NO_CONTEXT) {
|
|
|
|
|
if (!eglMakeCurrent(glamor_egl->display,
|
|
|
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) {
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
|
|
|
"Failed to make GLES context current\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2023-09-21 17:07:43 +03:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
|
"glamor: Using OpenGL ES %d.%d context.\n",
|
|
|
|
|
epoxy_gl_version() / 10,
|
|
|
|
|
epoxy_gl_version() % 10);
|
2023-10-31 19:52:07 +03:00
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-21 18:06:14 +03:00
|
|
|
enum {
|
|
|
|
|
GLAMOREGLOPT_RENDERING_API,
|
2023-10-10 17:36:50 +03:00
|
|
|
GLAMOREGLOPT_VENDOR_LIBRARY
|
2023-09-21 18:06:14 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const OptionInfoRec GlamorEGLOptions[] = {
|
|
|
|
|
{ GLAMOREGLOPT_RENDERING_API, "RenderingAPI", OPTV_STRING, {0}, FALSE },
|
2023-10-10 17:36:50 +03:00
|
|
|
{ GLAMOREGLOPT_VENDOR_LIBRARY, "GlxVendorLibrary", OPTV_STRING, {0}, FALSE },
|
2023-09-21 18:06:14 +03:00
|
|
|
{ -1, NULL, OPTV_NONE, {0}, FALSE },
|
|
|
|
|
};
|
|
|
|
|
|
2011-11-02 13:44:50 +08:00
|
|
|
Bool
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
2011-08-24 16:54:32 +08:00
|
|
|
{
|
2013-12-18 11:59:07 -08:00
|
|
|
struct glamor_egl_screen_private *glamor_egl;
|
2018-09-14 11:33:43 -04:00
|
|
|
const GLubyte *renderer;
|
2023-09-21 18:06:14 +03:00
|
|
|
OptionInfoPtr options;
|
|
|
|
|
const char *api = NULL;
|
|
|
|
|
Bool es_allowed = TRUE;
|
|
|
|
|
Bool force_es = FALSE;
|
2023-10-10 17:36:50 +03:00
|
|
|
const char *glvnd_vendor = NULL;
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2024-07-14 11:24:00 -07:00
|
|
|
glamor_egl = calloc(1, sizeof(*glamor_egl));
|
2013-12-18 11:59:07 -08:00
|
|
|
if (glamor_egl == NULL)
|
|
|
|
|
return FALSE;
|
2019-10-14 12:48:24 +02:00
|
|
|
if (xf86GlamorEGLPrivateIndex == -1)
|
|
|
|
|
xf86GlamorEGLPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
|
2013-12-18 11:59:07 -08:00
|
|
|
|
2024-05-08 10:29:32 +02:00
|
|
|
options = XNFalloc(sizeof(GlamorEGLOptions));
|
2023-09-21 18:06:14 +03:00
|
|
|
memcpy(options, GlamorEGLOptions, sizeof(GlamorEGLOptions));
|
|
|
|
|
xf86ProcessOptions(scrn->scrnIndex, scrn->options, options);
|
2023-10-10 17:36:50 +03:00
|
|
|
glvnd_vendor = xf86GetOptValString(options, GLAMOREGLOPT_VENDOR_LIBRARY);
|
2025-11-07 14:44:55 +02:00
|
|
|
if (glvnd_vendor)
|
|
|
|
|
glamor_egl->glvnd_vendor = XNFstrdup(glvnd_vendor);
|
|
|
|
|
|
2023-09-21 18:06:14 +03:00
|
|
|
api = xf86GetOptValString(options, GLAMOREGLOPT_RENDERING_API);
|
|
|
|
|
if (api && !strncasecmp(api, "es", 2))
|
|
|
|
|
force_es = TRUE;
|
|
|
|
|
else if (api && !strncasecmp(api, "gl", 2))
|
|
|
|
|
es_allowed = FALSE;
|
|
|
|
|
free(options);
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl;
|
2013-12-18 11:59:07 -08:00
|
|
|
glamor_egl->fd = fd;
|
|
|
|
|
glamor_egl->gbm = gbm_create_device(glamor_egl->fd);
|
|
|
|
|
if (glamor_egl->gbm == NULL) {
|
|
|
|
|
ErrorF("couldn't get display device\n");
|
2015-07-03 20:42:48 +02:00
|
|
|
goto error;
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
2016-10-05 12:34:34 -04:00
|
|
|
|
|
|
|
|
glamor_egl->display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA,
|
|
|
|
|
glamor_egl->gbm);
|
2016-12-20 13:00:43 +01:00
|
|
|
if (!glamor_egl->display) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetDisplay() failed\n");
|
2016-12-20 13:00:43 +01:00
|
|
|
goto error;
|
|
|
|
|
}
|
2011-12-16 15:02:54 +08:00
|
|
|
|
2017-05-09 15:33:21 -07:00
|
|
|
if (!eglInitialize(glamor_egl->display, NULL, NULL)) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n");
|
2015-07-03 20:42:48 +02:00
|
|
|
glamor_egl->display = EGL_NO_DISPLAY;
|
|
|
|
|
goto error;
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
2011-08-24 16:54:32 +08:00
|
|
|
|
|
|
|
|
#define GLAMOR_CHECK_EGL_EXTENSION(EXT) \
|
2013-12-27 18:27:56 -08:00
|
|
|
if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT)) { \
|
2012-08-07 18:13:32 +02:00
|
|
|
ErrorF("EGL_" #EXT " required.\n"); \
|
2015-07-03 20:42:48 +02:00
|
|
|
goto error; \
|
2011-12-13 22:48:34 +08:00
|
|
|
}
|
2011-08-24 16:54:32 +08:00
|
|
|
|
2012-08-07 18:16:58 +02:00
|
|
|
#define GLAMOR_CHECK_EGL_EXTENSIONS(EXT1, EXT2) \
|
2013-12-27 18:27:56 -08:00
|
|
|
if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT1) && \
|
|
|
|
|
!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT2)) { \
|
2012-08-07 18:16:58 +02:00
|
|
|
ErrorF("EGL_" #EXT1 " or EGL_" #EXT2 " required.\n"); \
|
2015-07-03 20:42:48 +02:00
|
|
|
goto error; \
|
2012-08-07 18:16:58 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-17 17:06:43 -07:00
|
|
|
GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_context);
|
2021-08-17 12:41:08 -04:00
|
|
|
GLAMOR_CHECK_EGL_EXTENSION(KHR_no_config_context);
|
2011-08-24 16:54:32 +08:00
|
|
|
|
2023-09-21 18:06:14 +03:00
|
|
|
if (!force_es) {
|
|
|
|
|
if(!glamor_egl_try_big_gl_api(scrn))
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2017-05-17 17:06:44 -07:00
|
|
|
|
2023-09-21 18:06:14 +03:00
|
|
|
if (glamor_egl->context == EGL_NO_CONTEXT && es_allowed) {
|
2023-10-31 19:52:07 +03:00
|
|
|
if(!glamor_egl_try_gles_api(scrn))
|
2019-12-25 18:54:03 +01:00
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-17 17:06:44 -07:00
|
|
|
if (glamor_egl->context == EGL_NO_CONTEXT) {
|
2023-10-31 19:52:07 +03:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
|
|
|
|
"glamor: Failed to create GL or GLES2 contexts\n");
|
|
|
|
|
goto error;
|
2013-12-18 11:59:07 -08:00
|
|
|
}
|
2018-09-14 11:33:43 -04:00
|
|
|
|
|
|
|
|
renderer = glGetString(GL_RENDERER);
|
2018-10-05 14:50:20 -04:00
|
|
|
if (!renderer) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2018-10-05 14:50:20 -04:00
|
|
|
"glGetString() returned NULL, your GL is broken\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2022-12-21 18:29:21 +04:00
|
|
|
if (strstr((const char *)renderer, "softpipe")) {
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
|
"Refusing to try glamor on softpipe\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2022-08-01 16:03:38 +02:00
|
|
|
if (!strncmp("llvmpipe", (const char *)renderer, strlen("llvmpipe"))) {
|
2021-07-08 06:14:21 +02:00
|
|
|
if (scrn->confScreen->num_gpu_devices)
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
|
"Allowing glamor on llvmpipe for PRIME\n");
|
|
|
|
|
else {
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
|
"Refusing to try glamor on llvmpipe\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2018-09-14 11:33:43 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-08 09:30:31 +02:00
|
|
|
/*
|
|
|
|
|
* Force the next glamor_make_current call to set the right context
|
|
|
|
|
* (in case of multiple GPUs using glamor)
|
|
|
|
|
*/
|
|
|
|
|
lastGLContext = NULL;
|
2017-05-16 11:37:16 -07:00
|
|
|
|
|
|
|
|
if (!epoxy_has_gl_extension("GL_OES_EGL_image")) {
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
2017-05-16 11:37:16 -07:00
|
|
|
"glamor acceleration requires GL_OES_EGL_image\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2015-09-25 14:04:34 +01:00
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor X acceleration enabled on %s\n",
|
|
|
|
|
renderer);
|
2017-05-16 11:37:12 -07:00
|
|
|
|
2018-02-28 01:19:43 +00:00
|
|
|
#ifdef GBM_BO_WITH_MODIFIERS
|
|
|
|
|
if (epoxy_has_egl_extension(glamor_egl->display,
|
|
|
|
|
"EGL_EXT_image_dma_buf_import") &&
|
|
|
|
|
epoxy_has_egl_extension(glamor_egl->display,
|
2018-03-30 22:31:46 +02:00
|
|
|
"EGL_EXT_image_dma_buf_import_modifiers")) {
|
Revert "glamor: Enable modifier support for xfree86 too"
This reverts commit 9b8999411033c9473cd68e92e4690a91aecf5b95.
Turns out that defaulting glamor_egl->dmabuf_capable = TRUE
breaks kms page-flipping on various Mesa+Linux/DRM-KMS+hardware
combos, resulting in broken presentation timing, degraded performance
and awful tearing. E.g., my testing shows that X-Server master +
Mesa 21.2 + Linux 5.3 on Intel Kabylake has broken pageflipping.
Similar behaviour was observed in the past on RaspberryPi 4/400
with VideoCore-6 by myself and others, and iirc by myself on some
AMD gpu's, although my memories of the latter are a bit dim.
Cfe. https://gitlab.freedesktop.org/mesa/mesa/-/issues/3601 and
possibly https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/254
for related problems.
The reason for pageflip failure on the modesetting-ddx under
DRI3/Present seems to be the following sequence:
1. Atomic modesetting for the modesetting-ddx is broken and therefore
both disabled by default in the modesetting-ddx itself and also
force-disabled by the Linux kernel since quite a while. If the kernel
detects drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1); from the
X-Server, it will reject the request, as a countermeasure to all the
past and current brokeness.
2. Without DRM_CLIENT_CAP_ATOMIC we don't get the implied universal
planes support (DRM_CLIENT_CAP_UNIVERSAL_PLANES).
3. Without DRM_CLIENT_CAP_UNIVERSAL_PLANES, drmModeGetPlaneResources()
will only return overlay planes, but not primary- or cursor planes.
4. As modesetting-ddx drmmode_crtc_create_planes() function can only
operate on primary planes, but can't get any from drmModeGetPlaneResources(),
the drmmode_crtc_create_planes() mostly turns into a no-op, never
executes populate_format_modifiers() and therefore the Linux kernels
DRM-KMS driver is not ever queried for the list of scanout/pageflip
capable DRM format modifiers. Iow. the drmmode_crtc->formats[i].modifiers
list stays empty with zero drmmode_crtc->formats[i].num_modifiers.
5. The list from step 4 provides the format+modifiers for intersection
which would get returned by the X-Servers DRI3 backend as response to
a xcb_dri3_get_supported_modifiers_window_modifiers() request. Given
an empty list was returned in step 4, this will lead to return of an
empty modifiers list by xcb_dri3_get_supported_modifiers_window_modifiers().
6. Both Mesa's DRI3/Present OpenGL backbuffer allocation logic and iirc
Mesa/Vulkan/WSI/X11's swapchain image allocation logic use the list
from xcb_dri3_get_supported_modifiers_window_modifiers() for format+
modifier selection for scanout/pageflip capable buffers. Cfe. Mesa's
dri3_alloc_render_buffer() function.
Due to the empty list, the Mesa code falls back to the format+modifiers
reported by xcb_dri3_get_supported_modifiers_screen_modifiers()
instead. This list contains all modifiers reported by GLAMOR as
result of glamor_get_formats() and glamor_get_modifiers(), which
in turn are query results from Mesa eglQueryDmaBufFormatsEXT()
and eglQueryDmaBufModifiersEXT(). Iow. all format+modifiers which
are supported for rendering are considered for the OpenGL backbuffers
and Vulkan swapchain buffers.
7. Depending on kms driver + gpu combo and Mesa version, such buffers
are often not direct-scanout / pageflip capable, and so pageflipping
can't be used for DRI3/Present of fullscreen windows. Whenever the
system has to fallback to copies instead of pageflips, the results
are broken presentation timing, degraded performance and quite
horrible tearing, as the current DRI3/Present implementation does not
perform any hardware synchronization of copy presents to the start
of vblank or similar.
By defaulting glamor_egl->dmabuf_capable = FALSE instead, as the server
1.20 branch does, we avoid this failure:
1. glamor_get_modifiers() turns into a no-op and returns false, not
reporting any supported dmabuf modifiers to the servers DRI3 code,
ie. the servers cache_formats_and_modifiers() function can't retrieve
and cache any format+modifiers. Therefore the servers DRI3 code now
also reports an empty format+modifiers list when Mesa does a
xcb_dri3_get_supported_modifiers_screen_modifiers() query.
2. Mesa's buffer allocation code therefore falls back to using the old
DRI image extensions createImage() function to allocate buffers
with use flags __DRI_IMAGE_USE_SCANOUT | __DRI_IMAGE_USE_BACKBUFFER
and our OpenGL backbuffers / Vulkan swapchain images get allocated
in a direct-scanout / pageflip capable format. Pageflipping works,
timing and performance is good, presentation is tear-free.
Please consider merging this for branching the X-Server 1.21 branch.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
2021-08-26 17:06:49 +02:00
|
|
|
if (xf86Info.debug != NULL)
|
|
|
|
|
glamor_egl->dmabuf_capable = !!strstr(xf86Info.debug,
|
|
|
|
|
"dmabuf_capable");
|
2023-12-16 08:38:11 +02:00
|
|
|
else if (strstr((const char *)renderer, "Intel"))
|
|
|
|
|
glamor_egl->dmabuf_capable = TRUE;
|
2025-03-06 18:44:59 -06:00
|
|
|
else if (strstr((const char *)renderer, "zink"))
|
|
|
|
|
glamor_egl->dmabuf_capable = TRUE;
|
Revert "glamor: Enable modifier support for xfree86 too"
This reverts commit 9b8999411033c9473cd68e92e4690a91aecf5b95.
Turns out that defaulting glamor_egl->dmabuf_capable = TRUE
breaks kms page-flipping on various Mesa+Linux/DRM-KMS+hardware
combos, resulting in broken presentation timing, degraded performance
and awful tearing. E.g., my testing shows that X-Server master +
Mesa 21.2 + Linux 5.3 on Intel Kabylake has broken pageflipping.
Similar behaviour was observed in the past on RaspberryPi 4/400
with VideoCore-6 by myself and others, and iirc by myself on some
AMD gpu's, although my memories of the latter are a bit dim.
Cfe. https://gitlab.freedesktop.org/mesa/mesa/-/issues/3601 and
possibly https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/254
for related problems.
The reason for pageflip failure on the modesetting-ddx under
DRI3/Present seems to be the following sequence:
1. Atomic modesetting for the modesetting-ddx is broken and therefore
both disabled by default in the modesetting-ddx itself and also
force-disabled by the Linux kernel since quite a while. If the kernel
detects drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1); from the
X-Server, it will reject the request, as a countermeasure to all the
past and current brokeness.
2. Without DRM_CLIENT_CAP_ATOMIC we don't get the implied universal
planes support (DRM_CLIENT_CAP_UNIVERSAL_PLANES).
3. Without DRM_CLIENT_CAP_UNIVERSAL_PLANES, drmModeGetPlaneResources()
will only return overlay planes, but not primary- or cursor planes.
4. As modesetting-ddx drmmode_crtc_create_planes() function can only
operate on primary planes, but can't get any from drmModeGetPlaneResources(),
the drmmode_crtc_create_planes() mostly turns into a no-op, never
executes populate_format_modifiers() and therefore the Linux kernels
DRM-KMS driver is not ever queried for the list of scanout/pageflip
capable DRM format modifiers. Iow. the drmmode_crtc->formats[i].modifiers
list stays empty with zero drmmode_crtc->formats[i].num_modifiers.
5. The list from step 4 provides the format+modifiers for intersection
which would get returned by the X-Servers DRI3 backend as response to
a xcb_dri3_get_supported_modifiers_window_modifiers() request. Given
an empty list was returned in step 4, this will lead to return of an
empty modifiers list by xcb_dri3_get_supported_modifiers_window_modifiers().
6. Both Mesa's DRI3/Present OpenGL backbuffer allocation logic and iirc
Mesa/Vulkan/WSI/X11's swapchain image allocation logic use the list
from xcb_dri3_get_supported_modifiers_window_modifiers() for format+
modifier selection for scanout/pageflip capable buffers. Cfe. Mesa's
dri3_alloc_render_buffer() function.
Due to the empty list, the Mesa code falls back to the format+modifiers
reported by xcb_dri3_get_supported_modifiers_screen_modifiers()
instead. This list contains all modifiers reported by GLAMOR as
result of glamor_get_formats() and glamor_get_modifiers(), which
in turn are query results from Mesa eglQueryDmaBufFormatsEXT()
and eglQueryDmaBufModifiersEXT(). Iow. all format+modifiers which
are supported for rendering are considered for the OpenGL backbuffers
and Vulkan swapchain buffers.
7. Depending on kms driver + gpu combo and Mesa version, such buffers
are often not direct-scanout / pageflip capable, and so pageflipping
can't be used for DRI3/Present of fullscreen windows. Whenever the
system has to fallback to copies instead of pageflips, the results
are broken presentation timing, degraded performance and quite
horrible tearing, as the current DRI3/Present implementation does not
perform any hardware synchronization of copy presents to the start
of vblank or similar.
By defaulting glamor_egl->dmabuf_capable = FALSE instead, as the server
1.20 branch does, we avoid this failure:
1. glamor_get_modifiers() turns into a no-op and returns false, not
reporting any supported dmabuf modifiers to the servers DRI3 code,
ie. the servers cache_formats_and_modifiers() function can't retrieve
and cache any format+modifiers. Therefore the servers DRI3 code now
also reports an empty format+modifiers list when Mesa does a
xcb_dri3_get_supported_modifiers_screen_modifiers() query.
2. Mesa's buffer allocation code therefore falls back to using the old
DRI image extensions createImage() function to allocate buffers
with use flags __DRI_IMAGE_USE_SCANOUT | __DRI_IMAGE_USE_BACKBUFFER
and our OpenGL backbuffers / Vulkan swapchain images get allocated
in a direct-scanout / pageflip capable format. Pageflipping works,
timing and performance is good, presentation is tear-free.
Please consider merging this for branching the X-Server 1.21 branch.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
2021-08-26 17:06:49 +02:00
|
|
|
else
|
|
|
|
|
glamor_egl->dmabuf_capable = FALSE;
|
2018-03-30 22:31:46 +02:00
|
|
|
}
|
2018-02-28 01:19:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl->saved_free_screen = scrn->FreeScreen;
|
|
|
|
|
scrn->FreeScreen = glamor_egl_free_screen;
|
2013-12-18 11:59:07 -08:00
|
|
|
return TRUE;
|
2015-07-03 20:42:48 +02:00
|
|
|
|
|
|
|
|
error:
|
2019-10-14 12:48:24 +02:00
|
|
|
glamor_egl_cleanup(glamor_egl);
|
2015-07-03 20:42:48 +02:00
|
|
|
return FALSE;
|
2011-11-02 13:44:50 +08:00
|
|
|
}
|
2011-09-08 15:16:01 +08:00
|
|
|
|
2013-12-30 18:33:09 -08:00
|
|
|
/** Stub to retain compatibility with pre-server-1.16 ABI. */
|
2011-11-02 13:44:50 +08:00
|
|
|
Bool
|
|
|
|
|
glamor_egl_init_textured_pixmap(ScreenPtr screen)
|
|
|
|
|
{
|
2013-12-18 11:59:07 -08:00
|
|
|
return TRUE;
|
2011-08-24 16:54:32 +08:00
|
|
|
}
|