1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * Copyright (C) 2012-2014, 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 #include <fcntl.h> 21 #include <errno.h> 22 23 #include <cutils/log.h> 24 #include <utils/Trace.h> 25 #include <overlayWriteback.h> 26 #include "hwc_utils.h" 27 #include "hwc_fbupdate.h" 28 #include "hwc_mdpcomp.h" 29 #include "hwc_dump_layers.h" 30 #include "hwc_copybit.h" 31 #include "hwc_virtual.h" 32 #include "sync/sync.h" 33 34 #define HWCVIRTUAL_LOG 0 35 36 using namespace qhwc; 37 using namespace overlay; 38 39 HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) { 40 41 if(isVDSEnabled) { 42 ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display", 43 __FUNCTION__); 44 return new HWCVirtualVDS(); 45 } else { 46 ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display", 47 __FUNCTION__); 48 return new HWCVirtualV4L2(); 49 } 50 } 51 52 HWCVirtualVDS::HWCVirtualVDS() { 53 char value[PROPERTY_VALUE_MAX]; 54 mVDSDumpEnabled = false; 55 if((property_get("debug.hwc.enable_vds_dump", value, NULL) > 0)) { 56 if(atoi(value) != 0) { 57 mVDSDumpEnabled = true; 58 } 59 } 60 } 61 62 void HWCVirtualVDS::init(hwc_context_t *ctx) { 63 const int dpy = HWC_DISPLAY_VIRTUAL; 64 ctx->mFBUpdate[dpy] = 65 IFBUpdate::getObject(ctx, dpy); 66 ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy); 67 68 if(ctx->mFBUpdate[dpy]) 69 ctx->mFBUpdate[dpy]->reset(); 70 if(ctx->mMDPComp[dpy]) 71 ctx->mMDPComp[dpy]->reset(); 72 } 73 74 void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/, 75 hwc_display_contents_1_t** displays) { 76 int dpy = HWC_DISPLAY_VIRTUAL; 77 78 //Cleanup virtual display objs, since there is no explicit disconnect 79 if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) { 80 ctx->dpyAttr[dpy].connected = false; 81 ctx->dpyAttr[dpy].isPause = false; 82 83 if(ctx->mFBUpdate[dpy]) { 84 delete ctx->mFBUpdate[dpy]; 85 ctx->mFBUpdate[dpy] = NULL; 86 } 87 if(ctx->mMDPComp[dpy]) { 88 delete ctx->mMDPComp[dpy]; 89 ctx->mMDPComp[dpy] = NULL; 90 } 91 // We reset the WB session to non-secure when the virtual display 92 // has been disconnected. 93 if(!Writeback::getInstance()->setSecure(false)) { 94 ALOGE("Failure while attempting to reset WB session."); 95 } 96 ctx->mWfdSyncLock.lock(); 97 ctx->mWfdSyncLock.signal(); 98 ctx->mWfdSyncLock.unlock(); 99 } 100 } 101 102 int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev, 103 hwc_display_contents_1_t *list) { 104 ATRACE_CALL(); 105 //XXX: Fix when framework support is added 106 hwc_context_t* ctx = (hwc_context_t*)(dev); 107 const int dpy = HWC_DISPLAY_VIRTUAL; 108 109 if (list && list->outbuf && list->numHwLayers > 0) { 110 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 111 uint32_t last = (uint32_t)list->numHwLayers - 1; 112 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 113 int fbWidth = 0, fbHeight = 0; 114 getLayerResolution(fbLayer, fbWidth, fbHeight); 115 ctx->dpyAttr[dpy].xres = fbWidth; 116 ctx->dpyAttr[dpy].yres = fbHeight; 117 118 if(ctx->dpyAttr[dpy].connected == false) { 119 ctx->dpyAttr[dpy].connected = true; 120 ctx->dpyAttr[dpy].isPause = false; 121 // We set the vsync period to the primary refresh rate, leaving 122 // it up to the consumer to decide how fast to consume frames. 123 ctx->dpyAttr[dpy].vsync_period 124 = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period; 125 init(ctx); 126 // XXX: for architectures with limited resources we would normally 127 // allow one padding round to free up resources but this breaks 128 // certain use cases. 129 } 130 if(!ctx->dpyAttr[dpy].isPause) { 131 ctx->dpyAttr[dpy].isConfiguring = false; 132 ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd(); 133 private_handle_t *ohnd = (private_handle_t *)list->outbuf; 134 Writeback::getInstance()->configureDpyInfo(ohnd->width, 135 ohnd->height); 136 setListStats(ctx, list, dpy); 137 138 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 139 const int fbZ = 0; 140 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) 141 { 142 ctx->mOverlay->clear(dpy); 143 ctx->mLayerRotMap[dpy]->clear(); 144 } 145 } 146 } else { 147 /* Virtual Display is in Pause state. 148 * Mark all application layers as OVERLAY so that 149 * GPU will not compose. 150 */ 151 Writeback::getInstance(); //Ensure that WB is active during pause 152 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { 153 hwc_layer_1_t *layer = &list->hwLayers[i]; 154 layer->compositionType = HWC_OVERLAY; 155 } 156 } 157 } 158 return 0; 159 } 160 161 int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) { 162 ATRACE_CALL(); 163 int ret = 0; 164 const int dpy = HWC_DISPLAY_VIRTUAL; 165 166 if (list && list->outbuf && list->numHwLayers > 0) { 167 uint32_t last = (uint32_t)list->numHwLayers - 1; 168 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 169 170 if(ctx->dpyAttr[dpy].connected 171 && (!ctx->dpyAttr[dpy].isPause)) 172 { 173 private_handle_t *ohnd = (private_handle_t *)list->outbuf; 174 int format = ohnd->format; 175 if (format == HAL_PIXEL_FORMAT_RGBA_8888) 176 format = HAL_PIXEL_FORMAT_RGBX_8888; 177 Writeback::getInstance()->setOutputFormat( 178 utils::getMdpFormat(format)); 179 180 // Configure WB as secure if the output buffer handle is secure. 181 if(isSecureBuffer(ohnd)){ 182 if(! Writeback::getInstance()->setSecure(true)) 183 { 184 ALOGE("Failed to set WB as secure for virtual display"); 185 return false; 186 } 187 } 188 189 int fd = -1; //FenceFD from the Copybit 190 hwc_sync(ctx, list, dpy, fd); 191 192 // Dump the layers for virtual 193 if(ctx->mHwcDebug[dpy]) 194 ctx->mHwcDebug[dpy]->dumpLayers(list); 195 196 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 197 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 198 ret = -1; 199 } 200 // We need an FB layer handle check to cater for this usecase: 201 // Video is playing in landscape on primary, then launch 202 // ScreenRecord app. 203 // In this scenario, the first VDS draw call will have HWC 204 // composition and VDS does nit involve GPU to get eglSwapBuffer 205 // to get valid fb handle. 206 if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx, 207 (private_handle_t *)fbLayer->handle)) { 208 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 209 ret = -1; 210 } 211 212 Writeback::getInstance()->queueBuffer(ohnd->fd, 213 (uint32_t)ohnd->offset); 214 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 215 ALOGE("%s: display commit fail!", __FUNCTION__); 216 ret = -1; 217 } 218 219 if(mVDSDumpEnabled) { 220 char bufferName[128]; 221 // Dumping frame buffer 222 sync_wait(fbLayer->acquireFenceFd, 1000); 223 snprintf(bufferName, sizeof(bufferName), "vds.fb"); 224 dumpBuffer((private_handle_t *)fbLayer->handle, bufferName); 225 // Dumping WB output for non-secure session 226 if(!isSecureBuffer(ohnd)) { 227 sync_wait(list->retireFenceFd, 1000); 228 snprintf(bufferName, sizeof(bufferName), "vds.wb"); 229 dumpBuffer(ohnd, bufferName); 230 } 231 } 232 } else if(list->outbufAcquireFenceFd >= 0) { 233 //If we dont handle the frame, set retireFenceFd to outbufFenceFd, 234 //which will make sure, the framework waits on it and closes it. 235 //The other way is to wait on outbufFenceFd ourselves, close it and 236 //set retireFenceFd to -1. Since we want hwc to be async, choosing 237 //the former. 238 //Also dup because, the closeAcquireFds() will close the outbufFence 239 list->retireFenceFd = dup(list->outbufAcquireFenceFd); 240 } 241 } 242 243 closeAcquireFds(list); 244 return ret; 245 } 246 247 void HWCVirtualVDS::pause(hwc_context_t* ctx, int dpy) { 248 { 249 Locker::Autolock _l(ctx->mDrawLock); 250 ctx->dpyAttr[dpy].isActive = true; 251 ctx->dpyAttr[dpy].isPause = true; 252 ctx->proc->invalidate(ctx->proc); 253 } 254 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period 255 * 2 / 1000); 256 // At this point all the pipes used by External have been 257 // marked as UNSET. 258 { 259 Locker::Autolock _l(ctx->mDrawLock); 260 // Perform commit to unstage the pipes. 261 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 262 ALOGE("%s: display commit fail! for %d dpy", 263 __FUNCTION__, dpy); 264 } 265 ctx->proc->invalidate(ctx->proc); 266 } 267 return; 268 } 269 270 void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) { 271 { 272 Locker::Autolock _l(ctx->mDrawLock); 273 ctx->dpyAttr[dpy].isConfiguring = true; 274 ctx->dpyAttr[dpy].isActive = true; 275 ctx->proc->invalidate(ctx->proc); 276 } 277 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period 278 * 2 / 1000); 279 //At this point external has all the pipes it would need. 280 { 281 Locker::Autolock _l(ctx->mDrawLock); 282 ctx->dpyAttr[dpy].isPause = false; 283 ctx->proc->invalidate(ctx->proc); 284 } 285 return; 286 } 287 288 /* Implementation for HWCVirtualV4L2 class */ 289 290 int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev, 291 hwc_display_contents_1_t *list) { 292 ATRACE_CALL(); 293 294 hwc_context_t* ctx = (hwc_context_t*)(dev); 295 const int dpy = HWC_DISPLAY_VIRTUAL; 296 297 if (LIKELY(list && list->numHwLayers > 1) && 298 ctx->dpyAttr[dpy].isActive && 299 ctx->dpyAttr[dpy].connected) { 300 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); 301 if(!ctx->dpyAttr[dpy].isPause) { 302 ctx->dpyAttr[dpy].isConfiguring = false; 303 setListStats(ctx, list, dpy); 304 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 305 const int fbZ = 0; 306 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) 307 { 308 ctx->mOverlay->clear(dpy); 309 ctx->mLayerRotMap[dpy]->clear(); 310 } 311 } 312 } else { 313 /* Virtual Display is in Pause state. 314 * Mark all application layers as OVERLAY so that 315 * GPU will not compose. 316 */ 317 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { 318 hwc_layer_1_t *layer = &list->hwLayers[i]; 319 layer->compositionType = HWC_OVERLAY; 320 } 321 } 322 } 323 return 0; 324 } 325 326 int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) { 327 ATRACE_CALL(); 328 int ret = 0; 329 330 const int dpy = HWC_DISPLAY_VIRTUAL; 331 332 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && 333 ctx->dpyAttr[dpy].connected && 334 !ctx->dpyAttr[dpy].isPause) { 335 uint32_t last = (uint32_t)list->numHwLayers - 1; 336 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 337 int fd = -1; //FenceFD from the Copybit(valid in async mode) 338 bool copybitDone = false; 339 if(ctx->mCopyBit[dpy]) 340 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 341 342 if(list->numHwLayers > 1) 343 hwc_sync(ctx, list, dpy, fd); 344 345 // Dump the layers for virtual 346 if(ctx->mHwcDebug[dpy]) 347 ctx->mHwcDebug[dpy]->dumpLayers(list); 348 349 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 350 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 351 ret = -1; 352 } 353 354 int extOnlyLayerIndex = 355 ctx->listStats[dpy].extOnlyLayerIndex; 356 357 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 358 if(extOnlyLayerIndex!= -1) { 359 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex]; 360 hnd = (private_handle_t *)extLayer->handle; 361 } else if(copybitDone) { 362 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 363 } 364 365 if(hnd && !isYuvBuffer(hnd)) { 366 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 367 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 368 ret = -1; 369 } 370 } 371 372 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 373 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 374 ret = -1; 375 } 376 } 377 378 closeAcquireFds(list); 379 380 if (list && list->outbuf && (list->retireFenceFd < 0) ) { 381 // SF assumes HWC waits for the acquire fence and returns a new fence 382 // that signals when we're done. Since we don't wait, and also don't 383 // touch the buffer, we can just handle the acquire fence back to SF 384 // as the retire fence. 385 list->retireFenceFd = list->outbufAcquireFenceFd; 386 } 387 388 return ret; 389 } 390 391 void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) { 392 { 393 Locker::Autolock _l(ctx->mDrawLock); 394 ctx->dpyAttr[dpy].isActive = true; 395 ctx->dpyAttr[dpy].isPause = true; 396 ctx->proc->invalidate(ctx->proc); 397 } 398 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period 399 * 2 / 1000); 400 // At this point all the pipes used by External have been 401 // marked as UNSET. 402 { 403 Locker::Autolock _l(ctx->mDrawLock); 404 // Perform commit to unstage the pipes. 405 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 406 ALOGE("%s: display commit fail! for %d dpy", 407 __FUNCTION__, dpy); 408 } 409 } 410 return; 411 } 412 413 void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){ 414 //Treat Resume as Online event 415 //Since external didnt have any pipes, force primary to give up 416 //its pipes; we don't allow inter-mixer pipe transfers. 417 { 418 Locker::Autolock _l(ctx->mDrawLock); 419 420 // A dynamic resolution change (DRC) can be made for a WiFi 421 // display. In order to support the resolution change, we 422 // need to reconfigure the corresponding display attributes. 423 // Since DRC is only on WiFi display, we only need to call 424 // configure() on the VirtualDisplay device. 425 //TODO: clean up 426 if(dpy == HWC_DISPLAY_VIRTUAL) 427 ctx->mVirtualDisplay->configure(); 428 429 ctx->dpyAttr[dpy].isConfiguring = true; 430 ctx->dpyAttr[dpy].isActive = true; 431 ctx->proc->invalidate(ctx->proc); 432 } 433 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period 434 * 2 / 1000); 435 //At this point external has all the pipes it would need. 436 { 437 Locker::Autolock _l(ctx->mDrawLock); 438 ctx->dpyAttr[dpy].isPause = false; 439 ctx->proc->invalidate(ctx->proc); 440 } 441 return; 442 } 443