| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 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> |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 23 | #include <EGL/egl.h> |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 24 | |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 25 | #include <overlay.h> |
| 26 | #include <fb_priv.h> |
| Naseer Ahmed | 912842f | 2012-07-25 18:27:14 -0700 | [diff] [blame] | 27 | #include <mdp_version.h> |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 28 | #include "hwc_utils.h" |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 29 | #include "hwc_qbuf.h" |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 30 | #include "hwc_video.h" |
| Prashant Surana | cc5cb17 | 2012-08-13 11:49:01 +0530 | [diff] [blame] | 31 | #include "hwc_pip.h" |
| Arun Kumar K.R | 59d5b62 | 2012-06-25 17:34:58 -0700 | [diff] [blame] | 32 | #include "hwc_uimirror.h" |
| Sravan Kumar D.V.N | c80da70 | 2012-07-19 15:03:29 +0530 | [diff] [blame] | 33 | #include "hwc_copybit.h" |
| Arun Kumar K.R | a72904b | 2012-07-23 13:44:38 -0700 | [diff] [blame] | 34 | #include "hwc_external.h" |
| Jeykumar Sankaran | bd86fcf | 2012-07-23 12:22:21 -0700 | [diff] [blame] | 35 | #include "hwc_mdpcomp.h" |
| Saurabh Shah | bf3c454 | 2012-07-21 19:06:55 -0700 | [diff] [blame] | 36 | #include "hwc_extonly.h" |
| Jeykumar Sankaran | cfb095e | 2012-08-28 17:56:00 -0700 | [diff] [blame] | 37 | #include "qcom_ui.h" |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 38 | |
| Neti Ravi Kumar | c356c1c | 2012-09-16 01:35:41 +0530 | [diff] [blame] | 39 | #define VSYNC_DEBUG 0 |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 40 | using namespace qhwc; |
| 41 | |
| 42 | static int hwc_device_open(const struct hw_module_t* module, |
| 43 | const char* name, |
| 44 | struct hw_device_t** device); |
| 45 | |
| 46 | static struct hw_module_methods_t hwc_module_methods = { |
| 47 | open: hwc_device_open |
| 48 | }; |
| 49 | |
| 50 | hwc_module_t HAL_MODULE_INFO_SYM = { |
| 51 | common: { |
| 52 | tag: HARDWARE_MODULE_TAG, |
| 53 | version_major: 2, |
| 54 | version_minor: 0, |
| 55 | id: HWC_HARDWARE_MODULE_ID, |
| 56 | name: "Qualcomm Hardware Composer Module", |
| 57 | author: "CodeAurora Forum", |
| 58 | methods: &hwc_module_methods, |
| 59 | dso: 0, |
| 60 | reserved: {0}, |
| 61 | } |
| 62 | }; |
| 63 | |
| 64 | /* |
| 65 | * Save callback functions registered to HWC |
| 66 | */ |
| 67 | static void hwc_registerProcs(struct hwc_composer_device* dev, |
| 68 | hwc_procs_t const* procs) |
| 69 | { |
| 70 | hwc_context_t* ctx = (hwc_context_t*)(dev); |
| 71 | if(!ctx) { |
| 72 | ALOGE("%s: Invalid context", __FUNCTION__); |
| 73 | return; |
| 74 | } |
| 75 | ctx->device.reserved_proc[0] = (void*)procs; |
| Arun Kumar K.R | b25918a | 2012-08-22 16:09:48 -0700 | [diff] [blame] | 76 | |
| Neti Ravi Kumar | 673e493 | 2012-09-12 18:14:25 +0530 | [diff] [blame] | 77 | // Now that we have the functions needed, kick off |
| 78 | // the uevent & vsync threads |
| Arun Kumar K.R | b25918a | 2012-08-22 16:09:48 -0700 | [diff] [blame] | 79 | init_uevent_thread(ctx); |
| Neti Ravi Kumar | 673e493 | 2012-09-12 18:14:25 +0530 | [diff] [blame] | 80 | init_vsync_thread(ctx); |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) |
| 84 | { |
| 85 | hwc_context_t* ctx = (hwc_context_t*)(dev); |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 86 | ctx->overlayInUse = false; |
| 87 | |
| Amara Venkata Mastan Manoj Kumar | a4b0340 | 2012-09-05 18:18:51 -0700 | [diff] [blame] | 88 | if(ctx->mSecureConfig == true) { |
| 89 | // This will tear down External Display Device. |
| 90 | return 0; |
| 91 | } |
| 92 | |
| Amara Venkata Mastan Manoj Kumar | 211f9f4 | 2012-08-02 08:26:21 -0700 | [diff] [blame] | 93 | if(ctx->mExtDisplay->getExternalDisplay()) |
| 94 | ovutils::setExtType(ctx->mExtDisplay->getExternalDisplay()); |
| Pawan Kumar | 9d12887 | 2012-09-22 14:30:29 +0530 | [diff] [blame] | 95 | if (ctx->hdmi_pending == true) { |
| 96 | if ((qdutils::MDPVersion::getInstance().getMDPVersion() >= |
| 97 | qdutils::MDP_V4_2) || (ctx->mOverlay->getState() != |
| 98 | ovutils::OV_BYPASS_3_LAYER)) { |
| 99 | ctx->mExtDisplay->processUEventOnline((const char*)ctx->mHDMIEvent); |
| 100 | ctx->hdmi_pending = false; |
| 101 | } |
| 102 | } |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 103 | if (LIKELY(list)) { |
| Saurabh Shah | bf3c454 | 2012-07-21 19:06:55 -0700 | [diff] [blame] | 104 | //reset for this draw round |
| 105 | VideoOverlay::reset(); |
| Prashant Surana | cc5cb17 | 2012-08-13 11:49:01 +0530 | [diff] [blame] | 106 | VideoPIP::reset(); |
| Saurabh Shah | bf3c454 | 2012-07-21 19:06:55 -0700 | [diff] [blame] | 107 | ExtOnly::reset(); |
| 108 | |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 109 | getLayerStats(ctx, list); |
| Neti Ravi Kumar | 97d3484 | 2012-07-21 21:02:05 +0530 | [diff] [blame] | 110 | // Mark all layers to COPYBIT initially |
| 111 | CopyBit::prepare(ctx, list); |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 112 | if(VideoOverlay::prepare(ctx, list)) { |
| 113 | ctx->overlayInUse = true; |
| 114 | //Nothing here |
| Prashant Surana | cc5cb17 | 2012-08-13 11:49:01 +0530 | [diff] [blame] | 115 | } else if(VideoPIP::prepare(ctx, list)) { |
| 116 | ctx->overlayInUse = true; |
| Saurabh Shah | bf3c454 | 2012-07-21 19:06:55 -0700 | [diff] [blame] | 117 | } else if(ExtOnly::prepare(ctx, list)) { |
| 118 | ctx->overlayInUse = true; |
| Arun Kumar K.R | 59d5b62 | 2012-06-25 17:34:58 -0700 | [diff] [blame] | 119 | } else if(UIMirrorOverlay::prepare(ctx, list)) { |
| 120 | ctx->overlayInUse = true; |
| Jeykumar Sankaran | bd86fcf | 2012-07-23 12:22:21 -0700 | [diff] [blame] | 121 | } else if(MDPComp::configure(dev, list)) { |
| 122 | ctx->overlayInUse = true; |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 123 | } else if (0) { |
| 124 | //Other features |
| 125 | ctx->overlayInUse = true; |
| Sravan Kumar D.V.N | c80da70 | 2012-07-19 15:03:29 +0530 | [diff] [blame] | 126 | } else { // Else set this flag to false, otherwise video cases |
| 127 | // fail in non-overlay targets. |
| 128 | ctx->overlayInUse = false; |
| Jeykumar Sankaran | e8c4c54 | 2012-08-23 11:07:40 -0700 | [diff] [blame] | 129 | ctx->mOverlay->setState(ovutils::OV_CLOSED); |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 130 | } |
| Steve Kondik | 1a8d986 | 2012-10-31 14:20:41 -0700 | [diff] [blame] | 131 | qdutils::CBUtils::checkforGPULayer(list); |
| 132 | |
| Steve Kondik | 2657e2e | 2012-09-14 10:34:58 -0700 | [diff] [blame] | 133 | } else { |
| 134 | ctx->overlayInUse = false; |
| 135 | ctx->mOverlay->setState(ovutils::OV_CLOSED); |
| 136 | ctx->qbuf->unlockAll(); |
| Jeykumar Sankaran | cfb095e | 2012-08-28 17:56:00 -0700 | [diff] [blame] | 137 | |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 138 | } |
| 139 | return 0; |
| 140 | } |
| 141 | |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 142 | static int hwc_eventControl(struct hwc_composer_device* dev, |
| Arun Kumar K.R | 9813cf3 | 2012-07-27 19:49:03 -0700 | [diff] [blame] | 143 | int event, int value) |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 144 | { |
| 145 | int ret = 0; |
| Neti Ravi Kumar | c356c1c | 2012-09-16 01:35:41 +0530 | [diff] [blame] | 146 | static int prev_value, temp; |
| 147 | |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 148 | hwc_context_t* ctx = (hwc_context_t*)(dev); |
| 149 | private_module_t* m = reinterpret_cast<private_module_t*>( |
| 150 | ctx->mFbDev->common.module); |
| 151 | switch(event) { |
| Steve Kondik | 85ff2df | 2012-08-07 19:56:31 -0700 | [diff] [blame] | 152 | #ifndef NO_HW_VSYNC |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 153 | case HWC_EVENT_VSYNC: |
| Neti Ravi Kumar | c356c1c | 2012-09-16 01:35:41 +0530 | [diff] [blame] | 154 | if (value == prev_value){ |
| 155 | //TODO see why HWC gets repeated events |
| 156 | ALOGD_IF(VSYNC_DEBUG, "%s - VSYNC is already %s", |
| 157 | __FUNCTION__, (value)?"ENABLED":"DISABLED"); |
| 158 | } |
| 159 | temp = ctx->vstate.enable; |
| Arun Kumar K.R | 9813cf3 | 2012-07-27 19:49:03 -0700 | [diff] [blame] | 160 | if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &value) < 0) |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 161 | ret = -errno; |
| Arun Kumar K.R | a72904b | 2012-07-23 13:44:38 -0700 | [diff] [blame] | 162 | |
| Neti Ravi Kumar | c356c1c | 2012-09-16 01:35:41 +0530 | [diff] [blame] | 163 | /* vsync state change logic */ |
| 164 | if (value == 1) { |
| 165 | //unblock vsync thread |
| 166 | pthread_mutex_lock(&ctx->vstate.lock); |
| 167 | ctx->vstate.enable = true; |
| 168 | pthread_cond_signal(&ctx->vstate.cond); |
| 169 | pthread_mutex_unlock(&ctx->vstate.lock); |
| Arun Kumar K.R | a72904b | 2012-07-23 13:44:38 -0700 | [diff] [blame] | 170 | } |
| Neti Ravi Kumar | c356c1c | 2012-09-16 01:35:41 +0530 | [diff] [blame] | 171 | if (value == 0 && temp) { |
| 172 | //vsync thread will block |
| 173 | pthread_mutex_lock(&ctx->vstate.lock); |
| 174 | ctx->vstate.enable = false; |
| 175 | pthread_mutex_unlock(&ctx->vstate.lock); |
| 176 | } |
| 177 | ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed from %s to %s", |
| 178 | (prev_value)?"ENABLED":"DISABLED", (value)?"ENABLED":"DISABLED"); |
| 179 | prev_value = value; |
| 180 | /* vsync state change logic - end*/ |
| 181 | |
| 182 | if(ctx->mExtDisplay->isHDMIConfigured() && |
| 183 | (ctx->mExtDisplay->getExternalDisplay()==EXTERN_DISPLAY_FB1)) { |
| Arun Kumar K.R | c3dafd1 | 2012-09-20 11:01:09 -0700 | [diff] [blame] | 184 | // enableHDMIVsync will return -errno on error |
| Neti Ravi Kumar | c356c1c | 2012-09-16 01:35:41 +0530 | [diff] [blame] | 185 | ret = ctx->mExtDisplay->enableHDMIVsync(value); |
| 186 | } |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 187 | break; |
| Steve Kondik | 85ff2df | 2012-08-07 19:56:31 -0700 | [diff] [blame] | 188 | #endif |
| Arun Kumar K.R | 9813cf3 | 2012-07-27 19:49:03 -0700 | [diff] [blame] | 189 | case HWC_EVENT_ORIENTATION: |
| 190 | ctx->deviceOrientation = value; |
| 191 | break; |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 192 | default: |
| 193 | ret = -EINVAL; |
| 194 | } |
| 195 | return ret; |
| 196 | } |
| 197 | |
| 198 | static int hwc_query(struct hwc_composer_device* dev, |
| 199 | int param, int* value) |
| 200 | { |
| 201 | hwc_context_t* ctx = (hwc_context_t*)(dev); |
| 202 | private_module_t* m = reinterpret_cast<private_module_t*>( |
| 203 | ctx->mFbDev->common.module); |
| 204 | |
| 205 | switch (param) { |
| 206 | case HWC_BACKGROUND_LAYER_SUPPORTED: |
| 207 | // Not supported for now |
| 208 | value[0] = 0; |
| 209 | break; |
| 210 | case HWC_VSYNC_PERIOD: |
| 211 | value[0] = 1000000000.0 / m->fps; |
| 212 | ALOGI("fps: %d", value[0]); |
| 213 | break; |
| 214 | default: |
| 215 | return -EINVAL; |
| 216 | } |
| 217 | return 0; |
| 218 | |
| 219 | } |
| 220 | |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 221 | static int hwc_set(hwc_composer_device_t *dev, |
| 222 | hwc_display_t dpy, |
| 223 | hwc_surface_t sur, |
| 224 | hwc_layer_list_t* list) |
| 225 | { |
| 226 | int ret = 0; |
| 227 | hwc_context_t* ctx = (hwc_context_t*)(dev); |
| Naseer Ahmed | 357ee6d | 2012-08-27 13:49:18 -0400 | [diff] [blame] | 228 | if (dpy && sur) { |
| 229 | if (LIKELY(list)) { |
| 230 | VideoOverlay::draw(ctx, list); |
| 231 | VideoPIP::draw(ctx,list); |
| 232 | ExtOnly::draw(ctx, list); |
| 233 | CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); |
| 234 | MDPComp::draw(ctx, list); |
| 235 | } |
| 236 | eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); |
| Saurabh Shah | 43dfffc | 2012-09-10 11:39:45 -0700 | [diff] [blame] | 237 | if (ctx->mMDP.hasOverlay) { |
| 238 | wait4fbPost(ctx); |
| 239 | //Can draw to HDMI only when fb_post is reached |
| 240 | UIMirrorOverlay::draw(ctx); |
| 241 | //HDMI commit and primary commit (PAN) happening in parallel |
| 242 | if(ctx->mExtDisplay->getExternalDisplay()) |
| 243 | ctx->mExtDisplay->commit(); |
| 244 | //Virtual barrier for threads to finish |
| 245 | wait4Pan(ctx); |
| 246 | } |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 247 | } else { |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 248 | ctx->mOverlay->setState(ovutils::OV_CLOSED); |
| Saurabh Shah | 1be2fcd | 2012-08-16 10:19:07 -0700 | [diff] [blame] | 249 | ctx->qbuf->unlockAll(); |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 250 | } |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 251 | |
| Saurabh Shah | 5704501 | 2012-07-10 18:33:17 -0700 | [diff] [blame] | 252 | |
| Saurabh Shah | 0a2352a | 2012-08-23 08:41:05 -0700 | [diff] [blame] | 253 | ctx->qbuf->unlockAllPrevious(); |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 254 | return ret; |
| 255 | } |
| 256 | |
| 257 | static int hwc_device_close(struct hw_device_t *dev) |
| 258 | { |
| 259 | if(!dev) { |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 260 | ALOGE("%s: NULL device pointer", __FUNCTION__); |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 261 | return -1; |
| 262 | } |
| 263 | closeContext((hwc_context_t*)dev); |
| 264 | free(dev); |
| 265 | |
| 266 | return 0; |
| 267 | } |
| 268 | |
| 269 | static int hwc_device_open(const struct hw_module_t* module, const char* name, |
| 270 | struct hw_device_t** device) |
| 271 | { |
| 272 | int status = -EINVAL; |
| 273 | |
| 274 | if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { |
| 275 | struct hwc_context_t *dev; |
| 276 | dev = (hwc_context_t*)malloc(sizeof(*dev)); |
| 277 | memset(dev, 0, sizeof(*dev)); |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 278 | |
| 279 | //Initialize hwc context |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 280 | initContext(dev); |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 281 | |
| 282 | //Setup HWC methods |
| 283 | hwc_methods_t *methods; |
| 284 | methods = (hwc_methods_t *)malloc(sizeof(*methods)); |
| 285 | memset(methods, 0, sizeof(*methods)); |
| 286 | methods->eventControl = hwc_eventControl; |
| 287 | |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 288 | dev->device.common.tag = HARDWARE_DEVICE_TAG; |
| Neti Ravi Kumar | 673e493 | 2012-09-12 18:14:25 +0530 | [diff] [blame] | 289 | #ifndef NO_HW_VSYNC |
| 290 | //XXX: This disables hardware vsync on 8x55 |
| 291 | // Fix when HW vsync is available on 8x55 |
| 292 | if(dev->mMDP.version == 400 || (dev->mMDP.version >= 500)) { |
| 293 | #endif |
| 294 | dev->device.common.version = 0; |
| 295 | ALOGI("%s: Hardware VSYNC not supported", __FUNCTION__); |
| 296 | #ifndef NO_HW_VSYNC |
| 297 | } else { |
| 298 | dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; |
| 299 | ALOGI("%s: Hardware VSYNC supported", __FUNCTION__); |
| 300 | } |
| Steve Kondik | 85ff2df | 2012-08-07 19:56:31 -0700 | [diff] [blame] | 301 | #endif |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 302 | dev->device.common.module = const_cast<hw_module_t*>(module); |
| 303 | dev->device.common.close = hwc_device_close; |
| 304 | dev->device.prepare = hwc_prepare; |
| 305 | dev->device.set = hwc_set; |
| 306 | dev->device.registerProcs = hwc_registerProcs; |
| Naseer Ahmed | 9ccb397 | 2012-07-21 12:17:13 -0700 | [diff] [blame] | 307 | dev->device.query = hwc_query; |
| 308 | dev->device.methods = methods; |
| Naseer Ahmed | 7341799 | 2012-06-14 00:56:20 -0700 | [diff] [blame] | 309 | *device = &dev->device.common; |
| 310 | status = 0; |
| 311 | } |
| 312 | return status; |
| 313 | } |