• 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     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,const Rect & crop)160 void SurfaceUtils::ComputeTransformMatrix(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
161     sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, const 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 
248 /*
249  * Computes a transformation matrix for buffer rendering with crop and coordinate system conversion.
250  *
251  * The transformation process involves texture coordinate translation, coordinate system
252  * conversion, and scaling operations to achieve proper buffer rendering.
253  *
254  * Texture Coordinate Translation involves converting device coordinates to normalized
255  * texture coordinates [0,1], where:
256  * - tx = crop.x / bufferWidth represents X-axis translation ratio
257  * - ty = (bufferHeight - crop.y - crop.h) / bufferHeight handles Y-axis translation with flip
258  *
259  * Coordinate System Conversion handles the following:
260  * - Device coordinates with origin at top-left and Y-axis down
261  * - OpenGL coordinates with origin at bottom-left and Y-axis up
262  * The Y-axis calculation requires:
263  * - Moving origin from top to bottom using bufferHeight - crop.y
264  * - Accounting for crop region height by subtracting crop.h
265  * - Normalizing to [0,1] range by dividing with bufferHeight
266  *
267  * Scale calculation uses the following factors:
268  * - sx = crop.w / bufferWidth for X-axis scaling
269  * - sy = crop.h / bufferHeight for Y-axis scaling
270  *
271  * The final transformation matrix has the structure:
272  * | sx  0   0   0 |  (X-axis scaling)
273  * | 0   sy  0   0 |  (Y-axis scaling)
274  * | 0   0   1   0 |  (Z-axis unchanged)
275  * | tx  ty  0   1 |  (Translation)
276  *
277  * @param matrix [out] Output array where the transformation matrix will be stored
278  * @param matrixSize Size of the provided matrix array
279  * @param buffer Source surface buffer containing the image data
280  * @param transform Rotation transformation type to be applied
281  * @param crop Rectangle defining the region of interest for cropping
282  */
ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,const Rect & crop)283 void SurfaceUtils::ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
284     sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, const Rect& crop)
285 {
286     if (buffer == nullptr) {
287         return;
288     }
289     float tx = 0.f;
290     float ty = 0.f;
291     float sx = 1.f;
292     float sy = 1.f;
293     switch (transform) {
294         case GraphicTransformType::GRAPHIC_ROTATE_90:
295             transform = GraphicTransformType::GRAPHIC_ROTATE_270;
296             break;
297         case GraphicTransformType::GRAPHIC_ROTATE_270:
298             transform = GraphicTransformType::GRAPHIC_ROTATE_90;
299             break;
300         default:
301             break;
302     }
303     std::array<float, TRANSFORM_MATRIX_ELE_COUNT> transformMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
304     ComputeTransformByMatrixV2(transform, &transformMatrix);
305 
306     float bufferWidth = buffer->GetWidth();
307     float bufferHeight = buffer->GetHeight();
308     bool changeFlag = false;
309     if (crop.w < bufferWidth && bufferWidth != 0) {
310         tx = (float(crop.x) / bufferWidth);
311         sx = (float(crop.w) / bufferWidth);
312         changeFlag = true;
313     }
314     if (crop.h < bufferHeight && bufferHeight != 0) {
315         ty = (float(bufferHeight - crop.y - crop.h) / bufferHeight);
316         sy = (float(crop.h) / bufferHeight);
317         changeFlag = true;
318     }
319     if (changeFlag) {
320         std::array<float, MATRIX_ARRAY_SIZE> cropMatrix = {sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1};
321         transformMatrix = MatrixProduct(cropMatrix, transformMatrix);
322     }
323 
324     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};
325     transformMatrix = MatrixProduct(flipV, transformMatrix);
326 
327     auto ret = memcpy_s(matrix, matrixSize * sizeof(float),
328                         transformMatrix.data(), sizeof(transformMatrix));
329     if (ret != EOK) {
330         BLOGE("memcpy_s failed, ret: %{public}d", ret);
331     }
332 }
333 
ComputeBufferMatrix(float matrix[MATRIX_ARRAY_SIZE],uint32_t matrixSize,sptr<SurfaceBuffer> & buffer,GraphicTransformType & transform,const Rect & crop)334 void SurfaceUtils::ComputeBufferMatrix(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize,
335     sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, const Rect& crop)
336 {
337     ComputeTransformMatrixV2(matrix, matrixSize, buffer, transform, crop);
338 }
339 
GetNativeWindow(uint64_t uniqueId)340 void* SurfaceUtils::GetNativeWindow(uint64_t uniqueId)
341 {
342     std::lock_guard<std::mutex> lockGuard(mutex_);
343     if (nativeWindowCache_.count(uniqueId) == 0) {
344         BLOGE("Cannot find nativeWindow, uniqueId %" PRIu64 ".", uniqueId);
345         return nullptr;
346     }
347     return nativeWindowCache_[uniqueId];
348 }
349 
AddNativeWindow(uint64_t uniqueId,void * nativeWidow)350 SurfaceError SurfaceUtils::AddNativeWindow(uint64_t uniqueId, void *nativeWidow)
351 {
352     if (nativeWidow == nullptr) {
353         return GSERROR_INVALID_ARGUMENTS;
354     }
355     std::lock_guard<std::mutex> lockGuard(mutex_);
356     if (nativeWindowCache_.count(uniqueId) == 0) {
357         nativeWindowCache_[uniqueId] = nativeWidow;
358         return GSERROR_OK;
359     }
360     BLOGD("the nativeWidow already existed, uniqueId %" PRIu64, uniqueId);
361     return GSERROR_OK;
362 }
363 
RemoveNativeWindow(uint64_t uniqueId)364 SurfaceError SurfaceUtils::RemoveNativeWindow(uint64_t uniqueId)
365 {
366     std::lock_guard<std::mutex> lockGuard(mutex_);
367     nativeWindowCache_.erase(uniqueId);
368     return GSERROR_OK;
369 }
370 } // namespace OHOS
371