HWComposer.cpp revision 03e407270c7ad76632f982c886d0776bed9e9b4c
1/*
2 * Copyright (C) 2010 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
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/types.h>
24
25#include <utils/Errors.h>
26#include <utils/String8.h>
27#include <utils/Thread.h>
28#include <utils/Trace.h>
29#include <utils/Vector.h>
30
31#include <hardware/hardware.h>
32#include <hardware/hwcomposer.h>
33
34#include <cutils/log.h>
35#include <cutils/properties.h>
36
37#include <EGL/egl.h>
38
39#include "LayerBase.h"
40#include "HWComposer.h"
41#include "SurfaceFlinger.h"
42
43namespace android {
44// ---------------------------------------------------------------------------
45
46HWComposer::HWComposer(
47        const sp<SurfaceFlinger>& flinger,
48        EventHandler& handler,
49        nsecs_t refreshPeriod)
50    : mFlinger(flinger),
51      mModule(0), mHwc(0), mList(0), mCapacity(0),
52      mNumOVLayers(0), mNumFBLayers(0),
53      mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE),
54      mEventHandler(handler),
55      mRefreshPeriod(refreshPeriod),
56      mVSyncCount(0), mDebugForceFakeVSync(false)
57{
58    char value[PROPERTY_VALUE_MAX];
59    property_get("debug.sf.no_hw_vsync", value, "0");
60    mDebugForceFakeVSync = atoi(value);
61
62    bool needVSyncThread = false;
63    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
64    ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
65    if (err == 0) {
66        err = hwc_open(mModule, &mHwc);
67        ALOGE_IF(err, "%s device failed to initialize (%s)",
68                HWC_HARDWARE_COMPOSER, strerror(-err));
69        if (err == 0) {
70            if (mHwc->registerProcs) {
71                mCBContext.hwc = this;
72                mCBContext.procs.invalidate = &hook_invalidate;
73                mCBContext.procs.vsync = &hook_vsync;
74                mHwc->registerProcs(mHwc, &mCBContext.procs);
75                memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));
76            }
77            if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
78                if (mDebugForceFakeVSync) {
79                    // make sure to turn h/w vsync off in "fake vsync" mode
80                    mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0);
81                }
82            } else {
83                needVSyncThread = true;
84            }
85        }
86    } else {
87        needVSyncThread = true;
88    }
89
90    if (needVSyncThread) {
91        // we don't have VSYNC support, we need to fake it
92        mVSyncThread = new VSyncThread(*this);
93    }
94}
95
96HWComposer::~HWComposer() {
97    eventControl(EVENT_VSYNC, 0);
98    free(mList);
99    if (mVSyncThread != NULL) {
100        mVSyncThread->requestExitAndWait();
101    }
102    if (mHwc) {
103        hwc_close(mHwc);
104    }
105}
106
107status_t HWComposer::initCheck() const {
108    return mHwc ? NO_ERROR : NO_INIT;
109}
110
111void HWComposer::hook_invalidate(struct hwc_procs* procs) {
112    reinterpret_cast<cb_context *>(procs)->hwc->invalidate();
113}
114
115void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) {
116    reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp);
117}
118
119void HWComposer::invalidate() {
120    mFlinger->repaintEverything();
121}
122
123void HWComposer::vsync(int dpy, int64_t timestamp) {
124    ATRACE_INT("VSYNC", ++mVSyncCount&1);
125    mEventHandler.onVSyncReceived(dpy, timestamp);
126}
127
128void HWComposer::eventControl(int event, int enabled) {
129    status_t err = NO_ERROR;
130    if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
131        if (!mDebugForceFakeVSync) {
132            err = mHwc->methods->eventControl(mHwc, event, enabled);
133            // error here should not happen -- not sure what we should
134            // do if it does.
135            ALOGE_IF(err, "eventControl(%d, %d) failed %s",
136                    event, enabled, strerror(-err));
137        }
138    }
139
140    if (err == NO_ERROR && mVSyncThread != NULL) {
141        mVSyncThread->setEnabled(enabled);
142    }
143}
144
145void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
146    mDpy = (hwc_display_t)dpy;
147    mSur = (hwc_surface_t)sur;
148}
149
150status_t HWComposer::createWorkList(size_t numLayers) {
151    if (mHwc) {
152        if (!mList || mCapacity < numLayers) {
153            free(mList);
154            size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
155            mList = (hwc_layer_list_t*)malloc(size);
156            mCapacity = numLayers;
157        }
158        mList->flags = HWC_GEOMETRY_CHANGED;
159        mList->numHwLayers = numLayers;
160    }
161    return NO_ERROR;
162}
163
164status_t HWComposer::prepare() const {
165    int err = mHwc->prepare(mHwc, mList);
166    if (err == NO_ERROR) {
167        size_t numOVLayers = 0;
168        size_t numFBLayers = 0;
169        size_t count = mList->numHwLayers;
170        for (size_t i=0 ; i<count ; i++) {
171            hwc_layer& l(mList->hwLayers[i]);
172            if (l.flags & HWC_SKIP_LAYER) {
173                l.compositionType = HWC_FRAMEBUFFER;
174            }
175            switch (l.compositionType) {
176                case HWC_OVERLAY:
177                    numOVLayers++;
178                    break;
179                case HWC_FRAMEBUFFER:
180                    numFBLayers++;
181                    break;
182            }
183        }
184        mNumOVLayers = numOVLayers;
185        mNumFBLayers = numFBLayers;
186    }
187    return (status_t)err;
188}
189
190size_t HWComposer::getLayerCount(int type) const {
191    switch (type) {
192        case HWC_OVERLAY:
193            return mNumOVLayers;
194        case HWC_FRAMEBUFFER:
195            return mNumFBLayers;
196    }
197    return 0;
198}
199
200status_t HWComposer::commit() const {
201    int err = mHwc->set(mHwc, mDpy, mSur, mList);
202    if (mList) {
203        mList->flags &= ~HWC_GEOMETRY_CHANGED;
204    }
205    return (status_t)err;
206}
207
208status_t HWComposer::release() const {
209    if (mHwc) {
210        if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
211            mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0);
212        }
213        int err = mHwc->set(mHwc, NULL, NULL, NULL);
214        return (status_t)err;
215    }
216    return NO_ERROR;
217}
218
219status_t HWComposer::disable() {
220    if (mHwc) {
221        free(mList);
222        mList = NULL;
223        int err = mHwc->prepare(mHwc, NULL);
224        return (status_t)err;
225    }
226    return NO_ERROR;
227}
228
229size_t HWComposer::getNumLayers() const {
230    return mList ? mList->numHwLayers : 0;
231}
232
233hwc_layer_t* HWComposer::getLayers() const {
234    return mList ? mList->hwLayers : 0;
235}
236
237void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
238        const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
239    if (mHwc && mList) {
240        result.append("Hardware Composer state:\n");
241        result.appendFormat("  mDebugForceFakeVSync=%d\n",
242                mDebugForceFakeVSync);
243        result.appendFormat("  numHwLayers=%u, flags=%08x\n",
244                mList->numHwLayers, mList->flags);
245        result.append(
246                "   type   |  handle  |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
247                "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
248        //      " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
249        for (size_t i=0 ; i<mList->numHwLayers ; i++) {
250            const hwc_layer_t& l(mList->hwLayers[i]);
251            const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
252            int32_t format = -1;
253            if (layer->getLayer() != NULL) {
254                const sp<GraphicBuffer>& buffer(layer->getLayer()->getActiveBuffer());
255                if (buffer != NULL) {
256                    format = buffer->getPixelFormat();
257                }
258            }
259            result.appendFormat(
260                    " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
261                    l.compositionType ? "OVERLAY" : "FB",
262                    intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
263                    l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
264                    l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
265                    layer->getName().string());
266        }
267    }
268    if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_1 && mHwc->dump) {
269        mHwc->dump(mHwc, buffer, SIZE);
270        result.append(buffer);
271    }
272}
273
274// ---------------------------------------------------------------------------
275
276HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
277    : mHwc(hwc), mEnabled(false),
278      mNextFakeVSync(0),
279      mRefreshPeriod(hwc.mRefreshPeriod)
280{
281}
282
283void HWComposer::VSyncThread::setEnabled(bool enabled) {
284    Mutex::Autolock _l(mLock);
285    mEnabled = enabled;
286    mCondition.signal();
287}
288
289void HWComposer::VSyncThread::onFirstRef() {
290    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
291}
292
293bool HWComposer::VSyncThread::threadLoop() {
294    { // scope for lock
295        Mutex::Autolock _l(mLock);
296        while (!mEnabled) {
297            mCondition.wait(mLock);
298        }
299    }
300
301    const nsecs_t period = mRefreshPeriod;
302    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
303    nsecs_t next_vsync = mNextFakeVSync;
304    nsecs_t sleep = next_vsync - now;
305    if (sleep < 0) {
306        // we missed, find where the next vsync should be
307        sleep = (period - ((now - next_vsync) % period));
308        next_vsync = now + sleep;
309    }
310    mNextFakeVSync = next_vsync + period;
311
312    struct timespec spec;
313    spec.tv_sec  = next_vsync / 1000000000;
314    spec.tv_nsec = next_vsync % 1000000000;
315
316    int err;
317    do {
318        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
319    } while (err<0 && errno == EINTR);
320
321    if (err == 0) {
322        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
323    }
324
325    return true;
326}
327
328// ---------------------------------------------------------------------------
329}; // namespace android
330