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 <surface_utils.h>
17 #include <cinttypes>
18 #include "securec.h"
19 #include "buffer_log.h"
20
21 namespace OHOS {
22 using namespace HiviewDFX;
23 static SurfaceUtils* instance = nullptr;
24 static std::once_flag createFlag_;
25 constexpr uint32_t MATRIX_ARRAY_SIZE = 16;
26
GetInstance()27 SurfaceUtils* SurfaceUtils::GetInstance()
28 {
29 std::call_once(createFlag_, [&]() {
30 instance = new SurfaceUtils();
31 });
32
33 return instance;
34 }
35
~SurfaceUtils()36 SurfaceUtils::~SurfaceUtils()
37 {
38 instance = nullptr;
39 surfaceCache_.clear();
40 nativeWindowCache_.clear();
41 }
42
GetSurface(uint64_t uniqueId)43 sptr<Surface> SurfaceUtils::GetSurface(uint64_t uniqueId)
44 {
45 std::lock_guard<std::mutex> lockGuard(mutex_);
46 if (surfaceCache_.count(uniqueId) == 0) {
47 BLOGE("Cannot find surface, uniqueId: %{public}" PRIu64 ".", uniqueId);
48 return nullptr;
49 }
50 sptr<Surface> surface = surfaceCache_[uniqueId].promote();
51 if (surface == nullptr) {
52 BLOGE("surface is nullptr, uniqueId: %{public}" PRIu64 ".", uniqueId);
53 return nullptr;
54 }
55 return surface;
56 }
57
Add(uint64_t uniqueId,const wptr<Surface> & surface)58 SurfaceError SurfaceUtils::Add(uint64_t uniqueId, const wptr<Surface> &surface)
59 {
60 std::lock_guard<std::mutex> lockGuard(mutex_);
61 if (surface == nullptr) {
62 return GSERROR_INVALID_ARGUMENTS;
63 }
64 if (surfaceCache_.count(uniqueId) == 0) {
65 surfaceCache_[uniqueId] = surface;
66 return GSERROR_OK;
67 }
68 BLOGD("the surface already existed, uniqueId: %{public}" PRIu64, uniqueId);
69 return GSERROR_OK;
70 }
71
Remove(uint64_t uniqueId)72 SurfaceError SurfaceUtils::Remove(uint64_t uniqueId)
73 {
74 std::lock_guard<std::mutex> lockGuard(mutex_);
75 if (surfaceCache_.count(uniqueId) == 0) {
76 BLOGD("Delete failed without surface, uniqueId %{public}" PRIu64, uniqueId);
77 return GSERROR_INVALID_OPERATING;
78 }
79 surfaceCache_.erase(uniqueId);
80 return GSERROR_OK;
81 }
82
MatrixProduct(const std::array<float,MATRIX_ARRAY_SIZE> & lMat,const std::array<float,MATRIX_ARRAY_SIZE> & rMat)83 std::array<float, MATRIX_ARRAY_SIZE> SurfaceUtils::MatrixProduct(const std::array<float, MATRIX_ARRAY_SIZE>& lMat,
84 const std::array<float, MATRIX_ARRAY_SIZE>& rMat)
85 {
86 // Product matrix 4 * 4 = 16
87 return std::array<float, MATRIX_ARRAY_SIZE> {
88 lMat[0] * rMat[0] + lMat[4] * rMat[1] + lMat[8] * rMat[2] + lMat[12] * rMat[3],
89 lMat[1] * rMat[0] + lMat[5] * rMat[1] + lMat[9] * rMat[2] + lMat[13] * rMat[3],
90 lMat[2] * rMat[0] + lMat[6] * rMat[1] + lMat[10] * rMat[2] + lMat[14] * rMat[3],
91 lMat[3] * rMat[0] + lMat[7] * rMat[1] + lMat[11] * rMat[2] + lMat[15] * rMat[3],
92
93 lMat[0] * rMat[4] + lMat[4] * rMat[5] + lMat[8] * rMat[6] + lMat[12] * rMat[7],
94 lMat[1] * rMat[4] + lMat[5] * rMat[5] + lMat[9] * rMat[6] + lMat[13] * rMat[7],
95 lMat[2] * rMat[4] + lMat[6] * rMat[5] + lMat[10] * rMat[6] + lMat[14] * rMat[7],
96 lMat[3] * rMat[4] + lMat[7] * rMat[5] + lMat[11] * rMat[6] + lMat[15] * rMat[7],
97
98 lMat[0] * rMat[8] + lMat[4] * rMat[9] + lMat[8] * rMat[10] + lMat[12] * rMat[11],
99 lMat[1] * rMat[8] + lMat[5] * rMat[9] + lMat[9] * rMat[10] + lMat[13] * rMat[11],
100 lMat[2] * rMat[8] + lMat[6] * rMat[9] + lMat[10] * rMat[10] + lMat[14] * rMat[11],
101 lMat[3] * rMat[8] + lMat[7] * rMat[9] + lMat[11] * rMat[10] + lMat[15] * rMat[11],
102
103 lMat[0] * rMat[12] + lMat[4] * rMat[13] + lMat[8] * rMat[14] + lMat[12] * rMat[15],
104 lMat[1] * rMat[12] + lMat[5] * rMat[13] + lMat[9] * rMat[14] + lMat[13] * rMat[15],
105 lMat[2] * rMat[12] + lMat[6] * rMat[13] + lMat[10] * rMat[14] + lMat[14] * rMat[15],
106 lMat[3] * rMat[12] + lMat[7] * rMat[13] + lMat[11] * rMat[14] + lMat[15] * rMat[15]
107 };
108 }
109
ComputeTransformByMatrix(GraphicTransformType & transform,std::array<float,TRANSFORM_MATRIX_ELE_COUNT> * transformMatrix)110 void SurfaceUtils::ComputeTransformByMatrix(GraphicTransformType& transform,
111 std::array<float, TRANSFORM_MATRIX_ELE_COUNT> *transformMatrix)
112 {
113 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> rotate90 = {0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
114 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> rotate180 = {-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
115 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> rotate270 = {0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
116 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> flipH = {-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
117 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> flipV = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
118
119 switch (transform) {
120 case GraphicTransformType::GRAPHIC_ROTATE_NONE:
121 break;
122 case GraphicTransformType::GRAPHIC_ROTATE_90:
123 *transformMatrix = MatrixProduct(*transformMatrix, rotate90);
124 break;
125 case GraphicTransformType::GRAPHIC_ROTATE_180:
126 *transformMatrix = MatrixProduct(*transformMatrix, rotate180);
127 break;
128 case GraphicTransformType::GRAPHIC_ROTATE_270:
129 *transformMatrix = MatrixProduct(*transformMatrix, rotate270);
130 break;
131 case GraphicTransformType::GRAPHIC_FLIP_H:
132 *transformMatrix = MatrixProduct(*transformMatrix, flipH);
133 break;
134 case GraphicTransformType::GRAPHIC_FLIP_V:
135 *transformMatrix = MatrixProduct(*transformMatrix, flipV);
136 break;
137 case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
138 *transformMatrix = MatrixProduct(flipH, rotate90);
139 break;
140 case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
141 *transformMatrix = MatrixProduct(flipV, rotate90);
142 break;
143 case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
144 *transformMatrix = MatrixProduct(flipH, rotate180);
145 break;
146 case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
147 *transformMatrix = MatrixProduct(flipV, rotate180);
148 break;
149 case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
150 *transformMatrix = MatrixProduct(flipH, rotate270);
151 break;
152 case GraphicTransformType::GRAPHIC_FLIP_V_ROT270:
153 *transformMatrix = MatrixProduct(flipV, rotate270);
154 break;
155 default:
156 break;
157 }
158 }
159
ComputeTransformMatrix(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,Rect & crop)160 void SurfaceUtils::ComputeTransformMatrix(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
161 sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, Rect& crop)
162 {
163 if (buffer == nullptr) {
164 return;
165 }
166 float tx = 0.f;
167 float ty = 0.f;
168 float sx = 1.f;
169 float sy = 1.f;
170 std::array<float, TRANSFORM_MATRIX_ELE_COUNT> transformMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
171 ComputeTransformByMatrix(transform, &transformMatrix);
172
173 float bufferWidth = buffer->GetWidth();
174 float bufferHeight = buffer->GetHeight();
175 bool changeFlag = false;
176 if (crop.w < bufferWidth && bufferWidth != 0) {
177 tx = (float(crop.x) / bufferWidth);
178 sx = (float(crop.w) / bufferWidth);
179 changeFlag = true;
180 }
181 if (crop.h < bufferHeight && bufferHeight != 0) {
182 ty = (float(bufferHeight - crop.y) / bufferHeight);
183 sy = (float(crop.h) / bufferHeight);
184 changeFlag = true;
185 }
186 if (changeFlag) {
187 std::array<float, MATRIX_ARRAY_SIZE> cropMatrix = {sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1};
188 transformMatrix = MatrixProduct(cropMatrix, transformMatrix);
189 }
190
191 auto ret = memcpy_s(matrix, matrixSize * sizeof(float),
192 transformMatrix.data(), sizeof(transformMatrix));
193 if (ret != EOK) {
194 BLOGE("memcpy_s failed, ret: %{public}d", ret);
195 }
196 }
197
ComputeTransformByMatrixV2(GraphicTransformType & transform,std::array<float,TRANSFORM_MATRIX_ELE_COUNT> * transformMatrix)198 void SurfaceUtils::ComputeTransformByMatrixV2(GraphicTransformType& transform,
199 std::array<float, TRANSFORM_MATRIX_ELE_COUNT> *transformMatrix)
200 {
201 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> rotate90 = {0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1};
202 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> rotate180 = {-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1};
203 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> rotate270 = {0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1};
204 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> flipH = {-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1};
205 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> flipV = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1};
206
207 switch (transform) {
208 case GraphicTransformType::GRAPHIC_ROTATE_NONE:
209 break;
210 case GraphicTransformType::GRAPHIC_ROTATE_90:
211 *transformMatrix = rotate90;
212 break;
213 case GraphicTransformType::GRAPHIC_ROTATE_180:
214 *transformMatrix = rotate180;
215 break;
216 case GraphicTransformType::GRAPHIC_ROTATE_270:
217 *transformMatrix = rotate270;
218 break;
219 case GraphicTransformType::GRAPHIC_FLIP_H:
220 *transformMatrix = flipH;
221 break;
222 case GraphicTransformType::GRAPHIC_FLIP_V:
223 *transformMatrix = flipV;
224 break;
225 case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
226 *transformMatrix = MatrixProduct(flipV, rotate90);
227 break;
228 case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
229 *transformMatrix = MatrixProduct(flipH, rotate90);
230 break;
231 case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
232 *transformMatrix = flipV;
233 break;
234 case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
235 *transformMatrix = flipH;
236 break;
237 case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
238 *transformMatrix = MatrixProduct(flipH, rotate90);
239 break;
240 case GraphicTransformType::GRAPHIC_FLIP_V_ROT270:
241 *transformMatrix = MatrixProduct(flipV, rotate90);
242 break;
243 default:
244 break;
245 }
246 }
247
ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,Rect & crop)248 void SurfaceUtils::ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
249 sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, Rect& crop)
250 {
251 if (buffer == nullptr) {
252 return;
253 }
254 float tx = 0.f;
255 float ty = 0.f;
256 float sx = 1.f;
257 float sy = 1.f;
258 switch (transform) {
259 case GraphicTransformType::GRAPHIC_ROTATE_90:
260 transform = GraphicTransformType::GRAPHIC_ROTATE_270;
261 break;
262 case GraphicTransformType::GRAPHIC_ROTATE_270:
263 transform = GraphicTransformType::GRAPHIC_ROTATE_90;
264 break;
265 default:
266 break;
267 }
268 std::array<float, TRANSFORM_MATRIX_ELE_COUNT> transformMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
269 ComputeTransformByMatrixV2(transform, &transformMatrix);
270
271 float bufferWidth = buffer->GetWidth();
272 float bufferHeight = buffer->GetHeight();
273 bool changeFlag = false;
274 if (crop.w < bufferWidth && bufferWidth != 0) {
275 tx = (float(crop.x) / bufferWidth);
276 sx = (float(crop.w) / bufferWidth);
277 changeFlag = true;
278 }
279 if (crop.h < bufferHeight && bufferHeight != 0) {
280 ty = (float(bufferHeight - crop.y) / bufferHeight);
281 sy = (float(crop.h) / bufferHeight);
282 changeFlag = true;
283 }
284 if (changeFlag) {
285 std::array<float, MATRIX_ARRAY_SIZE> cropMatrix = {sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1};
286 transformMatrix = MatrixProduct(cropMatrix, transformMatrix);
287 }
288
289 const std::array<float, TRANSFORM_MATRIX_ELE_COUNT> flipV = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1};
290 transformMatrix = MatrixProduct(flipV, transformMatrix);
291
292 auto ret = memcpy_s(matrix, matrixSize * sizeof(float),
293 transformMatrix.data(), sizeof(transformMatrix));
294 if (ret != EOK) {
295 BLOGE("memcpy_s failed, ret: %{public}d", ret);
296 }
297 }
298
GetNativeWindow(uint64_t uniqueId)299 void* SurfaceUtils::GetNativeWindow(uint64_t uniqueId)
300 {
301 std::lock_guard<std::mutex> lockGuard(mutex_);
302 if (nativeWindowCache_.count(uniqueId) == 0) {
303 BLOGE("Cannot find nativeWindow, uniqueId %" PRIu64 ".", uniqueId);
304 return nullptr;
305 }
306 return nativeWindowCache_[uniqueId];
307 }
308
AddNativeWindow(uint64_t uniqueId,void * nativeWidow)309 SurfaceError SurfaceUtils::AddNativeWindow(uint64_t uniqueId, void *nativeWidow)
310 {
311 if (nativeWidow == nullptr) {
312 return GSERROR_INVALID_ARGUMENTS;
313 }
314 std::lock_guard<std::mutex> lockGuard(mutex_);
315 if (nativeWindowCache_.count(uniqueId) == 0) {
316 nativeWindowCache_[uniqueId] = nativeWidow;
317 return GSERROR_OK;
318 }
319 BLOGD("the nativeWidow already existed, uniqueId %" PRIu64, uniqueId);
320 return GSERROR_OK;
321 }
322
RemoveNativeWindow(uint64_t uniqueId)323 SurfaceError SurfaceUtils::RemoveNativeWindow(uint64_t uniqueId)
324 {
325 std::lock_guard<std::mutex> lockGuard(mutex_);
326 nativeWindowCache_.erase(uniqueId);
327 return GSERROR_OK;
328 }
329 } // namespace OHOS
330