// Copyright 2022 The Dawn Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "dawn/native/opengl/AdapterGL.h" #include #include #include #include "dawn/common/GPUInfo.h" #include "dawn/native/Instance.h" #include "dawn/native/opengl/ContextEGL.h" #include "dawn/native/opengl/DeviceGL.h" namespace dawn::native::opengl { namespace { struct Vendor { const char* vendorName; uint32_t vendorId; }; const Vendor kVendors[] = {{"ATI", gpu_info::kVendorID_AMD}, {"ARM", gpu_info::kVendorID_ARM}, {"Imagination", gpu_info::kVendorID_ImgTec}, {"Intel", gpu_info::kVendorID_Intel}, {"NVIDIA", gpu_info::kVendorID_Nvidia}, {"Qualcomm", gpu_info::kVendorID_Qualcomm}}; uint32_t GetVendorIdFromVendors(const char* vendor) { uint32_t vendorId = 0; for (const auto& it : kVendors) { // Matching vendor name with vendor string if (strstr(vendor, it.vendorName) != nullptr) { vendorId = it.vendorId; break; } } return vendorId; } } // anonymous namespace Adapter::Adapter(InstanceBase* instance, wgpu::BackendType backendType) : AdapterBase(instance, backendType) {} MaybeError Adapter::InitializeGLFunctions(void* (*getProc)(const char*)) { // Use getProc to populate the dispatch table mEGLFunctions.Init(getProc); return mFunctions.Initialize(getProc); } bool Adapter::SupportsExternalImages() const { // Via dawn::native::opengl::WrapExternalEGLImage return GetBackendType() == wgpu::BackendType::OpenGLES; } MaybeError Adapter::InitializeImpl() { if (mFunctions.GetVersion().IsES()) { ASSERT(GetBackendType() == wgpu::BackendType::OpenGLES); } else { ASSERT(GetBackendType() == wgpu::BackendType::OpenGL); } mName = reinterpret_cast(mFunctions.GetString(GL_RENDERER)); // Workaroud to find vendor id from vendor name const char* vendor = reinterpret_cast(mFunctions.GetString(GL_VENDOR)); mVendorId = GetVendorIdFromVendors(vendor); mDriverDescription = std::string("OpenGL version ") + reinterpret_cast(mFunctions.GetString(GL_VERSION)); if (mName.find("SwiftShader") != std::string::npos) { mAdapterType = wgpu::AdapterType::CPU; } return {}; } MaybeError Adapter::InitializeSupportedFeaturesImpl() { // TextureCompressionBC { // BC1, BC2 and BC3 are not supported in OpenGL or OpenGL ES core features. bool supportsS3TC = mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_s3tc") || (mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_dxt1") && mFunctions.IsGLExtensionSupported("GL_ANGLE_texture_compression_dxt3") && mFunctions.IsGLExtensionSupported("GL_ANGLE_texture_compression_dxt5")); // COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT and // COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT requires both GL_EXT_texture_sRGB and // GL_EXT_texture_compression_s3tc on desktop OpenGL drivers. // (https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_sRGB.txt) bool supportsTextureSRGB = mFunctions.IsGLExtensionSupported("GL_EXT_texture_sRGB"); // GL_EXT_texture_compression_s3tc_srgb is an extension in OpenGL ES. // NVidia GLES drivers don't support this extension, but they do support // GL_NV_sRGB_formats. (Note that GL_EXT_texture_sRGB does not exist on ES. // GL_EXT_sRGB does (core in ES 3.0), but it does not automatically provide S3TC // SRGB support even if S3TC is supported; see // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_sRGB.txt.) bool supportsS3TCSRGB = mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_s3tc_srgb") || mFunctions.IsGLExtensionSupported("GL_NV_sRGB_formats"); // BC4 and BC5 bool supportsRGTC = mFunctions.IsAtLeastGL(3, 0) || mFunctions.IsGLExtensionSupported("GL_ARB_texture_compression_rgtc") || mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_rgtc"); // BC6 and BC7 bool supportsBPTC = mFunctions.IsAtLeastGL(4, 2) || mFunctions.IsGLExtensionSupported("GL_ARB_texture_compression_bptc") || mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_bptc"); if (supportsS3TC && (supportsTextureSRGB || supportsS3TCSRGB) && supportsRGTC && supportsBPTC) { mSupportedFeatures.EnableFeature(dawn::native::Feature::TextureCompressionBC); } } // Non-zero baseInstance requires at least desktop OpenGL 4.2, and it is not supported in // OpenGL ES OpenGL: // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsIndirect.xhtml // OpenGL ES: // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glDrawElementsIndirect.xhtml if (mFunctions.IsAtLeastGL(4, 2)) { mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance); } return {}; } MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) { GetDefaultLimits(&limits->v1); return {}; } ResultOrError> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { EGLenum api = GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API; std::unique_ptr context; DAWN_TRY_ASSIGN(context, ContextEGL::Create(mEGLFunctions, api)); return Device::Create(this, descriptor, mFunctions, std::move(context)); } } // namespace dawn::native::opengl