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