hwc.cpp revision 5d0935531842ab9cf01775a77e92f204e6d40971
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* 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->device.reserved_proc[0] = (void*)procs; 73} 74 75static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) 76{ 77 hwc_context_t* ctx = (hwc_context_t*)(dev); 78 ctx->overlayInUse = false; 79 80 //Prepare is called after a vsync, so unlock previous buffers here. 81 ctx->qbuf->unlockAllPrevious(); 82 return 0; 83 84 if (LIKELY(list)) { 85 //reset for this draw round 86 VideoOverlay::reset(); 87 ExtOnly::reset(); 88 89 getLayerStats(ctx, list); 90 if(VideoOverlay::prepare(ctx, list)) { 91 ctx->overlayInUse = true; 92 //Nothing here 93 } else if(ExtOnly::prepare(ctx, list)) { 94 ctx->overlayInUse = true; 95 } else if(UIMirrorOverlay::prepare(ctx, list)) { 96 ctx->overlayInUse = true; 97 } else if(MDPComp::configure(dev, list)) { 98 ctx->overlayInUse = true; 99 } else if (0) { 100 //Other features 101 ctx->overlayInUse = true; 102 } else { // Else set this flag to false, otherwise video cases 103 // fail in non-overlay targets. 104 ctx->overlayInUse = false; 105 } 106 CopyBit::prepare(ctx, list); 107 } 108 109 return 0; 110} 111 112static int hwc_eventControl(struct hwc_composer_device* dev, 113 int event, int enabled) 114{ 115 int ret = 0; 116 hwc_context_t* ctx = (hwc_context_t*)(dev); 117 private_module_t* m = reinterpret_cast<private_module_t*>( 118 ctx->mFbDev->common.module); 119 switch(event) { 120 case HWC_EVENT_VSYNC: 121 if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0) 122 ret = -errno; 123 124 if(ctx->mExtDisplay->getExternalDisplay()) { 125 ret = ctx->mExtDisplay->enableHDMIVsync(enabled); 126 } 127 break; 128 default: 129 ret = -EINVAL; 130 } 131 return ret; 132} 133 134static int hwc_query(struct hwc_composer_device* dev, 135 int param, int* value) 136{ 137 hwc_context_t* ctx = (hwc_context_t*)(dev); 138 private_module_t* m = reinterpret_cast<private_module_t*>( 139 ctx->mFbDev->common.module); 140 141 switch (param) { 142 case HWC_BACKGROUND_LAYER_SUPPORTED: 143 // Not supported for now 144 value[0] = 0; 145 break; 146 case HWC_VSYNC_PERIOD: 147 value[0] = 1000000000.0 / m->fps; 148 ALOGI("fps: %d", value[0]); 149 break; 150 default: 151 return -EINVAL; 152 } 153 return 0; 154 155} 156 157static int hwc_set(hwc_composer_device_t *dev, 158 hwc_display_t dpy, 159 hwc_surface_t sur, 160 hwc_layer_list_t* list) 161{ 162 int ret = 0; 163 hwc_context_t* ctx = (hwc_context_t*)(dev); 164 if (LIKELY(list)) { 165 VideoOverlay::draw(ctx, list); 166 ExtOnly::draw(ctx, list); 167 CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); 168 MDPComp::draw(ctx, list); 169 EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); 170 UIMirrorOverlay::draw(ctx); 171 if(ctx->mExtDisplay->getExternalDisplay()) 172 ctx->mExtDisplay->commit(); 173 } else { 174 ctx->mOverlay->setState(ovutils::OV_CLOSED); 175 ctx->qbuf->unlockAllPrevious(); 176 } 177 178 if(!ctx->overlayInUse) 179 ctx->mOverlay->setState(ovutils::OV_CLOSED); 180 181 return ret; 182} 183 184static int hwc_device_close(struct hw_device_t *dev) 185{ 186 if(!dev) { 187 ALOGE("%s: NULL device pointer", __FUNCTION__); 188 return -1; 189 } 190 closeContext((hwc_context_t*)dev); 191 free(dev); 192 193 return 0; 194} 195 196static int hwc_device_open(const struct hw_module_t* module, const char* name, 197 struct hw_device_t** device) 198{ 199 int status = -EINVAL; 200 201 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 202 struct hwc_context_t *dev; 203 dev = (hwc_context_t*)malloc(sizeof(*dev)); 204 memset(dev, 0, sizeof(*dev)); 205 206 //Initialize hwc context 207 initContext(dev); 208 209 //Setup HWC methods 210 hwc_methods_t *methods; 211 methods = (hwc_methods_t *)malloc(sizeof(*methods)); 212 memset(methods, 0, sizeof(*methods)); 213 methods->eventControl = hwc_eventControl; 214 215 dev->device.common.tag = HARDWARE_DEVICE_TAG; 216 dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; 217 dev->device.common.module = const_cast<hw_module_t*>(module); 218 dev->device.common.close = hwc_device_close; 219 dev->device.prepare = hwc_prepare; 220 dev->device.set = hwc_set; 221 dev->device.registerProcs = hwc_registerProcs; 222 dev->device.query = hwc_query; 223 dev->device.methods = methods; 224 *device = &dev->device.common; 225 status = 0; 226 } 227 return status; 228} 229