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