OSDN Git Service

drm_hwcomposer: Fix up #include ordering
[android-x86/external-drm_hwcomposer.git] / hwcomposer.cpp
1 /*
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
19 #include "drm_hwcomposer.h"
20 #include "drmresources.h"
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <list>
25 #include <pthread.h>
26 #include <stdlib.h>
27 #include <sys/param.h>
28 #include <sys/resource.h>
29 #include <xf86drm.h>
30 #include <xf86drmMode.h>
31
32 #include <cutils/log.h>
33 #include <cutils/properties.h>
34 #include <hardware/hardware.h>
35 #include <hardware/hwcomposer.h>
36 #include <sw_sync.h>
37 #include <sync/sync.h>
38
39 #define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0]))
40
41 #define MAX_NUM_DISPLAYS 3
42 #define UM_PER_INCH 25400
43
44 namespace android {
45
46 struct hwc_worker {
47   pthread_t thread;
48   pthread_mutex_t lock;
49   pthread_cond_t cond;
50   bool exit;
51 };
52
53 struct hwc_drm_display {
54   struct hwc_context_t *ctx;
55   int display;
56
57   std::vector<uint32_t> config_ids;
58
59   struct hwc_worker set_worker;
60
61   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;
65
66   int timeline_fd;
67   unsigned timeline_next;
68
69   bool enable_vsync_events;
70   unsigned int vsync_sequence;
71 };
72
73 struct hwc_context_t {
74   hwc_composer_device_1_t device;
75
76   hwc_procs_t const *procs;
77   struct hwc_import_context *import_ctx;
78
79   struct hwc_drm_display displays[MAX_NUM_DISPLAYS];
80   int num_displays;
81
82   struct hwc_worker event_worker;
83
84   DrmResources drm;
85 };
86
87 static int hwc_get_drm_display(struct hwc_context_t *ctx, int display,
88                                struct hwc_drm_display **hd) {
89   if (display >= MAX_NUM_DISPLAYS) {
90     ALOGE("Requested display is out-of-bounds %d %d", display,
91           MAX_NUM_DISPLAYS);
92     return -EINVAL;
93   }
94   *hd = &ctx->displays[display];
95   return 0;
96 }
97
98 static int hwc_prepare_layer(hwc_layer_1_t *layer) {
99   /* TODO: We can't handle background right now, defer to sufaceFlinger */
100   if (layer->compositionType == HWC_BACKGROUND) {
101     layer->compositionType = HWC_FRAMEBUFFER;
102     ALOGV("Can't handle background layers yet");
103
104     /* TODO: Support sideband compositions */
105   } else if (layer->compositionType == HWC_SIDEBAND) {
106     layer->compositionType = HWC_FRAMEBUFFER;
107     ALOGV("Can't handle sideband content yet");
108   }
109
110   layer->hints = 0;
111
112   /* TODO: Handle cursor by setting compositionType=HWC_CURSOR_OVERLAY */
113   if (layer->flags & HWC_IS_CURSOR_LAYER) {
114     ALOGV("Can't handle async cursors yet");
115   }
116
117   /* TODO: Handle transformations */
118   if (layer->transform) {
119     ALOGV("Can't handle transformations yet");
120   }
121
122   /* TODO: Handle blending & plane alpha*/
123   if (layer->blending == HWC_BLENDING_PREMULT ||
124       layer->blending == HWC_BLENDING_COVERAGE) {
125     ALOGV("Can't handle blending yet");
126   }
127
128   /* TODO: Handle cropping & scaling */
129
130   return 0;
131 }
132
133 static int hwc_prepare(hwc_composer_device_1_t * /* dev */, size_t num_displays,
134                        hwc_display_contents_1_t **display_contents) {
135   /* TODO: Check flags for HWC_GEOMETRY_CHANGED */
136
137   for (int i = 0; i < (int)num_displays && i < MAX_NUM_DISPLAYS; ++i) {
138     if (!display_contents[i])
139       continue;
140
141     for (int j = 0; j < (int)display_contents[i]->numHwLayers; ++j) {
142       int ret = hwc_prepare_layer(&display_contents[i]->hwLayers[j]);
143       if (ret) {
144         ALOGE("Failed to prepare layer %d:%d", j, i);
145         return ret;
146       }
147     }
148   }
149
150   return 0;
151 }
152
153 static int hwc_queue_vblank_event(struct hwc_drm_display *hd) {
154   DrmCrtc *crtc = hd->ctx->drm.GetCrtcForDisplay(hd->display);
155   if (!crtc) {
156     ALOGE("Failed to get crtc for display");
157     return -ENODEV;
158   }
159
160   drmVBlank vblank;
161   memset(&vblank, 0, sizeof(vblank));
162
163   uint32_t high_crtc = (crtc->pipe() << DRM_VBLANK_HIGH_CRTC_SHIFT);
164   vblank.request.type = (drmVBlankSeqType)(
165       DRM_VBLANK_ABSOLUTE | DRM_VBLANK_NEXTONMISS | DRM_VBLANK_EVENT |
166       (high_crtc & DRM_VBLANK_HIGH_CRTC_MASK));
167   vblank.request.signal = (unsigned long)hd;
168   vblank.request.sequence = hd->vsync_sequence + 1;
169
170   int ret = drmWaitVBlank(hd->ctx->drm.fd(), &vblank);
171   if (ret) {
172     ALOGE("Failed to wait for vblank %d", ret);
173     return ret;
174   }
175
176   return 0;
177 }
178
179 static void hwc_vblank_event_handler(int /* fd */, unsigned int sequence,
180                                      unsigned int tv_sec, unsigned int tv_usec,
181                                      void *user_data) {
182   struct hwc_drm_display *hd = (struct hwc_drm_display *)user_data;
183
184   if (!hd->enable_vsync_events || !hd->ctx->procs->vsync)
185     return;
186
187   /*
188    * Discard duplicate vsync (can happen when enabling vsync events while
189    * already processing vsyncs).
190    */
191   if (sequence <= hd->vsync_sequence)
192     return;
193
194   hd->vsync_sequence = sequence;
195   int ret = hwc_queue_vblank_event(hd);
196   if (ret)
197     ALOGE("Failed to queue vblank event ret=%d", ret);
198
199   int64_t timestamp =
200       (int64_t)tv_sec * 1000 * 1000 * 1000 + (int64_t)tv_usec * 1000;
201   hd->ctx->procs->vsync(hd->ctx->procs, hd->display, timestamp);
202 }
203
204 static void hwc_flip_event_handler(int /* fd */, unsigned int /* sequence */,
205                                    unsigned int /* tv_sec */,
206                                    unsigned int /* tv_usec */,
207                                    void *user_data) {
208   struct hwc_drm_display *hd = (struct hwc_drm_display *)user_data;
209
210   int ret = pthread_mutex_lock(&hd->flip_lock);
211   if (ret) {
212     ALOGE("Failed to lock flip lock ret=%d", ret);
213     return;
214   }
215
216   ret = pthread_cond_signal(&hd->flip_cond);
217   if (ret)
218     ALOGE("Failed to signal flip condition ret=%d", ret);
219
220   ret = pthread_mutex_unlock(&hd->flip_lock);
221   if (ret) {
222     ALOGE("Failed to unlock flip lock ret=%d", ret);
223     return;
224   }
225 }
226
227 static void *hwc_event_worker(void *arg) {
228   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
229
230   struct hwc_context_t *ctx = (struct hwc_context_t *)arg;
231   do {
232     fd_set fds;
233     FD_ZERO(&fds);
234     FD_SET(ctx->drm.fd(), &fds);
235
236     drmEventContext event_context;
237     event_context.version = DRM_EVENT_CONTEXT_VERSION;
238     event_context.page_flip_handler = hwc_flip_event_handler;
239     event_context.vblank_handler = hwc_vblank_event_handler;
240
241     int ret;
242     do {
243       ret = select(ctx->drm.fd() + 1, &fds, NULL, NULL, NULL);
244     } while (ret == -1 && errno == EINTR);
245
246     if (ret != 1) {
247       ALOGE("Failed waiting for drm event\n");
248       continue;
249     }
250
251     drmHandleEvent(ctx->drm.fd(), &event_context);
252   } while (true);
253
254   return NULL;
255 }
256
257 static bool hwc_mode_is_equal(drmModeModeInfoPtr a, drmModeModeInfoPtr b) {
258   return a->clock == b->clock && a->hdisplay == b->hdisplay &&
259          a->hsync_start == b->hsync_start && a->hsync_end == b->hsync_end &&
260          a->htotal == b->htotal && a->hskew == b->hskew &&
261          a->vdisplay == b->vdisplay && a->vsync_start == b->vsync_start &&
262          a->vsync_end == b->vsync_end && a->vtotal == b->vtotal &&
263          a->vscan == b->vscan && a->vrefresh == b->vrefresh &&
264          a->flags == b->flags && a->type == b->type &&
265          !strcmp(a->name, b->name);
266 }
267
268 static int hwc_flip(struct hwc_drm_display *hd, struct hwc_drm_bo *buf) {
269   DrmCrtc *crtc = hd->ctx->drm.GetCrtcForDisplay(hd->display);
270   if (!crtc) {
271     ALOGE("Failed to get crtc for display %d", hd->display);
272     return -ENODEV;
273   }
274
275   DrmConnector *connector = hd->ctx->drm.GetConnectorForDisplay(hd->display);
276   if (!connector) {
277     ALOGE("Failed to get connector for display %d", hd->display);
278     return -ENODEV;
279   }
280
281   int ret;
282   if (crtc->requires_modeset()) {
283     drmModeModeInfo drm_mode;
284     connector->active_mode().ToModeModeInfo(&drm_mode);
285     uint32_t connector_id = connector->id();
286     ret = drmModeSetCrtc(hd->ctx->drm.fd(), crtc->id(), buf->fb_id, 0, 0,
287                          &connector_id, 1, &drm_mode);
288     if (ret) {
289       ALOGE("Modeset failed for crtc %d", crtc->id());
290       return ret;
291     }
292     return 0;
293   }
294
295   ret = drmModePageFlip(hd->ctx->drm.fd(), crtc->id(), buf->fb_id,
296                         DRM_MODE_PAGE_FLIP_EVENT, hd);
297   if (ret) {
298     ALOGE("Failed to flip buffer for crtc %d", crtc->id());
299     return ret;
300   }
301
302   ret = pthread_cond_wait(&hd->flip_cond, &hd->flip_lock);
303   if (ret) {
304     ALOGE("Failed to wait on condition %d", ret);
305     return ret;
306   }
307
308   return 0;
309 }
310
311 static int hwc_wait_and_set(struct hwc_drm_display *hd,
312                             struct hwc_drm_bo *buf) {
313   int ret;
314   if (buf->acquire_fence_fd >= 0) {
315     ret = sync_wait(buf->acquire_fence_fd, -1);
316     close(buf->acquire_fence_fd);
317     buf->acquire_fence_fd = -1;
318     if (ret) {
319       ALOGE("Failed to wait for acquire %d", ret);
320       return ret;
321     }
322   }
323
324   ret = hwc_flip(hd, buf);
325   if (ret) {
326     ALOGE("Failed to perform flip\n");
327     return ret;
328   }
329
330   if (hwc_import_bo_release(hd->ctx->drm.fd(), hd->ctx->import_ctx,
331                             &hd->front)) {
332     struct drm_gem_close args;
333     memset(&args, 0, sizeof(args));
334     for (int i = 0; i < ARRAY_SIZE(hd->front.gem_handles); ++i) {
335       if (!hd->front.gem_handles[i])
336         continue;
337
338       ret = pthread_mutex_lock(&hd->set_worker.lock);
339       if (ret) {
340         ALOGE("Failed to lock set lock in wait_and_set() %d", ret);
341         continue;
342       }
343
344       /* check for duplicate handle in buf_queue */
345       bool found = false;
346       for (std::list<struct hwc_drm_bo>::iterator bi = hd->buf_queue.begin();
347            bi != hd->buf_queue.end(); ++bi)
348         for (int j = 0; j < ARRAY_SIZE(bi->gem_handles); ++j)
349           if (hd->front.gem_handles[i] == bi->gem_handles[j])
350             found = true;
351
352       for (int j = 0; j < ARRAY_SIZE(buf->gem_handles); ++j)
353         if (hd->front.gem_handles[i] == buf->gem_handles[j])
354           found = true;
355
356       if (!found) {
357         args.handle = hd->front.gem_handles[i];
358         drmIoctl(hd->ctx->drm.fd(), DRM_IOCTL_GEM_CLOSE, &args);
359       }
360       if (pthread_mutex_unlock(&hd->set_worker.lock))
361         ALOGE("Failed to unlock set lock in wait_and_set() %d", ret);
362     }
363   }
364
365   hd->front = *buf;
366
367   return ret;
368 }
369
370 static void *hwc_set_worker(void *arg) {
371   setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
372
373   struct hwc_drm_display *hd = (struct hwc_drm_display *)arg;
374   int ret = pthread_mutex_lock(&hd->flip_lock);
375   if (ret) {
376     ALOGE("Failed to lock flip lock ret=%d", ret);
377     return NULL;
378   }
379
380   do {
381     ret = pthread_mutex_lock(&hd->set_worker.lock);
382     if (ret) {
383       ALOGE("Failed to lock set lock %d", ret);
384       return NULL;
385     }
386
387     if (hd->set_worker.exit)
388       break;
389
390     if (hd->buf_queue.empty()) {
391       ret = pthread_cond_wait(&hd->set_worker.cond, &hd->set_worker.lock);
392       if (ret) {
393         ALOGE("Failed to wait on condition %d", ret);
394         break;
395       }
396     }
397
398     struct hwc_drm_bo buf;
399     buf = hd->buf_queue.front();
400     hd->buf_queue.pop_front();
401
402     ret = pthread_mutex_unlock(&hd->set_worker.lock);
403     if (ret) {
404       ALOGE("Failed to unlock set lock %d", ret);
405       return NULL;
406     }
407
408     ret = hwc_wait_and_set(hd, &buf);
409     if (ret)
410       ALOGE("Failed to wait and set %d", ret);
411
412     ret = sw_sync_timeline_inc(hd->timeline_fd, 1);
413     if (ret)
414       ALOGE("Failed to increment sync timeline %d", ret);
415   } while (true);
416
417   ret = pthread_mutex_unlock(&hd->set_worker.lock);
418   if (ret)
419     ALOGE("Failed to unlock set lock while exiting %d", ret);
420
421   ret = pthread_mutex_unlock(&hd->flip_lock);
422   if (ret)
423     ALOGE("Failed to unlock flip lock ret=%d", ret);
424
425   return NULL;
426 }
427
428 static void hwc_close_fences(hwc_display_contents_1_t *display_contents) {
429   for (int i = 0; i < (int)display_contents->numHwLayers; ++i) {
430     hwc_layer_1_t *layer = &display_contents->hwLayers[i];
431     if (layer->acquireFenceFd >= 0) {
432       close(layer->acquireFenceFd);
433       layer->acquireFenceFd = -1;
434     }
435   }
436   if (display_contents->outbufAcquireFenceFd >= 0) {
437     close(display_contents->outbufAcquireFenceFd);
438     display_contents->outbufAcquireFenceFd = -1;
439   }
440 }
441
442 static int hwc_set_display(hwc_context_t *ctx, int display,
443                            hwc_display_contents_1_t *display_contents) {
444   struct hwc_drm_display *hd = NULL;
445   int ret = hwc_get_drm_display(ctx, display, &hd);
446   if (ret) {
447     hwc_close_fences(display_contents);
448     return ret;
449   }
450
451   DrmCrtc *crtc = hd->ctx->drm.GetCrtcForDisplay(display);
452   if (!crtc) {
453     ALOGE("There is no active crtc for display %d", display);
454     hwc_close_fences(display_contents);
455     return -ENOENT;
456   }
457
458   /*
459    * TODO: We can only support one hw layer atm, so choose either the
460    * first one or the framebuffer target.
461    */
462   hwc_layer_1_t *layer = NULL;
463   if (!display_contents->numHwLayers) {
464     return 0;
465   } else if (display_contents->numHwLayers == 1) {
466     layer = &display_contents->hwLayers[0];
467   } else {
468     int i;
469     for (i = 0; i < (int)display_contents->numHwLayers; ++i) {
470       layer = &display_contents->hwLayers[i];
471       if (layer->compositionType == HWC_FRAMEBUFFER_TARGET)
472         break;
473     }
474     if (i == (int)display_contents->numHwLayers) {
475       ALOGE("Could not find a suitable layer for display %d", display);
476     }
477   }
478
479   ret = pthread_mutex_lock(&hd->set_worker.lock);
480   if (ret) {
481     ALOGE("Failed to lock set lock in set() %d", ret);
482     hwc_close_fences(display_contents);
483     return ret;
484   }
485
486   struct hwc_drm_bo buf;
487   memset(&buf, 0, sizeof(buf));
488   ret =
489       hwc_import_bo_create(ctx->drm.fd(), ctx->import_ctx, layer->handle, &buf);
490   if (ret) {
491     ALOGE("Failed to import handle to drm bo %d", ret);
492     hwc_close_fences(display_contents);
493     return ret;
494   }
495   buf.acquire_fence_fd = layer->acquireFenceFd;
496   layer->acquireFenceFd = -1;
497
498   /*
499    * TODO: Retire and release can use the same sync point here b/c hwc is
500    * restricted to one layer. Once that is no longer true, this will need
501    * to change
502    */
503   ++hd->timeline_next;
504   display_contents->retireFenceFd = sw_sync_fence_create(
505       hd->timeline_fd, "drm_hwc_retire", hd->timeline_next);
506   layer->releaseFenceFd = sw_sync_fence_create(
507       hd->timeline_fd, "drm_hwc_release", hd->timeline_next);
508   hd->buf_queue.push_back(buf);
509
510   ret = pthread_cond_signal(&hd->set_worker.cond);
511   if (ret)
512     ALOGE("Failed to signal set worker %d", ret);
513
514   if (pthread_mutex_unlock(&hd->set_worker.lock))
515     ALOGE("Failed to unlock set lock in set()");
516
517   hwc_close_fences(display_contents);
518   return ret;
519 }
520
521 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
522                    hwc_display_contents_1_t **display_contents) {
523   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
524
525   int ret = 0;
526   for (int i = 0; i < (int)num_displays && i < MAX_NUM_DISPLAYS; ++i) {
527     if (display_contents[i])
528       ret = hwc_set_display(ctx, i, display_contents[i]);
529   }
530
531   return ret;
532 }
533
534 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
535                              int event, int enabled) {
536   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
537   struct hwc_drm_display *hd = NULL;
538   int ret = hwc_get_drm_display(ctx, display, &hd);
539   if (ret)
540     return ret;
541
542   if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
543     return -EINVAL;
544
545   DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(display);
546   if (!crtc) {
547     ALOGD("Can't service events for display %d, no crtc", display);
548     return -EINVAL;
549   }
550
551   hd->enable_vsync_events = !!enabled;
552
553   if (!hd->enable_vsync_events)
554     return 0;
555
556   /*
557    * Note that it's possible that the event worker is already waiting for
558    * a vsync, and this will be a duplicate request. In that event, we'll
559    * end up firing the event handler twice, and it will discard the second
560    * event. Not ideal, but not worth introducing a bunch of additional
561    * logic/locks/state for.
562    */
563   ret = hwc_queue_vblank_event(hd);
564   if (ret) {
565     ALOGE("Failed to queue vblank event ret=%d", ret);
566     return ret;
567   }
568
569   return 0;
570 }
571
572 static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
573                               int mode) {
574   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
575
576   uint64_t dpmsValue = 0;
577   switch (mode) {
578     case HWC_POWER_MODE_OFF:
579       dpmsValue = DRM_MODE_DPMS_OFF;
580       break;
581
582     /* We can't support dozing right now, so go full on */
583     case HWC_POWER_MODE_DOZE:
584     case HWC_POWER_MODE_DOZE_SUSPEND:
585     case HWC_POWER_MODE_NORMAL:
586       dpmsValue = DRM_MODE_DPMS_ON;
587       break;
588   };
589   return ctx->drm.SetDpmsMode(display, dpmsValue);
590 }
591
592 static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
593                      int *value) {
594   switch (what) {
595     case HWC_BACKGROUND_LAYER_SUPPORTED:
596       *value = 0; /* TODO: We should do this */
597       break;
598     case HWC_VSYNC_PERIOD:
599       ALOGW("Query for deprecated vsync value, returning 60Hz");
600       *value = 1000 * 1000 * 1000 / 60;
601       break;
602     case HWC_DISPLAY_TYPES_SUPPORTED:
603       *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
604       break;
605   }
606   return 0;
607 }
608
609 static void hwc_register_procs(struct hwc_composer_device_1 *dev,
610                                hwc_procs_t const *procs) {
611   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
612
613   ctx->procs = procs;
614 }
615
616 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
617                                    int display, uint32_t *configs,
618                                    size_t *num_configs) {
619   if (!*num_configs)
620     return 0;
621
622   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
623   struct hwc_drm_display *hd = NULL;
624   int ret = hwc_get_drm_display(ctx, display, &hd);
625   if (ret)
626     return ret;
627
628   hd->config_ids.clear();
629
630   DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
631   if (!connector) {
632     ALOGE("Failed to get connector for display %d", display);
633     return -ENODEV;
634   }
635
636   ret = connector->UpdateModes();
637   if (ret) {
638     ALOGE("Failed to update display modes %d", ret);
639     return ret;
640   }
641
642   for (DrmConnector::ModeIter iter = connector->begin_modes();
643        iter != connector->end_modes(); ++iter) {
644     size_t idx = hd->config_ids.size();
645     if (idx == *num_configs)
646       break;
647     hd->config_ids.push_back(iter->id());
648     configs[idx] = iter->id();
649   }
650   *num_configs = hd->config_ids.size();
651   return *num_configs == 0 ? -1 : 0;
652 }
653
654 static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
655                                       int display, uint32_t config,
656                                       const uint32_t *attributes,
657                                       int32_t *values) {
658   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
659   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
660   if (!c) {
661     ALOGE("Failed to get DrmConnector for display %d", display);
662     return -ENODEV;
663   }
664   DrmMode mode;
665   for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
666        ++iter) {
667     if (iter->id() == config) {
668       mode = *iter;
669       break;
670     }
671   }
672   if (mode.id() == 0) {
673     ALOGE("Failed to find active mode for display %d", display);
674     return -ENOENT;
675   }
676
677   uint32_t mm_width = c->mm_width();
678   uint32_t mm_height = c->mm_height();
679   for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
680     switch (attributes[i]) {
681       case HWC_DISPLAY_VSYNC_PERIOD:
682         values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
683         break;
684       case HWC_DISPLAY_WIDTH:
685         values[i] = mode.h_display();
686         break;
687       case HWC_DISPLAY_HEIGHT:
688         values[i] = mode.v_display();
689         break;
690       case HWC_DISPLAY_DPI_X:
691         /* Dots per 1000 inches */
692         values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
693         break;
694       case HWC_DISPLAY_DPI_Y:
695         /* Dots per 1000 inches */
696         values[i] =
697             mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
698         break;
699     }
700   }
701   return 0;
702 }
703
704 static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
705                                  int display) {
706   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
707   struct hwc_drm_display *hd = NULL;
708   int ret = hwc_get_drm_display(ctx, display, &hd);
709   if (ret)
710     return ret;
711
712   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
713   if (!c) {
714     ALOGE("Failed to get DrmConnector for display %d", display);
715     return -ENODEV;
716   }
717
718   DrmMode mode = c->active_mode();
719   for (size_t i = 0; i < hd->config_ids.size(); ++i) {
720     if (hd->config_ids[i] == mode.id())
721       return i;
722   }
723   return -1;
724 }
725
726 static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
727                                  int index) {
728   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
729   struct hwc_drm_display *hd = NULL;
730   int ret = hwc_get_drm_display(ctx, display, &hd);
731   if (ret)
732     return ret;
733
734   if (index >= (int)hd->config_ids.size()) {
735     ALOGE("Invalid config index %d passed in", index);
736     return -EINVAL;
737   }
738
739   ret =
740       ctx->drm.SetDisplayActiveMode(display, hd->config_ids[index]);
741   if (ret) {
742     ALOGE("Failed to set config for display %d", display);
743     return ret;
744   }
745
746   return ret;
747 }
748
749 static int hwc_destroy_worker(struct hwc_worker *worker) {
750   int ret = pthread_mutex_lock(&worker->lock);
751   if (ret) {
752     ALOGE("Failed to lock in destroy() %d", ret);
753     return ret;
754   }
755
756   worker->exit = true;
757
758   ret |= pthread_cond_signal(&worker->cond);
759   if (ret)
760     ALOGE("Failed to signal cond in destroy() %d", ret);
761
762   ret |= pthread_mutex_unlock(&worker->lock);
763   if (ret)
764     ALOGE("Failed to unlock in destroy() %d", ret);
765
766   ret |= pthread_join(worker->thread, NULL);
767   if (ret && ret != ESRCH)
768     ALOGE("Failed to join thread in destroy() %d", ret);
769
770   return ret;
771 }
772
773 static void hwc_destroy_display(struct hwc_drm_display *hd) {
774   if (hwc_destroy_worker(&hd->set_worker))
775     ALOGE("Destroy set worker failed");
776 }
777
778 static int hwc_device_close(struct hw_device_t *dev) {
779   struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
780
781   for (int i = 0; i < MAX_NUM_DISPLAYS; ++i)
782     hwc_destroy_display(&ctx->displays[i]);
783
784   if (hwc_destroy_worker(&ctx->event_worker))
785     ALOGE("Destroy event worker failed");
786
787   int ret = hwc_import_destroy(ctx->import_ctx);
788   if (ret)
789     ALOGE("Could not destroy import %d", ret);
790
791   delete ctx;
792
793   return 0;
794 }
795
796 static int hwc_initialize_worker(struct hwc_worker *worker,
797                                  void *(*routine)(void *), void *arg) {
798   int ret = pthread_cond_init(&worker->cond, NULL);
799   if (ret) {
800     ALOGE("Failed to create worker condition %d", ret);
801     return ret;
802   }
803
804   ret = pthread_mutex_init(&worker->lock, NULL);
805   if (ret) {
806     ALOGE("Failed to initialize worker lock %d", ret);
807     pthread_cond_destroy(&worker->cond);
808     return ret;
809   }
810
811   worker->exit = false;
812
813   ret = pthread_create(&worker->thread, NULL, routine, arg);
814   if (ret) {
815     ALOGE("Could not create worker thread %d", ret);
816     pthread_mutex_destroy(&worker->lock);
817     pthread_cond_destroy(&worker->cond);
818     return ret;
819   }
820   return 0;
821 }
822
823 /*
824  * TODO: This function sets the active config to the first one in the list. This
825  * should be fixed such that it selects the preferred mode for the display, or
826  * some other, saner, method of choosing the config.
827  */
828 static int hwc_set_initial_config(struct hwc_drm_display *hd) {
829   uint32_t config;
830   size_t num_configs = 1;
831   int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
832                                     &num_configs);
833   if (ret || !num_configs)
834     return 0;
835
836   ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
837   if (ret) {
838     ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
839     return ret;
840   }
841
842   return ret;
843 }
844
845 static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
846   struct hwc_drm_display *hd = NULL;
847   int ret = hwc_get_drm_display(ctx, display, &hd);
848   if (ret)
849     return ret;
850
851   hd->ctx = ctx;
852   hd->display = display;
853   hd->enable_vsync_events = false;
854   hd->vsync_sequence = 0;
855
856   ret = pthread_mutex_init(&hd->flip_lock, NULL);
857   if (ret) {
858     ALOGE("Failed to initialize flip lock %d", ret);
859     return ret;
860   }
861
862   ret = pthread_cond_init(&hd->flip_cond, NULL);
863   if (ret) {
864     ALOGE("Failed to intiialize flip condition %d", ret);
865     pthread_mutex_destroy(&hd->flip_lock);
866     return ret;
867   }
868
869   ret = sw_sync_timeline_create();
870   if (ret < 0) {
871     ALOGE("Failed to create sw sync timeline %d", ret);
872     pthread_cond_destroy(&hd->flip_cond);
873     pthread_mutex_destroy(&hd->flip_lock);
874     return ret;
875   }
876   hd->timeline_fd = ret;
877
878   /*
879    * Initialize timeline_next to 1, because point 0 will be the very first
880    * set operation. Since we increment every time set() is called,
881    * initializing to 0 would cause an off-by-one error where
882    * surfaceflinger would composite on the front buffer.
883    */
884   hd->timeline_next = 1;
885
886   ret = hwc_set_initial_config(hd);
887   if (ret) {
888     ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
889     close(hd->timeline_fd);
890     pthread_cond_destroy(&hd->flip_cond);
891     pthread_mutex_destroy(&hd->flip_lock);
892     return ret;
893   }
894
895   ret = hwc_initialize_worker(&hd->set_worker, hwc_set_worker, hd);
896   if (ret) {
897     ALOGE("Failed to create set worker %d\n", ret);
898     close(hd->timeline_fd);
899     pthread_cond_destroy(&hd->flip_cond);
900     pthread_mutex_destroy(&hd->flip_lock);
901     return ret;
902   }
903
904   return 0;
905 }
906
907 static void hwc_free_conn_list(drmModeConnectorPtr *conn_list, int num_conn) {
908   for (int i = 0; i < num_conn; ++i) {
909     if (conn_list[i])
910       drmModeFreeConnector(conn_list[i]);
911   }
912   free(conn_list);
913 }
914
915 static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
916   int ret;
917   for (DrmResources::ConnectorIter c = ctx->drm.begin_connectors();
918        c != ctx->drm.end_connectors(); ++c) {
919     ret = hwc_initialize_display(ctx, (*c)->display());
920     if (ret) {
921       ALOGE("Failed to initialize display %d", (*c)->display());
922       return ret;
923     }
924   }
925
926   return 0;
927 }
928
929 static int hwc_device_open(const struct hw_module_t *module, const char *name,
930                            struct hw_device_t **dev) {
931   if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
932     ALOGE("Invalid module name- %s", name);
933     return -EINVAL;
934   }
935
936   struct hwc_context_t *ctx = new hwc_context_t();
937   if (!ctx) {
938     ALOGE("Failed to allocate hwc context");
939     return -ENOMEM;
940   }
941
942   int ret = ctx->drm.Init();
943   if (ret) {
944     ALOGE("Can't initialize Drm object %d", ret);
945     delete ctx;
946     return ret;
947   }
948
949   ret = hwc_import_init(&ctx->import_ctx);
950   if (ret) {
951     ALOGE("Failed to initialize import context");
952     delete ctx;
953     return ret;
954   }
955
956   ret = hwc_enumerate_displays(ctx);
957   if (ret) {
958     ALOGE("Failed to enumerate displays: %s", strerror(ret));
959     delete ctx;
960     return ret;
961   }
962
963   ret = hwc_initialize_worker(&ctx->event_worker, hwc_event_worker, ctx);
964   if (ret) {
965     ALOGE("Failed to create event worker %d\n", ret);
966     delete ctx;
967     return ret;
968   }
969
970   ctx->device.common.tag = HARDWARE_DEVICE_TAG;
971   ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
972   ctx->device.common.module = const_cast<hw_module_t *>(module);
973   ctx->device.common.close = hwc_device_close;
974
975   ctx->device.prepare = hwc_prepare;
976   ctx->device.set = hwc_set;
977   ctx->device.eventControl = hwc_event_control;
978   ctx->device.setPowerMode = hwc_set_power_mode;
979   ctx->device.query = hwc_query;
980   ctx->device.registerProcs = hwc_register_procs;
981   ctx->device.getDisplayConfigs = hwc_get_display_configs;
982   ctx->device.getDisplayAttributes = hwc_get_display_attributes;
983   ctx->device.getActiveConfig = hwc_get_active_config;
984   ctx->device.setActiveConfig = hwc_set_active_config;
985   ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
986
987   *dev = &ctx->device.common;
988
989   return 0;
990 }
991 }
992
993 static struct hw_module_methods_t hwc_module_methods = {
994   open : android::hwc_device_open
995 };
996
997 hwc_module_t HAL_MODULE_INFO_SYM = {
998   common : {
999     tag : HARDWARE_MODULE_TAG,
1000     version_major : 1,
1001     version_minor : 0,
1002     id : HWC_HARDWARE_MODULE_ID,
1003     name : "DRM hwcomposer module",
1004     author : "The Android Open Source Project",
1005     methods : &hwc_module_methods,
1006     dso : NULL,
1007     reserved : {0},
1008   }
1009 };