hwc.cpp revision 5a107b4b7124301baf3b9e58089c7621fb9dfc95
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved. 4 * 5 * Not a Contribution, Apache license notifications and license are retained 6 * for attribution purposes only. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21#include <fcntl.h> 22#include <errno.h> 23 24#include <cutils/log.h> 25#include <cutils/atomic.h> 26#include <EGL/egl.h> 27 28#include <overlay.h> 29#include <fb_priv.h> 30#include <mdp_version.h> 31#include "hwc_utils.h" 32#include "hwc_video.h" 33#include "hwc_fbupdate.h" 34#include "hwc_mdpcomp.h" 35#include "external.h" 36#include "hwc_copybit.h" 37 38using namespace qhwc; 39#define VSYNC_DEBUG 0 40 41static int hwc_device_open(const struct hw_module_t* module, 42 const char* name, 43 struct hw_device_t** device); 44 45static struct hw_module_methods_t hwc_module_methods = { 46 open: hwc_device_open 47}; 48 49hwc_module_t HAL_MODULE_INFO_SYM = { 50 common: { 51 tag: HARDWARE_MODULE_TAG, 52 version_major: 2, 53 version_minor: 0, 54 id: HWC_HARDWARE_MODULE_ID, 55 name: "Qualcomm Hardware Composer Module", 56 author: "CodeAurora Forum", 57 methods: &hwc_module_methods, 58 dso: 0, 59 reserved: {0}, 60 } 61}; 62 63/* 64 * Save callback functions registered to HWC 65 */ 66static void hwc_registerProcs(struct hwc_composer_device_1* dev, 67 hwc_procs_t const* procs) 68{ 69 ALOGI("%s", __FUNCTION__); 70 hwc_context_t* ctx = (hwc_context_t*)(dev); 71 if(!ctx) { 72 ALOGE("%s: Invalid context", __FUNCTION__); 73 return; 74 } 75 ctx->proc = procs; 76 77 // Now that we have the functions needed, kick off 78 // the uevent & vsync threads 79 init_uevent_thread(ctx); 80 init_vsync_thread(ctx); 81} 82 83//Helper 84static void reset(hwc_context_t *ctx, int numDisplays, 85 hwc_display_contents_1_t** displays) { 86 memset(ctx->listStats, 0, sizeof(ctx->listStats)); 87 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){ 88 hwc_display_contents_1_t *list = displays[i]; 89 // XXX:SurfaceFlinger no longer guarantees that this 90 // value is reset on every prepare. However, for the layer 91 // cache we need to reset it. 92 // We can probably rethink that later on 93 if (LIKELY(list && list->numHwLayers > 1)) { 94 for(uint32_t j = 0; j < list->numHwLayers; j++) { 95 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET) 96 list->hwLayers[j].compositionType = HWC_FRAMEBUFFER; 97 } 98 } 99 100 if(ctx->mFBUpdate[i]) 101 ctx->mFBUpdate[i]->reset(); 102 103 if(ctx->mCopyBit[i]) 104 ctx->mCopyBit[i]->reset(); 105 } 106 VideoOverlay::reset(); 107} 108 109//clear prev layer prop flags and realloc for current frame 110static void reset_layer_prop(hwc_context_t* ctx, int dpy) { 111 int layer_count = ctx->listStats[dpy].numAppLayers; 112 113 if(ctx->layerProp[dpy]) { 114 delete[] ctx->layerProp[dpy]; 115 ctx->layerProp[dpy] = NULL; 116 } 117 118 if(layer_count) { 119 ctx->layerProp[dpy] = new LayerProp[layer_count]; 120 } 121} 122 123static int hwc_prepare_primary(hwc_composer_device_1 *dev, 124 hwc_display_contents_1_t *list) { 125 hwc_context_t* ctx = (hwc_context_t*)(dev); 126 const int dpy = HWC_DISPLAY_PRIMARY; 127 if (LIKELY(list && list->numHwLayers > 1) && 128 ctx->dpyAttr[dpy].isActive) { 129 130 uint32_t last = list->numHwLayers - 1; 131 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 132 if(fbLayer->handle) { 133 setListStats(ctx, list, dpy); 134 reset_layer_prop(ctx, dpy); 135 int ret = ctx->mMDPComp->prepare(ctx, list); 136 if(!ret) { 137 // IF MDPcomp fails use this route 138 VideoOverlay::prepare(ctx, list, dpy); 139 ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer); 140 } 141 ctx->mLayerCache[dpy]->updateLayerCache(list); 142 // Use Copybit, when MDP comp fails 143 if(!ret && ctx->mCopyBit[dpy]) 144 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); 145 } 146 } 147 return 0; 148} 149 150static int hwc_prepare_external(hwc_composer_device_1 *dev, 151 hwc_display_contents_1_t *list) { 152 hwc_context_t* ctx = (hwc_context_t*)(dev); 153 const int dpy = HWC_DISPLAY_EXTERNAL; 154 155 if (LIKELY(list && list->numHwLayers > 1) && 156 ctx->dpyAttr[dpy].isActive && 157 ctx->dpyAttr[dpy].connected) { 158 159 uint32_t last = list->numHwLayers - 1; 160 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 161 if(fbLayer->handle) { 162 setListStats(ctx, list, dpy); 163 reset_layer_prop(ctx, dpy); 164 VideoOverlay::prepare(ctx, list, dpy); 165 ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer); 166 ctx->mLayerCache[dpy]->updateLayerCache(list); 167 if(ctx->mCopyBit[dpy]) 168 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); 169 ctx->mExtDispConfiguring = false; 170 } 171 } 172 return 0; 173} 174 175static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 176 hwc_display_contents_1_t** displays) 177{ 178 int ret = 0; 179 hwc_context_t* ctx = (hwc_context_t*)(dev); 180 Locker::Autolock _l(ctx->mBlankLock); 181 reset(ctx, numDisplays, displays); 182 183 ctx->mOverlay->configBegin(); 184 185 for (int32_t i = numDisplays - 1; i >= 0; i--) { 186 hwc_display_contents_1_t *list = displays[i]; 187 switch(i) { 188 case HWC_DISPLAY_PRIMARY: 189 ret = hwc_prepare_primary(dev, list); 190 break; 191 case HWC_DISPLAY_EXTERNAL: 192 ret = hwc_prepare_external(dev, list); 193 break; 194 default: 195 ret = -EINVAL; 196 } 197 } 198 199 ctx->mOverlay->configDone(); 200 return ret; 201} 202 203static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 204 int event, int enabled) 205{ 206 int ret = 0; 207 208 hwc_context_t* ctx = (hwc_context_t*)(dev); 209 private_module_t* m = reinterpret_cast<private_module_t*>( 210 ctx->mFbDev->common.module); 211 pthread_mutex_lock(&ctx->vstate.lock); 212 switch(event) { 213 case HWC_EVENT_VSYNC: 214 if (ctx->vstate.enable == enabled) 215 break; 216 ctx->vstate.enable = !!enabled; 217 pthread_cond_signal(&ctx->vstate.cond); 218 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s", 219 (enabled)?"ENABLED":"DISABLED"); 220 break; 221 default: 222 ret = -EINVAL; 223 } 224 pthread_mutex_unlock(&ctx->vstate.lock); 225 return ret; 226} 227 228static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 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 Locker::Autolock _l(ctx->mBlankLock); 234 int ret = 0; 235 ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank); 236 switch(dpy) { 237 case HWC_DISPLAY_PRIMARY: 238 if(blank) { 239 ctx->mOverlay->configBegin(); 240 ctx->mOverlay->configDone(); 241 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); 242 } else { 243 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK); 244 } 245 break; 246 case HWC_DISPLAY_EXTERNAL: 247 if(blank) { 248 // External Display post commits the changes to display 249 // Call this on blank, so that any pipe unsets gets committed 250 if (!ctx->mExtDisplay->post()) { 251 ret = -1; 252 ALOGE("%s:ctx->mExtDisplay->post fail!! ", __FUNCTION__); 253 } 254 } else { 255 } 256 break; 257 default: 258 return -EINVAL; 259 } 260 // Enable HPD here, as during bootup unblank is called 261 // when SF is completely initialized 262 ctx->mExtDisplay->setHPD(1); 263 264 if(ret < 0) { 265 ALOGE("%s: failed. Dpy=%d, blank=%d : %s", 266 __FUNCTION__, dpy, blank, strerror(errno)); 267 return ret; 268 } 269 ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank); 270 ctx->dpyAttr[dpy].isActive = !blank; 271 return 0; 272} 273 274static int hwc_query(struct hwc_composer_device_1* dev, 275 int param, int* value) 276{ 277 hwc_context_t* ctx = (hwc_context_t*)(dev); 278 private_module_t* m = reinterpret_cast<private_module_t*>( 279 ctx->mFbDev->common.module); 280 int supported = HWC_DISPLAY_PRIMARY_BIT; 281 282 switch (param) { 283 case HWC_BACKGROUND_LAYER_SUPPORTED: 284 // Not supported for now 285 value[0] = 0; 286 break; 287 case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1 288 value[0] = m->fps; 289 ALOGI("fps: %d", value[0]); 290 break; 291 case HWC_DISPLAY_TYPES_SUPPORTED: 292 if(ctx->mMDP.hasOverlay) 293 supported |= HWC_DISPLAY_EXTERNAL_BIT; 294 value[0] = supported; 295 break; 296 default: 297 return -EINVAL; 298 } 299 return 0; 300 301} 302 303static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 304 int ret = 0; 305 const int dpy = HWC_DISPLAY_PRIMARY; 306 307 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) { 308 uint32_t last = list->numHwLayers - 1; 309 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 310 int fd = -1; //FenceFD from the Copybit(valid in async mode) 311 if(ctx->mCopyBit[dpy]) 312 ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 313 if(list->numHwLayers > 1) 314 hwc_sync(ctx, list, dpy, fd); 315 if (!VideoOverlay::draw(ctx, list, dpy)) { 316 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); 317 ret = -1; 318 } 319 if (!ctx->mMDPComp->draw(ctx, list)) { 320 ALOGE("%s: MDPComp::draw fail!", __FUNCTION__); 321 ret = -1; 322 } 323 324 //TODO We dont check for SKIP flag on this layer because we need PAN 325 //always. Last layer is always FB 326 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 327 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) { 328 if(!(fbLayer->flags & HWC_SKIP_LAYER) && 329 (list->numHwLayers > 1)) { 330 if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) { 331 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 332 ret = -1; 333 } 334 } 335 if (ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle)) { 336 ALOGE("%s: ctx->mFbDev->post fail!", __FUNCTION__); 337 return -1; 338 } 339 } 340 } 341 return ret; 342} 343 344static int hwc_set_external(hwc_context_t *ctx, 345 hwc_display_contents_1_t* list) { 346 int ret = 0; 347 const int dpy = HWC_DISPLAY_EXTERNAL; 348 349 Locker::Autolock _l(ctx->mExtSetLock); 350 351 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && 352 ctx->dpyAttr[dpy].connected) { 353 uint32_t last = list->numHwLayers - 1; 354 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 355 int fd = -1; //FenceFD from the Copybit(valid in async mode) 356 if(ctx->mCopyBit[dpy]) 357 ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 358 359 if(list->numHwLayers > 1) 360 hwc_sync(ctx, list, dpy, fd); 361 362 if (!VideoOverlay::draw(ctx, list, dpy)) { 363 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); 364 ret = -1; 365 } 366 367 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 368 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && 369 !(fbLayer->flags & HWC_SKIP_LAYER) && hnd && 370 (list->numHwLayers > 1)) { 371 if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) { 372 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 373 ret = -1; 374 } 375 } 376 if (!ctx->mExtDisplay->post()) { 377 ALOGE("%s: ctx->mExtDisplay->post fail!", __FUNCTION__); 378 return -1; 379 } 380 } 381 return ret; 382} 383 384static int hwc_set(hwc_composer_device_1 *dev, 385 size_t numDisplays, 386 hwc_display_contents_1_t** displays) 387{ 388 int ret = 0; 389 hwc_context_t* ctx = (hwc_context_t*)(dev); 390 Locker::Autolock _l(ctx->mBlankLock); 391 for (uint32_t i = 0; i < numDisplays; i++) { 392 hwc_display_contents_1_t* list = displays[i]; 393 switch(i) { 394 case HWC_DISPLAY_PRIMARY: 395 ret = hwc_set_primary(ctx, list); 396 break; 397 case HWC_DISPLAY_EXTERNAL: 398 ret = hwc_set_external(ctx, list); 399 break; 400 default: 401 ret = -EINVAL; 402 } 403 } 404 return ret; 405} 406 407int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, 408 uint32_t* configs, size_t* numConfigs) { 409 int ret = 0; 410 hwc_context_t* ctx = (hwc_context_t*)(dev); 411 //in 1.1 there is no way to choose a config, report as config id # 0 412 //This config is passed to getDisplayAttributes. Ignore for now. 413 switch(disp) { 414 case HWC_DISPLAY_PRIMARY: 415 if(*numConfigs > 0) { 416 configs[0] = 0; 417 *numConfigs = 1; 418 } 419 ret = 0; //NO_ERROR 420 break; 421 case HWC_DISPLAY_EXTERNAL: 422 ret = -1; //Not connected 423 if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) { 424 ret = 0; //NO_ERROR 425 if(*numConfigs > 0) { 426 configs[0] = 0; 427 *numConfigs = 1; 428 } 429 } 430 break; 431 } 432 return ret; 433} 434 435int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, 436 uint32_t config, const uint32_t* attributes, int32_t* values) { 437 438 hwc_context_t* ctx = (hwc_context_t*)(dev); 439 //If hotpluggable displays are inactive return error 440 if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) { 441 return -1; 442 } 443 444 //From HWComposer 445 static const uint32_t DISPLAY_ATTRIBUTES[] = { 446 HWC_DISPLAY_VSYNC_PERIOD, 447 HWC_DISPLAY_WIDTH, 448 HWC_DISPLAY_HEIGHT, 449 HWC_DISPLAY_DPI_X, 450 HWC_DISPLAY_DPI_Y, 451 HWC_DISPLAY_NO_ATTRIBUTE, 452 }; 453 454 const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / 455 sizeof(DISPLAY_ATTRIBUTES)[0]); 456 457 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { 458 switch (attributes[i]) { 459 case HWC_DISPLAY_VSYNC_PERIOD: 460 values[i] = ctx->dpyAttr[disp].vsync_period; 461 break; 462 case HWC_DISPLAY_WIDTH: 463 values[i] = ctx->dpyAttr[disp].xres; 464 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp, 465 ctx->dpyAttr[disp].xres); 466 break; 467 case HWC_DISPLAY_HEIGHT: 468 values[i] = ctx->dpyAttr[disp].yres; 469 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp, 470 ctx->dpyAttr[disp].yres); 471 break; 472 case HWC_DISPLAY_DPI_X: 473 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0); 474 break; 475 case HWC_DISPLAY_DPI_Y: 476 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0); 477 break; 478 default: 479 ALOGE("Unknown display attribute %d", 480 attributes[i]); 481 return -EINVAL; 482 } 483 } 484 return 0; 485} 486 487void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) 488{ 489 hwc_context_t* ctx = (hwc_context_t*)(dev); 490 android::String8 buf(""); 491 dumpsys_log(buf, "Qualcomm HWC state:\n"); 492 dumpsys_log(buf, " MDPVersion=%d\n", ctx->mMDP.version); 493 dumpsys_log(buf, " DisplayPanel=%c\n", ctx->mMDP.panel); 494 ctx->mMDPComp->dump(buf); 495 //XXX: Call Other dump functions 496 strlcpy(buff, buf.string(), buff_len); 497} 498 499static int hwc_device_close(struct hw_device_t *dev) 500{ 501 if(!dev) { 502 ALOGE("%s: NULL device pointer", __FUNCTION__); 503 return -1; 504 } 505 closeContext((hwc_context_t*)dev); 506 free(dev); 507 508 return 0; 509} 510 511static int hwc_device_open(const struct hw_module_t* module, const char* name, 512 struct hw_device_t** device) 513{ 514 int status = -EINVAL; 515 516 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 517 struct hwc_context_t *dev; 518 dev = (hwc_context_t*)malloc(sizeof(*dev)); 519 memset(dev, 0, sizeof(*dev)); 520 521 //Initialize hwc context 522 initContext(dev); 523 524 //Setup HWC methods 525 dev->device.common.tag = HARDWARE_DEVICE_TAG; 526 dev->device.common.version = HWC_DEVICE_API_VERSION_1_1; 527 dev->device.common.module = const_cast<hw_module_t*>(module); 528 dev->device.common.close = hwc_device_close; 529 dev->device.prepare = hwc_prepare; 530 dev->device.set = hwc_set; 531 dev->device.eventControl = hwc_eventControl; 532 dev->device.blank = hwc_blank; 533 dev->device.query = hwc_query; 534 dev->device.registerProcs = hwc_registerProcs; 535 dev->device.dump = hwc_dump; 536 dev->device.getDisplayConfigs = hwc_getDisplayConfigs; 537 dev->device.getDisplayAttributes = hwc_getDisplayAttributes; 538 *device = &dev->device.common; 539 status = 0; 540 } 541 return status; 542} 543