@@ -54,371 +54,3 @@ impl Drop for Context {
5454 }
5555 }
5656}
57-
58- impl Device {
59- /// Creates a context descriptor with the given attributes.
60- ///
61- /// Context descriptors are local to this device.
62- #[ inline]
63- pub fn create_context_descriptor (
64- & self ,
65- attributes : & ContextAttributes ,
66- ) -> Result < ContextDescriptor , Error > {
67- unsafe {
68- ContextDescriptor :: new (
69- self . egl_display ,
70- attributes,
71- & [
72- egl:: BIND_TO_TEXTURE_RGBA as EGLint ,
73- 1 as EGLint ,
74- egl:: SURFACE_TYPE as EGLint ,
75- egl:: PBUFFER_BIT as EGLint ,
76- egl:: RENDERABLE_TYPE as EGLint ,
77- egl:: OPENGL_ES2_BIT as EGLint ,
78- ] ,
79- )
80- }
81- }
82-
83- /// Creates a new OpenGL context.
84- ///
85- /// The context initially has no surface attached. Until a surface is bound to it, rendering
86- /// commands will fail or have no effect.
87- pub fn create_context (
88- & self ,
89- descriptor : & ContextDescriptor ,
90- share_with : Option < & Context > ,
91- ) -> Result < Context , Error > {
92- let ( egl_context, id) = {
93- let mut next_context_id_lock = CREATE_CONTEXT_MUTEX . lock ( ) . unwrap ( ) ;
94- let egl_context = unsafe {
95- context:: create_context (
96- self . egl_display ,
97- descriptor,
98- share_with. map_or ( egl:: NO_CONTEXT , |ctx| ctx. egl_context ) ,
99- self . gl_api ( ) ,
100- ) ?
101- } ;
102- next_context_id_lock. 0 += 1 ;
103- ( egl_context, * next_context_id_lock)
104- } ;
105-
106- unsafe {
107- EGL_FUNCTIONS . with ( |egl| {
108- let result = egl. MakeCurrent (
109- self . egl_display ,
110- egl:: NO_SURFACE ,
111- egl:: NO_SURFACE ,
112- egl_context,
113- ) ;
114- if result == egl:: FALSE {
115- return Err ( Error :: MakeCurrentFailed (
116- egl. GetError ( ) . to_windowing_api_error ( ) ,
117- ) ) ;
118- }
119- Ok ( ( ) )
120- } ) ?;
121- }
122-
123- let context = Context {
124- egl_context,
125- id,
126- framebuffer : Framebuffer :: None ,
127- context_is_owned : true ,
128- gl : unsafe { Gl :: from_loader_function ( context:: get_proc_address) } ,
129- } ;
130- Ok ( context)
131- }
132-
133- /// Wraps a native `EGLContext` in a context object.
134- ///
135- /// The underlying `EGLContext` is not retained, as there is no way to do this in the EGL API.
136- /// Therefore, it is the caller's responsibility to keep it alive as long as this `Context`
137- /// remains alive.
138- pub unsafe fn create_context_from_native_context (
139- & self ,
140- native_context : NativeContext ,
141- ) -> Result < Context , Error > {
142- let mut next_context_id = CREATE_CONTEXT_MUTEX . lock ( ) . unwrap ( ) ;
143-
144- // Create the context.
145- let context = Context {
146- egl_context : native_context. egl_context ,
147- id : * next_context_id,
148- framebuffer : Framebuffer :: External ( ExternalEGLSurfaces {
149- draw : native_context. egl_draw_surface ,
150- read : native_context. egl_read_surface ,
151- } ) ,
152- context_is_owned : false ,
153- gl : Gl :: from_loader_function ( context:: get_proc_address) ,
154- } ;
155- next_context_id. 0 += 1 ;
156-
157- Ok ( context)
158- }
159-
160- /// Destroys a context.
161- ///
162- /// The context must have been created on this device.
163- pub fn destroy_context ( & self , context : & mut Context ) -> Result < ( ) , Error > {
164- if context. egl_context == egl:: NO_CONTEXT {
165- return Ok ( ( ) ) ;
166- }
167-
168- if let Ok ( Some ( mut surface) ) = self . unbind_surface_from_context ( context) {
169- self . destroy_surface ( context, & mut surface) ?;
170- }
171-
172- EGL_FUNCTIONS . with ( |egl| unsafe {
173- egl. MakeCurrent (
174- self . egl_display ,
175- egl:: NO_SURFACE ,
176- egl:: NO_SURFACE ,
177- egl:: NO_CONTEXT ,
178- ) ;
179-
180- if context. context_is_owned {
181- let result = egl. DestroyContext ( self . egl_display , context. egl_context ) ;
182- assert_ne ! ( result, egl:: FALSE ) ;
183- }
184-
185- context. egl_context = egl:: NO_CONTEXT ;
186- } ) ;
187-
188- Ok ( ( ) )
189- }
190-
191- /// Returns the descriptor that this context was created with.
192- pub fn context_descriptor ( & self , context : & Context ) -> ContextDescriptor {
193- unsafe {
194- ContextDescriptor :: from_egl_context ( & context. gl , self . egl_display , context. egl_context )
195- }
196- }
197-
198- /// Makes the context the current OpenGL context for this thread.
199- ///
200- /// After calling this function, it is valid to use OpenGL rendering commands.
201- pub fn make_context_current ( & self , context : & Context ) -> Result < ( ) , Error > {
202- unsafe {
203- let ( egl_draw_surface, egl_read_surface) = match context. framebuffer {
204- Framebuffer :: Surface ( ref surface) => ( surface. egl_surface , surface. egl_surface ) ,
205- Framebuffer :: None => ( egl:: NO_SURFACE , egl:: NO_SURFACE ) ,
206- Framebuffer :: External ( ref surfaces) => ( surfaces. draw , surfaces. read ) ,
207- } ;
208-
209- EGL_FUNCTIONS . with ( |egl| {
210- let result = egl. MakeCurrent (
211- self . egl_display ,
212- egl_draw_surface,
213- egl_read_surface,
214- context. egl_context ,
215- ) ;
216- if result == egl:: FALSE {
217- let err = egl. GetError ( ) . to_windowing_api_error ( ) ;
218- return Err ( Error :: MakeCurrentFailed ( err) ) ;
219- }
220- Ok ( ( ) )
221- } )
222- }
223- }
224-
225- /// Removes the current OpenGL context from this thread.
226- ///
227- /// After calling this function, OpenGL rendering commands will fail until a new context is
228- /// made current.
229- pub fn make_no_context_current ( & self ) -> Result < ( ) , Error > {
230- unsafe { context:: make_no_context_current ( self . egl_display ) }
231- }
232-
233- pub ( crate ) fn temporarily_make_context_current (
234- & self ,
235- context : & Context ,
236- ) -> Result < CurrentContextGuard , Error > {
237- let guard = CurrentContextGuard :: new ( ) ;
238- self . make_context_current ( context) ?;
239- Ok ( guard)
240- }
241-
242- pub ( crate ) fn context_is_current ( & self , context : & Context ) -> bool {
243- EGL_FUNCTIONS . with ( |egl| unsafe { egl. GetCurrentContext ( ) == context. egl_context } )
244- }
245-
246- /// Returns the attributes that the context descriptor was created with.
247- #[ inline]
248- pub fn context_descriptor_attributes (
249- & self ,
250- context_descriptor : & ContextDescriptor ,
251- ) -> ContextAttributes {
252- unsafe { context_descriptor. attributes ( self . egl_display ) }
253- }
254-
255- /// Fetches the address of an OpenGL function associated with this context.
256- ///
257- /// OpenGL functions are local to a context. You should not use OpenGL functions on one context
258- /// with any other context.
259- ///
260- /// This method is typically used with a function like `gl::load_with()` from the `gl` crate to
261- /// load OpenGL function pointers.
262- #[ inline]
263- pub fn get_proc_address ( & self , _: & Context , symbol_name : & str ) -> * const c_void {
264- context:: get_proc_address ( symbol_name)
265- }
266-
267- #[ inline]
268- pub ( crate ) fn context_descriptor_to_egl_config (
269- & self ,
270- context_descriptor : & ContextDescriptor ,
271- ) -> EGLConfig {
272- unsafe { context:: egl_config_from_id ( self . egl_display , context_descriptor. egl_config_id ) }
273- }
274-
275- /// Attaches a surface to a context for rendering.
276- ///
277- /// This function takes ownership of the surface. The surface must have been created with this
278- /// context, or an `IncompatibleSurface` error is returned.
279- ///
280- /// If this function is called with a surface already bound, a `SurfaceAlreadyBound` error is
281- /// returned. To avoid this error, first unbind the existing surface with
282- /// `unbind_surface_from_context`.
283- ///
284- /// If an error is returned, the surface is returned alongside it.
285- pub fn bind_surface_to_context (
286- & self ,
287- context : & mut Context ,
288- surface : Surface ,
289- ) -> Result < ( ) , ( Error , Surface ) > {
290- if context. id != surface. context_id {
291- return Err ( ( Error :: IncompatibleSurface , surface) ) ;
292- }
293-
294- match context. framebuffer {
295- Framebuffer :: None => { }
296- Framebuffer :: External ( _) => return Err ( ( Error :: ExternalRenderTarget , surface) ) ,
297- Framebuffer :: Surface ( _) => return Err ( ( Error :: SurfaceAlreadyBound , surface) ) ,
298- }
299-
300- // If the surface is synchronized with GLFinish, then finish.
301- // FIXME(pcwalton): Is this necessary and sufficient?
302- if surface. uses_gl_finish ( ) {
303- if let Ok ( _guard) = self . temporarily_make_context_current ( context) {
304- unsafe {
305- context. gl . finish ( ) ;
306- }
307- }
308- }
309-
310- let is_current = self . context_is_current ( context) ;
311-
312- match surface. win32_objects {
313- Win32Objects :: Pbuffer {
314- synchronization : Synchronization :: KeyedMutex ( ref keyed_mutex) ,
315- ..
316- } => unsafe {
317- let result = keyed_mutex. AcquireSync ( 0 , INFINITE ) ;
318- assert_eq ! ( result, S_OK ) ;
319- } ,
320- _ => { }
321- }
322-
323- context. framebuffer = Framebuffer :: Surface ( surface) ;
324-
325- if is_current {
326- // We need to make ourselves current again, because the surface changed.
327- drop ( self . make_context_current ( context) ) ;
328- }
329-
330- Ok ( ( ) )
331- }
332-
333- /// Removes and returns any attached surface from this context.
334- ///
335- /// Any pending OpenGL commands targeting this surface will be automatically flushed, so the
336- /// surface is safe to read from immediately when this function returns.
337- pub fn unbind_surface_from_context (
338- & self ,
339- context : & mut Context ,
340- ) -> Result < Option < Surface > , Error > {
341- match context. framebuffer {
342- Framebuffer :: None => return Ok ( None ) ,
343- Framebuffer :: External ( _) => return Err ( Error :: ExternalRenderTarget ) ,
344- Framebuffer :: Surface ( _) => { }
345- }
346-
347- let surface = match mem:: replace ( & mut context. framebuffer , Framebuffer :: None ) {
348- Framebuffer :: Surface ( surface) => surface,
349- Framebuffer :: None | Framebuffer :: External ( _) => unreachable ! ( ) ,
350- } ;
351-
352- match surface. win32_objects {
353- Win32Objects :: Pbuffer {
354- synchronization : Synchronization :: KeyedMutex ( ref keyed_mutex) ,
355- ..
356- } => unsafe {
357- let result = keyed_mutex. ReleaseSync ( 0 ) ;
358- assert_eq ! ( result, S_OK ) ;
359- } ,
360- _ => { }
361- }
362-
363- Ok ( Some ( surface) )
364- }
365-
366- /// Displays the contents of the currently bound surface to the screen, if
367- /// it is a widget surface.
368- ///
369- /// Widget surfaces are internally double-buffered, so changes to them don't
370- /// show up in their associated widgets until this method is called.
371- pub fn present_bound_surface ( & self , context : & mut Context ) -> Result < ( ) , Error > {
372- match & context. framebuffer {
373- Framebuffer :: Surface ( surface) => surface. present ( self ) ,
374- _ => Ok ( ( ) ) ,
375- }
376- }
377-
378- /// If the currently bound surface is a widget surface, resize it,
379- pub fn resize_bound_surface (
380- & self ,
381- context : & mut Context ,
382- size : Size2D < i32 > ,
383- ) -> Result < ( ) , Error > {
384- if let Framebuffer :: Surface ( surface) = & mut context. framebuffer {
385- surface. resize ( size) ;
386- }
387- Ok ( ( ) )
388- }
389-
390- /// Returns a unique ID representing a context.
391- ///
392- /// This ID is unique to all currently-allocated contexts. If you destroy a context and create
393- /// a new one, the new context might have the same ID as the destroyed one.
394- #[ inline]
395- pub fn context_id ( & self , context : & Context ) -> ContextID {
396- context. id
397- }
398-
399- /// Returns various information about the surface attached to a context.
400- ///
401- /// This includes, most notably, the OpenGL framebuffer object needed to render to the surface.
402- pub fn context_surface_info ( & self , context : & Context ) -> Result < Option < SurfaceInfo > , Error > {
403- match context. framebuffer {
404- Framebuffer :: None => Ok ( None ) ,
405- Framebuffer :: External ( _) => Err ( Error :: ExternalRenderTarget ) ,
406- Framebuffer :: Surface ( ref surface) => Ok ( Some ( self . surface_info ( surface) ) ) ,
407- }
408- }
409-
410- /// Given a context, returns its underlying EGL context and attached surfaces.
411- pub fn native_context ( & self , context : & Context ) -> NativeContext {
412- let ( egl_draw_surface, egl_read_surface) = match context. framebuffer {
413- Framebuffer :: Surface ( Surface { egl_surface, .. } ) => ( egl_surface, egl_surface) ,
414- Framebuffer :: External ( ExternalEGLSurfaces { draw, read } ) => ( draw, read) ,
415- Framebuffer :: None => ( egl:: NO_SURFACE , egl:: NO_SURFACE ) ,
416- } ;
417-
418- NativeContext {
419- egl_context : context. egl_context ,
420- egl_draw_surface,
421- egl_read_surface,
422- }
423- }
424- }
0 commit comments