1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
use super::*; /// Attributes that you can use to control OpenGL's loading and context creation /// process. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(windows, repr(i32))] #[cfg_attr(not(windows), repr(u32))] pub enum GLattr { /// the minimum number of bits for the red channel of the color buffer; defaults to 3 RedSize = SDL_GL_RED_SIZE, /// the minimum number of bits for the green channel of the color buffer; defaults to 3 GreenSize = SDL_GL_GREEN_SIZE, /// the minimum number of bits for the blue channel of the color buffer; defaults to 2 BlueSize = SDL_GL_BLUE_SIZE, /// the minimum number of bits for the alpha channel of the color buffer; defaults to 0 AlphaSize = SDL_GL_ALPHA_SIZE, /// the minimum number of bits for frame buffer size; defaults to 0 BufferSize = SDL_GL_BUFFER_SIZE, /// whether the output is single or double buffered; defaults to double buffering on DoubleBuffer = SDL_GL_DOUBLEBUFFER, /// the minimum number of bits in the depth buffer; defaults to 16 DepthSize = SDL_GL_DEPTH_SIZE, /// the minimum number of bits in the stencil buffer; defaults to 0 StencilSize = SDL_GL_STENCIL_SIZE, /// the minimum number of bits for the red channel of the accumulation buffer; defaults to 0 AccumRedSize = SDL_GL_ACCUM_RED_SIZE, /// the minimum number of bits for the green channel of the accumulation buffer; defaults to 0 AccumGreenSize = SDL_GL_ACCUM_GREEN_SIZE, /// the minimum number of bits for the blue channel of the accumulation buffer; defaults to 0 AccumBlueSize = SDL_GL_ACCUM_BLUE_SIZE, /// the minimum number of bits for the alpha channel of the accumulation buffer; defaults to 0 AccumAlphaSize = SDL_GL_ACCUM_ALPHA_SIZE, /// whether the output is stereo 3D; defaults to off Stereo = SDL_GL_STEREO, /// the number of buffers used for multisample anti-aliasing; defaults to 0; see Remarks for details MultisampleBuffers = SDL_GL_MULTISAMPLEBUFFERS, /// the number of samples used around the current pixel used for multisample anti-aliasing; defaults to 0; see Remarks for details MultisampleSamples = SDL_GL_MULTISAMPLESAMPLES, /// set to 1 to require hardware acceleration, set to 0 to force software rendering; defaults to allow either AcceleratedVisuals = SDL_GL_ACCELERATED_VISUAL, /// OpenGL context major version ContextMajorVersion = SDL_GL_CONTEXT_MAJOR_VERSION, /// OpenGL context minor version ContextMinorVersion = SDL_GL_CONTEXT_MINOR_VERSION, /// some combination of 0 or more of elements of the SDL_GLContextFlag enumeration; defaults to 0 ContextFlags = SDL_GL_CONTEXT_FLAGS, /// type of GL context (Core, Compatibility, ES), default value depends on platform ContextProfileMask = SDL_GL_CONTEXT_PROFILE_MASK, /// OpenGL context sharing; defaults to 0 ShareWithCurrentContext = SDL_GL_SHARE_WITH_CURRENT_CONTEXT, /// requests sRGB capable visual; defaults to 0 FramebufferSRGBCapable = SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /// sets context the release behavior; defaults to 1 ContextReleaseBehavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR, } /// Requests an OpenGL Compatibility context. pub const CONTEXT_PROFILE_COMPATIBILITY: i32 = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY as i32; /// Requests an OpenGL Core context. pub const CONTEXT_PROFILE_CORE: i32 = SDL_GL_CONTEXT_PROFILE_CORE as i32; /// Requests an OpenGL ES context. pub const CONTEXT_PROFILE_ES: i32 = SDL_GL_CONTEXT_PROFILE_ES as i32; /// A flag for use with [`GLattr::ContextFlags`]. /// /// This flag maps to `GLX_CONTEXT_DEBUG_BIT_ARB` in the /// `GLX_ARB_create_context` extension for X11 and `WGL_CONTEXT_DEBUG_BIT_ARB` /// in the `WGL_ARB_create_context` extension for Windows. This flag is /// currently ignored on other targets that don't support equivalent /// functionality. This flag is intended to put the GL into a "debug" mode which /// might offer better developer insights, possibly at a loss of performance /// (although a given GL implementation may or may not do anything differently /// in the presence of this flag). pub const CONTEXT_DEBUG_FLAG: i32 = SDL_GL_CONTEXT_DEBUG_FLAG as i32; /// A flag for use with [`GLattr::ContextFlags`]. /// /// This flag maps to `GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB` in the /// `GLX_ARB_create_context` extension for X11 and /// `WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB` in the `WGL_ARB_create_context` /// extension for Windows. This flag is currently ignored on other targets that /// don't support equivalent functionality. This flag is intended to put the GL /// into a "forward compatible" mode, which means that no deprecated /// functionality will be supported, possibly at a gain in performance, and only /// applies to GL 3.0 and later contexts. pub const CONTEXT_FORWARD_COMPATIBLE_FLAG: i32 = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG as i32; /// A flag for use with [`GLattr::ContextFlags`]. /// /// This flag maps to `GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB` in the /// `GLX_ARB_create_context_robustness` extension for X11 and /// `WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB` in the `WGL_ARB_create_context_robustness` /// extension for Windows. This flag is currently ignored on other targets that /// don't support equivalent functionality. This flag is intended to require a /// GL context that supports the GL_ARB_robustness extension--a mode that offers /// a few APIs that are safer than the usual defaults (think `snprintf()` vs /// `sprintf()`). pub const CONTEXT_ROBUST_ACCESS_FLAG: i32 = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG as i32; /// A flag for use with [`GLattr::ContextFlags`]. /// /// This flag maps to `GLX_CONTEXT_RESET_ISOLATION_BIT_ARB` in the /// `GLX_ARB_robustness_isolation` extension for X11 and /// `WGL_CONTEXT_RESET_ISOLATION_BIT_ARB` in the `WGL_ARB_robustness_isolation` /// extension for Windows. This flag is currently ignored on other targets that /// don't support equivalent functionality. This flag is intended to require the /// GL to make promises about what to do in the face of driver or hardware /// failure. pub const CONTEXT_RESET_ISOLATION_FLAG: i32 = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG as i32; /// A GLWindow is a [Window] with an OpenGL context bundled in. /// /// This will [Deref](core::ops::Deref) to the inner window, or you can call /// OpenGL related methods. /// /// ## General OpenGL Unsafety /// /// It's possible to have more than one OpenGL context in the world. All of the /// `unsafe` methods here require that this context is the current one when /// calling them. Use [GLWindow::is_current] check and [GLWindow::make_current] /// if needed. Of course, if you only have a single OpenGL context in your /// program you'll always have the current one. #[derive(Debug)] pub struct GLWindow<'sdl> { pub(crate) ctx: SDL_GLContext, pub(crate) window: Window<'sdl>, } impl<'sdl> Drop for GLWindow<'sdl> { fn drop(&mut self) { unsafe { SDL_GL_DeleteContext(self.ctx) } } } impl<'sdl> Deref for GLWindow<'sdl> { type Target = Window<'sdl>; fn deref(&self) -> &Self::Target { &self.window } } impl<'sdl> GLWindow<'sdl> { /// Checks if the given extension is available in this context. pub unsafe fn extension_supported(&self, name: &str) -> bool { let name_null: Vec<u8> = name.bytes().chain(Some(0)).collect(); SDL_TRUE == SDL_GL_ExtensionSupported(name_null.as_ptr() as *const c_char) } /// Obtains the actual value of the attribute for this context. /// /// Note that the context you request and the context that you get might not /// match, because yay. pub unsafe fn get_attribute(&self, attr: GLattr) -> Result<i32, String> { let mut output = 0; if 0 == SDL_GL_GetAttribute(attr as fermium::SDL_GLattr::Type, &mut output) { Ok(output) } else { Err(get_error()) } } /// Determines the swap interval of the video display. /// /// * 0: No vsync /// * 1: Vsync /// * -1: "adaptive vsync", late swaps will happen immediately /// /// If the swap interval can't be determined this returns 0 as a "safe /// default". You can also call [get_error](get_error) to potentially find out /// more. pub unsafe fn swap_interval(&self) -> i32 { SDL_GL_GetSwapInterval() } /// Attempts to set the swap interval value. /// /// The values work as per [swap_interval](GLWindow::swap_interval). /// /// Note that if you request adaptive vsync and get an error it is likely that /// standard vsync might still be available as a fallback. pub unsafe fn set_swap_interval(&self, interval: i32) -> Result<(), String> { let out = SDL_GL_SetSwapInterval(interval); if out == 0 { Ok(()) } else { Err(get_error()) } } /// Checks if this context is current. pub fn is_current(&self) -> bool { let cur = unsafe { SDL_GL_GetCurrentContext() }; self.ctx == cur } /// Makes the given context the current context in this window. pub fn make_current(&self) -> Result<(), String> { let out = unsafe { SDL_GL_MakeCurrent(self.window.ptr, self.ctx) }; if out == 0 { Ok(()) } else { Err(get_error()) } } /// Obtains the size of the drawable space in the window. /// /// This gives you a number of "physical pixels", so it might be different /// from the "logical pixels" value you get when you call /// [size](Window::size). This is primarily for use with /// [glViewport](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glViewport.xhtml) pub fn drawable_size(&self) -> (i32, i32) { let mut w = 0; let mut h = 0; unsafe { SDL_GL_GetDrawableSize(self.window.ptr, &mut w, &mut h) }; (w, h) } /// Swaps the window's OpenGL buffers. /// /// If double buffering isn't enabled this just does nothing. pub unsafe fn swap_window(&self) { SDL_GL_SwapWindow(self.window.ptr) } }