• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,
352                  HwcFenceDirection::TO);
353     mExynosCompositionInfo.mAcquireFence = -1;
354     /* mClientCompositionInfo.mAcquireFence is delivered to G2D */
355     mClientCompositionInfo.mAcquireFence = -1;
356 
357     return ret;
358 }
359 
checkFrameValidation()360 bool ExynosVirtualDisplay::checkFrameValidation()
361 {
362     if (mOutputBuffer == NULL) {
363         handleAcquireFence();
364         return false;
365     }
366 
367     buffer_handle_t outbufHandle = mOutputBuffer;
368     if (outbufHandle == NULL) {
369         handleAcquireFence();
370         return false;
371     }
372 
373     if (mCompositionType != COMPOSITION_HWC) {
374         if (mClientCompositionInfo.mTargetBuffer == NULL) {
375             handleAcquireFence();
376             return false;
377         }
378     }
379 
380     return true;
381 
382 }
383 
setSinkBufferUsage()384 void ExynosVirtualDisplay::setSinkBufferUsage()
385 {
386     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
387     if (mIsSecureDRM) {
388         mSinkUsage |= BufferUsage::CPU_READ_NEVER |
389             BufferUsage::CPU_WRITE_NEVER |
390             BufferUsage::PROTECTED;
391     } else if (mIsNormalDRM)
392         mSinkUsage |= VendorGraphicBufferUsage::PRIVATE_NONSECURE;
393 }
394 
setCompositionType()395 void ExynosVirtualDisplay::setCompositionType()
396 {
397     size_t compositionClientLayerCount = 0;
398     size_t CompositionDeviceLayerCount = 0;;
399     for (size_t i = 0; i < mLayers.size(); i++) {
400         ExynosLayer *layer = mLayers[i];
401         if (layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT ||
402             layer->mValidateCompositionType == HWC2_COMPOSITION_INVALID) {
403             compositionClientLayerCount++;
404         }
405         if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
406             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
407             CompositionDeviceLayerCount++;
408         }
409     }
410     if (compositionClientLayerCount > 0 && CompositionDeviceLayerCount > 0) {
411         mCompositionType = COMPOSITION_MIXED;
412     } else if (CompositionDeviceLayerCount > 0) {
413         mCompositionType = COMPOSITION_HWC;
414     } else {
415         mCompositionType = COMPOSITION_GLES;
416     }
417 
418     if (mCompositionType == COMPOSITION_GLES)
419         mCompositionType = COMPOSITION_MIXED;
420 
421     DISPLAY_LOGD(eDebugVirtualDisplay, "setCompositionType(), compositionClientLayerCount %zu, CompositionDeviceLayerCount %zu, mCompositionType %d",
422         compositionClientLayerCount, CompositionDeviceLayerCount, mCompositionType);
423 }
424 
initPerFrameData()425 void ExynosVirtualDisplay::initPerFrameData()
426 {
427     mIsSkipFrame = false;
428     mIsSecureDRM = false;
429     mIsNormalDRM = false;
430     mCompositionType = COMPOSITION_HWC;
431     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
432 }
433 
checkSkipFrame()434 bool ExynosVirtualDisplay::checkSkipFrame()
435 {
436     // FIXME: HWC2_COMPOSITION_SCREENSHOT is not dfeind in AOSP
437     //        HWC guys should fix this.
438 #if 0
439     for (size_t i = 0; i < mLayers.size(); i++) {
440         ExynosLayer *layer = mLayers[i];
441         if (layer->mCompositionType == HWC2_COMPOSITION_SCREENSHOT) {
442             DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), skip rotation animation layer");
443             return true;
444         }
445     }
446 #endif
447 
448     if (mLayers.size() == 0) {
449         DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), mLayers.size() %zu", mLayers.size());
450         return true;
451     }
452 
453     if (mIsWFDState == 0) {
454         DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), mIsWFDState %d", mIsWFDState);
455         return true;
456     }
457 
458     if (mIsWFDState == GOOGLEWFD_TO_LLWFD || mIsWFDState == LLWFD_TO_GOOGLEWFD) {
459         DISPLAY_LOGD(eDebugVirtualDisplay, "checkSkipFrame(), mIsWFDState %d", mIsWFDState);
460         return true;
461     }
462 
463     return false;
464 }
465 
setDrmMode()466 void ExynosVirtualDisplay::setDrmMode()
467 {
468     mIsSecureDRM = false;
469     for (size_t i = 0; i < mLayers.size(); i++) {
470         ExynosLayer *layer = mLayers[i];
471         if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
472             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) &&
473             layer->mLayerBuffer && getDrmMode(layer->mLayerBuffer) == SECURE_DRM) {
474             mIsSecureDRM = true;
475             DISPLAY_LOGD(eDebugVirtualDisplay, "include secure drm layer");
476         }
477         if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
478             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) &&
479             layer->mLayerBuffer && getDrmMode(layer->mLayerBuffer) == NORMAL_DRM) {
480             mIsNormalDRM = true;
481             DISPLAY_LOGD(eDebugVirtualDisplay, "include normal drm layer");
482         }
483     }
484     DISPLAY_LOGD(eDebugVirtualDisplay, "setDrmMode(), mIsSecureDRM %d", mIsSecureDRM);
485 }
486 
handleSkipFrame()487 void ExynosVirtualDisplay::handleSkipFrame()
488 {
489     mIsSkipFrame = true;
490     for (size_t i = 0; i < mLayers.size(); i++) {
491         ExynosLayer *layer = mLayers[i];
492         layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
493     }
494     mIsSecureDRM = false;
495     mIsNormalDRM = false;
496     mCompositionType = COMPOSITION_HWC;
497     mSinkUsage = BufferUsage::COMPOSER_OVERLAY | BufferUsage::VIDEO_ENCODER;
498     DISPLAY_LOGD(eDebugVirtualDisplay, "handleSkipFrame()");
499 }
500 
handleAcquireFence()501 void ExynosVirtualDisplay::handleAcquireFence()
502 {
503     /* handle fence of DEVICE or EXYNOS composition layers */
504     for (size_t i = 0; i < mLayers.size(); i++) {
505         ExynosLayer *layer = mLayers[i];
506         if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE ||
507             layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
508             layer->mReleaseFence = layer->mAcquireFence;
509             setFenceInfo(layer->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER,
510                          HwcFenceDirection::TO);
511             layer->mAcquireFence = -1;
512         }
513     }
514     mClientCompositionInfo.mReleaseFence = mClientCompositionInfo.mAcquireFence;
515     setFenceInfo(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB,
516                  HwcFenceDirection::TO);
517     mClientCompositionInfo.mAcquireFence = -1;
518 
519     mOutputBufferReleaseFenceFd = mOutputBufferAcquireFenceFd;
520     mOutputBufferAcquireFenceFd = -1;
521     DISPLAY_LOGD(eDebugVirtualDisplay, "handleAcquireFence()");
522 }
523 
getHdrCapabilities(uint32_t * outNumTypes,int32_t * outTypes,float * outMaxLuminance,float * outMaxAverageLuminance,float * outMinLuminance)524 int32_t ExynosVirtualDisplay::getHdrCapabilities(uint32_t* outNumTypes,
525         int32_t* outTypes, float* outMaxLuminance,
526         float* outMaxAverageLuminance, float* outMinLuminance)
527 {
528     if (outTypes == NULL) {
529         *outNumTypes = 1;
530         return 0;
531     }
532     outTypes[0] = HAL_HDR_HDR10;
533     return 0;
534 }
535