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 {
hwc_drm_display_framebufferandroid::hwc_drm_display_framebuffer53   hwc_drm_display_framebuffer() : release_fence_fd_(-1) {
54   }
55 
~hwc_drm_display_framebufferandroid::hwc_drm_display_framebuffer56   ~hwc_drm_display_framebuffer() {
57     if (release_fence_fd() >= 0)
58       close(release_fence_fd());
59   }
60 
is_validandroid::hwc_drm_display_framebuffer61   bool is_valid() {
62     return buffer_ != NULL;
63   }
64 
bufferandroid::hwc_drm_display_framebuffer65   sp<GraphicBuffer> buffer() {
66     return buffer_;
67   }
68 
release_fence_fdandroid::hwc_drm_display_framebuffer69   int release_fence_fd() {
70     return release_fence_fd_;
71   }
72 
set_release_fence_fdandroid::hwc_drm_display_framebuffer73   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 
Allocateandroid::hwc_drm_display_framebuffer79   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 
Clearandroid::hwc_drm_display_framebuffer98   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 
WaitReleasedandroid::hwc_drm_display_framebuffer110   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 
hwc_context_tandroid::hwc_context_t143   hwc_context_t() : procs(NULL), importer(NULL) {
144   }
145 
~hwc_context_tandroid::hwc_context_t146   ~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 
hwc_dump(struct hwc_composer_device_1 * dev,char * buff,int buff_len)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 
hwc_prepare(hwc_composer_device_1_t * dev,size_t num_displays,hwc_display_contents_1_t ** display_contents)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 
hwc_set_cleanup(size_t num_displays,hwc_display_contents_1_t ** display_contents,Composition * composition)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 
hwc_add_layer(int display,hwc_context_t * ctx,hwc_layer_1_t * layer,Composition * composition)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 
hwc_set(hwc_composer_device_1_t * dev,size_t num_displays,hwc_display_contents_1_t ** display_contents)238 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
239                    hwc_display_contents_1_t **display_contents) {
240   ATRACE_CALL();
241   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
242   Composition *composition =
243       ctx->drm.compositor()->CreateComposition(ctx->importer);
244   if (!composition) {
245     ALOGE("Drm composition init failed");
246     hwc_set_cleanup(num_displays, display_contents, NULL);
247     return -EINVAL;
248   }
249 
250   int ret;
251   for (int i = 0; i < (int)num_displays; ++i) {
252     if (!display_contents[i])
253       continue;
254 
255     hwc_display_contents_1_t *dc = display_contents[i];
256     int j;
257     unsigned num_layers = 0;
258     unsigned num_dc_layers = dc->numHwLayers;
259     for (j = 0; j < (int)num_dc_layers; ++j) {
260       hwc_layer_1_t *layer = &dc->hwLayers[j];
261       if (layer->flags & HWC_SKIP_LAYER)
262         continue;
263       if (layer->compositionType == HWC_OVERLAY)
264         num_layers++;
265     }
266 
267     unsigned num_planes = composition->GetRemainingLayers(i, num_layers);
268     bool use_pre_compositor = false;
269 
270     if (num_layers > num_planes) {
271       use_pre_compositor = true;
272       // Reserve one of the planes for the result of the pre compositor.
273       num_planes--;
274     }
275 
276     for (j = 0; num_planes && j < (int)num_dc_layers; ++j) {
277       hwc_layer_1_t *layer = &dc->hwLayers[j];
278       if (layer->flags & HWC_SKIP_LAYER)
279         continue;
280       if (layer->compositionType != HWC_OVERLAY)
281         continue;
282 
283       ret = hwc_add_layer(i, ctx, layer, composition);
284       if (ret) {
285         ALOGE("Add layer failed %d", ret);
286         hwc_set_cleanup(num_displays, display_contents, composition);
287         return ret;
288       }
289       --num_planes;
290     }
291 
292     int last_comp_layer = j;
293 
294     if (use_pre_compositor) {
295       hwc_drm_display_t *hd = &ctx->displays[i];
296       struct hwc_drm_display_framebuffer *fb = &hd->fb_chain[hd->fb_idx];
297       ret = fb->WaitReleased(-1);
298       if (ret) {
299         ALOGE("Failed to wait for framebuffer %d", ret);
300         hwc_set_cleanup(num_displays, display_contents, composition);
301         return ret;
302       }
303 
304       DrmConnector *connector = ctx->drm.GetConnectorForDisplay(i);
305       if (!connector) {
306         ALOGE("No connector for display %d", i);
307         hwc_set_cleanup(num_displays, display_contents, composition);
308         return -ENODEV;
309       }
310 
311       const DrmMode &mode = connector->active_mode();
312       if (!fb->Allocate(mode.h_display(), mode.v_display())) {
313         ALOGE("Failed to allocate framebuffer with size %dx%d",
314               mode.h_display(), mode.v_display());
315         hwc_set_cleanup(num_displays, display_contents, composition);
316         return -EINVAL;
317       }
318 
319       sp<GraphicBuffer> fb_buffer = fb->buffer();
320       if (fb_buffer == NULL) {
321         ALOGE("Framebuffer is NULL");
322         hwc_set_cleanup(num_displays, display_contents, composition);
323         return -EINVAL;
324       }
325 
326       Targeting *targeting = ctx->pre_compositor.targeting();
327       if (targeting == NULL) {
328         ALOGE("Pre-compositor does not support targeting");
329         hwc_set_cleanup(num_displays, display_contents, composition);
330         return -EINVAL;
331       }
332 
333       int target = targeting->CreateTarget(fb_buffer);
334       targeting->SetTarget(target);
335 
336       Composition *pre_composition = ctx->pre_compositor.CreateComposition(ctx->importer);
337       if (pre_composition == NULL) {
338         ALOGE("Failed to create pre-composition");
339         targeting->ForgetTarget(target);
340         hwc_set_cleanup(num_displays, display_contents, composition);
341         return -EINVAL;
342       }
343 
344       for (j = last_comp_layer; j < (int)num_dc_layers; ++j) {
345         hwc_layer_1_t *layer = &dc->hwLayers[j];
346         if (layer->flags & HWC_SKIP_LAYER)
347           continue;
348         if (layer->compositionType != HWC_OVERLAY)
349           continue;
350         ret = hwc_add_layer(i, ctx, layer, pre_composition);
351         if (ret) {
352           ALOGE("Add layer failed %d", ret);
353           delete pre_composition;
354           targeting->ForgetTarget(target);
355           hwc_set_cleanup(num_displays, display_contents, composition);
356           return ret;
357         }
358       }
359 
360       ret = ctx->pre_compositor.QueueComposition(pre_composition);
361       pre_composition = NULL;
362 
363       targeting->ForgetTarget(target);
364       if (ret < 0 && ret != -EALREADY) {
365         ALOGE("Pre-composition failed %d", ret);
366         hwc_set_cleanup(num_displays, display_contents, composition);
367         return ret;
368       }
369 
370       for (j = last_comp_layer; j < (int)num_dc_layers; ++j) {
371         hwc_layer_1_t *layer = &dc->hwLayers[j];
372         if (layer->flags & HWC_SKIP_LAYER)
373           continue;
374         if (layer->compositionType != HWC_OVERLAY)
375           continue;
376         layer->acquireFenceFd = -1;
377       }
378 
379       hwc_layer_1_t composite_layer;
380       hwc_rect_t visible_rect;
381       memset(&composite_layer, 0, sizeof(composite_layer));
382       memset(&visible_rect, 0, sizeof(visible_rect));
383 
384       composite_layer.compositionType = HWC_OVERLAY;
385       composite_layer.handle = fb_buffer->getNativeBuffer()->handle;
386       composite_layer.sourceCropf.right = composite_layer.displayFrame.right =
387           visible_rect.right = fb_buffer->getWidth();
388       composite_layer.sourceCropf.bottom = composite_layer.displayFrame.bottom =
389           visible_rect.bottom = fb_buffer->getHeight();
390       composite_layer.visibleRegionScreen.numRects = 1;
391       composite_layer.visibleRegionScreen.rects = &visible_rect;
392       composite_layer.acquireFenceFd = ret == -EALREADY ? -1 : ret;
393       // A known invalid fd in case AddLayer does not modify this field.
394       composite_layer.releaseFenceFd = -1;
395       composite_layer.planeAlpha = 0xff;
396 
397       ret = hwc_add_layer(i, ctx, &composite_layer, composition);
398       if (ret) {
399         ALOGE("Add layer failed %d", ret);
400         hwc_set_cleanup(num_displays, display_contents, composition);
401         return ret;
402       }
403 
404       fb->set_release_fence_fd(composite_layer.releaseFenceFd);
405       hd->fb_idx = (hd->fb_idx + 1) % HWC_FB_BUFFERS;
406     }
407   }
408 
409   ret = ctx->drm.compositor()->QueueComposition(composition);
410   composition = NULL;
411   if (ret) {
412     ALOGE("Failed to queue the composition");
413     hwc_set_cleanup(num_displays, display_contents, NULL);
414     return ret;
415   }
416   hwc_set_cleanup(num_displays, display_contents, NULL);
417   return ret;
418 }
419 
hwc_event_control(struct hwc_composer_device_1 * dev,int display,int event,int enabled)420 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
421                              int event, int enabled) {
422   if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
423     return -EINVAL;
424 
425   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
426   hwc_drm_display_t *hd = &ctx->displays[display];
427   return hd->vsync_worker.VSyncControl(enabled);
428 }
429 
hwc_set_power_mode(struct hwc_composer_device_1 * dev,int display,int mode)430 static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
431                               int mode) {
432   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
433 
434   uint64_t dpmsValue = 0;
435   switch (mode) {
436     case HWC_POWER_MODE_OFF:
437       dpmsValue = DRM_MODE_DPMS_OFF;
438       break;
439 
440     /* We can't support dozing right now, so go full on */
441     case HWC_POWER_MODE_DOZE:
442     case HWC_POWER_MODE_DOZE_SUSPEND:
443     case HWC_POWER_MODE_NORMAL:
444       dpmsValue = DRM_MODE_DPMS_ON;
445       break;
446   };
447   return ctx->drm.SetDpmsMode(display, dpmsValue);
448 }
449 
hwc_query(struct hwc_composer_device_1 *,int what,int * value)450 static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
451                      int *value) {
452   switch (what) {
453     case HWC_BACKGROUND_LAYER_SUPPORTED:
454       *value = 0; /* TODO: We should do this */
455       break;
456     case HWC_VSYNC_PERIOD:
457       ALOGW("Query for deprecated vsync value, returning 60Hz");
458       *value = 1000 * 1000 * 1000 / 60;
459       break;
460     case HWC_DISPLAY_TYPES_SUPPORTED:
461       *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
462       break;
463   }
464   return 0;
465 }
466 
hwc_register_procs(struct hwc_composer_device_1 * dev,hwc_procs_t const * procs)467 static void hwc_register_procs(struct hwc_composer_device_1 *dev,
468                                hwc_procs_t const *procs) {
469   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
470 
471   ctx->procs = procs;
472 
473   for (hwc_context_t::DisplayMapIter iter = ctx->displays.begin();
474        iter != ctx->displays.end(); ++iter) {
475     iter->second.vsync_worker.SetProcs(procs);
476   }
477 }
478 
hwc_get_display_configs(struct hwc_composer_device_1 * dev,int display,uint32_t * configs,size_t * num_configs)479 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
480                                    int display, uint32_t *configs,
481                                    size_t *num_configs) {
482   if (!*num_configs)
483     return 0;
484 
485   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
486   hwc_drm_display_t *hd = &ctx->displays[display];
487   hd->config_ids.clear();
488 
489   DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
490   if (!connector) {
491     ALOGE("Failed to get connector for display %d", display);
492     return -ENODEV;
493   }
494 
495   int ret = connector->UpdateModes();
496   if (ret) {
497     ALOGE("Failed to update display modes %d", ret);
498     return ret;
499   }
500 
501   for (DrmConnector::ModeIter iter = connector->begin_modes();
502        iter != connector->end_modes(); ++iter) {
503     size_t idx = hd->config_ids.size();
504     if (idx == *num_configs)
505       break;
506     hd->config_ids.push_back(iter->id());
507     configs[idx] = iter->id();
508   }
509   *num_configs = hd->config_ids.size();
510   return *num_configs == 0 ? -1 : 0;
511 }
512 
hwc_get_display_attributes(struct hwc_composer_device_1 * dev,int display,uint32_t config,const uint32_t * attributes,int32_t * values)513 static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
514                                       int display, uint32_t config,
515                                       const uint32_t *attributes,
516                                       int32_t *values) {
517   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
518   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
519   if (!c) {
520     ALOGE("Failed to get DrmConnector for display %d", display);
521     return -ENODEV;
522   }
523   DrmMode mode;
524   for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
525        ++iter) {
526     if (iter->id() == config) {
527       mode = *iter;
528       break;
529     }
530   }
531   if (mode.id() == 0) {
532     ALOGE("Failed to find active mode for display %d", display);
533     return -ENOENT;
534   }
535 
536   uint32_t mm_width = c->mm_width();
537   uint32_t mm_height = c->mm_height();
538   for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
539     switch (attributes[i]) {
540       case HWC_DISPLAY_VSYNC_PERIOD:
541         values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
542         break;
543       case HWC_DISPLAY_WIDTH:
544         values[i] = mode.h_display();
545         break;
546       case HWC_DISPLAY_HEIGHT:
547         values[i] = mode.v_display();
548         break;
549       case HWC_DISPLAY_DPI_X:
550         /* Dots per 1000 inches */
551         values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
552         break;
553       case HWC_DISPLAY_DPI_Y:
554         /* Dots per 1000 inches */
555         values[i] =
556             mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
557         break;
558     }
559   }
560   return 0;
561 }
562 
hwc_get_active_config(struct hwc_composer_device_1 * dev,int display)563 static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
564                                  int display) {
565   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
566   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
567   if (!c) {
568     ALOGE("Failed to get DrmConnector for display %d", display);
569     return -ENODEV;
570   }
571 
572   DrmMode mode = c->active_mode();
573   hwc_drm_display_t *hd = &ctx->displays[display];
574   for (size_t i = 0; i < hd->config_ids.size(); ++i) {
575     if (hd->config_ids[i] == mode.id())
576       return i;
577   }
578   return -1;
579 }
580 
hwc_set_active_config(struct hwc_composer_device_1 * dev,int display,int index)581 static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
582                                  int index) {
583   struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
584   hwc_drm_display_t *hd = &ctx->displays[display];
585   if (index >= (int)hd->config_ids.size()) {
586     ALOGE("Invalid config index %d passed in", index);
587     return -EINVAL;
588   }
589 
590   DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
591   if (!c) {
592     ALOGE("Failed to get connector for display %d", display);
593     return -ENODEV;
594   }
595   DrmMode mode;
596   for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
597        ++iter) {
598     if (iter->id() == hd->config_ids[index]) {
599       mode = *iter;
600       break;
601     }
602   }
603   if (mode.id() != hd->config_ids[index]) {
604     ALOGE("Could not find active mode for %d/%d", index, hd->config_ids[index]);
605     return -ENOENT;
606   }
607   int ret = ctx->drm.SetDisplayActiveMode(display, mode);
608   if (ret) {
609     ALOGE("Failed to set active config %d", ret);
610     return ret;
611   }
612   return ret;
613 }
614 
hwc_device_close(struct hw_device_t * dev)615 static int hwc_device_close(struct hw_device_t *dev) {
616   struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
617   delete ctx;
618   return 0;
619 }
620 
621 /*
622  * TODO: This function sets the active config to the first one in the list. This
623  * should be fixed such that it selects the preferred mode for the display, or
624  * some other, saner, method of choosing the config.
625  */
hwc_set_initial_config(hwc_drm_display_t * hd)626 static int hwc_set_initial_config(hwc_drm_display_t *hd) {
627   uint32_t config;
628   size_t num_configs = 1;
629   int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
630                                     &num_configs);
631   if (ret || !num_configs)
632     return 0;
633 
634   ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
635   if (ret) {
636     ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
637     return ret;
638   }
639 
640   return ret;
641 }
642 
hwc_initialize_display(struct hwc_context_t * ctx,int display)643 static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
644   hwc_drm_display_t *hd = &ctx->displays[display];
645   hd->ctx = ctx;
646   hd->display = display;
647   hd->fb_idx = 0;
648 
649   int ret = hwc_set_initial_config(hd);
650   if (ret) {
651     ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
652     return ret;
653   }
654 
655   ret = hd->vsync_worker.Init(&ctx->drm, display);
656   if (ret) {
657     ALOGE("Failed to create event worker for display %d %d\n", display, ret);
658     return ret;
659   }
660 
661   return 0;
662 }
663 
hwc_enumerate_displays(struct hwc_context_t * ctx)664 static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
665   int ret;
666   for (DrmResources::ConnectorIter c = ctx->drm.begin_connectors();
667        c != ctx->drm.end_connectors(); ++c) {
668     ret = hwc_initialize_display(ctx, (*c)->display());
669     if (ret) {
670       ALOGE("Failed to initialize display %d", (*c)->display());
671       return ret;
672     }
673   }
674 
675   return 0;
676 }
677 
hwc_device_open(const struct hw_module_t * module,const char * name,struct hw_device_t ** dev)678 static int hwc_device_open(const struct hw_module_t *module, const char *name,
679                            struct hw_device_t **dev) {
680   if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
681     ALOGE("Invalid module name- %s", name);
682     return -EINVAL;
683   }
684 
685   struct hwc_context_t *ctx = new hwc_context_t();
686   if (!ctx) {
687     ALOGE("Failed to allocate hwc context");
688     return -ENOMEM;
689   }
690 
691   int ret = ctx->drm.Init();
692   if (ret) {
693     ALOGE("Can't initialize Drm object %d", ret);
694     delete ctx;
695     return ret;
696   }
697 
698   ret = ctx->pre_compositor.Init();
699   if (ret) {
700     ALOGE("Can't initialize OpenGL Compositor object %d", ret);
701     delete ctx;
702     return ret;
703   }
704 
705   ctx->importer = Importer::CreateInstance(&ctx->drm);
706   if (!ctx->importer) {
707     ALOGE("Failed to create importer instance");
708     delete ctx;
709     return ret;
710   }
711 
712   ret = hwc_enumerate_displays(ctx);
713   if (ret) {
714     ALOGE("Failed to enumerate displays: %s", strerror(ret));
715     delete ctx;
716     return ret;
717   }
718 
719   ctx->device.common.tag = HARDWARE_DEVICE_TAG;
720   ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
721   ctx->device.common.module = const_cast<hw_module_t *>(module);
722   ctx->device.common.close = hwc_device_close;
723 
724   ctx->device.dump = hwc_dump;
725   ctx->device.prepare = hwc_prepare;
726   ctx->device.set = hwc_set;
727   ctx->device.eventControl = hwc_event_control;
728   ctx->device.setPowerMode = hwc_set_power_mode;
729   ctx->device.query = hwc_query;
730   ctx->device.registerProcs = hwc_register_procs;
731   ctx->device.getDisplayConfigs = hwc_get_display_configs;
732   ctx->device.getDisplayAttributes = hwc_get_display_attributes;
733   ctx->device.getActiveConfig = hwc_get_active_config;
734   ctx->device.setActiveConfig = hwc_set_active_config;
735   ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
736 
737   *dev = &ctx->device.common;
738 
739   return 0;
740 }
741 }
742 
743 static struct hw_module_methods_t hwc_module_methods = {
744   open : android::hwc_device_open
745 };
746 
747 hwc_module_t HAL_MODULE_INFO_SYM = {
748   common : {
749     tag : HARDWARE_MODULE_TAG,
750     version_major : 1,
751     version_minor : 0,
752     id : HWC_HARDWARE_MODULE_ID,
753     name : "DRM hwcomposer module",
754     author : "The Android Open Source Project",
755     methods : &hwc_module_methods,
756     dso : NULL,
757     reserved : {0},
758   }
759 };
760