OSDN Git Service

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