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