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