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