Merge remote branch 'krh/dri2-resource-fixes'

This commit is contained in:
Keith Packard 2010-05-11 08:38:44 -07:00
commit 3df22b293c
10 changed files with 182 additions and 48 deletions

View File

@ -589,6 +589,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
res->value, TypeNameString(res->type)); res->value, TypeNameString(res->type));
#endif #endif
*prev = res->next; *prev = res->next;
clientTable[cid].elements--;
CallResourceStateCallback(ResourceStateFreeing, res); CallResourceStateCallback(ResourceStateFreeing, res);
@ -734,12 +735,14 @@ FreeClientNeverRetainResources(ClientPtr client)
ResourcePtr *resources; ResourcePtr *resources;
ResourcePtr this; ResourcePtr this;
ResourcePtr *prev; ResourcePtr *prev;
int j; int j, elements;
int *eltptr;
if (!client) if (!client)
return; return;
resources = clientTable[client->index].resources; resources = clientTable[client->index].resources;
eltptr = &clientTable[client->index].elements;
for (j=0; j < clientTable[client->index].buckets; j++) for (j=0; j < clientTable[client->index].buckets; j++)
{ {
prev = &resources[j]; prev = &resources[j];
@ -753,11 +756,15 @@ FreeClientNeverRetainResources(ClientPtr client)
this->value, TypeNameString(this->type)); this->value, TypeNameString(this->type));
#endif #endif
*prev = this->next; *prev = this->next;
clientTable[client->index].elements--;
CallResourceStateCallback(ResourceStateFreeing, this); CallResourceStateCallback(ResourceStateFreeing, this);
elements = *eltptr;
(*DeleteFuncs[rtype & TypeMask])(this->value, this->id); (*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
xfree(this); xfree(this);
if (*eltptr != elements)
prev = &resources[j]; /* prev may no longer be valid */
} }
else else
prev = &this->next; prev = &this->next;
@ -804,6 +811,7 @@ FreeClientResources(ClientPtr client)
this->value, TypeNameString(this->type)); this->value, TypeNameString(this->type));
#endif #endif
*head = this->next; *head = this->next;
clientTable[client->index].elements--;
CallResourceStateCallback(ResourceStateFreeing, this); CallResourceStateCallback(ResourceStateFreeing, this);

View File

@ -512,8 +512,9 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error)) if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
return NULL; return NULL;
pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
pDraw, GLX_DRAWABLE_WINDOW, pDraw, drawId,
GLX_DRAWABLE_WINDOW,
drawId, glxc->config); drawId, glxc->config);
/* since we are creating the drawablePrivate, drawId should be new */ /* since we are creating the drawablePrivate, drawId should be new */
@ -1104,15 +1105,17 @@ __glXDrawableRelease(__GLXdrawable *drawable)
} }
static int static int
DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config, DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
DrawablePtr pDraw, XID glxDrawableId, int type) __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
XID glxDrawableId, int type)
{ {
__GLXdrawable *pGlxDraw; __GLXdrawable *pGlxDraw;
if (pGlxScreen->pScreen != pDraw->pScreen) if (pGlxScreen->pScreen != pDraw->pScreen)
return BadMatch; return BadMatch;
pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type, pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
drawableId, type,
glxDrawableId, config); glxDrawableId, config);
if (pGlxDraw == NULL) if (pGlxDraw == NULL)
return BadAlloc; 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 /* Add the glx drawable under the XID of the underlying X drawable
* too. That way we'll get a callback in DrawableGone and can * too. That way we'll get a callback in DrawableGone and can
* clean up properly when the drawable is destroyed. */ * clean up properly when the drawable is destroyed. */
if (pDraw->id != glxDrawableId && if (drawableId != glxDrawableId &&
!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) { !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
pGlxDraw->destroy (pGlxDraw); pGlxDraw->destroy (pGlxDraw);
return BadAlloc; return BadAlloc;
@ -1153,7 +1156,7 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
return BadPixmap; return BadPixmap;
} }
err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
glxDrawableId, GLX_DRAWABLE_PIXMAP); glxDrawableId, GLX_DRAWABLE_PIXMAP);
return err; return err;
@ -1316,7 +1319,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
return BadAlloc; return BadAlloc;
return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
glxDrawableId, GLX_DRAWABLE_PBUFFER); glxDrawableId, glxDrawableId,
GLX_DRAWABLE_PBUFFER);
} }
int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
@ -1439,7 +1443,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
return err; return err;
return DoCreateGLXDrawable(client, pGlxScreen, config, 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) int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)

View File

@ -683,10 +683,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
} }
static __GLXdrawable * static __GLXdrawable *
__glXDRIscreenCreateDrawable(__GLXscreen *screen, __glXDRIscreenCreateDrawable(ClientPtr client,
__GLXscreen *screen,
DrawablePtr pDraw, DrawablePtr pDraw,
int type,
XID drawId, XID drawId,
int type,
XID glxDrawId,
__GLXconfig *glxConfig) __GLXconfig *glxConfig)
{ {
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
@ -700,7 +702,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
return NULL; return NULL;
if (!__glXDrawableInit(&private->base, screen, if (!__glXDrawableInit(&private->base, screen,
pDraw, type, drawId, glxConfig)) { pDraw, type, glxDrawId, glxConfig)) {
xfree(private); xfree(private);
return NULL; return NULL;
} }

View File

@ -430,10 +430,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
} }
static __GLXdrawable * static __GLXdrawable *
__glXDRIscreenCreateDrawable(__GLXscreen *screen, __glXDRIscreenCreateDrawable(ClientPtr client,
__GLXscreen *screen,
DrawablePtr pDraw, DrawablePtr pDraw,
int type,
XID drawId, XID drawId,
int type,
XID glxDrawId,
__GLXconfig *glxConfig) __GLXconfig *glxConfig)
{ {
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
@ -446,7 +448,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
private->screen = driScreen; private->screen = driScreen;
if (!__glXDrawableInit(&private->base, screen, if (!__glXDrawableInit(&private->base, screen,
pDraw, type, drawId, glxConfig)) { pDraw, type, glxDrawId, glxConfig)) {
xfree(private); xfree(private);
return NULL; return NULL;
} }
@ -457,7 +459,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
private->base.waitGL = __glXDRIdrawableWaitGL; private->base.waitGL = __glXDRIdrawableWaitGL;
private->base.waitX = __glXDRIdrawableWaitX; private->base.waitX = __glXDRIdrawableWaitX;
if (DRI2CreateDrawable(pDraw)) { if (DRI2CreateDrawable(client, pDraw, drawId)) {
xfree(private); xfree(private);
return NULL; return NULL;
} }
@ -653,7 +655,7 @@ initializeExtensions(__GLXDRIscreen *screen)
#ifdef __DRI2_FLUSH #ifdef __DRI2_FLUSH
if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 && if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
extensions[i]->version >= __DRI2_FLUSH_VERSION) { extensions[i]->version >= 3) {
screen->flush = (__DRI2flushExtension *) extensions[i]; screen->flush = (__DRI2flushExtension *) extensions[i];
} }
#endif #endif
@ -713,11 +715,11 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
for (i = 0; extensions[i]; i++) { for (i = 0; extensions[i]; i++) {
if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
extensions[i]->version >= __DRI_CORE_VERSION) { extensions[i]->version >= 1) {
screen->core = (const __DRIcoreExtension *) extensions[i]; screen->core = (const __DRIcoreExtension *) extensions[i];
} }
if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 && if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
extensions[i]->version >= __DRI_DRI2_VERSION) { extensions[i]->version >= 1) {
screen->dri2 = (const __DRIdri2Extension *) extensions[i]; screen->dri2 = (const __DRIdri2Extension *) extensions[i];
} }
} }

View File

@ -301,10 +301,12 @@ glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val)
} }
static __GLXdrawable * static __GLXdrawable *
__glXDRIscreenCreateDrawable(__GLXscreen *screen, __glXDRIscreenCreateDrawable(ClientPtr client,
__GLXscreen *screen,
DrawablePtr pDraw, DrawablePtr pDraw,
int type,
XID drawId, XID drawId,
int type,
XID glxDrawId,
__GLXconfig *glxConfig) __GLXconfig *glxConfig)
{ {
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
@ -319,7 +321,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
private->screen = driScreen; private->screen = driScreen;
if (!__glXDrawableInit(&private->base, screen, if (!__glXDrawableInit(&private->base, screen,
pDraw, type, drawId, glxConfig)) { pDraw, type, glxDrawId, glxConfig)) {
xfree(private); xfree(private);
return NULL; return NULL;
} }

View File

@ -134,10 +134,12 @@ struct __GLXscreen {
__GLXconfig *modes, __GLXconfig *modes,
__GLXcontext *shareContext); __GLXcontext *shareContext);
__GLXdrawable *(*createDrawable)(__GLXscreen *context, __GLXdrawable *(*createDrawable)(ClientPtr client,
__GLXscreen *context,
DrawablePtr pDraw, DrawablePtr pDraw,
int type,
XID drawId, XID drawId,
int type,
XID glxDrawId,
__GLXconfig *modes); __GLXconfig *modes);
int (*swapInterval) (__GLXdrawable *drawable, int (*swapInterval) (__GLXdrawable *drawable,
int interval); int interval);

View File

@ -37,6 +37,7 @@
#include <errno.h> #include <errno.h>
#include <xf86drm.h> #include <xf86drm.h>
#include "xf86Module.h" #include "xf86Module.h"
#include "list.h"
#include "scrnintstr.h" #include "scrnintstr.h"
#include "windowstr.h" #include "windowstr.h"
#include "dixstruct.h" #include "dixstruct.h"
@ -50,12 +51,18 @@ CARD8 dri2_minor;
static int dri2ScreenPrivateKeyIndex; static int dri2ScreenPrivateKeyIndex;
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex; static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
static int dri2WindowPrivateKeyIndex;
static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
static int dri2PixmapPrivateKeyIndex;
static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
static RESTYPE dri2DrawableRes; static RESTYPE dri2DrawableRes;
typedef struct _DRI2Screen *DRI2ScreenPtr; typedef struct _DRI2Screen *DRI2ScreenPtr;
typedef struct _DRI2Drawable { typedef struct _DRI2Drawable {
DRI2ScreenPtr dri2_screen; DRI2ScreenPtr dri2_screen;
DrawablePtr drawable;
struct list reference_list;
int width; int width;
int height; int height;
DRI2BufferPtr *buffers; DRI2BufferPtr *buffers;
@ -74,6 +81,7 @@ typedef struct _DRI2Drawable {
typedef struct _DRI2Screen { typedef struct _DRI2Screen {
ScreenPtr screen; ScreenPtr screen;
int refcnt;
unsigned int numDrivers; unsigned int numDrivers;
const char **driverNames; const char **driverNames;
const char *deviceName; const char *deviceName;
@ -99,35 +107,33 @@ DRI2GetScreen(ScreenPtr pScreen)
static DRI2DrawablePtr static DRI2DrawablePtr
DRI2GetDrawable(DrawablePtr pDraw) DRI2GetDrawable(DrawablePtr pDraw)
{ {
DRI2DrawablePtr pPriv; WindowPtr pWin;
int rc; PixmapPtr pPixmap;
rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id, if (pDraw->type == DRAWABLE_WINDOW) {
dri2DrawableRes, NULL, DixReadAccess); pWin = (WindowPtr) pDraw;
if (rc != Success) return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
return NULL; } else {
pPixmap = (PixmapPtr) pDraw;
return pPriv; return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
}
} }
int static DRI2DrawablePtr
DRI2CreateDrawable(DrawablePtr pDraw) DRI2AllocateDrawable(DrawablePtr pDraw)
{ {
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv; DRI2DrawablePtr pPriv;
CARD64 ust; CARD64 ust;
int rc; WindowPtr pWin;
PixmapPtr pPixmap;
rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
dri2DrawableRes, NULL, DixReadAccess);
if (rc == Success || rc != BadValue)
return rc;
pPriv = xalloc(sizeof *pPriv); pPriv = xalloc(sizeof *pPriv);
if (pPriv == NULL) if (pPriv == NULL)
return BadAlloc; return NULL;
pPriv->dri2_screen = ds; pPriv->dri2_screen = ds;
pPriv->drawable = pDraw;
pPriv->width = pDraw->width; pPriv->width = pDraw->width;
pPriv->height = pDraw->height; pPriv->height = pDraw->height;
pPriv->buffers = NULL; pPriv->buffers = NULL;
@ -145,10 +151,78 @@ DRI2CreateDrawable(DrawablePtr pDraw)
pPriv->swap_limit = 1; /* default to double buffering */ pPriv->swap_limit = 1; /* default to double buffering */
pPriv->last_swap_msc = 0; pPriv->last_swap_msc = 0;
pPriv->last_swap_ust = 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; 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; return Success;
} }
@ -156,13 +230,45 @@ static int DRI2DrawableGone(pointer p, XID id)
{ {
DRI2DrawablePtr pPriv = p; DRI2DrawablePtr pPriv = p;
DRI2ScreenPtr ds = pPriv->dri2_screen; DRI2ScreenPtr ds = pPriv->dri2_screen;
DrawablePtr root; DRI2DrawableRefPtr ref, next;
WindowPtr pWin;
PixmapPtr pPixmap;
DrawablePtr pDraw;
int i; 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) { if (pPriv->buffers != NULL) {
for (i = 0; i < pPriv->bufferCount; i++) for (i = 0; i < pPriv->bufferCount; i++)
(*ds->DestroyBuffer)(root, pPriv->buffers[i]); (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
xfree(pPriv->buffers); xfree(pPriv->buffers);
} }

View File

@ -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 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); extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);

View File

@ -167,7 +167,7 @@ ProcDRI2CreateDrawable(ClientPtr client)
&pDrawable, &status)) &pDrawable, &status))
return status; return status;
status = DRI2CreateDrawable(pDrawable); status = DRI2CreateDrawable(client, pDrawable, stuff->drawable);
if (status != Success) if (status != Success)
return status; return status;

View File

@ -94,4 +94,10 @@ list_is_empty(struct list *head)
&pos->member != (head); \ &pos->member != (head); \
pos = __container_of(pos->member.next, pos, member)) pos = __container_of(pos->member.next, pos, member))
#define list_for_each_entry_safe(pos, next, head, member) \
for (pos = __container_of((head)->next, pos, member), \
next = __container_of(pos->member.next, pos, member); \
&pos->member != (head); \
pos = next, next = __container_of(next->member.next, next, member))
#endif #endif