HWComposer.cpp revision 3a77871383bc1a03cc866686d81628493d14de7c
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 bool needVSyncThread = false; 57 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); 58 ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); 59 if (err == 0) { 60 err = hwc_open(mModule, &mHwc); 61 ALOGE_IF(err, "%s device failed to initialize (%s)", 62 HWC_HARDWARE_COMPOSER, strerror(-err)); 63 if (err == 0) { 64 if (mHwc->registerProcs) { 65 mCBContext.hwc = this; 66 mCBContext.procs.invalidate = &hook_invalidate; 67 mCBContext.procs.vsync = &hook_vsync; 68 mHwc->registerProcs(mHwc, &mCBContext.procs); 69 memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero)); 70 } 71 if (mHwc->common.version < HWC_DEVICE_API_VERSION_0_3) { 72 needVSyncThread = true; 73 } 74 } 75 } else { 76 needVSyncThread = true; 77 } 78 79 if (needVSyncThread) { 80 // we don't have VSYNC support, we need to fake it 81 mVSyncThread = new VSyncThread(*this); 82 } 83} 84 85HWComposer::~HWComposer() { 86 free(mList); 87 if (mVSyncThread != NULL) { 88 mVSyncThread->requestExitAndWait(); 89 } 90 if (mHwc) { 91 hwc_close(mHwc); 92 } 93} 94 95status_t HWComposer::initCheck() const { 96 return mHwc ? NO_ERROR : NO_INIT; 97} 98 99void HWComposer::hook_invalidate(struct hwc_procs* procs) { 100 reinterpret_cast<cb_context *>(procs)->hwc->invalidate(); 101} 102 103void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) { 104 reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp); 105} 106 107void HWComposer::invalidate() { 108 mFlinger->repaintEverything(); 109} 110 111void HWComposer::vsync(int dpy, int64_t timestamp) { 112 ATRACE_INT("VSYNC", ++mVSyncCount&1); 113 mEventHandler.onVSyncReceived(dpy, timestamp); 114} 115 116status_t HWComposer::eventControl(int event, int enabled) { 117 status_t err = NO_ERROR; 118 if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) { 119 err = mHwc->methods->eventControl(mHwc, event, enabled); 120 } 121 122 if (err == NO_ERROR && mVSyncThread != NULL) { 123 mVSyncThread->setEnabled(enabled); 124 } 125 126 return err; 127} 128 129void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) { 130 mDpy = (hwc_display_t)dpy; 131 mSur = (hwc_surface_t)sur; 132} 133 134status_t HWComposer::createWorkList(size_t numLayers) { 135 if (mHwc) { 136 if (!mList || mCapacity < numLayers) { 137 free(mList); 138 size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t); 139 mList = (hwc_layer_list_t*)malloc(size); 140 mCapacity = numLayers; 141 } 142 mList->flags = HWC_GEOMETRY_CHANGED; 143 mList->numHwLayers = numLayers; 144 } 145 return NO_ERROR; 146} 147 148status_t HWComposer::prepare() const { 149 int err = mHwc->prepare(mHwc, mList); 150 if (err == NO_ERROR) { 151 size_t numOVLayers = 0; 152 size_t numFBLayers = 0; 153 size_t count = mList->numHwLayers; 154 for (size_t i=0 ; i<count ; i++) { 155 hwc_layer& l(mList->hwLayers[i]); 156 if (l.flags & HWC_SKIP_LAYER) { 157 l.compositionType = HWC_FRAMEBUFFER; 158 } 159 switch (l.compositionType) { 160 case HWC_OVERLAY: 161 numOVLayers++; 162 break; 163 case HWC_FRAMEBUFFER: 164 numFBLayers++; 165 break; 166 } 167 } 168 mNumOVLayers = numOVLayers; 169 mNumFBLayers = numFBLayers; 170 } 171 return (status_t)err; 172} 173 174size_t HWComposer::getLayerCount(int type) const { 175 switch (type) { 176 case HWC_OVERLAY: 177 return mNumOVLayers; 178 case HWC_FRAMEBUFFER: 179 return mNumFBLayers; 180 } 181 return 0; 182} 183 184status_t HWComposer::commit() const { 185 int err = mHwc->set(mHwc, mDpy, mSur, mList); 186 if (mList) { 187 mList->flags &= ~HWC_GEOMETRY_CHANGED; 188 } 189 return (status_t)err; 190} 191 192status_t HWComposer::release() const { 193 if (mHwc) { 194 int err = mHwc->set(mHwc, NULL, NULL, NULL); 195 return (status_t)err; 196 } 197 return NO_ERROR; 198} 199 200status_t HWComposer::disable() { 201 if (mHwc) { 202 free(mList); 203 mList = NULL; 204 int err = mHwc->prepare(mHwc, NULL); 205 return (status_t)err; 206 } 207 return NO_ERROR; 208} 209 210size_t HWComposer::getNumLayers() const { 211 return mList ? mList->numHwLayers : 0; 212} 213 214hwc_layer_t* HWComposer::getLayers() const { 215 return mList ? mList->hwLayers : 0; 216} 217 218void HWComposer::dump(String8& result, char* buffer, size_t SIZE, 219 const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const { 220 if (mHwc && mList) { 221 result.append("Hardware Composer state:\n"); 222 223 snprintf(buffer, SIZE, " numHwLayers=%u, flags=%08x\n", 224 mList->numHwLayers, mList->flags); 225 result.append(buffer); 226 result.append( 227 " type | handle | hints | flags | tr | blend | format | source crop | frame name \n" 228 "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); 229 // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] 230 for (size_t i=0 ; i<mList->numHwLayers ; i++) { 231 const hwc_layer_t& l(mList->hwLayers[i]); 232 const sp<LayerBase> layer(visibleLayersSortedByZ[i]); 233 int32_t format = -1; 234 if (layer->getLayer() != NULL) { 235 const sp<GraphicBuffer>& buffer(layer->getLayer()->getActiveBuffer()); 236 if (buffer != NULL) { 237 format = buffer->getPixelFormat(); 238 } 239 } 240 snprintf(buffer, SIZE, 241 " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", 242 l.compositionType ? "OVERLAY" : "FB", 243 intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format, 244 l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, 245 l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, 246 layer->getName().string()); 247 result.append(buffer); 248 } 249 } 250 if (mHwc && mHwc->common.version >= 1 && mHwc->dump) { 251 mHwc->dump(mHwc, buffer, SIZE); 252 result.append(buffer); 253 } 254} 255 256// --------------------------------------------------------------------------- 257 258HWComposer::VSyncThread::VSyncThread(HWComposer& hwc) 259 : mHwc(hwc), mEnabled(false), 260 mNextFakeVSync(0), 261 mRefreshPeriod(hwc.mRefreshPeriod) 262{ 263} 264 265void HWComposer::VSyncThread::setEnabled(bool enabled) { 266 Mutex::Autolock _l(mLock); 267 mEnabled = enabled; 268 mCondition.signal(); 269} 270 271void HWComposer::VSyncThread::onFirstRef() { 272 run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); 273} 274 275bool HWComposer::VSyncThread::threadLoop() { 276 { // scope for lock 277 Mutex::Autolock _l(mLock); 278 while (!mEnabled) { 279 mCondition.wait(mLock); 280 } 281 } 282 283 const nsecs_t period = mRefreshPeriod; 284 const nsecs_t now = systemTime(CLOCK_MONOTONIC); 285 nsecs_t next_vsync = mNextFakeVSync; 286 nsecs_t sleep = next_vsync - now; 287 if (sleep < 0) { 288 // we missed, find where the next vsync should be 289 sleep = (period - ((now - next_vsync) % period)); 290 next_vsync = now + sleep; 291 } 292 mNextFakeVSync = next_vsync + period; 293 294 struct timespec spec; 295 spec.tv_sec = next_vsync / 1000000000; 296 spec.tv_nsec = next_vsync % 1000000000; 297 298 int err; 299 do { 300 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); 301 } while (err<0 && errno == EINTR); 302 303 if (err == 0) { 304 mHwc.mEventHandler.onVSyncReceived(0, next_vsync); 305 } 306 307 return true; 308} 309 310// --------------------------------------------------------------------------- 311}; // namespace android 312