blob: 65763db8d3125dfb79d55f2b2e89f20655b2d81f [file] [log] [blame]
Mathias Agopiana350ff92010-08-10 17:14:02 -07001/*
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
Mathias Agopian2965b262012-04-08 15:13:32 -070017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Mathias Agopiana350ff92010-08-10 17:14:02 -070019#include <stdint.h>
Mathias Agopianf1352df2010-08-11 17:31:33 -070020#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070023#include <sys/types.h>
24
25#include <utils/Errors.h>
Mathias Agopian83727852010-09-23 18:13:21 -070026#include <utils/String8.h>
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070027#include <utils/Thread.h>
Mathias Agopian2965b262012-04-08 15:13:32 -070028#include <utils/Trace.h>
Mathias Agopian22da60c2011-09-09 00:49:11 -070029#include <utils/Vector.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070030
31#include <hardware/hardware.h>
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070032#include <hardware/hwcomposer.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070033
34#include <cutils/log.h>
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -070035#include <cutils/properties.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070036
37#include <EGL/egl.h>
38
Mathias Agopian22da60c2011-09-09 00:49:11 -070039#include "LayerBase.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070040#include "HWComposer.h"
Mathias Agopianc7d14e22011-08-01 16:32:21 -070041#include "SurfaceFlinger.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070042
43namespace android {
44// ---------------------------------------------------------------------------
45
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070046HWComposer::HWComposer(
47 const sp<SurfaceFlinger>& flinger,
48 EventHandler& handler,
49 nsecs_t refreshPeriod)
Mathias Agopianc7d14e22011-08-01 16:32:21 -070050 : mFlinger(flinger),
51 mModule(0), mHwc(0), mList(0), mCapacity(0),
Mathias Agopian9c6e2972011-09-20 17:21:56 -070052 mNumOVLayers(0), mNumFBLayers(0),
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070053 mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE),
54 mEventHandler(handler),
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -070055 mRefreshPeriod(refreshPeriod),
56 mVSyncCount(0), mDebugForceFakeVSync(false)
Mathias Agopiana350ff92010-08-10 17:14:02 -070057{
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -070058 char value[PROPERTY_VALUE_MAX];
59 property_get("debug.sf.no_hw_vsync", value, "0");
60 mDebugForceFakeVSync = atoi(value);
61
Mathias Agopian3a778712012-04-09 14:16:47 -070062 bool needVSyncThread = false;
Mathias Agopiana350ff92010-08-10 17:14:02 -070063 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
Steve Block32397c12012-01-05 23:22:43 +000064 ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
Mathias Agopiana350ff92010-08-10 17:14:02 -070065 if (err == 0) {
66 err = hwc_open(mModule, &mHwc);
Steve Blocke6f43dd2012-01-06 19:20:56 +000067 ALOGE_IF(err, "%s device failed to initialize (%s)",
Mathias Agopiana350ff92010-08-10 17:14:02 -070068 HWC_HARDWARE_COMPOSER, strerror(-err));
Mathias Agopianc7d14e22011-08-01 16:32:21 -070069 if (err == 0) {
70 if (mHwc->registerProcs) {
71 mCBContext.hwc = this;
72 mCBContext.procs.invalidate = &hook_invalidate;
Mathias Agopian31d28432012-04-03 16:31:39 -070073 mCBContext.procs.vsync = &hook_vsync;
Mathias Agopianc7d14e22011-08-01 16:32:21 -070074 mHwc->registerProcs(mHwc, &mCBContext.procs);
Mathias Agopian31d28432012-04-03 16:31:39 -070075 memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));
Mathias Agopianc7d14e22011-08-01 16:32:21 -070076 }
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -070077 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 {
Mathias Agopian3a778712012-04-09 14:16:47 -070083 needVSyncThread = true;
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070084 }
Mathias Agopianc7d14e22011-08-01 16:32:21 -070085 }
Mathias Agopian3a778712012-04-09 14:16:47 -070086 } 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);
Mathias Agopiana350ff92010-08-10 17:14:02 -070093 }
94}
95
96HWComposer::~HWComposer() {
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -070097 eventControl(EVENT_VSYNC, 0);
Mathias Agopiana350ff92010-08-10 17:14:02 -070098 free(mList);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070099 if (mVSyncThread != NULL) {
100 mVSyncThread->requestExitAndWait();
101 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700102 if (mHwc) {
103 hwc_close(mHwc);
104 }
105}
106
107status_t HWComposer::initCheck() const {
108 return mHwc ? NO_ERROR : NO_INIT;
109}
110
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700111void HWComposer::hook_invalidate(struct hwc_procs* procs) {
112 reinterpret_cast<cb_context *>(procs)->hwc->invalidate();
113}
114
Mathias Agopian31d28432012-04-03 16:31:39 -0700115void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) {
116 reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp);
117}
118
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700119void HWComposer::invalidate() {
Mathias Agopiane2c2f922011-10-05 15:00:22 -0700120 mFlinger->repaintEverything();
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700121}
122
Mathias Agopian31d28432012-04-03 16:31:39 -0700123void HWComposer::vsync(int dpy, int64_t timestamp) {
Mathias Agopian2965b262012-04-08 15:13:32 -0700124 ATRACE_INT("VSYNC", ++mVSyncCount&1);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700125 mEventHandler.onVSyncReceived(dpy, timestamp);
126}
127
Mathias Agopian03e40722012-04-26 16:11:59 -0700128void HWComposer::eventControl(int event, int enabled) {
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700129 status_t err = NO_ERROR;
Erik Gilling1a3bf412012-04-06 14:13:32 -0700130 if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700131 if (!mDebugForceFakeVSync) {
132 err = mHwc->methods->eventControl(mHwc, event, enabled);
Mathias Agopian03e40722012-04-26 16:11:59 -0700133 // 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));
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700137 }
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700138 }
Mathias Agopian3a778712012-04-09 14:16:47 -0700139
140 if (err == NO_ERROR && mVSyncThread != NULL) {
141 mVSyncThread->setEnabled(enabled);
142 }
Mathias Agopian31d28432012-04-03 16:31:39 -0700143}
144
Mathias Agopiana350ff92010-08-10 17:14:02 -0700145void 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) {
Mathias Agopian45721772010-08-12 15:03:26 -0700151 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 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700158 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);
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700166 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 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700187 return (status_t)err;
188}
189
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700190size_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
Mathias Agopiana350ff92010-08-10 17:14:02 -0700200status_t HWComposer::commit() const {
201 int err = mHwc->set(mHwc, mDpy, mSur, mList);
Mathias Agopian58959342010-10-07 14:57:04 -0700202 if (mList) {
203 mList->flags &= ~HWC_GEOMETRY_CHANGED;
204 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700205 return (status_t)err;
206}
207
Antti Hatalaf5f27122010-09-09 02:33:05 -0700208status_t HWComposer::release() const {
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700209 if (mHwc) {
Mathias Agopian22ffb112012-04-10 21:04:02 -0700210 if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
211 mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0);
212 }
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700213 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;
Antti Hatalaf5f27122010-09-09 02:33:05 -0700227}
228
Mathias Agopian45721772010-08-12 15:03:26 -0700229size_t HWComposer::getNumLayers() const {
230 return mList ? mList->numHwLayers : 0;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700231}
232
Mathias Agopian45721772010-08-12 15:03:26 -0700233hwc_layer_t* HWComposer::getLayers() const {
234 return mList ? mList->hwLayers : 0;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700235}
236
Mathias Agopian22da60c2011-09-09 00:49:11 -0700237void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
238 const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
Mathias Agopian83727852010-09-23 18:13:21 -0700239 if (mHwc && mList) {
240 result.append("Hardware Composer state:\n");
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700241 result.appendFormat(" mDebugForceFakeVSync=%d\n",
242 mDebugForceFakeVSync);
243 result.appendFormat(" numHwLayers=%u, flags=%08x\n",
Mathias Agopian83727852010-09-23 18:13:21 -0700244 mList->numHwLayers, mList->flags);
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700245 result.append(
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700246 " type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
247 "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
248 // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
Mathias Agopian83727852010-09-23 18:13:21 -0700249 for (size_t i=0 ; i<mList->numHwLayers ; i++) {
250 const hwc_layer_t& l(mList->hwLayers[i]);
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700251 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 }
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700259 result.appendFormat(
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700260 " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
Mathias Agopian83727852010-09-23 18:13:21 -0700261 l.compositionType ? "OVERLAY" : "FB",
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700262 intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
Mathias Agopian83727852010-09-23 18:13:21 -0700263 l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
Mathias Agopian22da60c2011-09-09 00:49:11 -0700264 l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700265 layer->getName().string());
Mathias Agopian83727852010-09-23 18:13:21 -0700266 }
Erik Gilling1d21a9c2010-12-01 16:38:01 -0800267 }
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700268 if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_1 && mHwc->dump) {
Erik Gilling1d21a9c2010-12-01 16:38:01 -0800269 mHwc->dump(mHwc, buffer, SIZE);
270 result.append(buffer);
Mathias Agopian83727852010-09-23 18:13:21 -0700271 }
272}
273
Mathias Agopiana350ff92010-08-10 17:14:02 -0700274// ---------------------------------------------------------------------------
Mathias Agopian2965b262012-04-08 15:13:32 -0700275
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// ---------------------------------------------------------------------------
Mathias Agopiana350ff92010-08-10 17:14:02 -0700329}; // namespace android