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