diff options
Diffstat (limited to 'src/gl/error.cc')
-rw-r--r-- | src/gl/error.cc | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/gl/error.cc b/src/gl/error.cc new file mode 100644 index 0000000..20b2c74 --- /dev/null +++ b/src/gl/error.cc @@ -0,0 +1,84 @@ +// 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 <new> +#include <stdexcept> +#include <thread> + +#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<std::thread::id> thread_id; +static_assert(absl::is_trivially_destructible<decltype(thread_id)>::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 |