• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     auto iter = surfaceCache_.find(uniqueId);
47     if (iter == surfaceCache_.end()) {
48         BLOGE("Cannot find surface, uniqueId: %{public}" PRIu64 ".", uniqueId);
49         return nullptr;
50     }
51     sptr<Surface> surface = iter->second.promote();
52     if (surface == nullptr) {
53         BLOGE("surface is nullptr, uniqueId: %{public}" PRIu64 ".", uniqueId);
54         return nullptr;
55     }
56     return surface;
57 }
58 
Add(uint64_t uniqueId,const wptr<Surface> & surface)59 SurfaceError SurfaceUtils::Add(uint64_t uniqueId, const wptr<Surface> &surface)
60 {
61     if (surface == nullptr) {
62         return GSERROR_INVALID_ARGUMENTS;
63     }
64     std::lock_guard<std::mutex> lockGuard(mutex_);
65     if (surfaceCache_.count(uniqueId) == 0) {
66         surfaceCache_[uniqueId] = surface;
67         return GSERROR_OK;
68     }
69     BLOGD("the surface already existed, uniqueId: %{public}" PRIu64, uniqueId);
70     return GSERROR_OK;
71 }
72 
Remove(uint64_t uniqueId)73 SurfaceError SurfaceUtils::Remove(uint64_t uniqueId)
74 {
75     std::lock_guard<std::mutex> lockGuard(mutex_);
76     auto iter = surfaceCache_.find(uniqueId);
77     if (iter == surfaceCache_.end()) {
78         BLOGD("Cannot find surface, uniqueId: %{public}" PRIu64 ".", uniqueId);
79         return GSERROR_INVALID_OPERATING;
80     }
81     surfaceCache_.erase(iter);
82     return GSERROR_OK;
83 }
84 
MatrixProduct(const std::array<float,MATRIX_ARRAY_SIZE> & lMat,const std::array<float,MATRIX_ARRAY_SIZE> & rMat)85 std::array<float, MATRIX_ARRAY_SIZE> SurfaceUtils::MatrixProduct(const std::array<float, MATRIX_ARRAY_SIZE>& lMat,
86     const std::array<float, MATRIX_ARRAY_SIZE>& rMat)
87 {
88     // Product matrix 4 * 4 = 16
89     return std::array<float, MATRIX_ARRAY_SIZE> {
90         lMat[0] * rMat[0] + lMat[4] * rMat[1] + lMat[8] * rMat[2] + lMat[12] * rMat[3],
91         lMat[1] * rMat[0] + lMat[5] * rMat[1] + lMat[9] * rMat[2] + lMat[13] * rMat[3],
92         lMat[2] * rMat[0] + lMat[6] * rMat[1] + lMat[10] * rMat[2] + lMat[14] * rMat[3],
93         lMat[3] * rMat[0] + lMat[7] * rMat[1] + lMat[11] * rMat[2] + lMat[15] * rMat[3],
94 
95         lMat[0] * rMat[4] + lMat[4] * rMat[5] + lMat[8] * rMat[6] + lMat[12] * rMat[7],
96         lMat[1] * rMat[4] + lMat[5] * rMat[5] + lMat[9] * rMat[6] + lMat[13] * rMat[7],
97         lMat[2] * rMat[4] + lMat[6] * rMat[5] + lMat[10] * rMat[6] + lMat[14] * rMat[7],
98         lMat[3] * rMat[4] + lMat[7] * rMat[5] + lMat[11] * rMat[6] + lMat[15] * rMat[7],
99 
100         lMat[0] * rMat[8] + lMat[4] * rMat[9] + lMat[8] * rMat[10] + lMat[12] * rMat[11],
101         lMat[1] * rMat[8] + lMat[5] * rMat[9] + lMat[9] * rMat[10] + lMat[13] * rMat[11],
102         lMat[2] * rMat[8] + lMat[6] * rMat[9] + lMat[10] * rMat[10] + lMat[14] * rMat[11],
103         lMat[3] * rMat[8] + lMat[7] * rMat[9] + lMat[11] * rMat[10] + lMat[15] * rMat[11],
104 
105         lMat[0] * rMat[12] + lMat[4] * rMat[13] + lMat[8] * rMat[14] + lMat[12] * rMat[15],
106         lMat[1] * rMat[12] + lMat[5] * rMat[13] + lMat[9] * rMat[14] + lMat[13] * rMat[15],
107         lMat[2] * rMat[12] + lMat[6] * rMat[13] + lMat[10] * rMat[14] + lMat[14] * rMat[15],
108         lMat[3] * rMat[12] + lMat[7] * rMat[13] + lMat[11] * rMat[14] + lMat[15] * rMat[15]
109     };
110 }
111 
ComputeTransformByMatrix(GraphicTransformType & transform,std::array<float,TRANSFORM_MATRIX_ELE_COUNT> * transformMatrix)112 void SurfaceUtils::ComputeTransformByMatrix(GraphicTransformType& transform,
113     std::array<float, TRANSFORM_MATRIX_ELE_COUNT> *transformMatrix)
114 {
115     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};
116     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};
117     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};
118     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};
119     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};
120 
121     switch (transform) {
122         case GraphicTransformType::GRAPHIC_ROTATE_NONE:
123             break;
124         case GraphicTransformType::GRAPHIC_ROTATE_90:
125             *transformMatrix = MatrixProduct(*transformMatrix, rotate90);
126             break;
127         case GraphicTransformType::GRAPHIC_ROTATE_180:
128             *transformMatrix = MatrixProduct(*transformMatrix, rotate180);
129             break;
130         case GraphicTransformType::GRAPHIC_ROTATE_270:
131             *transformMatrix = MatrixProduct(*transformMatrix, rotate270);
132             break;
133         case GraphicTransformType::GRAPHIC_FLIP_H:
134             *transformMatrix = MatrixProduct(*transformMatrix, flipH);
135             break;
136         case GraphicTransformType::GRAPHIC_FLIP_V:
137             *transformMatrix = MatrixProduct(*transformMatrix, flipV);
138             break;
139         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
140             *transformMatrix = MatrixProduct(flipH, rotate90);
141             break;
142         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
143             *transformMatrix = MatrixProduct(flipV, rotate90);
144             break;
145         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
146             *transformMatrix = MatrixProduct(flipH, rotate180);
147             break;
148         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
149             *transformMatrix = MatrixProduct(flipV, rotate180);
150             break;
151         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
152             *transformMatrix = MatrixProduct(flipH, rotate270);
153             break;
154         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270:
155             *transformMatrix = MatrixProduct(flipV, rotate270);
156             break;
157         default:
158             break;
159     }
160 }
161 
ComputeTransformMatrix(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,const Rect & crop)162 void SurfaceUtils::ComputeTransformMatrix(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
163     sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, const Rect& crop)
164 {
165     if (buffer == nullptr) {
166         return;
167     }
168     float tx = 0.f;
169     float ty = 0.f;
170     float sx = 1.f;
171     float sy = 1.f;
172     std::array<float, TRANSFORM_MATRIX_ELE_COUNT> transformMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
173     ComputeTransformByMatrix(transform, &transformMatrix);
174 
175     float bufferWidth = buffer->GetWidth();
176     float bufferHeight = buffer->GetHeight();
177     bool changeFlag = false;
178     if (crop.w < bufferWidth && bufferWidth != 0) {
179         tx = (float(crop.x) / bufferWidth);
180         sx = (float(crop.w) / bufferWidth);
181         changeFlag = true;
182     }
183     if (crop.h < bufferHeight && bufferHeight != 0) {
184         ty = (float(bufferHeight - crop.y) / bufferHeight);
185         sy = (float(crop.h) / bufferHeight);
186         changeFlag = true;
187     }
188     if (changeFlag) {
189         std::array<float, MATRIX_ARRAY_SIZE> cropMatrix = {sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1};
190         transformMatrix = MatrixProduct(cropMatrix, transformMatrix);
191     }
192 
193     auto ret = memcpy_s(matrix, matrixSize * sizeof(float),
194                         transformMatrix.data(), sizeof(transformMatrix));
195     if (ret != EOK) {
196         BLOGE("memcpy_s failed, ret: %{public}d", ret);
197     }
198 }
199 
ComputeTransformByMatrixV2(GraphicTransformType & transform,std::array<float,TRANSFORM_MATRIX_ELE_COUNT> * transformMatrix)200 void SurfaceUtils::ComputeTransformByMatrixV2(GraphicTransformType& transform,
201     std::array<float, TRANSFORM_MATRIX_ELE_COUNT> *transformMatrix)
202 {
203     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};
204     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};
205     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};
206     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};
207     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};
208 
209     switch (transform) {
210         case GraphicTransformType::GRAPHIC_ROTATE_NONE:
211             break;
212         case GraphicTransformType::GRAPHIC_ROTATE_90:
213             *transformMatrix = rotate90;
214             break;
215         case GraphicTransformType::GRAPHIC_ROTATE_180:
216             *transformMatrix = rotate180;
217             break;
218         case GraphicTransformType::GRAPHIC_ROTATE_270:
219             *transformMatrix = rotate270;
220             break;
221         case GraphicTransformType::GRAPHIC_FLIP_H:
222             *transformMatrix = flipH;
223             break;
224         case GraphicTransformType::GRAPHIC_FLIP_V:
225             *transformMatrix = flipV;
226             break;
227         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
228             *transformMatrix = MatrixProduct(flipV, rotate90);
229             break;
230         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
231             *transformMatrix = MatrixProduct(flipH, rotate90);
232             break;
233         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
234             *transformMatrix = flipV;
235             break;
236         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
237             *transformMatrix = flipH;
238             break;
239         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
240             *transformMatrix = MatrixProduct(flipH, rotate90);
241             break;
242         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270:
243             *transformMatrix = MatrixProduct(flipV, rotate90);
244             break;
245         default:
246             break;
247     }
248 }
249 
250 /*
251  * Computes a transformation matrix for buffer rendering with crop and coordinate system conversion.
252  *
253  * The transformation process involves texture coordinate translation, coordinate system
254  * conversion, and scaling operations to achieve proper buffer rendering.
255  *
256  * Texture Coordinate Translation involves converting device coordinates to normalized
257  * texture coordinates [0,1], where:
258  * - tx = crop.x / bufferWidth represents X-axis translation ratio
259  * - ty = (bufferHeight - crop.y - crop.h) / bufferHeight handles Y-axis translation with flip
260  *
261  * Coordinate System Conversion handles the following:
262  * - Device coordinates with origin at top-left and Y-axis down
263  * - OpenGL coordinates with origin at bottom-left and Y-axis up
264  * The Y-axis calculation requires:
265  * - Moving origin from top to bottom using bufferHeight - crop.y
266  * - Accounting for crop region height by subtracting crop.h
267  * - Normalizing to [0,1] range by dividing with bufferHeight
268  *
269  * Scale calculation uses the following factors:
270  * - sx = crop.w / bufferWidth for X-axis scaling
271  * - sy = crop.h / bufferHeight for Y-axis scaling
272  *
273  * The final transformation matrix has the structure:
274  * | sx  0   0   0 |  (X-axis scaling)
275  * | 0   sy  0   0 |  (Y-axis scaling)
276  * | 0   0   1   0 |  (Z-axis unchanged)
277  * | tx  ty  0   1 |  (Translation)
278  *
279  * @param matrix [out] Output array where the transformation matrix will be stored
280  * @param matrixSize Size of the provided matrix array
281  * @param buffer Source surface buffer containing the image data
282  * @param transform Rotation transformation type to be applied
283  * @param crop Rectangle defining the region of interest for cropping
284  */
ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,const Rect & crop)285 void SurfaceUtils::ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
286     sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, const Rect& crop)
287 {
288     if (buffer == nullptr) {
289         return;
290     }
291     float tx = 0.f;
292     float ty = 0.f;
293     float sx = 1.f;
294     float sy = 1.f;
295     switch (transform) {
296         case GraphicTransformType::GRAPHIC_ROTATE_90:
297             transform = GraphicTransformType::GRAPHIC_ROTATE_270;
298             break;
299         case GraphicTransformType::GRAPHIC_ROTATE_270:
300             transform = GraphicTransformType::GRAPHIC_ROTATE_90;
301             break;
302         default:
303             break;
304     }
305     std::array<float, TRANSFORM_MATRIX_ELE_COUNT> transformMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
306     ComputeTransformByMatrixV2(transform, &transformMatrix);
307 
308     float bufferWidth = buffer->GetWidth();
309     float bufferHeight = buffer->GetHeight();
310     bool changeFlag = false;
311     if (crop.w < bufferWidth && bufferWidth != 0) {
312         tx = (float(crop.x) / bufferWidth);
313         sx = (float(crop.w) / bufferWidth);
314         changeFlag = true;
315     }
316     if (crop.h < bufferHeight && bufferHeight != 0) {
317         ty = (float(bufferHeight - crop.y - crop.h) / bufferHeight);
318         sy = (float(crop.h) / bufferHeight);
319         changeFlag = true;
320     }
321     if (changeFlag) {
322         std::array<float, MATRIX_ARRAY_SIZE> cropMatrix = {sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1};
323         transformMatrix = MatrixProduct(cropMatrix, transformMatrix);
324     }
325 
326     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};
327     transformMatrix = MatrixProduct(flipV, transformMatrix);
328 
329     auto ret = memcpy_s(matrix, matrixSize * sizeof(float),
330                         transformMatrix.data(), sizeof(transformMatrix));
331     if (ret != EOK) {
332         BLOGE("memcpy_s failed, ret: %{public}d", ret);
333     }
334 }
335 
ComputeBufferMatrix(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,const Rect & crop)336 void SurfaceUtils::ComputeBufferMatrix(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
337     sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, const Rect& crop)
338 {
339     ComputeTransformMatrixV2(matrix, matrixSize, buffer, transform, crop);
340 }
341 
GetNativeWindow(uint64_t uniqueId)342 void* SurfaceUtils::GetNativeWindow(uint64_t uniqueId)
343 {
344     std::lock_guard<std::mutex> lockGuard(mutex_);
345     auto iter = nativeWindowCache_.find(uniqueId);
346     if (iter == nativeWindowCache_.end()) {
347         BLOGE("Cannot find nativeWindow, uniqueId %{public}" PRIu64 ".", uniqueId);
348         return nullptr;
349     }
350     return iter->second;
351 }
352 
AddNativeWindow(uint64_t uniqueId,void * nativeWidow)353 SurfaceError SurfaceUtils::AddNativeWindow(uint64_t uniqueId, void *nativeWidow)
354 {
355     if (nativeWidow == nullptr) {
356         return GSERROR_INVALID_ARGUMENTS;
357     }
358     std::lock_guard<std::mutex> lockGuard(mutex_);
359     if (nativeWindowCache_.count(uniqueId) == 0) {
360         nativeWindowCache_[uniqueId] = nativeWidow;
361         return GSERROR_OK;
362     }
363     BLOGD("the nativeWidow already existed, uniqueId %" PRIu64, uniqueId);
364     return GSERROR_OK;
365 }
366 
RemoveNativeWindow(uint64_t uniqueId)367 SurfaceError SurfaceUtils::RemoveNativeWindow(uint64_t uniqueId)
368 {
369     std::lock_guard<std::mutex> lockGuard(mutex_);
370     nativeWindowCache_.erase(uniqueId);
371     return GSERROR_OK;
372 }
373 } // namespace OHOS
374