1
0
Fork 0

drm_hwcomposer: Do not close gem handle if queued

Fix an issue where if the same gem handle was queued twice we would
close the handle when the first one came out of the queue, leading to
a failure when calling drmModeAddFB2() on the second buffer.

Change-Id: I0bd35158215f74b51111d2e259bca3ba5125b203
Reviewed-on: https://chrome-internal-review.googlesource.com/200715
Tested-by: Allen Martin <amartin@nvidia.com>
Reviewed-by: Stéphane Marchesin <marcheu@google.com>
This commit is contained in:
Allen Martin 2015-02-21 21:20:17 -08:00 committed by Stéphane Marchesin
parent ceaadea1bd
commit 3d3f70acc0

View file

@ -18,10 +18,10 @@
#include <fcntl.h>
#include <errno.h>
#include <list>
#include <sys/param.h>
#include <sys/resource.h>
#include <pthread.h>
#include <queue>
#include <cutils/log.h>
@ -72,7 +72,7 @@ struct hwc_drm_display {
struct hwc_worker set_worker;
std::queue<struct hwc_drm_bo> buf_queue;
std::list<struct hwc_drm_bo> buf_queue;
struct hwc_drm_bo front;
int timeline_fd;
@ -316,8 +316,31 @@ static int hwc_wait_and_set(struct hwc_drm_display *hd,
for (i = 0; i < ARRAY_SIZE(hd->front.gem_handles); i++) {
if (!hd->front.gem_handles[i])
continue;
args.handle = hd->front.gem_handles[i];
drmIoctl(hd->ctx->fd, DRM_IOCTL_GEM_CLOSE, &args);
/* check for duplicate handle in buf_queue */
bool found = false;
std::list<struct hwc_drm_bo>::iterator bi;
ret = pthread_mutex_lock(&hd->set_worker.lock);
if (ret) {
ALOGE("Failed to lock set lock in wait_and_set() %d", ret);
continue;
}
found = false;
for (bi = hd->buf_queue.begin();
bi != hd->buf_queue.end();
++bi)
for (int j = 0; j < ARRAY_SIZE(bi->gem_handles); j++)
if (hd->front.gem_handles[i] == bi->gem_handles[j])
found = true;
if (!found) {
args.handle = hd->front.gem_handles[i];
drmIoctl(hd->ctx->fd, DRM_IOCTL_GEM_CLOSE, &args);
}
if (pthread_mutex_unlock(&hd->set_worker.lock))
ALOGE("Failed to unlock set lock in wait_and_set() %d", ret);
}
hd->front = *buf;
@ -353,7 +376,7 @@ static void *hwc_set_worker(void *arg)
}
buf = hd->buf_queue.front();
hd->buf_queue.pop();
hd->buf_queue.pop_front();
ret = pthread_mutex_unlock(&hd->set_worker.lock);
if (ret) {
@ -419,6 +442,13 @@ static int hwc_set_display(hwc_context_t *ctx, int display,
}
}
ret = pthread_mutex_lock(&hd->set_worker.lock);
if (ret) {
ALOGE("Failed to lock set lock in set() %d", ret);
goto out;
}
ret = hwc_create_bo_from_import(ctx->fd, ctx->import_ctx, layer->handle,
&buf);
if (ret) {
@ -428,12 +458,6 @@ static int hwc_set_display(hwc_context_t *ctx, int display,
buf.acquire_fence_fd = layer->acquireFenceFd;
layer->acquireFenceFd = -1;
ret = pthread_mutex_lock(&hd->set_worker.lock);
if (ret) {
ALOGE("Failed to lock set lock in set() %d", ret);
goto out;
}
/*
* TODO: Retire and release can use the same sync point here b/c hwc is
* restricted to one layer. Once that is no longer true, this will need
@ -444,7 +468,7 @@ static int hwc_set_display(hwc_context_t *ctx, int display,
"drm_hwc_retire", hd->timeline_next);
layer->releaseFenceFd = sw_sync_fence_create(hd->timeline_fd,
"drm_hwc_release", hd->timeline_next);
hd->buf_queue.push(buf);
hd->buf_queue.push_back(buf);
ret = pthread_cond_signal(&hd->set_worker.cond);
if (ret)