blob: 891955d7c17a522e6ce39abbac1994402247fe08 [file] [log] [blame]
Sean Paule0c4c3d2015-01-20 16:56:04 -05001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "hwcomposer-drm"
18
Sean Paulef8f1f92015-04-29 16:05:23 -040019#include "drm_hwcomposer.h"
Sean Paul6a55e9f2015-04-30 15:31:06 -040020#include "drmresources.h"
Sean Paulef8f1f92015-04-29 16:05:23 -040021
Sean Paule0c4c3d2015-01-20 16:56:04 -050022#include <errno.h>
Sean Paulef8f1f92015-04-29 16:05:23 -040023#include <fcntl.h>
Sean Paul5ad302c2015-05-11 10:43:31 -070024#include <list>
Sean Paule42febf2015-05-07 11:35:29 -070025#include <map>
Sean Paulef8f1f92015-04-29 16:05:23 -040026#include <pthread.h>
Dan Albertc5255b32015-05-07 23:42:54 -070027#include <stdlib.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050028#include <sys/param.h>
Sean Paul9aa5ad32015-01-22 15:47:54 -050029#include <sys/resource.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050030#include <xf86drm.h>
31#include <xf86drmMode.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050032
Sean Paulef8f1f92015-04-29 16:05:23 -040033#include <cutils/log.h>
34#include <cutils/properties.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050035#include <hardware/hardware.h>
36#include <hardware/hwcomposer.h>
Sean Paulf1dc1912015-01-24 01:34:31 -050037#include <sw_sync.h>
Sean Paulef8f1f92015-04-29 16:05:23 -040038#include <sync/sync.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050039
40#define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0]))
41
Sean Paule0c4c3d2015-01-20 16:56:04 -050042#define UM_PER_INCH 25400
43
Sean Paul6a55e9f2015-04-30 15:31:06 -040044namespace android {
Sean Paule0c4c3d2015-01-20 16:56:04 -050045
Sean Paul9aa5ad32015-01-22 15:47:54 -050046struct hwc_worker {
Sean Paulef8f1f92015-04-29 16:05:23 -040047 pthread_t thread;
48 pthread_mutex_t lock;
49 pthread_cond_t cond;
50 bool exit;
Sean Paul9aa5ad32015-01-22 15:47:54 -050051};
52
Sean Paule42febf2015-05-07 11:35:29 -070053typedef struct hwc_drm_display {
Sean Paulef8f1f92015-04-29 16:05:23 -040054 struct hwc_context_t *ctx;
55 int display;
Sean Paul9aa5ad32015-01-22 15:47:54 -050056
Sean Paul6a55e9f2015-04-30 15:31:06 -040057 std::vector<uint32_t> config_ids;
Sean Paul9aa5ad32015-01-22 15:47:54 -050058
Sean Paulef8f1f92015-04-29 16:05:23 -040059 struct hwc_worker set_worker;
Sean Paul9aa5ad32015-01-22 15:47:54 -050060
Sean Paulef8f1f92015-04-29 16:05:23 -040061 std::list<struct hwc_drm_bo> buf_queue;
62 struct hwc_drm_bo front;
63 pthread_mutex_t flip_lock;
64 pthread_cond_t flip_cond;
Sean Paulf1dc1912015-01-24 01:34:31 -050065
Sean Paulef8f1f92015-04-29 16:05:23 -040066 int timeline_fd;
67 unsigned timeline_next;
Sean Pauleb9e75c2015-01-25 23:31:30 -050068
Sean Paulef8f1f92015-04-29 16:05:23 -040069 bool enable_vsync_events;
70 unsigned int vsync_sequence;
Sean Paule42febf2015-05-07 11:35:29 -070071} hwc_drm_display_t;
Sean Paule0c4c3d2015-01-20 16:56:04 -050072
73struct hwc_context_t {
Sean Paule42febf2015-05-07 11:35:29 -070074 // map of display:hwc_drm_display_t
75 typedef std::map<int, hwc_drm_display_t> DisplayMap;
76 typedef DisplayMap::iterator DisplayMapIter;
Sean Paule0c4c3d2015-01-20 16:56:04 -050077
Sean Paule42febf2015-05-07 11:35:29 -070078 hwc_composer_device_1_t device;
Sean Paulef8f1f92015-04-29 16:05:23 -040079 hwc_procs_t const *procs;
80 struct hwc_import_context *import_ctx;
Sean Paule0c4c3d2015-01-20 16:56:04 -050081
Sean Paulef8f1f92015-04-29 16:05:23 -040082 struct hwc_worker event_worker;
Sean Paul6a55e9f2015-04-30 15:31:06 -040083
Sean Paule42febf2015-05-07 11:35:29 -070084 DisplayMap displays;
Sean Paul6a55e9f2015-04-30 15:31:06 -040085 DrmResources drm;
Sean Paule0c4c3d2015-01-20 16:56:04 -050086};
87
Sean Paulef8f1f92015-04-29 16:05:23 -040088static int hwc_prepare_layer(hwc_layer_1_t *layer) {
89 /* TODO: We can't handle background right now, defer to sufaceFlinger */
90 if (layer->compositionType == HWC_BACKGROUND) {
91 layer->compositionType = HWC_FRAMEBUFFER;
92 ALOGV("Can't handle background layers yet");
Sean Paule0c4c3d2015-01-20 16:56:04 -050093
Sean Paulef8f1f92015-04-29 16:05:23 -040094 /* TODO: Support sideband compositions */
95 } else if (layer->compositionType == HWC_SIDEBAND) {
96 layer->compositionType = HWC_FRAMEBUFFER;
97 ALOGV("Can't handle sideband content yet");
98 }
Sean Paule0c4c3d2015-01-20 16:56:04 -050099
Sean Paulef8f1f92015-04-29 16:05:23 -0400100 layer->hints = 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500101
Sean Paulef8f1f92015-04-29 16:05:23 -0400102 /* TODO: Handle cursor by setting compositionType=HWC_CURSOR_OVERLAY */
103 if (layer->flags & HWC_IS_CURSOR_LAYER) {
104 ALOGV("Can't handle async cursors yet");
105 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500106
Sean Paulef8f1f92015-04-29 16:05:23 -0400107 /* TODO: Handle transformations */
108 if (layer->transform) {
109 ALOGV("Can't handle transformations yet");
110 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500111
Sean Paulef8f1f92015-04-29 16:05:23 -0400112 /* TODO: Handle blending & plane alpha*/
113 if (layer->blending == HWC_BLENDING_PREMULT ||
114 layer->blending == HWC_BLENDING_COVERAGE) {
115 ALOGV("Can't handle blending yet");
116 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500117
Sean Paulef8f1f92015-04-29 16:05:23 -0400118 /* TODO: Handle cropping & scaling */
Sean Paule0c4c3d2015-01-20 16:56:04 -0500119
Sean Paulef8f1f92015-04-29 16:05:23 -0400120 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500121}
122
Sean Paulef8f1f92015-04-29 16:05:23 -0400123static int hwc_prepare(hwc_composer_device_1_t * /* dev */, size_t num_displays,
124 hwc_display_contents_1_t **display_contents) {
125 /* TODO: Check flags for HWC_GEOMETRY_CHANGED */
Sean Paule0c4c3d2015-01-20 16:56:04 -0500126
Sean Paule42febf2015-05-07 11:35:29 -0700127 for (int i = 0; i < (int)num_displays; ++i) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400128 if (!display_contents[i])
129 continue;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500130
Sean Paulef8f1f92015-04-29 16:05:23 -0400131 for (int j = 0; j < (int)display_contents[i]->numHwLayers; ++j) {
132 int ret = hwc_prepare_layer(&display_contents[i]->hwLayers[j]);
133 if (ret) {
134 ALOGE("Failed to prepare layer %d:%d", j, i);
135 return ret;
136 }
137 }
138 }
Sean Pauldffca952015-02-04 10:19:55 -0800139
Sean Paulef8f1f92015-04-29 16:05:23 -0400140 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500141}
142
Sean Paulef8f1f92015-04-29 16:05:23 -0400143static int hwc_queue_vblank_event(struct hwc_drm_display *hd) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400144 DrmCrtc *crtc = hd->ctx->drm.GetCrtcForDisplay(hd->display);
145 if (!crtc) {
146 ALOGE("Failed to get crtc for display");
147 return -ENODEV;
Sean Paulef8f1f92015-04-29 16:05:23 -0400148 }
Sean Paul814bddb2015-03-03 17:46:19 -0500149
Sean Paulef8f1f92015-04-29 16:05:23 -0400150 drmVBlank vblank;
151 memset(&vblank, 0, sizeof(vblank));
Sean Paul814bddb2015-03-03 17:46:19 -0500152
Sean Paul6a55e9f2015-04-30 15:31:06 -0400153 uint32_t high_crtc = (crtc->pipe() << DRM_VBLANK_HIGH_CRTC_SHIFT);
Sean Paulef8f1f92015-04-29 16:05:23 -0400154 vblank.request.type = (drmVBlankSeqType)(
155 DRM_VBLANK_ABSOLUTE | DRM_VBLANK_NEXTONMISS | DRM_VBLANK_EVENT |
156 (high_crtc & DRM_VBLANK_HIGH_CRTC_MASK));
157 vblank.request.signal = (unsigned long)hd;
158 vblank.request.sequence = hd->vsync_sequence + 1;
Sean Paul814bddb2015-03-03 17:46:19 -0500159
Sean Paul6a55e9f2015-04-30 15:31:06 -0400160 int ret = drmWaitVBlank(hd->ctx->drm.fd(), &vblank);
Sean Paulef8f1f92015-04-29 16:05:23 -0400161 if (ret) {
162 ALOGE("Failed to wait for vblank %d", ret);
163 return ret;
164 }
Sean Paul814bddb2015-03-03 17:46:19 -0500165
Sean Paulef8f1f92015-04-29 16:05:23 -0400166 return 0;
Sean Paul814bddb2015-03-03 17:46:19 -0500167}
168
169static void hwc_vblank_event_handler(int /* fd */, unsigned int sequence,
Sean Paulef8f1f92015-04-29 16:05:23 -0400170 unsigned int tv_sec, unsigned int tv_usec,
171 void *user_data) {
172 struct hwc_drm_display *hd = (struct hwc_drm_display *)user_data;
Sean Paul814bddb2015-03-03 17:46:19 -0500173
Sean Paulef8f1f92015-04-29 16:05:23 -0400174 if (!hd->enable_vsync_events || !hd->ctx->procs->vsync)
175 return;
Sean Paul814bddb2015-03-03 17:46:19 -0500176
Sean Paulef8f1f92015-04-29 16:05:23 -0400177 /*
178 * Discard duplicate vsync (can happen when enabling vsync events while
179 * already processing vsyncs).
180 */
181 if (sequence <= hd->vsync_sequence)
182 return;
Sean Paul814bddb2015-03-03 17:46:19 -0500183
Sean Paulef8f1f92015-04-29 16:05:23 -0400184 hd->vsync_sequence = sequence;
185 int ret = hwc_queue_vblank_event(hd);
186 if (ret)
187 ALOGE("Failed to queue vblank event ret=%d", ret);
Sean Paul814bddb2015-03-03 17:46:19 -0500188
Sean Paulef8f1f92015-04-29 16:05:23 -0400189 int64_t timestamp =
190 (int64_t)tv_sec * 1000 * 1000 * 1000 + (int64_t)tv_usec * 1000;
191 hd->ctx->procs->vsync(hd->ctx->procs, hd->display, timestamp);
Sean Paul814bddb2015-03-03 17:46:19 -0500192}
193
194static void hwc_flip_event_handler(int /* fd */, unsigned int /* sequence */,
Sean Paulef8f1f92015-04-29 16:05:23 -0400195 unsigned int /* tv_sec */,
196 unsigned int /* tv_usec */,
197 void *user_data) {
198 struct hwc_drm_display *hd = (struct hwc_drm_display *)user_data;
Sean Paul814bddb2015-03-03 17:46:19 -0500199
Sean Paulef8f1f92015-04-29 16:05:23 -0400200 int ret = pthread_mutex_lock(&hd->flip_lock);
201 if (ret) {
202 ALOGE("Failed to lock flip lock ret=%d", ret);
203 return;
204 }
Sean Paul814bddb2015-03-03 17:46:19 -0500205
Sean Paulef8f1f92015-04-29 16:05:23 -0400206 ret = pthread_cond_signal(&hd->flip_cond);
207 if (ret)
208 ALOGE("Failed to signal flip condition ret=%d", ret);
Sean Paul814bddb2015-03-03 17:46:19 -0500209
Sean Paulef8f1f92015-04-29 16:05:23 -0400210 ret = pthread_mutex_unlock(&hd->flip_lock);
211 if (ret) {
212 ALOGE("Failed to unlock flip lock ret=%d", ret);
213 return;
214 }
Sean Paul814bddb2015-03-03 17:46:19 -0500215}
216
Sean Paulef8f1f92015-04-29 16:05:23 -0400217static void *hwc_event_worker(void *arg) {
218 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
Sean Paul814bddb2015-03-03 17:46:19 -0500219
Sean Paulef8f1f92015-04-29 16:05:23 -0400220 struct hwc_context_t *ctx = (struct hwc_context_t *)arg;
221 do {
222 fd_set fds;
223 FD_ZERO(&fds);
Sean Paul6a55e9f2015-04-30 15:31:06 -0400224 FD_SET(ctx->drm.fd(), &fds);
Sean Paul814bddb2015-03-03 17:46:19 -0500225
Sean Paulef8f1f92015-04-29 16:05:23 -0400226 drmEventContext event_context;
227 event_context.version = DRM_EVENT_CONTEXT_VERSION;
228 event_context.page_flip_handler = hwc_flip_event_handler;
229 event_context.vblank_handler = hwc_vblank_event_handler;
Sean Paul814bddb2015-03-03 17:46:19 -0500230
Sean Paulef8f1f92015-04-29 16:05:23 -0400231 int ret;
232 do {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400233 ret = select(ctx->drm.fd() + 1, &fds, NULL, NULL, NULL);
Sean Paulef8f1f92015-04-29 16:05:23 -0400234 } while (ret == -1 && errno == EINTR);
Sean Paul814bddb2015-03-03 17:46:19 -0500235
Sean Paulef8f1f92015-04-29 16:05:23 -0400236 if (ret != 1) {
237 ALOGE("Failed waiting for drm event\n");
238 continue;
239 }
Sean Paul814bddb2015-03-03 17:46:19 -0500240
Sean Paul6a55e9f2015-04-30 15:31:06 -0400241 drmHandleEvent(ctx->drm.fd(), &event_context);
Sean Paulef8f1f92015-04-29 16:05:23 -0400242 } while (true);
Sean Paul814bddb2015-03-03 17:46:19 -0500243
Sean Paulef8f1f92015-04-29 16:05:23 -0400244 return NULL;
Sean Paul814bddb2015-03-03 17:46:19 -0500245}
246
Sean Paulef8f1f92015-04-29 16:05:23 -0400247static bool hwc_mode_is_equal(drmModeModeInfoPtr a, drmModeModeInfoPtr b) {
248 return a->clock == b->clock && a->hdisplay == b->hdisplay &&
249 a->hsync_start == b->hsync_start && a->hsync_end == b->hsync_end &&
250 a->htotal == b->htotal && a->hskew == b->hskew &&
251 a->vdisplay == b->vdisplay && a->vsync_start == b->vsync_start &&
252 a->vsync_end == b->vsync_end && a->vtotal == b->vtotal &&
253 a->vscan == b->vscan && a->vrefresh == b->vrefresh &&
254 a->flags == b->flags && a->type == b->type &&
255 !strcmp(a->name, b->name);
Sean Paule0c4c3d2015-01-20 16:56:04 -0500256}
257
Sean Paul6a55e9f2015-04-30 15:31:06 -0400258static int hwc_flip(struct hwc_drm_display *hd, struct hwc_drm_bo *buf) {
259 DrmCrtc *crtc = hd->ctx->drm.GetCrtcForDisplay(hd->display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400260 if (!crtc) {
261 ALOGE("Failed to get crtc for display %d", hd->display);
262 return -ENODEV;
263 }
Sean Paulefb20cb2015-02-04 09:29:15 -0800264
Sean Paul6a55e9f2015-04-30 15:31:06 -0400265 DrmConnector *connector = hd->ctx->drm.GetConnectorForDisplay(hd->display);
266 if (!connector) {
267 ALOGE("Failed to get connector for display %d", hd->display);
268 return -ENODEV;
Sean Paulef8f1f92015-04-29 16:05:23 -0400269 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400270
271 int ret;
272 if (crtc->requires_modeset()) {
273 drmModeModeInfo drm_mode;
274 connector->active_mode().ToModeModeInfo(&drm_mode);
275 uint32_t connector_id = connector->id();
276 ret = drmModeSetCrtc(hd->ctx->drm.fd(), crtc->id(), buf->fb_id, 0, 0,
277 &connector_id, 1, &drm_mode);
Sean Paulef8f1f92015-04-29 16:05:23 -0400278 if (ret) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400279 ALOGE("Modeset failed for crtc %d", crtc->id());
Sean Paulef8f1f92015-04-29 16:05:23 -0400280 return ret;
281 }
282 return 0;
283 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500284
Sean Paul6a55e9f2015-04-30 15:31:06 -0400285 ret = drmModePageFlip(hd->ctx->drm.fd(), crtc->id(), buf->fb_id,
Sean Paulef8f1f92015-04-29 16:05:23 -0400286 DRM_MODE_PAGE_FLIP_EVENT, hd);
287 if (ret) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400288 ALOGE("Failed to flip buffer for crtc %d", crtc->id());
Sean Paulef8f1f92015-04-29 16:05:23 -0400289 return ret;
290 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500291
Sean Paulef8f1f92015-04-29 16:05:23 -0400292 ret = pthread_cond_wait(&hd->flip_cond, &hd->flip_lock);
293 if (ret) {
294 ALOGE("Failed to wait on condition %d", ret);
295 return ret;
296 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500297
Sean Paulef8f1f92015-04-29 16:05:23 -0400298 return 0;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500299}
300
Sean Paul3bc48e82015-01-23 01:41:13 -0500301static int hwc_wait_and_set(struct hwc_drm_display *hd,
Sean Paulef8f1f92015-04-29 16:05:23 -0400302 struct hwc_drm_bo *buf) {
303 int ret;
304 if (buf->acquire_fence_fd >= 0) {
305 ret = sync_wait(buf->acquire_fence_fd, -1);
306 close(buf->acquire_fence_fd);
307 buf->acquire_fence_fd = -1;
308 if (ret) {
309 ALOGE("Failed to wait for acquire %d", ret);
310 return ret;
311 }
312 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500313
Sean Paulef8f1f92015-04-29 16:05:23 -0400314 ret = hwc_flip(hd, buf);
315 if (ret) {
316 ALOGE("Failed to perform flip\n");
317 return ret;
318 }
Lauri Peltonen132e0102015-02-12 13:54:33 +0200319
Sean Paul6a55e9f2015-04-30 15:31:06 -0400320 if (hwc_import_bo_release(hd->ctx->drm.fd(), hd->ctx->import_ctx,
321 &hd->front)) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400322 struct drm_gem_close args;
323 memset(&args, 0, sizeof(args));
324 for (int i = 0; i < ARRAY_SIZE(hd->front.gem_handles); ++i) {
325 if (!hd->front.gem_handles[i])
326 continue;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500327
Sean Paulef8f1f92015-04-29 16:05:23 -0400328 ret = pthread_mutex_lock(&hd->set_worker.lock);
329 if (ret) {
330 ALOGE("Failed to lock set lock in wait_and_set() %d", ret);
331 continue;
332 }
Allen Martin3d3f70a2015-02-21 21:20:17 -0800333
Sean Paulef8f1f92015-04-29 16:05:23 -0400334 /* check for duplicate handle in buf_queue */
335 bool found = false;
336 for (std::list<struct hwc_drm_bo>::iterator bi = hd->buf_queue.begin();
337 bi != hd->buf_queue.end(); ++bi)
338 for (int j = 0; j < ARRAY_SIZE(bi->gem_handles); ++j)
339 if (hd->front.gem_handles[i] == bi->gem_handles[j])
340 found = true;
Allen Martin3d3f70a2015-02-21 21:20:17 -0800341
Sean Paulef8f1f92015-04-29 16:05:23 -0400342 for (int j = 0; j < ARRAY_SIZE(buf->gem_handles); ++j)
343 if (hd->front.gem_handles[i] == buf->gem_handles[j])
344 found = true;
Allen Martin3d3f70a2015-02-21 21:20:17 -0800345
Sean Paulef8f1f92015-04-29 16:05:23 -0400346 if (!found) {
347 args.handle = hd->front.gem_handles[i];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400348 drmIoctl(hd->ctx->drm.fd(), DRM_IOCTL_GEM_CLOSE, &args);
Sean Paulef8f1f92015-04-29 16:05:23 -0400349 }
350 if (pthread_mutex_unlock(&hd->set_worker.lock))
351 ALOGE("Failed to unlock set lock in wait_and_set() %d", ret);
352 }
353 }
Lauri Peltonen77d6d7a2015-02-23 20:44:16 +0200354
Sean Paulef8f1f92015-04-29 16:05:23 -0400355 hd->front = *buf;
Allen Martin3d3f70a2015-02-21 21:20:17 -0800356
Sean Paulef8f1f92015-04-29 16:05:23 -0400357 return ret;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500358}
359
Sean Paulef8f1f92015-04-29 16:05:23 -0400360static void *hwc_set_worker(void *arg) {
361 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500362
Sean Paulef8f1f92015-04-29 16:05:23 -0400363 struct hwc_drm_display *hd = (struct hwc_drm_display *)arg;
364 int ret = pthread_mutex_lock(&hd->flip_lock);
365 if (ret) {
366 ALOGE("Failed to lock flip lock ret=%d", ret);
367 return NULL;
368 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500369
Sean Paulef8f1f92015-04-29 16:05:23 -0400370 do {
371 ret = pthread_mutex_lock(&hd->set_worker.lock);
372 if (ret) {
373 ALOGE("Failed to lock set lock %d", ret);
374 return NULL;
375 }
Sean Paul814bddb2015-03-03 17:46:19 -0500376
Sean Paulef8f1f92015-04-29 16:05:23 -0400377 if (hd->set_worker.exit)
378 break;
Sean Paul3bc48e82015-01-23 01:41:13 -0500379
Sean Paulef8f1f92015-04-29 16:05:23 -0400380 if (hd->buf_queue.empty()) {
381 ret = pthread_cond_wait(&hd->set_worker.cond, &hd->set_worker.lock);
382 if (ret) {
383 ALOGE("Failed to wait on condition %d", ret);
384 break;
385 }
386 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500387
Sean Paulef8f1f92015-04-29 16:05:23 -0400388 struct hwc_drm_bo buf;
389 buf = hd->buf_queue.front();
390 hd->buf_queue.pop_front();
Sean Paul3bc48e82015-01-23 01:41:13 -0500391
Sean Paulef8f1f92015-04-29 16:05:23 -0400392 ret = pthread_mutex_unlock(&hd->set_worker.lock);
393 if (ret) {
394 ALOGE("Failed to unlock set lock %d", ret);
395 return NULL;
396 }
Sean Paul3bc48e82015-01-23 01:41:13 -0500397
Sean Paulef8f1f92015-04-29 16:05:23 -0400398 ret = hwc_wait_and_set(hd, &buf);
399 if (ret)
400 ALOGE("Failed to wait and set %d", ret);
Sean Paul3bc48e82015-01-23 01:41:13 -0500401
Sean Paulef8f1f92015-04-29 16:05:23 -0400402 ret = sw_sync_timeline_inc(hd->timeline_fd, 1);
403 if (ret)
404 ALOGE("Failed to increment sync timeline %d", ret);
405 } while (true);
Sean Paul3bc48e82015-01-23 01:41:13 -0500406
Sean Paulef8f1f92015-04-29 16:05:23 -0400407 ret = pthread_mutex_unlock(&hd->set_worker.lock);
408 if (ret)
409 ALOGE("Failed to unlock set lock while exiting %d", ret);
Sean Paulf1dc1912015-01-24 01:34:31 -0500410
Sean Paulef8f1f92015-04-29 16:05:23 -0400411 ret = pthread_mutex_unlock(&hd->flip_lock);
412 if (ret)
413 ALOGE("Failed to unlock flip lock ret=%d", ret);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500414
Sean Paulef8f1f92015-04-29 16:05:23 -0400415 return NULL;
416}
Sean Paul9aa5ad32015-01-22 15:47:54 -0500417
Sean Paulef8f1f92015-04-29 16:05:23 -0400418static void hwc_close_fences(hwc_display_contents_1_t *display_contents) {
419 for (int i = 0; i < (int)display_contents->numHwLayers; ++i) {
420 hwc_layer_1_t *layer = &display_contents->hwLayers[i];
421 if (layer->acquireFenceFd >= 0) {
422 close(layer->acquireFenceFd);
423 layer->acquireFenceFd = -1;
424 }
425 }
426 if (display_contents->outbufAcquireFenceFd >= 0) {
427 close(display_contents->outbufAcquireFenceFd);
428 display_contents->outbufAcquireFenceFd = -1;
429 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500430}
431
Sean Paule0c4c3d2015-01-20 16:56:04 -0500432static int hwc_set_display(hwc_context_t *ctx, int display,
Sean Paulef8f1f92015-04-29 16:05:23 -0400433 hwc_display_contents_1_t *display_contents) {
Sean Paule42febf2015-05-07 11:35:29 -0700434 struct hwc_drm_display *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400435 DrmCrtc *crtc = hd->ctx->drm.GetCrtcForDisplay(display);
436 if (!crtc) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400437 ALOGE("There is no active crtc for display %d", display);
438 hwc_close_fences(display_contents);
439 return -ENOENT;
440 }
Sean Paul9b1bb842015-01-23 01:11:58 -0500441
Sean Paulef8f1f92015-04-29 16:05:23 -0400442 /*
443 * TODO: We can only support one hw layer atm, so choose either the
444 * first one or the framebuffer target.
445 */
446 hwc_layer_1_t *layer = NULL;
447 if (!display_contents->numHwLayers) {
448 return 0;
449 } else if (display_contents->numHwLayers == 1) {
450 layer = &display_contents->hwLayers[0];
451 } else {
452 int i;
453 for (i = 0; i < (int)display_contents->numHwLayers; ++i) {
454 layer = &display_contents->hwLayers[i];
455 if (layer->compositionType == HWC_FRAMEBUFFER_TARGET)
456 break;
457 }
458 if (i == (int)display_contents->numHwLayers) {
459 ALOGE("Could not find a suitable layer for display %d", display);
460 }
461 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500462
Sean Paule42febf2015-05-07 11:35:29 -0700463 int ret = pthread_mutex_lock(&hd->set_worker.lock);
Sean Paulef8f1f92015-04-29 16:05:23 -0400464 if (ret) {
465 ALOGE("Failed to lock set lock in set() %d", ret);
466 hwc_close_fences(display_contents);
467 return ret;
468 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500469
Sean Paulef8f1f92015-04-29 16:05:23 -0400470 struct hwc_drm_bo buf;
471 memset(&buf, 0, sizeof(buf));
Sean Paul6a55e9f2015-04-30 15:31:06 -0400472 ret =
473 hwc_import_bo_create(ctx->drm.fd(), ctx->import_ctx, layer->handle, &buf);
Sean Paulef8f1f92015-04-29 16:05:23 -0400474 if (ret) {
475 ALOGE("Failed to import handle to drm bo %d", ret);
476 hwc_close_fences(display_contents);
477 return ret;
478 }
479 buf.acquire_fence_fd = layer->acquireFenceFd;
480 layer->acquireFenceFd = -1;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500481
Sean Paulef8f1f92015-04-29 16:05:23 -0400482 /*
483 * TODO: Retire and release can use the same sync point here b/c hwc is
484 * restricted to one layer. Once that is no longer true, this will need
485 * to change
486 */
487 ++hd->timeline_next;
488 display_contents->retireFenceFd = sw_sync_fence_create(
489 hd->timeline_fd, "drm_hwc_retire", hd->timeline_next);
490 layer->releaseFenceFd = sw_sync_fence_create(
491 hd->timeline_fd, "drm_hwc_release", hd->timeline_next);
492 hd->buf_queue.push_back(buf);
Allen Martin3d3f70a2015-02-21 21:20:17 -0800493
Sean Paulef8f1f92015-04-29 16:05:23 -0400494 ret = pthread_cond_signal(&hd->set_worker.cond);
495 if (ret)
496 ALOGE("Failed to signal set worker %d", ret);
Allen Martin3d3f70a2015-02-21 21:20:17 -0800497
Sean Paulef8f1f92015-04-29 16:05:23 -0400498 if (pthread_mutex_unlock(&hd->set_worker.lock))
499 ALOGE("Failed to unlock set lock in set()");
Sean Paul3bc48e82015-01-23 01:41:13 -0500500
Sean Paulef8f1f92015-04-29 16:05:23 -0400501 hwc_close_fences(display_contents);
502 return ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500503}
504
505static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
Sean Paulef8f1f92015-04-29 16:05:23 -0400506 hwc_display_contents_1_t **display_contents) {
507 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500508
Sean Paulef8f1f92015-04-29 16:05:23 -0400509 int ret = 0;
Sean Paule42febf2015-05-07 11:35:29 -0700510 for (int i = 0; i < (int)num_displays; ++i) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400511 if (display_contents[i])
512 ret = hwc_set_display(ctx, i, display_contents[i]);
513 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500514
Sean Paulef8f1f92015-04-29 16:05:23 -0400515 return ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500516}
517
Sean Paulef8f1f92015-04-29 16:05:23 -0400518static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
519 int event, int enabled) {
520 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule42febf2015-05-07 11:35:29 -0700521 struct hwc_drm_display *hd = &ctx->displays[display];
Sean Paulef8f1f92015-04-29 16:05:23 -0400522 if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
523 return -EINVAL;
Sean Pauleb9e75c2015-01-25 23:31:30 -0500524
Sean Paul6a55e9f2015-04-30 15:31:06 -0400525 DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(display);
526 if (!crtc) {
527 ALOGD("Can't service events for display %d, no crtc", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400528 return -EINVAL;
529 }
Sean Pauleb9e75c2015-01-25 23:31:30 -0500530
Sean Paulef8f1f92015-04-29 16:05:23 -0400531 hd->enable_vsync_events = !!enabled;
Sean Pauleb9e75c2015-01-25 23:31:30 -0500532
Sean Paulef8f1f92015-04-29 16:05:23 -0400533 if (!hd->enable_vsync_events)
534 return 0;
Sean Pauleb9e75c2015-01-25 23:31:30 -0500535
Sean Paulef8f1f92015-04-29 16:05:23 -0400536 /*
537 * Note that it's possible that the event worker is already waiting for
538 * a vsync, and this will be a duplicate request. In that event, we'll
539 * end up firing the event handler twice, and it will discard the second
540 * event. Not ideal, but not worth introducing a bunch of additional
541 * logic/locks/state for.
542 */
Sean Paule42febf2015-05-07 11:35:29 -0700543 int ret = hwc_queue_vblank_event(hd);
Sean Paulef8f1f92015-04-29 16:05:23 -0400544 if (ret) {
545 ALOGE("Failed to queue vblank event ret=%d", ret);
546 return ret;
547 }
Sean Pauleb9e75c2015-01-25 23:31:30 -0500548
Sean Paulef8f1f92015-04-29 16:05:23 -0400549 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500550}
551
Sean Paulef8f1f92015-04-29 16:05:23 -0400552static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
553 int mode) {
554 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500555
Sean Paul6a55e9f2015-04-30 15:31:06 -0400556 uint64_t dpmsValue = 0;
Sean Paulef8f1f92015-04-29 16:05:23 -0400557 switch (mode) {
558 case HWC_POWER_MODE_OFF:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400559 dpmsValue = DRM_MODE_DPMS_OFF;
Sean Paulef8f1f92015-04-29 16:05:23 -0400560 break;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500561
Sean Paulef8f1f92015-04-29 16:05:23 -0400562 /* We can't support dozing right now, so go full on */
563 case HWC_POWER_MODE_DOZE:
564 case HWC_POWER_MODE_DOZE_SUSPEND:
565 case HWC_POWER_MODE_NORMAL:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400566 dpmsValue = DRM_MODE_DPMS_ON;
Sean Paulef8f1f92015-04-29 16:05:23 -0400567 break;
568 };
Sean Paul6a55e9f2015-04-30 15:31:06 -0400569 return ctx->drm.SetDpmsMode(display, dpmsValue);
Sean Paule0c4c3d2015-01-20 16:56:04 -0500570}
571
Sean Paulef8f1f92015-04-29 16:05:23 -0400572static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
573 int *value) {
574 switch (what) {
575 case HWC_BACKGROUND_LAYER_SUPPORTED:
576 *value = 0; /* TODO: We should do this */
577 break;
578 case HWC_VSYNC_PERIOD:
579 ALOGW("Query for deprecated vsync value, returning 60Hz");
580 *value = 1000 * 1000 * 1000 / 60;
581 break;
582 case HWC_DISPLAY_TYPES_SUPPORTED:
583 *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
584 break;
585 }
586 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500587}
588
Sean Paulef8f1f92015-04-29 16:05:23 -0400589static void hwc_register_procs(struct hwc_composer_device_1 *dev,
590 hwc_procs_t const *procs) {
591 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500592
Sean Paulef8f1f92015-04-29 16:05:23 -0400593 ctx->procs = procs;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500594}
595
Sean Paulef8f1f92015-04-29 16:05:23 -0400596static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
597 int display, uint32_t *configs,
Sean Paul6a55e9f2015-04-30 15:31:06 -0400598 size_t *num_configs) {
599 if (!*num_configs)
Sean Paulef8f1f92015-04-29 16:05:23 -0400600 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500601
Sean Paulef8f1f92015-04-29 16:05:23 -0400602 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule42febf2015-05-07 11:35:29 -0700603 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400604 hd->config_ids.clear();
605
606 DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
607 if (!connector) {
608 ALOGE("Failed to get connector for display %d", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400609 return -ENODEV;
610 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500611
Sean Paule42febf2015-05-07 11:35:29 -0700612 int ret = connector->UpdateModes();
Sean Paul6a55e9f2015-04-30 15:31:06 -0400613 if (ret) {
614 ALOGE("Failed to update display modes %d", ret);
Sean Paulef8f1f92015-04-29 16:05:23 -0400615 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400616 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500617
Sean Paul6a55e9f2015-04-30 15:31:06 -0400618 for (DrmConnector::ModeIter iter = connector->begin_modes();
619 iter != connector->end_modes(); ++iter) {
620 size_t idx = hd->config_ids.size();
621 if (idx == *num_configs)
622 break;
623 hd->config_ids.push_back(iter->id());
624 configs[idx] = iter->id();
625 }
626 *num_configs = hd->config_ids.size();
627 return *num_configs == 0 ? -1 : 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500628}
629
Sean Paulef8f1f92015-04-29 16:05:23 -0400630static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
631 int display, uint32_t config,
632 const uint32_t *attributes,
633 int32_t *values) {
634 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400635 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400636 if (!c) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400637 ALOGE("Failed to get DrmConnector for display %d", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400638 return -ENODEV;
639 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400640 DrmMode mode;
641 for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
642 ++iter) {
643 if (iter->id() == config) {
644 mode = *iter;
645 break;
646 }
647 }
648 if (mode.id() == 0) {
649 ALOGE("Failed to find active mode for display %d", display);
650 return -ENOENT;
Sean Paulef8f1f92015-04-29 16:05:23 -0400651 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500652
Sean Paul6a55e9f2015-04-30 15:31:06 -0400653 uint32_t mm_width = c->mm_width();
654 uint32_t mm_height = c->mm_height();
Sean Paulef8f1f92015-04-29 16:05:23 -0400655 for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
656 switch (attributes[i]) {
657 case HWC_DISPLAY_VSYNC_PERIOD:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400658 values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
Sean Paulef8f1f92015-04-29 16:05:23 -0400659 break;
660 case HWC_DISPLAY_WIDTH:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400661 values[i] = mode.h_display();
Sean Paulef8f1f92015-04-29 16:05:23 -0400662 break;
663 case HWC_DISPLAY_HEIGHT:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400664 values[i] = mode.v_display();
Sean Paulef8f1f92015-04-29 16:05:23 -0400665 break;
666 case HWC_DISPLAY_DPI_X:
667 /* Dots per 1000 inches */
Sean Paul6a55e9f2015-04-30 15:31:06 -0400668 values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
Sean Paulef8f1f92015-04-29 16:05:23 -0400669 break;
670 case HWC_DISPLAY_DPI_Y:
671 /* Dots per 1000 inches */
Sean Paul6a55e9f2015-04-30 15:31:06 -0400672 values[i] =
673 mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
Sean Paulef8f1f92015-04-29 16:05:23 -0400674 break;
675 }
676 }
Sean Paulef8f1f92015-04-29 16:05:23 -0400677 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500678}
679
Sean Paulef8f1f92015-04-29 16:05:23 -0400680static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
681 int display) {
682 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400683 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
684 if (!c) {
685 ALOGE("Failed to get DrmConnector for display %d", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400686 return -ENODEV;
687 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500688
Sean Paul6a55e9f2015-04-30 15:31:06 -0400689 DrmMode mode = c->active_mode();
Sean Paule42febf2015-05-07 11:35:29 -0700690 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400691 for (size_t i = 0; i < hd->config_ids.size(); ++i) {
692 if (hd->config_ids[i] == mode.id())
693 return i;
Sean Paulef8f1f92015-04-29 16:05:23 -0400694 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400695 return -1;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500696}
697
Sean Paulef8f1f92015-04-29 16:05:23 -0400698static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
699 int index) {
700 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule42febf2015-05-07 11:35:29 -0700701 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400702 if (index >= (int)hd->config_ids.size()) {
703 ALOGE("Invalid config index %d passed in", index);
704 return -EINVAL;
Sean Paulef8f1f92015-04-29 16:05:23 -0400705 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500706
Sean Paule42febf2015-05-07 11:35:29 -0700707 int ret =
Sean Paul6a55e9f2015-04-30 15:31:06 -0400708 ctx->drm.SetDisplayActiveMode(display, hd->config_ids[index]);
709 if (ret) {
710 ALOGE("Failed to set config for display %d", display);
711 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400712 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500713
Sean Paul6a55e9f2015-04-30 15:31:06 -0400714 return ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500715}
716
Sean Paulef8f1f92015-04-29 16:05:23 -0400717static int hwc_destroy_worker(struct hwc_worker *worker) {
718 int ret = pthread_mutex_lock(&worker->lock);
719 if (ret) {
720 ALOGE("Failed to lock in destroy() %d", ret);
721 return ret;
722 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500723
Sean Paulef8f1f92015-04-29 16:05:23 -0400724 worker->exit = true;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500725
Sean Paulef8f1f92015-04-29 16:05:23 -0400726 ret |= pthread_cond_signal(&worker->cond);
727 if (ret)
728 ALOGE("Failed to signal cond in destroy() %d", ret);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500729
Sean Paulef8f1f92015-04-29 16:05:23 -0400730 ret |= pthread_mutex_unlock(&worker->lock);
731 if (ret)
732 ALOGE("Failed to unlock in destroy() %d", ret);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500733
Sean Paulef8f1f92015-04-29 16:05:23 -0400734 ret |= pthread_join(worker->thread, NULL);
735 if (ret && ret != ESRCH)
736 ALOGE("Failed to join thread in destroy() %d", ret);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500737
Sean Paulef8f1f92015-04-29 16:05:23 -0400738 return ret;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500739}
740
Sean Paulef8f1f92015-04-29 16:05:23 -0400741static void hwc_destroy_display(struct hwc_drm_display *hd) {
742 if (hwc_destroy_worker(&hd->set_worker))
743 ALOGE("Destroy set worker failed");
Sean Paul9aa5ad32015-01-22 15:47:54 -0500744}
745
Sean Paulef8f1f92015-04-29 16:05:23 -0400746static int hwc_device_close(struct hw_device_t *dev) {
747 struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500748
Sean Paule42febf2015-05-07 11:35:29 -0700749 for (hwc_context_t::DisplayMapIter iter = ctx->displays.begin();
750 iter != ctx->displays.end(); ++iter)
751 hwc_destroy_display(&iter->second);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500752
Sean Paulef8f1f92015-04-29 16:05:23 -0400753 if (hwc_destroy_worker(&ctx->event_worker))
754 ALOGE("Destroy event worker failed");
Sean Paul814bddb2015-03-03 17:46:19 -0500755
Sean Paulef8f1f92015-04-29 16:05:23 -0400756 int ret = hwc_import_destroy(ctx->import_ctx);
757 if (ret)
758 ALOGE("Could not destroy import %d", ret);
Sean Paulcd36a9e2015-01-22 18:01:18 -0500759
Sean Paulef8f1f92015-04-29 16:05:23 -0400760 delete ctx;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500761
Sean Paulef8f1f92015-04-29 16:05:23 -0400762 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500763}
764
Sean Paul814bddb2015-03-03 17:46:19 -0500765static int hwc_initialize_worker(struct hwc_worker *worker,
Sean Paulef8f1f92015-04-29 16:05:23 -0400766 void *(*routine)(void *), void *arg) {
767 int ret = pthread_cond_init(&worker->cond, NULL);
768 if (ret) {
769 ALOGE("Failed to create worker condition %d", ret);
770 return ret;
771 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500772
Sean Paulef8f1f92015-04-29 16:05:23 -0400773 ret = pthread_mutex_init(&worker->lock, NULL);
774 if (ret) {
775 ALOGE("Failed to initialize worker lock %d", ret);
776 pthread_cond_destroy(&worker->cond);
777 return ret;
778 }
Sean Paul9aa5ad32015-01-22 15:47:54 -0500779
Sean Paulef8f1f92015-04-29 16:05:23 -0400780 worker->exit = false;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500781
Sean Paulef8f1f92015-04-29 16:05:23 -0400782 ret = pthread_create(&worker->thread, NULL, routine, arg);
783 if (ret) {
784 ALOGE("Could not create worker thread %d", ret);
785 pthread_mutex_destroy(&worker->lock);
786 pthread_cond_destroy(&worker->cond);
787 return ret;
788 }
789 return 0;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500790}
791
Sean Paul24a26e32015-02-04 10:34:47 -0800792/*
793 * TODO: This function sets the active config to the first one in the list. This
794 * should be fixed such that it selects the preferred mode for the display, or
795 * some other, saner, method of choosing the config.
796 */
Sean Paule42febf2015-05-07 11:35:29 -0700797static int hwc_set_initial_config(hwc_drm_display_t *hd) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400798 uint32_t config;
799 size_t num_configs = 1;
800 int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
801 &num_configs);
802 if (ret || !num_configs)
803 return 0;
Sean Paul24a26e32015-02-04 10:34:47 -0800804
Sean Paulef8f1f92015-04-29 16:05:23 -0400805 ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
806 if (ret) {
807 ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
808 return ret;
809 }
Sean Paul24a26e32015-02-04 10:34:47 -0800810
Sean Paulef8f1f92015-04-29 16:05:23 -0400811 return ret;
Sean Paul24a26e32015-02-04 10:34:47 -0800812}
813
Sean Paul6a55e9f2015-04-30 15:31:06 -0400814static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
Sean Paule42febf2015-05-07 11:35:29 -0700815 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paulef8f1f92015-04-29 16:05:23 -0400816 hd->ctx = ctx;
817 hd->display = display;
Sean Paulef8f1f92015-04-29 16:05:23 -0400818 hd->enable_vsync_events = false;
819 hd->vsync_sequence = 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500820
Sean Paule42febf2015-05-07 11:35:29 -0700821 int ret = pthread_mutex_init(&hd->flip_lock, NULL);
Sean Paulef8f1f92015-04-29 16:05:23 -0400822 if (ret) {
823 ALOGE("Failed to initialize flip lock %d", ret);
824 return ret;
825 }
Sean Paul814bddb2015-03-03 17:46:19 -0500826
Sean Paulef8f1f92015-04-29 16:05:23 -0400827 ret = pthread_cond_init(&hd->flip_cond, NULL);
828 if (ret) {
829 ALOGE("Failed to intiialize flip condition %d", ret);
830 pthread_mutex_destroy(&hd->flip_lock);
831 return ret;
832 }
Sean Paul814bddb2015-03-03 17:46:19 -0500833
Sean Paulef8f1f92015-04-29 16:05:23 -0400834 ret = sw_sync_timeline_create();
835 if (ret < 0) {
836 ALOGE("Failed to create sw sync timeline %d", ret);
837 pthread_cond_destroy(&hd->flip_cond);
838 pthread_mutex_destroy(&hd->flip_lock);
839 return ret;
840 }
841 hd->timeline_fd = ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500842
Sean Paulef8f1f92015-04-29 16:05:23 -0400843 /*
844 * Initialize timeline_next to 1, because point 0 will be the very first
845 * set operation. Since we increment every time set() is called,
846 * initializing to 0 would cause an off-by-one error where
847 * surfaceflinger would composite on the front buffer.
848 */
849 hd->timeline_next = 1;
Sean Paule147a2a2015-02-22 17:55:43 -0500850
Sean Paulef8f1f92015-04-29 16:05:23 -0400851 ret = hwc_set_initial_config(hd);
852 if (ret) {
853 ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
854 close(hd->timeline_fd);
855 pthread_cond_destroy(&hd->flip_cond);
856 pthread_mutex_destroy(&hd->flip_lock);
857 return ret;
858 }
Sean Paulf1dc1912015-01-24 01:34:31 -0500859
Sean Paulef8f1f92015-04-29 16:05:23 -0400860 ret = hwc_initialize_worker(&hd->set_worker, hwc_set_worker, hd);
861 if (ret) {
862 ALOGE("Failed to create set worker %d\n", ret);
863 close(hd->timeline_fd);
864 pthread_cond_destroy(&hd->flip_cond);
865 pthread_mutex_destroy(&hd->flip_lock);
866 return ret;
867 }
Sean Paul24a26e32015-02-04 10:34:47 -0800868
Sean Paulef8f1f92015-04-29 16:05:23 -0400869 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500870}
871
Sean Paulef8f1f92015-04-29 16:05:23 -0400872static void hwc_free_conn_list(drmModeConnectorPtr *conn_list, int num_conn) {
873 for (int i = 0; i < num_conn; ++i) {
874 if (conn_list[i])
875 drmModeFreeConnector(conn_list[i]);
876 }
877 free(conn_list);
Sean Paule0c4c3d2015-01-20 16:56:04 -0500878}
879
Sean Paulef8f1f92015-04-29 16:05:23 -0400880static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400881 int ret;
882 for (DrmResources::ConnectorIter c = ctx->drm.begin_connectors();
883 c != ctx->drm.end_connectors(); ++c) {
884 ret = hwc_initialize_display(ctx, (*c)->display());
885 if (ret) {
886 ALOGE("Failed to initialize display %d", (*c)->display());
887 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400888 }
889 }
Sean Paulef8f1f92015-04-29 16:05:23 -0400890
891 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500892}
893
Sean Paulef8f1f92015-04-29 16:05:23 -0400894static int hwc_device_open(const struct hw_module_t *module, const char *name,
895 struct hw_device_t **dev) {
896 if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
897 ALOGE("Invalid module name- %s", name);
898 return -EINVAL;
899 }
900
901 struct hwc_context_t *ctx = new hwc_context_t();
902 if (!ctx) {
903 ALOGE("Failed to allocate hwc context");
904 return -ENOMEM;
905 }
906
Sean Paul6a55e9f2015-04-30 15:31:06 -0400907 int ret = ctx->drm.Init();
908 if (ret) {
909 ALOGE("Can't initialize Drm object %d", ret);
910 delete ctx;
911 return ret;
912 }
913
914 ret = hwc_import_init(&ctx->import_ctx);
Sean Paulef8f1f92015-04-29 16:05:23 -0400915 if (ret) {
916 ALOGE("Failed to initialize import context");
917 delete ctx;
918 return ret;
919 }
920
Sean Paulef8f1f92015-04-29 16:05:23 -0400921 ret = hwc_enumerate_displays(ctx);
922 if (ret) {
923 ALOGE("Failed to enumerate displays: %s", strerror(ret));
Sean Paul6a55e9f2015-04-30 15:31:06 -0400924 delete ctx;
925 return ret;
926 }
927
928 ret = hwc_initialize_worker(&ctx->event_worker, hwc_event_worker, ctx);
929 if (ret) {
930 ALOGE("Failed to create event worker %d\n", ret);
Sean Paulef8f1f92015-04-29 16:05:23 -0400931 delete ctx;
932 return ret;
933 }
934
935 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
936 ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
937 ctx->device.common.module = const_cast<hw_module_t *>(module);
938 ctx->device.common.close = hwc_device_close;
939
940 ctx->device.prepare = hwc_prepare;
941 ctx->device.set = hwc_set;
942 ctx->device.eventControl = hwc_event_control;
943 ctx->device.setPowerMode = hwc_set_power_mode;
944 ctx->device.query = hwc_query;
945 ctx->device.registerProcs = hwc_register_procs;
946 ctx->device.getDisplayConfigs = hwc_get_display_configs;
947 ctx->device.getDisplayAttributes = hwc_get_display_attributes;
948 ctx->device.getActiveConfig = hwc_get_active_config;
949 ctx->device.setActiveConfig = hwc_set_active_config;
950 ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
951
952 *dev = &ctx->device.common;
953
954 return 0;
955}
Sean Paul6a55e9f2015-04-30 15:31:06 -0400956}
Sean Paulef8f1f92015-04-29 16:05:23 -0400957
Sean Paul6a55e9f2015-04-30 15:31:06 -0400958static struct hw_module_methods_t hwc_module_methods = {
959 open : android::hwc_device_open
960};
Sean Paule0c4c3d2015-01-20 16:56:04 -0500961
962hwc_module_t HAL_MODULE_INFO_SYM = {
Sean Paulef8f1f92015-04-29 16:05:23 -0400963 common : {
964 tag : HARDWARE_MODULE_TAG,
965 version_major : 1,
966 version_minor : 0,
967 id : HWC_HARDWARE_MODULE_ID,
968 name : "DRM hwcomposer module",
969 author : "The Android Open Source Project",
970 methods : &hwc_module_methods,
971 dso : NULL,
972 reserved : {0},
973 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500974};