hwc.cpp revision 25322c7f78dfeb2c9c441dc0720dba6c639b198c
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012, The Linux Foundation. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#include <fcntl.h> 19#include <errno.h> 20 21#include <cutils/log.h> 22#include <cutils/atomic.h> 23#include <EGL/egl.h> 24 25#include <overlay.h> 26#include <fb_priv.h> 27#include <mdp_version.h> 28#include "hwc_utils.h" 29#include "hwc_qbuf.h" 30#include "hwc_video.h" 31#include "hwc_uimirror.h" 32#include "hwc_copybit.h" 33#include "external.h" 34#include "hwc_mdpcomp.h" 35#include "hwc_extonly.h" 36 37using namespace qhwc; 38 39static int hwc_device_open(const struct hw_module_t* module, 40 const char* name, 41 struct hw_device_t** device); 42 43static struct hw_module_methods_t hwc_module_methods = { 44 open: hwc_device_open 45}; 46 47hwc_module_t HAL_MODULE_INFO_SYM = { 48 common: { 49 tag: HARDWARE_MODULE_TAG, 50 version_major: 2, 51 version_minor: 0, 52 id: HWC_HARDWARE_MODULE_ID, 53 name: "Qualcomm Hardware Composer Module", 54 author: "CodeAurora Forum", 55 methods: &hwc_module_methods, 56 dso: 0, 57 reserved: {0}, 58 } 59}; 60 61/* 62 * Save callback functions registered to HWC 63 */ 64static void hwc_registerProcs(struct hwc_composer_device_1* dev, 65 hwc_procs_t const* procs) 66{ 67 hwc_context_t* ctx = (hwc_context_t*)(dev); 68 if(!ctx) { 69 ALOGE("%s: Invalid context", __FUNCTION__); 70 return; 71 } 72 ctx->proc = procs; 73 74 // don't start listening for events until we can do something with them 75 init_uevent_thread(ctx); 76} 77 78//Helper 79static void reset() { 80 //reset for this draw round 81 VideoOverlay::reset(); 82 ExtOnly::reset(); 83 UIMirrorOverlay::reset(); 84 ExtOnly::reset(); 85 //TODO MDPComp 86} 87 88static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 89 hwc_display_contents_1_t** displays) 90{ 91 hwc_context_t* ctx = (hwc_context_t*)(dev); 92 ctx->overlayInUse = false; 93 94 reset(); 95 96 //If securing of h/w in progress skip comp using overlay. 97 if(ctx->mSecuring == true) return 0; 98 99 for (uint32_t i = 0; i < numDisplays; i++) { 100 hwc_display_contents_1_t *list = displays[i]; 101 //XXX: Actually handle the multiple displays 102 if (LIKELY(list && list->numHwLayers)) { 103 ctx->dpys[i] = list->dpy; 104 105 if(ctx->isPoweredDown) 106 ALOGW("SF called %s after a POWERDOWN", __FUNCTION__); 107 108 getLayerStats(ctx, list); 109 if(VideoOverlay::prepare(ctx, list)) { 110 ctx->overlayInUse = true; 111 //Nothing here 112 } else if(ExtOnly::prepare(ctx, list)) { 113 ctx->overlayInUse = true; 114 } else if(UIMirrorOverlay::prepare(ctx, list)) { 115 ctx->overlayInUse = true; 116 } else if(MDPComp::configure(dev, list)) { 117 ctx->overlayInUse = true; 118 } else if (0) { 119 //Other features 120 ctx->overlayInUse = true; 121 } else { // Else set this flag to false, otherwise video cases 122 // fail in non-overlay targets. 123 ctx->overlayInUse = false; 124 } 125 } 126 } 127 128 return 0; 129} 130 131static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 132 int event, int enabled) 133{ 134 int ret = 0; 135 hwc_context_t* ctx = (hwc_context_t*)(dev); 136 private_module_t* m = reinterpret_cast<private_module_t*>( 137 ctx->mFbDev->common.module); 138 //XXX: Handle dpy 139 switch(event) { 140 case HWC_EVENT_VSYNC: 141 if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0) 142 ret = -errno; 143 144 if(ctx->mExtDisplay->getExternalDisplay()) { 145 ret = ctx->mExtDisplay->enableHDMIVsync(enabled); 146 } 147 break; 148 default: 149 ret = -EINVAL; 150 } 151 return ret; 152} 153 154static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 155{ 156 //XXX: Handle based on dpy 157 hwc_context_t* ctx = (hwc_context_t*)(dev); 158 private_module_t* m = reinterpret_cast<private_module_t*>( 159 ctx->mFbDev->common.module); 160 if(blank) { 161 ctx->mOverlay->setState(ovutils::OV_CLOSED); 162 ctx->qbuf->unlockAllPrevious(); 163 ALOGD("HWC Calling POWERDOWN ..."); 164 ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); 165 ALOGD("HWC Done POWERDOWN ..."); 166 ctx->isPoweredDown = true; 167 } else { 168 ALOGD("HWC Calling UNBLANK ..."); 169 ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK); 170 ALOGD("HWC Done UNBLANK ..."); 171 ctx->isPoweredDown = false; 172 } 173 return 0; 174} 175 176static int hwc_query(struct hwc_composer_device_1* dev, 177 int param, int* value) 178{ 179 hwc_context_t* ctx = (hwc_context_t*)(dev); 180 private_module_t* m = reinterpret_cast<private_module_t*>( 181 ctx->mFbDev->common.module); 182 183 switch (param) { 184 case HWC_BACKGROUND_LAYER_SUPPORTED: 185 // Not supported for now 186 value[0] = 0; 187 break; 188 case HWC_VSYNC_PERIOD: 189 value[0] = m->fps; 190 ALOGI("fps: %d", value[0]); 191 break; 192 default: 193 return -EINVAL; 194 } 195 return 0; 196 197} 198 199static int hwc_set(hwc_composer_device_1 *dev, 200 size_t numDisplays, 201 hwc_display_contents_1_t** displays) 202{ 203 int ret = 0; 204 hwc_context_t* ctx = (hwc_context_t*)(dev); 205 for (uint32_t i = 0; i <numDisplays; i++) { 206 hwc_display_contents_1_t* list = displays[i]; 207 //XXX: Actually handle the multiple displays 208 if (LIKELY(list)) { 209 VideoOverlay::draw(ctx, list); 210 ExtOnly::draw(ctx, list); 211 MDPComp::draw(ctx, list); 212 EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy, 213 (EGLSurface)list->sur); 214 wait4fbPost(ctx); 215 //Can draw to HDMI only when fb_post is reached 216 UIMirrorOverlay::draw(ctx); 217 //HDMI commit and primary commit (PAN) happening in parallel 218 if(ctx->mExtDisplay->getExternalDisplay()) 219 ctx->mExtDisplay->commit(); 220 //Virtual barrier for threads to finish 221 wait4Pan(ctx); 222 } else { 223 ctx->mOverlay->setState(ovutils::OV_CLOSED); 224 ctx->qbuf->unlockAll(); 225 } 226 227 if(!ctx->overlayInUse) 228 ctx->mOverlay->setState(ovutils::OV_CLOSED); 229 } 230 ctx->qbuf->unlockAllPrevious(); 231 return ret; 232} 233 234static int hwc_device_close(struct hw_device_t *dev) 235{ 236 if(!dev) { 237 ALOGE("%s: NULL device pointer", __FUNCTION__); 238 return -1; 239 } 240 closeContext((hwc_context_t*)dev); 241 free(dev); 242 243 return 0; 244} 245 246static int hwc_device_open(const struct hw_module_t* module, const char* name, 247 struct hw_device_t** device) 248{ 249 int status = -EINVAL; 250 251 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 252 struct hwc_context_t *dev; 253 dev = (hwc_context_t*)malloc(sizeof(*dev)); 254 memset(dev, 0, sizeof(*dev)); 255 256 //Initialize hwc context 257 initContext(dev); 258 259 //Setup HWC methods 260 dev->device.common.tag = HARDWARE_DEVICE_TAG; 261 dev->device.common.version = HWC_DEVICE_API_VERSION_1_0; 262 dev->device.common.module = const_cast<hw_module_t*>(module); 263 dev->device.common.close = hwc_device_close; 264 dev->device.prepare = hwc_prepare; 265 dev->device.set = hwc_set; 266 dev->device.eventControl = hwc_eventControl; 267 dev->device.blank = hwc_blank; 268 dev->device.query = hwc_query; 269 dev->device.registerProcs = hwc_registerProcs; 270 *device = &dev->device.common; 271 status = 0; 272 } 273 return status; 274} 275