hwc.cpp revision 640cb9421639c13248aeb30c3496cdfaec6d894c
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_fbupdate.h" 31#include "hwc_mdpcomp.h" 32#include "external.h" 33 34using namespace qhwc; 35#define VSYNC_DEBUG 0 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 hwc_display_contents_1_t** displays) { 82 memset(ctx->listStats, 0, sizeof(ctx->listStats)); 83 for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){ 84 ctx->listStats[i].yuvIndex = -1; 85 hwc_display_contents_1_t *list = displays[i]; 86 // XXX:SurfaceFlinger no longer guarantees that this 87 // value is reset on every prepare. However, for the layer 88 // cache we need to reset it. 89 // We can probably rethink that later on 90 if (LIKELY(list && list->numHwLayers > 1)) { 91 for(uint32_t j = 0; j < list->numHwLayers; j++) { 92 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET) 93 list->hwLayers[j].compositionType = HWC_FRAMEBUFFER; 94 } 95 } 96 97 if(ctx->mFBUpdate[i]) 98 ctx->mFBUpdate[i]->reset(); 99 } 100 VideoOverlay::reset(); 101} 102 103//clear prev layer prop flags and realloc for current frame 104static void reset_layer_prop(hwc_context_t* ctx, int dpy) { 105 int layer_count = ctx->listStats[dpy].numAppLayers; 106 107 if(ctx->layerProp[dpy]) { 108 delete[] ctx->layerProp[dpy]; 109 ctx->layerProp[dpy] = NULL; 110 } 111 112 if(layer_count) { 113 ctx->layerProp[dpy] = new LayerProp[layer_count]; 114 } 115} 116 117static int hwc_prepare_primary(hwc_composer_device_1 *dev, 118 hwc_display_contents_1_t *list) { 119 hwc_context_t* ctx = (hwc_context_t*)(dev); 120 const int dpy = HWC_DISPLAY_PRIMARY; 121 122 if (LIKELY(list && list->numHwLayers > 1) && 123 ctx->dpyAttr[dpy].isActive) { 124 125 uint32_t last = list->numHwLayers - 1; 126 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 127 if(fbLayer->handle) { 128 setListStats(ctx, list, dpy); 129 reset_layer_prop(ctx, dpy); 130 if(!MDPComp::configure(ctx, list)) { 131 VideoOverlay::prepare(ctx, list, dpy); 132 ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer); 133 } 134 ctx->mLayerCache[dpy]->updateLayerCache(list); 135 } 136 } 137 return 0; 138} 139 140static int hwc_prepare_external(hwc_composer_device_1 *dev, 141 hwc_display_contents_1_t *list) { 142 hwc_context_t* ctx = (hwc_context_t*)(dev); 143 const int dpy = HWC_DISPLAY_EXTERNAL; 144 145 if (LIKELY(list && list->numHwLayers > 1) && 146 ctx->dpyAttr[dpy].isActive && 147 ctx->dpyAttr[dpy].connected) { 148 149 uint32_t last = list->numHwLayers - 1; 150 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 151 if(fbLayer->handle) { 152 setListStats(ctx, list, dpy); 153 reset_layer_prop(ctx, dpy); 154 VideoOverlay::prepare(ctx, list, dpy); 155 ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer); 156 ctx->mLayerCache[dpy]->updateLayerCache(list); 157 } 158 } 159 return 0; 160} 161 162static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, 163 hwc_display_contents_1_t** displays) 164{ 165 int ret = 0; 166 hwc_context_t* ctx = (hwc_context_t*)(dev); 167 Locker::Autolock _l(ctx->mBlankLock); 168 reset(ctx, numDisplays, displays); 169 170 ctx->mOverlay->configBegin(); 171 172 for (int32_t i = numDisplays - 1; i >= 0; i--) { 173 hwc_display_contents_1_t *list = displays[i]; 174 switch(i) { 175 case HWC_DISPLAY_PRIMARY: 176 ret = hwc_prepare_primary(dev, list); 177 break; 178 case HWC_DISPLAY_EXTERNAL: 179 ret = hwc_prepare_external(dev, list); 180 break; 181 default: 182 ret = -EINVAL; 183 } 184 } 185 186 ctx->mOverlay->configDone(); 187 return ret; 188} 189 190static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, 191 int event, int enabled) 192{ 193 int ret = 0; 194 195 hwc_context_t* ctx = (hwc_context_t*)(dev); 196 private_module_t* m = reinterpret_cast<private_module_t*>( 197 ctx->mFbDev->common.module); 198 pthread_mutex_lock(&ctx->vstate.lock); 199 switch(event) { 200 case HWC_EVENT_VSYNC: 201 if (ctx->vstate.enable == enabled) 202 break; 203 ctx->vstate.enable = !!enabled; 204 pthread_cond_signal(&ctx->vstate.cond); 205 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s", 206 (enabled)?"ENABLED":"DISABLED"); 207 break; 208 default: 209 ret = -EINVAL; 210 } 211 pthread_mutex_unlock(&ctx->vstate.lock); 212 return ret; 213} 214 215static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) 216{ 217 hwc_context_t* ctx = (hwc_context_t*)(dev); 218 private_module_t* m = reinterpret_cast<private_module_t*>( 219 ctx->mFbDev->common.module); 220 Locker::Autolock _l(ctx->mBlankLock); 221 int ret = 0; 222 ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank); 223 switch(dpy) { 224 case HWC_DISPLAY_PRIMARY: 225 if(blank) { 226 ctx->mOverlay->configBegin(); 227 ctx->mOverlay->configDone(); 228 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); 229 } else { 230 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK); 231 } 232 break; 233 case HWC_DISPLAY_EXTERNAL: 234 if(blank) { 235 //TODO actual 236 } else { 237 } 238 break; 239 default: 240 return -EINVAL; 241 } 242 // Enable HPD here, as during bootup unblank is called 243 // when SF is completely initialized 244 ctx->mExtDisplay->setHPD(1); 245 246 if(ret < 0) { 247 ALOGE("%s: failed. Dpy=%d, blank=%d : %s", 248 __FUNCTION__, dpy, blank, strerror(errno)); 249 return ret; 250 } 251 ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank); 252 ctx->dpyAttr[dpy].isActive = !blank; 253 return 0; 254} 255 256static int hwc_query(struct hwc_composer_device_1* dev, 257 int param, int* value) 258{ 259 hwc_context_t* ctx = (hwc_context_t*)(dev); 260 private_module_t* m = reinterpret_cast<private_module_t*>( 261 ctx->mFbDev->common.module); 262 int supported = HWC_DISPLAY_PRIMARY_BIT; 263 264 switch (param) { 265 case HWC_BACKGROUND_LAYER_SUPPORTED: 266 // Not supported for now 267 value[0] = 0; 268 break; 269 case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1 270 value[0] = m->fps; 271 ALOGI("fps: %d", value[0]); 272 break; 273 case HWC_DISPLAY_TYPES_SUPPORTED: 274 if(ctx->mMDP.hasOverlay) 275 supported |= HWC_DISPLAY_EXTERNAL_BIT; 276 value[0] = supported; 277 break; 278 default: 279 return -EINVAL; 280 } 281 return 0; 282 283} 284 285static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { 286 int ret = 0; 287 const int dpy = HWC_DISPLAY_PRIMARY; 288 289 if (LIKELY(list && list->numHwLayers > 1) && 290 ctx->dpyAttr[dpy].isActive) { 291 uint32_t last = list->numHwLayers - 1; 292 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 293 294 hwc_sync(ctx, list, dpy); 295 if (!VideoOverlay::draw(ctx, list, dpy)) { 296 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); 297 ret = -1; 298 } 299 if (!MDPComp::draw(ctx, list)) { 300 ALOGE("%s: MDPComp::draw fail!", __FUNCTION__); 301 ret = -1; 302 } 303 304 //TODO We dont check for SKIP flag on this layer because we need PAN 305 //always. Last layer is always FB 306 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 307 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) { 308 if(!(fbLayer->flags & HWC_SKIP_LAYER)) { 309 if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) { 310 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 311 ret = -1; 312 } 313 } 314 if (ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle)) { 315 ALOGE("%s: ctx->mFbDev->post fail!", __FUNCTION__); 316 return -1; 317 } 318 } 319 } 320 return ret; 321} 322 323static int hwc_set_external(hwc_context_t *ctx, 324 hwc_display_contents_1_t* list) { 325 int ret = 0; 326 const int dpy = HWC_DISPLAY_EXTERNAL; 327 328 Locker::Autolock _l(ctx->mExtSetLock); 329 330 if (LIKELY(list && list->numHwLayers > 1) && 331 ctx->dpyAttr[dpy].isActive && 332 ctx->dpyAttr[dpy].connected) { 333 uint32_t last = list->numHwLayers - 1; 334 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 335 336 hwc_sync(ctx, list, dpy); 337 338 if (!VideoOverlay::draw(ctx, list, dpy)) { 339 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); 340 ret = -1; 341 } 342 343 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 344 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && 345 !(fbLayer->flags & HWC_SKIP_LAYER) && hnd) { 346 if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) { 347 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 348 ret = -1; 349 } 350 } 351 if (!ctx->mExtDisplay->post()) { 352 ALOGE("%s: ctx->mExtDisplay->post fail!", __FUNCTION__); 353 return -1; 354 } 355 } 356 return ret; 357} 358 359static int hwc_set(hwc_composer_device_1 *dev, 360 size_t numDisplays, 361 hwc_display_contents_1_t** displays) 362{ 363 int ret = 0; 364 hwc_context_t* ctx = (hwc_context_t*)(dev); 365 Locker::Autolock _l(ctx->mBlankLock); 366 367 for (uint32_t i = 0; i < numDisplays; i++) { 368 hwc_display_contents_1_t* list = displays[i]; 369 switch(i) { 370 case HWC_DISPLAY_PRIMARY: 371 ret = hwc_set_primary(ctx, list); 372 break; 373 case HWC_DISPLAY_EXTERNAL: 374 ret = hwc_set_external(ctx, list); 375 break; 376 default: 377 ret = -EINVAL; 378 } 379 } 380 return ret; 381} 382 383int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, 384 uint32_t* configs, size_t* numConfigs) { 385 int ret = 0; 386 hwc_context_t* ctx = (hwc_context_t*)(dev); 387 //in 1.1 there is no way to choose a config, report as config id # 0 388 //This config is passed to getDisplayAttributes. Ignore for now. 389 switch(disp) { 390 case HWC_DISPLAY_PRIMARY: 391 if(*numConfigs > 0) { 392 configs[0] = 0; 393 *numConfigs = 1; 394 } 395 ret = 0; //NO_ERROR 396 break; 397 case HWC_DISPLAY_EXTERNAL: 398 ret = -1; //Not connected 399 if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) { 400 ret = 0; //NO_ERROR 401 if(*numConfigs > 0) { 402 configs[0] = 0; 403 *numConfigs = 1; 404 } 405 } 406 break; 407 } 408 return ret; 409} 410 411int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, 412 uint32_t config, const uint32_t* attributes, int32_t* values) { 413 414 hwc_context_t* ctx = (hwc_context_t*)(dev); 415 //If hotpluggable displays are inactive return error 416 if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) { 417 return -1; 418 } 419 420 //From HWComposer 421 static const uint32_t DISPLAY_ATTRIBUTES[] = { 422 HWC_DISPLAY_VSYNC_PERIOD, 423 HWC_DISPLAY_WIDTH, 424 HWC_DISPLAY_HEIGHT, 425 HWC_DISPLAY_DPI_X, 426 HWC_DISPLAY_DPI_Y, 427 HWC_DISPLAY_NO_ATTRIBUTE, 428 }; 429 430 const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / 431 sizeof(DISPLAY_ATTRIBUTES)[0]); 432 433 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { 434 switch (attributes[i]) { 435 case HWC_DISPLAY_VSYNC_PERIOD: 436 values[i] = ctx->dpyAttr[disp].vsync_period; 437 break; 438 case HWC_DISPLAY_WIDTH: 439 values[i] = ctx->dpyAttr[disp].xres; 440 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp, 441 ctx->dpyAttr[disp].xres); 442 break; 443 case HWC_DISPLAY_HEIGHT: 444 values[i] = ctx->dpyAttr[disp].yres; 445 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp, 446 ctx->dpyAttr[disp].yres); 447 break; 448 case HWC_DISPLAY_DPI_X: 449 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0); 450 break; 451 case HWC_DISPLAY_DPI_Y: 452 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0); 453 break; 454 default: 455 ALOGE("Unknown display attribute %d", 456 attributes[i]); 457 return -EINVAL; 458 } 459 } 460 return 0; 461} 462 463void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) 464{ 465 hwc_context_t* ctx = (hwc_context_t*)(dev); 466 android::String8 buf(""); 467 dumpsys_log(buf, "Qualcomm HWC state:\n"); 468 dumpsys_log(buf, " MDPVersion=%d\n", ctx->mMDP.version); 469 dumpsys_log(buf, " DisplayPanel=%c\n", ctx->mMDP.panel); 470 MDPComp::dump(buf); 471 //XXX: Call Other dump functions 472 strlcpy(buff, buf.string(), buff_len); 473} 474 475static int hwc_device_close(struct hw_device_t *dev) 476{ 477 if(!dev) { 478 ALOGE("%s: NULL device pointer", __FUNCTION__); 479 return -1; 480 } 481 closeContext((hwc_context_t*)dev); 482 free(dev); 483 484 return 0; 485} 486 487static int hwc_device_open(const struct hw_module_t* module, const char* name, 488 struct hw_device_t** device) 489{ 490 int status = -EINVAL; 491 492 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 493 struct hwc_context_t *dev; 494 dev = (hwc_context_t*)malloc(sizeof(*dev)); 495 memset(dev, 0, sizeof(*dev)); 496 497 //Initialize hwc context 498 initContext(dev); 499 500 //Setup HWC methods 501 dev->device.common.tag = HARDWARE_DEVICE_TAG; 502 dev->device.common.version = HWC_DEVICE_API_VERSION_1_1; 503 dev->device.common.module = const_cast<hw_module_t*>(module); 504 dev->device.common.close = hwc_device_close; 505 dev->device.prepare = hwc_prepare; 506 dev->device.set = hwc_set; 507 dev->device.eventControl = hwc_eventControl; 508 dev->device.blank = hwc_blank; 509 dev->device.query = hwc_query; 510 dev->device.registerProcs = hwc_registerProcs; 511 dev->device.dump = hwc_dump; 512 dev->device.getDisplayConfigs = hwc_getDisplayConfigs; 513 dev->device.getDisplayAttributes = hwc_getDisplayAttributes; 514 *device = &dev->device.common; 515 status = 0; 516 } 517 return status; 518} 519