blob: d42153c45cd3429266363cf3abc697706b564377 [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>
35
36#include <EGL/egl.h>
37
Mathias Agopian22da60c2011-09-09 00:49:11 -070038#include "LayerBase.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070039#include "HWComposer.h"
Mathias Agopianc7d14e22011-08-01 16:32:21 -070040#include "SurfaceFlinger.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070041
42namespace android {
43// ---------------------------------------------------------------------------
44
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070045HWComposer::HWComposer(
46 const sp<SurfaceFlinger>& flinger,
47 EventHandler& handler,
48 nsecs_t refreshPeriod)
Mathias Agopianc7d14e22011-08-01 16:32:21 -070049 : mFlinger(flinger),
50 mModule(0), mHwc(0), mList(0), mCapacity(0),
Mathias Agopian9c6e2972011-09-20 17:21:56 -070051 mNumOVLayers(0), mNumFBLayers(0),
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070052 mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE),
53 mEventHandler(handler),
Mathias Agopian2965b262012-04-08 15:13:32 -070054 mRefreshPeriod(refreshPeriod), mVSyncCount(0)
Mathias Agopiana350ff92010-08-10 17:14:02 -070055{
56 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
Steve Block32397c12012-01-05 23:22:43 +000057 ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
Mathias Agopiana350ff92010-08-10 17:14:02 -070058 if (err == 0) {
59 err = hwc_open(mModule, &mHwc);
Steve Blocke6f43dd2012-01-06 19:20:56 +000060 ALOGE_IF(err, "%s device failed to initialize (%s)",
Mathias Agopiana350ff92010-08-10 17:14:02 -070061 HWC_HARDWARE_COMPOSER, strerror(-err));
Mathias Agopianc7d14e22011-08-01 16:32:21 -070062 if (err == 0) {
63 if (mHwc->registerProcs) {
64 mCBContext.hwc = this;
65 mCBContext.procs.invalidate = &hook_invalidate;
Mathias Agopian31d28432012-04-03 16:31:39 -070066 mCBContext.procs.vsync = &hook_vsync;
Mathias Agopianc7d14e22011-08-01 16:32:21 -070067 mHwc->registerProcs(mHwc, &mCBContext.procs);
Mathias Agopian31d28432012-04-03 16:31:39 -070068 memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));
Mathias Agopianc7d14e22011-08-01 16:32:21 -070069 }
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070070
71 if (mHwc->common.version < HWC_DEVICE_API_VERSION_0_3) {
72 // we don't have VSYNC support, we need to fake it
73 mVSyncThread = new VSyncThread(*this);
74 }
Mathias Agopianc7d14e22011-08-01 16:32:21 -070075 }
Mathias Agopiana350ff92010-08-10 17:14:02 -070076 }
77}
78
79HWComposer::~HWComposer() {
80 free(mList);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070081 if (mVSyncThread != NULL) {
82 mVSyncThread->requestExitAndWait();
83 }
Mathias Agopiana350ff92010-08-10 17:14:02 -070084 if (mHwc) {
85 hwc_close(mHwc);
86 }
87}
88
89status_t HWComposer::initCheck() const {
90 return mHwc ? NO_ERROR : NO_INIT;
91}
92
Mathias Agopianc7d14e22011-08-01 16:32:21 -070093void HWComposer::hook_invalidate(struct hwc_procs* procs) {
94 reinterpret_cast<cb_context *>(procs)->hwc->invalidate();
95}
96
Mathias Agopian31d28432012-04-03 16:31:39 -070097void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) {
98 reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp);
99}
100
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700101void HWComposer::invalidate() {
Mathias Agopiane2c2f922011-10-05 15:00:22 -0700102 mFlinger->repaintEverything();
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700103}
104
Mathias Agopian31d28432012-04-03 16:31:39 -0700105void HWComposer::vsync(int dpy, int64_t timestamp) {
Mathias Agopian2965b262012-04-08 15:13:32 -0700106 ATRACE_INT("VSYNC", ++mVSyncCount&1);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700107 mEventHandler.onVSyncReceived(dpy, timestamp);
108}
109
110status_t HWComposer::eventControl(int event, int enabled) {
111 status_t err = NO_ERROR;
Erik Gilling1a3bf412012-04-06 14:13:32 -0700112 if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700113 err = mHwc->methods->eventControl(mHwc, event, enabled);
114 } else {
115 if (mVSyncThread != NULL) {
116 mVSyncThread->setEnabled(enabled);
117 } else {
118 err = BAD_VALUE;
119 }
120 }
121 return err;
Mathias Agopian31d28432012-04-03 16:31:39 -0700122}
123
Mathias Agopiana350ff92010-08-10 17:14:02 -0700124void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
125 mDpy = (hwc_display_t)dpy;
126 mSur = (hwc_surface_t)sur;
127}
128
129status_t HWComposer::createWorkList(size_t numLayers) {
Mathias Agopian45721772010-08-12 15:03:26 -0700130 if (mHwc) {
131 if (!mList || mCapacity < numLayers) {
132 free(mList);
133 size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
134 mList = (hwc_layer_list_t*)malloc(size);
135 mCapacity = numLayers;
136 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700137 mList->flags = HWC_GEOMETRY_CHANGED;
138 mList->numHwLayers = numLayers;
139 }
140 return NO_ERROR;
141}
142
143status_t HWComposer::prepare() const {
144 int err = mHwc->prepare(mHwc, mList);
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700145 if (err == NO_ERROR) {
146 size_t numOVLayers = 0;
147 size_t numFBLayers = 0;
148 size_t count = mList->numHwLayers;
149 for (size_t i=0 ; i<count ; i++) {
150 hwc_layer& l(mList->hwLayers[i]);
151 if (l.flags & HWC_SKIP_LAYER) {
152 l.compositionType = HWC_FRAMEBUFFER;
153 }
154 switch (l.compositionType) {
155 case HWC_OVERLAY:
156 numOVLayers++;
157 break;
158 case HWC_FRAMEBUFFER:
159 numFBLayers++;
160 break;
161 }
162 }
163 mNumOVLayers = numOVLayers;
164 mNumFBLayers = numFBLayers;
165 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700166 return (status_t)err;
167}
168
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700169size_t HWComposer::getLayerCount(int type) const {
170 switch (type) {
171 case HWC_OVERLAY:
172 return mNumOVLayers;
173 case HWC_FRAMEBUFFER:
174 return mNumFBLayers;
175 }
176 return 0;
177}
178
Mathias Agopiana350ff92010-08-10 17:14:02 -0700179status_t HWComposer::commit() const {
180 int err = mHwc->set(mHwc, mDpy, mSur, mList);
Mathias Agopian58959342010-10-07 14:57:04 -0700181 if (mList) {
182 mList->flags &= ~HWC_GEOMETRY_CHANGED;
183 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700184 return (status_t)err;
185}
186
Antti Hatalaf5f27122010-09-09 02:33:05 -0700187status_t HWComposer::release() const {
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700188 if (mHwc) {
189 int err = mHwc->set(mHwc, NULL, NULL, NULL);
190 return (status_t)err;
191 }
192 return NO_ERROR;
193}
194
195status_t HWComposer::disable() {
196 if (mHwc) {
197 free(mList);
198 mList = NULL;
199 int err = mHwc->prepare(mHwc, NULL);
200 return (status_t)err;
201 }
202 return NO_ERROR;
Antti Hatalaf5f27122010-09-09 02:33:05 -0700203}
204
Mathias Agopian45721772010-08-12 15:03:26 -0700205size_t HWComposer::getNumLayers() const {
206 return mList ? mList->numHwLayers : 0;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700207}
208
Mathias Agopian45721772010-08-12 15:03:26 -0700209hwc_layer_t* HWComposer::getLayers() const {
210 return mList ? mList->hwLayers : 0;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700211}
212
Mathias Agopian22da60c2011-09-09 00:49:11 -0700213void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
214 const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
Mathias Agopian83727852010-09-23 18:13:21 -0700215 if (mHwc && mList) {
216 result.append("Hardware Composer state:\n");
217
218 snprintf(buffer, SIZE, " numHwLayers=%u, flags=%08x\n",
219 mList->numHwLayers, mList->flags);
220 result.append(buffer);
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700221 result.append(
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700222 " type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
223 "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
224 // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
Mathias Agopian83727852010-09-23 18:13:21 -0700225 for (size_t i=0 ; i<mList->numHwLayers ; i++) {
226 const hwc_layer_t& l(mList->hwLayers[i]);
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700227 const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
228 int32_t format = -1;
229 if (layer->getLayer() != NULL) {
230 const sp<GraphicBuffer>& buffer(layer->getLayer()->getActiveBuffer());
231 if (buffer != NULL) {
232 format = buffer->getPixelFormat();
233 }
234 }
235 snprintf(buffer, SIZE,
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700236 " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
Mathias Agopian83727852010-09-23 18:13:21 -0700237 l.compositionType ? "OVERLAY" : "FB",
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700238 intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
Mathias Agopian83727852010-09-23 18:13:21 -0700239 l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
Mathias Agopian22da60c2011-09-09 00:49:11 -0700240 l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700241 layer->getName().string());
Mathias Agopian83727852010-09-23 18:13:21 -0700242 result.append(buffer);
243 }
Erik Gilling1d21a9c2010-12-01 16:38:01 -0800244 }
245 if (mHwc && mHwc->common.version >= 1 && mHwc->dump) {
246 mHwc->dump(mHwc, buffer, SIZE);
247 result.append(buffer);
Mathias Agopian83727852010-09-23 18:13:21 -0700248 }
249}
250
Mathias Agopiana350ff92010-08-10 17:14:02 -0700251// ---------------------------------------------------------------------------
Mathias Agopian2965b262012-04-08 15:13:32 -0700252
253HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
254 : mHwc(hwc), mEnabled(false),
255 mNextFakeVSync(0),
256 mRefreshPeriod(hwc.mRefreshPeriod)
257{
258}
259
260void HWComposer::VSyncThread::setEnabled(bool enabled) {
261 Mutex::Autolock _l(mLock);
262 mEnabled = enabled;
263 mCondition.signal();
264}
265
266void HWComposer::VSyncThread::onFirstRef() {
267 run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
268}
269
270bool HWComposer::VSyncThread::threadLoop() {
271 { // scope for lock
272 Mutex::Autolock _l(mLock);
273 while (!mEnabled) {
274 mCondition.wait(mLock);
275 }
276 }
277
278 const nsecs_t period = mRefreshPeriod;
279 const nsecs_t now = systemTime(CLOCK_MONOTONIC);
280 nsecs_t next_vsync = mNextFakeVSync;
281 nsecs_t sleep = next_vsync - now;
282 if (sleep < 0) {
283 // we missed, find where the next vsync should be
284 sleep = (period - ((now - next_vsync) % period));
285 next_vsync = now + sleep;
286 }
287 mNextFakeVSync = next_vsync + period;
288
289 struct timespec spec;
290 spec.tv_sec = next_vsync / 1000000000;
291 spec.tv_nsec = next_vsync % 1000000000;
292
293 int err;
294 do {
295 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
296 } while (err<0 && errno == EINTR);
297
298 if (err == 0) {
299 mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
300 }
301
302 return true;
303}
304
305// ---------------------------------------------------------------------------
Mathias Agopiana350ff92010-08-10 17:14:02 -0700306}; // namespace android