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