1 /*
2  * Copyright (c) 2021 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_gfx_composition.h"
17 #include <cinttypes>
18 #include <dlfcn.h>
19 #include <cerrno>
20 #include "display_gfx.h"
21 
22 namespace OHOS {
23 namespace HDI {
24 namespace DISPLAY {
Init(void)25 int32_t HdiGfxComposition::Init(void)
26 {
27     DISPLAY_LOGD();
28     int32_t ret = GfxModuleInit();
29     if ((ret != DISPLAY_SUCCESS) || (mGfxFuncs == nullptr)) {
30         DISPLAY_LOGE("GfxModuleInit failed will use client composition always");
31         return DISPLAY_SUCCESS;
32     }
33     ret = mGfxFuncs->InitGfx();
34     DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("gfx init failed"));
35     if (ret != DISPLAY_SUCCESS) {
36         DISPLAY_LOGE("Failed to init gfx will use client composition always");
37         return DISPLAY_SUCCESS;
38     }
39     valid_ = true;
40     return DISPLAY_SUCCESS;
41 }
42 
GfxModuleInit(void)43 int32_t HdiGfxComposition::GfxModuleInit(void)
44 {
45     DISPLAY_LOGD();
46     mGfxModule = dlopen(LIB_HDI_GFX_NAME, RTLD_NOW | RTLD_NOLOAD);
47     if (mGfxModule != nullptr) {
48         DISPLAY_LOGI("Module '%{public}s' already loaded", LIB_HDI_GFX_NAME);
49     } else {
50         DISPLAY_LOGI("Loading module '%{public}s'", LIB_HDI_GFX_NAME);
51         mGfxModule = dlopen(LIB_HDI_GFX_NAME, RTLD_NOW);
52         if (mGfxModule == nullptr) {
53             DISPLAY_LOGE("Failed to load module: %{public}s", dlerror());
54             return DISPLAY_FAILURE;
55         }
56     }
57 
58     using InitFunc = int32_t (*)(GfxFuncs **funcs);
59     InitFunc func = reinterpret_cast<InitFunc>(dlsym(mGfxModule, LIB_GFX_FUNC_INIT));
60     if (func == nullptr) {
61         DISPLAY_LOGE("Failed to lookup %{public}s function: %s", LIB_GFX_FUNC_INIT, dlerror());
62         dlclose(mGfxModule);
63         return DISPLAY_FAILURE;
64     }
65     return func(&mGfxFuncs);
66 }
67 
GfxModuleDeinit(void)68 int32_t HdiGfxComposition::GfxModuleDeinit(void)
69 {
70     DISPLAY_LOGD();
71     int32_t ret = DISPLAY_SUCCESS;
72     if (mGfxModule == nullptr) {
73         using DeinitFunc = int32_t (*)(GfxFuncs *funcs);
74         DeinitFunc func = reinterpret_cast<DeinitFunc>(dlsym(mGfxModule, LIB_GFX_FUNC_DEINIT));
75         if (func == nullptr) {
76             DISPLAY_LOGE("Failed to lookup %{public}s function: %s", LIB_GFX_FUNC_DEINIT, dlerror());
77         } else {
78             ret = func(mGfxFuncs);
79         }
80         dlclose(mGfxModule);
81     }
82     return ret;
83 }
84 
CanHandle(HdiLayer & hdiLayer)85 bool HdiGfxComposition::CanHandle(HdiLayer &hdiLayer)
86 {
87     DISPLAY_LOGD();
88     (void)hdiLayer;
89     return valid_;
90 }
91 
SetLayers(std::vector<HdiLayer * > & layers,HdiLayer & clientLayer)92 int32_t HdiGfxComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
93 {
94     DISPLAY_LOGD("layers size %{public}zd", layers.size());
95     mClientLayer = &clientLayer;
96     mCompLayers.clear();
97     for (auto &layer : layers) {
98         if (CanHandle(*layer)) {
99             if ((layer->GetCompositionType() != COMPOSITION_VIDEO) &&
100                 (layer->GetCompositionType() != COMPOSITION_CURSOR)) {
101                 layer->SetDeviceSelect(COMPOSITION_DEVICE);
102             } else {
103                 layer->SetDeviceSelect(layer->GetCompositionType());
104             }
105             mCompLayers.push_back(layer);
106         } else {
107             layer->SetDeviceSelect(COMPOSITION_CLIENT);
108         }
109     }
110     DISPLAY_LOGD("composer layers size %{public}zd", mCompLayers.size());
111     return DISPLAY_SUCCESS;
112 }
113 
InitGfxSurface(ISurface & surface,HdiLayerBuffer & buffer)114 void HdiGfxComposition::InitGfxSurface(ISurface &surface, HdiLayerBuffer &buffer)
115 {
116     surface.width = buffer.GetWidth();
117     surface.height = buffer.GetHeight();
118     surface.phyAddr = buffer.GetMemHandle();
119     surface.enColorFmt = (PixelFormat)buffer.GetFormat();
120     surface.stride = buffer.GetStride();
121     surface.bAlphaExt1555 = true;
122     surface.bAlphaMax255 = true;
123     surface.alpha0 = 0XFF;
124     surface.alpha1 = 0XFF;
125     DISPLAY_LOGD("surface w:%{public}d h:%{public}d fmt:%{public}d stride:%{public}d",
126         surface.width, surface.height, surface.enColorFmt, surface.stride);
127 }
128 
129 // now not handle the alpha of layer
BlitLayer(HdiLayer & src,HdiLayer & dst)130 int32_t HdiGfxComposition::BlitLayer(HdiLayer &src, HdiLayer &dst)
131 {
132     ISurface srcSurface = { 0 };
133     ISurface dstSurface = { 0 };
134     GfxOpt opt = { 0 };
135     DISPLAY_LOGD();
136     HdiLayerBuffer *srcBuffer = src.GetCurrentBuffer();
137     DISPLAY_CHK_RETURN((srcBuffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the srcbuffer is null"));
138     DISPLAY_LOGD("init the src surface");
139     InitGfxSurface(srcSurface, *srcBuffer);
140 
141     HdiLayerBuffer *dstBuffer = dst.GetCurrentBuffer();
142     DISPLAY_CHK_RETURN((dstBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get client layer buffer"));
143     DISPLAY_LOGD("init the dst surface");
144     InitGfxSurface(dstSurface, *dstBuffer);
145 
146     opt.blendType = src.GetLayerBlenType();
147     DISPLAY_LOGD("blendType %{public}d", opt.blendType);
148     opt.enPixelAlpha = true;
149     opt.enableScale = true;
150 
151     if (src.GetAlpha().enGlobalAlpha) { // is alpha is 0xff we not set it
152         opt.enGlobalAlpha = true;
153         srcSurface.alpha0 = src.GetAlpha().gAlpha;
154         DISPLAY_LOGD("src alpha %{public}x", src.GetAlpha().gAlpha);
155     }
156     opt.rotateType = src.GetTransFormType();
157     DISPLAY_LOGD(" the roate type is %{public}d", opt.rotateType);
158     IRect crop = src.GetLayerCrop();
159     IRect displayRect = src.GetLayerDisplayRect();
160     DISPLAY_LOGD("crop x: %{public}d y : %{public}d w : %{public}d h: %{public}d", crop.x, crop.y, crop.w, crop.h);
161     DISPLAY_LOGD("displayRect x: %{public}d y : %{public}d w : %{public}d h : %{public}d", displayRect.x, displayRect.y,
162         displayRect.w, displayRect.h);
163     DISPLAY_CHK_RETURN(mGfxFuncs == nullptr, DISPLAY_FAILURE, DISPLAY_LOGE("Blit: mGfxFuncs is null"));
164     return mGfxFuncs->Blit(&srcSurface, &crop, &dstSurface, &displayRect, &opt);
165 }
166 
ClearRect(HdiLayer & src,HdiLayer & dst)167 int32_t HdiGfxComposition::ClearRect(HdiLayer &src, HdiLayer &dst)
168 {
169     ISurface dstSurface = { 0 };
170     GfxOpt opt = { 0 };
171     DISPLAY_LOGD();
172     HdiLayerBuffer *dstBuffer = dst.GetCurrentBuffer();
173     DISPLAY_CHK_RETURN((dstBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get client layer buffer"));
174     InitGfxSurface(dstSurface, *dstBuffer);
175     IRect rect = src.GetLayerDisplayRect();
176     DISPLAY_CHK_RETURN(mGfxFuncs == nullptr, DISPLAY_FAILURE, DISPLAY_LOGE("Rect: mGfxFuncs is null"));
177     return mGfxFuncs->FillRect(&dstSurface, &rect, 0, &opt);
178 }
179 
Apply(bool modeSet)180 int32_t HdiGfxComposition::Apply(bool modeSet)
181 {
182     int32_t ret;
183     DISPLAY_LOGD("composer layers size %{public}zd", mCompLayers.size());
184     for (uint32_t i = 0; i < mCompLayers.size(); i++) {
185         HdiLayer *layer = mCompLayers[i];
186         CompositionType compType = layer->GetDeviceSelect();
187         switch (compType) {
188             case COMPOSITION_VIDEO:
189                 ret = ClearRect(*layer, *mClientLayer);
190                 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
191                     DISPLAY_LOGE("clear layer %{public}d failed", i));
192                 break;
193             case COMPOSITION_DEVICE:
194                 ret = BlitLayer(*layer, *mClientLayer);
195                 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
196                     DISPLAY_LOGE("blit layer %{public}d failed ", i));
197                 break;
198             default:
199                 DISPLAY_LOGE("the gfx composition can not surpport the type %{public}d", compType);
200                 break;
201         }
202     }
203     return DISPLAY_SUCCESS;
204 }
205 } // namespace OHOS
206 } // namespace HDI
207 } // namespace DISPLAY
208