• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gpu_image_gles.h"
17 
18 #if (RENDER_PERF_ENABLED == 1)
19 #include <core/implementation_uids.h>
20 #include <core/perf/intf_performance_data_manager.h>
21 #endif
22 
23 #include <base/math/vector.h>
24 #include <render/namespace.h>
25 
26 #include "gles/device_gles.h"
27 #include "gles/gl_functions.h"
28 #include "util/log.h"
29 
30 using namespace BASE_NS;
31 
32 RENDER_BEGIN_NAMESPACE()
33 namespace {
34 #if (RENDER_PERF_ENABLED == 1)
RecordAllocation(const int64_t alignedByteSize)35 void RecordAllocation(const int64_t alignedByteSize)
36 {
37     if (auto* inst = CORE_NS::GetInstance<CORE_NS::IPerformanceDataManagerFactory>(CORE_NS::UID_PERFORMANCE_FACTORY);
38         inst) {
39         CORE_NS::IPerformanceDataManager* pdm = inst->Get("Memory");
40         pdm->UpdateData("AllGpuImages", "GPU_IMAGE", alignedByteSize);
41     }
42 }
43 #endif
44 
ConvertFormat(const DeviceGLES::ImageFormat & fmt)45 GpuImagePlatformDataGL ConvertFormat(const DeviceGLES::ImageFormat& fmt)
46 {
47     GpuImagePlatformDataGL result {};
48     if (fmt.coreFormat == BASE_FORMAT_UNDEFINED) {
49         PLUGIN_ASSERT_MSG(false, "Unsupported texture format in GpuImageGLES::convertFormat!");
50     }
51     result.bytesperpixel = fmt.bytesperpixel;
52     result.dataType = fmt.dataType;
53     result.format = fmt.format;
54     result.internalFormat = fmt.internalFormat;
55     result.compression = { fmt.compression.compressed, fmt.compression.blockW, fmt.compression.blockH,
56         fmt.compression.bytesperblock };
57     result.swizzle = fmt.swizzle;
58     return result;
59 }
60 
ConvertSampleCountFlags(SampleCountFlags flags)61 constexpr uint32_t ConvertSampleCountFlags(SampleCountFlags flags)
62 {
63     uint32_t sampleCount = 1;
64     if ((uint32_t)flags != 1) {
65         // MSAA
66         sampleCount = (uint32_t)flags;
67     }
68     return sampleCount;
69 }
70 
MapSwizzle(ComponentSwizzle swizzle,uint32_t input)71 GLenum MapSwizzle(ComponentSwizzle swizzle, uint32_t input)
72 {
73     switch (swizzle) {
74         case CORE_COMPONENT_SWIZZLE_IDENTITY:
75             return input;
76         case CORE_COMPONENT_SWIZZLE_ZERO:
77             return GL_ZERO;
78         case CORE_COMPONENT_SWIZZLE_ONE:
79             return GL_ONE;
80         case CORE_COMPONENT_SWIZZLE_R:
81             return GL_RED;
82         case CORE_COMPONENT_SWIZZLE_G:
83             return GL_GREEN;
84         case CORE_COMPONENT_SWIZZLE_B:
85             return GL_BLUE;
86         case CORE_COMPONENT_SWIZZLE_A:
87             return GL_ALPHA;
88         default:
89             break;
90     }
91     return input;
92 }
93 
DoSwizzle(const GpuImageDesc & desc,GpuImagePlatformDataGL & plat)94 void DoSwizzle(const GpuImageDesc& desc, GpuImagePlatformDataGL& plat)
95 {
96     plat.swizzle.x = MapSwizzle(desc.componentMapping.r, plat.swizzle.x);
97     plat.swizzle.y = MapSwizzle(desc.componentMapping.g, plat.swizzle.y);
98     plat.swizzle.z = MapSwizzle(desc.componentMapping.b, plat.swizzle.z);
99     plat.swizzle.w = MapSwizzle(desc.componentMapping.a, plat.swizzle.w);
100 }
101 
GenerateImageStorage(DeviceGLES & device,const GpuImageDesc & desc,GpuImagePlatformDataGL & plat)102 void GenerateImageStorage(DeviceGLES& device, const GpuImageDesc& desc, GpuImagePlatformDataGL& plat)
103 {
104     const uint32_t sampleCount = ConvertSampleCountFlags(desc.sampleCountFlags);
105     glGenTextures(1, &plat.image);
106 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
107     if (plat.image) {
108         PLUGIN_LOG_D("gpu image id >: %u", plat.image);
109     }
110 #endif
111 
112     const Math::UVec2 size2D { desc.width, desc.height };
113     switch (desc.imageViewType) {
114         case CORE_IMAGE_VIEW_TYPE_2D: {
115             PLUGIN_ASSERT_MSG(desc.layerCount == 1, "layerCount != 1 for normal texture!");
116             if (sampleCount > 1) {
117                 plat.type = GL_TEXTURE_2D_MULTISAMPLE;
118                 // must use fixed sample locations so that renderbuffer/texture fbos work.
119                 device.TexStorage2DMultisample(plat.image, plat.type, sampleCount, plat.internalFormat, size2D, true);
120             } else {
121                 plat.type = GL_TEXTURE_2D;
122                 device.TexStorage2D(plat.image, plat.type, desc.mipCount, plat.internalFormat, size2D);
123             }
124             break;
125         }
126         case CORE_IMAGE_VIEW_TYPE_CUBE: {
127             PLUGIN_ASSERT_MSG(desc.layerCount == 6, "layerCount != 6 for cubemap!");
128             plat.type = GL_TEXTURE_CUBE_MAP;
129             device.TexStorage2D(plat.image, plat.type, desc.mipCount, plat.internalFormat, size2D);
130             break;
131         }
132         case CORE_IMAGE_VIEW_TYPE_2D_ARRAY: {
133             PLUGIN_ASSERT_MSG(desc.layerCount <= 256, "layerCount > 256 for 2D Array!");
134             if (sampleCount > 1 && device.HasExtension("GL_EXT_multiview_texture_multisample")) {
135                 plat.type = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
136                 // must use fixed sample locations so that renderbuffer/texture fbos work.
137                 device.TexStorage3DMultisample(plat.image, plat.type, sampleCount, plat.internalFormat,
138                     { desc.width, desc.height, desc.layerCount }, true);
139             } else {
140                 plat.type = GL_TEXTURE_2D_ARRAY;
141                 device.TexStorage3D(plat.image, plat.type, desc.mipCount, plat.internalFormat,
142                     { desc.width, desc.height, desc.layerCount });
143             }
144             break;
145         }
146         case CORE_IMAGE_VIEW_TYPE_3D: {
147             plat.type = GL_TEXTURE_3D;
148             device.TexStorage3D(
149                 plat.image, plat.type, desc.mipCount, plat.internalFormat, { desc.width, desc.height, desc.depth });
150             break;
151         }
152         case CORE_IMAGE_VIEW_TYPE_1D:
153         case CORE_IMAGE_VIEW_TYPE_1D_ARRAY:
154         case CORE_IMAGE_VIEW_TYPE_CUBE_ARRAY:
155         default:
156             PLUGIN_ASSERT_MSG(false, "UNSUPPORTED IMAGEVIEW TYPE");
157             plat.type = GL_NONE;
158             break;
159     }
160     // set swizzle.
161     DoSwizzle(desc, plat);
162     device.TexSwizzle(plat.image, plat.type, plat.swizzle);
163 }
164 } // namespace
165 
GetPlatformData(const DeviceGLES & device,Format format)166 GpuImagePlatformDataGL GpuImageGLES::GetPlatformData(const DeviceGLES& device, Format format)
167 {
168     const auto& fmt = device.GetGlImageFormat(format);
169     return ConvertFormat(fmt);
170 }
171 
GpuImageGLES(Device & device,const GpuImageDesc & desc)172 GpuImageGLES::GpuImageGLES(Device& device, const GpuImageDesc& desc)
173     : GpuImage(), device_((DeviceGLES&)device), desc_(desc)
174 {
175     PLUGIN_ASSERT(device_.IsActive());
176     PLUGIN_ASSERT_MSG(desc_.memoryPropertyFlags & MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
177         "Device local memory is only memory property supported for GLES GpuImage (flags: %u)",
178         desc_.memoryPropertyFlags);
179     plat_ = GetPlatformData(device_, desc_.format);
180     // Check for formats that require special attention.
181     if ((desc.usageFlags & CORE_IMAGE_USAGE_STORAGE_BIT)) {
182         // Force the format to "other" (there might be others that require "special handling".
183         if (desc_.format == BASE_FORMAT_B10G11R11_UFLOAT_PACK32) {
184             plat_ = GetPlatformData(device_, BASE_FORMAT_R16G16B16A16_SFLOAT);
185         }
186     }
187     const bool isArray =
188         (desc_.imageViewType == CORE_IMAGE_VIEW_TYPE_1D_ARRAY || desc_.imageViewType == CORE_IMAGE_VIEW_TYPE_2D_ARRAY ||
189             desc_.imageViewType == CORE_IMAGE_VIEW_TYPE_CUBE_ARRAY);
190     const bool isSrc = (desc_.usageFlags & CORE_IMAGE_USAGE_TRANSFER_SRC_BIT);
191     const bool isDst = (desc_.usageFlags & CORE_IMAGE_USAGE_TRANSFER_DST_BIT);
192     const bool isSample = (desc_.usageFlags & CORE_IMAGE_USAGE_SAMPLED_BIT);
193     const bool isStorage = (desc_.usageFlags & CORE_IMAGE_USAGE_STORAGE_BIT);
194     // could check for bool isColor = (desc_.usageFlags & CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
195     // could check for bool isDepth = (desc_.usageFlags & CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
196     // could check for bool isTrans = (desc_.usageFlags & CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT);
197     const bool isInput = (desc_.usageFlags & CORE_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
198     if ((!isArray) && (!isSrc) && (!isDst) && (!isSample) && (!isStorage) && (!isInput)) {
199         // Use render buffers for "non-input,non-compute,non-texture,no src/dst transfer" images
200         // ie. temporary render targets
201         glGenRenderbuffers(1, &plat_.renderBuffer);
202 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
203         if (plat_.renderBuffer) {
204             PLUGIN_LOG_D("gpu renderbuffer id >: %u", plat_.renderBuffer);
205         }
206 #endif
207         glBindRenderbuffer(GL_RENDERBUFFER, plat_.renderBuffer);
208         const uint32_t sampleCount = ConvertSampleCountFlags(desc_.sampleCountFlags);
209         if (sampleCount > 1) {
210 #if RENDER_HAS_GLES_BACKEND
211             // Sadly Mali driver doesn't understand a multisampled render buffer created with the core function attached
212             // to the same FBO with FramebufferTexture2DMultisampleEXT attachments, so in order to use that on Mali
213             // render buffer must also use the EXT function.
214             if (device_.HasExtension("GL_EXT_multisampled_render_to_texture2")) {
215                 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, (GLsizei)sampleCount, plat_.internalFormat,
216                     (GLsizei)desc_.width, (GLsizei)desc_.height);
217             } else {
218                 glRenderbufferStorageMultisample(GL_RENDERBUFFER, (GLsizei)sampleCount, plat_.internalFormat,
219                     (GLsizei)desc_.width, (GLsizei)desc_.height);
220             }
221 #else
222             glRenderbufferStorageMultisample(GL_RENDERBUFFER, (GLsizei)sampleCount, plat_.internalFormat,
223                 (GLsizei)desc_.width, (GLsizei)desc_.height);
224 #endif
225         } else {
226             glRenderbufferStorage(GL_RENDERBUFFER, plat_.internalFormat, (GLsizei)desc_.width, (GLsizei)desc_.height);
227         }
228     } else {
229         GenerateImageStorage(device_, desc_, plat_);
230     }
231 #if (RENDER_PERF_ENABLED == 1)
232     RecordAllocation(static_cast<int64_t>(plat_.bytesperpixel * desc_.width * desc_.height * desc_.depth));
233 #endif
234 }
235 
GpuImageGLES(Device & device,const GpuImageDesc & desc,const GpuImagePlatformData & platformData)236 GpuImageGLES::GpuImageGLES(Device& device, const GpuImageDesc& desc, const GpuImagePlatformData& platformData)
237     : GpuImage(), device_((DeviceGLES&)device), plat_((const GpuImagePlatformDataGL&)platformData), desc_(desc),
238       ownsResources_(false)
239 {
240     PLUGIN_ASSERT(device_.IsActive());
241 #if (RENDER_HAS_GLES_BACKEND == 1)
242     if (reinterpret_cast<GLeglImageOES>(plat_.eglImage) != 0) {
243         glGenTextures(1, &plat_.image);
244 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
245         PLUGIN_LOG_D("gpu image id >: %u", plat_.image);
246 #endif
247 
248         constexpr const uint32_t TEMP_BIND_UNIT = 15u;
249         // store the previous tex id for restoring.
250         const auto oldTex = device_.BoundTexture(TEMP_BIND_UNIT, GL_TEXTURE_EXTERNAL_OES);
251         device_.BindTexture(TEMP_BIND_UNIT, GL_TEXTURE_EXTERNAL_OES, plat_.image);
252 
253         // need to make sure the correct texUnit is active when calling GL directly.
254         device_.SetActiveTextureUnit(TEMP_BIND_UNIT);
255         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
256         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
257         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
258         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
259         glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<GLeglImageOES>(plat_.eglImage));
260 
261         // set swizzle.
262         DoSwizzle(desc, plat_);
263         device_.TexSwizzle(plat_.image, GL_TEXTURE_EXTERNAL_OES, plat_.swizzle);
264 
265         // restore previous tex id.
266         device_.BindTexture(TEMP_BIND_UNIT, GL_TEXTURE_EXTERNAL_OES, oldTex);
267     }
268 #endif // RENDER_HAS_GLES_BACKEND
269 }
270 
~GpuImageGLES()271 GpuImageGLES::~GpuImageGLES()
272 {
273     PLUGIN_ASSERT(device_.IsActive());
274     if (ownsResources_) {
275         if (plat_.image) {
276             device_.DeleteTexture(plat_.image);
277 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
278             PLUGIN_LOG_D("gpu image id <: %u", plat_.image);
279 #endif
280         }
281         if (plat_.renderBuffer) {
282             glDeleteRenderbuffers(1, &plat_.renderBuffer);
283 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
284             PLUGIN_LOG_D("gpu render buffer id <: %u", plat_.renderBuffer);
285 #endif
286         }
287 
288 #if (RENDER_PERF_ENABLED == 1)
289         RecordAllocation(-static_cast<int64_t>(plat_.bytesperpixel * desc_.width * desc_.height * desc_.depth));
290 #endif
291     }
292 #if (RENDER_HAS_GLES_BACKEND == 1)
293     if (reinterpret_cast<GLeglImageOES>(plat_.eglImage) != 0) {
294         if (plat_.image) {
295             device_.DeleteTexture(plat_.image);
296 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
297             PLUGIN_LOG_D("gpu image id <: %u", plat_.image);
298 #endif
299         }
300     }
301 #endif
302 }
303 
GetDesc() const304 const GpuImageDesc& GpuImageGLES::GetDesc() const
305 {
306     return desc_;
307 }
308 
GetPlatformData() const309 const GpuImagePlatformDataGL& GpuImageGLES::GetPlatformData() const
310 {
311     return plat_;
312 }
313 
GetBasePlatformData() const314 const GpuImagePlatformData& GpuImageGLES::GetBasePlatformData() const
315 {
316     return plat_;
317 }
318 
GetAdditionalFlags() const319 GpuImage::AdditionalFlags GpuImageGLES::GetAdditionalFlags() const
320 {
321     // expecting all egl images to need special platform conversion (e.g. OES binding)
322     return (plat_.eglImage) ? ADDITIONAL_PLATFORM_CONVERSION_BIT : 0u;
323 }
324 RENDER_END_NAMESPACE()
325