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