HWComposer.cpp revision e2c4f4ec23b735dd2a03f4ea8b08b288a1bb04e8
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
128status_t 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        }
134    }
135
136    if (err == NO_ERROR && mVSyncThread != NULL) {
137        mVSyncThread->setEnabled(enabled);
138    }
139
140    return err;
141}
142
143void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
144    mDpy = (hwc_display_t)dpy;
145    mSur = (hwc_surface_t)sur;
146}
147
148status_t HWComposer::createWorkList(size_t numLayers) {
149    if (mHwc) {
150        if (!mList || mCapacity < numLayers) {
151            free(mList);
152            size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
153            mList = (hwc_layer_list_t*)malloc(size);
154            mCapacity = numLayers;
155        }
156        mList->flags = HWC_GEOMETRY_CHANGED;
157        mList->numHwLayers = numLayers;
158    }
159    return NO_ERROR;
160}
161
162status_t HWComposer::prepare() const {
163    int err = mHwc->prepare(mHwc, mList);
164    if (err == NO_ERROR) {
165        size_t numOVLayers = 0;
166        size_t numFBLayers = 0;
167        size_t count = mList->numHwLayers;
168        for (size_t i=0 ; i<count ; i++) {
169            hwc_layer& l(mList->hwLayers[i]);
170            if (l.flags & HWC_SKIP_LAYER) {
171                l.compositionType = HWC_FRAMEBUFFER;
172            }
173            switch (l.compositionType) {
174                case HWC_OVERLAY:
175                    numOVLayers++;
176                    break;
177                case HWC_FRAMEBUFFER:
178                    numFBLayers++;
179                    break;
180            }
181        }
182        mNumOVLayers = numOVLayers;
183        mNumFBLayers = numFBLayers;
184    }
185    return (status_t)err;
186}
187
188size_t HWComposer::getLayerCount(int type) const {
189    switch (type) {
190        case HWC_OVERLAY:
191            return mNumOVLayers;
192        case HWC_FRAMEBUFFER:
193            return mNumFBLayers;
194    }
195    return 0;
196}
197
198status_t HWComposer::commit() const {
199    int err = mHwc->set(mHwc, mDpy, mSur, mList);
200    if (mList) {
201        mList->flags &= ~HWC_GEOMETRY_CHANGED;
202    }
203    return (status_t)err;
204}
205
206status_t HWComposer::release() const {
207    if (mHwc) {
208        int err = mHwc->set(mHwc, NULL, NULL, NULL);
209        return (status_t)err;
210    }
211    return NO_ERROR;
212}
213
214status_t HWComposer::disable() {
215    if (mHwc) {
216        free(mList);
217        mList = NULL;
218        int err = mHwc->prepare(mHwc, NULL);
219        return (status_t)err;
220    }
221    return NO_ERROR;
222}
223
224size_t HWComposer::getNumLayers() const {
225    return mList ? mList->numHwLayers : 0;
226}
227
228hwc_layer_t* HWComposer::getLayers() const {
229    return mList ? mList->hwLayers : 0;
230}
231
232void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
233        const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
234    if (mHwc && mList) {
235        result.append("Hardware Composer state:\n");
236        result.appendFormat("  mDebugForceFakeVSync=%d\n",
237                mDebugForceFakeVSync);
238        result.appendFormat("  numHwLayers=%u, flags=%08x\n",
239                mList->numHwLayers, mList->flags);
240        result.append(
241                "   type   |  handle  |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
242                "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
243        //      " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
244        for (size_t i=0 ; i<mList->numHwLayers ; i++) {
245            const hwc_layer_t& l(mList->hwLayers[i]);
246            const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
247            int32_t format = -1;
248            if (layer->getLayer() != NULL) {
249                const sp<GraphicBuffer>& buffer(layer->getLayer()->getActiveBuffer());
250                if (buffer != NULL) {
251                    format = buffer->getPixelFormat();
252                }
253            }
254            result.appendFormat(
255                    " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
256                    l.compositionType ? "OVERLAY" : "FB",
257                    intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
258                    l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
259                    l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
260                    layer->getName().string());
261        }
262    }
263    if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_1 && mHwc->dump) {
264        mHwc->dump(mHwc, buffer, SIZE);
265        result.append(buffer);
266    }
267}
268
269// ---------------------------------------------------------------------------
270
271HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
272    : mHwc(hwc), mEnabled(false),
273      mNextFakeVSync(0),
274      mRefreshPeriod(hwc.mRefreshPeriod)
275{
276}
277
278void HWComposer::VSyncThread::setEnabled(bool enabled) {
279    Mutex::Autolock _l(mLock);
280    mEnabled = enabled;
281    mCondition.signal();
282}
283
284void HWComposer::VSyncThread::onFirstRef() {
285    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
286}
287
288bool HWComposer::VSyncThread::threadLoop() {
289    { // scope for lock
290        Mutex::Autolock _l(mLock);
291        while (!mEnabled) {
292            mCondition.wait(mLock);
293        }
294    }
295
296    const nsecs_t period = mRefreshPeriod;
297    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
298    nsecs_t next_vsync = mNextFakeVSync;
299    nsecs_t sleep = next_vsync - now;
300    if (sleep < 0) {
301        // we missed, find where the next vsync should be
302        sleep = (period - ((now - next_vsync) % period));
303        next_vsync = now + sleep;
304    }
305    mNextFakeVSync = next_vsync + period;
306
307    struct timespec spec;
308    spec.tv_sec  = next_vsync / 1000000000;
309    spec.tv_nsec = next_vsync % 1000000000;
310
311    int err;
312    do {
313        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
314    } while (err<0 && errno == EINTR);
315
316    if (err == 0) {
317        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
318    }
319
320    return true;
321}
322
323// ---------------------------------------------------------------------------
324}; // namespace android
325