已合并
fix(egl): harden pixel map GL buffer handling #5794
fix(egl): harden pixel map GL buffer handling #5794
已合并
yaozhupeng创建于 21 天前
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 
158struct GlImageInfo {158struct 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};
167typedef struct GPUTransformData {167typedef 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 
49private:49private:
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#include <cstddef>23#include <cstddef>
24#include <cstdint>24#include <cstdint>
25-#include <limits>
26 25 
27#include "EGL/egl.h"26#include "EGL/egl.h"
28#include "EGL/eglext.h"27#include "EGL/eglext.h"
29#include "GLES3/gl32.h"28#include "GLES3/gl32.h"
30 29 
30+#include "pixel_map_gl_common.h"
31#include "pixel_map_gl_utils.h"31#include "pixel_map_gl_utils.h"
32#include "securec.h"32#include "securec.h"
33#include "window.h"33#include "window.h"
@@ -36,6 +36,7 @@ namespace OHOS {
36namespace Media {36namespace Media {
37namespace PixelMapGlResource {37namespace PixelMapGlResource {
38constexpr int32_t MAX_GL_TRANSFER_DIMENSION = 8192;38constexpr int32_t MAX_GL_TRANSFER_DIMENSION = 8192;
39+constexpr int32_t BYTES_PER_PIXEL_RGBA = 4;
39 40 
40inline void DeleteTexture(GLuint &textureId)41inline void DeleteTexture(GLuint &textureId)
41{42{
@@ -284,15 +285,39 @@ inline bool IsValidGlTransferSize(const Size &size)
284 285 
285inline bool ValidateStridedBufferSize(size_t bufferSize, int32_t stride, int32_t height, size_t rowBytes)286inline 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 
298inline bool CopyStridedToLinear(const uint8_t *src, size_t srcSize, int32_t srcStride, int32_t height,323inline 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 
319inline bool CopyLinearToStrided(const char *src, size_t srcSize, size_t rowBytes, int32_t height,344inline 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+#ifndef FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_SHADER_UTILS_H
17+#define FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_SHADER_UTILS_H
18+ 
19+#include <cstdint>
20+#include <mutex>
21+#include <utility>
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+#endif // FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_SHADER_UTILS_H
@@ -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+ 
90inline bool ValidateImageLayout(const Size &size, int32_t stride, int32_t pixelBytes,106inline 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+ 
39inline bool ShouldWaitForAvailableProgram(int32_t totalInstances, int32_t maxInstanceCount, size_t availableInstances)49inline 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+}
70std::once_flag g_shaderInitFlag;89std::once_flag g_shaderInitFlag;
71bool g_shaderBuildResult = false;90bool g_shaderBuildResult = false;
72} // namespace91} // 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+ 
89void PixelMapGLPostProcProgram::Clear() noexcept151void 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 
572bool PixelMapGLPostProcProgram::Execute()640bool 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#include "pixel_map_gl_shader.h"16#include "pixel_map_gl_shader.h"
17#include "pixel_map_gl_resource.h"17#include "pixel_map_gl_resource.h"
18+#include "pixel_map_gl_shader_utils.h"
18#include "pixel_map_gl_utils.h"19#include "pixel_map_gl_utils.h"
19 20 
21+#include <cerrno>
20#include <fcntl.h>22#include <fcntl.h>
21#include <inttypes.h>23#include <inttypes.h>
22#include <sys/stat.h>24#include <sys/stat.h>
23#include <sys/types.h>25#include <sys/types.h>
26+#include <unistd.h>
24 27 
25#include <filesystem>28#include <filesystem>
26#include <fstream>29#include <fstream>
30+#include <limits>
27#include <memory>31#include <memory>
28#include <sstream>32#include <sstream>
29#include <string>33#include <string>
30 34 
31-#ifdef USE_M133_SKIA
32-#include <unistd.h>
33-#endif
34- 
35#include "securec.h"35#include "securec.h"
36 36 
37#undef LOG_DOMAIN37#undef LOG_DOMAIN
@@ -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+ 
200Shader::Shader()231Shader::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#include <gtest/gtest.h>16#include <gtest/gtest.h>
17 17 
18#include <array>18#include <array>
19+#include <atomic>
19#include <cmath>20#include <cmath>
20#include <limits>21#include <limits>
21#include <memory>22#include <memory>
@@ -32,6 +33,7 @@
32#include "pixel_map_gl_resource.h"33#include "pixel_map_gl_resource.h"
33#include "pixel_map_gl_scope.h"34#include "pixel_map_gl_scope.h"
34#include "pixel_map_gl_shader.h"35#include "pixel_map_gl_shader.h"
36+#include "pixel_map_gl_shader_utils.h"
35#include "pixel_map_gl_utils.h"37#include "pixel_map_gl_utils.h"
36#include "pixel_map_program_manager.h"38#include "pixel_map_program_manager.h"
37#include "pixel_map_program_manager_utils.h"39#include "pixel_map_program_manager_utils.h"
@@ -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: PixelMapGlUtilsResolveDmaTransferModeTest002423 * @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 Media805} // namespace Media
660} // namespace OHOS806} // 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: PixelMapGlUtilsBuildSlrWeightsTest001108 * @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#endif // !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)223#endif // !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
220 224 
221} // namespace Multimedia225} // namespace Multimedia
222-} // namespace OHOS226+} // namespace OHOS