glamor: Add support for DRI3.
The render-nodes case is untested.
v2: Add a flag for wayland to suppress the native DRI3 support.
    Wayland isn't running as a master itself, so it can't do the auth
    on its own and has to ask the compositor to do it for us.  Dropped
    XXX about randr provider -- the conclusion from discussion with
    keithp was that if the driver's dri3_open for a provider on a
    different screen, that's a core dri3 bug.
v3: Don't put quite so much under GLAMOR_NO_DRI3, and add a comment
    explaining what this is about.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									fb4a1e6ef6
								
							
						
					
					
						commit
						da08316605
					
				|  | @ -67,10 +67,12 @@ typedef enum glamor_pixmap_type { | ||||||
| #define GLAMOR_USE_SCREEN		(1 << 1) | #define GLAMOR_USE_SCREEN		(1 << 1) | ||||||
| #define GLAMOR_USE_PICTURE_SCREEN 	(1 << 2) | #define GLAMOR_USE_PICTURE_SCREEN 	(1 << 2) | ||||||
| #define GLAMOR_USE_EGL_SCREEN		(1 << 3) | #define GLAMOR_USE_EGL_SCREEN		(1 << 3) | ||||||
|  | #define GLAMOR_NO_DRI3			(1 << 4) | ||||||
| #define GLAMOR_VALID_FLAGS      (GLAMOR_INVERTED_Y_AXIS  		\ | #define GLAMOR_VALID_FLAGS      (GLAMOR_INVERTED_Y_AXIS  		\ | ||||||
| 				 | GLAMOR_USE_SCREEN 			\ | 				 | GLAMOR_USE_SCREEN 			\ | ||||||
|                                  | GLAMOR_USE_PICTURE_SCREEN		\ |                                  | GLAMOR_USE_PICTURE_SCREEN		\ | ||||||
| 				 | GLAMOR_USE_EGL_SCREEN) | 				 | GLAMOR_USE_EGL_SCREEN                \ | ||||||
|  |                                  | GLAMOR_NO_DRI3) | ||||||
| 
 | 
 | ||||||
| /* @glamor_init: Initialize glamor internal data structure.
 | /* @glamor_init: Initialize glamor internal data structure.
 | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -50,6 +50,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "glamor.h" | #include "glamor.h" | ||||||
| #include "glamor_priv.h" | #include "glamor_priv.h" | ||||||
|  | #include "dri3.h" | ||||||
| 
 | 
 | ||||||
| static const char glamor_name[] = "glamor"; | static const char glamor_name[] = "glamor"; | ||||||
| 
 | 
 | ||||||
|  | @ -68,6 +69,7 @@ struct glamor_egl_screen_private { | ||||||
|     EGLDisplay display; |     EGLDisplay display; | ||||||
|     EGLContext context; |     EGLContext context; | ||||||
|     EGLint major, minor; |     EGLint major, minor; | ||||||
|  |     char *device_path; | ||||||
| 
 | 
 | ||||||
|     CreateScreenResourcesProcPtr CreateScreenResources; |     CreateScreenResourcesProcPtr CreateScreenResources; | ||||||
|     CloseScreenProcPtr CloseScreen; |     CloseScreenProcPtr CloseScreen; | ||||||
|  | @ -627,10 +629,67 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, | ||||||
|     return FALSE; |     return FALSE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int | ||||||
|  | glamor_dri3_open(ScreenPtr screen, | ||||||
|  |                  RRProviderPtr provider, | ||||||
|  |                  int *fdp) | ||||||
|  | { | ||||||
|  |     ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | ||||||
|  |     struct glamor_egl_screen_private *glamor_egl = | ||||||
|  |         glamor_egl_get_screen_private(scrn); | ||||||
|  |     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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static dri3_screen_info_rec glamor_dri3_info = { | ||||||
|  |     .version = 0, | ||||||
|  |     .open = glamor_dri3_open, | ||||||
|  |     .pixmap_from_fd = glamor_pixmap_from_fd, | ||||||
|  |     .fd_from_pixmap = glamor_fd_from_pixmap, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| void | void | ||||||
| glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) | glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) | ||||||
| { | { | ||||||
|     ScrnInfoPtr scrn = xf86ScreenToScrn(screen); |     ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | ||||||
|  |     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); | ||||||
|     struct glamor_egl_screen_private *glamor_egl = |     struct glamor_egl_screen_private *glamor_egl = | ||||||
|         glamor_egl_get_screen_private(scrn); |         glamor_egl_get_screen_private(scrn); | ||||||
| 
 | 
 | ||||||
|  | @ -642,6 +701,30 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) | ||||||
| 
 | 
 | ||||||
|     glamor_ctx->get_context = glamor_egl_get_context; |     glamor_ctx->get_context = glamor_egl_get_context; | ||||||
|     glamor_ctx->put_context = glamor_egl_put_context; |     glamor_ctx->put_context = glamor_egl_put_context; | ||||||
|  | 
 | ||||||
|  |     if (glamor_egl->dri3_capable) { | ||||||
|  |         /* Tell the core that we have the interfaces for import/export
 | ||||||
|  |          * of pixmaps. | ||||||
|  |          */ | ||||||
|  |         glamor_enable_dri3(screen); | ||||||
|  | 
 | ||||||
|  |         /* 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. | ||||||
|  |              */ | ||||||
|  |             glamor_egl->device_path = drmGetDeviceNameFromFd(glamor_egl->fd); | ||||||
|  | 
 | ||||||
|  |             if (!dri3_screen_init(screen, &glamor_dri3_info)) { | ||||||
|  |                 xf86DrvMsg(scrn->scrnIndex, X_ERROR, | ||||||
|  |                            "Failed to initialize DRI3.\n"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -658,6 +741,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn) | ||||||
|         if (glamor_egl->gbm) |         if (glamor_egl->gbm) | ||||||
|             gbm_device_destroy(glamor_egl->gbm); |             gbm_device_destroy(glamor_egl->gbm); | ||||||
| #endif | #endif | ||||||
|  |         free(glamor_egl->device_path); | ||||||
|  | 
 | ||||||
|         scrn->FreeScreen = glamor_egl->saved_free_screen; |         scrn->FreeScreen = glamor_egl->saved_free_screen; | ||||||
|         free(glamor_egl); |         free(glamor_egl); | ||||||
|         scrn->FreeScreen(scrn); |         scrn->FreeScreen(scrn); | ||||||
|  |  | ||||||
|  | @ -36,5 +36,8 @@ libglamoregl_la_LIBADD = \ | ||||||
| 	$(top_builddir)/glamor/libglamor.la \
 | 	$(top_builddir)/glamor/libglamor.la \
 | ||||||
| 	$() | 	$() | ||||||
| 
 | 
 | ||||||
| AM_CPPFLAGS = $(XORG_INCS) | AM_CPPFLAGS = $(XORG_INCS) \
 | ||||||
|  | 	-I$(top_srcdir)/dri3 \
 | ||||||
|  | 	$() | ||||||
|  | 
 | ||||||
| AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS) | AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue