OSDN Git Service

drm_hwcomposer: Move SeparateLayers into a member function
[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 ATRACE_TAG ATRACE_TAG_GRAPHICS
18 #define LOG_TAG "hwcomposer-drm"
19
20 #include "drmhwcomposer.h"
21 #include "drmeventlistener.h"
22 #include "drmresources.h"
23 #include "platform.h"
24 #include "virtualcompositorworker.h"
25 #include "vsyncworker.h"
26
27 #include <stdlib.h>
28
29 #include <cinttypes>
30 #include <map>
31 #include <vector>
32 #include <sstream>
33
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <pthread.h>
37 #include <sys/param.h>
38 #include <sys/resource.h>
39 #include <xf86drm.h>
40 #include <xf86drmMode.h>
41
42 #include <cutils/log.h>
43 #include <cutils/properties.h>
44 #include <hardware/hardware.h>
45 #include <hardware/hwcomposer.h>
46 #include <sw_sync.h>
47 #include <sync/sync.h>
48 #include <utils/Trace.h>
49
50 #define UM_PER_INCH 25400
51
52 namespace android {
53
54 class DummySwSyncTimeline {
55  public:
56   int Init() {
57     int ret = timeline_fd_.Set(sw_sync_timeline_create());
58     if (ret < 0)
59       return ret;
60     return 0;
61   }
62
63   UniqueFd CreateDummyFence() {
64     int ret = sw_sync_fence_create(timeline_fd_.get(), "dummy fence",
65                                    timeline_pt_ + 1);
66     if (ret < 0) {
67       ALOGE("Failed to create dummy fence %d", ret);
68       return ret;
69     }
70
71     UniqueFd ret_fd(ret);
72
73     ret = sw_sync_timeline_inc(timeline_fd_.get(), 1);
74     if (ret) {
75       ALOGE("Failed to increment dummy sync timeline %d", ret);
76       return ret;
77     }
78
79     ++timeline_pt_;
80     return ret_fd;
81   }
82
83  private:
84   UniqueFd timeline_fd_;
85   int timeline_pt_ = 0;
86 };
87
88 struct CheckedOutputFd {
89   CheckedOutputFd(int *fd, const char *description,
90                   DummySwSyncTimeline &timeline)
91       : fd_(fd), description_(description), timeline_(timeline) {
92   }
93   CheckedOutputFd(CheckedOutputFd &&rhs)
94       : description_(rhs.description_), timeline_(rhs.timeline_) {
95     std::swap(fd_, rhs.fd_);
96   }
97
98   CheckedOutputFd &operator=(const CheckedOutputFd &rhs) = delete;
99
100   ~CheckedOutputFd() {
101     if (fd_ == NULL)
102       return;
103
104     if (*fd_ >= 0)
105       return;
106
107     *fd_ = timeline_.CreateDummyFence().Release();
108
109     if (*fd_ < 0)
110       ALOGE("Failed to fill %s (%p == %d) before destruction",
111             description_.c_str(), fd_, *fd_);
112   }
113
114  private:
115   int *fd_ = NULL;
116   std::string description_;
117   DummySwSyncTimeline &timeline_;
118 };
119
120 typedef struct hwc_drm_display {
121   struct hwc_context_t *ctx;
122   int display;
123
124   std::vector<uint32_t> config_ids;
125
126   VSyncWorker vsync_worker;
127 } hwc_drm_display_t;
128
129 class DrmHotplugHandler : public DrmEventHandler {
130  public:
131   void Init(DrmResources *drm, const struct hwc_procs *procs) {
132     drm_ = drm;
133     procs_ = procs;
134   }
135
136   void HandleEvent(uint64_t timestamp_us) {
137     for (auto &conn : drm_->connectors()) {
138       drmModeConnection old_state = conn->state();
139
140       conn->UpdateModes();
141
142       drmModeConnection cur_state = conn->state();
143
144       if (cur_state == old_state)
145         continue;
146
147       ALOGI("%s event @%" PRIu64 " for connector %u\n",
148             cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us,
149             conn->id());
150
151       if (cur_state == DRM_MODE_CONNECTED) {
152         // Take the first one, then look for the preferred
153         DrmMode mode = *(conn->modes().begin());
154         for (auto &m : conn->modes()) {
155           if (m.type() & DRM_MODE_TYPE_PREFERRED) {
156             mode = m;
157             break;
158           }
159         }
160         ALOGI("Setting mode %dx%d for connector %d\n", mode.h_display(),
161               mode.v_display(), conn->id());
162         int ret = drm_->SetDisplayActiveMode(conn->display(), mode);
163         if (ret) {
164           ALOGE("Failed to set active config %d", ret);
165           return;
166         }
167       } else {
168         int ret = drm_->SetDpmsMode(conn->display(), DRM_MODE_DPMS_OFF);
169         if (ret) {
170           ALOGE("Failed to set dpms mode off %d", ret);
171           return;
172         }
173       }
174
175       procs_->hotplug(procs_, conn->display(),
176                       cur_state == DRM_MODE_CONNECTED ? 1 : 0);
177     }
178   }
179
180  private:
181   DrmResources *drm_ = NULL;
182   const struct hwc_procs *procs_ = NULL;
183 };
184
185 struct hwc_context_t {
186   // map of display:hwc_drm_display_t
187   typedef std::map<int, hwc_drm_display_t> DisplayMap;
188
189   ~hwc_context_t() {
190     virtual_compositor_worker.Exit();
191   }
192
193   hwc_composer_device_1_t device;
194   hwc_procs_t const *procs = NULL;
195
196   DisplayMap displays;
197   DrmResources drm;
198   std::unique_ptr<Importer> importer;
199   const gralloc_module_t *gralloc;
200   DummySwSyncTimeline dummy_timeline;
201   VirtualCompositorWorker virtual_compositor_worker;
202   DrmHotplugHandler hotplug_handler;
203 };
204
205 static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
206   native_handle_t *new_handle =
207       native_handle_create(handle->numFds, handle->numInts);
208   if (new_handle == NULL)
209     return NULL;
210
211   const int *old_data = handle->data;
212   int *new_data = new_handle->data;
213   for (int i = 0; i < handle->numFds; i++) {
214     *new_data = dup(*old_data);
215     old_data++;
216     new_data++;
217   }
218   memcpy(new_data, old_data, sizeof(int) * handle->numInts);
219
220   return new_handle;
221 }
222
223 static void free_buffer_handle(native_handle_t *handle) {
224   int ret = native_handle_close(handle);
225   if (ret)
226     ALOGE("Failed to close native handle %d", ret);
227   ret = native_handle_delete(handle);
228   if (ret)
229     ALOGE("Failed to delete native handle %d", ret);
230 }
231
232 const hwc_drm_bo *DrmHwcBuffer::operator->() const {
233   if (importer_ == NULL) {
234     ALOGE("Access of non-existent BO");
235     exit(1);
236     return NULL;
237   }
238   return &bo_;
239 }
240
241 void DrmHwcBuffer::Clear() {
242   if (importer_ != NULL) {
243     importer_->ReleaseBuffer(&bo_);
244     importer_ = NULL;
245   }
246 }
247
248 int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) {
249   hwc_drm_bo tmp_bo;
250
251   int ret = importer->ImportBuffer(handle, &tmp_bo);
252   if (ret)
253     return ret;
254
255   if (importer_ != NULL) {
256     importer_->ReleaseBuffer(&bo_);
257   }
258
259   importer_ = importer;
260
261   bo_ = tmp_bo;
262
263   return 0;
264 }
265
266 int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle,
267                                          const gralloc_module_t *gralloc) {
268   native_handle_t *handle_copy = dup_buffer_handle(handle);
269   if (handle_copy == NULL) {
270     ALOGE("Failed to duplicate handle");
271     return -ENOMEM;
272   }
273
274   int ret = gralloc->registerBuffer(gralloc, handle_copy);
275   if (ret) {
276     ALOGE("Failed to register buffer handle %d", ret);
277     free_buffer_handle(handle_copy);
278     return ret;
279   }
280
281   Clear();
282
283   gralloc_ = gralloc;
284   handle_ = handle_copy;
285
286   return 0;
287 }
288
289 DrmHwcNativeHandle::~DrmHwcNativeHandle() {
290   Clear();
291 }
292
293 void DrmHwcNativeHandle::Clear() {
294   if (gralloc_ != NULL && handle_ != NULL) {
295     gralloc_->unregisterBuffer(gralloc_, handle_);
296     free_buffer_handle(handle_);
297     gralloc_ = NULL;
298     handle_ = NULL;
299   }
300 }
301
302 int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
303                                   const gralloc_module_t *gralloc) {
304   sf_handle = sf_layer->handle;
305   alpha = sf_layer->planeAlpha;
306
307   source_crop = DrmHwcRect<float>(
308       sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
309       sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
310   display_frame = DrmHwcRect<int>(
311       sf_layer->displayFrame.left, sf_layer->displayFrame.top,
312       sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
313
314   transform = 0;
315   // 270* and 180* cannot be combined with flips. More specifically, they
316   // already contain both horizontal and vertical flips, so those fields are
317   // redundant in this case. 90* rotation can be combined with either horizontal
318   // flip or vertical flip, so treat it differently
319   if (sf_layer->transform == HWC_TRANSFORM_ROT_270) {
320     transform = DrmHwcTransform::kRotate270;
321   } else if (sf_layer->transform == HWC_TRANSFORM_ROT_180) {
322     transform = DrmHwcTransform::kRotate180;
323   } else {
324     if (sf_layer->transform & HWC_TRANSFORM_FLIP_H)
325       transform |= DrmHwcTransform::kFlipH;
326     if (sf_layer->transform & HWC_TRANSFORM_FLIP_V)
327       transform |= DrmHwcTransform::kFlipV;
328     if (sf_layer->transform & HWC_TRANSFORM_ROT_90)
329       transform |= DrmHwcTransform::kRotate90;
330   }
331
332   switch (sf_layer->blending) {
333     case HWC_BLENDING_NONE:
334       blending = DrmHwcBlending::kNone;
335       break;
336     case HWC_BLENDING_PREMULT:
337       blending = DrmHwcBlending::kPreMult;
338       break;
339     case HWC_BLENDING_COVERAGE:
340       blending = DrmHwcBlending::kCoverage;
341       break;
342     default:
343       ALOGE("Invalid blending in hwc_layer_1_t %d", sf_layer->blending);
344       return -EINVAL;
345   }
346
347   int ret = buffer.ImportBuffer(sf_layer->handle, importer);
348   if (ret)
349     return ret;
350
351   ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
352   if (ret)
353     return ret;
354
355   ret = gralloc->perform(gralloc, GRALLOC_MODULE_PERFORM_GET_USAGE,
356                          handle.get(), &gralloc_buffer_usage);
357   if (ret) {
358     ALOGE("Failed to get usage for buffer %p (%d)", handle.get(), ret);
359     return ret;
360   }
361
362   return 0;
363 }
364
365 static void hwc_dump(struct hwc_composer_device_1 *dev, char *buff,
366                      int buff_len) {
367   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
368   std::ostringstream out;
369
370   ctx->drm.compositor()->Dump(&out);
371   std::string out_str = out.str();
372   strncpy(buff, out_str.c_str(),
373           std::min((size_t)buff_len, out_str.length() + 1));
374   buff[buff_len - 1] = '\0';
375 }
376
377 static bool hwc_skip_layer(const std::pair<int, int> &indices, int i) {
378   return indices.first >= 0 && i >= indices.first && i <= indices.second;
379 }
380
381 static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
382                        hwc_display_contents_1_t **display_contents) {
383   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
384
385   for (int i = 0; i < (int)num_displays; ++i) {
386     if (!display_contents[i])
387       continue;
388
389     bool use_framebuffer_target = false;
390     DrmMode mode;
391     if (i == HWC_DISPLAY_VIRTUAL) {
392       use_framebuffer_target = true;
393     } else {
394       DrmConnector *c = ctx->drm.GetConnectorForDisplay(i);
395       if (!c) {
396         ALOGE("Failed to get DrmConnector for display %d", i);
397         return -ENODEV;
398       }
399       mode = c->active_mode();
400     }
401
402     // Since we can't composite HWC_SKIP_LAYERs by ourselves, we'll let SF
403     // handle all layers in between the first and last skip layers. So find the
404     // outer indices and mark everything in between as HWC_FRAMEBUFFER
405     std::pair<int, int> skip_layer_indices(-1, -1);
406     int num_layers = display_contents[i]->numHwLayers;
407     for (int j = 0; !use_framebuffer_target && j < num_layers; ++j) {
408       hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
409
410       if (!(layer->flags & HWC_SKIP_LAYER))
411         continue;
412
413       if (skip_layer_indices.first == -1)
414         skip_layer_indices.first = j;
415       skip_layer_indices.second = j;
416     }
417
418     for (int j = 0; j < num_layers; ++j) {
419       hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
420
421       if (!use_framebuffer_target && !hwc_skip_layer(skip_layer_indices, j)) {
422         // If the layer is off the screen, don't earmark it for an overlay.
423         // We'll leave it as-is, which effectively just drops it from the frame
424         const hwc_rect_t *frame = &layer->displayFrame;
425         if ((frame->right - frame->left) <= 0 ||
426             (frame->bottom - frame->top) <= 0 ||
427             frame->right <= 0 || frame->bottom <= 0 ||
428             frame->left >= (int)mode.h_display() ||
429             frame->top >= (int)mode.v_display())
430             continue;
431
432         if (layer->compositionType == HWC_FRAMEBUFFER)
433           layer->compositionType = HWC_OVERLAY;
434       } else {
435         switch (layer->compositionType) {
436           case HWC_OVERLAY:
437           case HWC_BACKGROUND:
438           case HWC_SIDEBAND:
439           case HWC_CURSOR_OVERLAY:
440             layer->compositionType = HWC_FRAMEBUFFER;
441             break;
442         }
443       }
444     }
445   }
446
447   return 0;
448 }
449
450 static void hwc_add_layer_to_retire_fence(
451     hwc_layer_1_t *layer, hwc_display_contents_1_t *display_contents) {
452   if (layer->releaseFenceFd < 0)
453     return;
454
455   if (display_contents->retireFenceFd >= 0) {
456     int old_retire_fence = display_contents->retireFenceFd;
457     display_contents->retireFenceFd =
458         sync_merge("dc_retire", old_retire_fence, layer->releaseFenceFd);
459     close(old_retire_fence);
460   } else {
461     display_contents->retireFenceFd = dup(layer->releaseFenceFd);
462   }
463 }
464
465 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
466                    hwc_display_contents_1_t **sf_display_contents) {
467   ATRACE_CALL();
468   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
469   int ret = 0;
470
471   std::vector<CheckedOutputFd> checked_output_fences;
472   std::vector<DrmHwcDisplayContents> displays_contents;
473   std::vector<DrmCompositionDisplayLayersMap> layers_map;
474   std::vector<std::vector<size_t>> layers_indices;
475   displays_contents.reserve(num_displays);
476   // layers_map.reserve(num_displays);
477   layers_indices.reserve(num_displays);
478
479   // Phase one does nothing that would cause errors. Only take ownership of FDs.
480   for (size_t i = 0; i < num_displays; ++i) {
481     hwc_display_contents_1_t *dc = sf_display_contents[i];
482     displays_contents.emplace_back();
483     DrmHwcDisplayContents &display_contents = displays_contents.back();
484     layers_indices.emplace_back();
485     std::vector<size_t> &indices_to_composite = layers_indices.back();
486
487     if (!sf_display_contents[i])
488       continue;
489
490     if (i == HWC_DISPLAY_VIRTUAL) {
491       ctx->virtual_compositor_worker.QueueComposite(dc);
492       continue;
493     }
494
495     std::ostringstream display_index_formatter;
496     display_index_formatter << "retire fence for display " << i;
497     std::string display_fence_description(display_index_formatter.str());
498     checked_output_fences.emplace_back(&dc->retireFenceFd,
499                                        display_fence_description.c_str(),
500                                        ctx->dummy_timeline);
501     display_contents.retire_fence = OutputFd(&dc->retireFenceFd);
502
503     size_t num_dc_layers = dc->numHwLayers;
504     int framebuffer_target_index = -1;
505     for (size_t j = 0; j < num_dc_layers; ++j) {
506       hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
507       if (sf_layer->compositionType == HWC_FRAMEBUFFER_TARGET) {
508         framebuffer_target_index = j;
509         break;
510       }
511     }
512
513     for (size_t j = 0; j < num_dc_layers; ++j) {
514       hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
515
516       display_contents.layers.emplace_back();
517       DrmHwcLayer &layer = display_contents.layers.back();
518
519       // In prepare() we marked all layers FRAMEBUFFER between SKIP_LAYER's.
520       // This means we should insert the FB_TARGET layer in the composition
521       // stack at the location of the first skip layer, and ignore the rest.
522       if (sf_layer->flags & HWC_SKIP_LAYER) {
523         if (framebuffer_target_index < 0)
524           continue;
525         int idx = framebuffer_target_index;
526         framebuffer_target_index = -1;
527         hwc_layer_1_t *fbt_layer = &dc->hwLayers[idx];
528         if (!fbt_layer->handle || (fbt_layer->flags & HWC_SKIP_LAYER)) {
529           ALOGE("Invalid HWC_FRAMEBUFFER_TARGET with HWC_SKIP_LAYER present");
530           continue;
531         }
532         indices_to_composite.push_back(idx);
533         continue;
534       }
535
536       if (sf_layer->compositionType == HWC_OVERLAY)
537         indices_to_composite.push_back(j);
538
539       layer.acquire_fence.Set(sf_layer->acquireFenceFd);
540       sf_layer->acquireFenceFd = -1;
541
542       std::ostringstream layer_fence_formatter;
543       layer_fence_formatter << "release fence for layer " << j << " of display "
544                             << i;
545       std::string layer_fence_description(layer_fence_formatter.str());
546       checked_output_fences.emplace_back(&sf_layer->releaseFenceFd,
547                                          layer_fence_description.c_str(),
548                                          ctx->dummy_timeline);
549       layer.release_fence = OutputFd(&sf_layer->releaseFenceFd);
550     }
551
552     // This is a catch-all in case we get a frame without any overlay layers, or
553     // skip layers, but with a value fb_target layer. This _shouldn't_ happen,
554     // but it's not ruled out by the hwc specification
555     if (indices_to_composite.empty() && framebuffer_target_index >= 0) {
556       hwc_layer_1_t *sf_layer = &dc->hwLayers[framebuffer_target_index];
557       if (!sf_layer->handle || (sf_layer->flags & HWC_SKIP_LAYER)) {
558         ALOGE(
559             "Expected valid layer with HWC_FRAMEBUFFER_TARGET when all "
560             "HWC_OVERLAY layers are skipped.");
561         ret = -EINVAL;
562       }
563       indices_to_composite.push_back(framebuffer_target_index);
564     }
565   }
566
567   if (ret)
568     return ret;
569
570   for (size_t i = 0; i < num_displays; ++i) {
571     hwc_display_contents_1_t *dc = sf_display_contents[i];
572     DrmHwcDisplayContents &display_contents = displays_contents[i];
573     if (!sf_display_contents[i] || i == HWC_DISPLAY_VIRTUAL)
574       continue;
575
576     layers_map.emplace_back();
577     DrmCompositionDisplayLayersMap &map = layers_map.back();
578     map.display = i;
579     map.geometry_changed =
580         (dc->flags & HWC_GEOMETRY_CHANGED) == HWC_GEOMETRY_CHANGED;
581     std::vector<size_t> &indices_to_composite = layers_indices[i];
582     for (size_t j : indices_to_composite) {
583       hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
584
585       DrmHwcLayer &layer = display_contents.layers[j];
586
587       ret = layer.InitFromHwcLayer(sf_layer, ctx->importer.get(), ctx->gralloc);
588       if (ret) {
589         ALOGE("Failed to init composition from layer %d", ret);
590         return ret;
591       }
592       map.layers.emplace_back(std::move(layer));
593     }
594   }
595
596   std::unique_ptr<DrmComposition> composition(
597       ctx->drm.compositor()->CreateComposition(ctx->importer.get()));
598   if (!composition) {
599     ALOGE("Drm composition init failed");
600     return -EINVAL;
601   }
602
603   ret = composition->SetLayers(layers_map.size(), layers_map.data());
604   if (ret) {
605     return -EINVAL;
606   }
607
608   ret = ctx->drm.compositor()->QueueComposition(std::move(composition));
609   if (ret) {
610     return -EINVAL;
611   }
612
613   for (size_t i = 0; i < num_displays; ++i) {
614     hwc_display_contents_1_t *dc = sf_display_contents[i];
615     if (!dc)
616       continue;
617
618     size_t num_dc_layers = dc->numHwLayers;
619     for (size_t j = 0; j < num_dc_layers; ++j) {
620       hwc_layer_1_t *layer = &dc->hwLayers[j];
621       if (layer->flags & HWC_SKIP_LAYER)
622         continue;
623       hwc_add_layer_to_retire_fence(layer, dc);
624     }
625   }
626
627   composition.reset(NULL);
628
629   return ret;
630 }
631
632 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
633                              int event, int enabled) {
634   if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
635     return -EINVAL;
636
637   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
638   hwc_drm_display_t *hd = &ctx->displays[display];
639   return hd->vsync_worker.VSyncControl(enabled);
640 }
641
642 static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
643                               int mode) {
644   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
645
646   uint64_t dpmsValue = 0;
647   switch (mode) {
648     case HWC_POWER_MODE_OFF:
649       dpmsValue = DRM_MODE_DPMS_OFF;
650       break;
651
652     /* We can't support dozing right now, so go full on */
653     case HWC_POWER_MODE_DOZE:
654     case HWC_POWER_MODE_DOZE_SUSPEND:
655     case HWC_POWER_MODE_NORMAL:
656       dpmsValue = DRM_MODE_DPMS_ON;
657       break;
658   };
659   return ctx->drm.SetDpmsMode(display, dpmsValue);
660 }
661
662 static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
663                      int *value) {
664   switch (what) {
665     case HWC_BACKGROUND_LAYER_SUPPORTED:
666       *value = 0; /* TODO: We should do this */
667       break;
668     case HWC_VSYNC_PERIOD:
669       ALOGW("Query for deprecated vsync value, returning 60Hz");
670       *value = 1000 * 1000 * 1000 / 60;
671       break;
672     case HWC_DISPLAY_TYPES_SUPPORTED:
673       *value = HWC_DISPLAY_PRIMARY_BIT | HWC_DISPLAY_EXTERNAL_BIT |
674                HWC_DISPLAY_VIRTUAL_BIT;
675       break;
676   }
677   return 0;
678 }
679
680 static void hwc_register_procs(struct hwc_composer_device_1 *dev,
681                                hwc_procs_t const *procs) {
682   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
683
684   ctx->procs = procs;
685
686   for (std::pair<const int, hwc_drm_display> &display_entry : ctx->displays)
687     display_entry.second.vsync_worker.SetProcs(procs);
688
689   ctx->hotplug_handler.Init(&ctx->drm, procs);
690   ctx->drm.event_listener()->RegisterHotplugHandler(&ctx->hotplug_handler);
691 }
692
693 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
694                                    int display, uint32_t *configs,
695                                    size_t *num_configs) {
696   if (!*num_configs)
697     return 0;
698
699   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
700   hwc_drm_display_t *hd = &ctx->displays[display];
701   hd->config_ids.clear();
702
703   DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
704   if (!connector) {
705     ALOGE("Failed to get connector for display %d", display);
706     return -ENODEV;
707   }
708
709   int ret = connector->UpdateModes();
710   if (ret) {
711     ALOGE("Failed to update display modes %d", ret);
712     return ret;
713   }
714
715   for (const DrmMode &mode : connector->modes()) {
716     size_t idx = hd->config_ids.size();
717     if (idx == *num_configs)
718       break;
719     hd->config_ids.push_back(mode.id());
720     configs[idx] = mode.id();
721   }
722   *num_configs = hd->config_ids.size();
723   return *num_configs == 0 ? -1 : 0;
724 }
725
726 static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
727                                       int display, uint32_t config,
728                                       const uint32_t *attributes,
729                                       int32_t *values) {
730   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
731   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
732   if (!c) {
733     ALOGE("Failed to get DrmConnector for display %d", display);
734     return -ENODEV;
735   }
736   DrmMode mode;
737   for (const DrmMode &conn_mode : c->modes()) {
738     if (conn_mode.id() == config) {
739       mode = conn_mode;
740       break;
741     }
742   }
743   if (mode.id() == 0) {
744     ALOGE("Failed to find active mode for display %d", display);
745     return -ENOENT;
746   }
747
748   uint32_t mm_width = c->mm_width();
749   uint32_t mm_height = c->mm_height();
750   for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
751     switch (attributes[i]) {
752       case HWC_DISPLAY_VSYNC_PERIOD:
753         values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
754         break;
755       case HWC_DISPLAY_WIDTH:
756         values[i] = mode.h_display();
757         break;
758       case HWC_DISPLAY_HEIGHT:
759         values[i] = mode.v_display();
760         break;
761       case HWC_DISPLAY_DPI_X:
762         /* Dots per 1000 inches */
763         values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
764         break;
765       case HWC_DISPLAY_DPI_Y:
766         /* Dots per 1000 inches */
767         values[i] =
768             mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
769         break;
770     }
771   }
772   return 0;
773 }
774
775 static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
776                                  int display) {
777   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
778   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
779   if (!c) {
780     ALOGE("Failed to get DrmConnector for display %d", display);
781     return -ENODEV;
782   }
783
784   DrmMode mode = c->active_mode();
785   hwc_drm_display_t *hd = &ctx->displays[display];
786   for (size_t i = 0; i < hd->config_ids.size(); ++i) {
787     if (hd->config_ids[i] == mode.id())
788       return i;
789   }
790   return -1;
791 }
792
793 static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
794                                  int index) {
795   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
796   hwc_drm_display_t *hd = &ctx->displays[display];
797   if (index >= (int)hd->config_ids.size()) {
798     ALOGE("Invalid config index %d passed in", index);
799     return -EINVAL;
800   }
801
802   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
803   if (!c) {
804     ALOGE("Failed to get connector for display %d", display);
805     return -ENODEV;
806   }
807
808   if (c->state() != DRM_MODE_CONNECTED)
809     return -ENODEV;
810
811   DrmMode mode;
812   for (const DrmMode &conn_mode : c->modes()) {
813     if (conn_mode.id() == hd->config_ids[index]) {
814       mode = conn_mode;
815       break;
816     }
817   }
818   if (mode.id() != hd->config_ids[index]) {
819     ALOGE("Could not find active mode for %d/%d", index, hd->config_ids[index]);
820     return -ENOENT;
821   }
822   int ret = ctx->drm.SetDisplayActiveMode(display, mode);
823   if (ret) {
824     ALOGE("Failed to set active config %d", ret);
825     return ret;
826   }
827   ret = ctx->drm.SetDpmsMode(display, DRM_MODE_DPMS_ON);
828   if (ret) {
829     ALOGE("Failed to set dpms mode on %d", ret);
830     return ret;
831   }
832   return ret;
833 }
834
835 static int hwc_device_close(struct hw_device_t *dev) {
836   struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
837   delete ctx;
838   return 0;
839 }
840
841 /*
842  * TODO: This function sets the active config to the first one in the list. This
843  * should be fixed such that it selects the preferred mode for the display, or
844  * some other, saner, method of choosing the config.
845  */
846 static int hwc_set_initial_config(hwc_drm_display_t *hd) {
847   uint32_t config;
848   size_t num_configs = 1;
849   int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
850                                     &num_configs);
851   if (ret || !num_configs)
852     return 0;
853
854   ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
855   if (ret) {
856     ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
857     return ret;
858   }
859
860   return ret;
861 }
862
863 static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
864   hwc_drm_display_t *hd = &ctx->displays[display];
865   hd->ctx = ctx;
866   hd->display = display;
867
868   int ret = hwc_set_initial_config(hd);
869   if (ret) {
870     ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
871     return ret;
872   }
873
874   ret = hd->vsync_worker.Init(&ctx->drm, display);
875   if (ret) {
876     ALOGE("Failed to create event worker for display %d %d\n", display, ret);
877     return ret;
878   }
879
880   return 0;
881 }
882
883 static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
884   int ret;
885   for (auto &conn : ctx->drm.connectors()) {
886     ret = hwc_initialize_display(ctx, conn->display());
887     if (ret) {
888       ALOGE("Failed to initialize display %d", conn->display());
889       return ret;
890     }
891   }
892
893   ret = ctx->virtual_compositor_worker.Init();
894   if (ret) {
895     ALOGE("Failed to initialize virtual compositor worker");
896     return ret;
897   }
898   return 0;
899 }
900
901 static int hwc_device_open(const struct hw_module_t *module, const char *name,
902                            struct hw_device_t **dev) {
903   if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
904     ALOGE("Invalid module name- %s", name);
905     return -EINVAL;
906   }
907
908   std::unique_ptr<hwc_context_t> ctx(new hwc_context_t());
909   if (!ctx) {
910     ALOGE("Failed to allocate hwc context");
911     return -ENOMEM;
912   }
913
914   int ret = ctx->drm.Init();
915   if (ret) {
916     ALOGE("Can't initialize Drm object %d", ret);
917     return ret;
918   }
919
920   ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
921                       (const hw_module_t **)&ctx->gralloc);
922   if (ret) {
923     ALOGE("Failed to open gralloc module %d", ret);
924     return ret;
925   }
926
927   ret = ctx->dummy_timeline.Init();
928   if (ret) {
929     ALOGE("Failed to create dummy sw sync timeline %d", ret);
930     return ret;
931   }
932
933   ctx->importer.reset(Importer::CreateInstance(&ctx->drm));
934   if (!ctx->importer) {
935     ALOGE("Failed to create importer instance");
936     return ret;
937   }
938
939   ret = hwc_enumerate_displays(ctx.get());
940   if (ret) {
941     ALOGE("Failed to enumerate displays: %s", strerror(ret));
942     return ret;
943   }
944
945   ctx->device.common.tag = HARDWARE_DEVICE_TAG;
946   ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
947   ctx->device.common.module = const_cast<hw_module_t *>(module);
948   ctx->device.common.close = hwc_device_close;
949
950   ctx->device.dump = hwc_dump;
951   ctx->device.prepare = hwc_prepare;
952   ctx->device.set = hwc_set;
953   ctx->device.eventControl = hwc_event_control;
954   ctx->device.setPowerMode = hwc_set_power_mode;
955   ctx->device.query = hwc_query;
956   ctx->device.registerProcs = hwc_register_procs;
957   ctx->device.getDisplayConfigs = hwc_get_display_configs;
958   ctx->device.getDisplayAttributes = hwc_get_display_attributes;
959   ctx->device.getActiveConfig = hwc_get_active_config;
960   ctx->device.setActiveConfig = hwc_set_active_config;
961   ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
962
963   *dev = &ctx->device.common;
964   ctx.release();
965
966   return 0;
967 }
968 }
969
970 static struct hw_module_methods_t hwc_module_methods = {
971   .open = android::hwc_device_open
972 };
973
974 hwc_module_t HAL_MODULE_INFO_SYM = {
975   .common = {
976     .tag = HARDWARE_MODULE_TAG,
977     .version_major = 1,
978     .version_minor = 0,
979     .id = HWC_HARDWARE_MODULE_ID,
980     .name = "DRM hwcomposer module",
981     .author = "The Android Open Source Project",
982     .methods = &hwc_module_methods,
983     .dso = NULL,
984     .reserved = {0},
985   }
986 };