1use euclid::default::Size2D;
4
5use super::device::Device;
6use super::surface::Surface;
7use crate::device::Device as DeviceInterface;
8use crate::{ContextAttributes, ContextID, Error, SurfaceInfo};
9
10use std::os::raw::c_void;
11
12pub enum Context<Def, Alt>
29where
30 Def: DeviceInterface,
31 Alt: DeviceInterface,
32{
33 Default(Def::Context),
35 Alternate(Alt::Context),
37}
38
39#[derive(Clone)]
43pub enum ContextDescriptor<Def, Alt>
44where
45 Def: DeviceInterface,
46 Alt: DeviceInterface,
47{
48 Default(Def::ContextDescriptor),
50 Alternate(Alt::ContextDescriptor),
52}
53
54pub enum NativeContext<Def, Alt>
56where
57 Def: DeviceInterface,
58 Alt: DeviceInterface,
59{
60 Default(Def::NativeContext),
62 Alternate(Alt::NativeContext),
64}
65
66impl<Def, Alt> Device<Def, Alt>
67where
68 Def: DeviceInterface,
69 Alt: DeviceInterface,
70{
71 pub fn create_context_descriptor(
75 &self,
76 attributes: &ContextAttributes,
77 ) -> Result<ContextDescriptor<Def, Alt>, Error> {
78 match *self {
79 Device::Default(ref device) => device
80 .create_context_descriptor(attributes)
81 .map(ContextDescriptor::Default),
82 Device::Alternate(ref device) => device
83 .create_context_descriptor(attributes)
84 .map(ContextDescriptor::Alternate),
85 }
86 }
87
88 pub fn create_context(
93 &self,
94 descriptor: &ContextDescriptor<Def, Alt>,
95 share_with: Option<&Context<Def, Alt>>,
96 ) -> Result<Context<Def, Alt>, Error> {
97 match (self, descriptor) {
98 (&Device::Default(ref device), ContextDescriptor::Default(descriptor)) => {
99 let shared = match share_with {
100 Some(Context::Default(other)) => Some(other),
101 Some(_) => {
102 return Err(Error::IncompatibleSharedContext);
103 }
104 None => None,
105 };
106 device
107 .create_context(descriptor, shared)
108 .map(Context::Default)
109 }
110 (&Device::Alternate(ref device), ContextDescriptor::Alternate(descriptor)) => {
111 let shared = match share_with {
112 Some(Context::Alternate(other)) => Some(other),
113 Some(_) => {
114 return Err(Error::IncompatibleSharedContext);
115 }
116 None => None,
117 };
118 device
119 .create_context(descriptor, shared)
120 .map(Context::Alternate)
121 }
122 _ => Err(Error::IncompatibleContextDescriptor),
123 }
124 }
125
126 pub unsafe fn create_context_from_native_context(
128 &self,
129 native_context: NativeContext<Def, Alt>,
130 ) -> Result<Context<Def, Alt>, Error> {
131 match self {
132 Device::Default(device) => match native_context {
133 NativeContext::Default(native_context) => device
134 .create_context_from_native_context(native_context)
135 .map(Context::Default),
136 _ => Err(Error::IncompatibleNativeContext),
137 },
138 Device::Alternate(device) => match native_context {
139 NativeContext::Alternate(native_context) => device
140 .create_context_from_native_context(native_context)
141 .map(Context::Alternate),
142 _ => Err(Error::IncompatibleNativeContext),
143 },
144 }
145 }
146
147 pub fn destroy_context(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
151 match (self, &mut *context) {
152 (Device::Default(device), &mut Context::Default(ref mut context)) => {
153 device.destroy_context(context)
154 }
155 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => {
156 device.destroy_context(context)
157 }
158 _ => Err(Error::IncompatibleContext),
159 }
160 }
161
162 pub fn native_context(&self, context: &Context<Def, Alt>) -> NativeContext<Def, Alt> {
164 match (self, context) {
165 (Device::Default(device), Context::Default(context)) => {
166 NativeContext::Default(device.native_context(context))
167 }
168 (Device::Alternate(device), Context::Alternate(context)) => {
169 NativeContext::Alternate(device.native_context(context))
170 }
171 _ => panic!("Incompatible context!"),
172 }
173 }
174
175 pub fn context_descriptor(&self, context: &Context<Def, Alt>) -> ContextDescriptor<Def, Alt> {
177 match (self, context) {
178 (Device::Default(device), Context::Default(context)) => {
179 ContextDescriptor::Default(device.context_descriptor(context))
180 }
181 (Device::Alternate(device), Context::Alternate(context)) => {
182 ContextDescriptor::Alternate(device.context_descriptor(context))
183 }
184 _ => panic!("Incompatible context!"),
185 }
186 }
187
188 pub fn make_context_current(&self, context: &Context<Def, Alt>) -> Result<(), Error> {
192 match (self, context) {
193 (Device::Default(device), Context::Default(context)) => {
194 device.make_context_current(context)
195 }
196 (Device::Alternate(device), Context::Alternate(context)) => {
197 device.make_context_current(context)
198 }
199 _ => Err(Error::IncompatibleContext),
200 }
201 }
202
203 pub fn make_no_context_current(&self) -> Result<(), Error> {
208 match self {
209 Device::Default(device) => device.make_no_context_current(),
210 Device::Alternate(device) => device.make_no_context_current(),
211 }
212 }
213
214 pub fn bind_surface_to_context(
225 &self,
226 context: &mut Context<Def, Alt>,
227 surface: Surface<Def, Alt>,
228 ) -> Result<(), (Error, Surface<Def, Alt>)> {
229 match (self, &mut *context) {
230 (Device::Default(device), &mut Context::Default(ref mut context)) => match surface {
231 Surface::Default(surface) => device
232 .bind_surface_to_context(context, surface)
233 .map_err(|(err, surface)| (err, Surface::Default(surface))),
234 _ => Err((Error::IncompatibleSurface, surface)),
235 },
236 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => {
237 match surface {
238 Surface::Alternate(surface) => device
239 .bind_surface_to_context(context, surface)
240 .map_err(|(err, surface)| (err, Surface::Alternate(surface))),
241 _ => Err((Error::IncompatibleSurface, surface)),
242 }
243 }
244 _ => Err((Error::IncompatibleContext, surface)),
245 }
246 }
247
248 pub fn unbind_surface_from_context(
253 &self,
254 context: &mut Context<Def, Alt>,
255 ) -> Result<Option<Surface<Def, Alt>>, Error> {
256 match (self, &mut *context) {
257 (Device::Default(device), &mut Context::Default(ref mut context)) => device
258 .unbind_surface_from_context(context)
259 .map(|surface| surface.map(Surface::Default)),
260 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => device
261 .unbind_surface_from_context(context)
262 .map(|surface| surface.map(Surface::Alternate)),
263 _ => Err(Error::IncompatibleContext),
264 }
265 }
266
267 pub fn present_bound_surface(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
273 match (self, context) {
274 (Device::Default(device), Context::Default(context)) => {
275 device.present_bound_surface(context)
276 }
277 (Device::Alternate(device), Context::Alternate(context)) => {
278 device.present_bound_surface(context)
279 }
280 _ => Err(Error::IncompatibleContext),
281 }
282 }
283
284 pub fn resize_bound_surface(
286 &self,
287 context: &mut Context<Def, Alt>,
288 size: Size2D<i32>,
289 ) -> Result<(), Error> {
290 match (self, context) {
291 (Device::Default(device), Context::Default(context)) => {
292 device.resize_bound_surface(context, size)
293 }
294 (Device::Alternate(device), Context::Alternate(context)) => {
295 device.resize_bound_surface(context, size)
296 }
297 _ => Err(Error::IncompatibleContext),
298 }
299 }
300
301 pub fn context_descriptor_attributes(
303 &self,
304 context_descriptor: &ContextDescriptor<Def, Alt>,
305 ) -> ContextAttributes {
306 match (self, context_descriptor) {
307 (Device::Default(device), ContextDescriptor::Default(context_descriptor)) => {
308 device.context_descriptor_attributes(context_descriptor)
309 }
310 (Device::Alternate(device), ContextDescriptor::Alternate(context_descriptor)) => {
311 device.context_descriptor_attributes(context_descriptor)
312 }
313 _ => panic!("Incompatible context!"),
314 }
315 }
316
317 pub fn get_proc_address(
325 &self,
326 context: &Context<Def, Alt>,
327 symbol_name: &str,
328 ) -> *const c_void {
329 match (self, context) {
330 (Device::Default(device), Context::Default(context)) => {
331 device.get_proc_address(context, symbol_name)
332 }
333 (Device::Alternate(device), Context::Alternate(context)) => {
334 device.get_proc_address(context, symbol_name)
335 }
336 _ => panic!("Incompatible context!"),
337 }
338 }
339
340 pub fn context_id(&self, context: &Context<Def, Alt>) -> ContextID {
345 match (self, context) {
346 (Device::Default(device), Context::Default(context)) => device.context_id(context),
347 (Device::Alternate(device), Context::Alternate(context)) => device.context_id(context),
348 _ => panic!("Incompatible context!"),
349 }
350 }
351
352 pub fn context_surface_info(
356 &self,
357 context: &Context<Def, Alt>,
358 ) -> Result<Option<SurfaceInfo>, Error> {
359 match (self, context) {
360 (Device::Default(device), Context::Default(context)) => {
361 device.context_surface_info(context)
362 }
363 (Device::Alternate(device), Context::Alternate(context)) => {
364 device.context_surface_info(context)
365 }
366 _ => Err(Error::IncompatibleContext),
367 }
368 }
369}