HWComposer.cpp revision 2965b26022f95051f65b09d7eac47cbe923855c9
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 36#include <EGL/egl.h> 37 38#include "LayerBase.h" 39#include "HWComposer.h" 40#include "SurfaceFlinger.h" 41 42namespace android { 43// --------------------------------------------------------------------------- 44 45HWComposer::HWComposer( 46 const sp<SurfaceFlinger>& flinger, 47 EventHandler& handler, 48 nsecs_t refreshPeriod) 49 : mFlinger(flinger), 50 mModule(0), mHwc(0), mList(0), mCapacity(0), 51 mNumOVLayers(0), mNumFBLayers(0), 52 mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE), 53 mEventHandler(handler), 54 mRefreshPeriod(refreshPeriod), mVSyncCount(0) 55{ 56 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); 57 ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); 58 if (err == 0) { 59 err = hwc_open(mModule, &mHwc); 60 ALOGE_IF(err, "%s device failed to initialize (%s)", 61 HWC_HARDWARE_COMPOSER, strerror(-err)); 62 if (err == 0) { 63 if (mHwc->registerProcs) { 64 mCBContext.hwc = this; 65 mCBContext.procs.invalidate = &hook_invalidate; 66 mCBContext.procs.vsync = &hook_vsync; 67 mHwc->registerProcs(mHwc, &mCBContext.procs); 68 memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero)); 69 } 70 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 } 75 } 76 } 77} 78 79HWComposer::~HWComposer() { 80 free(mList); 81 if (mVSyncThread != NULL) { 82 mVSyncThread->requestExitAndWait(); 83 } 84 if (mHwc) { 85 hwc_close(mHwc); 86 } 87} 88 89status_t HWComposer::initCheck() const { 90 return mHwc ? NO_ERROR : NO_INIT; 91} 92 93void HWComposer::hook_invalidate(struct hwc_procs* procs) { 94 reinterpret_cast<cb_context *>(procs)->hwc->invalidate(); 95} 96 97void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) { 98 reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp); 99} 100 101void HWComposer::invalidate() { 102 mFlinger->repaintEverything(); 103} 104 105void HWComposer::vsync(int dpy, int64_t timestamp) { 106 ATRACE_INT("VSYNC", ++mVSyncCount&1); 107 mEventHandler.onVSyncReceived(dpy, timestamp); 108} 109 110status_t HWComposer::eventControl(int event, int enabled) { 111 status_t err = NO_ERROR; 112 if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) { 113 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; 122} 123 124void 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) { 130 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 } 137 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); 145 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 } 166 return (status_t)err; 167} 168 169size_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 179status_t HWComposer::commit() const { 180 int err = mHwc->set(mHwc, mDpy, mSur, mList); 181 if (mList) { 182 mList->flags &= ~HWC_GEOMETRY_CHANGED; 183 } 184 return (status_t)err; 185} 186 187status_t HWComposer::release() const { 188 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; 203} 204 205size_t HWComposer::getNumLayers() const { 206 return mList ? mList->numHwLayers : 0; 207} 208 209hwc_layer_t* HWComposer::getLayers() const { 210 return mList ? mList->hwLayers : 0; 211} 212 213void HWComposer::dump(String8& result, char* buffer, size_t SIZE, 214 const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const { 215 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); 221 result.append( 222 " type | handle | hints | flags | tr | blend | format | source crop | frame name \n" 223 "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); 224 // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] 225 for (size_t i=0 ; i<mList->numHwLayers ; i++) { 226 const hwc_layer_t& l(mList->hwLayers[i]); 227 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, 236 " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", 237 l.compositionType ? "OVERLAY" : "FB", 238 intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format, 239 l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, 240 l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, 241 layer->getName().string()); 242 result.append(buffer); 243 } 244 } 245 if (mHwc && mHwc->common.version >= 1 && mHwc->dump) { 246 mHwc->dump(mHwc, buffer, SIZE); 247 result.append(buffer); 248 } 249} 250 251// --------------------------------------------------------------------------- 252 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// --------------------------------------------------------------------------- 306}; // namespace android 307