1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hdi_video_composition.h"
17 #include <set>
18 #include <cinttypes>
19 #include <dlfcn.h>
20
21 namespace OHOS {
22 namespace HDI {
23 namespace DISPLAY {
VideoModuleInit(void)24 int32_t HdiVideoComposition::VideoModuleInit(void)
25 {
26 DISPLAY_LOGD();
27 videoModule_ = dlopen(VO_LAYER_LIB_NAME, RTLD_NOW | RTLD_NOLOAD);
28 if (videoModule_ != nullptr) {
29 DISPLAY_LOGI("Module '%{public}s' already loaded", VO_LAYER_LIB_NAME);
30 } else {
31 DISPLAY_LOGI("Loading module '%{public}s'", VO_LAYER_LIB_NAME);
32 videoModule_ = dlopen(VO_LAYER_LIB_NAME, RTLD_NOW);
33 if (videoModule_ == nullptr) {
34 DISPLAY_LOGE("Failed to load module: %{public}s", dlerror());
35 return DISPLAY_FAILURE;
36 }
37 }
38
39 using InitFunc = int32_t (*)(LayerFuncs **funcs);
40 InitFunc func = reinterpret_cast<InitFunc>(dlsym(videoModule_, VO_LAYER_FUNC_INIT));
41 if (func == nullptr) {
42 DISPLAY_LOGE("Failed to lookup %{public}s function: %s", VO_LAYER_FUNC_INIT, dlerror());
43 dlclose(videoModule_);
44 videoModule_ = nullptr;
45 return DISPLAY_FAILURE;
46 }
47 return func(&layerFuncs_);
48 }
49
CreateVideoLayerForHdiLayer(HdiLayer & hdiLayer)50 uint32_t HdiVideoComposition::CreateVideoLayerForHdiLayer(HdiLayer &hdiLayer)
51 {
52 uint32_t voLayerId;
53 DISPLAY_LOGD("layerId %{public}d", hdiLayer.GetId());
54 IRect rect = hdiLayer.GetLayerDisplayRect();
55 LayerInfo layerInfo = { rect.w, rect.h, LAYER_TYPE_OVERLAY, 8, PIXEL_FMT_YCRCB_420_P }; // the bpp of yuv is 8
56 int ret = layerFuncs_->CreateLayer(0, &layerInfo, &voLayerId);
57 DISPLAY_CHK_RETURN(((ret != DISPLAY_SUCCESS) || (voLayerId == INVALIDE_LAYER_ID)), INVALIDE_LAYER_ID,
58 DISPLAY_LOGE("can not create video layer"));
59 layerMaps_[hdiLayer.GetId()] = voLayerId;
60 DISPLAY_LOGD("map the voLayerId %{public}d to layerId %{public}d", voLayerId, hdiLayer.GetId());
61 return voLayerId;
62 }
63
GetVoLayerId(HdiLayer & hdiLayer)64 uint32_t HdiVideoComposition::GetVoLayerId(HdiLayer &hdiLayer)
65 {
66 DISPLAY_LOGD("layerId %{public}d", hdiLayer.GetId());
67 uint32_t voLayerId = INVALIDE_LAYER_ID;
68 if (layerMaps_.find(hdiLayer.GetId()) != layerMaps_.end()) {
69 voLayerId = layerMaps_[hdiLayer.GetId()];
70 }
71 return voLayerId;
72 }
73
Init(void)74 int32_t HdiVideoComposition::Init(void)
75 {
76 DISPLAY_LOGD();
77 int ret = VideoModuleInit();
78 DISPLAY_CHK_RETURN(((ret != DISPLAY_SUCCESS) || (layerFuncs_ == nullptr)), DISPLAY_FAILURE,
79 DISPLAY_LOGE("can not init the video module"));
80 return DISPLAY_SUCCESS;
81 }
82
SetLayers(std::vector<HdiLayer * > & layers,HdiLayer & clientLayer)83 int32_t HdiVideoComposition::SetLayers(std::vector<HdiLayer*> &layers, HdiLayer &clientLayer)
84 {
85 DISPLAY_LOGD();
86 mCompLayers.clear();
87 std::vector<HdiLayer*> matchedLayers;
88 for (auto layer : layers) {
89 if ((layer != nullptr) && CanHandle(*layer)) {
90 matchedLayers.push_back(layer);
91 }
92 }
93 CLoseUnUsedLayer(matchedLayers);
94 // make sure has the videoLayer for the matched layer
95 for (auto layer : matchedLayers) {
96 if ((GetVoLayerId(*layer) != INVALIDE_LAYER_ID) ||
97 (CreateVideoLayerForHdiLayer(*layer) != INVALIDE_LAYER_ID)) {
98 layer->SetLayerCompositionType(COMPOSITION_VIDEO);
99 mCompLayers.push_back(layer);
100 }
101 }
102 return DISPLAY_SUCCESS;
103 }
104
Apply(bool modeSet)105 int32_t HdiVideoComposition::Apply(bool modeSet)
106 {
107 DISPLAY_LOGD();
108 for (auto hdiLayer : mCompLayers) {
109 if (hdiLayer == nullptr) {
110 DISPLAY_LOGE("the composer layer is nullptr");
111 continue;
112 }
113 uint32_t voLayerId = GetVoLayerId(*hdiLayer);
114 layerFuncs_->SetLayerSize(0, voLayerId, const_cast<IRect *>(&(hdiLayer->GetLayerDisplayRect())));
115 layerFuncs_->SetLayerCrop(0, voLayerId, const_cast<IRect *>(&(hdiLayer->GetLayerCrop())));
116 layerFuncs_->SetLayerZorder(0, voLayerId, hdiLayer->GetZorder());
117 layerFuncs_->SetTransformMode(0, voLayerId, hdiLayer->GetTransFormType());
118 // now the display_layer has no fence
119 layerFuncs_->SetLayerBuffer(0, voLayerId, &(hdiLayer->GetCurrentBuffer()->mHandle),
120 hdiLayer->GetAcquireFenceFd());
121 hdiLayer->SetReleaseFence(-1); // todo check the fence whether use the last fence.
122 }
123 return DISPLAY_SUCCESS;
124 }
125
CLoseUnUsedLayer(const std::vector<HdiLayer * > & layers)126 void HdiVideoComposition::CLoseUnUsedLayer(const std::vector<HdiLayer*> &layers)
127 {
128 DISPLAY_LOGD();
129 std::vector<uint32_t> neededRemove;
130 for (auto iter = layerMaps_.begin(); iter != layerMaps_.end(); iter++) {
131 bool found = false;
132 for (auto layer : layers) {
133 if (iter->first == layer->GetId()) {
134 found = true;
135 }
136 }
137 if (!found) {
138 DISPLAY_LOGD("close the layer Id %{public}d", iter->second);
139 layerFuncs_->CloseLayer(0, iter->second);
140 neededRemove.push_back(iter->first);
141 break;
142 }
143 }
144 for (auto id : neededRemove) {
145 DISPLAY_LOGD("erase the layer Id %{public}d", id);
146 layerMaps_.erase(id);
147 }
148 }
149
CanHandle(HdiLayer & hdiLayer)150 bool HdiVideoComposition::CanHandle(HdiLayer &hdiLayer)
151 {
152 static std::set<PixelFormat> formats = {
153 PIXEL_FMT_YUV_422_I, /* *< YUV422 interleaved format */
154 PIXEL_FMT_YCBCR_422_SP, /* *< YCBCR422 semi-planar format */
155 PIXEL_FMT_YCRCB_422_SP, /* *< YCRCB422 semi-planar format */
156 PIXEL_FMT_YCBCR_420_SP, /* *< YCBCR420 semi-planar format */
157 PIXEL_FMT_YCRCB_420_SP, /* *< YCRCB420 semi-planar format */
158 PIXEL_FMT_YCBCR_422_P, /* *< YCBCR422 planar format */
159 PIXEL_FMT_YCRCB_422_P, /* *< YCRCB422 planar format */
160 PIXEL_FMT_YCBCR_420_P, /* *< YCBCR420 planar format */
161 PIXEL_FMT_YCRCB_420_P, /* *< YCRCB420 planar format */
162 PIXEL_FMT_YUYV_422_PKG, /* *< YUYV422 packed format */
163 PIXEL_FMT_UYVY_422_PKG, /* *< UYVY422 packed format */
164 PIXEL_FMT_YVYU_422_PKG, /* *< YVYU422 packed format */
165 PIXEL_FMT_VYUY_422_PKG, /* *< VYUY422 packed format */
166 };
167
168 if (hdiLayer.GetType() == LAYER_TYPE_SIDEBAND) {
169 DISPLAY_LOGD("is sideband");
170 return false;
171 }
172
173 if (hdiLayer.GetCurrentBuffer() == nullptr) {
174 DISPLAY_LOGD("has no buffer");
175 return false;
176 }
177
178 if (formats.find(static_cast<PixelFormat>(hdiLayer.GetCurrentBuffer()->GetFormat())) == formats.end()) {
179 return false;
180 }
181 return true;
182 }
183 }
184 }
185 }
186