blob: db43435e267d35bd52e60941245805aae884f1cd [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 }
Tatenda Chipeperekwa92961f82014-01-17 13:04:28 -080091 // 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 }
Raj kamal59fea562014-04-01 16:52:19 +053096 ctx->mWfdSyncLock.lock();
97 ctx->mWfdSyncLock.signal();
98 ctx->mWfdSyncLock.unlock();
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080099 }
100}
101
102int 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
Tatenda Chipeperekwab0a9f9d2014-01-20 09:23:21 -0800109 if (list && list->outbuf && list->numHwLayers > 0) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530110 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
111 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800112 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;
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800120 ctx->dpyAttr[dpy].isPause = false;
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800121 // 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;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800125 init(ctx);
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800126 // 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.
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800129 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800130 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);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800137
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800138 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
139 const int fbZ = 0;
Saurabh Shahef19fe32014-04-22 15:31:58 -0700140 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
141 {
142 ctx->mOverlay->clear(dpy);
143 ctx->mLayerRotMap[dpy]->clear();
144 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800145 }
146 } else {
147 /* Virtual Display is in Pause state.
148 * Mark all application layers as OVERLAY so that
149 * GPU will not compose.
150 */
Raj Kamale012e0e2014-05-28 23:45:19 +0530151 Writeback::getInstance(); //Ensure that WB is active during pause
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800152 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 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800156 }
157 }
158 return 0;
159}
160
161int 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
Tatenda Chipeperekwaf19f84d2014-01-17 12:43:29 -0800166 if (list && list->outbuf && list->numHwLayers > 0) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530167 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800168 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
169
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800170 if(ctx->dpyAttr[dpy].connected
171 && (!ctx->dpyAttr[dpy].isPause))
172 {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800173 private_handle_t *ohnd = (private_handle_t *)list->outbuf;
Tatenda Chipeperekwaa2fdebe2014-01-20 12:29:50 -0800174 int format = ohnd->format;
175 if (format == HAL_PIXEL_FORMAT_RGBA_8888)
176 format = HAL_PIXEL_FORMAT_RGBX_8888;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800177 Writeback::getInstance()->setOutputFormat(
Tatenda Chipeperekwaa2fdebe2014-01-20 12:29:50 -0800178 utils::getMdpFormat(format));
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800179
Tatenda Chipeperekwa92961f82014-01-17 13:04:28 -0800180 // 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
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800189 int fd = -1; //FenceFD from the Copybit
190 hwc_sync(ctx, list, dpy, fd);
191
Tatenda Chipeperekwa523eac52014-05-29 14:58:39 -0700192 // Dump the layers for virtual
193 if(ctx->mHwcDebug[dpy])
194 ctx->mHwcDebug[dpy]->dumpLayers(list);
195
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800196 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
197 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
198 ret = -1;
199 }
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800200 // 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,
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800207 (private_handle_t *)fbLayer->handle)) {
208 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
209 ret = -1;
210 }
211
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530212 Writeback::getInstance()->queueBuffer(ohnd->fd,
213 (uint32_t)ohnd->offset);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800214 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
215 ALOGE("%s: display commit fail!", __FUNCTION__);
216 ret = -1;
217 }
218
Tatenda Chipeperekwa523eac52014-05-29 14:58:39 -0700219 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 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800232 } 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
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800247void 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);
Raj Kamale012e0e2014-05-28 23:45:19 +0530256 // 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 }
Raj Kamaldf3d1d22014-05-30 21:23:27 +0530265 ctx->proc->invalidate(ctx->proc);
Raj Kamale012e0e2014-05-28 23:45:19 +0530266 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800267 return;
268}
269
270void 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
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800288/* Implementation for HWCVirtualV4L2 class */
289
290int 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 &&
Raj Kamal5ef25b82014-07-03 17:33:54 +0530299 ctx->dpyAttr[dpy].connected) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530300 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800301 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;
Saurabh Shahef19fe32014-04-22 15:31:58 -0700306 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
307 {
308 ctx->mOverlay->clear(dpy);
309 ctx->mLayerRotMap[dpy]->clear();
310 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800311 }
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
326int 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 &&
Raj Kamal5ef25b82014-07-03 17:33:54 +0530334 !ctx->dpyAttr[dpy].isPause) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530335 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800336 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
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800354 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
Ramkumar Radhakrishnan3d863772014-08-12 16:49:03 -0700355 if(copybitDone) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800356 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
357 }
358
Ramkumar Radhakrishnan3d863772014-08-12 16:49:03 -0700359 if(hnd) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800360 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
361 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
362 ret = -1;
363 }
364 }
365
366 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
367 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
368 ret = -1;
369 }
370 }
371
372 closeAcquireFds(list);
373
Baldev Sahuec852382014-02-14 08:36:00 +0530374 if (list && list->outbuf && (list->retireFenceFd < 0) ) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800375 // SF assumes HWC waits for the acquire fence and returns a new fence
376 // that signals when we're done. Since we don't wait, and also don't
377 // touch the buffer, we can just handle the acquire fence back to SF
378 // as the retire fence.
379 list->retireFenceFd = list->outbufAcquireFenceFd;
380 }
381
382 return ret;
383}
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800384
385void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
386 {
387 Locker::Autolock _l(ctx->mDrawLock);
388 ctx->dpyAttr[dpy].isActive = true;
389 ctx->dpyAttr[dpy].isPause = true;
390 ctx->proc->invalidate(ctx->proc);
391 }
392 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
393 * 2 / 1000);
394 // At this point all the pipes used by External have been
395 // marked as UNSET.
396 {
397 Locker::Autolock _l(ctx->mDrawLock);
398 // Perform commit to unstage the pipes.
399 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
400 ALOGE("%s: display commit fail! for %d dpy",
401 __FUNCTION__, dpy);
402 }
403 }
404 return;
405}
406
407void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
408 //Treat Resume as Online event
409 //Since external didnt have any pipes, force primary to give up
410 //its pipes; we don't allow inter-mixer pipe transfers.
411 {
412 Locker::Autolock _l(ctx->mDrawLock);
413
414 // A dynamic resolution change (DRC) can be made for a WiFi
415 // display. In order to support the resolution change, we
416 // need to reconfigure the corresponding display attributes.
417 // Since DRC is only on WiFi display, we only need to call
418 // configure() on the VirtualDisplay device.
419 //TODO: clean up
420 if(dpy == HWC_DISPLAY_VIRTUAL)
421 ctx->mVirtualDisplay->configure();
422
423 ctx->dpyAttr[dpy].isConfiguring = true;
424 ctx->dpyAttr[dpy].isActive = true;
425 ctx->proc->invalidate(ctx->proc);
426 }
427 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
428 * 2 / 1000);
429 //At this point external has all the pipes it would need.
430 {
431 Locker::Autolock _l(ctx->mDrawLock);
432 ctx->dpyAttr[dpy].isPause = false;
433 ctx->proc->invalidate(ctx->proc);
434 }
435 return;
436}