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