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 #include "sync/sync.h"
33 
34 #define HWCVIRTUAL_LOG 0
35 
36 using namespace qhwc;
37 using namespace overlay;
38 
getObject(bool isVDSEnabled)39 HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
40 
41     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();
49     }
50 }
51 
HWCVirtualVDS()52 HWCVirtualVDS::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 
init(hwc_context_t * ctx)62 void 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 
destroy(hwc_context_t * ctx,size_t,hwc_display_contents_1_t ** displays)74 void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
75                        hwc_display_contents_1_t** displays) {
76     int dpy = HWC_DISPLAY_VIRTUAL;
77 
78     //Cleanup virtual display objs, since there is no explicit disconnect
79     if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
80         ctx->dpyAttr[dpy].connected = false;
81         ctx->dpyAttr[dpy].isPause = false;
82 
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         }
91         // 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         }
96         ctx->mWfdSyncLock.lock();
97         ctx->mWfdSyncLock.signal();
98         ctx->mWfdSyncLock.unlock();
99     }
100 }
101 
prepare(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)102 int 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 
109     if (list && list->outbuf && list->numHwLayers > 0) {
110         reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
111         uint32_t last = (uint32_t)list->numHwLayers - 1;
112         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;
120             ctx->dpyAttr[dpy].isPause = false;
121             // 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;
125             init(ctx);
126             // 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.
129         }
130         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);
137 
138             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
139                 const int fbZ = 0;
140                 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
141                 {
142                     ctx->mOverlay->clear(dpy);
143                     ctx->mLayerRotMap[dpy]->clear();
144                 }
145             }
146         } else {
147             /* Virtual Display is in Pause state.
148              * Mark all application layers as OVERLAY so that
149              * GPU will not compose.
150              */
151             Writeback::getInstance(); //Ensure that WB is active during pause
152             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             }
156         }
157     }
158     return 0;
159 }
160 
set(hwc_context_t * ctx,hwc_display_contents_1_t * list)161 int 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 
166     if (list && list->outbuf && list->numHwLayers > 0) {
167         uint32_t last = (uint32_t)list->numHwLayers - 1;
168         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
169 
170         if(ctx->dpyAttr[dpy].connected
171                 && (!ctx->dpyAttr[dpy].isPause))
172         {
173             private_handle_t *ohnd = (private_handle_t *)list->outbuf;
174             int format = ohnd->format;
175             if (format == HAL_PIXEL_FORMAT_RGBA_8888)
176                 format = HAL_PIXEL_FORMAT_RGBX_8888;
177             Writeback::getInstance()->setOutputFormat(
178                                     utils::getMdpFormat(format));
179 
180             // 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 
189             int fd = -1; //FenceFD from the Copybit
190             hwc_sync(ctx, list, dpy, fd);
191 
192             // Dump the layers for virtual
193             if(ctx->mHwcDebug[dpy])
194                 ctx->mHwcDebug[dpy]->dumpLayers(list);
195 
196             if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
197                 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
198                 ret = -1;
199             }
200             // 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,
207                         (private_handle_t *)fbLayer->handle)) {
208                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
209                 ret = -1;
210             }
211 
212             Writeback::getInstance()->queueBuffer(ohnd->fd,
213                                         (uint32_t)ohnd->offset);
214             if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
215                 ALOGE("%s: display commit fail!", __FUNCTION__);
216                 ret = -1;
217             }
218 
219             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             }
232         } 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 
pause(hwc_context_t * ctx,int dpy)247 void 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);
256     // 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         }
265         ctx->proc->invalidate(ctx->proc);
266     }
267     return;
268 }
269 
resume(hwc_context_t * ctx,int dpy)270 void 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 
288 /* Implementation for HWCVirtualV4L2 class */
289 
prepare(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)290 int 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 &&
299             ctx->dpyAttr[dpy].connected) {
300         reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
301         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;
306                 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
307                 {
308                     ctx->mOverlay->clear(dpy);
309                     ctx->mLayerRotMap[dpy]->clear();
310                 }
311             }
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 
set(hwc_context_t * ctx,hwc_display_contents_1_t * list)326 int 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 &&
334             !ctx->dpyAttr[dpy].isPause) {
335         uint32_t last = (uint32_t)list->numHwLayers - 1;
336         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 
354         int extOnlyLayerIndex =
355             ctx->listStats[dpy].extOnlyLayerIndex;
356 
357         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
358         if(extOnlyLayerIndex!= -1) {
359             hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
360             hnd = (private_handle_t *)extLayer->handle;
361         } else if(copybitDone) {
362             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
363         }
364 
365         if(hnd && !isYuvBuffer(hnd)) {
366             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
367                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
368                 ret = -1;
369             }
370         }
371 
372         if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
373             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
374             ret = -1;
375         }
376     }
377 
378     closeAcquireFds(list);
379 
380     if (list && list->outbuf && (list->retireFenceFd < 0) ) {
381         // SF assumes HWC waits for the acquire fence and returns a new fence
382         // that signals when we're done. Since we don't wait, and also don't
383         // touch the buffer, we can just handle the acquire fence back to SF
384         // as the retire fence.
385         list->retireFenceFd = list->outbufAcquireFenceFd;
386     }
387 
388     return ret;
389 }
390 
pause(hwc_context_t * ctx,int dpy)391 void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
392     {
393         Locker::Autolock _l(ctx->mDrawLock);
394         ctx->dpyAttr[dpy].isActive = true;
395         ctx->dpyAttr[dpy].isPause = true;
396         ctx->proc->invalidate(ctx->proc);
397     }
398     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
399             * 2 / 1000);
400     // At this point all the pipes used by External have been
401     // marked as UNSET.
402     {
403         Locker::Autolock _l(ctx->mDrawLock);
404         // Perform commit to unstage the pipes.
405         if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
406             ALOGE("%s: display commit fail! for %d dpy",
407                     __FUNCTION__, dpy);
408         }
409     }
410     return;
411 }
412 
resume(hwc_context_t * ctx,int dpy)413 void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
414     //Treat Resume as Online event
415     //Since external didnt have any pipes, force primary to give up
416     //its pipes; we don't allow inter-mixer pipe transfers.
417     {
418         Locker::Autolock _l(ctx->mDrawLock);
419 
420         // A dynamic resolution change (DRC) can be made for a WiFi
421         // display. In order to support the resolution change, we
422         // need to reconfigure the corresponding display attributes.
423         // Since DRC is only on WiFi display, we only need to call
424         // configure() on the VirtualDisplay device.
425         //TODO: clean up
426         if(dpy == HWC_DISPLAY_VIRTUAL)
427             ctx->mVirtualDisplay->configure();
428 
429         ctx->dpyAttr[dpy].isConfiguring = true;
430         ctx->dpyAttr[dpy].isActive = true;
431         ctx->proc->invalidate(ctx->proc);
432     }
433     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
434             * 2 / 1000);
435     //At this point external has all the pipes it would need.
436     {
437         Locker::Autolock _l(ctx->mDrawLock);
438         ctx->dpyAttr[dpy].isPause = false;
439         ctx->proc->invalidate(ctx->proc);
440     }
441     return;
442 }
443