blob: 34fe7d3bb98f6487b32c222a464edcc9782599af [file] [log] [blame]
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -08001/*
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"
Tatenda Chipeperekwa523eac52014-05-29 14:58:39 -070032#include "sync/sync.h"
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080033
34#define HWCVIRTUAL_LOG 0
35
36using namespace qhwc;
37using namespace overlay;
38
Raj kamal59fea562014-04-01 16:52:19 +053039HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080040
Raj kamal59fea562014-04-01 16:52:19 +053041 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();
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080049 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080050}
51
Tatenda Chipeperekwa523eac52014-05-29 14:58:39 -070052HWCVirtualVDS::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
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080062void 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
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -080074void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080075 hwc_display_contents_1_t** displays) {
76 int dpy = HWC_DISPLAY_VIRTUAL;
77
78 //Cleanup virtual display objs, since there is no explicit disconnect
Raj Kamal52b4fdb2014-01-27 19:35:13 +053079 if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080080 ctx->dpyAttr[dpy].connected = false;
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -080081 ctx->dpyAttr[dpy].isPause = false;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080082
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 }
Manoj Kumar AVMfb472b02014-08-21 15:13:37 -070091 // signal synclock to indicate successful wfd teardown
Raj kamal59fea562014-04-01 16:52:19 +053092 ctx->mWfdSyncLock.lock();
93 ctx->mWfdSyncLock.signal();
94 ctx->mWfdSyncLock.unlock();
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080095 }
96}
97
98int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev,
99 hwc_display_contents_1_t *list) {
100 ATRACE_CALL();
101 //XXX: Fix when framework support is added
102 hwc_context_t* ctx = (hwc_context_t*)(dev);
103 const int dpy = HWC_DISPLAY_VIRTUAL;
104
Tatenda Chipeperekwab0a9f9d2014-01-20 09:23:21 -0800105 if (list && list->outbuf && list->numHwLayers > 0) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530106 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
107 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800108 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
109 int fbWidth = 0, fbHeight = 0;
110 getLayerResolution(fbLayer, fbWidth, fbHeight);
111 ctx->dpyAttr[dpy].xres = fbWidth;
112 ctx->dpyAttr[dpy].yres = fbHeight;
113
114 if(ctx->dpyAttr[dpy].connected == false) {
115 ctx->dpyAttr[dpy].connected = true;
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800116 ctx->dpyAttr[dpy].isPause = false;
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800117 // We set the vsync period to the primary refresh rate, leaving
118 // it up to the consumer to decide how fast to consume frames.
119 ctx->dpyAttr[dpy].vsync_period
120 = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800121 init(ctx);
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800122 // XXX: for architectures with limited resources we would normally
123 // allow one padding round to free up resources but this breaks
124 // certain use cases.
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800125 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800126 if(!ctx->dpyAttr[dpy].isPause) {
127 ctx->dpyAttr[dpy].isConfiguring = false;
128 ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
129 private_handle_t *ohnd = (private_handle_t *)list->outbuf;
130 Writeback::getInstance()->configureDpyInfo(ohnd->width,
131 ohnd->height);
132 setListStats(ctx, list, dpy);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800133
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800134 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
135 const int fbZ = 0;
Saurabh Shahef19fe32014-04-22 15:31:58 -0700136 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
137 {
138 ctx->mOverlay->clear(dpy);
139 ctx->mLayerRotMap[dpy]->clear();
140 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800141 }
142 } else {
143 /* Virtual Display is in Pause state.
144 * Mark all application layers as OVERLAY so that
145 * GPU will not compose.
146 */
Raj Kamale012e0e2014-05-28 23:45:19 +0530147 Writeback::getInstance(); //Ensure that WB is active during pause
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800148 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
149 hwc_layer_1_t *layer = &list->hwLayers[i];
150 layer->compositionType = HWC_OVERLAY;
151 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800152 }
153 }
154 return 0;
155}
156
157int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
158 ATRACE_CALL();
159 int ret = 0;
160 const int dpy = HWC_DISPLAY_VIRTUAL;
161
Tatenda Chipeperekwaf19f84d2014-01-17 12:43:29 -0800162 if (list && list->outbuf && list->numHwLayers > 0) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530163 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800164 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
165
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800166 if(ctx->dpyAttr[dpy].connected
167 && (!ctx->dpyAttr[dpy].isPause))
168 {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800169 private_handle_t *ohnd = (private_handle_t *)list->outbuf;
Tatenda Chipeperekwaa2fdebe2014-01-20 12:29:50 -0800170 int format = ohnd->format;
171 if (format == HAL_PIXEL_FORMAT_RGBA_8888)
172 format = HAL_PIXEL_FORMAT_RGBX_8888;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800173 Writeback::getInstance()->setOutputFormat(
Tatenda Chipeperekwaa2fdebe2014-01-20 12:29:50 -0800174 utils::getMdpFormat(format));
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800175
Manoj Kumar AVMfb472b02014-08-21 15:13:37 -0700176 // Configure WB secure mode based on output buffer handle
177 if(! Writeback::getInstance()->setSecure(isSecureBuffer(ohnd)))
178 {
179 ALOGE("Failed to set WB secure mode: %d for virtual display",
180 isSecureBuffer(ohnd));
181 return false;
Tatenda Chipeperekwa92961f82014-01-17 13:04:28 -0800182 }
183
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800184 int fd = -1; //FenceFD from the Copybit
185 hwc_sync(ctx, list, dpy, fd);
186
Tatenda Chipeperekwa523eac52014-05-29 14:58:39 -0700187 // Dump the layers for virtual
188 if(ctx->mHwcDebug[dpy])
189 ctx->mHwcDebug[dpy]->dumpLayers(list);
190
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800191 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
192 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
193 ret = -1;
194 }
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800195 // We need an FB layer handle check to cater for this usecase:
196 // Video is playing in landscape on primary, then launch
197 // ScreenRecord app.
198 // In this scenario, the first VDS draw call will have HWC
199 // composition and VDS does nit involve GPU to get eglSwapBuffer
200 // to get valid fb handle.
201 if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800202 (private_handle_t *)fbLayer->handle)) {
203 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
204 ret = -1;
205 }
206
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530207 Writeback::getInstance()->queueBuffer(ohnd->fd,
208 (uint32_t)ohnd->offset);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800209 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
210 ALOGE("%s: display commit fail!", __FUNCTION__);
211 ret = -1;
212 }
213
Tatenda Chipeperekwa523eac52014-05-29 14:58:39 -0700214 if(mVDSDumpEnabled) {
215 char bufferName[128];
216 // Dumping frame buffer
217 sync_wait(fbLayer->acquireFenceFd, 1000);
218 snprintf(bufferName, sizeof(bufferName), "vds.fb");
219 dumpBuffer((private_handle_t *)fbLayer->handle, bufferName);
220 // Dumping WB output for non-secure session
221 if(!isSecureBuffer(ohnd)) {
222 sync_wait(list->retireFenceFd, 1000);
223 snprintf(bufferName, sizeof(bufferName), "vds.wb");
224 dumpBuffer(ohnd, bufferName);
225 }
226 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800227 } else if(list->outbufAcquireFenceFd >= 0) {
228 //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
229 //which will make sure, the framework waits on it and closes it.
230 //The other way is to wait on outbufFenceFd ourselves, close it and
231 //set retireFenceFd to -1. Since we want hwc to be async, choosing
232 //the former.
233 //Also dup because, the closeAcquireFds() will close the outbufFence
234 list->retireFenceFd = dup(list->outbufAcquireFenceFd);
235 }
236 }
237
238 closeAcquireFds(list);
239 return ret;
240}
241
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800242void HWCVirtualVDS::pause(hwc_context_t* ctx, int dpy) {
243 {
244 Locker::Autolock _l(ctx->mDrawLock);
245 ctx->dpyAttr[dpy].isActive = true;
246 ctx->dpyAttr[dpy].isPause = true;
247 ctx->proc->invalidate(ctx->proc);
248 }
249 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
250 * 2 / 1000);
Raj Kamale012e0e2014-05-28 23:45:19 +0530251 // At this point all the pipes used by External have been
252 // marked as UNSET.
253 {
254 Locker::Autolock _l(ctx->mDrawLock);
255 // Perform commit to unstage the pipes.
256 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
257 ALOGE("%s: display commit fail! for %d dpy",
258 __FUNCTION__, dpy);
259 }
Raj Kamaldf3d1d22014-05-30 21:23:27 +0530260 ctx->proc->invalidate(ctx->proc);
Raj Kamale012e0e2014-05-28 23:45:19 +0530261 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800262 return;
263}
264
265void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) {
266 {
267 Locker::Autolock _l(ctx->mDrawLock);
268 ctx->dpyAttr[dpy].isConfiguring = true;
269 ctx->dpyAttr[dpy].isActive = true;
270 ctx->proc->invalidate(ctx->proc);
271 }
272 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
273 * 2 / 1000);
274 //At this point external has all the pipes it would need.
275 {
276 Locker::Autolock _l(ctx->mDrawLock);
277 ctx->dpyAttr[dpy].isPause = false;
278 ctx->proc->invalidate(ctx->proc);
279 }
280 return;
281}
282
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800283/* Implementation for HWCVirtualV4L2 class */
284
285int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev,
286 hwc_display_contents_1_t *list) {
287 ATRACE_CALL();
288
289 hwc_context_t* ctx = (hwc_context_t*)(dev);
290 const int dpy = HWC_DISPLAY_VIRTUAL;
291
292 if (LIKELY(list && list->numHwLayers > 1) &&
293 ctx->dpyAttr[dpy].isActive &&
Raj Kamal5ef25b82014-07-03 17:33:54 +0530294 ctx->dpyAttr[dpy].connected) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530295 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800296 if(!ctx->dpyAttr[dpy].isPause) {
297 ctx->dpyAttr[dpy].isConfiguring = false;
298 setListStats(ctx, list, dpy);
299 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
300 const int fbZ = 0;
Saurabh Shahef19fe32014-04-22 15:31:58 -0700301 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
302 {
303 ctx->mOverlay->clear(dpy);
304 ctx->mLayerRotMap[dpy]->clear();
305 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800306 }
307 } else {
308 /* Virtual Display is in Pause state.
309 * Mark all application layers as OVERLAY so that
310 * GPU will not compose.
311 */
312 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
313 hwc_layer_1_t *layer = &list->hwLayers[i];
314 layer->compositionType = HWC_OVERLAY;
315 }
316 }
317 }
318 return 0;
319}
320
321int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
322 ATRACE_CALL();
323 int ret = 0;
324
325 const int dpy = HWC_DISPLAY_VIRTUAL;
326
327 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
328 ctx->dpyAttr[dpy].connected &&
Raj Kamal5ef25b82014-07-03 17:33:54 +0530329 !ctx->dpyAttr[dpy].isPause) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530330 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800331 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
332 int fd = -1; //FenceFD from the Copybit(valid in async mode)
333 bool copybitDone = false;
334 if(ctx->mCopyBit[dpy])
335 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
336
337 if(list->numHwLayers > 1)
338 hwc_sync(ctx, list, dpy, fd);
339
340 // Dump the layers for virtual
341 if(ctx->mHwcDebug[dpy])
342 ctx->mHwcDebug[dpy]->dumpLayers(list);
343
344 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
345 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
346 ret = -1;
347 }
348
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800349 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
Ramkumar Radhakrishnan3d863772014-08-12 16:49:03 -0700350 if(copybitDone) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800351 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
352 }
353
Ramkumar Radhakrishnan3d863772014-08-12 16:49:03 -0700354 if(hnd) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800355 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
356 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
357 ret = -1;
358 }
359 }
360
361 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
362 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
363 ret = -1;
364 }
365 }
366
367 closeAcquireFds(list);
368
Baldev Sahuec852382014-02-14 08:36:00 +0530369 if (list && list->outbuf && (list->retireFenceFd < 0) ) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800370 // SF assumes HWC waits for the acquire fence and returns a new fence
371 // that signals when we're done. Since we don't wait, and also don't
372 // touch the buffer, we can just handle the acquire fence back to SF
373 // as the retire fence.
374 list->retireFenceFd = list->outbufAcquireFenceFd;
375 }
376
377 return ret;
378}
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800379
380void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
381 {
382 Locker::Autolock _l(ctx->mDrawLock);
383 ctx->dpyAttr[dpy].isActive = true;
384 ctx->dpyAttr[dpy].isPause = true;
385 ctx->proc->invalidate(ctx->proc);
386 }
387 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
388 * 2 / 1000);
389 // At this point all the pipes used by External have been
390 // marked as UNSET.
391 {
392 Locker::Autolock _l(ctx->mDrawLock);
393 // Perform commit to unstage the pipes.
394 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
395 ALOGE("%s: display commit fail! for %d dpy",
396 __FUNCTION__, dpy);
397 }
398 }
399 return;
400}
401
402void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
403 //Treat Resume as Online event
404 //Since external didnt have any pipes, force primary to give up
405 //its pipes; we don't allow inter-mixer pipe transfers.
406 {
407 Locker::Autolock _l(ctx->mDrawLock);
408
409 // A dynamic resolution change (DRC) can be made for a WiFi
410 // display. In order to support the resolution change, we
411 // need to reconfigure the corresponding display attributes.
412 // Since DRC is only on WiFi display, we only need to call
413 // configure() on the VirtualDisplay device.
414 //TODO: clean up
415 if(dpy == HWC_DISPLAY_VIRTUAL)
416 ctx->mVirtualDisplay->configure();
417
418 ctx->dpyAttr[dpy].isConfiguring = true;
419 ctx->dpyAttr[dpy].isActive = true;
420 ctx->proc->invalidate(ctx->proc);
421 }
422 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
423 * 2 / 1000);
424 //At this point external has all the pipes it would need.
425 {
426 Locker::Autolock _l(ctx->mDrawLock);
427 ctx->dpyAttr[dpy].isPause = false;
428 ctx->proc->invalidate(ctx->proc);
429 }
430 return;
431}