// 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. // An idiomatic C++ interface to EGL 1.5. #ifndef GLPLANET_SRC_EGL_H_ #define GLPLANET_SRC_EGL_H_ #include #include #include #include #include "src/undo_xlib_dot_h_namespace_pollution.h" // #include "src/util.h" #include "third_party/abseil/absl/types/optional.h" namespace egl { class Context; class Display; class Surface; // Makes a Context active in the current thread. void BindContext(Surface&, Context&); // Configuration attributes. enum Attribute : EGLint { kBufferSize = EGL_BUFFER_SIZE, kRedSize = EGL_RED_SIZE, kGreenSize = EGL_GREEN_SIZE, kBlueSize = EGL_BLUE_SIZE, kLuminanceSize = EGL_LUMINANCE_SIZE, kAlphaSize = EGL_ALPHA_SIZE, kAlphaMaskSize = EGL_ALPHA_MASK_SIZE, kBindToTextureRgb = EGL_BIND_TO_TEXTURE_RGB, kBindToTextureRgba = EGL_BIND_TO_TEXTURE_RGBA, kColorBufferType = EGL_COLOR_BUFFER_TYPE, kConfigCaveat = EGL_CONFIG_CAVEAT, kConfigId = EGL_CONFIG_ID, kConformantMask = EGL_CONFORMANT, kDepthSize = EGL_DEPTH_SIZE, kLevel = EGL_LEVEL, kMatchNativePixmap = EGL_MATCH_NATIVE_PIXMAP, kMaxSwapInterval = EGL_MAX_SWAP_INTERVAL, kMinSwapInterval = EGL_MIN_SWAP_INTERVAL, kNativeRenderable = EGL_NATIVE_RENDERABLE, kNativeVisualId = EGL_NATIVE_VISUAL_ID, kNativeVisualType = EGL_NATIVE_VISUAL_TYPE, kSampleBuffers = EGL_SAMPLE_BUFFERS, kSamples = EGL_SAMPLES, kStencilSize = EGL_STENCIL_SIZE, kSurfaceTypeMask = EGL_SURFACE_TYPE, kTransparentType = EGL_TRANSPARENT_TYPE, kTransparentRedValue = EGL_TRANSPARENT_RED_VALUE, kTransparentGreenValue = EGL_TRANSPARENT_GREEN_VALUE, kTransparentBlueValue = EGL_TRANSPARENT_BLUE_VALUE, kRenderableTypeMask = EGL_RENDERABLE_TYPE, }; // A "don't care" value for use in attribute lists. constexpr int kDontCare = EGL_DONT_CARE; enum class Api : EGLenum { kOpenglEs = EGL_OPENGL_ES_API, kOpenvg = EGL_OPENVG_API, kOpengl = EGL_OPENGL_API, }; enum ApiMask : EGLint { kOpenglEsBit = EGL_OPENGL_ES_BIT, kOpenVgBit = EGL_OPENVG_BIT, kOpenglEs2Bit = EGL_OPENGL_ES2_BIT, kOpenglBit = EGL_OPENGL_BIT, }; // The format, type, and size of the buffers for a drawable. // // This class is thread-safe. class Configuration final { public: Configuration(const Configuration&) = default; Configuration& operator=(const Configuration&) = default; Configuration(Configuration&&) noexcept = default; Configuration& operator=(Configuration&&) noexcept = default; int Get(Attribute attribute) const; private: friend class Display; explicit Configuration(EGLDisplay display, EGLConfig config) noexcept : display_(display), config_(config) {} EGLDisplay display_; EGLConfig config_; }; // A rendering surface. // // This class inherits the thread-safety properties of the Display that // constructed it. class Surface final { public: Surface(const Surface&) = default; Surface& operator=(const Surface&) = default; Surface(Surface&&) noexcept = default; Surface& operator=(Surface&&) noexcept = default; void SwapBuffers(); private: friend class Display; friend void BindContext(Surface&, Context&); explicit Surface(EGLDisplay display, EGLSurface surface) noexcept : display_(display), surface_(surface) {} EGLDisplay display_; EGLSurface surface_; }; // A rendering context. // // This class inherits the thread-safety properties of the Display that // constructed it. class Context final { public: Context(Context&&) noexcept = default; Context& operator=(Context&&) noexcept = default; ~Context() noexcept { // This should always succeed, since display_ and context_ are guaranteed // valid. DCHECK(eglDestroyContext(display_, context_)); } private: friend class Display; friend void BindContext(Surface&, Context&); explicit Context(EGLDisplay display, EGLContext context) noexcept : display_(display), context_(context) {} EGLDisplay display_; EGLContext context_; }; // The abstract display on which graphics are drawn. // // This class inherits the thread-safety properties of the underlying Xlib // Display with which it is constructed. class Display final { public: explicit Display(::Display* xlib_display); Display(Display&&) noexcept = default; Display& operator=(Display&&) noexcept = default; ~Display() noexcept; // Gets Configurations that match the specified attributes. If a limit is // specified, no more than that many Configurations will be returned. // // The returned Configurations hold references into this object and must not // outlive it. std::vector GetConfigurations( const std::vector>& filter_attributes, absl::optional limit = absl::nullopt) const; // Creates a rendering surface on a window. // // The returned Surface holds a reference into this Display and must not // outlive it. Surface CreateWindowSurface(const Configuration& config, ::Window window); // Creates an OpenGL context. // // The returned Context holds a reference into this Display and must not // outlive it. Context CreateContext(const Configuration& config, Api api, int major, int minor); private: EGLDisplay display_; }; } // namespace egl #endif // GLPLANET_SRC_EGL_H_