1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #undef LOG_TAG
18 #define LOG_TAG "virtualdisplay"
19 #include "ExynosVirtualDisplay.h"
20 #include "../libdevice/ExynosDevice.h"
21 #include "../libdevice/ExynosLayer.h"
22 
23 #include "ExynosHWCHelper.h"
24 #include "VendorGraphicBuffer.h"
25 
26 using vendor::graphics::BufferUsage;
27 using vendor::graphics::VendorGraphicBufferUsage;
28 
29 extern struct exynos_hwc_control exynosHWCControl;
30 
ExynosVirtualDisplay(uint32_t index,ExynosDevice * device)31 ExynosVirtualDisplay::ExynosVirtualDisplay(uint32_t index, ExynosDevice *device)
32     : ExynosDisplay(index, device)
33 {
34     /* Initialization */
35     mType = HWC_DISPLAY_VIRTUAL;
36     mIndex = index;
37     mDisplayId = getDisplayId(mType, mIndex);
38 
39     mDisplayControl.earlyStartMPP = false;
40 
41     mOutputBufferAcquireFenceFd = -1;
42     mOutputBufferReleaseFenceFd = -1;
43 
44     mIsWFDState = 0;
45     mIsSecureVDSState = false;
46     mIsSkipFrame = false;
47     mPresentationMode = false;
48 
49     // TODO : Hard coded currently
50     mNumMaxPriorityAllowed = 1;
51 
52     mDisplayWidth = 0;
53     mDisplayHeight = 0;
54     mOutputBuffer = NULL;
55     mCompositionType = COMPOSITION_GLES;
56     mGLESFormat = HAL_PIXEL_FORMAT_RGBA_8888;
57     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
58     mIsSecureDRM = false;
59     mIsNormalDRM = false;
60     mNeedReloadResourceForHWFC = false;
61     mMinTargetLuminance = 0;
62     mMaxTargetLuminance = 100;
63     mSinkDeviceType = 0;
64 
65     mUseDpu = false;
66     mDisplayControl.enableExynosCompositionOptimization = false;
67     mDisplayControl.enableClientCompositionOptimization = false;
68     mDisplayControl.handleLowFpsLayers = false;
69     mMaxWindowNum = 0;
70 }
71 
~ExynosVirtualDisplay()72 ExynosVirtualDisplay::~ExynosVirtualDisplay()
73 {
74 
75 }
76 
createVirtualDisplay(uint32_t width,uint32_t height,int32_t * format)77 void ExynosVirtualDisplay::createVirtualDisplay(uint32_t width, uint32_t height, int32_t* format)
78 {
79     ALOGI("Virtual display is added. width(%d), height(%d), format(%d)", width, height, *format);
80 
81     initDisplay();
82 
83     // Virtual Display don't use skip static layer.
84     mClientCompositionInfo.mEnableSkipStatic = false;
85 
86     mPlugState = true;
87     mDisplayWidth = width;
88     mDisplayHeight = height;
89     mXres = width;
90     mYres = height;
91     mGLESFormat = *format;
92 }
93 
destroyVirtualDisplay()94 void ExynosVirtualDisplay::destroyVirtualDisplay()
95 {
96     ALOGI("Virtual display is deleted");
97 
98     mPlugState = false;
99     mDisplayWidth = 0;
100     mDisplayHeight = 0;
101     mXres = 0;
102     mYres = 0;
103     mMinTargetLuminance = 0;
104     mMaxTargetLuminance = 100;
105     mSinkDeviceType = 0;
106     mCompositionType = COMPOSITION_GLES;
107     mGLESFormat = HAL_PIXEL_FORMAT_RGBA_8888;
108     mResourceManager->reloadResourceForHWFC();
109     mResourceManager->setTargetDisplayLuminance(mMinTargetLuminance, mMaxTargetLuminance);
110     mResourceManager->setTargetDisplayDevice(mSinkDeviceType);
111     mNeedReloadResourceForHWFC = false;
112 }
113 
setWFDMode(unsigned int mode)114 int ExynosVirtualDisplay::setWFDMode(unsigned int mode)
115 {
116     if ((mode == GOOGLEWFD_TO_LLWFD || mode == LLWFD_TO_GOOGLEWFD))
117         mNeedReloadResourceForHWFC = true;
118     mIsWFDState = mode;
119     return HWC2_ERROR_NONE;
120 }
121 
getWFDMode()122 int ExynosVirtualDisplay::getWFDMode()
123 {
124     return mIsWFDState;
125 }
126 
sendWFDCommand(int32_t cmd,int32_t ext1,int32_t ext2)127 int ExynosVirtualDisplay::sendWFDCommand(int32_t cmd, int32_t ext1, int32_t ext2)
128 {
129     ALOGI("sendWFDCommand: cmd(%d), ext1(%d), ext2(%d)", cmd, ext1, ext2);
130 
131     int ret = 0;
132 
133     switch (cmd) {
134         case SET_WFD_MODE:
135             /* ext1: mode, ext2: unused */
136             ret = setWFDMode(ext1);
137             break;
138         case SET_TARGET_DISPLAY_LUMINANCE:
139             /* ext1: min, ext2: max */
140             mMinTargetLuminance = (uint16_t)ext1;
141             mMaxTargetLuminance = (uint16_t)ext2;
142             mResourceManager->setTargetDisplayLuminance(mMinTargetLuminance, mMaxTargetLuminance);
143             break;
144         case SET_TARGET_DISPLAY_DEVICE:
145             /* ext1: type, ext2: unused */
146             mSinkDeviceType = ext1;
147             mResourceManager->setTargetDisplayDevice(mSinkDeviceType);
148             break;
149         default:
150             ALOGE("invalid cmd(%d)", cmd);
151             break;
152     }
153 
154     return ret;
155 }
156 
setSecureVDSMode(unsigned int mode)157 int ExynosVirtualDisplay::setSecureVDSMode(unsigned int mode)
158 {
159     mIsWFDState = mode;
160     mIsSecureVDSState = !!mode;
161     return HWC2_ERROR_NONE;
162 }
163 
setWFDOutputResolution(unsigned int width,unsigned int height)164 int ExynosVirtualDisplay::setWFDOutputResolution(
165     unsigned int width, unsigned int height)
166 {
167     mDisplayWidth = width;
168     mDisplayHeight = height;
169     mXres = width;
170     mYres = height;
171     return HWC2_ERROR_NONE;
172 }
173 
getWFDOutputResolution(unsigned int * width,unsigned int * height)174 void ExynosVirtualDisplay::getWFDOutputResolution(
175     unsigned int *width, unsigned int *height)
176 {
177     *width = mDisplayWidth;
178     *height = mDisplayHeight;
179 }
180 
setPresentationMode(bool use)181 void ExynosVirtualDisplay::setPresentationMode(bool use)
182 {
183     mPresentationMode = use;
184 }
185 
getPresentationMode(void)186 int ExynosVirtualDisplay::getPresentationMode(void)
187 {
188     return mPresentationMode;
189 }
190 
setVDSGlesFormat(int format)191 int ExynosVirtualDisplay::setVDSGlesFormat(int format)
192 {
193     DISPLAY_LOGD(eDebugVirtualDisplay, "setVDSGlesFormat: 0x%x", format);
194     mGLESFormat = format;
195     return HWC2_ERROR_NONE;
196 }
197 
setOutputBuffer(buffer_handle_t buffer,int32_t releaseFence)198 int32_t ExynosVirtualDisplay::setOutputBuffer(
199     buffer_handle_t buffer, int32_t releaseFence) {
200     mOutputBuffer = buffer;
201     mOutputBufferAcquireFenceFd = hwc_dup(releaseFence,
202             this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
203     releaseFence = fence_close(releaseFence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
204 
205     if (mExynosCompositionInfo.mM2mMPP != NULL) {
206         mExynosCompositionInfo.mM2mMPP->setOutBuf(mOutputBuffer, mOutputBufferAcquireFenceFd);
207         mOutputBufferAcquireFenceFd = -1;
208     }
209 
210     DISPLAY_LOGD(eDebugVirtualDisplay, "setOutputBuffer(), mOutputBufferAcquireFenceFd %d", mOutputBufferAcquireFenceFd);
211     return HWC2_ERROR_NONE;
212 }
213 
clearDisplay(bool needModeClear)214 int ExynosVirtualDisplay::clearDisplay(bool needModeClear) {
215     return 0;
216 }
217 
validateDisplay(uint32_t * outNumTypes,uint32_t * outNumRequests)218 int32_t ExynosVirtualDisplay::validateDisplay(
219     uint32_t* outNumTypes, uint32_t* outNumRequests)
220 {
221     DISPLAY_LOGD(eDebugVirtualDisplay, "validateDisplay");
222     int32_t ret = HWC2_ERROR_NONE;
223 
224     initPerFrameData();
225 
226     mClientCompositionInfo.setCompressed(false);
227 
228     if (mNeedReloadResourceForHWFC) {
229         ALOGI("validateDisplay() mIsWFDState %d", mIsWFDState);
230         mResourceManager->reloadResourceForHWFC();
231         mResourceManager->setTargetDisplayLuminance(mMinTargetLuminance, mMaxTargetLuminance);
232         mResourceManager->setTargetDisplayDevice(mSinkDeviceType);
233         mNeedReloadResourceForHWFC = false;
234     }
235 
236     /* validateDisplay should be called for preAssignResource */
237     ret = ExynosDisplay::validateDisplay(outNumTypes, outNumRequests);
238 
239     if (checkSkipFrame()) {
240         handleSkipFrame();
241     } else {
242         setDrmMode();
243         setSinkBufferUsage();
244         setCompositionType();
245     }
246 
247     return ret;
248 }
249 
canSkipValidate()250 int32_t ExynosVirtualDisplay::canSkipValidate() {
251 #if 1   // disable the skipValidate features when virtual display is added
252     return SKIP_ERR_FORCE_VALIDATE;
253 #else
254     if (checkSkipFrame())
255         return SKIP_ERR_FORCE_VALIDATE;
256 
257     return ExynosDisplay::canSkipValidate();
258 #endif
259 }
260 
presentDisplay(int32_t * outRetireFence)261 int32_t ExynosVirtualDisplay::presentDisplay(
262     int32_t* outRetireFence)
263 {
264     DISPLAY_LOGD(eDebugVirtualDisplay, "presentDisplay, mCompositionType %d",
265         mCompositionType);
266 
267     int32_t ret = HWC2_ERROR_NONE;
268 
269     if (mIsSkipFrame) {
270         if ((exynosHWCControl.skipValidate == true) &&
271             ((mRenderingState == RENDERING_STATE_PRESENTED) ||
272              (mRenderingState == RENDERING_STATE_NONE))) {
273 
274             if (mDevice->canSkipValidate() == false) {
275                 mRenderingState = RENDERING_STATE_NONE;
276                 return HWC2_ERROR_NOT_VALIDATED;
277             } else {
278                 DISPLAY_LOGD(eDebugSkipValidate, "validate is skipped");
279             }
280         }
281 
282         handleAcquireFence();
283         /* this frame is not presented, but mRenderingState is updated to RENDERING_STATE_PRESENTED */
284         mRenderingState = RENDERING_STATE_PRESENTED;
285 
286         /*
287          * Resource assignment information was initialized during skipping frames
288          * So resource assignment for the first displayed frame after skpping frames
289          * should not be skipped
290          */
291         setGeometryChanged(GEOMETRY_DISPLAY_FORCE_VALIDATE);
292 
293         return ret;
294     }
295 
296     ret = ExynosDisplay::presentDisplay(outRetireFence);
297 
298     /* handle outbuf acquireFence */
299     mOutputBufferAcquireFenceFd = fence_close(mOutputBufferAcquireFenceFd, this,
300             FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D);
301 
302     if (*outRetireFence == -1 && mOutputBufferReleaseFenceFd >= 0) {
303         *outRetireFence = mOutputBufferReleaseFenceFd;
304         mOutputBufferReleaseFenceFd = -1;
305     }
306 
307     DISPLAY_LOGD(eDebugVirtualDisplay, "presentDisplay(), outRetireFence %d", *outRetireFence);
308 
309     return ret;
310 }
311 
setWinConfigData()312 int ExynosVirtualDisplay::setWinConfigData()
313 {
314     return NO_ERROR;
315 }
316 
setDisplayWinConfigData()317 int ExynosVirtualDisplay::setDisplayWinConfigData()
318 {
319     return NO_ERROR;
320 }
321 
validateWinConfigData()322 int32_t ExynosVirtualDisplay::validateWinConfigData()
323 {
324     return NO_ERROR;
325 }
326 
deliverWinConfigData()327 int ExynosVirtualDisplay::deliverWinConfigData()
328 {
329     mDpuData.retire_fence = -1;
330     return 0;
331 }
332 
setReleaseFences()333 int ExynosVirtualDisplay::setReleaseFences()
334 {
335     DISPLAY_LOGD(eDebugVirtualDisplay, "setReleaseFences(), mCompositionType %d", mCompositionType);
336 
337     int ret = 0;
338 
339     if (mClientCompositionInfo.mHasCompositionLayer) {
340         int fence;
341         uint32_t framebufferTargetIndex;
342         framebufferTargetIndex = mExynosCompositionInfo.mM2mMPP->getAssignedSourceNum() - 1;
343         fence = mExynosCompositionInfo.mM2mMPP->getSrcReleaseFence(framebufferTargetIndex);
344         if (fence > 0)
345             fence_close(fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
346     }
347 
348     ret = ExynosDisplay::setReleaseFences();
349 
350     mOutputBufferReleaseFenceFd = hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, mExynosCompositionInfo.mAcquireFence);
351     setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, FENCE_TO);
352     mExynosCompositionInfo.mAcquireFence = -1;
353     /* mClientCompositionInfo.mAcquireFence is delivered to G2D */
354     mClientCompositionInfo.mAcquireFence = -1;
355 
356     return ret;
357 }
358 
checkFrameValidation()359 bool ExynosVirtualDisplay::checkFrameValidation()
360 {
361     if (mOutputBuffer == NULL) {
362         handleAcquireFence();
363         return false;
364     }
365 
366     buffer_handle_t outbufHandle = mOutputBuffer;
367     if (outbufHandle == NULL) {
368         handleAcquireFence();
369         return false;
370     }
371 
372     if (mCompositionType != COMPOSITION_HWC) {
373         if (mClientCompositionInfo.mTargetBuffer == NULL) {
374             handleAcquireFence();
375             return false;
376         }
377     }
378 
379     return true;
380 
381 }
382 
setSinkBufferUsage()383 void ExynosVirtualDisplay::setSinkBufferUsage()
384 {
385     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
386     if (mIsSecureDRM) {
387         mSinkUsage |= BufferUsage::CPU_READ_NEVER |
388             BufferUsage::CPU_WRITE_NEVER |
389             BufferUsage::PROTECTED;
390     } else if (mIsNormalDRM)
391         mSinkUsage |= VendorGraphicBufferUsage::PRIVATE_NONSECURE;
392 }
393 
setCompositionType()394 void ExynosVirtualDisplay::setCompositionType()
395 {
396     size_t compositionClientLayerCount = 0;
397     size_t CompositionDeviceLayerCount = 0;;
398     for (size_t i = 0; i < mLayers.size(); i++) {
399         ExynosLayer *layer = mLayers[i];
400         if (layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT ||
401             layer->mValidateCompositionType == HWC2_COMPOSITION_INVALID) {
402             compositionClientLayerCount++;
403         }
404         if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
405             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
406             CompositionDeviceLayerCount++;
407         }
408     }
409     if (compositionClientLayerCount > 0 && CompositionDeviceLayerCount > 0) {
410         mCompositionType = COMPOSITION_MIXED;
411     } else if (CompositionDeviceLayerCount > 0) {
412         mCompositionType = COMPOSITION_HWC;
413     } else {
414         mCompositionType = COMPOSITION_GLES;
415     }
416 
417     if (mCompositionType == COMPOSITION_GLES)
418         mCompositionType = COMPOSITION_MIXED;
419 
420     DISPLAY_LOGD(eDebugVirtualDisplay, "setCompositionType(), compositionClientLayerCount %zu, CompositionDeviceLayerCount %zu, mCompositionType %d",
421         compositionClientLayerCount, CompositionDeviceLayerCount, mCompositionType);
422 }
423 
initPerFrameData()424 void ExynosVirtualDisplay::initPerFrameData()
425 {
426     mIsSkipFrame = false;
427     mIsSecureDRM = false;
428     mIsNormalDRM = false;
429     mCompositionType = COMPOSITION_HWC;
430     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
431 }
432 
checkSkipFrame()433 bool ExynosVirtualDisplay::checkSkipFrame()
434 {
435     // FIXME: HWC2_COMPOSITION_SCREENSHOT is not dfeind in AOSP
436     //        HWC guys should fix this.
437 #if 0
438     for (size_t i = 0; i < mLayers.size(); i++) {
439         ExynosLayer *layer = mLayers[i];
440         if (layer->mCompositionType == HWC2_COMPOSITION_SCREENSHOT) {
441             DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), skip rotation animation layer");
442             return true;
443         }
444     }
445 #endif
446 
447     if (mLayers.size() == 0) {
448         DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), mLayers.size() %zu", mLayers.size());
449         return true;
450     }
451 
452     if (mIsWFDState == 0) {
453         DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), mIsWFDState %d", mIsWFDState);
454         return true;
455     }
456 
457     if (mIsWFDState == GOOGLEWFD_TO_LLWFD || mIsWFDState == LLWFD_TO_GOOGLEWFD) {
458         DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), mIsWFDState %d", mIsWFDState);
459         return true;
460     }
461 
462     return false;
463 }
464 
setDrmMode()465 void ExynosVirtualDisplay::setDrmMode()
466 {
467     mIsSecureDRM = false;
468     for (size_t i = 0; i < mLayers.size(); i++) {
469         ExynosLayer *layer = mLayers[i];
470         if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
471             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) &&
472             layer->mLayerBuffer && getDrmMode(layer->mLayerBuffer) == SECURE_DRM) {
473             mIsSecureDRM = true;
474             DISPLAY_LOGD(eDebugVirtualDisplay, "include secure drm layer");
475         }
476         if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
477             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) &&
478             layer->mLayerBuffer && getDrmMode(layer->mLayerBuffer) == NORMAL_DRM) {
479             mIsNormalDRM = true;
480             DISPLAY_LOGD(eDebugVirtualDisplay, "include normal drm layer");
481         }
482     }
483     DISPLAY_LOGD(eDebugVirtualDisplay, "setDrmMode(), mIsSecureDRM %d", mIsSecureDRM);
484 }
485 
handleSkipFrame()486 void ExynosVirtualDisplay::handleSkipFrame()
487 {
488     mIsSkipFrame = true;
489     for (size_t i = 0; i < mLayers.size(); i++) {
490         ExynosLayer *layer = mLayers[i];
491         layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
492     }
493     mIsSecureDRM = false;
494     mIsNormalDRM = false;
495     mCompositionType = COMPOSITION_HWC;
496     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
497     DISPLAY_LOGD(eDebugVirtualDisplay, "handleSkipFrame()");
498 }
499 
handleAcquireFence()500 void ExynosVirtualDisplay::handleAcquireFence()
501 {
502     /* handle fence of DEVICE or EXYNOS composition layers */
503     for (size_t i = 0; i < mLayers.size(); i++) {
504         ExynosLayer *layer = mLayers[i];
505         if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
506             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
507             layer->mReleaseFence = layer->mAcquireFence;
508             setFenceInfo(layer->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_TO);
509             layer->mAcquireFence = -1;
510         }
511     }
512     mClientCompositionInfo.mReleaseFence = mClientCompositionInfo.mAcquireFence;
513     setFenceInfo(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, FENCE_TO);
514     mClientCompositionInfo.mAcquireFence = -1;
515 
516     mOutputBufferReleaseFenceFd = mOutputBufferAcquireFenceFd;
517     mOutputBufferAcquireFenceFd = -1;
518     DISPLAY_LOGD(eDebugVirtualDisplay, "handleAcquireFence()");
519 }
520 
getHdrCapabilities(uint32_t * outNumTypes,int32_t * outTypes,float * outMaxLuminance,float * outMaxAverageLuminance,float * outMinLuminance)521 int32_t ExynosVirtualDisplay::getHdrCapabilities(uint32_t* outNumTypes,
522         int32_t* outTypes, float* outMaxLuminance,
523         float* outMaxAverageLuminance, float* outMinLuminance)
524 {
525     if (outTypes == NULL) {
526         *outNumTypes = 1;
527         return 0;
528     }
529     outTypes[0] = HAL_HDR_HDR10;
530     return 0;
531 }
532