blob: dd7023289fa5349118f9bd30edea829996792114 [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
Jesse Hall5880cc52012-06-05 23:40:32 -070019// Uncomment this to remove support for HWC_DEVICE_API_VERSION_0_3 and older
20// #define HWC_REMOVE_DEPRECATED_VERSIONS 1
21
Mathias Agopiana350ff92010-08-10 17:14:02 -070022#include <stdint.h>
Mathias Agopianf1352df2010-08-11 17:31:33 -070023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070026#include <sys/types.h>
27
28#include <utils/Errors.h>
Mathias Agopian83727852010-09-23 18:13:21 -070029#include <utils/String8.h>
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070030#include <utils/Thread.h>
Mathias Agopian2965b262012-04-08 15:13:32 -070031#include <utils/Trace.h>
Mathias Agopian22da60c2011-09-09 00:49:11 -070032#include <utils/Vector.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070033
Mathias Agopian921e6ac2012-07-23 23:11:29 -070034#include <ui/GraphicBuffer.h>
35
Mathias Agopiana350ff92010-08-10 17:14:02 -070036#include <hardware/hardware.h>
Mathias Agopian3eb38cb2012-04-03 22:09:52 -070037#include <hardware/hwcomposer.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070038
39#include <cutils/log.h>
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -070040#include <cutils/properties.h>
Mathias Agopiana350ff92010-08-10 17:14:02 -070041
Mathias Agopian921e6ac2012-07-23 23:11:29 -070042#include "Layer.h" // needed only for debugging
Mathias Agopian22da60c2011-09-09 00:49:11 -070043#include "LayerBase.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070044#include "HWComposer.h"
Mathias Agopianc7d14e22011-08-01 16:32:21 -070045#include "SurfaceFlinger.h"
Mathias Agopiana350ff92010-08-10 17:14:02 -070046
47namespace android {
Jesse Hall5880cc52012-06-05 23:40:32 -070048
49// ---------------------------------------------------------------------------
50// Support for HWC_DEVICE_API_VERSION_0_3 and older:
51// Since v0.3 is deprecated and support will be dropped soon, as much as
52// possible the code is written to target v1.0. When using a v0.3 HWC, we
Jesse Hallb685c542012-07-31 14:32:56 -070053// allocate v0.3 structures, but assign them to v1.0 pointers.
Jesse Hall5880cc52012-06-05 23:40:32 -070054
55#if HWC_REMOVE_DEPRECATED_VERSIONS
Jesse Hallb685c542012-07-31 14:32:56 -070056// We need complete types to satisfy semantic checks, even though the code
57// paths that use these won't get executed at runtime (and will likely be dead-
58// code-eliminated). When we remove the code to support v0.3 we can remove
Jesse Hall5880cc52012-06-05 23:40:32 -070059// these as well.
60typedef hwc_layer_1_t hwc_layer_t;
Jesse Hallb685c542012-07-31 14:32:56 -070061typedef hwc_display_contents_1_t hwc_layer_list_t;
Jesse Hall5880cc52012-06-05 23:40:32 -070062typedef hwc_composer_device_1_t hwc_composer_device_t;
63#endif
64
65// This function assumes we've already rejected HWC's with lower-than-required
66// versions. Don't use it for the initial "does HWC meet requirements" check!
67static bool hwcHasVersion(const hwc_composer_device_1_t* hwc, uint32_t version) {
68 if (HWC_REMOVE_DEPRECATED_VERSIONS &&
69 version <= HWC_DEVICE_API_VERSION_1_0) {
70 return true;
71 } else {
72 return hwc->common.version >= version;
73 }
74}
75
Jesse Hallb685c542012-07-31 14:32:56 -070076static bool hwcHasVsyncEvent(const hwc_composer_device_1_t* hwc) {
77 return hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_0_3);
78}
79
Jesse Hall5880cc52012-06-05 23:40:32 -070080static size_t sizeofHwcLayerList(const hwc_composer_device_1_t* hwc,
81 size_t numLayers) {
82 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
Jesse Hallb685c542012-07-31 14:32:56 -070083 return sizeof(hwc_display_contents_1_t) + numLayers*sizeof(hwc_layer_1_t);
Jesse Hall5880cc52012-06-05 23:40:32 -070084 } else {
85 return sizeof(hwc_layer_list_t) + numLayers*sizeof(hwc_layer_t);
86 }
87}
88
Jesse Hallb685c542012-07-31 14:32:56 -070089static int hwcEventControl(hwc_composer_device_1_t* hwc, int dpy,
90 int event, int enabled) {
91 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
Jesse Hallbbd164a2012-08-21 12:05:09 -070092 return hwc->eventControl(hwc, dpy, event, enabled);
Jesse Hallb685c542012-07-31 14:32:56 -070093 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -070094 hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
Jesse Hallb685c542012-07-31 14:32:56 -070095 return hwc0->methods->eventControl(hwc0, event, enabled);
96 }
97}
98
99static int hwcBlank(hwc_composer_device_1_t* hwc, int dpy, int blank) {
100 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
Jesse Hallbbd164a2012-08-21 12:05:09 -0700101 return hwc->blank(hwc, dpy, blank);
Jesse Hallb685c542012-07-31 14:32:56 -0700102 } else {
103 if (blank) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700104 hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
Jesse Hallb685c542012-07-31 14:32:56 -0700105 return hwc0->set(hwc0, NULL, NULL, NULL);
106 } else {
107 // HWC 0.x turns the screen on at the next set()
108 return NO_ERROR;
109 }
110 }
111}
112
113static int hwcPrepare(hwc_composer_device_1_t* hwc,
114 size_t numDisplays, hwc_display_contents_1_t** displays) {
115 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
116 return hwc->prepare(hwc, numDisplays, displays);
117 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -0700118 hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
119 hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(displays[0]);
Jesse Hallb685c542012-07-31 14:32:56 -0700120 // In the past, SurfaceFlinger would pass a NULL list when doing full
121 // OpenGL ES composition. I don't know what, if any, dependencies there
122 // are on this behavior, so I'm playing it safe and preserving it.
123 if (list0->numHwLayers == 0)
124 return hwc0->prepare(hwc0, NULL);
125 else
126 return hwc0->prepare(hwc0, list0);
127 }
128}
129
130static int hwcSet(hwc_composer_device_1_t* hwc, EGLDisplay dpy, EGLSurface sur,
131 size_t numDisplays, hwc_display_contents_1_t** displays) {
132 int err;
133 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
134 displays[0]->dpy = dpy;
135 displays[0]->sur = sur;
136 err = hwc->set(hwc, numDisplays, displays);
137 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -0700138 hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
139 hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(displays[0]);
Jesse Hallb685c542012-07-31 14:32:56 -0700140 err = hwc0->set(hwc0, dpy, sur, list0);
141 }
142 return err;
143}
144
145static uint32_t& hwcFlags(hwc_composer_device_1_t* hwc,
146 hwc_display_contents_1_t* display) {
147 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
148 return display->flags;
149 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -0700150 hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(display);
Jesse Hallb685c542012-07-31 14:32:56 -0700151 return list0->flags;
152 }
153}
154
155static size_t& hwcNumHwLayers(hwc_composer_device_1_t* hwc,
156 hwc_display_contents_1_t* display) {
157 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
158 return display->numHwLayers;
159 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -0700160 hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(display);
Jesse Hallb685c542012-07-31 14:32:56 -0700161 return list0->numHwLayers;
162 }
163}
164
Jesse Hallbbd164a2012-08-21 12:05:09 -0700165static void hwcDump(hwc_composer_device_1_t* hwc, char* buff, int buff_len) {
166 if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_1_0)) {
167 if (hwc->dump)
168 hwc->dump(hwc, buff, buff_len);
169 } else if (hwcHasVersion(hwc, HWC_DEVICE_API_VERSION_0_1)) {
170 hwc_composer_device_t* hwc0 = reinterpret_cast<hwc_composer_device_t*>(hwc);
171 if (hwc0->dump)
172 hwc0->dump(hwc0, buff, buff_len);
173 }
174}
175
Mathias Agopiana350ff92010-08-10 17:14:02 -0700176// ---------------------------------------------------------------------------
177
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700178struct HWComposer::cb_context {
179 struct callbacks : public hwc_procs_t {
180 // these are here to facilitate the transition when adding
181 // new callbacks (an implementation can check for NULL before
182 // calling a new callback).
183 void (*zero[4])(void);
184 };
185 callbacks procs;
186 HWComposer* hwc;
187};
188
189// ---------------------------------------------------------------------------
190
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700191HWComposer::HWComposer(
192 const sp<SurfaceFlinger>& flinger,
Mathias Agopian8b736f12012-08-13 17:54:26 -0700193 EventHandler& handler,
194 framebuffer_device_t const* fbDev)
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700195 : mFlinger(flinger),
Jesse Hall8f971ff2012-08-22 11:50:00 -0700196 mModule(0), mHwc(0), mNumDisplays(1), mCapacity(0),
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700197 mCBContext(new cb_context),
Mathias Agopiane60b0682012-08-21 23:34:09 -0700198 mEventHandler(handler),
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700199 mVSyncCount(0), mDebugForceFakeVSync(false)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700200{
Mathias Agopiane60b0682012-08-21 23:34:09 -0700201 for (size_t i =0 ; i<MAX_DISPLAYS ; i++) {
202 mLists[i] = 0;
203 }
Jesse Hallb685c542012-07-31 14:32:56 -0700204
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700205 char value[PROPERTY_VALUE_MAX];
206 property_get("debug.sf.no_hw_vsync", value, "0");
207 mDebugForceFakeVSync = atoi(value);
208
Mathias Agopian028508c2012-07-25 21:12:12 -0700209 bool needVSyncThread = true;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700210 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
Steve Block32397c12012-01-05 23:22:43 +0000211 ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700212 if (err == 0) {
Jesse Hall5880cc52012-06-05 23:40:32 -0700213 err = hwc_open_1(mModule, &mHwc);
Steve Blocke6f43dd2012-01-06 19:20:56 +0000214 ALOGE_IF(err, "%s device failed to initialize (%s)",
Mathias Agopiana350ff92010-08-10 17:14:02 -0700215 HWC_HARDWARE_COMPOSER, strerror(-err));
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700216 if (err == 0) {
Jesse Hall5880cc52012-06-05 23:40:32 -0700217 if (HWC_REMOVE_DEPRECATED_VERSIONS &&
218 mHwc->common.version < HWC_DEVICE_API_VERSION_1_0) {
219 ALOGE("%s device version %#x too old, will not be used",
220 HWC_HARDWARE_COMPOSER, mHwc->common.version);
221 hwc_close_1(mHwc);
222 mHwc = NULL;
223 }
224 }
225
226 if (mHwc) {
Jesse Hallbbd164a2012-08-21 12:05:09 -0700227 if (mHwc->registerProcs) {
228 mCBContext->hwc = this;
229 mCBContext->procs.invalidate = &hook_invalidate;
230 mCBContext->procs.vsync = &hook_vsync;
231 memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
232 mHwc->registerProcs(mHwc, &mCBContext->procs);
233 }
234
Mathias Agopiane60b0682012-08-21 23:34:09 -0700235 // these IDs are always reserved
236 mTokens.markBit(HWC_DISPLAY_PRIMARY);
237 mTokens.markBit(HWC_DISPLAY_EXTERNAL);
238
Jesse Hallb685c542012-07-31 14:32:56 -0700239 // always turn vsync off when we start
240 needVSyncThread = false;
241 if (hwcHasVsyncEvent(mHwc)) {
242 hwcEventControl(mHwc, 0, HWC_EVENT_VSYNC, 0);
Mathias Agopian888c8222012-08-04 21:10:38 -0700243
244 int period;
245 if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700246 mDisplayData[0].refresh = nsecs_t(period);
Mathias Agopian888c8222012-08-04 21:10:38 -0700247 }
Jesse Hallb685c542012-07-31 14:32:56 -0700248 } else {
249 needVSyncThread = true;
Mathias Agopian028508c2012-07-25 21:12:12 -0700250 }
Jesse Hallb685c542012-07-31 14:32:56 -0700251
Jesse Hall8f971ff2012-08-22 11:50:00 -0700252 if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
253 mNumDisplays = HWC_NUM_DISPLAY_TYPES;
254
Jesse Hallb685c542012-07-31 14:32:56 -0700255 // create initial empty display contents for display 0
Jesse Hall8f971ff2012-08-22 11:50:00 -0700256 createWorkList(HWC_DISPLAY_PRIMARY, 0);
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700257 }
Mathias Agopian3a778712012-04-09 14:16:47 -0700258 }
259
Mathias Agopian8b736f12012-08-13 17:54:26 -0700260
261 if (fbDev) {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700262 if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
263 mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / fbDev->fps);
264 ALOGW("getting VSYNC period from fb HAL: %lld", mDisplayData[0].refresh);
Mathias Agopian888c8222012-08-04 21:10:38 -0700265 }
Mathias Agopiane60b0682012-08-21 23:34:09 -0700266 mDisplayData[HWC_DISPLAY_PRIMARY].xdpi = fbDev->xdpi;
267 mDisplayData[HWC_DISPLAY_PRIMARY].ydpi = fbDev->ydpi;
Mathias Agopian888c8222012-08-04 21:10:38 -0700268 }
269
Mathias Agopiane60b0682012-08-21 23:34:09 -0700270 if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
271 mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / 60.0);
272 ALOGW("getting VSYNC period thin air: %lld", mDisplayData[0].refresh);
Mathias Agopian888c8222012-08-04 21:10:38 -0700273 }
274
Mathias Agopian3a778712012-04-09 14:16:47 -0700275 if (needVSyncThread) {
276 // we don't have VSYNC support, we need to fake it
277 mVSyncThread = new VSyncThread(*this);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700278 }
279}
280
281HWComposer::~HWComposer() {
Jesse Hallb685c542012-07-31 14:32:56 -0700282 hwcEventControl(mHwc, 0, EVENT_VSYNC, 0);
Mathias Agopiane60b0682012-08-21 23:34:09 -0700283 for (size_t i = 0; i < MAX_DISPLAYS; i++) {
Jesse Hallb685c542012-07-31 14:32:56 -0700284 free(mLists[i]);
Mathias Agopiane60b0682012-08-21 23:34:09 -0700285 }
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700286 if (mVSyncThread != NULL) {
287 mVSyncThread->requestExitAndWait();
288 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700289 if (mHwc) {
Jesse Hall5880cc52012-06-05 23:40:32 -0700290 hwc_close_1(mHwc);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700291 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700292 delete mCBContext;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700293}
294
295status_t HWComposer::initCheck() const {
296 return mHwc ? NO_ERROR : NO_INIT;
297}
298
Jesse Hallbbd164a2012-08-21 12:05:09 -0700299void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
300 cb_context* ctx = reinterpret_cast<cb_context*>(
301 const_cast<hwc_procs_t*>(procs));
302 ctx->hwc->invalidate();
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700303}
304
Jesse Hallbbd164a2012-08-21 12:05:09 -0700305void HWComposer::hook_vsync(const struct hwc_procs* procs, int dpy,
306 int64_t timestamp) {
307 cb_context* ctx = reinterpret_cast<cb_context*>(
308 const_cast<hwc_procs_t*>(procs));
309 ctx->hwc->vsync(dpy, timestamp);
Mathias Agopian31d28432012-04-03 16:31:39 -0700310}
311
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700312void HWComposer::invalidate() {
Mathias Agopiane2c2f922011-10-05 15:00:22 -0700313 mFlinger->repaintEverything();
Mathias Agopianc7d14e22011-08-01 16:32:21 -0700314}
315
Mathias Agopian31d28432012-04-03 16:31:39 -0700316void HWComposer::vsync(int dpy, int64_t timestamp) {
Mathias Agopian2965b262012-04-08 15:13:32 -0700317 ATRACE_INT("VSYNC", ++mVSyncCount&1);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700318 mEventHandler.onVSyncReceived(dpy, timestamp);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700319 Mutex::Autolock _l(mLock);
320 mLastHwVSync = timestamp;
321}
322
Mathias Agopiane60b0682012-08-21 23:34:09 -0700323int32_t HWComposer::allocateDisplayId() {
324 if (mTokens.isFull()) {
325 return NO_MEMORY;
326 }
327
328 // FIXME: for now we don't support h/w composition wifi displays
329 return -1;
330
331 int32_t id = mTokens.firstUnmarkedBit();
332 mTokens.markBit(id);
333 return id;
334}
335
336status_t HWComposer::freeDisplayId(int32_t id) {
337 if (id < MAX_DISPLAYS) {
338 return BAD_VALUE;
339 }
340 if (!mTokens.hasBit(id)) {
341 return BAD_INDEX;
342 }
343 mTokens.clearBit(id);
344 return NO_ERROR;
345}
346
Mathias Agopian888c8222012-08-04 21:10:38 -0700347nsecs_t HWComposer::getRefreshPeriod() const {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700348 return mDisplayData[0].refresh;
Mathias Agopian888c8222012-08-04 21:10:38 -0700349}
350
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700351nsecs_t HWComposer::getRefreshTimestamp() const {
352 // this returns the last refresh timestamp.
353 // if the last one is not available, we estimate it based on
354 // the refresh period and whatever closest timestamp we have.
355 Mutex::Autolock _l(mLock);
356 nsecs_t now = systemTime(CLOCK_MONOTONIC);
Mathias Agopiane60b0682012-08-21 23:34:09 -0700357 return now - ((now - mLastHwVSync) % mDisplayData[0].refresh);
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700358}
359
Mathias Agopian8b736f12012-08-13 17:54:26 -0700360float HWComposer::getDpiX() const {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700361 return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi;
Mathias Agopian8b736f12012-08-13 17:54:26 -0700362}
363
364float HWComposer::getDpiY() const {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700365 return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi;
Mathias Agopian8b736f12012-08-13 17:54:26 -0700366}
367
Mathias Agopian03e40722012-04-26 16:11:59 -0700368void HWComposer::eventControl(int event, int enabled) {
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700369 status_t err = NO_ERROR;
Erik Gilling1a3bf412012-04-06 14:13:32 -0700370 if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700371 if (!mDebugForceFakeVSync) {
Jesse Hallb685c542012-07-31 14:32:56 -0700372 err = hwcEventControl(mHwc, 0, event, enabled);
Mathias Agopian03e40722012-04-26 16:11:59 -0700373 // error here should not happen -- not sure what we should
374 // do if it does.
375 ALOGE_IF(err, "eventControl(%d, %d) failed %s",
376 event, enabled, strerror(-err));
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700377 }
Mathias Agopian3eb38cb2012-04-03 22:09:52 -0700378 }
Mathias Agopian3a778712012-04-09 14:16:47 -0700379
380 if (err == NO_ERROR && mVSyncThread != NULL) {
381 mVSyncThread->setEnabled(enabled);
382 }
Mathias Agopian31d28432012-04-03 16:31:39 -0700383}
384
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700385status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700386 if (!mTokens.hasBit(id)) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700387 return BAD_INDEX;
Mathias Agopiane60b0682012-08-21 23:34:09 -0700388 }
Mathias Agopian1e260872012-08-08 18:35:12 -0700389
Mathias Agopiane60b0682012-08-21 23:34:09 -0700390 // FIXME: handle multiple displays
Mathias Agopian45721772010-08-12 15:03:26 -0700391 if (mHwc) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700392 // TODO: must handle multiple displays here
Jesse Hallb685c542012-07-31 14:32:56 -0700393 // mLists[0] is NULL only when this is called from the constructor
394 if (!mLists[0] || mCapacity < numLayers) {
395 free(mLists[0]);
Jesse Hall5880cc52012-06-05 23:40:32 -0700396 size_t size = sizeofHwcLayerList(mHwc, numLayers);
Jesse Hallb685c542012-07-31 14:32:56 -0700397 mLists[0] = (hwc_display_contents_1_t*)malloc(size);
Mathias Agopian45721772010-08-12 15:03:26 -0700398 mCapacity = numLayers;
399 }
Jesse Hallb685c542012-07-31 14:32:56 -0700400 hwcFlags(mHwc, mLists[0]) = HWC_GEOMETRY_CHANGED;
401 hwcNumHwLayers(mHwc, mLists[0]) = numLayers;
402 if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
403 mLists[0]->flipFenceFd = -1;
404 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700405 }
406 return NO_ERROR;
407}
408
Mathias Agopiane60b0682012-08-21 23:34:09 -0700409status_t HWComposer::prepare() {
Jesse Hall8f971ff2012-08-22 11:50:00 -0700410 int err = hwcPrepare(mHwc, mNumDisplays,
Jesse Hallb685c542012-07-31 14:32:56 -0700411 const_cast<hwc_display_contents_1_t**>(mLists));
Mathias Agopiane60b0682012-08-21 23:34:09 -0700412
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700413 if (err == NO_ERROR) {
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700414
415 // here we're just making sure that "skip" layers are set
416 // to HWC_FRAMEBUFFER and we're also counting how many layers
417 // we have of each type.
418 // It would be nice if we could get rid of this entirely, which I
419 // think is almost possible.
420
421 // TODO: must handle multiple displays here
Mathias Agopiane60b0682012-08-21 23:34:09 -0700422 if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
423 size_t count = getNumLayers(0);
424 struct hwc_display_contents_1* disp = mLists[0];
425 mDisplayData[0].hasFbComp = false;
426 mDisplayData[0].hasOvComp = false;
427 for (size_t i=0 ; i<count ; i++) {
428 hwc_layer_1_t* l = &disp->hwLayers[i];
Mathias Agopian1e260872012-08-08 18:35:12 -0700429 if (l->flags & HWC_SKIP_LAYER) {
430 l->compositionType = HWC_FRAMEBUFFER;
431 }
Mathias Agopiane60b0682012-08-21 23:34:09 -0700432 if (l->compositionType == HWC_FRAMEBUFFER)
433 mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
434 if (l->compositionType == HWC_OVERLAY)
435 mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700436 }
Mathias Agopiane60b0682012-08-21 23:34:09 -0700437 } else {
438 size_t count = getNumLayers(0);
439 hwc_layer_list_t* disp = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
440 mDisplayData[0].hasFbComp = false;
441 mDisplayData[0].hasOvComp = false;
442 for (size_t i=0 ; i<count ; i++) {
443 hwc_layer_t* l = &disp->hwLayers[i];
444 if (l->flags & HWC_SKIP_LAYER) {
445 l->compositionType = HWC_FRAMEBUFFER;
446 }
447 if (l->compositionType == HWC_FRAMEBUFFER)
448 mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
449 if (l->compositionType == HWC_OVERLAY)
450 mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700451 }
452 }
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700453 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700454 return (status_t)err;
455}
456
Mathias Agopiane60b0682012-08-21 23:34:09 -0700457bool HWComposer::hasHwcComposition(int32_t id) const {
458 if (!mTokens.hasBit(id))
459 return false;
460 return mDisplayData[id].hasOvComp;
Mathias Agopian9c6e2972011-09-20 17:21:56 -0700461}
462
Mathias Agopiane60b0682012-08-21 23:34:09 -0700463bool HWComposer::hasGlesComposition(int32_t id) const {
464 if (!mTokens.hasBit(id))
465 return false;
466 return mDisplayData[id].hasFbComp;
467}
468
469status_t HWComposer::commit() const {
Mathias Agopian86303202012-07-24 22:46:10 -0700470 int err = NO_ERROR;
471 if (mHwc) {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700472 void* fbDisplay = eglGetCurrentDisplay();
473 void* fbSurface = eglGetCurrentSurface(EGL_DRAW);
Jesse Hall8f971ff2012-08-22 11:50:00 -0700474 err = hwcSet(mHwc, fbDisplay, fbSurface, mNumDisplays,
Jesse Hallb685c542012-07-31 14:32:56 -0700475 const_cast<hwc_display_contents_1_t**>(mLists));
476 if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
477 if (mLists[0]->flipFenceFd != -1) {
478 close(mLists[0]->flipFenceFd);
479 mLists[0]->flipFenceFd = -1;
480 }
Mathias Agopian86303202012-07-24 22:46:10 -0700481 }
Jesse Hallb685c542012-07-31 14:32:56 -0700482 hwcFlags(mHwc, mLists[0]) &= ~HWC_GEOMETRY_CHANGED;
Mathias Agopian58959342010-10-07 14:57:04 -0700483 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700484 return (status_t)err;
485}
486
Antti Hatalaf5f27122010-09-09 02:33:05 -0700487status_t HWComposer::release() const {
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700488 if (mHwc) {
Jesse Hallb685c542012-07-31 14:32:56 -0700489 if (hwcHasVsyncEvent(mHwc)) {
490 hwcEventControl(mHwc, 0, HWC_EVENT_VSYNC, 0);
Mathias Agopian22ffb112012-04-10 21:04:02 -0700491 }
Jesse Hallb685c542012-07-31 14:32:56 -0700492 return (status_t)hwcBlank(mHwc, 0, 1);
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700493 }
494 return NO_ERROR;
495}
496
Colin Cross10fbdb62012-07-12 17:56:34 -0700497status_t HWComposer::acquire() const {
498 if (mHwc) {
Jesse Hallb685c542012-07-31 14:32:56 -0700499 return (status_t)hwcBlank(mHwc, 0, 0);
Colin Cross10fbdb62012-07-12 17:56:34 -0700500 }
Colin Cross10fbdb62012-07-12 17:56:34 -0700501 return NO_ERROR;
502}
503
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700504status_t HWComposer::disable() {
505 if (mHwc) {
Jesse Hallb685c542012-07-31 14:32:56 -0700506 hwcNumHwLayers(mHwc, mLists[0]) = 0;
Jesse Hall8f971ff2012-08-22 11:50:00 -0700507 int err = hwcPrepare(mHwc, mNumDisplays, mLists);
Mathias Agopian7ee4cd52011-09-02 12:22:39 -0700508 return (status_t)err;
509 }
510 return NO_ERROR;
Antti Hatalaf5f27122010-09-09 02:33:05 -0700511}
512
Mathias Agopian1e260872012-08-08 18:35:12 -0700513size_t HWComposer::getNumLayers(int32_t id) const { // FIXME: handle multiple displays
Jesse Hallb685c542012-07-31 14:32:56 -0700514 return mHwc ? hwcNumHwLayers(mHwc, mLists[0]) : 0;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700515}
516
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700517/*
518 * Helper template to implement a concrete HWCLayer
519 * This holds the pointer to the concrete hwc layer type
520 * and implements the "iterable" side of HWCLayer.
521 */
522template<typename CONCRETE, typename HWCTYPE>
523class Iterable : public HWComposer::HWCLayer {
524protected:
525 HWCTYPE* const mLayerList;
526 HWCTYPE* mCurrentLayer;
527 Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
528 inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
529 inline HWCTYPE* getLayer() { return mCurrentLayer; }
530 virtual ~Iterable() { }
531private:
532 // returns a copy of ourselves
533 virtual HWComposer::HWCLayer* dup() {
534 return new CONCRETE( static_cast<const CONCRETE&>(*this) );
535 }
536 virtual status_t setLayer(size_t index) {
537 mCurrentLayer = &mLayerList[index];
538 return NO_ERROR;
539 }
540};
541
Jesse Hall5880cc52012-06-05 23:40:32 -0700542// #if !HWC_REMOVE_DEPRECATED_VERSIONS
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700543/*
544 * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_0_3
545 * This implements the HWCLayer side of HWCIterableLayer.
546 */
Jesse Hall5880cc52012-06-05 23:40:32 -0700547class HWCLayerVersion0 : public Iterable<HWCLayerVersion0, hwc_layer_t> {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700548public:
Jesse Hall5880cc52012-06-05 23:40:32 -0700549 HWCLayerVersion0(hwc_layer_t* layer)
550 : Iterable<HWCLayerVersion0, hwc_layer_t>(layer) { }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700551
552 virtual int32_t getCompositionType() const {
553 return getLayer()->compositionType;
554 }
555 virtual uint32_t getHints() const {
556 return getLayer()->hints;
557 }
Jesse Hallef194142012-06-14 14:45:17 -0700558 virtual int getAndResetReleaseFenceFd() {
559 // not supported on VERSION_03
560 return -1;
561 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700562 virtual void setAcquireFenceFd(int fenceFd) {
563 if (fenceFd != -1) {
564 ALOGE("HWC 0.x can't handle acquire fences");
565 close(fenceFd);
566 }
567 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700568
569 virtual void setDefaultState() {
570 getLayer()->compositionType = HWC_FRAMEBUFFER;
571 getLayer()->hints = 0;
572 getLayer()->flags = HWC_SKIP_LAYER;
573 getLayer()->transform = 0;
574 getLayer()->blending = HWC_BLENDING_NONE;
575 getLayer()->visibleRegionScreen.numRects = 0;
576 getLayer()->visibleRegionScreen.rects = NULL;
577 }
578 virtual void setSkip(bool skip) {
579 if (skip) {
580 getLayer()->flags |= HWC_SKIP_LAYER;
581 } else {
582 getLayer()->flags &= ~HWC_SKIP_LAYER;
583 }
584 }
585 virtual void setBlending(uint32_t blending) {
586 getLayer()->blending = blending;
587 }
588 virtual void setTransform(uint32_t transform) {
589 getLayer()->transform = transform;
590 }
591 virtual void setFrame(const Rect& frame) {
592 reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame;
593 }
594 virtual void setCrop(const Rect& crop) {
595 reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
596 }
597 virtual void setVisibleRegionScreen(const Region& reg) {
598 getLayer()->visibleRegionScreen.rects =
599 reinterpret_cast<hwc_rect_t const *>(
600 reg.getArray(&getLayer()->visibleRegionScreen.numRects));
601 }
602 virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
603 if (buffer == 0 || buffer->handle == 0) {
604 getLayer()->compositionType = HWC_FRAMEBUFFER;
605 getLayer()->flags |= HWC_SKIP_LAYER;
606 getLayer()->handle = 0;
607 } else {
608 getLayer()->handle = buffer->handle;
609 }
610 }
611};
Jesse Hall5880cc52012-06-05 23:40:32 -0700612// #endif // !HWC_REMOVE_DEPRECATED_VERSIONS
613
614/*
615 * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
616 * This implements the HWCLayer side of HWCIterableLayer.
617 */
618class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
619public:
620 HWCLayerVersion1(hwc_layer_1_t* layer)
621 : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer) { }
622
623 virtual int32_t getCompositionType() const {
624 return getLayer()->compositionType;
625 }
626 virtual uint32_t getHints() const {
627 return getLayer()->hints;
628 }
Jesse Hallef194142012-06-14 14:45:17 -0700629 virtual int getAndResetReleaseFenceFd() {
630 int fd = getLayer()->releaseFenceFd;
631 getLayer()->releaseFenceFd = -1;
632 return fd;
633 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700634 virtual void setAcquireFenceFd(int fenceFd) {
635 getLayer()->acquireFenceFd = fenceFd;
636 }
Jesse Hall5880cc52012-06-05 23:40:32 -0700637
638 virtual void setDefaultState() {
639 getLayer()->compositionType = HWC_FRAMEBUFFER;
640 getLayer()->hints = 0;
641 getLayer()->flags = HWC_SKIP_LAYER;
642 getLayer()->transform = 0;
643 getLayer()->blending = HWC_BLENDING_NONE;
644 getLayer()->visibleRegionScreen.numRects = 0;
645 getLayer()->visibleRegionScreen.rects = NULL;
646 getLayer()->acquireFenceFd = -1;
647 getLayer()->releaseFenceFd = -1;
648 }
649 virtual void setSkip(bool skip) {
650 if (skip) {
651 getLayer()->flags |= HWC_SKIP_LAYER;
652 } else {
653 getLayer()->flags &= ~HWC_SKIP_LAYER;
654 }
655 }
656 virtual void setBlending(uint32_t blending) {
657 getLayer()->blending = blending;
658 }
659 virtual void setTransform(uint32_t transform) {
660 getLayer()->transform = transform;
661 }
662 virtual void setFrame(const Rect& frame) {
663 reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame;
664 }
665 virtual void setCrop(const Rect& crop) {
666 reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
667 }
668 virtual void setVisibleRegionScreen(const Region& reg) {
669 getLayer()->visibleRegionScreen.rects =
670 reinterpret_cast<hwc_rect_t const *>(
671 reg.getArray(&getLayer()->visibleRegionScreen.numRects));
672 }
673 virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
674 if (buffer == 0 || buffer->handle == 0) {
675 getLayer()->compositionType = HWC_FRAMEBUFFER;
676 getLayer()->flags |= HWC_SKIP_LAYER;
677 getLayer()->handle = 0;
678 } else {
679 getLayer()->handle = buffer->handle;
680 }
681 }
682};
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700683
684/*
685 * returns an iterator initialized at a given index in the layer list
686 */
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700687HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
Mathias Agopiane60b0682012-08-21 23:34:09 -0700688 if (!mTokens.hasBit(id))
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700689 return LayerListIterator();
690
Mathias Agopiane60b0682012-08-21 23:34:09 -0700691 // FIXME: handle multiple displays
Mathias Agopian748f3df2012-08-10 14:36:40 -0700692 if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700693 return LayerListIterator();
Jesse Hall5880cc52012-06-05 23:40:32 -0700694 if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
Jesse Hallb685c542012-07-31 14:32:56 -0700695 return LayerListIterator(new HWCLayerVersion1(mLists[0]->hwLayers),
696 index);
Jesse Hall5880cc52012-06-05 23:40:32 -0700697 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -0700698 hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
Jesse Hall5880cc52012-06-05 23:40:32 -0700699 return LayerListIterator(new HWCLayerVersion0(list0->hwLayers), index);
700 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700701}
702
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700703/*
704 * returns an iterator on the beginning of the layer list
705 */
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700706HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700707 return getLayerIterator(id, 0);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700708}
709
710/*
711 * returns an iterator on the end of the layer list
712 */
Mathias Agopian5f20e2d2012-08-10 18:50:38 -0700713HWComposer::LayerListIterator HWComposer::end(int32_t id) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700714 return getLayerIterator(id, getNumLayers(id));
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700715}
716
Mathias Agopian22da60c2011-09-09 00:49:11 -0700717void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
718 const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
Jesse Hallb685c542012-07-31 14:32:56 -0700719 if (mHwc) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700720 hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
Jesse Hallb685c542012-07-31 14:32:56 -0700721
Mathias Agopian83727852010-09-23 18:13:21 -0700722 result.append("Hardware Composer state:\n");
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700723 result.appendFormat(" mDebugForceFakeVSync=%d\n",
724 mDebugForceFakeVSync);
725 result.appendFormat(" numHwLayers=%u, flags=%08x\n",
Jesse Hallb685c542012-07-31 14:32:56 -0700726 hwcNumHwLayers(mHwc, mLists[0]), hwcFlags(mHwc, mLists[0]));
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700727 result.append(
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700728 " type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
729 "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
730 // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
Jesse Hallb685c542012-07-31 14:32:56 -0700731 for (size_t i=0 ; i<hwcNumHwLayers(mHwc, mLists[0]) ; i++) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700732 hwc_layer_1_t const* lp;
Jesse Hall5880cc52012-06-05 23:40:32 -0700733 if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
Mathias Agopian1e260872012-08-08 18:35:12 -0700734 lp = &mLists[0]->hwLayers[i];
Jesse Hall5880cc52012-06-05 23:40:32 -0700735 } else {
Mathias Agopian1e260872012-08-08 18:35:12 -0700736 // FIXME: here we rely on hwc_layer_1_t and hwc_layer_t having the same layout
737 lp = reinterpret_cast<hwc_layer_1_t const*>(&list0->hwLayers[i]);
Jesse Hall5880cc52012-06-05 23:40:32 -0700738 }
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700739 const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
740 int32_t format = -1;
741 if (layer->getLayer() != NULL) {
742 const sp<GraphicBuffer>& buffer(layer->getLayer()->getActiveBuffer());
743 if (buffer != NULL) {
744 format = buffer->getPixelFormat();
745 }
746 }
Mathias Agopian1e260872012-08-08 18:35:12 -0700747 const hwc_layer_1_t& l(*lp);
Mathias Agopiane2c4f4e2012-04-10 18:25:31 -0700748 result.appendFormat(
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700749 " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
Mathias Agopian83727852010-09-23 18:13:21 -0700750 l.compositionType ? "OVERLAY" : "FB",
Mathias Agopianaebac5f2011-09-29 18:07:08 -0700751 intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
Mathias Agopian83727852010-09-23 18:13:21 -0700752 l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
Mathias Agopian22da60c2011-09-09 00:49:11 -0700753 l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
Mathias Agopianfb4d5d52011-09-20 15:13:14 -0700754 layer->getName().string());
Mathias Agopian83727852010-09-23 18:13:21 -0700755 }
Erik Gilling1d21a9c2010-12-01 16:38:01 -0800756 }
Jesse Hallbbd164a2012-08-21 12:05:09 -0700757 if (mHwc) {
758 hwcDump(mHwc, buffer, SIZE);
Erik Gilling1d21a9c2010-12-01 16:38:01 -0800759 result.append(buffer);
Mathias Agopian83727852010-09-23 18:13:21 -0700760 }
761}
762
Mathias Agopiana350ff92010-08-10 17:14:02 -0700763// ---------------------------------------------------------------------------
Mathias Agopian2965b262012-04-08 15:13:32 -0700764
765HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
766 : mHwc(hwc), mEnabled(false),
767 mNextFakeVSync(0),
Mathias Agopiane60b0682012-08-21 23:34:09 -0700768 mRefreshPeriod(hwc.getRefreshPeriod())
Mathias Agopian2965b262012-04-08 15:13:32 -0700769{
770}
771
772void HWComposer::VSyncThread::setEnabled(bool enabled) {
773 Mutex::Autolock _l(mLock);
774 mEnabled = enabled;
775 mCondition.signal();
776}
777
778void HWComposer::VSyncThread::onFirstRef() {
779 run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
780}
781
782bool HWComposer::VSyncThread::threadLoop() {
783 { // scope for lock
784 Mutex::Autolock _l(mLock);
785 while (!mEnabled) {
786 mCondition.wait(mLock);
787 }
788 }
789
790 const nsecs_t period = mRefreshPeriod;
791 const nsecs_t now = systemTime(CLOCK_MONOTONIC);
792 nsecs_t next_vsync = mNextFakeVSync;
793 nsecs_t sleep = next_vsync - now;
794 if (sleep < 0) {
795 // we missed, find where the next vsync should be
796 sleep = (period - ((now - next_vsync) % period));
797 next_vsync = now + sleep;
798 }
799 mNextFakeVSync = next_vsync + period;
800
801 struct timespec spec;
802 spec.tv_sec = next_vsync / 1000000000;
803 spec.tv_nsec = next_vsync % 1000000000;
804
805 int err;
806 do {
807 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
808 } while (err<0 && errno == EINTR);
809
810 if (err == 0) {
811 mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
812 }
813
814 return true;
815}
816
817// ---------------------------------------------------------------------------
Mathias Agopiana350ff92010-08-10 17:14:02 -0700818}; // namespace android