use crate::core::error::Result as OclCoreResult;
use crate::core::{
self, ClContextPtr, ClVersions, Context as ContextCore, ContextInfo, ContextInfoResult,
ContextProperties, ContextPropertyValue, CreateContextCallbackFn, DeviceInfo, DeviceInfoResult,
OpenclVersion, PlatformInfo, PlatformInfoResult, UserDataPtr,
};
use crate::error::{Error as OclError, Result as OclResult};
use crate::ffi::cl_context;
use crate::standard::{Device, DeviceSpecifier, Platform};
use std;
use std::ops::{Deref, DerefMut};
#[derive(Debug, Clone)]
pub struct Context(ContextCore);
impl Context {
pub fn builder() -> ContextBuilder {
ContextBuilder::new()
}
pub fn new(
properties: Option<ContextProperties>,
device_spec: Option<DeviceSpecifier>,
pfn_notify: Option<CreateContextCallbackFn>,
user_data: Option<UserDataPtr>,
) -> OclResult<Context> {
assert!(
pfn_notify.is_none() && user_data.is_none(),
"Context creation callbacks not yet implemented - file issue if you need this."
);
let platform: Option<Platform> = match properties {
Some(ref props) => props.get_platform().map(Platform::new),
None => None,
};
let device_spec = match device_spec {
Some(ds) => ds,
None => DeviceSpecifier::All,
};
let device_list = device_spec.to_device_list(platform)?;
let obj_core =
core::create_context(properties.as_ref(), &device_list, pfn_notify, user_data)?;
Ok(Context(obj_core))
}
pub fn resolve_wrapping_device_idxs(&self, idxs: &[usize]) -> Vec<Device> {
Device::resolve_idxs_wrap(idxs, &self.devices())
}
pub fn get_device_by_wrapping_index(&self, index: usize) -> Device {
self.resolve_wrapping_device_idxs(&[index; 1])[0]
}
pub fn platform_info(&self, info_kind: PlatformInfo) -> OclResult<PlatformInfoResult> {
match self.platform() {
Ok(plat_opt) => match plat_opt {
Some(ref p) => core::get_platform_info(p, info_kind).map_err(OclError::from),
None => Err(OclError::from(
"Context::platform_info: \
This context has no associated platform.",
)),
},
Err(err) => Err(err),
}
}
pub fn device_info(&self, index: usize, info_kind: DeviceInfo) -> OclResult<DeviceInfoResult> {
match self.devices().get(index) {
Some(d) => core::get_device_info(d, info_kind).map_err(OclError::from),
None => Err(OclError::from("Context::device_info: Invalid device index")),
}
}
pub fn info(&self, info_kind: ContextInfo) -> OclResult<ContextInfoResult> {
core::get_context_info(&self.0, info_kind).map_err(OclError::from)
}
#[inline]
pub fn as_core(&self) -> &ContextCore {
&self.0
}
pub fn devices(&self) -> Vec<Device> {
Device::list_from_core(self.0.devices().unwrap())
}
pub fn device_versions(&self) -> OclResult<Vec<OpenclVersion>> {
Device::list_from_core(self.0.devices().map_err(OclError::from)?)
.into_iter()
.map(|d| d.version().map_err(OclError::from))
.collect()
}
pub fn platform(&self) -> OclResult<Option<Platform>> {
self.0
.platform()
.map(|opt| opt.map(Platform::from))
.map_err(OclError::from)
}
fn fmt_info(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Context")
.field("ReferenceCount", &self.info(ContextInfo::ReferenceCount))
.field("Devices", &self.info(ContextInfo::Devices))
.field("Properties", &self.info(ContextInfo::Properties))
.field("NumDevices", &self.info(ContextInfo::NumDevices))
.finish()
}
}
impl From<ContextCore> for Context {
fn from(c: ContextCore) -> Context {
Context(c)
}
}
impl std::fmt::Display for Context {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.fmt_info(f)
}
}
impl Deref for Context {
type Target = ContextCore;
fn deref(&self) -> &ContextCore {
&self.0
}
}
impl DerefMut for Context {
fn deref_mut(&mut self) -> &mut ContextCore {
&mut self.0
}
}
unsafe impl<'a> ClContextPtr for &'a Context {
fn as_ptr(&self) -> cl_context {
self.0.as_ptr()
}
}
impl ClVersions for Context {
fn device_versions(&self) -> OclCoreResult<Vec<OpenclVersion>> {
self.0.device_versions()
}
fn platform_version(&self) -> OclCoreResult<OpenclVersion> {
self.0.platform_version()
}
}
impl<'a> ClVersions for &'a Context {
fn device_versions(&self) -> OclCoreResult<Vec<OpenclVersion>> {
self.0.device_versions()
}
fn platform_version(&self) -> OclCoreResult<OpenclVersion> {
self.0.platform_version()
}
}
#[must_use = "builders do nothing unless '::build' is called"]
pub struct ContextBuilder {
properties: ContextProperties,
device_spec: Option<DeviceSpecifier>,
}
impl ContextBuilder {
pub fn new() -> ContextBuilder {
let properties = ContextProperties::new();
ContextBuilder {
properties,
device_spec: None,
}
}
pub fn properties<'a>(&'a mut self, properties: ContextProperties) -> &'a mut ContextBuilder {
self.properties = properties;
self
}
pub fn property<'a>(&'a mut self, prop_val: ContextPropertyValue) -> &'a mut ContextBuilder {
self.properties.set_property_value(prop_val);
self
}
pub fn platform(&mut self, platform: Platform) -> &mut ContextBuilder {
self.properties.set_platform(platform);
self
}
pub fn gl_context(&mut self, gl_handle: *mut crate::ffi::c_void) -> &mut ContextBuilder {
self.properties.set_gl_context(gl_handle);
self
}
pub fn glx_display(&mut self, glx_display: *mut crate::ffi::c_void) -> &mut ContextBuilder {
self.properties.set_glx_display(glx_display);
self
}
pub fn devices<D: Into<DeviceSpecifier>>(&mut self, device_spec: D) -> &mut ContextBuilder {
assert!(
self.device_spec.is_none(),
"ocl::ContextBuilder::devices: Devices already specified"
);
self.device_spec = Some(device_spec.into());
self
}
pub fn build(&self) -> OclResult<Context> {
let mut props = self.properties.clone();
if props.get_platform().is_none() {
props.set_platform(Platform::default());
}
Context::new(Some(props), self.device_spec.clone(), None, None)
}
}