dri2: Take an XID for tracking the DRI2 drawable
Some pixmaps (window pixmaps and scratch pixmaps) don't have the drawable->id set and thus DRI2 gets confused when using that field for looking up the DRI2 drawable. Go back to using privates for getting at the DRI2 drawable from a DrawablePtr. We need to keep the resource tracking in place so we can remove the DRI2 drawable when the X resource it was created for goes away. Additionally, we also now track the DRI2 drawable using a client XID so we can reclaim the DRI2 drawable even if the client goes before the drawable and doesn't destroy the DRI2 drawable. Tested-by: Owen W. Taylor <otaylor@fishsoup.net> Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
This commit is contained in:
		
							parent
							
								
									32381363cd
								
							
						
					
					
						commit
						9de0e31746
					
				|  | @ -512,8 +512,9 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, | |||
|     if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error)) | ||||
| 	return NULL; | ||||
| 
 | ||||
|     pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, | ||||
| 						pDraw, GLX_DRAWABLE_WINDOW, | ||||
|     pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen, | ||||
| 						pDraw, drawId, | ||||
| 						GLX_DRAWABLE_WINDOW, | ||||
| 						drawId, glxc->config); | ||||
| 
 | ||||
|     /* since we are creating the drawablePrivate, drawId should be new */ | ||||
|  | @ -1104,15 +1105,17 @@ __glXDrawableRelease(__GLXdrawable *drawable) | |||
| } | ||||
| 
 | ||||
| static int  | ||||
| DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config, | ||||
| 		    DrawablePtr pDraw, XID glxDrawableId, int type) | ||||
| DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, | ||||
| 		    __GLXconfig *config, DrawablePtr pDraw, XID drawableId, | ||||
| 		    XID glxDrawableId, int type) | ||||
| { | ||||
|     __GLXdrawable *pGlxDraw; | ||||
| 
 | ||||
|     if (pGlxScreen->pScreen != pDraw->pScreen) | ||||
| 	return BadMatch; | ||||
| 
 | ||||
|     pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type, | ||||
|     pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw, | ||||
| 					  drawableId, type, | ||||
| 					  glxDrawableId, config); | ||||
|     if (pGlxDraw == NULL) | ||||
| 	return BadAlloc; | ||||
|  | @ -1125,7 +1128,7 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf | |||
|     /* Add the glx drawable under the XID of the underlying X drawable
 | ||||
|      * too.  That way we'll get a callback in DrawableGone and can | ||||
|      * clean up properly when the drawable is destroyed. */ | ||||
|     if (pDraw->id != glxDrawableId && | ||||
|     if (drawableId != glxDrawableId && | ||||
| 	!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) { | ||||
| 	pGlxDraw->destroy (pGlxDraw); | ||||
| 	return BadAlloc; | ||||
|  | @ -1153,7 +1156,7 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config | |||
| 	return BadPixmap; | ||||
|     } | ||||
| 
 | ||||
|     err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, | ||||
|     err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId, | ||||
| 			      glxDrawableId, GLX_DRAWABLE_PIXMAP); | ||||
| 
 | ||||
|     return err; | ||||
|  | @ -1316,7 +1319,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, | |||
| 	return BadAlloc; | ||||
| 
 | ||||
|     return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, | ||||
| 			       glxDrawableId, GLX_DRAWABLE_PBUFFER); | ||||
| 			       glxDrawableId, glxDrawableId, | ||||
| 			       GLX_DRAWABLE_PBUFFER); | ||||
| } | ||||
| 
 | ||||
| int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) | ||||
|  | @ -1439,7 +1443,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) | |||
| 	return err; | ||||
| 
 | ||||
|     return DoCreateGLXDrawable(client, pGlxScreen, config, | ||||
| 			       pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW); | ||||
| 			       pDraw, req->window, | ||||
| 			       req->glxwindow, GLX_DRAWABLE_WINDOW); | ||||
| } | ||||
| 
 | ||||
| int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc) | ||||
|  |  | |||
|  | @ -683,10 +683,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, | |||
| } | ||||
| 
 | ||||
| static __GLXdrawable * | ||||
| __glXDRIscreenCreateDrawable(__GLXscreen *screen, | ||||
| __glXDRIscreenCreateDrawable(ClientPtr client, | ||||
| 			     __GLXscreen *screen, | ||||
| 			     DrawablePtr pDraw, | ||||
| 			     int type, | ||||
| 			     XID drawId, | ||||
| 			     int type, | ||||
| 			     XID glxDrawId, | ||||
| 			     __GLXconfig *glxConfig) | ||||
| { | ||||
|     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; | ||||
|  | @ -700,7 +702,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, | |||
| 	return NULL; | ||||
| 
 | ||||
|     if (!__glXDrawableInit(&private->base, screen, | ||||
| 			   pDraw, type, drawId, glxConfig)) { | ||||
| 			   pDraw, type, glxDrawId, glxConfig)) { | ||||
|         xfree(private); | ||||
| 	return NULL; | ||||
|     } | ||||
|  |  | |||
|  | @ -430,10 +430,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, | |||
| } | ||||
| 
 | ||||
| static __GLXdrawable * | ||||
| __glXDRIscreenCreateDrawable(__GLXscreen *screen, | ||||
| __glXDRIscreenCreateDrawable(ClientPtr client, | ||||
| 			     __GLXscreen *screen, | ||||
| 			     DrawablePtr pDraw, | ||||
| 			     int type, | ||||
| 			     XID drawId, | ||||
| 			     int type, | ||||
| 			     XID glxDrawId, | ||||
| 			     __GLXconfig *glxConfig) | ||||
| { | ||||
|     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; | ||||
|  | @ -446,7 +448,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, | |||
| 
 | ||||
|     private->screen = driScreen; | ||||
|     if (!__glXDrawableInit(&private->base, screen, | ||||
| 			   pDraw, type, drawId, glxConfig)) { | ||||
| 			   pDraw, type, glxDrawId, glxConfig)) { | ||||
|         xfree(private); | ||||
| 	return NULL; | ||||
|     } | ||||
|  | @ -457,7 +459,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, | |||
|     private->base.waitGL	= __glXDRIdrawableWaitGL; | ||||
|     private->base.waitX		= __glXDRIdrawableWaitX; | ||||
| 
 | ||||
|     if (DRI2CreateDrawable(pDraw)) { | ||||
|     if (DRI2CreateDrawable(client, pDraw, drawId)) { | ||||
| 	    xfree(private); | ||||
| 	    return NULL; | ||||
|     } | ||||
|  |  | |||
|  | @ -301,10 +301,12 @@ glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val) | |||
| } | ||||
| 
 | ||||
| static __GLXdrawable * | ||||
| __glXDRIscreenCreateDrawable(__GLXscreen *screen, | ||||
| __glXDRIscreenCreateDrawable(ClientPtr client, | ||||
| 			     __GLXscreen *screen, | ||||
| 			     DrawablePtr pDraw, | ||||
| 			     int type, | ||||
| 			     XID drawId, | ||||
| 			     int type, | ||||
| 			     XID glxDrawId, | ||||
| 			     __GLXconfig *glxConfig) | ||||
| { | ||||
|     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; | ||||
|  | @ -319,7 +321,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, | |||
| 
 | ||||
|     private->screen = driScreen; | ||||
|     if (!__glXDrawableInit(&private->base, screen, | ||||
| 			   pDraw, type, drawId, glxConfig)) { | ||||
| 			   pDraw, type, glxDrawId, glxConfig)) { | ||||
|         xfree(private); | ||||
| 	return NULL; | ||||
|     } | ||||
|  |  | |||
|  | @ -134,10 +134,12 @@ struct __GLXscreen { | |||
| 				    __GLXconfig *modes, | ||||
| 				    __GLXcontext *shareContext); | ||||
| 
 | ||||
|     __GLXdrawable *(*createDrawable)(__GLXscreen *context, | ||||
|     __GLXdrawable *(*createDrawable)(ClientPtr client, | ||||
| 				     __GLXscreen *context, | ||||
| 				     DrawablePtr pDraw, | ||||
| 				     int type, | ||||
| 				     XID drawId, | ||||
| 				     int type, | ||||
| 				     XID glxDrawId, | ||||
| 				     __GLXconfig *modes); | ||||
|     int            (*swapInterval)  (__GLXdrawable *drawable, | ||||
| 				     int interval); | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ | |||
| #include <errno.h> | ||||
| #include <xf86drm.h> | ||||
| #include "xf86Module.h" | ||||
| #include "list.h" | ||||
| #include "scrnintstr.h" | ||||
| #include "windowstr.h" | ||||
| #include "dixstruct.h" | ||||
|  | @ -50,12 +51,18 @@ CARD8 dri2_minor; | |||
| 
 | ||||
| static int           dri2ScreenPrivateKeyIndex; | ||||
| static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex; | ||||
| static int dri2WindowPrivateKeyIndex; | ||||
| static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; | ||||
| static int dri2PixmapPrivateKeyIndex; | ||||
| static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; | ||||
| static RESTYPE       dri2DrawableRes; | ||||
| 
 | ||||
| typedef struct _DRI2Screen *DRI2ScreenPtr; | ||||
| 
 | ||||
| typedef struct _DRI2Drawable { | ||||
|     DRI2ScreenPtr        dri2_screen; | ||||
|     DrawablePtr		 drawable; | ||||
|     struct list		 reference_list; | ||||
|     int			 width; | ||||
|     int			 height; | ||||
|     DRI2BufferPtr	*buffers; | ||||
|  | @ -74,6 +81,7 @@ typedef struct _DRI2Drawable { | |||
| 
 | ||||
| typedef struct _DRI2Screen { | ||||
|     ScreenPtr			 screen; | ||||
|     int				 refcnt; | ||||
|     unsigned int		 numDrivers; | ||||
|     const char			**driverNames; | ||||
|     const char			*deviceName; | ||||
|  | @ -99,35 +107,33 @@ DRI2GetScreen(ScreenPtr pScreen) | |||
| static DRI2DrawablePtr | ||||
| DRI2GetDrawable(DrawablePtr pDraw) | ||||
| { | ||||
|     DRI2DrawablePtr pPriv; | ||||
|     int rc; | ||||
|     WindowPtr pWin; | ||||
|     PixmapPtr pPixmap; | ||||
| 
 | ||||
|     rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id, | ||||
| 				 dri2DrawableRes, NULL, DixReadAccess); | ||||
|     if (rc != Success) | ||||
| 	return NULL; | ||||
| 
 | ||||
|     return pPriv; | ||||
|     if (pDraw->type == DRAWABLE_WINDOW) { | ||||
| 	pWin = (WindowPtr) pDraw; | ||||
| 	return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey); | ||||
|     } else { | ||||
| 	pPixmap = (PixmapPtr) pDraw; | ||||
| 	return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int | ||||
| DRI2CreateDrawable(DrawablePtr pDraw) | ||||
| static DRI2DrawablePtr | ||||
| DRI2AllocateDrawable(DrawablePtr pDraw) | ||||
| { | ||||
|     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen); | ||||
|     DRI2DrawablePtr pPriv; | ||||
|     CARD64          ust; | ||||
|     int		    rc; | ||||
| 
 | ||||
|     rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id, | ||||
| 				 dri2DrawableRes, NULL, DixReadAccess); | ||||
|     if (rc == Success || rc != BadValue) | ||||
| 	return rc; | ||||
|     WindowPtr pWin; | ||||
|     PixmapPtr pPixmap; | ||||
| 
 | ||||
|     pPriv = xalloc(sizeof *pPriv); | ||||
|     if (pPriv == NULL) | ||||
| 	return BadAlloc; | ||||
| 	return NULL; | ||||
| 
 | ||||
|     pPriv->dri2_screen = ds; | ||||
|     pPriv->drawable = pDraw; | ||||
|     pPriv->width = pDraw->width; | ||||
|     pPriv->height = pDraw->height; | ||||
|     pPriv->buffers = NULL; | ||||
|  | @ -145,10 +151,78 @@ DRI2CreateDrawable(DrawablePtr pDraw) | |||
|     pPriv->swap_limit = 1; /* default to double buffering */ | ||||
|     pPriv->last_swap_msc = 0; | ||||
|     pPriv->last_swap_ust = 0; | ||||
|     list_init(&pPriv->reference_list); | ||||
| 
 | ||||
|     if (!AddResource(pDraw->id, dri2DrawableRes, pPriv)) | ||||
|     if (pDraw->type == DRAWABLE_WINDOW) { | ||||
| 	pWin = (WindowPtr) pDraw; | ||||
| 	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv); | ||||
|     } else { | ||||
| 	pPixmap = (PixmapPtr) pDraw; | ||||
| 	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv); | ||||
|     } | ||||
| 
 | ||||
|     return pPriv; | ||||
| } | ||||
| 
 | ||||
| typedef struct DRI2DrawableRefRec { | ||||
|     XID id; | ||||
|     XID dri2_id; | ||||
|     struct list link; | ||||
| } DRI2DrawableRefRec, *DRI2DrawableRefPtr; | ||||
| 
 | ||||
| static DRI2DrawableRefPtr | ||||
| DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id) | ||||
| { | ||||
|     DRI2DrawableRefPtr ref; | ||||
| 
 | ||||
|     list_for_each_entry(ref, &pPriv->reference_list, link) { | ||||
| 	if (ref->id == id) | ||||
| 	    return ref; | ||||
|     } | ||||
|      | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id) | ||||
| { | ||||
|     DRI2DrawableRefPtr ref; | ||||
| 
 | ||||
|     ref = malloc(sizeof *ref); | ||||
|     if (ref == NULL) | ||||
| 	return BadAlloc; | ||||
| 	 | ||||
|     if (!AddResource(dri2_id, dri2DrawableRes, pPriv)) | ||||
| 	return BadAlloc; | ||||
|     if (!DRI2LookupDrawableRef(pPriv, id)) | ||||
| 	if (!AddResource(id, dri2DrawableRes, pPriv)) | ||||
| 	    return BadAlloc; | ||||
| 
 | ||||
|     ref->id = id; | ||||
|     ref->dri2_id = dri2_id;  | ||||
|     list_add(&ref->link, &pPriv->reference_list); | ||||
| 
 | ||||
|     return Success; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id) | ||||
| { | ||||
|     DRI2DrawablePtr pPriv; | ||||
|     XID dri2_id; | ||||
|     int rc; | ||||
| 
 | ||||
|     pPriv = DRI2GetDrawable(pDraw); | ||||
|     if (pPriv == NULL) | ||||
| 	pPriv = DRI2AllocateDrawable(pDraw); | ||||
|     if (pPriv == NULL) | ||||
| 	return BadAlloc; | ||||
|      | ||||
|     dri2_id = FakeClientID(client->index); | ||||
|     rc = DRI2AddDrawableRef(pPriv, id, dri2_id); | ||||
|     if (rc != Success) | ||||
| 	return rc; | ||||
| 
 | ||||
|     return Success; | ||||
| } | ||||
| 
 | ||||
|  | @ -156,13 +230,45 @@ static int DRI2DrawableGone(pointer p, XID id) | |||
| { | ||||
|     DRI2DrawablePtr pPriv = p; | ||||
|     DRI2ScreenPtr   ds = pPriv->dri2_screen; | ||||
|     DrawablePtr     root; | ||||
|     DRI2DrawableRefPtr ref, next; | ||||
|     WindowPtr pWin; | ||||
|     PixmapPtr pPixmap; | ||||
|     DrawablePtr pDraw; | ||||
|     int i; | ||||
| 
 | ||||
|     root = &WindowTable[ds->screen->myNum]->drawable; | ||||
|     list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) { | ||||
| 	if (ref->dri2_id == id) { | ||||
| 	    list_del(&ref->link); | ||||
| 	    /* If this was the last ref under this X drawable XID,
 | ||||
| 	     * unregister the X drawable resource. */ | ||||
| 	    if (!DRI2LookupDrawableRef(pPriv, ref->id)) | ||||
| 		FreeResourceByType(ref->id, dri2DrawableRes, TRUE); | ||||
| 	    free(ref); | ||||
| 	    break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ref->id == id) { | ||||
| 	    list_del(&ref->link); | ||||
| 	    FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE); | ||||
| 	    free(ref); | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     if (!list_is_empty(&pPriv->reference_list)) | ||||
| 	return Success; | ||||
| 
 | ||||
|     pDraw = pPriv->drawable; | ||||
|     if (pDraw->type == DRAWABLE_WINDOW) { | ||||
| 	pWin = (WindowPtr) pDraw; | ||||
| 	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); | ||||
|     } else { | ||||
| 	pPixmap = (PixmapPtr) pDraw; | ||||
| 	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); | ||||
|     } | ||||
| 
 | ||||
|     if (pPriv->buffers != NULL) { | ||||
| 	for (i = 0; i < pPriv->bufferCount; i++) | ||||
| 	    (*ds->DestroyBuffer)(root, pPriv->buffers[i]); | ||||
| 	    (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); | ||||
| 
 | ||||
| 	xfree(pPriv->buffers); | ||||
|     } | ||||
|  |  | |||
|  | @ -198,7 +198,8 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen, | |||
| 
 | ||||
| extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic); | ||||
| 
 | ||||
| extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw); | ||||
| extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client, | ||||
| 					DrawablePtr pDraw, XID id); | ||||
| 
 | ||||
| extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw); | ||||
| 
 | ||||
|  |  | |||
|  | @ -167,7 +167,7 @@ ProcDRI2CreateDrawable(ClientPtr client) | |||
| 		       &pDrawable, &status)) | ||||
| 	return status; | ||||
| 
 | ||||
|     status = DRI2CreateDrawable(pDrawable); | ||||
|     status = DRI2CreateDrawable(client, pDrawable, stuff->drawable); | ||||
|     if (status != Success) | ||||
| 	return status; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue