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 21namespace OHOS { 22using namespace HiviewDFX; 23static SurfaceUtils* instance = nullptr; 24static std::once_flag createFlag_; 25constexpr uint32_t MATRIX_ARRAY_SIZE = 16; 26 27SurfaceUtils* SurfaceUtils::GetInstance() 28{ 29 std::call_once(createFlag_, [&]() { 30 instance = new SurfaceUtils(); 31 }); 32 33 return instance; 34} 35 36SurfaceUtils::~SurfaceUtils() 37{ 38 instance = nullptr; 39 surfaceCache_.clear(); 40 nativeWindowCache_.clear(); 41} 42 43sptr<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 59SurfaceError 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 73SurfaceError 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 85std::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 112void 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 162void SurfaceUtils::ComputeTransformMatrix(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize, 163 sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, 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 200void 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 250void SurfaceUtils::ComputeTransformMatrixV2(float matrix[MATRIX_ARRAY_SIZE], uint32_t matrixSize, 251 sptr<SurfaceBuffer>& buffer, GraphicTransformType& transform, Rect& crop) 252{ 253 if (buffer == nullptr) { 254 return; 255 } 256 float tx = 0.f; 257 float ty = 0.f; 258 float sx = 1.f; 259 float sy = 1.f; 260 switch (transform) { 261 case GraphicTransformType::GRAPHIC_ROTATE_90: 262 transform = GraphicTransformType::GRAPHIC_ROTATE_270; 263 break; 264 case GraphicTransformType::GRAPHIC_ROTATE_270: 265 transform = GraphicTransformType::GRAPHIC_ROTATE_90; 266 break; 267 default: 268 break; 269 } 270 std::array<float, TRANSFORM_MATRIX_ELE_COUNT> transformMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 271 ComputeTransformByMatrixV2(transform, &transformMatrix); 272 273 float bufferWidth = buffer->GetWidth(); 274 float bufferHeight = buffer->GetHeight(); 275 bool changeFlag = false; 276 if (crop.w < bufferWidth && bufferWidth != 0) { 277 tx = (float(crop.x) / bufferWidth); 278 sx = (float(crop.w) / bufferWidth); 279 changeFlag = true; 280 } 281 if (crop.h < bufferHeight && bufferHeight != 0) { 282 ty = (float(bufferHeight - crop.y) / bufferHeight); 283 sy = (float(crop.h) / bufferHeight); 284 changeFlag = true; 285 } 286 if (changeFlag) { 287 std::array<float, MATRIX_ARRAY_SIZE> cropMatrix = {sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1}; 288 transformMatrix = MatrixProduct(cropMatrix, transformMatrix); 289 } 290 291 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}; 292 transformMatrix = MatrixProduct(flipV, transformMatrix); 293 294 auto ret = memcpy_s(matrix, matrixSize * sizeof(float), 295 transformMatrix.data(), sizeof(transformMatrix)); 296 if (ret != EOK) { 297 BLOGE("memcpy_s failed, ret: %{public}d", ret); 298 } 299} 300 301void* SurfaceUtils::GetNativeWindow(uint64_t uniqueId) 302{ 303 std::lock_guard<std::mutex> lockGuard(mutex_); 304 auto iter = nativeWindowCache_.find(uniqueId); 305 if (iter == nativeWindowCache_.end()) { 306 BLOGE("Cannot find nativeWindow, uniqueId %{public}" PRIu64 ".", uniqueId); 307 return nullptr; 308 } 309 return iter->second; 310} 311 312SurfaceError SurfaceUtils::AddNativeWindow(uint64_t uniqueId, void *nativeWidow) 313{ 314 if (nativeWidow == nullptr) { 315 return GSERROR_INVALID_ARGUMENTS; 316 } 317 std::lock_guard<std::mutex> lockGuard(mutex_); 318 if (nativeWindowCache_.count(uniqueId) == 0) { 319 nativeWindowCache_[uniqueId] = nativeWidow; 320 return GSERROR_OK; 321 } 322 BLOGD("the nativeWidow already existed, uniqueId %" PRIu64, uniqueId); 323 return GSERROR_OK; 324} 325 326SurfaceError SurfaceUtils::RemoveNativeWindow(uint64_t uniqueId) 327{ 328 std::lock_guard<std::mutex> lockGuard(mutex_); 329 nativeWindowCache_.erase(uniqueId); 330 return GSERROR_OK; 331} 332} // namespace OHOS 333