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 43 namespace android { 44 // --------------------------------------------------------------------------- 45 46 HWComposer::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 96 HWComposer::~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 107 status_t HWComposer::initCheck() const { 108 return mHwc ? NO_ERROR : NO_INIT; 109 } 110 111 void HWComposer::hook_invalidate(struct hwc_procs* procs) { 112 reinterpret_cast<cb_context *>(procs)->hwc->invalidate(); 113 } 114 115 void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) { 116 reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp); 117 } 118 119 void HWComposer::invalidate() { 120 mFlinger->repaintEverything(); 121 } 122 123 void HWComposer::vsync(int dpy, int64_t timestamp) { 124 ATRACE_INT("VSYNC", ++mVSyncCount&1); 125 mEventHandler.onVSyncReceived(dpy, timestamp); 126 } 127 128 void 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 145 void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) { 146 mDpy = (hwc_display_t)dpy; 147 mSur = (hwc_surface_t)sur; 148 } 149 150 status_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 164 status_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 190 size_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 200 status_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 208 status_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 219 status_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 229 size_t HWComposer::getNumLayers() const { 230 return mList ? mList->numHwLayers : 0; 231 } 232 233 hwc_layer_t* HWComposer::getLayers() const { 234 return mList ? mList->hwLayers : 0; 235 } 236 237 void 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 276 HWComposer::VSyncThread::VSyncThread(HWComposer& hwc) 277 : mHwc(hwc), mEnabled(false), 278 mNextFakeVSync(0), 279 mRefreshPeriod(hwc.mRefreshPeriod) 280 { 281 } 282 283 void HWComposer::VSyncThread::setEnabled(bool enabled) { 284 Mutex::Autolock _l(mLock); 285 mEnabled = enabled; 286 mCondition.signal(); 287 } 288 289 void HWComposer::VSyncThread::onFirstRef() { 290 run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); 291 } 292 293 bool 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