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
35 using namespace qhwc;
36 using namespace overlay;
37
getObject(bool isVDSEnabled)38 HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
39
40 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();
48 }
49 }
50
init(hwc_context_t * ctx)51 void 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
destroy(hwc_context_t * ctx,size_t,hwc_display_contents_1_t ** displays)63 void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
64 hwc_display_contents_1_t** displays) {
65 int dpy = HWC_DISPLAY_VIRTUAL;
66
67 //Cleanup virtual display objs, since there is no explicit disconnect
68 if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
69 ctx->dpyAttr[dpy].connected = false;
70 ctx->dpyAttr[dpy].isPause = false;
71
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 }
80 // 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 }
85 ctx->mWfdSyncLock.lock();
86 ctx->mWfdSyncLock.signal();
87 ctx->mWfdSyncLock.unlock();
88 }
89 }
90
prepare(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)91 int 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
98 if (list && list->outbuf && list->numHwLayers > 0) {
99 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
100 uint32_t last = (uint32_t)list->numHwLayers - 1;
101 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;
109 ctx->dpyAttr[dpy].isPause = false;
110 // 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;
114 init(ctx);
115 // Do a padding round so that primary can free up a pipe for virtual
116 // The virtual composition falls back to GPU for this frame
117 ctx->isPaddingRound = true;
118 }
119 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);
126
127 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
128 const int fbZ = 0;
129 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
130 {
131 ctx->mOverlay->clear(dpy);
132 ctx->mLayerRotMap[dpy]->clear();
133 }
134 }
135 } else {
136 /* Virtual Display is in Pause state.
137 * Mark all application layers as OVERLAY so that
138 * GPU will not compose.
139 */
140 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
141 hwc_layer_1_t *layer = &list->hwLayers[i];
142 layer->compositionType = HWC_OVERLAY;
143 }
144 }
145 }
146 return 0;
147 }
148
set(hwc_context_t * ctx,hwc_display_contents_1_t * list)149 int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
150 ATRACE_CALL();
151 int ret = 0;
152 const int dpy = HWC_DISPLAY_VIRTUAL;
153
154 if (list && list->outbuf && list->numHwLayers > 0) {
155 uint32_t last = (uint32_t)list->numHwLayers - 1;
156 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
157
158 if(ctx->dpyAttr[dpy].connected
159 && (!ctx->dpyAttr[dpy].isPause))
160 {
161 private_handle_t *ohnd = (private_handle_t *)list->outbuf;
162 int format = ohnd->format;
163 if (format == HAL_PIXEL_FORMAT_RGBA_8888)
164 format = HAL_PIXEL_FORMAT_RGBX_8888;
165 Writeback::getInstance()->setOutputFormat(
166 utils::getMdpFormat(format));
167
168 // Configure WB as secure if the output buffer handle is secure.
169 if(isSecureBuffer(ohnd)){
170 if(! Writeback::getInstance()->setSecure(true))
171 {
172 ALOGE("Failed to set WB as secure for virtual display");
173 return false;
174 }
175 }
176
177 int fd = -1; //FenceFD from the Copybit
178 hwc_sync(ctx, list, dpy, fd);
179
180 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
181 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
182 ret = -1;
183 }
184 // We need an FB layer handle check to cater for this usecase:
185 // Video is playing in landscape on primary, then launch
186 // ScreenRecord app.
187 // In this scenario, the first VDS draw call will have HWC
188 // composition and VDS does nit involve GPU to get eglSwapBuffer
189 // to get valid fb handle.
190 if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
191 (private_handle_t *)fbLayer->handle)) {
192 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
193 ret = -1;
194 }
195
196 Writeback::getInstance()->queueBuffer(ohnd->fd,
197 (uint32_t)ohnd->offset);
198 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
199 ALOGE("%s: display commit fail!", __FUNCTION__);
200 ret = -1;
201 }
202
203 } else if(list->outbufAcquireFenceFd >= 0) {
204 //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
205 //which will make sure, the framework waits on it and closes it.
206 //The other way is to wait on outbufFenceFd ourselves, close it and
207 //set retireFenceFd to -1. Since we want hwc to be async, choosing
208 //the former.
209 //Also dup because, the closeAcquireFds() will close the outbufFence
210 list->retireFenceFd = dup(list->outbufAcquireFenceFd);
211 }
212 }
213
214 closeAcquireFds(list);
215 return ret;
216 }
217
pause(hwc_context_t * ctx,int dpy)218 void HWCVirtualVDS::pause(hwc_context_t* ctx, int dpy) {
219 {
220 Locker::Autolock _l(ctx->mDrawLock);
221 ctx->dpyAttr[dpy].isActive = true;
222 ctx->dpyAttr[dpy].isPause = true;
223 ctx->proc->invalidate(ctx->proc);
224 }
225 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
226 * 2 / 1000);
227 return;
228 }
229
resume(hwc_context_t * ctx,int dpy)230 void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) {
231 {
232 Locker::Autolock _l(ctx->mDrawLock);
233 ctx->dpyAttr[dpy].isConfiguring = true;
234 ctx->dpyAttr[dpy].isActive = true;
235 ctx->proc->invalidate(ctx->proc);
236 }
237 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
238 * 2 / 1000);
239 //At this point external has all the pipes it would need.
240 {
241 Locker::Autolock _l(ctx->mDrawLock);
242 ctx->dpyAttr[dpy].isPause = false;
243 ctx->proc->invalidate(ctx->proc);
244 }
245 return;
246 }
247
248 /* Implementation for HWCVirtualV4L2 class */
249
prepare(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)250 int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev,
251 hwc_display_contents_1_t *list) {
252 ATRACE_CALL();
253
254 hwc_context_t* ctx = (hwc_context_t*)(dev);
255 const int dpy = HWC_DISPLAY_VIRTUAL;
256
257 if (LIKELY(list && list->numHwLayers > 1) &&
258 ctx->dpyAttr[dpy].isActive &&
259 ctx->dpyAttr[dpy].connected &&
260 canUseMDPforVirtualDisplay(ctx,list)) {
261 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
262 if(!ctx->dpyAttr[dpy].isPause) {
263 ctx->dpyAttr[dpy].isConfiguring = false;
264 setListStats(ctx, list, dpy);
265 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
266 const int fbZ = 0;
267 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
268 {
269 ctx->mOverlay->clear(dpy);
270 ctx->mLayerRotMap[dpy]->clear();
271 }
272 }
273 } else {
274 /* Virtual Display is in Pause state.
275 * Mark all application layers as OVERLAY so that
276 * GPU will not compose.
277 */
278 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
279 hwc_layer_1_t *layer = &list->hwLayers[i];
280 layer->compositionType = HWC_OVERLAY;
281 }
282 }
283 }
284 return 0;
285 }
286
set(hwc_context_t * ctx,hwc_display_contents_1_t * list)287 int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
288 ATRACE_CALL();
289 int ret = 0;
290
291 const int dpy = HWC_DISPLAY_VIRTUAL;
292
293 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
294 ctx->dpyAttr[dpy].connected &&
295 (!ctx->dpyAttr[dpy].isPause) &&
296 canUseMDPforVirtualDisplay(ctx,list)) {
297 uint32_t last = (uint32_t)list->numHwLayers - 1;
298 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
299 int fd = -1; //FenceFD from the Copybit(valid in async mode)
300 bool copybitDone = false;
301 if(ctx->mCopyBit[dpy])
302 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
303
304 if(list->numHwLayers > 1)
305 hwc_sync(ctx, list, dpy, fd);
306
307 // Dump the layers for virtual
308 if(ctx->mHwcDebug[dpy])
309 ctx->mHwcDebug[dpy]->dumpLayers(list);
310
311 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
312 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
313 ret = -1;
314 }
315
316 int extOnlyLayerIndex =
317 ctx->listStats[dpy].extOnlyLayerIndex;
318
319 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
320 if(extOnlyLayerIndex!= -1) {
321 hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
322 hnd = (private_handle_t *)extLayer->handle;
323 } else if(copybitDone) {
324 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
325 }
326
327 if(hnd && !isYuvBuffer(hnd)) {
328 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
329 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
330 ret = -1;
331 }
332 }
333
334 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
335 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
336 ret = -1;
337 }
338 }
339
340 closeAcquireFds(list);
341
342 if (list && list->outbuf && (list->retireFenceFd < 0) ) {
343 // SF assumes HWC waits for the acquire fence and returns a new fence
344 // that signals when we're done. Since we don't wait, and also don't
345 // touch the buffer, we can just handle the acquire fence back to SF
346 // as the retire fence.
347 list->retireFenceFd = list->outbufAcquireFenceFd;
348 }
349
350 return ret;
351 }
352
pause(hwc_context_t * ctx,int dpy)353 void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
354 {
355 Locker::Autolock _l(ctx->mDrawLock);
356 ctx->dpyAttr[dpy].isActive = true;
357 ctx->dpyAttr[dpy].isPause = true;
358 ctx->proc->invalidate(ctx->proc);
359 }
360 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
361 * 2 / 1000);
362 // At this point all the pipes used by External have been
363 // marked as UNSET.
364 {
365 Locker::Autolock _l(ctx->mDrawLock);
366 // Perform commit to unstage the pipes.
367 if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
368 ALOGE("%s: display commit fail! for %d dpy",
369 __FUNCTION__, dpy);
370 }
371 }
372 return;
373 }
374
resume(hwc_context_t * ctx,int dpy)375 void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
376 //Treat Resume as Online event
377 //Since external didnt have any pipes, force primary to give up
378 //its pipes; we don't allow inter-mixer pipe transfers.
379 {
380 Locker::Autolock _l(ctx->mDrawLock);
381
382 // A dynamic resolution change (DRC) can be made for a WiFi
383 // display. In order to support the resolution change, we
384 // need to reconfigure the corresponding display attributes.
385 // Since DRC is only on WiFi display, we only need to call
386 // configure() on the VirtualDisplay device.
387 //TODO: clean up
388 if(dpy == HWC_DISPLAY_VIRTUAL)
389 ctx->mVirtualDisplay->configure();
390
391 ctx->dpyAttr[dpy].isConfiguring = true;
392 ctx->dpyAttr[dpy].isActive = true;
393 ctx->proc->invalidate(ctx->proc);
394 }
395 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
396 * 2 / 1000);
397 //At this point external has all the pipes it would need.
398 {
399 Locker::Autolock _l(ctx->mDrawLock);
400 ctx->dpyAttr[dpy].isPause = false;
401 ctx->proc->invalidate(ctx->proc);
402 }
403 return;
404 }
405