已合并
fix(egl): harden pixel map GL buffer handling #5794
yaozhupeng创建于 21 天前
fix(egl): harden pixel map GL buffer handling #5794
已合并
共 13 个文件变更+457-73
| @@ -932,7 +932,8 @@ static bool CheckPixelMapSLR(PixelMap &pixelMap, const Size &desiredSize, GPUTra | |||
| 932 | int32_t pixelBytes = pixelMap.GetPixelBytes(); | 932 | int32_t pixelBytes = pixelMap.GetPixelBytes(); |
| 933 | cond = pixelBytes <= 0; | 933 | cond = pixelBytes <= 0; |
| 934 | CHECK_ERROR_RETURN_RET_LOG(cond, false, "slr_gpu CheckPixelMapSLR invalid pixel bytes, %{public}d", pixelBytes); | 934 | CHECK_ERROR_RETURN_RET_LOG(cond, false, "slr_gpu CheckPixelMapSLR invalid pixel bytes, %{public}d", pixelBytes); |
| 935 | - cond = srcWidth > g_maxTextureSize || srcHeight > g_maxTextureSize; | 935 | + cond = srcWidth > g_maxTextureSize || srcHeight > g_maxTextureSize || |
| 936 | + desiredSize.width > g_maxTextureSize || desiredSize.height > g_maxTextureSize; | ||
| 936 | CHECK_INFO_RETURN_RET_LOG(cond, false, | 937 | CHECK_INFO_RETURN_RET_LOG(cond, false, |
| 937 | "slr_gpu CheckPixelMapSLR The maximum width and height cannot exceed:%{public}d.", g_maxTextureSize); | 938 | "slr_gpu CheckPixelMapSLR The maximum width and height cannot exceed:%{public}d.", g_maxTextureSize); |
| 938 | uint64_t dstSizeOverflow = static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(desiredSize.height) * | 939 | uint64_t dstSizeOverflow = static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(desiredSize.height) * |
| @@ -1011,18 +1012,30 @@ static bool PixelMapPostProcWithGL(PixelMap &sourcePixelMap, GPUTransformData &t | |||
| 1011 | if (dmaMode.isSourceDma && !dmaMode.isTargetDma) { | 1012 | if (dmaMode.isSourceDma && !dmaMode.isTargetDma) { |
| 1012 | IMAGE_LOGI("slr_gpu PixelMapPostProcWithGL no-padding DMA does not support GPU writeback, fallback output"); | 1013 | IMAGE_LOGI("slr_gpu PixelMapPostProcWithGL no-padding DMA does not support GPU writeback, fallback output"); |
| 1013 | } | 1014 | } |
| 1014 | - size_t buffersize = static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(desiredSize.height) * 4; | 1015 | + size_t outputRowBytes = 0; |
| 1015 | - MemoryData memoryData = {nullptr, buffersize, "PixelMapPostProcWithGL", desiredSize}; | 1016 | + size_t buffersize = 0; |
| 1017 | + cond = !PixelMapGlUtils::ComputeRowBytes(desiredSize.width, perPixelSize, outputRowBytes) || | ||
| 1018 | + !PixelMapGlUtils::ComputePackedBufferSize(desiredSize, perPixelSize, buffersize) || | ||
| 1019 | + outputRowBytes > static_cast<size_t>(std::numeric_limits<int32_t>::max()); | ||
| 1020 | + CHECK_ERROR_RETURN_RET_LOG(cond, false, "slr_gpu PixelMapPostProcWithGL invalid target buffer layout"); | ||
| 1021 | + MemoryData memoryData = { | ||
| 1022 | + nullptr, buffersize, "PixelMapPostProcWithGL", desiredSize, PixelFormat::RGBA_8888 | ||
| 1023 | + }; | ||
| 1016 | memoryData.usage = noPaddingUsage; | 1024 | memoryData.usage = noPaddingUsage; |
| 1017 | std::unique_ptr<AbsMemory> dstMemory = MemoryManager::CreateMemory(dmaMode.outputAllocType, memoryData); | 1025 | std::unique_ptr<AbsMemory> dstMemory = MemoryManager::CreateMemory(dmaMode.outputAllocType, memoryData); |
| 1018 | cond = dstMemory == nullptr || dstMemory->data.data == nullptr; | 1026 | cond = dstMemory == nullptr || dstMemory->data.data == nullptr; |
| 1019 | CHECK_ERROR_RETURN_RET_LOG(cond, false, "slr_gpu PixelMapPostProcWithGL dstMemory is null"); | 1027 | CHECK_ERROR_RETURN_RET_LOG(cond, false, "slr_gpu PixelMapPostProcWithGL dstMemory is null"); |
| 1020 | - int outputStride = 4 * desiredSize.width; | 1028 | + int outputStride = static_cast<int32_t>(outputRowBytes); |
| 1029 | + size_t outputBufferSize = dstMemory->data.size; | ||
| 1021 | if (dmaMode.isTargetDma) { | 1030 | if (dmaMode.isTargetDma) { |
| 1022 | SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*>(dstMemory->extend.data); | 1031 | SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*>(dstMemory->extend.data); |
| 1032 | + if (sbBuffer == nullptr) { | ||
| 1033 | + dstMemory->Release(); | ||
| 1034 | + IMAGE_LOGE("slr_gpu PixelMapPostProcWithGL target surface buffer is null"); | ||
| 1035 | + return false; | ||
| 1036 | + } | ||
| 1023 | outputStride = sbBuffer->GetStride(); | 1037 | outputStride = sbBuffer->GetStride(); |
| 1024 | - buffersize = static_cast<uint32_t>(static_cast<uint64_t>(sbBuffer->GetStride()) * | 1038 | + outputBufferSize = sbBuffer->GetSize(); |
| 1025 | - static_cast<uint64_t>(desiredSize.height)); | ||
| 1026 | } | 1039 | } |
| 1027 | PixelMapProgramManager::BuildShader(); | 1040 | PixelMapProgramManager::BuildShader(); |
| 1028 | bool ret = true; | 1041 | bool ret = true; |
| @@ -1033,6 +1046,7 @@ static bool PixelMapPostProcWithGL(PixelMap &sourcePixelMap, GPUTransformData &t | |||
| 1033 | } else { | 1046 | } else { |
| 1034 | trans.targetInfo_.stride = outputStride; | 1047 | trans.targetInfo_.stride = outputStride; |
| 1035 | trans.targetInfo_.pixelBytes = perPixelSize; | 1048 | trans.targetInfo_.pixelBytes = perPixelSize; |
| 1049 | + trans.targetInfo_.bufferSize = outputBufferSize; | ||
| 1036 | trans.targetInfo_.outdata = dstMemory->data.data; | 1050 | trans.targetInfo_.outdata = dstMemory->data.data; |
| 1037 | trans.targetInfo_.context = dstMemory->extend.data; | 1051 | trans.targetInfo_.context = dstMemory->extend.data; |
| 1038 | trans.glFormat = glFormat; | 1052 | trans.glFormat = glFormat; |
| @@ -156,18 +156,18 @@ enum TransformationType { | |||
| 156 | }; | 156 | }; |
| 157 | 157 | ||
| 158 | struct GlImageInfo { | 158 | struct GlImageInfo { |
| 159 | - Size size; | 159 | + Size size {}; |
| 160 | - int32_t stride; | 160 | + int32_t stride = 0; |
| 161 | - int pixelBytes; | 161 | + int pixelBytes = 0; |
| 162 | size_t bufferSize = 0; | 162 | size_t bufferSize = 0; |
| 163 | const uint8_t *addr = nullptr; | 163 | const uint8_t *addr = nullptr; |
| 164 | void *context = nullptr; | 164 | void *context = nullptr; |
| 165 | void *outdata = nullptr; | 165 | void *outdata = nullptr; |
| 166 | }; | 166 | }; |
| 167 | typedef struct GPUTransformData { | 167 | typedef struct GPUTransformData { |
| 168 | - float rotateDegreeZ; | 168 | + float rotateDegreeZ = 0.0f; |
| 169 | GlCommon::Mat4 rotateTrans; | 169 | GlCommon::Mat4 rotateTrans; |
| 170 | - TransformationType transformationType; | 170 | + TransformationType transformationType = static_cast<TransformationType>(0); |
| 171 | GLenum glFormat = GL_RGBA; | 171 | GLenum glFormat = GL_RGBA; |
| 172 | bool isDma = false; | 172 | bool isDma = false; |
| 173 | bool isSourceDma = false; | 173 | bool isSourceDma = false; |
| @@ -47,6 +47,7 @@ public: | |||
| 47 | static bool BuildShader(); | 47 | static bool BuildShader(); |
| 48 | 48 | ||
| 49 | private: | 49 | private: |
| 50 | + bool ValidateTransformData() const; | ||
| 50 | bool GLMakecurrent(bool needCurrent); | 51 | bool GLMakecurrent(bool needCurrent); |
| 51 | bool InitGLResource(); | 52 | bool InitGLResource(); |
| 52 | bool CreateEGLImage(OHNativeWindowBuffer *nativeBuffer, EGLImageKHR &eglImage, GLuint &imageTexId); | 53 | bool CreateEGLImage(OHNativeWindowBuffer *nativeBuffer, EGLImageKHR &eglImage, GLuint &imageTexId); |
| @@ -22,12 +22,12 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | - | ||
| 26 | 25 | ||
| 27 | 26 | ||
| 28 | 27 | ||
| 29 | 28 | ||
| 30 | 29 | ||
| 30 | + | ||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | 33 | ||
| @@ -36,6 +36,7 @@ namespace OHOS { | |||
| 36 | namespace Media { | 36 | namespace Media { |
| 37 | namespace PixelMapGlResource { | 37 | namespace PixelMapGlResource { |
| 38 | constexpr int32_t MAX_GL_TRANSFER_DIMENSION = 8192; | 38 | constexpr int32_t MAX_GL_TRANSFER_DIMENSION = 8192; |
| 39 | +constexpr int32_t BYTES_PER_PIXEL_RGBA = 4; | ||
| 39 | 40 | ||
| 40 | inline void DeleteTexture(GLuint &textureId) | 41 | inline void DeleteTexture(GLuint &textureId) |
| 41 | { | 42 | { |
| @@ -284,15 +285,39 @@ inline bool IsValidGlTransferSize(const Size &size) | |||
| 284 | 285 | ||
| 285 | inline bool ValidateStridedBufferSize(size_t bufferSize, int32_t stride, int32_t height, size_t rowBytes) | 286 | inline bool ValidateStridedBufferSize(size_t bufferSize, int32_t stride, int32_t height, size_t rowBytes) |
| 286 | { | 287 | { |
| 287 | - if (stride <= 0 || height <= 0 || rowBytes == 0 || rowBytes > static_cast<size_t>(stride)) { | 288 | + size_t requiredSize = 0; |
| 289 | + return PixelMapGlUtils::ComputeRequiredStridedBufferSize(stride, height, rowBytes, requiredSize) && | ||
| 290 | + requiredSize <= bufferSize; | ||
| 291 | +} | ||
| 292 | + | ||
| 293 | +inline bool ValidateTransferLayout(const Size &size, int32_t stride, int32_t pixelBytes, | ||
| 294 | + size_t &rowBytes, size_t &contiguousSize); | ||
| 295 | + | ||
| 296 | +inline bool ValidateCpuImageInfo(const GlImageInfo &imageInfo, GLenum glFormat) | ||
| 297 | +{ | ||
| 298 | + size_t rowBytes = 0; | ||
| 299 | + size_t contiguousSize = 0; | ||
| 300 | + return glFormat == GL_RGBA && imageInfo.pixelBytes == BYTES_PER_PIXEL_RGBA && | ||
| 301 | + ValidateTransferLayout(imageInfo.size, imageInfo.stride, imageInfo.pixelBytes, rowBytes, contiguousSize) && | ||
| 302 | + ValidateStridedBufferSize(imageInfo.bufferSize, imageInfo.stride, imageInfo.size.height, rowBytes); | ||
| 303 | +} | ||
| 304 | + | ||
| 305 | +struct SurfaceBufferInfo { | ||
| 306 | + Size size {}; | ||
| 307 | + int32_t stride = 0; | ||
| 308 | + size_t bufferSize = 0; | ||
| 309 | + int32_t format = 0; | ||
| 310 | +}; | ||
| 311 | + | ||
| 312 | +inline bool ValidateSurfaceBufferInfo(const GlImageInfo &imageInfo, const SurfaceBufferInfo &surfaceInfo, | ||
| 313 | + GLenum glFormat, int32_t expectedSurfaceFormat) | ||
| 314 | +{ | ||
| 315 | + if (imageInfo.size.width != surfaceInfo.size.width || imageInfo.size.height != surfaceInfo.size.height || | ||
| 316 | + imageInfo.stride != surfaceInfo.stride || imageInfo.bufferSize != surfaceInfo.bufferSize || | ||
| 317 | + surfaceInfo.format != expectedSurfaceFormat) { | ||
| 288 | return false; | 318 | return false; |
| 289 | } | 319 | } |
| 290 | - const size_t rowsBeforeLast = static_cast<size_t>(height - 1); | 320 | + return ValidateCpuImageInfo(imageInfo, glFormat); |
| 291 | - const size_t strideSize = static_cast<size_t>(stride); | ||
| 292 | - if (rowsBeforeLast > (std::numeric_limits<size_t>::max() - rowBytes) / strideSize) { | ||
| 293 | - return false; | ||
| 294 | - } | ||
| 295 | - return rowsBeforeLast * strideSize + rowBytes <= bufferSize; | ||
| 296 | } | 321 | } |
| 297 | 322 | ||
| 298 | inline bool CopyStridedToLinear(const uint8_t *src, size_t srcSize, int32_t srcStride, int32_t height, | 323 | inline bool CopyStridedToLinear(const uint8_t *src, size_t srcSize, int32_t srcStride, int32_t height, |
| @@ -317,19 +342,19 @@ inline bool CopyStridedToLinear(const uint8_t *src, size_t srcSize, int32_t srcS | |||
| 317 | } | 342 | } |
| 318 | 343 | ||
| 319 | inline bool CopyLinearToStrided(const char *src, size_t srcSize, size_t rowBytes, int32_t height, | 344 | inline bool CopyLinearToStrided(const char *src, size_t srcSize, size_t rowBytes, int32_t height, |
| 320 | - uint8_t *dst, int32_t dstStride) | 345 | + uint8_t *dst, size_t dstSize, int32_t dstStride) |
| 321 | { | 346 | { |
| 322 | if (src == nullptr || dst == nullptr || dstStride <= 0 || height <= 0 || rowBytes == 0) { | 347 | if (src == nullptr || dst == nullptr || dstStride <= 0 || height <= 0 || rowBytes == 0) { |
| 323 | return false; | 348 | return false; |
| 324 | } | 349 | } |
| 350 | + if (!ValidateStridedBufferSize(dstSize, dstStride, height, rowBytes) || | ||
| 351 | + static_cast<size_t>(height) > srcSize / rowBytes) { | ||
| 352 | + return false; | ||
| 353 | + } | ||
| 325 | for (int32_t i = 0; i < height; ++i) { | 354 | for (int32_t i = 0; i < height; ++i) { |
| 326 | const size_t srcOffset = rowBytes * static_cast<size_t>(i); | 355 | const size_t srcOffset = rowBytes * static_cast<size_t>(i); |
| 327 | const size_t dstOffset = static_cast<size_t>(dstStride) * static_cast<size_t>(i); | 356 | const size_t dstOffset = static_cast<size_t>(dstStride) * static_cast<size_t>(i); |
| 328 | - const size_t dstRemain = static_cast<size_t>(dstStride) * static_cast<size_t>(height - i); | 357 | + if (memcpy_s(dst + dstOffset, dstSize - dstOffset, src + srcOffset, rowBytes) != EOK) { |
| 329 | - if (srcOffset > srcSize || srcSize - srcOffset < rowBytes || dstRemain < rowBytes) { | ||
| 330 | - return false; | ||
| 331 | - } | ||
| 332 | - if (memcpy_s(dst + dstOffset, dstRemain, src + srcOffset, rowBytes) != EOK) { | ||
| 333 | return false; | 358 | return false; |
| 334 | } | 359 | } |
| 335 | } | 360 | } |
| @@ -0,0 +1,49 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (C) 2026 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 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace OHOS { | ||
| 24 | +namespace Media { | ||
| 25 | +namespace PixelMapGlShaderUtils { | ||
| 26 | +constexpr uint64_t MAX_SHADER_CACHE_FILE_SIZE = 64ULL * 1024ULL * 1024ULL; | ||
| 27 | + | ||
| 28 | +inline bool IsShaderCacheFileSizeValid(uint64_t fileSize, uint64_t metadataSize) | ||
| 29 | +{ | ||
| 30 | + return metadataSize > 0 && fileSize >= metadataSize && fileSize <= MAX_SHADER_CACHE_FILE_SIZE; | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +inline std::mutex &GetShaderCacheMutex() | ||
| 34 | +{ | ||
| 35 | + static std::mutex shaderCacheMutex; | ||
| 36 | + return shaderCacheMutex; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +template<typename Function> | ||
| 40 | +bool WithShaderCacheLock(Function &&function) | ||
| 41 | +{ | ||
| 42 | + std::lock_guard<std::mutex> lock(GetShaderCacheMutex()); | ||
| 43 | + return std::forward<Function>(function)(); | ||
| 44 | +} | ||
| 45 | +} // namespace PixelMapGlShaderUtils | ||
| 46 | +} // namespace Media | ||
| 47 | +} // namespace OHOS | ||
| 48 | + | ||
| 49 | + | ||
| @@ -87,6 +87,22 @@ inline bool ComputePackedBufferSize(const Size &size, int32_t pixelBytes, size_t | |||
| 87 | return true; | 87 | return true; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | +inline bool ComputeRequiredStridedBufferSize(int32_t stride, int32_t height, size_t rowBytes, | ||
| 91 | + size_t &requiredSize) | ||
| 92 | +{ | ||
| 93 | + requiredSize = 0; | ||
| 94 | + if (stride <= 0 || height <= 0 || rowBytes == 0 || rowBytes > static_cast<size_t>(stride)) { | ||
| 95 | + return false; | ||
| 96 | + } | ||
| 97 | + const size_t rowsBeforeLast = static_cast<size_t>(height - 1); | ||
| 98 | + const size_t strideSize = static_cast<size_t>(stride); | ||
| 99 | + if (rowsBeforeLast > (std::numeric_limits<size_t>::max() - rowBytes) / strideSize) { | ||
| 100 | + return false; | ||
| 101 | + } | ||
| 102 | + requiredSize = rowsBeforeLast * strideSize + rowBytes; | ||
| 103 | + return true; | ||
| 104 | +} | ||
| 105 | + | ||
| 90 | inline bool ValidateImageLayout(const Size &size, int32_t stride, int32_t pixelBytes, | 106 | inline bool ValidateImageLayout(const Size &size, int32_t stride, int32_t pixelBytes, |
| 91 | size_t &rowBytes, size_t &contiguousSize) | 107 | size_t &rowBytes, size_t &contiguousSize) |
| 92 | { | 108 | { |
| @@ -36,6 +36,16 @@ inline bool CanCreateProgram(int32_t totalInstances, int32_t maxInstanceCount) | |||
| 36 | return totalInstances >= 0 && totalInstances < maxInstanceCount; | 36 | return totalInstances >= 0 && totalInstances < maxInstanceCount; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | +inline bool TryReserveProgram(int32_t &totalInstances, int32_t maxInstanceCount, int32_t &reservedTotal) | ||
| 40 | +{ | ||
| 41 | + if (!CanCreateProgram(totalInstances, maxInstanceCount)) { | ||
| 42 | + return false; | ||
| 43 | + } | ||
| 44 | + totalInstances++; | ||
| 45 | + reservedTotal = totalInstances; | ||
| 46 | + return true; | ||
| 47 | +} | ||
| 48 | + | ||
| 39 | inline bool ShouldWaitForAvailableProgram(int32_t totalInstances, int32_t maxInstanceCount, size_t availableInstances) | 49 | inline bool ShouldWaitForAvailableProgram(int32_t totalInstances, int32_t maxInstanceCount, size_t availableInstances) |
| 40 | { | 50 | { |
| 41 | return availableInstances == 0 && totalInstances >= maxInstanceCount; | 51 | return availableInstances == 0 && totalInstances >= maxInstanceCount; |
| @@ -67,6 +67,25 @@ bool RestoreEglCurrentState(const EglCurrentState &state, EGLDisplay fallbackDis | |||
| 67 | } | 67 | } |
| 68 | return eglMakeCurrent(restoreDisplay, state.drawSurface, state.readSurface, state.context) == EGL_TRUE; | 68 | return eglMakeCurrent(restoreDisplay, state.drawSurface, state.readSurface, state.context) == EGL_TRUE; |
| 69 | } | 69 | } |
| 70 | + | ||
| 71 | +bool GetExpectedSurfaceFormat(GLenum glFormat, int32_t &surfaceFormat) | ||
| 72 | +{ | ||
| 73 | + if (glFormat != GL_RGBA) { | ||
| 74 | + return false; | ||
| 75 | + } | ||
| 76 | + surfaceFormat = GRAPHIC_PIXEL_FMT_RGBA_8888; | ||
| 77 | + return true; | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +PixelMapGlResource::SurfaceBufferInfo GetSurfaceBufferInfo(const SurfaceBuffer &surfaceBuffer) | ||
| 81 | +{ | ||
| 82 | + return { | ||
| 83 | + .size = { surfaceBuffer.GetWidth(), surfaceBuffer.GetHeight() }, | ||
| 84 | + .stride = surfaceBuffer.GetStride(), | ||
| 85 | + .bufferSize = surfaceBuffer.GetSize(), | ||
| 86 | + .format = surfaceBuffer.GetFormat(), | ||
| 87 | + }; | ||
| 88 | +} | ||
| 70 | std::once_flag g_shaderInitFlag; | 89 | std::once_flag g_shaderInitFlag; |
| 71 | bool g_shaderBuildResult = false; | 90 | bool g_shaderBuildResult = false; |
| 72 | } // namespace | 91 | } // namespace |
| @@ -86,6 +105,49 @@ void PixelMapGLPostProcProgram::SetGPUTransformData(GPUTransformData &transformD | |||
| 86 | this->transformData_ = transformData; | 105 | this->transformData_ = transformData; |
| 87 | } | 106 | } |
| 88 | 107 | ||
| 108 | +bool PixelMapGLPostProcProgram::ValidateTransformData() const | ||
| 109 | +{ | ||
| 110 | + if (transformData_.transformationType != TransformationType::SCALE && | ||
| 111 | + transformData_.transformationType != TransformationType::ROTATE) { | ||
| 112 | + IMAGE_LOGE("slr_gpu %{public}s invalid transformation type", __func__); | ||
| 113 | + return false; | ||
| 114 | + } | ||
| 115 | + if (transformData_.isDma != (transformData_.isSourceDma || transformData_.isTargetDma)) { | ||
| 116 | + IMAGE_LOGE("slr_gpu %{public}s inconsistent DMA flags", __func__); | ||
| 117 | + return false; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + if (transformData_.isSourceDma) { | ||
| 121 | + const auto *surfaceBuffer = reinterpret_cast<const SurfaceBuffer *>(transformData_.sourceInfo_.context); | ||
| 122 | + int32_t expectedSurfaceFormat = 0; | ||
| 123 | + if (surfaceBuffer == nullptr || !GetExpectedSurfaceFormat(transformData_.glFormat, expectedSurfaceFormat) || | ||
| 124 | + !PixelMapGlResource::ValidateSurfaceBufferInfo(transformData_.sourceInfo_, | ||
| 125 | + GetSurfaceBufferInfo(*surfaceBuffer), transformData_.glFormat, expectedSurfaceFormat)) { | ||
| 126 | + IMAGE_LOGE("slr_gpu %{public}s invalid source DMA metadata", __func__); | ||
| 127 | + return false; | ||
| 128 | + } | ||
| 129 | + } else if (transformData_.sourceInfo_.addr == nullptr || | ||
| 130 | + !PixelMapGlResource::ValidateCpuImageInfo(transformData_.sourceInfo_, transformData_.glFormat)) { | ||
| 131 | + IMAGE_LOGE("slr_gpu %{public}s invalid source CPU buffer", __func__); | ||
| 132 | + return false; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + if (transformData_.isTargetDma) { | ||
| 136 | + const auto *surfaceBuffer = reinterpret_cast<const SurfaceBuffer *>(transformData_.targetInfo_.context); | ||
| 137 | + if (surfaceBuffer == nullptr || | ||
| 138 | + !PixelMapGlResource::ValidateSurfaceBufferInfo(transformData_.targetInfo_, | ||
| 139 | + GetSurfaceBufferInfo(*surfaceBuffer), GL_RGBA, GRAPHIC_PIXEL_FMT_RGBA_8888)) { | ||
| 140 | + IMAGE_LOGE("slr_gpu %{public}s invalid target DMA metadata", __func__); | ||
| 141 | + return false; | ||
| 142 | + } | ||
| 143 | + } else if (transformData_.targetInfo_.outdata == nullptr || | ||
| 144 | + !PixelMapGlResource::ValidateCpuImageInfo(transformData_.targetInfo_, GL_RGBA)) { | ||
| 145 | + IMAGE_LOGE("slr_gpu %{public}s invalid target CPU buffer", __func__); | ||
| 146 | + return false; | ||
| 147 | + } | ||
| 148 | + return true; | ||
| 149 | +} | ||
| 150 | + | ||
| 89 | void PixelMapGLPostProcProgram::Clear() noexcept | 151 | void PixelMapGLPostProcProgram::Clear() noexcept |
| 90 | { | 152 | { |
| 91 | if (renderContext_ == nullptr || renderContext_->eglContext_ == EGL_NO_CONTEXT) { | 153 | if (renderContext_ == nullptr || renderContext_->eglContext_ == EGL_NO_CONTEXT) { |
| @@ -497,6 +559,11 @@ bool PixelMapGLPostProcProgram::ReadEndData(char *targetData, GLuint &writeTexId | |||
| 497 | IMAGE_LOGE("slr_gpu %{public}s invalid target image layout", __func__); | 559 | IMAGE_LOGE("slr_gpu %{public}s invalid target image layout", __func__); |
| 498 | return false; | 560 | return false; |
| 499 | } | 561 | } |
| 562 | + if (!PixelMapGlResource::ValidateStridedBufferSize(transformData_.targetInfo_.bufferSize, | ||
| 563 | + transformData_.targetInfo_.stride, targetSize.height, rowBytes)) { | ||
| 564 | + IMAGE_LOGE("slr_gpu %{public}s target buffer is too small", __func__); | ||
| 565 | + return false; | ||
| 566 | + } | ||
| 500 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, writeTexId, 0); | 567 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, writeTexId, 0); |
| 501 | if (static_cast<size_t>(transformData_.targetInfo_.stride) == rowBytes) { | 568 | if (static_cast<size_t>(transformData_.targetInfo_.stride) == rowBytes) { |
| 502 | glReadPixels(0, 0, targetSize.width, targetSize.height, GL_RGBA, GL_UNSIGNED_BYTE, targetData); | 569 | glReadPixels(0, 0, targetSize.width, targetSize.height, GL_RGBA, GL_UNSIGNED_BYTE, targetData); |
| @@ -514,7 +581,8 @@ bool PixelMapGLPostProcProgram::ReadEndData(char *targetData, GLuint &writeTexId | |||
| 514 | return false; | 581 | return false; |
| 515 | } | 582 | } |
| 516 | if (!PixelMapGlResource::CopyLinearToStrided(mapPointer, contiguousSize, rowBytes, targetSize.height, | 583 | if (!PixelMapGlResource::CopyLinearToStrided(mapPointer, contiguousSize, rowBytes, targetSize.height, |
| 517 | - reinterpret_cast<uint8_t *>(targetData), transformData_.targetInfo_.stride)) { | 584 | + reinterpret_cast<uint8_t *>(targetData), transformData_.targetInfo_.bufferSize, |
| 585 | + transformData_.targetInfo_.stride)) { | ||
| 518 | IMAGE_LOGE("slr_gpu %{public}s CopyLinearToStrided fail", __func__); | 586 | IMAGE_LOGE("slr_gpu %{public}s CopyLinearToStrided fail", __func__); |
| 519 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER); | 587 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER); |
| 520 | return false; | 588 | return false; |
| @@ -571,6 +639,9 @@ bool PixelMapGLPostProcProgram::ReadEndDMAData(void *surfaceBuffer, GLuint &writ | |||
| 571 | 639 | ||
| 572 | bool PixelMapGLPostProcProgram::Execute() | 640 | bool PixelMapGLPostProcProgram::Execute() |
| 573 | { | 641 | { |
| 642 | + if (!ValidateTransformData()) { | ||
| 643 | + return false; | ||
| 644 | + } | ||
| 574 | if (!GLMakecurrent(true)) { | 645 | if (!GLMakecurrent(true)) { |
| 575 | IMAGE_LOGE("slr_gpu GenProcEndData cannot makecurent with opengl"); | 646 | IMAGE_LOGE("slr_gpu GenProcEndData cannot makecurent with opengl"); |
| 576 | return false; | 647 | return false; |
| @@ -15,23 +15,23 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 21 | + | ||
| 20 | 22 | ||
| 21 | 23 | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 26 | + | ||
| 24 | 27 | ||
| 25 | 28 | ||
| 26 | 29 | ||
| 30 | + | ||
| 27 | 31 | ||
| 28 | 32 | ||
| 29 | 33 | ||
| 30 | 34 | ||
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - | ||
| 35 | 35 | ||
| 36 | 36 | ||
| 37 | 37 | ||
| @@ -83,41 +83,60 @@ static bool checkProgram(GLuint &programId) | |||
| 83 | return true; | 83 | return true; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | -static bool loadShaderFromFile(unsigned char*&shaderBinary, GLenum &binaryFormat, GLuint &binarySize, | 86 | +static bool ReadFileFully(int fd, unsigned char *data, size_t size) |
| 87 | +{ | ||
| 88 | + size_t totalRead = 0; | ||
| 89 | + while (totalRead < size) { | ||
| 90 | + errno = 0; | ||
| 91 | + const ssize_t readLen = read(fd, data + totalRead, size - totalRead); | ||
| 92 | + if (readLen > 0) { | ||
| 93 | + totalRead += static_cast<size_t>(readLen); | ||
| 94 | + continue; | ||
| 95 | + } | ||
| 96 | + if (readLen < 0 && errno == EINTR) { | ||
| 97 | + continue; | ||
| 98 | + } | ||
| 99 | + return false; | ||
| 100 | + } | ||
| 101 | + return true; | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +static bool loadShaderFromFileLocked(unsigned char*&shaderBinary, GLenum &binaryFormat, GLuint &binarySize, | ||
| 87 | const char* filePath, int version) | 105 | const char* filePath, int version) |
| 88 | { | 106 | { |
| 89 | if (shaderBinary != nullptr) { | 107 | if (shaderBinary != nullptr) { |
| 90 | return true; | 108 | return true; |
| 91 | } | 109 | } |
| 92 | 110 | ||
| 93 | - struct stat fileStat; | ||
| 94 | - if (stat(filePath, &fileStat) != 0) { | ||
| 95 | - IMAGE_LOGE("slr_gpu shader cache is not exist! error %{public}d", errno); | ||
| 96 | - return false; | ||
| 97 | - } | ||
| 98 | - | ||
| 99 | - const size_t minSize = sizeof(GLenum) + sizeof(version); | ||
| 100 | - if (fileStat.st_size < 0) { | ||
| 101 | - IMAGE_LOGE("slr_gpu shader cache file size failed! size:%{public}lld", | ||
| 102 | - static_cast<long long>(fileStat.st_size)); | ||
| 103 | - return false; | ||
| 104 | - } | ||
| 105 | - const uint64_t fileSize64 = static_cast<uint64_t>(fileStat.st_size); | ||
| 106 | - if (fileSize64 < minSize) { | ||
| 107 | - IMAGE_LOGE("slr_gpu shader cache file size failed! size:%{public}llu", | ||
| 108 | - static_cast<unsigned long long>(fileSize64)); | ||
| 109 | - return false; | ||
| 110 | - } | ||
| 111 | - | ||
| 112 | int binaryFd = open(filePath, O_RDONLY); | 111 | int binaryFd = open(filePath, O_RDONLY); |
| 113 | if (binaryFd < 0) { | 112 | if (binaryFd < 0) { |
| 114 | IMAGE_LOGE("slr_gpu shader cache open failed! error %{public}d", errno); | 113 | IMAGE_LOGE("slr_gpu shader cache open failed! error %{public}d", errno); |
| 115 | return false; | 114 | return false; |
| 116 | } | 115 | } |
| 117 | 116 | ||
| 118 | - if (fileSize64 > std::numeric_limits<size_t>::max()) { | 117 | + struct stat fileStat; |
| 118 | + if (fstat(binaryFd, &fileStat) != 0) { | ||
| 119 | + const int statError = errno; | ||
| 119 | close(binaryFd); | 120 | close(binaryFd); |
| 120 | - IMAGE_LOGE("slr_gpu shader cache file too large for platform size_t"); | 121 | + IMAGE_LOGE("slr_gpu shader cache fstat failed! error %{public}d", statError); |
| 122 | + return false; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + const size_t minSize = sizeof(GLenum) + sizeof(version); | ||
| 126 | + if (fileStat.st_size < 0) { | ||
| 127 | + close(binaryFd); | ||
| 128 | + IMAGE_LOGE("slr_gpu shader cache file size failed! size:%{public}lld", | ||
| 129 | + static_cast<long long>(fileStat.st_size)); | ||
| 130 | + return false; | ||
| 131 | + } | ||
| 132 | + const uint64_t fileSize64 = static_cast<uint64_t>(fileStat.st_size); | ||
| 133 | + const uint64_t maxSize = static_cast<uint64_t>(std::numeric_limits<size_t>::max()); | ||
| 134 | + const uint64_t maxReadSize = static_cast<uint64_t>(std::numeric_limits<ssize_t>::max()); | ||
| 135 | + if (!PixelMapGlShaderUtils::IsShaderCacheFileSizeValid(fileSize64, minSize) || | ||
| 136 | + fileSize64 > maxSize || fileSize64 > maxReadSize) { | ||
| 137 | + close(binaryFd); | ||
| 138 | + IMAGE_LOGE("slr_gpu shader cache file size failed! size:%{public}llu", | ||
| 139 | + static_cast<unsigned long long>(fileSize64)); | ||
| 121 | return false; | 140 | return false; |
| 122 | } | 141 | } |
| 123 | const size_t fileSize = static_cast<size_t>(fileSize64); | 142 | const size_t fileSize = static_cast<size_t>(fileSize64); |
| @@ -126,17 +145,13 @@ static bool loadShaderFromFile(unsigned char*&shaderBinary, GLenum &binaryFormat | |||
| 126 | IMAGE_LOGE("slr_gpu shader cache file too large"); | 145 | IMAGE_LOGE("slr_gpu shader cache file too large"); |
| 127 | return false; | 146 | return false; |
| 128 | } | 147 | } |
| 129 | - std::unique_ptr<unsigned char[]> binaryData(new (std::nothrow) unsigned char[fileSize]); | 148 | + auto binaryData = std::make_unique<unsigned char[]>(fileSize); |
| 130 | - if (binaryData == nullptr) { | 149 | + const bool readSuccess = ReadFileFully(binaryFd, binaryData.get(), fileSize); |
| 131 | - close(binaryFd); | 150 | + const int readError = errno; |
| 132 | - return false; | ||
| 133 | - } | ||
| 134 | - ssize_t readLen = read(binaryFd, binaryData.get(), fileSize); | ||
| 135 | close(binaryFd); | 151 | close(binaryFd); |
| 136 | 152 | ||
| 137 | - if (readLen != static_cast<ssize_t>(fileSize)) { | 153 | + if (!readSuccess) { |
| 138 | - IMAGE_LOGE("slr_gpu shader cache read failed! error " | 154 | + IMAGE_LOGE("slr_gpu shader cache read failed! error %{public}d", readError); |
| 139 | - "%{public}d readnum %{public}zd", errno, readLen); | ||
| 140 | return false; | 155 | return false; |
| 141 | } | 156 | } |
| 142 | binarySize = static_cast<uint32_t>(fileSize - minSize); | 157 | binarySize = static_cast<uint32_t>(fileSize - minSize); |
| @@ -157,7 +172,15 @@ static bool loadShaderFromFile(unsigned char*&shaderBinary, GLenum &binaryFormat | |||
| 157 | return true; | 172 | return true; |
| 158 | } | 173 | } |
| 159 | 174 | ||
| 160 | -bool saveShaderToFile(unsigned char*&shaderBinary, GLenum &binaryFormat, | 175 | +static bool loadShaderFromFile(unsigned char*&shaderBinary, GLenum &binaryFormat, GLuint &binarySize, |
| 176 | + const char* filePath, int version) | ||
| 177 | +{ | ||
| 178 | + return PixelMapGlShaderUtils::WithShaderCacheLock([&]() { | ||
| 179 | + return loadShaderFromFileLocked(shaderBinary, binaryFormat, binarySize, filePath, version); | ||
| 180 | + }); | ||
| 181 | +} | ||
| 182 | + | ||
| 183 | +static bool saveShaderToFileLocked(unsigned char*&shaderBinary, GLenum &binaryFormat, | ||
| 161 | GLuint &binarySize, const char* filePath, GLuint &programId) | 184 | GLuint &binarySize, const char* filePath, GLuint &programId) |
| 162 | { | 185 | { |
| 163 | if (shaderBinary == nullptr) { | 186 | if (shaderBinary == nullptr) { |
| @@ -197,6 +220,14 @@ bool saveShaderToFile(unsigned char*&shaderBinary, GLenum &binaryFormat, | |||
| 197 | return true; | 220 | return true; |
| 198 | } | 221 | } |
| 199 | 222 | ||
| 223 | +bool saveShaderToFile(unsigned char*&shaderBinary, GLenum &binaryFormat, | ||
| 224 | + GLuint &binarySize, const char* filePath, GLuint &programId) | ||
| 225 | +{ | ||
| 226 | + return PixelMapGlShaderUtils::WithShaderCacheLock([&]() { | ||
| 227 | + return saveShaderToFileLocked(shaderBinary, binaryFormat, binarySize, filePath, programId); | ||
| 228 | + }); | ||
| 229 | +} | ||
| 230 | + | ||
| 200 | Shader::Shader() | 231 | Shader::Shader() |
| 201 | { | 232 | { |
| 202 | glGenFramebuffers(1, &writeFbo_); | 233 | glGenFramebuffers(1, &writeFbo_); |
| @@ -62,6 +62,7 @@ PixelMapGLPostProcProgram* PixelMapProgramManager::GetProgram() | |||
| 62 | ImageTrace imageTrace("PixelMapProgramManager::GetProgram"); | 62 | ImageTrace imageTrace("PixelMapProgramManager::GetProgram"); |
| 63 | PixelMapGLPostProcProgram *program = nullptr; | 63 | PixelMapGLPostProcProgram *program = nullptr; |
| 64 | bool needCreateProgram = false; | 64 | bool needCreateProgram = false; |
| 65 | + int32_t reservedTotal = 0; | ||
| 65 | std::unique_lock<std::mutex> locker(g_contextMutex); | 66 | std::unique_lock<std::mutex> locker(g_contextMutex); |
| 66 | g_lastTouchInstanceTime = GetMonotonicTimeSec(); | 67 | g_lastTouchInstanceTime = GetMonotonicTimeSec(); |
| 67 | program = TakeAvailableProgramLocked(); | 68 | program = TakeAvailableProgramLocked(); |
| @@ -84,8 +85,7 @@ PixelMapGLPostProcProgram* PixelMapProgramManager::GetProgram() | |||
| 84 | return program; | 85 | return program; |
| 85 | } | 86 | } |
| 86 | } | 87 | } |
| 87 | - if (PixelMapProgramManagerUtils::CanCreateProgram(g_nowInstanceNum, MAX_GL_INSTANCE_NUM)) { | 88 | + if (PixelMapProgramManagerUtils::TryReserveProgram(g_nowInstanceNum, MAX_GL_INSTANCE_NUM, reservedTotal)) { |
| 88 | - g_nowInstanceNum++; | ||
| 89 | needCreateProgram = true; | 89 | needCreateProgram = true; |
| 90 | } | 90 | } |
| 91 | locker.unlock(); | 91 | locker.unlock(); |
| @@ -98,8 +98,7 @@ PixelMapGLPostProcProgram* PixelMapProgramManager::GetProgram() | |||
| 98 | g_dataCond.notify_one(); | 98 | g_dataCond.notify_one(); |
| 99 | return nullptr; | 99 | return nullptr; |
| 100 | } else { | 100 | } else { |
| 101 | - const int num = g_nowInstanceNum; | 101 | + IMAGE_LOGI("slr_gpu %{public}s new instance(%{public}d)", __func__, reservedTotal); |
| 102 | - IMAGE_LOGI("slr_gpu %{public}s new instance(%{public}d)", __func__, num); | ||
| 103 | program = newProgram.release(); | 102 | program = newProgram.release(); |
| 104 | } | 103 | } |
| 105 | } | 104 | } |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -32,6 +33,7 @@ | |||
| 32 | 33 | ||
| 33 | 34 | ||
| 34 | 35 | ||
| 36 | + | ||
| 35 | 37 | ||
| 36 | 38 | ||
| 37 | 39 | ||
| @@ -120,6 +122,10 @@ HWTEST_F(EglImageHelperTest, PixelMapGlCommonTransformDefaultsTest001, TestSize. | |||
| 120 | EXPECT_FALSE(transformData.isDma); | 122 | EXPECT_FALSE(transformData.isDma); |
| 121 | EXPECT_FALSE(transformData.isSourceDma); | 123 | EXPECT_FALSE(transformData.isSourceDma); |
| 122 | EXPECT_FALSE(transformData.isTargetDma); | 124 | EXPECT_FALSE(transformData.isTargetDma); |
| 125 | + EXPECT_EQ(transformData.transformationType, static_cast<TransformationType>(0)); | ||
| 126 | + EXPECT_EQ(transformData.sourceInfo_.size.width, 0); | ||
| 127 | + EXPECT_EQ(transformData.sourceInfo_.stride, 0); | ||
| 128 | + EXPECT_EQ(transformData.sourceInfo_.pixelBytes, 0); | ||
| 123 | EXPECT_EQ(transformData.sourceInfo_.addr, nullptr); | 129 | EXPECT_EQ(transformData.sourceInfo_.addr, nullptr); |
| 124 | EXPECT_EQ(transformData.sourceInfo_.context, nullptr); | 130 | EXPECT_EQ(transformData.sourceInfo_.context, nullptr); |
| 125 | EXPECT_EQ(transformData.sourceInfo_.bufferSize, 0); | 131 | EXPECT_EQ(transformData.sourceInfo_.bufferSize, 0); |
| @@ -187,6 +193,51 @@ HWTEST_F(EglImageHelperTest, PixelMapGlResourceValidationTest001, TestSize.Level | |||
| 187 | EXPECT_FALSE(PixelMapGlResource::ValidateTransferLayout( | 193 | EXPECT_FALSE(PixelMapGlResource::ValidateTransferLayout( |
| 188 | Size { PixelMapGlResource::MAX_GL_TRANSFER_DIMENSION + 1, 1 }, | 194 | Size { PixelMapGlResource::MAX_GL_TRANSFER_DIMENSION + 1, 1 }, |
| 189 | (PixelMapGlResource::MAX_GL_TRANSFER_DIMENSION + 1) * 4, 4, rowBytes, contiguousSize)); | 195 | (PixelMapGlResource::MAX_GL_TRANSFER_DIMENSION + 1) * 4, 4, rowBytes, contiguousSize)); |
| 196 | + size_t requiredSize = 0; | ||
| 197 | + EXPECT_TRUE(PixelMapGlUtils::ComputeRequiredStridedBufferSize(16, 3, 8, requiredSize)); | ||
| 198 | + EXPECT_EQ(requiredSize, 40U); | ||
| 199 | + EXPECT_FALSE(PixelMapGlUtils::ComputeRequiredStridedBufferSize(7, 3, 8, requiredSize)); | ||
| 200 | + EXPECT_FALSE(PixelMapGlUtils::ComputeRequiredStridedBufferSize(16, 0, 8, requiredSize)); | ||
| 201 | + | ||
| 202 | + GlImageInfo imageInfo {}; | ||
| 203 | + imageInfo.size = { 2, 2 }; | ||
| 204 | + imageInfo.stride = 8; | ||
| 205 | + imageInfo.pixelBytes = 4; | ||
| 206 | + imageInfo.bufferSize = 16; | ||
| 207 | + EXPECT_TRUE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_RGBA)); | ||
| 208 | + imageInfo.bufferSize = 15; | ||
| 209 | + EXPECT_FALSE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_RGBA)); | ||
| 210 | + imageInfo.bufferSize = 16; | ||
| 211 | + imageInfo.pixelBytes = 1; | ||
| 212 | + EXPECT_FALSE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_RGBA)); | ||
| 213 | + EXPECT_FALSE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_INVALID_ENUM)); | ||
| 214 | + | ||
| 215 | + imageInfo.pixelBytes = 4; | ||
| 216 | + PixelMapGlResource::SurfaceBufferInfo surfaceInfo { | ||
| 217 | + .size = { 2, 2 }, | ||
| 218 | + .stride = 8, | ||
| 219 | + .bufferSize = 16, | ||
| 220 | + .format = GRAPHIC_PIXEL_FMT_RGBA_8888, | ||
| 221 | + }; | ||
| 222 | + EXPECT_TRUE(PixelMapGlResource::ValidateSurfaceBufferInfo( | ||
| 223 | + imageInfo, surfaceInfo, GL_RGBA, GRAPHIC_PIXEL_FMT_RGBA_8888)); | ||
| 224 | + surfaceInfo.size.width = 1; | ||
| 225 | + EXPECT_FALSE(PixelMapGlResource::ValidateSurfaceBufferInfo( | ||
| 226 | + imageInfo, surfaceInfo, GL_RGBA, GRAPHIC_PIXEL_FMT_RGBA_8888)); | ||
| 227 | + surfaceInfo.size.width = 2; | ||
| 228 | + surfaceInfo.stride = 12; | ||
| 229 | + EXPECT_FALSE(PixelMapGlResource::ValidateSurfaceBufferInfo( | ||
| 230 | + imageInfo, surfaceInfo, GL_RGBA, GRAPHIC_PIXEL_FMT_RGBA_8888)); | ||
| 231 | + surfaceInfo.stride = 8; | ||
| 232 | + imageInfo.bufferSize = 15; | ||
| 233 | + surfaceInfo.bufferSize = 15; | ||
| 234 | + EXPECT_FALSE(PixelMapGlResource::ValidateSurfaceBufferInfo( | ||
| 235 | + imageInfo, surfaceInfo, GL_RGBA, GRAPHIC_PIXEL_FMT_RGBA_8888)); | ||
| 236 | + imageInfo.bufferSize = 16; | ||
| 237 | + surfaceInfo.bufferSize = 16; | ||
| 238 | + surfaceInfo.format = GRAPHIC_PIXEL_FMT_RGB_888; | ||
| 239 | + EXPECT_FALSE(PixelMapGlResource::ValidateSurfaceBufferInfo( | ||
| 240 | + imageInfo, surfaceInfo, GL_RGBA, GRAPHIC_PIXEL_FMT_RGBA_8888)); | ||
| 190 | 241 | ||
| 191 | PixelMapGlResource::ScopedNativeWindowBuffer nativeBuffer; | 242 | PixelMapGlResource::ScopedNativeWindowBuffer nativeBuffer; |
| 192 | EXPECT_EQ(nativeBuffer.Get(), nullptr); | 243 | EXPECT_EQ(nativeBuffer.Get(), nullptr); |
| @@ -216,9 +267,14 @@ HWTEST_F(EglImageHelperTest, PixelMapGlResourceCopyFailureTest001, TestSize.Leve | |||
| 216 | 267 | ||
| 217 | const char linear[16] = {0}; | 268 | const char linear[16] = {0}; |
| 218 | uint8_t strided[12] = {0}; | 269 | uint8_t strided[12] = {0}; |
| 219 | - EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided(nullptr, sizeof(linear), rowBytes, 2, strided, 8)); | 270 | + EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided( |
| 220 | - EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided(linear, 4, rowBytes, 2, strided, 8)); | 271 | + nullptr, sizeof(linear), rowBytes, 2, strided, sizeof(strided), 8)); |
| 221 | - EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided(linear, sizeof(linear), rowBytes, 2, strided, 4)); | 272 | + EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided( |
| 273 | + linear, 4, rowBytes, 2, strided, sizeof(strided), 8)); | ||
| 274 | + EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided( | ||
| 275 | + linear, sizeof(linear), rowBytes, 2, strided, sizeof(strided), 4)); | ||
| 276 | + EXPECT_FALSE(PixelMapGlResource::CopyLinearToStrided( | ||
| 277 | + linear, sizeof(linear), rowBytes, 2, strided, sizeof(strided), 8)); | ||
| 222 | 278 | ||
| 223 | PixelMapGlResource::ScopedFramebuffer framebuffer(0U); | 279 | PixelMapGlResource::ScopedFramebuffer framebuffer(0U); |
| 224 | PixelMapGlResource::ScopedFramebuffer movedFramebuffer(std::move(framebuffer)); | 280 | PixelMapGlResource::ScopedFramebuffer movedFramebuffer(std::move(framebuffer)); |
| @@ -273,6 +329,96 @@ HWTEST_F(EglImageHelperTest, PixelMapProgramManagerUtilsStateTest002, TestSize.L | |||
| 273 | PixelMapGlUtils::GetContextExpireDelaySec(3, MAX_GL_INSTANCE_NUM)); | 329 | PixelMapGlUtils::GetContextExpireDelaySec(3, MAX_GL_INSTANCE_NUM)); |
| 274 | } | 330 | } |
| 275 | 331 | ||
| 332 | +/** | ||
| 333 | + * @tc.name: PixelMapProgramManagerUtilsReserveTest001 | ||
| 334 | + * @tc.desc: Test reserving a program slot returns a stable post-increment snapshot. | ||
| 335 | + * @tc.type: FUNC | ||
| 336 | + */ | ||
| 337 | +HWTEST_F(EglImageHelperTest, PixelMapProgramManagerUtilsReserveTest001, TestSize.Level3) | ||
| 338 | +{ | ||
| 339 | + using namespace PixelMapProgramManagerUtils; | ||
| 340 | + int32_t totalInstances = 0; | ||
| 341 | + int32_t reservedTotal = -1; | ||
| 342 | + EXPECT_TRUE(TryReserveProgram(totalInstances, MAX_GL_INSTANCE_NUM, reservedTotal)); | ||
| 343 | + EXPECT_EQ(totalInstances, 1); | ||
| 344 | + EXPECT_EQ(reservedTotal, 1); | ||
| 345 | + | ||
| 346 | + totalInstances = MAX_GL_INSTANCE_NUM; | ||
| 347 | + reservedTotal = -1; | ||
| 348 | + EXPECT_FALSE(TryReserveProgram(totalInstances, MAX_GL_INSTANCE_NUM, reservedTotal)); | ||
| 349 | + EXPECT_EQ(totalInstances, MAX_GL_INSTANCE_NUM); | ||
| 350 | + EXPECT_EQ(reservedTotal, -1); | ||
| 351 | + | ||
| 352 | + totalInstances = -1; | ||
| 353 | + EXPECT_FALSE(TryReserveProgram(totalInstances, MAX_GL_INSTANCE_NUM, reservedTotal)); | ||
| 354 | + EXPECT_EQ(totalInstances, -1); | ||
| 355 | +} | ||
| 356 | + | ||
| 357 | +/** | ||
| 358 | + * @tc.name: PixelMapGlShaderCacheSizeTest001 | ||
| 359 | + * @tc.desc: Test shader cache size validation rejects truncated and oversized files. | ||
| 360 | + * @tc.type: FUNC | ||
| 361 | + */ | ||
| 362 | +HWTEST_F(EglImageHelperTest, PixelMapGlShaderCacheSizeTest001, TestSize.Level3) | ||
| 363 | +{ | ||
| 364 | + using namespace PixelMapGlShaderUtils; | ||
| 365 | + constexpr uint64_t metadataSize = sizeof(GLenum) + sizeof(int); | ||
| 366 | + EXPECT_FALSE(IsShaderCacheFileSizeValid(metadataSize - 1, metadataSize)); | ||
| 367 | + EXPECT_TRUE(IsShaderCacheFileSizeValid(metadataSize, metadataSize)); | ||
| 368 | + EXPECT_TRUE(IsShaderCacheFileSizeValid(MAX_SHADER_CACHE_FILE_SIZE, metadataSize)); | ||
| 369 | + EXPECT_FALSE(IsShaderCacheFileSizeValid(MAX_SHADER_CACHE_FILE_SIZE + 1, metadataSize)); | ||
| 370 | +} | ||
| 371 | + | ||
| 372 | +/** | ||
| 373 | + * @tc.name: PixelMapGlShaderCacheLockTest001 | ||
| 374 | + * @tc.desc: Test shader cache state operations are serialized across threads. | ||
| 375 | + * @tc.type: FUNC | ||
| 376 | + */ | ||
| 377 | +HWTEST_F(EglImageHelperTest, PixelMapGlShaderCacheLockTest001, TestSize.Level3) | ||
| 378 | +{ | ||
| 379 | + constexpr size_t threadCount = 4; | ||
| 380 | + constexpr int iterationCount = 100; | ||
| 381 | + std::atomic<int> activeCount = 0; | ||
| 382 | + std::atomic<int> maxActiveCount = 0; | ||
| 383 | + std::atomic<bool> allOperationsSucceeded = true; | ||
| 384 | + std::atomic<size_t> readyThreadCount = 0; | ||
| 385 | + std::atomic<bool> startOperations = false; | ||
| 386 | + std::array<std::thread, threadCount> threads; | ||
| 387 | + for (auto &thread : threads) { | ||
| 388 | + thread = std::thread([&activeCount, &maxActiveCount, &allOperationsSucceeded, | ||
| 389 | + &readyThreadCount, &startOperations]() { | ||
| 390 | + readyThreadCount.fetch_add(1); | ||
| 391 | + while (!startOperations.load()) { | ||
| 392 | + std::this_thread::yield(); | ||
| 393 | + } | ||
| 394 | + for (int iteration = 0; iteration < iterationCount; ++iteration) { | ||
| 395 | + const bool success = PixelMapGlShaderUtils::WithShaderCacheLock([&activeCount, &maxActiveCount]() { | ||
| 396 | + const int active = activeCount.fetch_add(1) + 1; | ||
| 397 | + int observedMax = maxActiveCount.load(); | ||
| 398 | + while (active > observedMax && | ||
| 399 | + !maxActiveCount.compare_exchange_weak(observedMax, active)) { | ||
| 400 | + } | ||
| 401 | + std::this_thread::yield(); | ||
| 402 | + activeCount.fetch_sub(1); | ||
| 403 | + return true; | ||
| 404 | + }); | ||
| 405 | + if (!success) { | ||
| 406 | + allOperationsSucceeded.store(false); | ||
| 407 | + } | ||
| 408 | + } | ||
| 409 | + }); | ||
| 410 | + } | ||
| 411 | + while (readyThreadCount.load() != threadCount) { | ||
| 412 | + std::this_thread::yield(); | ||
| 413 | + } | ||
| 414 | + startOperations.store(true); | ||
| 415 | + for (auto &thread : threads) { | ||
| 416 | + thread.join(); | ||
| 417 | + } | ||
| 418 | + EXPECT_TRUE(allOperationsSucceeded.load()); | ||
| 419 | + EXPECT_EQ(maxActiveCount.load(), 1); | ||
| 420 | +} | ||
| 421 | + | ||
| 276 | /** | 422 | /** |
| 277 | * @tc.name: PixelMapGlUtilsResolveDmaTransferModeTest002 | 423 | * @tc.name: PixelMapGlUtilsResolveDmaTransferModeTest002 |
| 278 | * @tc.desc: Test helper routes no-padding DMA to heap writeback. | 424 | * @tc.desc: Test helper routes no-padding DMA to heap writeback. |
| @@ -654,7 +800,7 @@ HWTEST_F(EglImageHelperTest, PixelMapGLPostProcProgramInterfaceTest001, TestSize | |||
| 654 | transformData.transformationType = static_cast<TransformationType>(0); | 800 | transformData.transformationType = static_cast<TransformationType>(0); |
| 655 | program.SetGPUTransformData(transformData); | 801 | program.SetGPUTransformData(transformData); |
| 656 | EXPECT_TRUE(program.Init()); | 802 | EXPECT_TRUE(program.Init()); |
| 657 | - EXPECT_TRUE(program.Execute()); | 803 | + EXPECT_FALSE(program.Execute()); |
| 658 | } | 804 | } |
| 659 | } // namespace Media | 805 | } // namespace Media |
| 660 | } // namespace OHOS | 806 | } // namespace OHOS |
| @@ -86,6 +86,24 @@ HWTEST_F(EglImageTest, PixelMapGlUtilsImageLayoutTest001, TestSize.Level3) | |||
| 86 | Size{std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max()}, 8, contiguousSize)); | 86 | Size{std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max()}, 8, contiguousSize)); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | +/** | ||
| 90 | + * @tc.name: PixelMapGlResourceRgbaValidationTest001 | ||
| 91 | + * @tc.desc: Test EGL post-processing buffer validation only accepts the supported RGBA layout. | ||
| 92 | + * @tc.type: FUNC | ||
| 93 | + */ | ||
| 94 | +HWTEST_F(EglImageTest, PixelMapGlResourceRgbaValidationTest001, TestSize.Level3) | ||
| 95 | +{ | ||
| 96 | + GlImageInfo imageInfo; | ||
| 97 | + imageInfo.size = {2, 2}; | ||
| 98 | + imageInfo.stride = 8; | ||
| 99 | + imageInfo.pixelBytes = PixelMapGlResource::BYTES_PER_PIXEL_RGBA; | ||
| 100 | + imageInfo.bufferSize = 16; | ||
| 101 | + EXPECT_TRUE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_RGBA)); | ||
| 102 | + EXPECT_FALSE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_RGB)); | ||
| 103 | + imageInfo.pixelBytes = 3; | ||
| 104 | + EXPECT_FALSE(PixelMapGlResource::ValidateCpuImageInfo(imageInfo, GL_RGBA)); | ||
| 105 | +} | ||
| 106 | + | ||
| 89 | /** | 107 | /** |
| 90 | * @tc.name: PixelMapGlUtilsBuildSlrWeightsTest001 | 108 | * @tc.name: PixelMapGlUtilsBuildSlrWeightsTest001 |
| 91 | * @tc.desc: Test SLR weight generation is bounded and normalized. | 109 | * @tc.desc: Test SLR weight generation is bounded and normalized. |
| @@ -140,9 +158,9 @@ HWTEST_F(EglImageTest, PixelMapGlResourceCopyHelpersTest001, TestSize.Level3) | |||
| 140 | EXPECT_EQ(static_cast<uint8_t>(linear[8]), 9); | 158 | EXPECT_EQ(static_cast<uint8_t>(linear[8]), 9); |
| 141 | EXPECT_EQ(static_cast<uint8_t>(linear[15]), 16); | 159 | EXPECT_EQ(static_cast<uint8_t>(linear[15]), 16); |
| 142 | 160 | ||
| 143 | - std::vector<uint8_t> dst(static_cast<size_t>(stride) * height, 0); | 161 | + std::vector<uint8_t> dst(rowBytes + static_cast<size_t>(stride) * (height - 1), 0); |
| 144 | EXPECT_TRUE(PixelMapGlResource::CopyLinearToStrided( | 162 | EXPECT_TRUE(PixelMapGlResource::CopyLinearToStrided( |
| 145 | - linear.data(), linear.size(), rowBytes, height, dst.data(), stride)); | 163 | + linear.data(), linear.size(), rowBytes, height, dst.data(), dst.size(), stride)); |
| 146 | EXPECT_EQ(dst[0], 1); | 164 | EXPECT_EQ(dst[0], 1); |
| 147 | EXPECT_EQ(dst[7], 8); | 165 | EXPECT_EQ(dst[7], 8); |
| 148 | EXPECT_EQ(dst[12], 9); | 166 | EXPECT_EQ(dst[12], 9); |
| @@ -100,11 +100,13 @@ HWTEST_F(PixelMapGlTransformTest, ProgramManagerScaleSuccess001, TestSize.Level3 | |||
| 100 | trans.sourceInfo_.size = { pixelMap->GetWidth(), pixelMap->GetHeight() }; | 100 | trans.sourceInfo_.size = { pixelMap->GetWidth(), pixelMap->GetHeight() }; |
| 101 | trans.sourceInfo_.stride = pixelMap->GetRowStride(); | 101 | trans.sourceInfo_.stride = pixelMap->GetRowStride(); |
| 102 | trans.sourceInfo_.pixelBytes = pixelBytes; | 102 | trans.sourceInfo_.pixelBytes = pixelBytes; |
| 103 | + trans.sourceInfo_.bufferSize = pixelMap->GetAllocationByteCount(); | ||
| 103 | trans.sourceInfo_.addr = pixelMap->GetPixels(); | 104 | trans.sourceInfo_.addr = pixelMap->GetPixels(); |
| 104 | trans.sourceInfo_.context = pixelMap->GetFd(); | 105 | trans.sourceInfo_.context = pixelMap->GetFd(); |
| 105 | trans.targetInfo_.size = targetSize; | 106 | trans.targetInfo_.size = targetSize; |
| 106 | trans.targetInfo_.stride = targetSize.width * pixelBytes; | 107 | trans.targetInfo_.stride = targetSize.width * pixelBytes; |
| 107 | trans.targetInfo_.pixelBytes = pixelBytes; | 108 | trans.targetInfo_.pixelBytes = pixelBytes; |
| 109 | + trans.targetInfo_.bufferSize = targetBuf.size(); | ||
| 108 | trans.targetInfo_.outdata = targetBuf.data(); | 110 | trans.targetInfo_.outdata = targetBuf.data(); |
| 109 | auto dmaMode = PixelMapGlUtils::ResolveDmaTransferMode(pixelMap->GetAllocatorType(), 0); | 111 | auto dmaMode = PixelMapGlUtils::ResolveDmaTransferMode(pixelMap->GetAllocatorType(), 0); |
| 110 | trans.isSourceDma = dmaMode.isSourceDma; | 112 | trans.isSourceDma = dmaMode.isSourceDma; |
| @@ -157,11 +159,13 @@ HWTEST_F(PixelMapGlTransformTest, ProgramManagerRotateSuccess001, TestSize.Level | |||
| 157 | trans.sourceInfo_.size = { srcW, srcH }; | 159 | trans.sourceInfo_.size = { srcW, srcH }; |
| 158 | trans.sourceInfo_.stride = pixelMap->GetRowStride(); | 160 | trans.sourceInfo_.stride = pixelMap->GetRowStride(); |
| 159 | trans.sourceInfo_.pixelBytes = pixelBytes; | 161 | trans.sourceInfo_.pixelBytes = pixelBytes; |
| 162 | + trans.sourceInfo_.bufferSize = pixelMap->GetAllocationByteCount(); | ||
| 160 | trans.sourceInfo_.addr = pixelMap->GetPixels(); | 163 | trans.sourceInfo_.addr = pixelMap->GetPixels(); |
| 161 | trans.sourceInfo_.context = pixelMap->GetFd(); | 164 | trans.sourceInfo_.context = pixelMap->GetFd(); |
| 162 | trans.targetInfo_.size = targetSize; | 165 | trans.targetInfo_.size = targetSize; |
| 163 | trans.targetInfo_.stride = targetSize.width * pixelBytes; | 166 | trans.targetInfo_.stride = targetSize.width * pixelBytes; |
| 164 | trans.targetInfo_.pixelBytes = pixelBytes; | 167 | trans.targetInfo_.pixelBytes = pixelBytes; |
| 168 | + trans.targetInfo_.bufferSize = targetBuf.size(); | ||
| 165 | trans.targetInfo_.outdata = targetBuf.data(); | 169 | trans.targetInfo_.outdata = targetBuf.data(); |
| 166 | auto dmaMode = PixelMapGlUtils::ResolveDmaTransferMode(pixelMap->GetAllocatorType(), 0); | 170 | auto dmaMode = PixelMapGlUtils::ResolveDmaTransferMode(pixelMap->GetAllocatorType(), 0); |
| 167 | trans.isSourceDma = dmaMode.isSourceDma; | 171 | trans.isSourceDma = dmaMode.isSourceDma; |
| @@ -219,4 +223,4 @@ HWTEST_F(PixelMapGlTransformTest, ResolveDmaTransferModeShareMem001, TestSize.Le | |||
| 219 | 223 | ||
| 220 | 224 | ||
| 221 | } // namespace Multimedia | 225 | } // namespace Multimedia |
| 222 | -} // namespace OHOS | 226 | +} // namespace OHOS |