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 33#define HWCVIRTUAL_LOG 0 34 35using namespace qhwc; 36using namespace overlay; 37 38HWCVirtualBase* HWCVirtualBase::getObject() { 39 char property[PROPERTY_VALUE_MAX]; 40 41 if((property_get("persist.hwc.enable_vds", property, NULL) > 0)) { 42 if(atoi(property) != 0) { 43 ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display", 44 __FUNCTION__); 45 return new HWCVirtualVDS(); 46 } 47 } 48 ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display", 49 __FUNCTION__); 50 return new HWCVirtualV4L2(); 51} 52 53void HWCVirtualVDS::init(hwc_context_t *ctx) { 54 const int dpy = HWC_DISPLAY_VIRTUAL; 55 ctx->mFBUpdate[dpy] = 56 IFBUpdate::getObject(ctx, dpy); 57 ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy); 58 59 if(ctx->mFBUpdate[dpy]) 60 ctx->mFBUpdate[dpy]->reset(); 61 if(ctx->mMDPComp[dpy]) 62 ctx->mMDPComp[dpy]->reset(); 63} 64 65void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/, 66 hwc_display_contents_1_t** displays) { 67 int dpy = HWC_DISPLAY_VIRTUAL; 68 69 //Cleanup virtual display objs, since there is no explicit disconnect 70 if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) { 71 ctx->dpyAttr[dpy].connected = false; 72 73 if(ctx->mFBUpdate[dpy]) { 74 delete ctx->mFBUpdate[dpy]; 75 ctx->mFBUpdate[dpy] = NULL; 76 } 77 if(ctx->mMDPComp[dpy]) { 78 delete ctx->mMDPComp[dpy]; 79 ctx->mMDPComp[dpy] = NULL; 80 } 81 // We reset the WB session to non-secure when the virtual display 82 // has been disconnected. 83 if(!Writeback::getInstance()->setSecure(false)) { 84 ALOGE("Failure while attempting to reset WB session."); 85 } 86 } 87} 88 89int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev, 90 hwc_display_contents_1_t *list) { 91 ATRACE_CALL(); 92 //XXX: Fix when framework support is added 93 hwc_context_t* ctx = (hwc_context_t*)(dev); 94 const int dpy = HWC_DISPLAY_VIRTUAL; 95 96 if (list && list->outbuf && list->numHwLayers > 0) { 97 reset_layer_prop(ctx, dpy, list->numHwLayers - 1); 98 uint32_t last = list->numHwLayers - 1; 99 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 100 int fbWidth = 0, fbHeight = 0; 101 getLayerResolution(fbLayer, fbWidth, fbHeight); 102 ctx->dpyAttr[dpy].xres = fbWidth; 103 ctx->dpyAttr[dpy].yres = fbHeight; 104 105 if(ctx->dpyAttr[dpy].connected == false) { 106 ctx->dpyAttr[dpy].connected = true; 107 // We set the vsync period to the primary refresh rate, leaving 108 // it up to the consumer to decide how fast to consume frames. 109 ctx->dpyAttr[dpy].vsync_period 110 = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period; 111 init(ctx); 112 // XXX: for architectures with limited resources we would normally 113 // allow one padding round to free up resources but this breaks 114 // certain use cases. 115 } 116 117 ctx->dpyAttr[dpy].isConfiguring = false; 118 ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd(); 119 private_handle_t *ohnd = (private_handle_t *)list->outbuf; 120 Writeback::getInstance()->configureDpyInfo(ohnd->width, ohnd->height); 121 setListStats(ctx, list, dpy); 122 123 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 124 const int fbZ = 0; 125 ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ); 126 } 127 } 128 return 0; 129} 130 131int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) { 132 ATRACE_CALL(); 133 int ret = 0; 134 const int dpy = HWC_DISPLAY_VIRTUAL; 135 136 if (list && list->outbuf && list->numHwLayers > 0) { 137 uint32_t last = list->numHwLayers - 1; 138 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 139 140 if(ctx->dpyAttr[dpy].connected) { 141 private_handle_t *ohnd = (private_handle_t *)list->outbuf; 142 int format = ohnd->format; 143 if (format == HAL_PIXEL_FORMAT_RGBA_8888) 144 format = HAL_PIXEL_FORMAT_RGBX_8888; 145 Writeback::getInstance()->setOutputFormat( 146 utils::getMdpFormat(format)); 147 148 // Configure WB as secure if the output buffer handle is secure. 149 if(isSecureBuffer(ohnd)){ 150 if(! Writeback::getInstance()->setSecure(true)) 151 { 152 ALOGE("Failed to set WB as secure for virtual display"); 153 return false; 154 } 155 } 156 157 int fd = -1; //FenceFD from the Copybit 158 hwc_sync(ctx, list, dpy, fd); 159 160 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 161 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 162 ret = -1; 163 } 164 // We need an FB layer handle check to cater for this usecase: 165 // Video is playing in landscape on primary, then launch 166 // ScreenRecord app. 167 // In this scenario, the first VDS draw call will have HWC 168 // composition and VDS does nit involve GPU to get eglSwapBuffer 169 // to get valid fb handle. 170 if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx, 171 (private_handle_t *)fbLayer->handle)) { 172 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 173 ret = -1; 174 } 175 176 Writeback::getInstance()->queueBuffer(ohnd->fd, ohnd->offset); 177 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 178 ALOGE("%s: display commit fail!", __FUNCTION__); 179 ret = -1; 180 } 181 182 } else if(list->outbufAcquireFenceFd >= 0) { 183 //If we dont handle the frame, set retireFenceFd to outbufFenceFd, 184 //which will make sure, the framework waits on it and closes it. 185 //The other way is to wait on outbufFenceFd ourselves, close it and 186 //set retireFenceFd to -1. Since we want hwc to be async, choosing 187 //the former. 188 //Also dup because, the closeAcquireFds() will close the outbufFence 189 list->retireFenceFd = dup(list->outbufAcquireFenceFd); 190 } 191 } 192 193 closeAcquireFds(list); 194 return ret; 195} 196 197/* Implementation for HWCVirtualV4L2 class */ 198 199int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev, 200 hwc_display_contents_1_t *list) { 201 ATRACE_CALL(); 202 203 hwc_context_t* ctx = (hwc_context_t*)(dev); 204 const int dpy = HWC_DISPLAY_VIRTUAL; 205 206 if (LIKELY(list && list->numHwLayers > 1) && 207 ctx->dpyAttr[dpy].isActive && 208 ctx->dpyAttr[dpy].connected && 209 canUseMDPforVirtualDisplay(ctx,list)) { 210 reset_layer_prop(ctx, dpy, list->numHwLayers - 1); 211 if(!ctx->dpyAttr[dpy].isPause) { 212 ctx->dpyAttr[dpy].isConfiguring = false; 213 setListStats(ctx, list, dpy); 214 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { 215 const int fbZ = 0; 216 ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ); 217 } 218 } else { 219 /* Virtual Display is in Pause state. 220 * Mark all application layers as OVERLAY so that 221 * GPU will not compose. 222 */ 223 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { 224 hwc_layer_1_t *layer = &list->hwLayers[i]; 225 layer->compositionType = HWC_OVERLAY; 226 } 227 } 228 } 229 return 0; 230} 231 232int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) { 233 ATRACE_CALL(); 234 int ret = 0; 235 236 const int dpy = HWC_DISPLAY_VIRTUAL; 237 238 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && 239 ctx->dpyAttr[dpy].connected && 240 (!ctx->dpyAttr[dpy].isPause) && 241 canUseMDPforVirtualDisplay(ctx,list)) { 242 uint32_t last = list->numHwLayers - 1; 243 hwc_layer_1_t *fbLayer = &list->hwLayers[last]; 244 int fd = -1; //FenceFD from the Copybit(valid in async mode) 245 bool copybitDone = false; 246 if(ctx->mCopyBit[dpy]) 247 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); 248 249 if(list->numHwLayers > 1) 250 hwc_sync(ctx, list, dpy, fd); 251 252 // Dump the layers for virtual 253 if(ctx->mHwcDebug[dpy]) 254 ctx->mHwcDebug[dpy]->dumpLayers(list); 255 256 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { 257 ALOGE("%s: MDPComp draw failed", __FUNCTION__); 258 ret = -1; 259 } 260 261 int extOnlyLayerIndex = 262 ctx->listStats[dpy].extOnlyLayerIndex; 263 264 private_handle_t *hnd = (private_handle_t *)fbLayer->handle; 265 if(extOnlyLayerIndex!= -1) { 266 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex]; 267 hnd = (private_handle_t *)extLayer->handle; 268 } else if(copybitDone) { 269 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); 270 } 271 272 if(hnd && !isYuvBuffer(hnd)) { 273 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { 274 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); 275 ret = -1; 276 } 277 } 278 279 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { 280 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); 281 ret = -1; 282 } 283 } 284 285 closeAcquireFds(list); 286 287 if (list && list->outbuf && (list->retireFenceFd < 0) ) { 288 // SF assumes HWC waits for the acquire fence and returns a new fence 289 // that signals when we're done. Since we don't wait, and also don't 290 // touch the buffer, we can just handle the acquire fence back to SF 291 // as the retire fence. 292 list->retireFenceFd = list->outbufAcquireFenceFd; 293 } 294 295 return ret; 296} 297