• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 // Copyright (c) 2014 Intel Corporation 
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 #include <HwcTrace.h>
17 #include <Hwcomposer.h>
18 #include <Drm.h>
19 #include <PhysicalDevice.h>
20 
21 namespace android {
22 namespace intel {
23 
PhysicalDevice(uint32_t type,Hwcomposer & hwc,DeviceControlFactory * controlFactory)24 PhysicalDevice::PhysicalDevice(uint32_t type, Hwcomposer& hwc, DeviceControlFactory* controlFactory)
25     : mType(type),
26       mHwc(hwc),
27       mActiveDisplayConfig(-1),
28       mBlankControl(NULL),
29       mVsyncObserver(NULL),
30       mControlFactory(controlFactory),
31       mLayerList(NULL),
32       mConnected(false),
33       mBlank(false),
34       mDisplayState(DEVICE_DISPLAY_ON),
35       mInitialized(false)
36 {
37     CTRACE();
38 
39     switch (type) {
40     case DEVICE_PRIMARY:
41         mName = "Primary";
42         break;
43     case DEVICE_EXTERNAL:
44         mName = "External";
45         break;
46     default:
47         mName = "Unknown";
48     }
49 
50     mDisplayConfigs.setCapacity(DEVICE_COUNT);
51 }
52 
~PhysicalDevice()53 PhysicalDevice::~PhysicalDevice()
54 {
55     WARN_IF_NOT_DEINIT();
56 }
57 
onGeometryChanged(hwc_display_contents_1_t * list)58 void PhysicalDevice::onGeometryChanged(hwc_display_contents_1_t *list)
59 {
60     if (!list) {
61         ETRACE("list is NULL");
62         return;
63     }
64 
65     ATRACE("disp = %d, layer number = %d", mType, list->numHwLayers);
66 
67     // NOTE: should NOT be here
68     if (mLayerList) {
69         WTRACE("mLayerList exists");
70         DEINIT_AND_DELETE_OBJ(mLayerList);
71     }
72 
73     // create a new layer list
74     mLayerList = new HwcLayerList(list, mType);
75     if (!mLayerList) {
76         WTRACE("failed to create layer list");
77     }
78 }
79 
prePrepare(hwc_display_contents_1_t * display)80 bool PhysicalDevice::prePrepare(hwc_display_contents_1_t *display)
81 {
82     RETURN_FALSE_IF_NOT_INIT();
83     Mutex::Autolock _l(mLock);
84 
85     // for a null list, delete hwc list
86     if (!mConnected || !display || mBlank) {
87         if (mLayerList) {
88             DEINIT_AND_DELETE_OBJ(mLayerList);
89         }
90         return true;
91     }
92 
93     // check if geometry is changed, if changed delete list
94     if ((display->flags & HWC_GEOMETRY_CHANGED) && mLayerList) {
95         DEINIT_AND_DELETE_OBJ(mLayerList);
96     }
97     return true;
98 }
99 
prepare(hwc_display_contents_1_t * display)100 bool PhysicalDevice::prepare(hwc_display_contents_1_t *display)
101 {
102     RETURN_FALSE_IF_NOT_INIT();
103     Mutex::Autolock _l(mLock);
104 
105     if (!mConnected || !display || mBlank)
106         return true;
107 
108     // check if geometry is changed
109     if (display->flags & HWC_GEOMETRY_CHANGED) {
110         onGeometryChanged(display);
111     }
112     if (!mLayerList) {
113         WTRACE("null HWC layer list");
114         return true;
115     }
116 
117     // update list with new list
118     return mLayerList->update(display);
119 }
120 
121 
commit(hwc_display_contents_1_t * display,IDisplayContext * context)122 bool PhysicalDevice::commit(hwc_display_contents_1_t *display, IDisplayContext *context)
123 {
124     RETURN_FALSE_IF_NOT_INIT();
125 
126     if (!display || !context || !mLayerList || mBlank) {
127         return true;
128     }
129     return context->commitContents(display, mLayerList);
130 }
131 
vsyncControl(bool enabled)132 bool PhysicalDevice::vsyncControl(bool enabled)
133 {
134     RETURN_FALSE_IF_NOT_INIT();
135 
136     ATRACE("disp = %d, enabled = %d", mType, enabled);
137     return mVsyncObserver->control(enabled);
138 }
139 
blank(bool blank)140 bool PhysicalDevice::blank(bool blank)
141 {
142     RETURN_FALSE_IF_NOT_INIT();
143 
144     if (!mConnected)
145         return false;
146 
147     mBlank = blank;
148     bool ret = mBlankControl->blank(mType, blank);
149     if (ret == false) {
150         ETRACE("failed to blank device");
151         return false;
152     }
153 
154     return true;
155 }
156 
getDisplaySize(int * width,int * height)157 bool PhysicalDevice::getDisplaySize(int *width, int *height)
158 {
159     RETURN_FALSE_IF_NOT_INIT();
160     Mutex::Autolock _l(mLock);
161     if (!width || !height) {
162         ETRACE("invalid parameters");
163         return false;
164     }
165 
166     *width = 0;
167     *height = 0;
168     drmModeModeInfo mode;
169     Drm *drm = Hwcomposer::getInstance().getDrm();
170     bool ret = drm->getModeInfo(mType, mode);
171     if (!ret) {
172         return false;
173     }
174 
175     *width = mode.hdisplay;
176     *height = mode.vdisplay;
177     return true;
178 }
179 
180 template <typename T>
min(T a,T b)181 static inline T min(T a, T b) {
182     return a<b ? a : b;
183 }
184 
getDisplayConfigs(uint32_t * configs,size_t * numConfigs)185 bool PhysicalDevice::getDisplayConfigs(uint32_t *configs,
186                                          size_t *numConfigs)
187 {
188     RETURN_FALSE_IF_NOT_INIT();
189 
190     Mutex::Autolock _l(mLock);
191 
192     if (!mConnected) {
193         ITRACE("device is not connected");
194         return false;
195     }
196 
197     if (!configs || !numConfigs || *numConfigs < 1) {
198         ETRACE("invalid parameters");
199         return false;
200     }
201 
202     // fill in all config handles
203     *numConfigs = min(*numConfigs, mDisplayConfigs.size());
204     for (int i = 0; i < static_cast<int>(*numConfigs); i++) {
205         configs[i] = i;
206     }
207 
208     return true;
209 }
getDisplayAttributes(uint32_t config,const uint32_t * attributes,int32_t * values)210 bool PhysicalDevice::getDisplayAttributes(uint32_t config,
211                                             const uint32_t *attributes,
212                                             int32_t *values)
213 {
214     RETURN_FALSE_IF_NOT_INIT();
215 
216     Mutex::Autolock _l(mLock);
217 
218     if (!mConnected) {
219         ITRACE("device is not connected");
220         return false;
221     }
222 
223     if (!attributes || !values) {
224         ETRACE("invalid parameters");
225         return false;
226     }
227 
228     DisplayConfig *configChosen = mDisplayConfigs.itemAt(config);
229     if  (!configChosen) {
230         WTRACE("failed to get display config");
231         return false;
232     }
233 
234     int i = 0;
235     while (attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE) {
236         switch (attributes[i]) {
237         case HWC_DISPLAY_VSYNC_PERIOD:
238             if (configChosen->getRefreshRate()) {
239                 values[i] = 1e9 / configChosen->getRefreshRate();
240             } else {
241                 ETRACE("refresh rate is 0!!!");
242                 values[i] = 0;
243             }
244             break;
245         case HWC_DISPLAY_WIDTH:
246             values[i] = configChosen->getWidth();
247             break;
248         case HWC_DISPLAY_HEIGHT:
249             values[i] = configChosen->getHeight();
250             break;
251         case HWC_DISPLAY_DPI_X:
252             values[i] = configChosen->getDpiX() * 1000.0f;
253             break;
254         case HWC_DISPLAY_DPI_Y:
255             values[i] = configChosen->getDpiY() * 1000.0f;
256             break;
257         default:
258             ETRACE("unknown attribute %d", attributes[i]);
259             break;
260         }
261         i++;
262     }
263 
264     return true;
265 }
266 
compositionComplete()267 bool PhysicalDevice::compositionComplete()
268 {
269     CTRACE();
270     // do nothing by default
271     return true;
272 }
273 
removeDisplayConfigs()274 void PhysicalDevice::removeDisplayConfigs()
275 {
276     for (size_t i = 0; i < mDisplayConfigs.size(); i++) {
277         DisplayConfig *config = mDisplayConfigs.itemAt(i);
278         delete config;
279     }
280 
281     mDisplayConfigs.clear();
282     mActiveDisplayConfig = -1;
283 }
284 
detectDisplayConfigs()285 bool PhysicalDevice::detectDisplayConfigs()
286 {
287     Mutex::Autolock _l(mLock);
288 
289     Drm *drm = Hwcomposer::getInstance().getDrm();
290     if (!drm->detect(mType)) {
291         ETRACE("drm detection on device %d failed ", mType);
292         return false;
293     }
294     return updateDisplayConfigs();
295 }
296 
updateDisplayConfigs()297 bool PhysicalDevice::updateDisplayConfigs()
298 {
299     bool ret;
300     Drm *drm = Hwcomposer::getInstance().getDrm();
301 
302     // reset display configs
303     removeDisplayConfigs();
304 
305     // update device connection status
306     mConnected = drm->isConnected(mType);
307     if (!mConnected) {
308         return true;
309     }
310 
311     // reset the number of display configs
312     mDisplayConfigs.setCapacity(1);
313 
314     drmModeModeInfo mode;
315     ret = drm->getModeInfo(mType, mode);
316     if (!ret) {
317         ETRACE("failed to get mode info");
318         mConnected = false;
319         return false;
320     }
321 
322     uint32_t mmWidth, mmHeight;
323     ret = drm->getPhysicalSize(mType, mmWidth, mmHeight);
324     if (!ret) {
325         ETRACE("failed to get physical size");
326         mConnected = false;
327         return false;
328     }
329 
330     float physWidthInch = (float)mmWidth * 0.039370f;
331     float physHeightInch = (float)mmHeight * 0.039370f;
332 
333     // use current drm mode, likely it's preferred mode
334     int dpiX = 0;
335     int dpiY = 0;
336     if (physWidthInch && physHeightInch) {
337         dpiX = mode.hdisplay / physWidthInch;
338         dpiY = mode.vdisplay / physHeightInch;
339     } else {
340         ETRACE("invalid physical size, EDID read error?");
341         // don't bail out as it is not a fatal error
342     }
343     // use active fb dimension as config width/height
344     DisplayConfig *config = new DisplayConfig(mode.vrefresh,
345                                               mode.hdisplay,
346                                               mode.vdisplay,
347                                               dpiX, dpiY);
348     // add it to the front of other configs
349     mDisplayConfigs.push_front(config);
350 
351     // init the active display config
352     mActiveDisplayConfig = 0;
353 
354     drmModeModeInfoPtr modes;
355     drmModeModeInfoPtr compatMode;
356     int modeCount = 0;
357 
358     modes = drm->detectAllConfigs(mType, &modeCount);
359 
360     for (int i = 0; i < modeCount; i++) {
361         if (modes) {
362             compatMode = &modes[i];
363             if (!compatMode)
364                 continue;
365             if (compatMode->hdisplay == mode.hdisplay &&
366                 compatMode->vdisplay == mode.vdisplay &&
367                 compatMode->vrefresh != mode.vrefresh) {
368 
369                 bool found = false;
370                 for (size_t j = 0; j < mDisplayConfigs.size(); j++) {
371                      DisplayConfig *config = mDisplayConfigs.itemAt(j);
372                      if (config->getRefreshRate() == (int)compatMode->vrefresh) {
373                          found = true;
374                          break;
375                      }
376                 }
377 
378                 if (found) {
379                     continue;
380                 }
381 
382                 DisplayConfig *config = new DisplayConfig(compatMode->vrefresh,
383                                               compatMode->hdisplay,
384                                               compatMode->vdisplay,
385                                               dpiX, dpiY);
386                 // add it to the end of configs
387                 mDisplayConfigs.push_back(config);
388             }
389         }
390     }
391 
392     return true;
393 }
394 
initialize()395 bool PhysicalDevice::initialize()
396 {
397     CTRACE();
398 
399     if (mType != DEVICE_PRIMARY && mType != DEVICE_EXTERNAL) {
400         ETRACE("invalid device type");
401         return false;
402     }
403 
404     // detect display configs
405     bool ret = detectDisplayConfigs();
406     if (ret == false) {
407         DEINIT_AND_RETURN_FALSE("failed to detect display config");
408     }
409 
410     if (!mControlFactory) {
411         DEINIT_AND_RETURN_FALSE("failed to provide a controlFactory ");
412     }
413 
414     // create blank control
415     mBlankControl = mControlFactory->createBlankControl();
416     if (!mBlankControl) {
417         DEINIT_AND_RETURN_FALSE("failed to create blank control");
418     }
419 
420     // create vsync event observer
421     mVsyncObserver = new VsyncEventObserver(*this);
422     if (!mVsyncObserver || !mVsyncObserver->initialize()) {
423         DEINIT_AND_RETURN_FALSE("failed to create vsync observer");
424     }
425 
426     mInitialized = true;
427     return true;
428 }
429 
deinitialize()430 void PhysicalDevice::deinitialize()
431 {
432     Mutex::Autolock _l(mLock);
433     if (mLayerList) {
434         DEINIT_AND_DELETE_OBJ(mLayerList);
435     }
436 
437     DEINIT_AND_DELETE_OBJ(mVsyncObserver);
438 
439     // destroy blank control
440     if (mBlankControl) {
441         delete mBlankControl;
442         mBlankControl = 0;
443     }
444 
445     if (mControlFactory){
446         delete mControlFactory;
447         mControlFactory = 0;
448     }
449 
450     // remove configs
451     removeDisplayConfigs();
452 
453     mInitialized = false;
454 }
455 
isConnected() const456 bool PhysicalDevice::isConnected() const
457 {
458     RETURN_FALSE_IF_NOT_INIT();
459 
460     return mConnected;
461 }
462 
getName() const463 const char* PhysicalDevice::getName() const
464 {
465     return mName;
466 }
467 
getType() const468 int PhysicalDevice::getType() const
469 {
470     return mType;
471 }
472 
onVsync(int64_t timestamp)473 void PhysicalDevice::onVsync(int64_t timestamp)
474 {
475     RETURN_VOID_IF_NOT_INIT();
476     ATRACE("timestamp = %lld", timestamp);
477 
478     if (!mConnected)
479         return;
480 
481     // notify hwc
482     mHwc.vsync(mType, timestamp);
483 }
484 
dump(Dump & d)485 void PhysicalDevice::dump(Dump& d)
486 {
487     Mutex::Autolock _l(mLock);
488     d.append("-------------------------------------------------------------\n");
489     d.append("Device Name: %s (%s)\n", mName,
490             mConnected ? "connected" : "disconnected");
491     d.append("Display configs (count = %d):\n", mDisplayConfigs.size());
492     d.append(" CONFIG | VSYNC_PERIOD | WIDTH | HEIGHT | DPI_X | DPI_Y \n");
493     d.append("--------+--------------+-------+--------+-------+-------\n");
494     for (size_t i = 0; i < mDisplayConfigs.size(); i++) {
495         DisplayConfig *config = mDisplayConfigs.itemAt(i);
496         if (config) {
497             d.append("%s %2d   |     %4d     | %5d |  %4d  |  %3d  |  %3d  \n",
498                      (i == (size_t)mActiveDisplayConfig) ? "* " : "  ",
499                      i,
500                      config->getRefreshRate(),
501                      config->getWidth(),
502                      config->getHeight(),
503                      config->getDpiX(),
504                      config->getDpiY());
505         }
506     }
507     // dump layer list
508     if (mLayerList)
509         mLayerList->dump(d);
510 }
511 
setPowerMode(int mode)512 bool PhysicalDevice::setPowerMode(int mode)
513 {
514     // TODO: set proper power modes for HWC 1.4
515     ATRACE("mode = %d", mode);
516 
517     bool ret;
518     int arg = mode;
519 
520     Drm *drm = Hwcomposer::getInstance().getDrm();
521     ret = drm->writeIoctl(DRM_PSB_PM_SET, &arg, sizeof(arg));
522     if (ret == false) {
523           ETRACE("psb power mode set fail");
524           return false;
525     }
526 
527     return true;
528 }
529 
getActiveConfig()530 int PhysicalDevice::getActiveConfig()
531 {
532     return mActiveDisplayConfig;
533 }
534 
setActiveConfig(int index)535 bool PhysicalDevice::setActiveConfig(int index)
536 {
537     // TODO: for now only implement in external
538     if (index == 0)
539         return true;
540     return false;
541 }
542 
543 } // namespace intel
544 } // namespace android
545