hwc.cpp revision a71a7ecd0323a16fe7728271474f8b7056c679d8
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012, Code Aurora Forum. 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 "hwc_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 78static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 79 hwc_display_contents_1_t** displays) 80{ 81 hwc_context_t* ctx = (hwc_context_t*)(dev); 82 ctx->overlayInUse = false; 83 84 //Prepare is called after a vsync, so unlock previous buffers here. 85 ctx->qbuf->unlockAllPrevious(); 86 87 for (uint32_t i = 0; i <numDisplays; i++) { 88 hwc_display_contents_1_t* list = displays[i]; 89 ctx->dpys[i] = list->dpy; 90 //XXX: Actually handle the multiple displays 91 if (LIKELY(list)) { 92 //reset for this draw round 93 VideoOverlay::reset(); 94 ExtOnly::reset(); 95 96 getLayerStats(ctx, list); 97 if(VideoOverlay::prepare(ctx, list)) { 98 ctx->overlayInUse = true; 99 //Nothing here 100 } else if(ExtOnly::prepare(ctx, list)) { 101 ctx->overlayInUse = true; 102 } else if(UIMirrorOverlay::prepare(ctx, list)) { 103 ctx->overlayInUse = true; 104 } else if(MDPComp::configure(dev, list)) { 105 ctx->overlayInUse = true; 106 } else if (0) { 107 //Other features 108 ctx->overlayInUse = true; 109 } else { // Else set this flag to false, otherwise video cases 110 // fail in non-overlay targets. 111 ctx->overlayInUse = false; 112 } 113 } 114 } 115 116 return 0; 117} 118 119static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 120 int event, int enabled) 121{ 122 int ret = 0; 123 hwc_context_t* ctx = (hwc_context_t*)(dev); 124 private_module_t* m = reinterpret_cast<private_module_t*>( 125 ctx->mFbDev->common.module); 126 //XXX: Handle dpy 127 switch(event) { 128 case HWC_EVENT_VSYNC: 129 if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0) 130 ret = -errno; 131 132 if(ctx->mExtDisplay->getExternalDisplay()) { 133 ret = ctx->mExtDisplay->enableHDMIVsync(enabled); 134 } 135 break; 136 default: 137 ret = -EINVAL; 138 } 139 return ret; 140} 141 142static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 143{ 144 //XXX: Handle based on dpy 145 hwc_context_t* ctx = (hwc_context_t*)(dev); 146 private_module_t* m = reinterpret_cast<private_module_t*>( 147 ctx->mFbDev->common.module); 148 if(blank) { 149 ctx->mOverlay->setState(ovutils::OV_CLOSED); 150 ctx->qbuf->unlockAllPrevious(); 151 ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); 152 } else { 153 ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK); 154 } 155 return 0; 156} 157 158static int hwc_query(struct hwc_composer_device_1* dev, 159 int param, int* value) 160{ 161 hwc_context_t* ctx = (hwc_context_t*)(dev); 162 private_module_t* m = reinterpret_cast<private_module_t*>( 163 ctx->mFbDev->common.module); 164 165 switch (param) { 166 case HWC_BACKGROUND_LAYER_SUPPORTED: 167 // Not supported for now 168 value[0] = 0; 169 break; 170 case HWC_VSYNC_PERIOD: 171 value[0] = 1000000000.0 / m->fps; 172 ALOGI("fps: %d", value[0]); 173 break; 174 default: 175 return -EINVAL; 176 } 177 return 0; 178 179} 180 181static int hwc_set(hwc_composer_device_1 *dev, 182 size_t numDisplays, 183 hwc_display_contents_1_t** displays) 184{ 185 int ret = 0; 186 hwc_context_t* ctx = (hwc_context_t*)(dev); 187 for (uint32_t i = 0; i <numDisplays; i++) { 188 hwc_display_contents_1_t* list = displays[i]; 189 //XXX: Actually handle the multiple displays 190 if (LIKELY(list)) { 191 VideoOverlay::draw(ctx, list); 192 ExtOnly::draw(ctx, list); 193 MDPComp::draw(ctx, list); 194 EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy, 195 (EGLSurface)list->sur); 196 wait4fbPost(ctx); 197 //Can draw to HDMI only when fb_post is reached 198 UIMirrorOverlay::draw(ctx); 199 //HDMI commit and primary commit (PAN) happening in parallel 200 if(ctx->mExtDisplay->getExternalDisplay()) 201 ctx->mExtDisplay->commit(); 202 //Virtual barrier for threads to finish 203 wait4Pan(ctx); 204 } else { 205 ctx->mOverlay->setState(ovutils::OV_CLOSED); 206 ctx->qbuf->unlockAll(); 207 } 208 209 if(!ctx->overlayInUse) 210 ctx->mOverlay->setState(ovutils::OV_CLOSED); 211 } 212 return ret; 213} 214 215static int hwc_device_close(struct hw_device_t *dev) 216{ 217 if(!dev) { 218 ALOGE("%s: NULL device pointer", __FUNCTION__); 219 return -1; 220 } 221 closeContext((hwc_context_t*)dev); 222 free(dev); 223 224 return 0; 225} 226 227static int hwc_device_open(const struct hw_module_t* module, const char* name, 228 struct hw_device_t** device) 229{ 230 int status = -EINVAL; 231 232 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 233 struct hwc_context_t *dev; 234 dev = (hwc_context_t*)malloc(sizeof(*dev)); 235 memset(dev, 0, sizeof(*dev)); 236 237 //Initialize hwc context 238 initContext(dev); 239 240 //Setup HWC methods 241 dev->device.common.tag = HARDWARE_DEVICE_TAG; 242 dev->device.common.version = HWC_DEVICE_API_VERSION_1_0; 243 dev->device.common.module = const_cast<hw_module_t*>(module); 244 dev->device.common.close = hwc_device_close; 245 dev->device.prepare = hwc_prepare; 246 dev->device.set = hwc_set; 247 dev->device.eventControl = hwc_eventControl; 248 dev->device.blank = hwc_blank; 249 dev->device.query = hwc_query; 250 dev->device.registerProcs = hwc_registerProcs; 251 *device = &dev->device.common; 252 status = 0; 253 } 254 return status; 255} 256