hwc.cpp revision 2e449280f98f003bb5831c274fc07ab722ac1a94
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_video.h" 30#include "external.h" 31#include "hwc_mdpcomp.h" 32 33using namespace qhwc; 34 35static int hwc_device_open(const struct hw_module_t* module, 36 const char* name, 37 struct hw_device_t** device); 38 39static struct hw_module_methods_t hwc_module_methods = { 40 open: hwc_device_open 41}; 42 43hwc_module_t HAL_MODULE_INFO_SYM = { 44 common: { 45 tag: HARDWARE_MODULE_TAG, 46 version_major: 2, 47 version_minor: 0, 48 id: HWC_HARDWARE_MODULE_ID, 49 name: "Qualcomm Hardware Composer Module", 50 author: "CodeAurora Forum", 51 methods: &hwc_module_methods, 52 dso: 0, 53 reserved: {0}, 54 } 55}; 56 57/* 58 * Save callback functions registered to HWC 59 */ 60static void hwc_registerProcs(struct hwc_composer_device_1* dev, 61 hwc_procs_t const* procs) 62{ 63 hwc_context_t* ctx = (hwc_context_t*)(dev); 64 if(!ctx) { 65 ALOGE("%s: Invalid context", __FUNCTION__); 66 return; 67 } 68 ctx->proc = procs; 69 70 // don't start listening for events until we can do something with them 71 init_uevent_thread(ctx); 72} 73 74//Helper 75static void reset(hwc_context_t *ctx, int numDisplays) { 76 memset(ctx->listStats, 0, sizeof(ctx->listStats)); 77 for(int i = 0; i < numDisplays; i++){ 78 ctx->listStats[i].yuvIndex = -1; 79 } 80} 81 82static int hwc_prepare_primary(hwc_composer_device_1 *dev, 83 hwc_display_contents_1_t *list) { 84 hwc_context_t* ctx = (hwc_context_t*)(dev); 85 if (LIKELY(list && list->numHwLayers)) { 86 setListStats(ctx, list, HWC_DISPLAY_PRIMARY); 87 if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) { 88 ctx->overlayInUse = true; 89 } else if(MDPComp::configure(ctx, list)) { 90 ctx->overlayInUse = true; 91 } else { 92 ctx->overlayInUse = false; 93 } 94 } 95 return 0; 96} 97 98static int hwc_prepare_external(hwc_composer_device_1 *dev, 99 hwc_display_contents_1_t *list) { 100 101 hwc_context_t* ctx = (hwc_context_t*)(dev); 102 if (LIKELY(list && list->numHwLayers)) { 103 setListStats(ctx, list, HWC_DISPLAY_EXTERNAL); 104 //Nothing to do for now 105 } 106 return 0; 107} 108 109static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 110 hwc_display_contents_1_t** displays) 111{ 112 int ret = 0; 113 hwc_context_t* ctx = (hwc_context_t*)(dev); 114 ctx->overlayInUse = false; 115 116 reset(ctx, numDisplays); 117 118 //If securing of h/w in progress skip comp using overlay. 119 if(ctx->mSecuring == true) return 0; 120 121 for (uint32_t i = 0; i < numDisplays; i++) { 122 hwc_display_contents_1_t *list = displays[i]; 123 switch(i) { 124 case HWC_DISPLAY_PRIMARY: 125 ret = hwc_prepare_primary(dev, list); 126 break; 127 case HWC_DISPLAY_EXTERNAL: 128 ret = hwc_prepare_external(dev, list); 129 break; 130 default: 131 ret = -EINVAL; 132 } 133 } 134 return ret; 135} 136 137static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 138 int event, int enabled) 139{ 140 int ret = 0; 141 hwc_context_t* ctx = (hwc_context_t*)(dev); 142 private_module_t* m = reinterpret_cast<private_module_t*>( 143 ctx->mFbDev->common.module); 144 switch(event) { 145 case HWC_EVENT_VSYNC: 146 if(ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL, 147 &enabled) < 0) { 148 ALOGE("%s: vsync control failed. Dpy=%d, enabled=%d : %s", 149 __FUNCTION__, dpy, enabled, strerror(errno)); 150 ret = -errno; 151 } 152 break; 153 default: 154 ret = -EINVAL; 155 } 156 return ret; 157} 158 159static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 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 int ret = 0; 165 ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank); 166 switch(dpy) { 167 case HWC_DISPLAY_PRIMARY: 168 if(blank) { 169 ctx->mOverlay->setState(ovutils::OV_CLOSED); 170 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); 171 } else { 172 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK); 173 } 174 break; 175 case HWC_DISPLAY_EXTERNAL: 176 if(blank) { 177 //TODO actual 178 } else { 179 } 180 break; 181 default: 182 return -EINVAL; 183 } 184 185 if(ret < 0) { 186 ALOGE("%s: failed. Dpy=%d, blank=%d : %s", 187 __FUNCTION__, dpy, blank, strerror(errno)); 188 return ret; 189 } 190 ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank); 191 ctx->dpyAttr[dpy].isActive = !blank; 192 return 0; 193} 194 195static int hwc_query(struct hwc_composer_device_1* dev, 196 int param, int* value) 197{ 198 hwc_context_t* ctx = (hwc_context_t*)(dev); 199 private_module_t* m = reinterpret_cast<private_module_t*>( 200 ctx->mFbDev->common.module); 201 int supported = HWC_DISPLAY_PRIMARY_BIT; 202 203 switch (param) { 204 case HWC_BACKGROUND_LAYER_SUPPORTED: 205 // Not supported for now 206 value[0] = 0; 207 break; 208 case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1 209 value[0] = m->fps; 210 ALOGI("fps: %d", value[0]); 211 break; 212 case HWC_DISPLAY_TYPES_SUPPORTED: 213 //Enable later 214 //if(ctx->mMDP.hasOverlay) 215 //supported |= HWC_DISPLAY_EXTERNAL_BIT; 216 value[0] = supported; 217 break; 218 default: 219 return -EINVAL; 220 } 221 return 0; 222 223} 224 225static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 226 if (LIKELY(list && list->numHwLayers)) { 227 VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY); 228 MDPComp::draw(ctx, list); 229 hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY); 230 //TODO We dont check for SKIP flag on this layer because we need PAN 231 //always. Last layer is always FB 232 uint32_t last = list->numHwLayers - 1; 233 if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET) { 234 ctx->mFbDev->post(ctx->mFbDev, list->hwLayers[last].handle); 235 } 236 } 237 return 0; 238} 239 240static int hwc_set_external(hwc_context_t *ctx, 241 hwc_display_contents_1_t* list) { 242 if (LIKELY(list && list->numHwLayers)) { 243 hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL); 244 uint32_t last = list->numHwLayers - 1; 245 if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET && 246 ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) { 247 //ctx->mExtDisplay->post(list->hwLayers[last].handle); 248 } 249 } 250 return 0; 251} 252 253static int hwc_set(hwc_composer_device_1 *dev, 254 size_t numDisplays, 255 hwc_display_contents_1_t** displays) 256{ 257 int ret = 0; 258 hwc_context_t* ctx = (hwc_context_t*)(dev); 259 for (uint32_t i = 0; i < numDisplays; i++) { 260 hwc_display_contents_1_t* list = displays[i]; 261 switch(i) { 262 case HWC_DISPLAY_PRIMARY: 263 ret = hwc_set_primary(ctx, list); 264 case HWC_DISPLAY_EXTERNAL: 265 ret = hwc_set_external(ctx, list); 266 default: 267 ret = -EINVAL; 268 } 269 } 270 if(!ctx->overlayInUse) 271 ctx->mOverlay->setState(ovutils::OV_CLOSED); 272 273 return ret; 274} 275 276int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, 277 uint32_t* configs, size_t* numConfigs) { 278 int ret = 0; 279 //in 1.1 there is no way to choose a config, report as config id # 0 280 //This config is passed to getDisplayAttributes. Ignore for now. 281 if(*numConfigs == 1) 282 *configs = 0; 283 switch(disp) { 284 case HWC_DISPLAY_PRIMARY: 285 ret = 0; 286 break; 287 case HWC_DISPLAY_EXTERNAL: 288 //Hack until hotplug is supported. 289 //This makes framework ignore external display. 290 ret = -1; 291 break; 292 } 293 return ret; 294} 295 296int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, 297 uint32_t config, const uint32_t* attributes, int32_t* values) { 298 299 hwc_context_t* ctx = (hwc_context_t*)(dev); 300 //From HWComposer 301 static const uint32_t DISPLAY_ATTRIBUTES[] = { 302 HWC_DISPLAY_VSYNC_PERIOD, 303 HWC_DISPLAY_WIDTH, 304 HWC_DISPLAY_HEIGHT, 305 HWC_DISPLAY_DPI_X, 306 HWC_DISPLAY_DPI_Y, 307 HWC_DISPLAY_NO_ATTRIBUTE, 308 }; 309 310 const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / 311 sizeof(DISPLAY_ATTRIBUTES)[0]); 312 313 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { 314 switch (attributes[i]) { 315 case HWC_DISPLAY_VSYNC_PERIOD: 316 values[i] = ctx->dpyAttr[disp].vsync_period; 317 break; 318 case HWC_DISPLAY_WIDTH: 319 values[i] = ctx->dpyAttr[disp].xres; 320 ALOGD("%s width = %d",__FUNCTION__, ctx->dpyAttr[disp].xres); 321 break; 322 case HWC_DISPLAY_HEIGHT: 323 values[i] = ctx->dpyAttr[disp].yres; 324 ALOGD("%s height = %d",__FUNCTION__, ctx->dpyAttr[disp].yres); 325 break; 326 case HWC_DISPLAY_DPI_X: 327 values[i] = ctx->dpyAttr[disp].xdpi; 328 break; 329 case HWC_DISPLAY_DPI_Y: 330 values[i] = ctx->dpyAttr[disp].ydpi; 331 break; 332 default: 333 ALOGE("Unknown display attribute %d", 334 attributes[i]); 335 return -EINVAL; 336 } 337 } 338 return 0; 339} 340 341static int hwc_device_close(struct hw_device_t *dev) 342{ 343 if(!dev) { 344 ALOGE("%s: NULL device pointer", __FUNCTION__); 345 return -1; 346 } 347 closeContext((hwc_context_t*)dev); 348 free(dev); 349 350 return 0; 351} 352 353static int hwc_device_open(const struct hw_module_t* module, const char* name, 354 struct hw_device_t** device) 355{ 356 int status = -EINVAL; 357 358 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 359 struct hwc_context_t *dev; 360 dev = (hwc_context_t*)malloc(sizeof(*dev)); 361 memset(dev, 0, sizeof(*dev)); 362 363 //Initialize hwc context 364 initContext(dev); 365 366 //Setup HWC methods 367 dev->device.common.tag = HARDWARE_DEVICE_TAG; 368 dev->device.common.version = HWC_DEVICE_API_VERSION_1_1; 369 dev->device.common.module = const_cast<hw_module_t*>(module); 370 dev->device.common.close = hwc_device_close; 371 dev->device.prepare = hwc_prepare; 372 dev->device.set = hwc_set; 373 dev->device.eventControl = hwc_eventControl; 374 dev->device.blank = hwc_blank; 375 dev->device.query = hwc_query; 376 dev->device.registerProcs = hwc_registerProcs; 377 dev->device.dump = NULL; 378 dev->device.getDisplayConfigs = hwc_getDisplayConfigs; 379 dev->device.getDisplayAttributes = hwc_getDisplayAttributes; 380 *device = &dev->device.common; 381 status = 0; 382 } 383 return status; 384} 385