1 /*
2  * Copyright (c) 2021-2023 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_layer.h"
17 #include <cerrno>
18 #include <fstream>
19 #include <libsync.h>
20 #include <securec.h>
21 #include <sstream>
22 #include <string>
23 #include <sys/time.h>
24 #include <unistd.h>
25 #include "display_buffer_vdi_impl.h"
26 #include "v1_0/display_composer_type.h"
27 
28 namespace OHOS {
29 namespace HDI {
30 namespace DISPLAY {
31 uint32_t HdiLayer::mIdleId = 0;
32 std::unordered_set<uint32_t> HdiLayer::mIdSets;
33 std::shared_ptr<IDisplayBufferVdi> g_buffer;
34 constexpr int TIME_BUFFER_MAX_LEN = 15;
35 const std::string PATH_PREFIX = "/data/local/traces/";
36 
HdiLayerBuffer(const BufferHandle & hdl)37 HdiLayerBuffer::HdiLayerBuffer(const BufferHandle &hdl)
38     : mPhyAddr(hdl.phyAddr), mHeight(hdl.height), mWidth(hdl.width), mStride(hdl.stride), mFormat(hdl.format)
39 {
40     DISPLAY_LOGD();
41     mFd = dup(hdl.fd);
42     mHandle = hdl;
43     if (mFd < 0) {
44         DISPLAY_LOGE("the fd : %{public}d dup failed errno  %{public}d", hdl.fd, errno);
45     }
46 }
47 
~HdiLayerBuffer()48 HdiLayerBuffer::~HdiLayerBuffer()
49 {
50     DISPLAY_LOGD();
51     if (mFd >= 0) {
52         close(mFd);
53     }
54 }
55 
operator =(const BufferHandle & right)56 HdiLayerBuffer &HdiLayerBuffer::operator = (const BufferHandle &right)
57 {
58     DISPLAY_LOGD();
59     if (mFd >= 0) {
60         close(mFd);
61     }
62     mFd = dup(right.fd);
63     mPhyAddr = right.phyAddr;
64     mWidth = right.width;
65     mHeight = right.height;
66     mStride = right.stride;
67     mFormat = right.format;
68     return *this;
69 }
70 
GetIdleId()71 uint32_t HdiLayer::GetIdleId()
72 {
73     const uint32_t oldIdleId = mIdleId;
74     uint32_t id = INVALIDE_LAYER_ID;
75     // ensure the mIdleId not INVALIDE_LAYER_ID
76     mIdleId = mIdleId % INVALIDE_LAYER_ID;
77     do {
78         auto iter = mIdSets.find(mIdleId);
79         if (iter == mIdSets.end()) {
80             id = mIdleId;
81             break;
82         }
83         mIdleId = (mIdleId + 1) % INVALIDE_LAYER_ID;
84     } while (oldIdleId != mIdleId);
85     mIdSets.emplace(id);
86     mIdleId++;
87     DISPLAY_LOGD("id %{public}d mIdleId %{public}d", id, mIdleId);
88     return id;
89 }
90 
Init()91 int32_t HdiLayer::Init()
92 {
93     DISPLAY_LOGD();
94     uint32_t id = GetIdleId();
95     DISPLAY_CHK_RETURN((id == INVALIDE_LAYER_ID), DISPLAY_FAILURE, DISPLAY_LOGE("have no id to used"));
96     mId = id;
97     return DISPLAY_SUCCESS;
98 }
99 
SetLayerRegion(IRect * rect)100 int32_t HdiLayer::SetLayerRegion(IRect *rect)
101 {
102     DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr"));
103     DISPLAY_LOGD(" displayRect x: %{public}d y : %{public}d w : %{public}d h : %{public}d", rect->x, rect->y,
104         rect->w, rect->h);
105     mDisplayRect = *rect;
106     return DISPLAY_SUCCESS;
107 }
108 
SetLayerCrop(IRect * rect)109 int32_t HdiLayer::SetLayerCrop(IRect *rect)
110 {
111     DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr"));
112     DISPLAY_LOGD("id : %{public}d crop x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId,
113         rect->x, rect->y, rect->w, rect->h);
114     mCrop = *rect;
115     return DISPLAY_SUCCESS;
116 }
117 
SetLayerZorder(uint32_t zorder)118 void HdiLayer::SetLayerZorder(uint32_t zorder)
119 {
120     DISPLAY_LOGD("id : %{public}d zorder : %{public}d ", mId, zorder);
121     mZorder = zorder;
122 }
123 
SetLayerPreMulti(bool preMul)124 int32_t HdiLayer::SetLayerPreMulti(bool preMul)
125 {
126     DISPLAY_LOGD();
127     mPreMul = preMul;
128     return DISPLAY_SUCCESS;
129 }
130 
SetLayerAlpha(LayerAlpha * alpha)131 int32_t HdiLayer::SetLayerAlpha(LayerAlpha *alpha)
132 {
133     DISPLAY_CHK_RETURN((alpha == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in alpha is nullptr"));
134     DISPLAY_LOGD("enable alpha %{public}d galpha 0x%{public}x", alpha->enGlobalAlpha, alpha->gAlpha);
135     mAlpha = *alpha;
136     return DISPLAY_SUCCESS;
137 }
138 
SetLayerTransformMode(TransformType type)139 int32_t HdiLayer::SetLayerTransformMode(TransformType type)
140 {
141     DISPLAY_LOGD("TransformType %{public}d", type);
142     mTransformType = type;
143     return DISPLAY_SUCCESS;
144 }
145 
SetLayerDirtyRegion(IRect * region)146 int32_t HdiLayer::SetLayerDirtyRegion(IRect *region)
147 {
148     DISPLAY_CHK_RETURN((region == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the in rect is null"));
149     DISPLAY_LOGD("id : %{public}d DirtyRegion x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId,
150         region->x, region->y, region->w, region->h);
151     return DISPLAY_SUCCESS;
152 }
153 
SetLayerVisibleRegion(uint32_t num,IRect * rect)154 int32_t HdiLayer::SetLayerVisibleRegion(uint32_t num, IRect *rect)
155 {
156     DISPLAY_LOGD("id : %{public}d DirtyRegion x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId,
157         rect->x, rect->y, rect->w, rect->h);
158     return DISPLAY_SUCCESS;
159 }
160 
GetFileName(const BufferHandle * buffer)161 static std::string GetFileName(const BufferHandle *buffer)
162 {
163     struct timeval tv;
164     char nowStr[TIME_BUFFER_MAX_LEN] = {0};
165 
166     gettimeofday(&tv, nullptr);
167     if (strftime(nowStr, sizeof(nowStr), "%m-%d-%H-%M-%S", localtime(&tv.tv_sec)) == 0) {
168         DISPLAY_LOGE("strftime failed");
169         return "";
170     };
171 
172     std::ostringstream strStream;
173     strStream << "hdi_layer_" << nowStr << "_" << tv.tv_usec << "_" << buffer->width << "_" << buffer->height << ".img";
174     return strStream.str();
175 }
176 
DumpLayerBuffer(BufferHandle * buffer)177 static int32_t DumpLayerBuffer(BufferHandle *buffer)
178 {
179     CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR);
180 
181     int32_t ret = 0;
182     if (g_buffer== nullptr) {
183         IDisplayBufferVdi* dispBuf = new DisplayBufferVdiImpl();
184         DISPLAY_CHK_RETURN((dispBuf == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("dispBuf init failed"));
185         g_buffer.reset(dispBuf);
186     }
187 
188     std::string fileName = GetFileName(buffer);
189     DISPLAY_CHK_RETURN((fileName == ""), DISPLAY_FAILURE, DISPLAY_LOGE("GetFileName failed"));
190     DISPLAY_LOGI("fileName = %{public}s", fileName.c_str());
191 
192     std::stringstream filePath;
193     filePath << PATH_PREFIX << fileName;
194     std::ofstream rawDataFile(filePath.str(), std::ofstream::binary);
195     DISPLAY_CHK_RETURN((!rawDataFile.good()), DISPLAY_FAILURE, DISPLAY_LOGE("open file failed, %{public}s",
196         std::strerror(errno)));
197 
198     void *buffAddr = g_buffer->Mmap(*buffer);
199     DISPLAY_CHK_RETURN((buffAddr == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("Mmap buffer failed"));
200 
201     rawDataFile.write(static_cast<const char *>(buffAddr), buffer->size);
202     rawDataFile.close();
203 
204     ret = g_buffer->Unmap(*buffer);
205     DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("Unmap buffer failed"));
206     return DISPLAY_SUCCESS;
207 }
208 
SetLayerBuffer(const BufferHandle * buffer,int32_t fence)209 int32_t HdiLayer::SetLayerBuffer(const BufferHandle *buffer, int32_t fence)
210 {
211     DISPLAY_LOGD();
212     DISPLAY_CHK_RETURN((buffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("buffer is nullptr"));
213     std::unique_ptr<HdiLayerBuffer> layerbuffer = std::make_unique<HdiLayerBuffer>(*buffer);
214     mHdiBuffer = std::move(layerbuffer);
215     mAcquireFence = dup(fence);
216     if (access("/data/hdi_dump_layer", F_OK) != -1) {
217         if (DumpLayerBuffer(const_cast<BufferHandle *>(buffer)) != DISPLAY_SUCCESS) {
218             DISPLAY_LOGE("dump layer buffer failed");
219         }
220     }
221     return DISPLAY_SUCCESS;
222 }
223 
SetLayerCompositionType(CompositionType type)224 int32_t HdiLayer::SetLayerCompositionType(CompositionType type)
225 {
226     DISPLAY_LOGD("CompositionType type %{public}d", type);
227     mCompositionType = type;
228     return DISPLAY_SUCCESS;
229 }
230 
SetLayerBlendType(BlendType type)231 int32_t HdiLayer::SetLayerBlendType(BlendType type)
232 {
233     DISPLAY_LOGD("BlendType type %{public}d", type);
234     mBlendType = type;
235     return DISPLAY_SUCCESS;
236 }
237 
SetPixel(const BufferHandle & handle,int x,int y,uint32_t color)238 void HdiLayer::SetPixel(const BufferHandle &handle, int x, int y, uint32_t color)
239 {
240     const int32_t pixelBytes = 4;
241     DISPLAY_CHK_RETURN_NOT_VALUE((handle.format <= 0),
242         DISPLAY_LOGE("CheckPixel do not support format %{public}d", handle.format));
243     DISPLAY_CHK_RETURN_NOT_VALUE((handle.virAddr == nullptr), DISPLAY_LOGE("CheckPixel viraddr is null must map it"));
244     DISPLAY_CHK_RETURN_NOT_VALUE((x < 0 || x >= handle.width),
245         DISPLAY_LOGE("CheckPixel invalid parameter x:%{public}d width:%{public}d", x, handle.width));
246     DISPLAY_CHK_RETURN_NOT_VALUE((y < 0 || y >= handle.height),
247         DISPLAY_LOGE("CheckPixel invalid parameter y:%{public}d height:%{public}d", y, handle.height));
248     int32_t position = y * handle.width + x;
249     if ((position * pixelBytes) > handle.size) {
250         DISPLAY_LOGE("the pixel postion outside\n");
251     }
252     uint32_t *pixel = reinterpret_cast<uint32_t *>(handle.virAddr) + position;
253     *pixel = color;
254 }
255 
ClearColor(uint32_t color)256 void HdiLayer::ClearColor(uint32_t color)
257 {
258     DISPLAY_LOGD();
259     BufferHandle &handle = mHdiBuffer->mHandle;
260     for (int32_t x = 0; x < handle.width; x++) {
261         for (int32_t y = 0; y < handle.height; y++) {
262             SetPixel(handle, x, y, color);
263         }
264     }
265 }
266 
WaitAcquireFence()267 void HdiLayer::WaitAcquireFence()
268 {
269     int fd = GetAcquireFenceFd();
270     if (fd < 0) {
271         DISPLAY_LOGE("fd is invalid");
272         return;
273     }
274     sync_wait(fd, mFenceTimeOut);
275 }
276 } // namespace OHOS
277 } // namespace HDI
278 } // namespace DISPLAY
279