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_PICTURE_SCREEN 	(1 << 2) | ||||
| #define GLAMOR_USE_EGL_SCREEN		(1 << 3) | ||||
| #define GLAMOR_NO_DRI3			(1 << 4) | ||||
| #define GLAMOR_VALID_FLAGS      (GLAMOR_INVERTED_Y_AXIS  		\ | ||||
| 				 | GLAMOR_USE_SCREEN 			\ | ||||
|                                  | GLAMOR_USE_PICTURE_SCREEN		\ | ||||
| 				 | GLAMOR_USE_EGL_SCREEN) | ||||
| 				 | GLAMOR_USE_EGL_SCREEN                \ | ||||
|                                  | GLAMOR_NO_DRI3) | ||||
| 
 | ||||
| /* @glamor_init: Initialize glamor internal data structure.
 | ||||
|  * | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ | |||
| 
 | ||||
| #include "glamor.h" | ||||
| #include "glamor_priv.h" | ||||
| #include "dri3.h" | ||||
| 
 | ||||
| static const char glamor_name[] = "glamor"; | ||||
| 
 | ||||
|  | @ -68,6 +69,7 @@ struct glamor_egl_screen_private { | |||
|     EGLDisplay display; | ||||
|     EGLContext context; | ||||
|     EGLint major, minor; | ||||
|     char *device_path; | ||||
| 
 | ||||
|     CreateScreenResourcesProcPtr CreateScreenResources; | ||||
|     CloseScreenProcPtr CloseScreen; | ||||
|  | @ -627,10 +629,67 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, | |||
|     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 | ||||
| glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) | ||||
| { | ||||
|     ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | ||||
|     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); | ||||
|     struct glamor_egl_screen_private *glamor_egl = | ||||
|         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->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 | ||||
|  | @ -658,6 +741,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn) | |||
|         if (glamor_egl->gbm) | ||||
|             gbm_device_destroy(glamor_egl->gbm); | ||||
| #endif | ||||
|         free(glamor_egl->device_path); | ||||
| 
 | ||||
|         scrn->FreeScreen = glamor_egl->saved_free_screen; | ||||
|         free(glamor_egl); | ||||
|         scrn->FreeScreen(scrn); | ||||
|  |  | |||
|  | @ -36,5 +36,8 @@ libglamoregl_la_LIBADD = \ | |||
| 	$(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) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue