blob: df471a60839ba4d236e35ed17aef62d3043a3033 [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"
32
33#define HWCVIRTUAL_LOG 0
34
35using namespace qhwc;
36using namespace overlay;
37
Raj kamal59fea562014-04-01 16:52:19 +053038HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080039
Raj kamal59fea562014-04-01 16:52:19 +053040 if(isVDSEnabled) {
41 ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
42 __FUNCTION__);
43 return new HWCVirtualVDS();
44 } else {
45 ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
46 __FUNCTION__);
47 return new HWCVirtualV4L2();
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080048 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080049}
50
51void HWCVirtualVDS::init(hwc_context_t *ctx) {
52 const int dpy = HWC_DISPLAY_VIRTUAL;
53 ctx->mFBUpdate[dpy] =
54 IFBUpdate::getObject(ctx, dpy);
55 ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy);
56
57 if(ctx->mFBUpdate[dpy])
58 ctx->mFBUpdate[dpy]->reset();
59 if(ctx->mMDPComp[dpy])
60 ctx->mMDPComp[dpy]->reset();
61}
62
Arun Kumar K.R2aa44c62014-01-21 23:08:28 -080063void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080064 hwc_display_contents_1_t** displays) {
65 int dpy = HWC_DISPLAY_VIRTUAL;
66
67 //Cleanup virtual display objs, since there is no explicit disconnect
Raj Kamal52b4fdb2014-01-27 19:35:13 +053068 if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080069 ctx->dpyAttr[dpy].connected = false;
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -080070 ctx->dpyAttr[dpy].isPause = false;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080071
72 if(ctx->mFBUpdate[dpy]) {
73 delete ctx->mFBUpdate[dpy];
74 ctx->mFBUpdate[dpy] = NULL;
75 }
76 if(ctx->mMDPComp[dpy]) {
77 delete ctx->mMDPComp[dpy];
78 ctx->mMDPComp[dpy] = NULL;
79 }
Tatenda Chipeperekwa92961f82014-01-17 13:04:28 -080080 // We reset the WB session to non-secure when the virtual display
81 // has been disconnected.
82 if(!Writeback::getInstance()->setSecure(false)) {
83 ALOGE("Failure while attempting to reset WB session.");
84 }
Raj kamal59fea562014-04-01 16:52:19 +053085 ctx->mWfdSyncLock.lock();
86 ctx->mWfdSyncLock.signal();
87 ctx->mWfdSyncLock.unlock();
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -080088 }
89}
90
91int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev,
92 hwc_display_contents_1_t *list) {
93 ATRACE_CALL();
94 //XXX: Fix when framework support is added
95 hwc_context_t* ctx = (hwc_context_t*)(dev);
96 const int dpy = HWC_DISPLAY_VIRTUAL;
97
Tatenda Chipeperekwab0a9f9d2014-01-20 09:23:21 -080098 if (list && list->outbuf && list->numHwLayers > 0) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +053099 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
100 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800101 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
102 int fbWidth = 0, fbHeight = 0;
103 getLayerResolution(fbLayer, fbWidth, fbHeight);
104 ctx->dpyAttr[dpy].xres = fbWidth;
105 ctx->dpyAttr[dpy].yres = fbHeight;
106
107 if(ctx->dpyAttr[dpy].connected == false) {
108 ctx->dpyAttr[dpy].connected = true;
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800109 ctx->dpyAttr[dpy].isPause = false;
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800110 // We set the vsync period to the primary refresh rate, leaving
111 // it up to the consumer to decide how fast to consume frames.
112 ctx->dpyAttr[dpy].vsync_period
113 = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800114 init(ctx);
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800115 // XXX: for architectures with limited resources we would normally
116 // allow one padding round to free up resources but this breaks
117 // certain use cases.
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800118 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800119 if(!ctx->dpyAttr[dpy].isPause) {
120 ctx->dpyAttr[dpy].isConfiguring = false;
121 ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
122 private_handle_t *ohnd = (private_handle_t *)list->outbuf;
123 Writeback::getInstance()->configureDpyInfo(ohnd->width,
124 ohnd->height);
125 setListStats(ctx, list, dpy);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800126
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800127 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
128 const int fbZ = 0;
Saurabh Shahef19fe32014-04-22 15:31:58 -0700129 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
130 {
131 ctx->mOverlay->clear(dpy);
132 ctx->mLayerRotMap[dpy]->clear();
133 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800134 }
135 } else {
136 /* Virtual Display is in Pause state.
137 * Mark all application layers as OVERLAY so that
138 * GPU will not compose.
139 */
Raj Kamale012e0e2014-05-28 23:45:19 +0530140 Writeback::getInstance(); //Ensure that WB is active during pause
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800141 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
142 hwc_layer_1_t *layer = &list->hwLayers[i];
143 layer->compositionType = HWC_OVERLAY;
144 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800145 }
146 }
147 return 0;
148}
149
150int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
151 ATRACE_CALL();
152 int ret = 0;
153 const int dpy = HWC_DISPLAY_VIRTUAL;
154
Tatenda Chipeperekwaf19f84d2014-01-17 12:43:29 -0800155 if (list && list->outbuf && list->numHwLayers > 0) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530156 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800157 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
158
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800159 if(ctx->dpyAttr[dpy].connected
160 && (!ctx->dpyAttr[dpy].isPause))
161 {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800162 private_handle_t *ohnd = (private_handle_t *)list->outbuf;
Tatenda Chipeperekwaa2fdebe2014-01-20 12:29:50 -0800163 int format = ohnd->format;
164 if (format == HAL_PIXEL_FORMAT_RGBA_8888)
165 format = HAL_PIXEL_FORMAT_RGBX_8888;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800166 Writeback::getInstance()->setOutputFormat(
Tatenda Chipeperekwaa2fdebe2014-01-20 12:29:50 -0800167 utils::getMdpFormat(format));
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800168
Tatenda Chipeperekwa92961f82014-01-17 13:04:28 -0800169 // Configure WB as secure if the output buffer handle is secure.
170 if(isSecureBuffer(ohnd)){
171 if(! Writeback::getInstance()->setSecure(true))
172 {
173 ALOGE("Failed to set WB as secure for virtual display");
174 return false;
175 }
176 }
177
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800178 int fd = -1; //FenceFD from the Copybit
179 hwc_sync(ctx, list, dpy, fd);
180
181 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
182 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
183 ret = -1;
184 }
Tatenda Chipeperekwad6a8d4b2014-01-14 18:31:20 -0800185 // We need an FB layer handle check to cater for this usecase:
186 // Video is playing in landscape on primary, then launch
187 // ScreenRecord app.
188 // In this scenario, the first VDS draw call will have HWC
189 // composition and VDS does nit involve GPU to get eglSwapBuffer
190 // to get valid fb handle.
191 if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800192 (private_handle_t *)fbLayer->handle)) {
193 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
194 ret = -1;
195 }
196
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530197 Writeback::getInstance()->queueBuffer(ohnd->fd,
198 (uint32_t)ohnd->offset);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800199 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
200 ALOGE("%s: display commit fail!", __FUNCTION__);
201 ret = -1;
202 }
203
204 } else if(list->outbufAcquireFenceFd >= 0) {
205 //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
206 //which will make sure, the framework waits on it and closes it.
207 //The other way is to wait on outbufFenceFd ourselves, close it and
208 //set retireFenceFd to -1. Since we want hwc to be async, choosing
209 //the former.
210 //Also dup because, the closeAcquireFds() will close the outbufFence
211 list->retireFenceFd = dup(list->outbufAcquireFenceFd);
212 }
213 }
214
215 closeAcquireFds(list);
216 return ret;
217}
218
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800219void HWCVirtualVDS::pause(hwc_context_t* ctx, int dpy) {
220 {
221 Locker::Autolock _l(ctx->mDrawLock);
222 ctx->dpyAttr[dpy].isActive = true;
223 ctx->dpyAttr[dpy].isPause = true;
224 ctx->proc->invalidate(ctx->proc);
225 }
226 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
227 * 2 / 1000);
Raj Kamale012e0e2014-05-28 23:45:19 +0530228 // At this point all the pipes used by External have been
229 // marked as UNSET.
230 {
231 Locker::Autolock _l(ctx->mDrawLock);
232 // Perform commit to unstage the pipes.
233 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
234 ALOGE("%s: display commit fail! for %d dpy",
235 __FUNCTION__, dpy);
236 }
237 }
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800238 return;
239}
240
241void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) {
242 {
243 Locker::Autolock _l(ctx->mDrawLock);
244 ctx->dpyAttr[dpy].isConfiguring = true;
245 ctx->dpyAttr[dpy].isActive = true;
246 ctx->proc->invalidate(ctx->proc);
247 }
248 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
249 * 2 / 1000);
250 //At this point external has all the pipes it would need.
251 {
252 Locker::Autolock _l(ctx->mDrawLock);
253 ctx->dpyAttr[dpy].isPause = false;
254 ctx->proc->invalidate(ctx->proc);
255 }
256 return;
257}
258
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800259/* Implementation for HWCVirtualV4L2 class */
260
261int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev,
262 hwc_display_contents_1_t *list) {
263 ATRACE_CALL();
264
265 hwc_context_t* ctx = (hwc_context_t*)(dev);
266 const int dpy = HWC_DISPLAY_VIRTUAL;
267
268 if (LIKELY(list && list->numHwLayers > 1) &&
269 ctx->dpyAttr[dpy].isActive &&
Raj Kamal52b4fdb2014-01-27 19:35:13 +0530270 ctx->dpyAttr[dpy].connected &&
271 canUseMDPforVirtualDisplay(ctx,list)) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530272 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800273 if(!ctx->dpyAttr[dpy].isPause) {
274 ctx->dpyAttr[dpy].isConfiguring = false;
275 setListStats(ctx, list, dpy);
276 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
277 const int fbZ = 0;
Saurabh Shahef19fe32014-04-22 15:31:58 -0700278 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
279 {
280 ctx->mOverlay->clear(dpy);
281 ctx->mLayerRotMap[dpy]->clear();
282 }
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800283 }
284 } else {
285 /* Virtual Display is in Pause state.
286 * Mark all application layers as OVERLAY so that
287 * GPU will not compose.
288 */
289 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
290 hwc_layer_1_t *layer = &list->hwLayers[i];
291 layer->compositionType = HWC_OVERLAY;
292 }
293 }
294 }
295 return 0;
296}
297
298int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
299 ATRACE_CALL();
300 int ret = 0;
301
302 const int dpy = HWC_DISPLAY_VIRTUAL;
303
304 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
305 ctx->dpyAttr[dpy].connected &&
Raj Kamal52b4fdb2014-01-27 19:35:13 +0530306 (!ctx->dpyAttr[dpy].isPause) &&
307 canUseMDPforVirtualDisplay(ctx,list)) {
Praveena Pachipulusud9443c72014-02-17 10:42:28 +0530308 uint32_t last = (uint32_t)list->numHwLayers - 1;
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800309 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
310 int fd = -1; //FenceFD from the Copybit(valid in async mode)
311 bool copybitDone = false;
312 if(ctx->mCopyBit[dpy])
313 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
314
315 if(list->numHwLayers > 1)
316 hwc_sync(ctx, list, dpy, fd);
317
318 // Dump the layers for virtual
319 if(ctx->mHwcDebug[dpy])
320 ctx->mHwcDebug[dpy]->dumpLayers(list);
321
322 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
323 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
324 ret = -1;
325 }
326
327 int extOnlyLayerIndex =
328 ctx->listStats[dpy].extOnlyLayerIndex;
329
330 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
331 if(extOnlyLayerIndex!= -1) {
332 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
333 hnd = (private_handle_t *)extLayer->handle;
334 } else if(copybitDone) {
335 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
336 }
337
338 if(hnd && !isYuvBuffer(hnd)) {
339 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
340 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
341 ret = -1;
342 }
343 }
344
345 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
346 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
347 ret = -1;
348 }
349 }
350
351 closeAcquireFds(list);
352
Baldev Sahuec852382014-02-14 08:36:00 +0530353 if (list && list->outbuf && (list->retireFenceFd < 0) ) {
Ramkumar Radhakrishnan8bb48d32013-12-30 23:11:27 -0800354 // SF assumes HWC waits for the acquire fence and returns a new fence
355 // that signals when we're done. Since we don't wait, and also don't
356 // touch the buffer, we can just handle the acquire fence back to SF
357 // as the retire fence.
358 list->retireFenceFd = list->outbufAcquireFenceFd;
359 }
360
361 return ret;
362}
Tatenda Chipeperekwa8f1b9d72014-02-11 16:20:50 -0800363
364void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
365 {
366 Locker::Autolock _l(ctx->mDrawLock);
367 ctx->dpyAttr[dpy].isActive = true;
368 ctx->dpyAttr[dpy].isPause = true;
369 ctx->proc->invalidate(ctx->proc);
370 }
371 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
372 * 2 / 1000);
373 // At this point all the pipes used by External have been
374 // marked as UNSET.
375 {
376 Locker::Autolock _l(ctx->mDrawLock);
377 // Perform commit to unstage the pipes.
378 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
379 ALOGE("%s: display commit fail! for %d dpy",
380 __FUNCTION__, dpy);
381 }
382 }
383 return;
384}
385
386void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
387 //Treat Resume as Online event
388 //Since external didnt have any pipes, force primary to give up
389 //its pipes; we don't allow inter-mixer pipe transfers.
390 {
391 Locker::Autolock _l(ctx->mDrawLock);
392
393 // A dynamic resolution change (DRC) can be made for a WiFi
394 // display. In order to support the resolution change, we
395 // need to reconfigure the corresponding display attributes.
396 // Since DRC is only on WiFi display, we only need to call
397 // configure() on the VirtualDisplay device.
398 //TODO: clean up
399 if(dpy == HWC_DISPLAY_VIRTUAL)
400 ctx->mVirtualDisplay->configure();
401
402 ctx->dpyAttr[dpy].isConfiguring = true;
403 ctx->dpyAttr[dpy].isActive = true;
404 ctx->proc->invalidate(ctx->proc);
405 }
406 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
407 * 2 / 1000);
408 //At this point external has all the pipes it would need.
409 {
410 Locker::Autolock _l(ctx->mDrawLock);
411 ctx->dpyAttr[dpy].isPause = false;
412 ctx->proc->invalidate(ctx->proc);
413 }
414 return;
415}