drm_hwcomposer: Use queue buffer for pending sets
Instead of just using a front and back buffer, use a queue buffer
to allow more than one pending set.
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Change-Id: I451acbcb08fac5191b76ec2e372fe612d227167c
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 022fa62..ded7b0f 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -21,6 +21,7 @@
#include <sys/param.h>
#include <sys/resource.h>
#include <pthread.h>
+#include <queue>
#include <cutils/log.h>
@@ -67,8 +68,8 @@
struct hwc_worker set_worker;
+ std::queue<struct hwc_drm_bo> buf_queue;
struct hwc_drm_bo front;
- struct hwc_drm_bo back;
};
struct hwc_context_t {
@@ -216,7 +217,7 @@
{
}
-static int hwc_flip(struct hwc_drm_display *hd)
+static int hwc_flip(struct hwc_drm_display *hd, struct hwc_drm_bo *buf)
{
fd_set fds;
drmEventContext event_context;
@@ -229,8 +230,8 @@
return ret;
}
if (modeset_required) {
- ret = drmModeSetCrtc(hd->ctx->fd, hd->active_crtc,
- hd->back.fb_id, 0, 0, &hd->connector_id, 1,
+ ret = drmModeSetCrtc(hd->ctx->fd, hd->active_crtc, buf->fb_id,
+ 0, 0, &hd->connector_id, 1,
&hd->configs[hd->active_config]);
if (ret) {
ALOGE("Modeset failed for crtc %d",
@@ -246,7 +247,7 @@
event_context.version = DRM_EVENT_CONTEXT_VERSION;
event_context.page_flip_handler = hwc_flip_handler;
- ret = drmModePageFlip(hd->ctx->fd, hd->active_crtc, hd->back.fb_id,
+ ret = drmModePageFlip(hd->ctx->fd, hd->active_crtc, buf->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, hd);
if (ret) {
ALOGE("Failed to flip buffer for crtc %d",
@@ -270,25 +271,25 @@
static int hwc_wait_and_set(struct hwc_drm_display *hd)
{
int ret;
+ struct hwc_drm_bo buf = hd->buf_queue.front();
- ret = drmModeAddFB2(hwc_get_fd_for_bo(hd->ctx, &hd->back),
- hd->back.width, hd->back.height, hd->back.format,
- hd->back.gem_handles, hd->back.pitches, hd->back.offsets,
- &hd->back.fb_id, 0);
+ ret = drmModeAddFB2(hwc_get_fd_for_bo(hd->ctx, &buf), buf.width,
+ buf.height, buf.format, buf.gem_handles, buf.pitches,
+ buf.offsets, &buf.fb_id, 0);
if (ret) {
ALOGE("could not create drm fb %d", ret);
return ret;
}
- if (hd->back.acquire_fence_fd >= 0) {
- ret = sync_wait(hd->back.acquire_fence_fd, -1);
+ if (buf.acquire_fence_fd >= 0) {
+ ret = sync_wait(buf.acquire_fence_fd, -1);
if (ret) {
ALOGE("Failed to wait for acquire %d", ret);
return ret;
}
}
- ret = hwc_flip(hd);
+ ret = hwc_flip(hd, &buf);
if (ret) {
ALOGE("Failed to perform flip\n");
return ret;
@@ -302,11 +303,8 @@
return ret;
}
}
- hd->front = hd->back;
-
- memset(&hd->back, 0, sizeof(hd->back));
- hd->back.acquire_fence_fd = -1;
-
+ hd->front = buf;
+ hd->buf_queue.pop();
return ret;
}
@@ -352,9 +350,12 @@
{
struct hwc_drm_display *hd = NULL;
hwc_layer_1_t *layer = NULL;
+ struct hwc_drm_bo buf;
int ret, i;
uint32_t fb_id;
+ memset(&buf, 0, sizeof(buf));
+
ret = hwc_get_drm_display(ctx, display, &hd);
if (ret)
return ret;
@@ -390,22 +391,17 @@
return ret;
}
- if (hd->back.gem_handles[0]) {
- ALOGE("Failing set, back buffer already exists");
- ret = -EINVAL;
- goto out;
- }
-
ret = hwc_create_bo_from_import(ctx->fd, ctx->import_ctx, layer->handle,
- &hd->back);
+ &buf);
if (ret) {
ALOGE("Failed to import handle to drm bo %d", ret);
goto out;
}
-
- hd->back.acquire_fence_fd = layer->acquireFenceFd;
+ buf.acquire_fence_fd = layer->acquireFenceFd;
layer->releaseFenceFd = -1;
+ hd->buf_queue.push(buf);
+
ret = pthread_cond_signal(&hd->set_worker.cond);
if (ret) {
ALOGE("Failed to signal set worker %d", ret);
@@ -1053,7 +1049,7 @@
return -EINVAL;
}
- ctx = (hwc_context_t *)calloc(1, sizeof(*ctx));
+ ctx = new hwc_context_t();
if (!ctx) {
ALOGE("Failed to allocate hwc context");
return -ENOMEM;