OSDN Git Service

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