Hwcomposer.cpp revision c0529447ae16f023dfab2978ea2b245f368e893b
1/*
2 * Copyright © 2012 Intel Corporation
3 * All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Jackie Li <yaodong.li@intel.com>
26 *
27 */
28#include <HwcTrace.h>
29#include <Hwcomposer.h>
30#include <Dump.h>
31#include <UeventObserver.h>
32
33namespace android {
34namespace intel {
35
36Hwcomposer* Hwcomposer::sInstance(0);
37
38Hwcomposer::Hwcomposer()
39    : mProcs(0),
40      mDrm(0),
41      mPlaneManager(0),
42      mBufferManager(0),
43      mDisplayAnalyzer(0),
44      mDisplayContext(0),
45      mVsyncManager(0),
46      mMultiDisplayObserver(0),
47      mUeventObserver(0),
48      mPowerManager(0),
49      mInitialized(false)
50{
51    CTRACE();
52
53    mDisplayDevices.setCapacity(IDisplayDevice::DEVICE_COUNT);
54    mDisplayDevices.clear();
55}
56
57Hwcomposer::~Hwcomposer()
58{
59    CTRACE();
60    deinitialize();
61}
62
63bool Hwcomposer::initCheck() const
64{
65    return mInitialized;
66}
67
68bool Hwcomposer::prepare(size_t numDisplays,
69                          hwc_display_contents_1_t** displays)
70{
71    bool ret = true;
72
73    RETURN_FALSE_IF_NOT_INIT();
74    ATRACE("display count = %d", numDisplays);
75
76    if (!numDisplays || !displays) {
77        ETRACE("invalid parameters");
78        return false;
79    }
80
81    mDisplayAnalyzer->analyzeContents(numDisplays, displays);
82
83    // disable reclaimed planes
84    mPlaneManager->disableReclaimedPlanes();
85
86    // reclaim all allocated planes if possible
87    for (size_t i = 0; i < numDisplays; i++) {
88        IDisplayDevice *device = mDisplayDevices.itemAt(i);
89        if (!device) {
90            VTRACE("device %d doesn't exist", i);
91            continue;
92        }
93
94        device->prePrepare(displays[i]);
95    }
96
97    for (size_t i = 0; i < numDisplays; i++) {
98        IDisplayDevice *device = mDisplayDevices.itemAt(i);
99        if (!device) {
100            VTRACE("device %d doesn't exist", i);
101            continue;
102        }
103
104        ret = device->prepare(displays[i]);
105        if (ret == false) {
106            ETRACE("failed to do prepare for device %d", i);
107            continue;
108        }
109    }
110
111    return ret;
112}
113
114bool Hwcomposer::commit(size_t numDisplays,
115                         hwc_display_contents_1_t **displays)
116{
117    bool ret = true;
118
119    RETURN_FALSE_IF_NOT_INIT();
120    ATRACE("display count = %d", numDisplays);
121
122    if (!numDisplays || !displays) {
123        ETRACE("invalid parameters");
124        return false;
125    }
126
127    mDisplayContext->commitBegin(numDisplays, displays);
128
129    for (size_t i = 0; i < numDisplays; i++) {
130        IDisplayDevice *device = mDisplayDevices.itemAt(i);
131        if (!device) {
132            VTRACE("device %d doesn't exist", i);
133            continue;
134        }
135
136        if (!device->isConnected()) {
137            VTRACE("device %d is disconnected", i);
138            continue;
139        }
140
141        ret = device->commit(displays[i], mDisplayContext);
142        if (ret == false) {
143            ETRACE("failed to do commit for device %d", i);
144            continue;
145        }
146    }
147
148    mDisplayContext->commitEnd(numDisplays, displays);
149    // return true always
150    return true;
151}
152
153bool Hwcomposer::vsyncControl(int disp, int enabled)
154{
155    RETURN_FALSE_IF_NOT_INIT();
156    ATRACE("disp = %d, enabled = %d", disp, enabled);
157    return mVsyncManager->handleVsyncControl(disp, enabled ? true : false);
158}
159
160bool Hwcomposer::blank(int disp, int blank)
161{
162    RETURN_FALSE_IF_NOT_INIT();
163    ATRACE("disp = %d, blank = %d", disp, blank);
164
165    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
166        ETRACE("invalid disp %d", disp);
167        return false;
168    }
169
170    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
171    if (!device) {
172        ETRACE("no device found");
173        return false;
174    }
175
176    return device->blank(blank ? true : false);
177}
178
179bool Hwcomposer::getDisplayConfigs(int disp,
180                                      uint32_t *configs,
181                                      size_t *numConfigs)
182{
183    RETURN_FALSE_IF_NOT_INIT();
184
185    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
186        ETRACE("invalid disp %d", disp);
187        return false;
188    }
189
190    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
191    if (!device) {
192        ETRACE("no device %d found", disp);
193        return false;
194    }
195
196    return device->getDisplayConfigs(configs, numConfigs);
197}
198
199bool Hwcomposer::getDisplayAttributes(int disp,
200                                         uint32_t config,
201                                         const uint32_t *attributes,
202                                         int32_t *values)
203{
204    RETURN_FALSE_IF_NOT_INIT();
205
206    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
207        ETRACE("invalid disp %d", disp);
208        return false;
209    }
210
211    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
212    if (!device) {
213        ETRACE("no device found");
214        return false;
215    }
216
217    return device->getDisplayAttributes(config, attributes, values);
218}
219
220bool Hwcomposer::compositionComplete(int disp)
221{
222    RETURN_FALSE_IF_NOT_INIT();
223
224    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
225        ETRACE("invalid disp %d", disp);
226        return false;
227    }
228
229    mDisplayContext->compositionComplete();
230
231    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
232    if (!device) {
233        ETRACE("no device found");
234        return false;
235    }
236
237    return device->compositionComplete();
238}
239
240void Hwcomposer::vsync(int disp, int64_t timestamp)
241{
242    RETURN_VOID_IF_NOT_INIT();
243
244    if (mProcs && mProcs->vsync) {
245        VTRACE("report vsync on disp %d, timestamp %llu", disp, timestamp);
246        // workaround to pretend vsync is from primary display
247        // Display will freeze if vsync is from external display.
248        mProcs->vsync(const_cast<hwc_procs_t*>(mProcs), IDisplayDevice::DEVICE_PRIMARY, timestamp);
249    }
250}
251
252void Hwcomposer::hotplug(int disp, bool connected)
253{
254    RETURN_VOID_IF_NOT_INIT();
255
256    // TODO: Two fake hotplug events are sent during mode setting. To avoid
257    // unnecessary audio switch, real connection status should be sent to MDS
258    mMultiDisplayObserver->notifyHotPlug(mDrm->isConnected(disp));
259
260    if (mProcs && mProcs->hotplug) {
261        DTRACE("report hotplug on disp %d, connected %d", disp, connected);
262        mProcs->hotplug(const_cast<hwc_procs_t*>(mProcs), disp, connected);
263        DTRACE("hotplug callback processed and returned!");
264    }
265
266    mDisplayAnalyzer->postHotplugEvent(connected);
267}
268
269void Hwcomposer::invalidate()
270{
271    RETURN_VOID_IF_NOT_INIT();
272
273    if (mProcs && mProcs->invalidate) {
274        DTRACE("invalidating screen...");
275        mProcs->invalidate(const_cast<hwc_procs_t*>(mProcs));
276    }
277}
278
279bool Hwcomposer::release()
280{
281    RETURN_FALSE_IF_NOT_INIT();
282
283    return true;
284}
285
286bool Hwcomposer::dump(char *buff, int buff_len, int *cur_len)
287{
288    RETURN_FALSE_IF_NOT_INIT();
289
290    Dump d(buff, buff_len);
291
292    // dump composer status
293    d.append("Hardware Composer state:");
294    // dump device status
295    for (size_t i= 0; i < mDisplayDevices.size(); i++) {
296        IDisplayDevice *device = mDisplayDevices.itemAt(i);
297        if (device)
298            device->dump(d);
299    }
300
301    // dump plane manager status
302    if (mPlaneManager)
303        mPlaneManager->dump(d);
304
305    // dump buffer manager status
306    if (mBufferManager)
307        mBufferManager->dump(d);
308
309    return true;
310}
311
312void Hwcomposer::registerProcs(hwc_procs_t const *procs)
313{
314    CTRACE();
315
316    if (!procs) {
317        WTRACE("procs is NULL");
318    }
319    mProcs = procs;
320}
321
322bool Hwcomposer::initialize()
323{
324    CTRACE();
325
326    // create drm
327    mDrm = new Drm();
328    if (!mDrm || !mDrm->initialize()) {
329        DEINIT_AND_RETURN_FALSE("failed to create DRM");
330    }
331
332    // create buffer manager
333    mBufferManager = createBufferManager();
334    if (!mBufferManager || !mBufferManager->initialize()) {
335        DEINIT_AND_RETURN_FALSE("failed to create buffer manager");
336    }
337
338    // create display plane manager
339    mPlaneManager = createDisplayPlaneManager();
340    if (!mPlaneManager || !mPlaneManager->initialize()) {
341        DEINIT_AND_RETURN_FALSE("failed to create display plane manager");
342    }
343
344    mDisplayContext = createDisplayContext();
345    if (!mDisplayContext || !mDisplayContext->initialize()) {
346        DEINIT_AND_RETURN_FALSE("failed to create display context");
347    }
348
349    mPowerManager = createPowerManager();
350    if (!mPowerManager || !mPowerManager->initialize()) {
351        DEINIT_AND_RETURN_FALSE("failed to initialize power manager");
352    }
353
354    mUeventObserver = new UeventObserver();
355    if (!mUeventObserver || !mUeventObserver->initialize()) {
356        DEINIT_AND_RETURN_FALSE("failed to initialize uevent observer");
357    }
358
359    // create display device
360    for (int i = 0; i < IDisplayDevice::DEVICE_COUNT; i++) {
361        IDisplayDevice *device = createDisplayDevice(i, *mPlaneManager);
362        if (!device || !device->initialize()) {
363            DEINIT_AND_DELETE_OBJ(device);
364            DEINIT_AND_RETURN_FALSE("failed to create device %d", i);
365        }
366        // add this device
367        mDisplayDevices.insertAt(device, i, 1);
368    }
369
370    mVsyncManager = new VsyncManager(mDisplayDevices);
371    if (!mVsyncManager || !mVsyncManager->initialize()) {
372        DEINIT_AND_RETURN_FALSE("failed to create Vsync Manager");
373    }
374
375    mDisplayAnalyzer = new DisplayAnalyzer();
376    if (!mDisplayAnalyzer || !mDisplayAnalyzer->initialize()) {
377        DEINIT_AND_RETURN_FALSE("failed to initialize display analyzer");
378    }
379
380    mMultiDisplayObserver = new MultiDisplayObserver();
381    if (!mMultiDisplayObserver || !mMultiDisplayObserver->initialize()) {
382        DEINIT_AND_RETURN_FALSE("failed to initialize display observer");
383    }
384
385    // all initialized, starting uevent observer
386    mUeventObserver->start();
387
388    mInitialized = true;
389    return true;
390}
391
392void Hwcomposer::deinitialize()
393{
394    DEINIT_AND_DELETE_OBJ(mMultiDisplayObserver);
395    DEINIT_AND_DELETE_OBJ(mDisplayAnalyzer);
396    // delete mVsyncManager first as it holds reference to display devices.
397    DEINIT_AND_DELETE_OBJ(mVsyncManager);
398
399    DEINIT_AND_DELETE_OBJ(mUeventObserver);
400    // destroy display devices
401    for (size_t i = 0; i < mDisplayDevices.size(); i++) {
402        IDisplayDevice *device = mDisplayDevices.itemAt(i);
403        DEINIT_AND_DELETE_OBJ(device);
404    }
405    mDisplayDevices.clear();
406
407    DEINIT_AND_DELETE_OBJ(mPowerManager);
408    DEINIT_AND_DELETE_OBJ(mDisplayContext);
409    DEINIT_AND_DELETE_OBJ(mPlaneManager);
410    DEINIT_AND_DELETE_OBJ(mBufferManager);
411    DEINIT_AND_DELETE_OBJ(mDrm);
412    mInitialized = false;
413}
414
415Drm* Hwcomposer::getDrm()
416{
417    return mDrm;
418}
419
420DisplayPlaneManager* Hwcomposer::getPlaneManager()
421{
422    return mPlaneManager;
423}
424
425BufferManager* Hwcomposer::getBufferManager()
426{
427    return mBufferManager;
428}
429
430IDisplayContext* Hwcomposer::getDisplayContext()
431{
432    return mDisplayContext;
433}
434
435DisplayAnalyzer* Hwcomposer::getDisplayAnalyzer()
436{
437    return mDisplayAnalyzer;
438}
439
440MultiDisplayObserver* Hwcomposer::getMultiDisplayObserver()
441{
442    return mMultiDisplayObserver;
443}
444
445IDisplayDevice* Hwcomposer::getDisplayDevice(int disp)
446{
447    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
448        ETRACE("invalid disp %d", disp);
449        return NULL;
450    }
451    return mDisplayDevices.itemAt(disp);
452}
453
454VsyncManager* Hwcomposer::getVsyncManager()
455{
456    return mVsyncManager;
457}
458
459UeventObserver* Hwcomposer::getUeventObserver()
460{
461    return mUeventObserver;
462}
463
464IPowerManager* Hwcomposer::getPowerManager()
465{
466    return mPowerManager;
467}
468
469} // namespace intel
470} // namespace android
471