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