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