// Copyright 2021 Benjamin Barenblat // // 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 // // https://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 "src/gl/error.h" #include #include #include #include "third_party/glew/include/GL/glew.h" #include "third_party/abseil/absl/base/const_init.h" #include "third_party/abseil/absl/synchronization/mutex.h" #include "third_party/abseil/absl/types/optional.h" #include "third_party/abseil/absl/meta/type_traits.h" namespace gl_internal { #ifndef GLPLANET_DISABLE_GL_THREAD_SAFETY_CHECKS namespace { ABSL_CONST_INIT absl::Mutex thread_id_mu(absl::kConstInit); ABSL_CONST_INIT absl::optional thread_id; static_assert(absl::is_trivially_destructible::value); } // namespace void RecordThreadImpl() { absl::MutexLock lock(&thread_id_mu); if (thread_id.has_value()) { throw std::logic_error("GL: gl_internal::RecordThread called twice"); } thread_id = std::this_thread::get_id(); } void CheckThreadSafetyImpl() { absl::MutexLock lock(&thread_id_mu); if (!thread_id.has_value()) { throw std::logic_error( "GL: gl_internal::CheckThreadSafety called before " "gl_internal::RecordThread"); } if (std::this_thread::get_id() != *thread_id) { throw std::logic_error("GL: detected access from multiple threads"); } } #endif // !defined(GLPLANET_DISABLE_GL_THREAD_SAFETY_CHECKS) void ErrorCheck() { switch (glGetError()) { case GL_NO_ERROR: return; case GL_INVALID_ENUM: throw std::invalid_argument( "GL: unacceptable value specified for enumerated argument"); case GL_INVALID_VALUE: throw std::out_of_range("GL: numeric argument out of range"); case GL_INVALID_OPERATION: throw std::logic_error( "GL: specified operation not allowed in current state"); case GL_INVALID_FRAMEBUFFER_OPERATION: throw std::logic_error("GL: framebuffer object is not complete"); case GL_OUT_OF_MEMORY: throw std::bad_alloc(); case GL_STACK_UNDERFLOW: throw std::runtime_error("GL: stack underflow"); case GL_STACK_OVERFLOW: throw std::runtime_error("GL: stack overflow"); } } } // namespace gl_internal