OSDN Git Service

drm_hwcomposer: integrate GLCompositor with hwcomposer
[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 #include "gl_compositor.h"
22 #include "importer.h"
23 #include "vsyncworker.h"
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <list>
28 #include <map>
29 #include <pthread.h>
30 #include <stdlib.h>
31 #include <sys/param.h>
32 #include <sys/resource.h>
33 #include <xf86drm.h>
34 #include <xf86drmMode.h>
35
36 #include <cutils/log.h>
37 #include <cutils/properties.h>
38 #include <hardware/hardware.h>
39 #include <hardware/hwcomposer.h>
40 #include <sw_sync.h>
41 #include <sync/sync.h>
42 #include <ui/GraphicBuffer.h>
43 #include <ui/PixelFormat.h>
44
45 #define UM_PER_INCH 25400
46 #define HWC_FB_BUFFERS 2
47
48 namespace android {
49
50 struct hwc_drm_display_framebuffer {
51   hwc_drm_display_framebuffer() : release_fence_fd_(-1) {
52   }
53
54   ~hwc_drm_display_framebuffer() {
55     if (release_fence_fd() >= 0)
56       close(release_fence_fd());
57   }
58
59   bool is_valid() {
60     return buffer_ != NULL;
61   }
62
63   sp<GraphicBuffer> buffer() {
64     return buffer_;
65   }
66
67   int release_fence_fd() {
68     return release_fence_fd_;
69   }
70
71   void set_release_fence_fd(int fd) {
72     if (release_fence_fd_ >= 0)
73       close(release_fence_fd_);
74     release_fence_fd_ = fd;
75   }
76
77   bool Allocate(uint32_t w, uint32_t h) {
78     if (is_valid()) {
79       if (buffer_->getWidth() == w && buffer_->getHeight() == h)
80         return true;
81
82       if (release_fence_fd_ >= 0) {
83         if (sync_wait(release_fence_fd_, -1) != 0) {
84           return false;
85         }
86       }
87       Clear();
88     }
89     buffer_ = new GraphicBuffer(w, h, android::PIXEL_FORMAT_RGBA_8888,
90                                 GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER |
91                                     GRALLOC_USAGE_HW_COMPOSER);
92     release_fence_fd_ = -1;
93     return is_valid();
94   }
95
96   void Clear() {
97     if (!is_valid())
98       return;
99
100     if (release_fence_fd_ >= 0) {
101       close(release_fence_fd_);
102       release_fence_fd_ = -1;
103     }
104
105     buffer_.clear();
106   }
107
108   int WaitReleased(int timeout_milliseconds) {
109     if (!is_valid())
110       return 0;
111     if (release_fence_fd_ < 0)
112       return 0;
113
114     int ret = sync_wait(release_fence_fd_, timeout_milliseconds);
115     return ret;
116   }
117
118  private:
119   sp<GraphicBuffer> buffer_;
120   int release_fence_fd_;
121 };
122
123
124 typedef struct hwc_drm_display {
125   struct hwc_context_t *ctx;
126   int display;
127
128   std::vector<uint32_t> config_ids;
129
130   VSyncWorker vsync_worker;
131
132   hwc_drm_display_framebuffer fb_chain[HWC_FB_BUFFERS];
133   int fb_idx;
134 } hwc_drm_display_t;
135
136 struct hwc_context_t {
137   // map of display:hwc_drm_display_t
138   typedef std::map<int, hwc_drm_display_t> DisplayMap;
139   typedef DisplayMap::iterator DisplayMapIter;
140
141   hwc_context_t() : procs(NULL), importer(NULL) {
142   }
143
144   ~hwc_context_t() {
145     delete importer;
146   }
147
148   hwc_composer_device_1_t device;
149   hwc_procs_t const *procs;
150
151   DisplayMap displays;
152   DrmResources drm;
153   Importer *importer;
154   GLCompositor pre_compositor;
155 };
156
157 static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
158                        hwc_display_contents_1_t **display_contents) {
159   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
160   for (int i = 0; i < (int)num_displays; ++i) {
161     if (!display_contents[i])
162       continue;
163
164     DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
165     if (!crtc) {
166       ALOGE("No crtc for display %d", i);
167       return -ENODEV;
168     }
169
170     int num_layers = display_contents[i]->numHwLayers;
171     for (int j = 0; j < num_layers; j++) {
172       hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
173
174       if (crtc->requires_modeset()) {
175         if (layer->compositionType == HWC_OVERLAY)
176           layer->compositionType = HWC_FRAMEBUFFER;
177       } else {
178         if (layer->compositionType == HWC_FRAMEBUFFER)
179           layer->compositionType = HWC_OVERLAY;
180       }
181     }
182   }
183
184   return 0;
185 }
186
187 static void hwc_set_cleanup(size_t num_displays,
188                             hwc_display_contents_1_t **display_contents,
189                             Composition *composition) {
190   for (int i = 0; i < (int)num_displays; ++i) {
191     if (!display_contents[i])
192       continue;
193
194     hwc_display_contents_1_t *dc = display_contents[i];
195     for (size_t j = 0; j < dc->numHwLayers; ++j) {
196       hwc_layer_1_t *layer = &dc->hwLayers[j];
197       if (layer->acquireFenceFd >= 0) {
198         close(layer->acquireFenceFd);
199         layer->acquireFenceFd = -1;
200       }
201     }
202     if (dc->outbufAcquireFenceFd >= 0) {
203       close(dc->outbufAcquireFenceFd);
204       dc->outbufAcquireFenceFd = -1;
205     }
206   }
207
208   delete composition;
209 }
210
211 static int hwc_add_layer(int display, hwc_context_t *ctx, hwc_layer_1_t *layer,
212                          Composition *composition) {
213   hwc_drm_bo_t bo;
214   int ret = ctx->importer->ImportBuffer(layer->handle, &bo);
215   if (ret) {
216     ALOGE("Failed to import handle to bo %d", ret);
217     return ret;
218   }
219
220   ret = composition->AddLayer(display, layer, &bo);
221   if (!ret)
222     return 0;
223
224   int destroy_ret = ctx->importer->ReleaseBuffer(&bo);
225   if (destroy_ret)
226     ALOGE("Failed to destroy buffer %d", destroy_ret);
227
228   return ret;
229 }
230
231 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
232                    hwc_display_contents_1_t **display_contents) {
233   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
234   Composition *composition =
235       ctx->drm.compositor()->CreateComposition(ctx->importer);
236   if (!composition) {
237     ALOGE("Drm composition init failed");
238     hwc_set_cleanup(num_displays, display_contents, NULL);
239     return -EINVAL;
240   }
241
242   int ret;
243   for (int i = 0; i < (int)num_displays; ++i) {
244     if (!display_contents[i])
245       continue;
246
247     DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
248     if (!crtc) {
249       ALOGE("No crtc for display %d", i);
250       hwc_set_cleanup(num_displays, display_contents, composition);
251       return -ENODEV;
252     }
253     bool use_target = false;
254     if (crtc->requires_modeset()) {
255       use_target = true;
256     }
257
258     hwc_display_contents_1_t *dc = display_contents[i];
259     int j;
260     unsigned num_layers = 0;
261     unsigned num_dc_layers = dc->numHwLayers;
262     for (j = 0; j < (int)num_dc_layers; ++j) {
263       hwc_layer_1_t *layer = &dc->hwLayers[j];
264       if (layer->flags & HWC_SKIP_LAYER)
265         continue;
266       if ((use_target && layer->compositionType == HWC_FRAMEBUFFER_TARGET) ||
267           layer->compositionType == HWC_OVERLAY) {
268         num_layers++;
269       }
270     }
271
272     unsigned num_planes = composition->GetRemainingLayers(i, num_layers);
273     bool use_pre_compositor = false;
274
275     if (!use_target && num_layers > num_planes) {
276       use_pre_compositor = true;
277       // Reserve one of the planes for the result of the pre compositor.
278       num_planes--;
279     }
280
281     for (j = 0; num_planes && j < (int)num_dc_layers; ++j) {
282       hwc_layer_1_t *layer = &dc->hwLayers[j];
283       if (layer->flags & HWC_SKIP_LAYER)
284         continue;
285       if (use_target) {
286         if (layer->compositionType != HWC_FRAMEBUFFER_TARGET)
287           continue;
288       } else {
289         if (layer->compositionType != HWC_OVERLAY)
290           continue;
291       }
292
293       ret = hwc_add_layer(i, ctx, layer, composition);
294       if (ret) {
295         ALOGE("Add layer failed %d", ret);
296         hwc_set_cleanup(num_displays, display_contents, composition);
297         return ret;
298       }
299       --num_planes;
300     }
301
302     int last_comp_layer = j;
303
304     if (use_pre_compositor) {
305       hwc_drm_display_t *hd = &ctx->displays[i];
306       struct hwc_drm_display_framebuffer *fb = &hd->fb_chain[hd->fb_idx];
307       ret = fb->WaitReleased(-1);
308       if (ret) {
309         ALOGE("Failed to wait for framebuffer %d", ret);
310         hwc_set_cleanup(num_displays, display_contents, composition);
311         return ret;
312       }
313
314       DrmConnector *connector = ctx->drm.GetConnectorForDisplay(i);
315       if (!connector) {
316         ALOGE("No connector for display %d", i);
317         hwc_set_cleanup(num_displays, display_contents, composition);
318         return -ENODEV;
319       }
320
321       const DrmMode &mode = connector->active_mode();
322       if (!fb->Allocate(mode.h_display(), mode.v_display())) {
323         ALOGE("Failed to allocate framebuffer with size %dx%d",
324               mode.h_display(), mode.v_display());
325         hwc_set_cleanup(num_displays, display_contents, composition);
326         return -EINVAL;
327       }
328
329       sp<GraphicBuffer> fb_buffer = fb->buffer();
330       if (fb_buffer == NULL) {
331         ALOGE("Framebuffer is NULL");
332         hwc_set_cleanup(num_displays, display_contents, composition);
333         return -EINVAL;
334       }
335
336       Targeting *targeting = ctx->pre_compositor.targeting();
337       if (targeting == NULL) {
338         ALOGE("Pre-compositor does not support targeting");
339         hwc_set_cleanup(num_displays, display_contents, composition);
340         return -EINVAL;
341       }
342
343       int target = targeting->CreateTarget(fb_buffer);
344       targeting->SetTarget(target);
345
346       Composition *pre_composition = ctx->pre_compositor.CreateComposition(ctx->importer);
347       if (pre_composition == NULL) {
348         ALOGE("Failed to create pre-composition");
349         targeting->ForgetTarget(target);
350         hwc_set_cleanup(num_displays, display_contents, composition);
351         return -EINVAL;
352       }
353
354       for (j = last_comp_layer; j < (int)num_dc_layers; ++j) {
355         hwc_layer_1_t *layer = &dc->hwLayers[j];
356         if (layer->flags & HWC_SKIP_LAYER)
357           continue;
358         if (layer->compositionType != HWC_OVERLAY)
359           continue;
360         ret = hwc_add_layer(i, ctx, layer, pre_composition);
361         if (ret) {
362           ALOGE("Add layer failed %d", ret);
363           delete pre_composition;
364           targeting->ForgetTarget(target);
365           hwc_set_cleanup(num_displays, display_contents, composition);
366           return ret;
367         }
368       }
369
370       ret = ctx->pre_compositor.QueueComposition(pre_composition);
371       pre_composition = NULL;
372
373       targeting->ForgetTarget(target);
374       if (ret < 0 && ret != -EALREADY) {
375         ALOGE("Pre-composition failed %d", ret);
376         hwc_set_cleanup(num_displays, display_contents, composition);
377         return ret;
378       }
379
380       for (j = last_comp_layer; j < (int)num_dc_layers; ++j) {
381         hwc_layer_1_t *layer = &dc->hwLayers[j];
382         if (layer->flags & HWC_SKIP_LAYER)
383           continue;
384         if (layer->compositionType != HWC_OVERLAY)
385           continue;
386         layer->acquireFenceFd = -1;
387       }
388
389       hwc_layer_1_t composite_layer;
390       hwc_rect_t visible_rect;
391       memset(&composite_layer, 0, sizeof(composite_layer));
392       memset(&visible_rect, 0, sizeof(visible_rect));
393
394       composite_layer.compositionType = HWC_OVERLAY;
395       composite_layer.handle = fb_buffer->getNativeBuffer()->handle;
396       composite_layer.sourceCropf.right = composite_layer.displayFrame.right =
397           visible_rect.right = fb_buffer->getWidth();
398       composite_layer.sourceCropf.bottom = composite_layer.displayFrame.bottom =
399           visible_rect.bottom = fb_buffer->getHeight();
400       composite_layer.visibleRegionScreen.numRects = 1;
401       composite_layer.visibleRegionScreen.rects = &visible_rect;
402       composite_layer.acquireFenceFd = ret == -EALREADY ? -1 : ret;
403       // A known invalid fd in case AddLayer does not modify this field.
404       composite_layer.releaseFenceFd = -1;
405       composite_layer.planeAlpha = 0xff;
406
407       ret = hwc_add_layer(i, ctx, &composite_layer, composition);
408       if (ret) {
409         ALOGE("Add layer failed %d", ret);
410         hwc_set_cleanup(num_displays, display_contents, composition);
411         return ret;
412       }
413
414       fb->set_release_fence_fd(composite_layer.releaseFenceFd);
415       hd->fb_idx = (hd->fb_idx + 1) % HWC_FB_BUFFERS;
416     }
417   }
418
419   ret = ctx->drm.compositor()->QueueComposition(composition);
420   if (ret) {
421     ALOGE("Failed to queue the composition");
422     hwc_set_cleanup(num_displays, display_contents, composition);
423     return ret;
424   }
425   hwc_set_cleanup(num_displays, display_contents, NULL);
426   return ret;
427 }
428
429 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
430                              int event, int enabled) {
431   if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
432     return -EINVAL;
433
434   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
435   hwc_drm_display_t *hd = &ctx->displays[display];
436   return hd->vsync_worker.VSyncControl(enabled);
437 }
438
439 static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
440                               int mode) {
441   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
442
443   uint64_t dpmsValue = 0;
444   switch (mode) {
445     case HWC_POWER_MODE_OFF:
446       dpmsValue = DRM_MODE_DPMS_OFF;
447       break;
448
449     /* We can't support dozing right now, so go full on */
450     case HWC_POWER_MODE_DOZE:
451     case HWC_POWER_MODE_DOZE_SUSPEND:
452     case HWC_POWER_MODE_NORMAL:
453       dpmsValue = DRM_MODE_DPMS_ON;
454       break;
455   };
456   return ctx->drm.SetDpmsMode(display, dpmsValue);
457 }
458
459 static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
460                      int *value) {
461   switch (what) {
462     case HWC_BACKGROUND_LAYER_SUPPORTED:
463       *value = 0; /* TODO: We should do this */
464       break;
465     case HWC_VSYNC_PERIOD:
466       ALOGW("Query for deprecated vsync value, returning 60Hz");
467       *value = 1000 * 1000 * 1000 / 60;
468       break;
469     case HWC_DISPLAY_TYPES_SUPPORTED:
470       *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
471       break;
472   }
473   return 0;
474 }
475
476 static void hwc_register_procs(struct hwc_composer_device_1 *dev,
477                                hwc_procs_t const *procs) {
478   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
479
480   ctx->procs = procs;
481
482   for (hwc_context_t::DisplayMapIter iter = ctx->displays.begin();
483        iter != ctx->displays.end(); ++iter) {
484     iter->second.vsync_worker.SetProcs(procs);
485   }
486 }
487
488 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
489                                    int display, uint32_t *configs,
490                                    size_t *num_configs) {
491   if (!*num_configs)
492     return 0;
493
494   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
495   hwc_drm_display_t *hd = &ctx->displays[display];
496   hd->config_ids.clear();
497
498   DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
499   if (!connector) {
500     ALOGE("Failed to get connector for display %d", display);
501     return -ENODEV;
502   }
503
504   int ret = connector->UpdateModes();
505   if (ret) {
506     ALOGE("Failed to update display modes %d", ret);
507     return ret;
508   }
509
510   for (DrmConnector::ModeIter iter = connector->begin_modes();
511        iter != connector->end_modes(); ++iter) {
512     size_t idx = hd->config_ids.size();
513     if (idx == *num_configs)
514       break;
515     hd->config_ids.push_back(iter->id());
516     configs[idx] = iter->id();
517   }
518   *num_configs = hd->config_ids.size();
519   return *num_configs == 0 ? -1 : 0;
520 }
521
522 static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
523                                       int display, uint32_t config,
524                                       const uint32_t *attributes,
525                                       int32_t *values) {
526   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
527   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
528   if (!c) {
529     ALOGE("Failed to get DrmConnector for display %d", display);
530     return -ENODEV;
531   }
532   DrmMode mode;
533   for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
534        ++iter) {
535     if (iter->id() == config) {
536       mode = *iter;
537       break;
538     }
539   }
540   if (mode.id() == 0) {
541     ALOGE("Failed to find active mode for display %d", display);
542     return -ENOENT;
543   }
544
545   uint32_t mm_width = c->mm_width();
546   uint32_t mm_height = c->mm_height();
547   for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
548     switch (attributes[i]) {
549       case HWC_DISPLAY_VSYNC_PERIOD:
550         values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
551         break;
552       case HWC_DISPLAY_WIDTH:
553         values[i] = mode.h_display();
554         break;
555       case HWC_DISPLAY_HEIGHT:
556         values[i] = mode.v_display();
557         break;
558       case HWC_DISPLAY_DPI_X:
559         /* Dots per 1000 inches */
560         values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
561         break;
562       case HWC_DISPLAY_DPI_Y:
563         /* Dots per 1000 inches */
564         values[i] =
565             mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
566         break;
567     }
568   }
569   return 0;
570 }
571
572 static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
573                                  int display) {
574   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
575   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
576   if (!c) {
577     ALOGE("Failed to get DrmConnector for display %d", display);
578     return -ENODEV;
579   }
580
581   DrmMode mode = c->active_mode();
582   hwc_drm_display_t *hd = &ctx->displays[display];
583   for (size_t i = 0; i < hd->config_ids.size(); ++i) {
584     if (hd->config_ids[i] == mode.id())
585       return i;
586   }
587   return -1;
588 }
589
590 static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
591                                  int index) {
592   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
593   hwc_drm_display_t *hd = &ctx->displays[display];
594   if (index >= (int)hd->config_ids.size()) {
595     ALOGE("Invalid config index %d passed in", index);
596     return -EINVAL;
597   }
598
599   int ret = ctx->drm.SetDisplayActiveMode(display, hd->config_ids[index]);
600   if (ret) {
601     ALOGE("Failed to set config for display %d", display);
602     return ret;
603   }
604
605   return ret;
606 }
607
608 static int hwc_device_close(struct hw_device_t *dev) {
609   struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
610   delete ctx;
611   return 0;
612 }
613
614 /*
615  * TODO: This function sets the active config to the first one in the list. This
616  * should be fixed such that it selects the preferred mode for the display, or
617  * some other, saner, method of choosing the config.
618  */
619 static int hwc_set_initial_config(hwc_drm_display_t *hd) {
620   uint32_t config;
621   size_t num_configs = 1;
622   int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
623                                     &num_configs);
624   if (ret || !num_configs)
625     return 0;
626
627   ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
628   if (ret) {
629     ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
630     return ret;
631   }
632
633   return ret;
634 }
635
636 static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
637   hwc_drm_display_t *hd = &ctx->displays[display];
638   hd->ctx = ctx;
639   hd->display = display;
640   hd->fb_idx = 0;
641
642   int ret = hwc_set_initial_config(hd);
643   if (ret) {
644     ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
645     return ret;
646   }
647
648   ret = hd->vsync_worker.Init(&ctx->drm, display);
649   if (ret) {
650     ALOGE("Failed to create event worker for display %d %d\n", display, ret);
651     return ret;
652   }
653
654   return 0;
655 }
656
657 static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
658   int ret;
659   for (DrmResources::ConnectorIter c = ctx->drm.begin_connectors();
660        c != ctx->drm.end_connectors(); ++c) {
661     ret = hwc_initialize_display(ctx, (*c)->display());
662     if (ret) {
663       ALOGE("Failed to initialize display %d", (*c)->display());
664       return ret;
665     }
666   }
667
668   return 0;
669 }
670
671 static int hwc_device_open(const struct hw_module_t *module, const char *name,
672                            struct hw_device_t **dev) {
673   if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
674     ALOGE("Invalid module name- %s", name);
675     return -EINVAL;
676   }
677
678   struct hwc_context_t *ctx = new hwc_context_t();
679   if (!ctx) {
680     ALOGE("Failed to allocate hwc context");
681     return -ENOMEM;
682   }
683
684   int ret = ctx->drm.Init();
685   if (ret) {
686     ALOGE("Can't initialize Drm object %d", ret);
687     delete ctx;
688     return ret;
689   }
690
691   ret = ctx->pre_compositor.Init();
692   if (ret) {
693     ALOGE("Can't initialize OpenGL Compositor object %d", ret);
694     delete ctx;
695     return ret;
696   }
697
698   ctx->importer = Importer::CreateInstance(&ctx->drm);
699   if (!ctx->importer) {
700     ALOGE("Failed to create importer instance");
701     delete ctx;
702     return ret;
703   }
704
705   ret = hwc_enumerate_displays(ctx);
706   if (ret) {
707     ALOGE("Failed to enumerate displays: %s", strerror(ret));
708     delete ctx;
709     return ret;
710   }
711
712   ctx->device.common.tag = HARDWARE_DEVICE_TAG;
713   ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
714   ctx->device.common.module = const_cast<hw_module_t *>(module);
715   ctx->device.common.close = hwc_device_close;
716
717   ctx->device.prepare = hwc_prepare;
718   ctx->device.set = hwc_set;
719   ctx->device.eventControl = hwc_event_control;
720   ctx->device.setPowerMode = hwc_set_power_mode;
721   ctx->device.query = hwc_query;
722   ctx->device.registerProcs = hwc_register_procs;
723   ctx->device.getDisplayConfigs = hwc_get_display_configs;
724   ctx->device.getDisplayAttributes = hwc_get_display_attributes;
725   ctx->device.getActiveConfig = hwc_get_active_config;
726   ctx->device.setActiveConfig = hwc_set_active_config;
727   ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
728
729   *dev = &ctx->device.common;
730
731   return 0;
732 }
733 }
734
735 static struct hw_module_methods_t hwc_module_methods = {
736   open : android::hwc_device_open
737 };
738
739 hwc_module_t HAL_MODULE_INFO_SYM = {
740   common : {
741     tag : HARDWARE_MODULE_TAG,
742     version_major : 1,
743     version_minor : 0,
744     id : HWC_HARDWARE_MODULE_ID,
745     name : "DRM hwcomposer module",
746     author : "The Android Open Source Project",
747     methods : &hwc_module_methods,
748     dso : NULL,
749     reserved : {0},
750   }
751 };