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
54impl<Def, Alt> Device<Def, Alt>
55where
56 Def: DeviceInterface,
57 Alt: DeviceInterface,
58{
59 pub fn create_context_descriptor(
63 &self,
64 attributes: &ContextAttributes,
65 ) -> Result<ContextDescriptor<Def, Alt>, Error> {
66 match *self {
67 Device::Default(ref device) => device
68 .create_context_descriptor(attributes)
69 .map(ContextDescriptor::Default),
70 Device::Alternate(ref device) => device
71 .create_context_descriptor(attributes)
72 .map(ContextDescriptor::Alternate),
73 }
74 }
75
76 pub fn create_context(
81 &self,
82 descriptor: &ContextDescriptor<Def, Alt>,
83 share_with: Option<&Context<Def, Alt>>,
84 ) -> Result<Context<Def, Alt>, Error> {
85 match (self, descriptor) {
86 (Device::Default(device), ContextDescriptor::Default(descriptor)) => {
87 let shared = match share_with {
88 Some(Context::Default(other)) => Some(other),
89 Some(_) => {
90 return Err(Error::IncompatibleSharedContext);
91 }
92 None => None,
93 };
94 device
95 .create_context(descriptor, shared)
96 .map(Context::Default)
97 }
98 (Device::Alternate(device), ContextDescriptor::Alternate(descriptor)) => {
99 let shared = match share_with {
100 Some(Context::Alternate(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::Alternate)
109 }
110 _ => Err(Error::IncompatibleContextDescriptor),
111 }
112 }
113
114 pub fn destroy_context(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
118 match (self, &mut *context) {
119 (Device::Default(device), &mut Context::Default(ref mut context)) => {
120 device.destroy_context(context)
121 }
122 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => {
123 device.destroy_context(context)
124 }
125 _ => Err(Error::IncompatibleContext),
126 }
127 }
128
129 pub fn context_descriptor(&self, context: &Context<Def, Alt>) -> ContextDescriptor<Def, Alt> {
131 match (self, context) {
132 (Device::Default(device), Context::Default(context)) => {
133 ContextDescriptor::Default(device.context_descriptor(context))
134 }
135 (Device::Alternate(device), Context::Alternate(context)) => {
136 ContextDescriptor::Alternate(device.context_descriptor(context))
137 }
138 _ => panic!("Incompatible context!"),
139 }
140 }
141
142 pub fn make_context_current(&self, context: &Context<Def, Alt>) -> Result<(), Error> {
146 match (self, context) {
147 (Device::Default(device), Context::Default(context)) => {
148 device.make_context_current(context)
149 }
150 (Device::Alternate(device), Context::Alternate(context)) => {
151 device.make_context_current(context)
152 }
153 _ => Err(Error::IncompatibleContext),
154 }
155 }
156
157 pub fn make_no_context_current(&self) -> Result<(), Error> {
162 match self {
163 Device::Default(device) => device.make_no_context_current(),
164 Device::Alternate(device) => device.make_no_context_current(),
165 }
166 }
167
168 pub fn bind_surface_to_context(
179 &self,
180 context: &mut Context<Def, Alt>,
181 surface: Surface<Def, Alt>,
182 ) -> Result<(), (Error, Surface<Def, Alt>)> {
183 match (self, &mut *context) {
184 (Device::Default(device), &mut Context::Default(ref mut context)) => match surface {
185 Surface::Default(surface) => device
186 .bind_surface_to_context(context, surface)
187 .map_err(|(err, surface)| (err, Surface::Default(surface))),
188 _ => Err((Error::IncompatibleSurface, surface)),
189 },
190 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => {
191 match surface {
192 Surface::Alternate(surface) => device
193 .bind_surface_to_context(context, surface)
194 .map_err(|(err, surface)| (err, Surface::Alternate(surface))),
195 _ => Err((Error::IncompatibleSurface, surface)),
196 }
197 }
198 _ => Err((Error::IncompatibleContext, surface)),
199 }
200 }
201
202 pub fn unbind_surface_from_context(
207 &self,
208 context: &mut Context<Def, Alt>,
209 ) -> Result<Option<Surface<Def, Alt>>, Error> {
210 match (self, &mut *context) {
211 (Device::Default(device), &mut Context::Default(ref mut context)) => device
212 .unbind_surface_from_context(context)
213 .map(|surface| surface.map(Surface::Default)),
214 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => device
215 .unbind_surface_from_context(context)
216 .map(|surface| surface.map(Surface::Alternate)),
217 _ => Err(Error::IncompatibleContext),
218 }
219 }
220
221 pub fn present_bound_surface(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
227 match (self, context) {
228 (Device::Default(device), Context::Default(context)) => {
229 device.present_bound_surface(context)
230 }
231 (Device::Alternate(device), Context::Alternate(context)) => {
232 device.present_bound_surface(context)
233 }
234 _ => Err(Error::IncompatibleContext),
235 }
236 }
237
238 pub fn resize_bound_surface(
240 &self,
241 context: &mut Context<Def, Alt>,
242 size: Size2D<i32>,
243 ) -> Result<(), Error> {
244 match (self, context) {
245 (Device::Default(device), Context::Default(context)) => {
246 device.resize_bound_surface(context, size)
247 }
248 (Device::Alternate(device), Context::Alternate(context)) => {
249 device.resize_bound_surface(context, size)
250 }
251 _ => Err(Error::IncompatibleContext),
252 }
253 }
254
255 pub fn context_descriptor_attributes(
257 &self,
258 context_descriptor: &ContextDescriptor<Def, Alt>,
259 ) -> ContextAttributes {
260 match (self, context_descriptor) {
261 (Device::Default(device), ContextDescriptor::Default(context_descriptor)) => {
262 device.context_descriptor_attributes(context_descriptor)
263 }
264 (Device::Alternate(device), ContextDescriptor::Alternate(context_descriptor)) => {
265 device.context_descriptor_attributes(context_descriptor)
266 }
267 _ => panic!("Incompatible context!"),
268 }
269 }
270
271 pub fn get_proc_address(
279 &self,
280 context: &Context<Def, Alt>,
281 symbol_name: &str,
282 ) -> *const c_void {
283 match (self, context) {
284 (Device::Default(device), Context::Default(context)) => {
285 device.get_proc_address(context, symbol_name)
286 }
287 (Device::Alternate(device), Context::Alternate(context)) => {
288 device.get_proc_address(context, symbol_name)
289 }
290 _ => panic!("Incompatible context!"),
291 }
292 }
293
294 pub fn context_id(&self, context: &Context<Def, Alt>) -> ContextID {
299 match (self, context) {
300 (Device::Default(device), Context::Default(context)) => device.context_id(context),
301 (Device::Alternate(device), Context::Alternate(context)) => device.context_id(context),
302 _ => panic!("Incompatible context!"),
303 }
304 }
305
306 pub fn context_surface_info(
310 &self,
311 context: &Context<Def, Alt>,
312 ) -> Result<Option<SurfaceInfo>, Error> {
313 match (self, context) {
314 (Device::Default(device), Context::Default(context)) => {
315 device.context_surface_info(context)
316 }
317 (Device::Alternate(device), Context::Alternate(context)) => {
318 device.context_surface_info(context)
319 }
320 _ => Err(Error::IncompatibleContext),
321 }
322 }
323}