summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/intel.h3
-rw-r--r--src/intel_dri.c101
-rw-r--r--src/sna/sna_dri.c114
3 files changed, 176 insertions, 42 deletions
diff --git a/src/intel.h b/src/intel.h
index 2b114c37..9d64d30f 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -476,11 +476,12 @@ typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
typedef struct _DRI2FrameEvent {
XID drawable_id;
- XID client_id; /* fake client ID to track client destruction */
ClientPtr client;
enum DRI2FrameEventType type;
int frame;
+ struct list drawable_resource, client_resource;
+
/* for swaps & flips only */
DRI2SwapEventPtr event_complete;
void *event_data;
diff --git a/src/intel_dri.c b/src/intel_dri.c
index a6be07f6..38d7a6bc 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -71,6 +71,8 @@ typedef struct {
PixmapPtr pixmap;
} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
+static DevPrivateKeyRec i830_client_key;
+
static uint32_t pixmap_flink(PixmapPtr pixmap)
{
struct intel_pixmap *priv = intel_get_pixmap_private(pixmap);
@@ -608,22 +610,73 @@ I830DRI2DrawablePipe(DrawablePtr pDraw)
static RESTYPE frame_event_client_type, frame_event_drawable_type;
+struct i830_dri2_resource {
+ XID id;
+ RESTYPE type;
+ struct list list;
+};
+
+static struct i830_dri2_resource *
+get_resource(XID id, RESTYPE type)
+{
+ struct i830_dri2_resource *resource;
+ void *ptr;
+
+ ptr = NULL;
+ dixLookupResourceByType(&ptr, id, type, NULL, DixWriteAccess);
+ if (ptr)
+ return ptr;
+
+ resource = malloc(sizeof(*resource));
+ if (resource == NULL)
+ return NULL;
+
+ if (!AddResource(id, type, resource)) {
+ free(resource);
+ return NULL;
+ }
+
+ resource->id = id;
+ resource->type = type;
+ list_init(&resource->list);
+ return resource;
+}
+
static int
i830_dri2_frame_event_client_gone(void *data, XID id)
{
- DRI2FrameEventPtr frame_event = data;
+ struct i830_dri2_resource *resource = data;
+
+ while (!list_is_empty(&resource->list)) {
+ DRI2FrameEventPtr info =
+ list_first_entry(&resource->list,
+ DRI2FrameEventRec,
+ client_resource);
+
+ list_del(&info->client_resource);
+ info->client = NULL;
+ }
+ free(resource);
- frame_event->client = NULL;
- frame_event->client_id = None;
return Success;
}
static int
i830_dri2_frame_event_drawable_gone(void *data, XID id)
{
- DRI2FrameEventPtr frame_event = data;
+ struct i830_dri2_resource *resource = data;
+
+ while (!list_is_empty(&resource->list)) {
+ DRI2FrameEventPtr info =
+ list_first_entry(&resource->list,
+ DRI2FrameEventRec,
+ drawable_resource);
+
+ list_del(&info->drawable_resource);
+ info->drawable_id = None;
+ }
+ free(resource);
- frame_event->drawable_id = None;
return Success;
}
@@ -641,34 +694,48 @@ i830_dri2_register_frame_event_resource_types(void)
return TRUE;
}
+static XID
+get_client_id(ClientPtr client)
+{
+ XID *ptr = dixGetPrivateAddr(&client->devPrivates, &i830_client_key);
+ if (*ptr == 0)
+ *ptr = FakeClientID(client->index);
+ return *ptr;
+}
+
/*
* Hook this frame event into the server resource
* database so we can clean it up if the drawable or
* client exits while the swap is pending
*/
static Bool
-i830_dri2_add_frame_event(DRI2FrameEventPtr frame_event)
+i830_dri2_add_frame_event(DRI2FrameEventPtr info)
{
- frame_event->client_id = FakeClientID(frame_event->client->index);
+ struct i830_dri2_resource *resource;
- if (!AddResource(frame_event->client_id, frame_event_client_type, frame_event))
+ resource = get_resource(get_client_id(info->client),
+ frame_event_client_type);
+ if (resource == NULL)
return FALSE;
- if (!AddResource(frame_event->drawable_id, frame_event_drawable_type, frame_event)) {
- FreeResourceByType(frame_event->client_id, frame_event_client_type, TRUE);
+ list_add(&info->client_resource, &resource->list);
+
+ resource = get_resource(info->drawable_id, frame_event_drawable_type);
+ if (resource == NULL) {
+ list_del(&info->client_resource);
return FALSE;
}
+ list_add(&info->drawable_resource, &resource->list);
+
return TRUE;
}
static void
-i830_dri2_del_frame_event(DRI2FrameEventPtr frame_event)
+i830_dri2_del_frame_event(DRI2FrameEventPtr info)
{
- if (frame_event->client_id)
- FreeResourceByType(frame_event->client_id, frame_event_client_type, TRUE);
- if (frame_event->drawable_id)
- FreeResourceByType(frame_event->drawable_id, frame_event_drawable_type, TRUE);
+ list_del(&info->client_resource);
+ list_del(&info->drawable_resource);
}
static void
@@ -1350,6 +1417,10 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
return FALSE;
}
+ if (!dixRegisterPrivateKey(&i830_client_key, PRIVATE_CLIENT, sizeof(XID)))
+ return FALSE;
+
+
#if DRI2INFOREC_VERSION >= 4
if (serverGeneration != dri2_server_generation) {
dri2_server_generation = serverGeneration;
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index a6cc9ceb..f5d81b3e 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -93,16 +93,24 @@ struct sna_dri_private {
struct kgem_bo *bo;
};
+struct sna_dri_resource {
+ XID id;
+ RESTYPE type;
+ struct list list;
+};
+
struct sna_dri_frame_event {
struct sna *sna;
XID drawable_id;
- XID client_id; /* fake client ID to track client destruction */
ClientPtr client;
enum frame_event_type type;
int frame;
int pipe;
int count;
+ struct list drawable_resource;
+ struct list client_resource;
+
/* for swaps & flips only */
DRI2SwapEventPtr event_complete;
void *event_data;
@@ -120,6 +128,8 @@ struct sna_dri_frame_event {
struct sna_dri_frame_event *chain;
};
+static DevPrivateKeyRec sna_client_key;
+
static inline struct sna_dri_frame_event *
to_frame_event(void *data)
{
@@ -531,22 +541,67 @@ sna_dri_get_pipe(DrawablePtr pDraw)
static RESTYPE frame_event_client_type, frame_event_drawable_type;
+static struct sna_dri_resource *
+get_resource(XID id, RESTYPE type)
+{
+ struct sna_dri_resource *resource;
+ void *ptr;
+
+ ptr = NULL;
+ dixLookupResourceByType(&ptr, id, type, NULL, DixWriteAccess);
+ if (ptr)
+ return ptr;
+
+ resource = malloc(sizeof(*resource));
+ if (resource == NULL)
+ return NULL;
+
+ if (!AddResource(id, type, resource)) {
+ free(resource);
+ return NULL;
+ }
+
+ resource->id = id;
+ resource->type = type;
+ list_init(&resource->list);
+ return resource;
+}
+
static int
sna_dri_frame_event_client_gone(void *data, XID id)
{
- struct sna_dri_frame_event *frame_event = data;
+ struct sna_dri_resource *resource = data;
+
+ while (!list_is_empty(&resource->list)) {
+ struct sna_dri_frame_event *info =
+ list_first_entry(&resource->list,
+ struct sna_dri_frame_event,
+ client_resource);
+
+ list_del(&info->client_resource);
+ info->client = NULL;
+ }
+ free(resource);
- frame_event->client = NULL;
- frame_event->client_id = None;
return Success;
}
static int
sna_dri_frame_event_drawable_gone(void *data, XID id)
{
- struct sna_dri_frame_event *frame_event = data;
+ struct sna_dri_resource *resource = data;
+
+ while (!list_is_empty(&resource->list)) {
+ struct sna_dri_frame_event *info =
+ list_first_entry(&resource->list,
+ struct sna_dri_frame_event,
+ drawable_resource);
+
+ list_del(&info->drawable_resource);
+ info->drawable_id = None;
+ }
+ free(resource);
- frame_event->drawable_id = None;
return Success;
}
@@ -568,45 +623,48 @@ sna_dri_register_frame_event_resource_types(void)
return TRUE;
}
+static XID
+get_client_id(ClientPtr client)
+{
+ XID *ptr = dixGetPrivateAddr(&client->devPrivates, &sna_client_key);
+ if (*ptr == 0)
+ *ptr = FakeClientID(client->index);
+ return *ptr;
+}
+
/*
* Hook this frame event into the server resource
* database so we can clean it up if the drawable or
* client exits while the swap is pending
*/
static Bool
-sna_dri_add_frame_event(struct sna_dri_frame_event *frame_event)
+sna_dri_add_frame_event(struct sna_dri_frame_event *info)
{
- frame_event->client_id = FakeClientID(frame_event->client->index);
+ struct sna_dri_resource *resource;
- if (!AddResource(frame_event->client_id,
- frame_event_client_type,
- frame_event))
+ resource = get_resource(get_client_id(info->client),
+ frame_event_client_type);
+ if (resource == NULL)
return FALSE;
- if (!AddResource(frame_event->drawable_id,
- frame_event_drawable_type,
- frame_event)) {
- FreeResourceByType(frame_event->client_id,
- frame_event_client_type,
- TRUE);
+ list_add(&info->client_resource, &resource->list);
+
+ resource = get_resource(info->drawable_id, frame_event_drawable_type);
+ if (resource == NULL) {
+ list_del(&info->client_resource);
return FALSE;
}
+ list_add(&info->drawable_resource, &resource->list);
+
return TRUE;
}
static void
sna_dri_frame_event_info_free(struct sna_dri_frame_event *info)
{
- if (info->client_id)
- FreeResourceByType(info->client_id,
- frame_event_client_type,
- TRUE);
-
- if (info->drawable_id)
- FreeResourceByType(info->drawable_id,
- frame_event_drawable_type,
- TRUE);
+ list_del(&info->client_resource);
+ list_del(&info->drawable_resource);
if (info->front)
_sna_dri_destroy_buffer(info->sna, info->front);
@@ -1606,6 +1664,10 @@ Bool sna_dri_open(struct sna *sna, ScreenPtr screen)
return FALSE;
}
}
+
+ if (!dixRegisterPrivateKey(&sna_client_key, PRIVATE_CLIENT, sizeof(XID)))
+ return FALSE;
+
sna->deviceName = drmGetDeviceNameFromFd(sna->kgem.fd);
memset(&info, '\0', sizeof(info));
info.fd = sna->kgem.fd;