summaryrefslogtreecommitdiff
path: root/freedreno/freedreno_bo.c
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2013-04-25 16:36:15 -0400
committerRob Clark <robclark@freedesktop.org>2013-04-25 17:33:59 -0400
commitb3a3a77823ada2eb37233678b5a49efaec9b75cb (patch)
treef7ca28117adf931551667fc4b020922494408987 /freedreno/freedreno_bo.c
parentec3c257eb6958da493aee6f010f51a07d7ba4160 (diff)
freedreno: add synchronization between mesa and ddx
Super-cheezy way to synchronization between mesa and ddx.. the SET_ACTIVE ioctl gives us a way to stash a 32b # w/ a GEM bo, and GET_BUFINFO gives us a way to retrieve it. We use this to stash the timestamp of the last ISSUEIBCMDS on the buffer. To avoid an obscene amount of syscalls, we: 1) Only set the timestamp for buffers w/ an flink name, ie. only buffers shared across processes. This is enough to catch the DRI2 buffers. 2) Only set the timestamp for buffers submitted to the 3d ring and only check the timestamps on buffers submitted to the 2d ring. This should be enough to handle synchronizing of presentation blit. We could do synchronization in the other direction too, but that would be problematic if we are using the 3d ring from DDX, since client side wouldn't know this. The waiting on timestamp happens before flush, and setting of timestamp happens after flush. It is transparent to the user of libdrm_freedreno as all the tracking of buffers happens via _emit_reloc().. Signed-off-by: Rob Clark <robclark@freedesktop.org>
Diffstat (limited to 'freedreno/freedreno_bo.c')
-rw-r--r--freedreno/freedreno_bo.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/freedreno/freedreno_bo.c b/freedreno/freedreno_bo.c
index 4f566e10..be386b47 100644
--- a/freedreno/freedreno_bo.c
+++ b/freedreno/freedreno_bo.c
@@ -165,12 +165,17 @@ struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name)
struct drm_gem_open req = {
.name = name,
};
+ struct fd_bo *bo;
if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
return NULL;
}
- return bo_from_handle(dev, req.size, req.handle);
+ bo = bo_from_handle(dev, req.size, req.handle);
+ if (bo)
+ bo->name = name;
+
+ return bo;
}
struct fd_bo * fd_bo_ref(struct fd_bo *bo)
@@ -272,3 +277,64 @@ uint32_t fd_bo_gpuaddr(struct fd_bo *bo, uint32_t offset)
}
return bo->gpuaddr + offset;
}
+
+/*
+ * Super-cheezy way to synchronization between mesa and ddx.. the
+ * SET_ACTIVE ioctl gives us a way to stash a 32b # w/ a GEM bo, and
+ * GET_BUFINFO gives us a way to retrieve it. We use this to stash
+ * the timestamp of the last ISSUEIBCMDS on the buffer.
+ *
+ * To avoid an obscene amount of syscalls, we:
+ * 1) Only set the timestamp for buffers w/ an flink name, ie.
+ * only buffers shared across processes. This is enough to
+ * catch the DRI2 buffers.
+ * 2) Only set the timestamp for buffers submitted to the 3d ring
+ * and only check the timestamps on buffers submitted to the
+ * 2d ring. This should be enough to handle synchronizing of
+ * presentation blit. We could do synchronization in the other
+ * direction too, but that would be problematic if we are using
+ * the 3d ring from DDX, since client side wouldn't know this.
+ *
+ * The waiting on timestamp happens before flush, and setting of
+ * timestamp happens after flush. It is transparent to the user
+ * of libdrm_freedreno as all the tracking of buffers happens via
+ * _emit_reloc()..
+ */
+
+void fb_bo_set_timestamp(struct fd_bo *bo, uint32_t timestamp)
+{
+ if (bo->name) {
+ struct drm_kgsl_gem_active req = {
+ .handle = bo->handle,
+ .active = timestamp,
+ };
+ int ret;
+
+ ret = drmCommandWrite(bo->dev->fd, DRM_KGSL_GEM_SET_ACTIVE,
+ &req, sizeof(req));
+ if (ret) {
+ ERROR_MSG("set active failed: %s", strerror(errno));
+ }
+ }
+}
+
+uint32_t fd_bo_get_timestamp(struct fd_bo *bo)
+{
+ uint32_t timestamp = 0;
+ if (bo->name) {
+ struct drm_kgsl_gem_bufinfo req = {
+ .handle = bo->handle,
+ };
+ int ret;
+
+ ret = drmCommandWriteRead(bo->dev->fd, DRM_KGSL_GEM_GET_BUFINFO,
+ &req, sizeof(req));
+ if (ret) {
+ ERROR_MSG("get bufinfo failed: %s", strerror(errno));
+ return 0;
+ }
+
+ timestamp = req.active;
+ }
+ return timestamp;
+}