Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/chaos_game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn main() {
}

let connection = SystemConnection::new().unwrap();
let adapter = connection.create_adapter().unwrap();
let adapter = connection.create_adapter(Default::default()).unwrap();
let mut device = connection.create_device(&adapter).unwrap();

let event_loop = EventLoop::new().unwrap();
Expand Down
19 changes: 13 additions & 6 deletions examples/offscreen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use std::fs::File;
use std::mem;
use std::path::Path;
use std::slice;
use surfman::{Connection, ContextAttributeFlags, ContextAttributes, GLApi, GLVersion};
use surfman::{
AdapterPreferences, Connection, ContextAttributeFlags, ContextAttributes, GLApi, GLVersion,
RenderingPreference,
};
use surfman::{SurfaceAccess, SurfaceType};

mod common;
Expand Down Expand Up @@ -85,13 +88,17 @@ fn main() {

let connection = Connection::new().unwrap();

let adapter = if matches.is_present("software") {
connection.create_software_adapter().unwrap()
} else if matches.is_present("hardware") {
connection.create_hardware_adapter().unwrap()
let rendering = if matches.is_present("software") {
RenderingPreference::Software
} else {
connection.create_adapter().unwrap()
RenderingPreference::Hardware
};
let adapter = connection
.create_adapter(AdapterPreferences {
rendering,
..Default::default()
})
.unwrap();

let output_path = Path::new(matches.value_of("OUTPUT").unwrap()).to_owned();
let output_file = File::create(output_path).unwrap();
Expand Down
11 changes: 9 additions & 2 deletions examples/threads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use surfman::{Adapter, Connection, Context, ContextDescriptor, Device, GLApi, Su
use self::common::FilesystemResourceLoader;

#[cfg(not(target_os = "android"))]
use surfman::{ContextAttributeFlags, ContextAttributes, GLVersion};
use surfman::{
AdapterPreferences, ContextAttributeFlags, ContextAttributes, GLVersion, PowerPreference,
};
#[cfg(not(target_os = "android"))]
use winit::{
dpi::PhysicalSize,
Expand Down Expand Up @@ -134,7 +136,12 @@ fn main() {
let window_size = window.inner_size();
let window_size = Size2D::new(window_size.width as i32, window_size.height as i32);
let native_widget = make_native_widget(&window, &connection, window_size);
let adapter = connection.create_low_power_adapter().unwrap();
let adapter = connection
.create_adapter(AdapterPreferences {
power: PowerPreference::LowPower,
..Default::default()
})
.unwrap();
let device = connection.create_device(&adapter).unwrap();

let context_attributes = ContextAttributes {
Expand Down
30 changes: 30 additions & 0 deletions src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,36 @@ use crate::hardware_buffer::adapter::HardwareBufferAdapter;
use crate::wgl::adapter::WglAdapter;
use crate::Error;

/// A power usage preference for selecting an adapter.
#[derive(Copy, Clone, Debug, Default)]
pub enum PowerPreference {
/// Prefer a high-performance adapter.
#[default]
HighPerformance,
/// Prefer a low-power adapter.
LowPower,
}

/// A hardware/software preference for selecting an adapter.
#[derive(Copy, Clone, Debug, Default)]
pub enum RenderingPreference {
/// Prefer a hardware adapter.
#[default]
Hardware,
/// Prefer a software adapter.
Software,
}

/// A set of options to use when choosing an adapter. The default preference is
/// for a high-power hardware adapter.
#[derive(Copy, Clone, Debug, Default)]
pub struct AdapterPreferences {
/// The [`PowerPreference`] for choosing an adapter.
pub power: PowerPreference,
/// The [`RenderingPreference`] for choosing an adapter.
pub rendering: RenderingPreference,
}

/// Represents a hardware display adapter that can be used for rendering (including the CPU).
///
/// Adapters can be sent between threads. To render with an adapter, open a thread-local `Device`.
Expand Down
1 change: 0 additions & 1 deletion src/angle/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ impl AngleAdapter {
let choose_this = match vendor_preference {
VendorPreference::Prefer(vendor_id) => vendor_id == adapter_desc.VendorId,
VendorPreference::Avoid(vendor_id) => vendor_id != adapter_desc.VendorId,
VendorPreference::None => true,
};
if choose_this {
let mut dxgi_adapter: *mut IDXGIAdapter = ptr::null_mut();
Expand Down
44 changes: 12 additions & 32 deletions src/angle/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::adapter::AngleAdapter;
use super::device::{Device, NativeDevice, VendorPreference};
use super::surface::NativeWidget;
use crate::egl::types::{EGLDisplay, EGLNativeWindowType};
use crate::{Adapter, Error, GLApi};
use crate::{Adapter, AdapterPreferences, Error, GLApi, PowerPreference, RenderingPreference};

use euclid::default::Size2D;

Expand Down Expand Up @@ -63,38 +63,18 @@ impl Connection {
GLApi::GLES
}

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
///
/// This is an alias for `Connection::create_hardware_adapter()`.
#[inline]
pub fn create_adapter(&self) -> Result<Adapter, Error> {
self.create_hardware_adapter()
}

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
#[inline]
pub fn create_hardware_adapter(&self) -> Result<Adapter, Error> {
AngleAdapter::new(
D3D_DRIVER_TYPE_UNKNOWN,
VendorPreference::Avoid(INTEL_PCI_ID),
)
.map(Into::into)
}

/// Returns the "best" adapter on this system, preferring low-power hardware adapters.
#[inline]
pub fn create_low_power_adapter(&self) -> Result<Adapter, Error> {
AngleAdapter::new(
D3D_DRIVER_TYPE_UNKNOWN,
VendorPreference::Prefer(INTEL_PCI_ID),
)
.map(Into::into)
}

/// Returns the "best" adapter on this system, preferring software adapters.
/// Returns an adapter on this system according to the provided preferences.
#[inline]
pub fn create_software_adapter(&self) -> Result<Adapter, Error> {
AngleAdapter::new(D3D_DRIVER_TYPE_WARP, VendorPreference::None).map(Into::into)
pub fn create_adapter(&self, preferences: AdapterPreferences) -> Result<Adapter, Error> {
let driver_type = match preferences.rendering {
RenderingPreference::Hardware => D3D_DRIVER_TYPE_UNKNOWN,
RenderingPreference::Software => D3D_DRIVER_TYPE_WARP,
};
let vendor_preference = match preferences.power {
PowerPreference::HighPerformance => VendorPreference::Avoid(INTEL_PCI_ID),
PowerPreference::LowPower => VendorPreference::Prefer(INTEL_PCI_ID),
};
AngleAdapter::new(driver_type, vendor_preference).map(Into::into)
}

/// Opens the hardware device corresponding to the given adapter.
Expand Down
1 change: 0 additions & 1 deletion src/angle/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub struct Device {
}

pub(crate) enum VendorPreference {
None,
Prefer(UINT),
Avoid(UINT),
}
Expand Down
33 changes: 7 additions & 26 deletions src/base/io_surface/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use super::adapter::AppleAdapter;
use super::device::{Device, NativeDevice};
use super::surface::NativeWidget;
use crate::adapter::{AdapterPreferences, PowerPreference, RenderingPreference};
use crate::Error;

use objc2::rc::Retained;
Expand Down Expand Up @@ -67,32 +68,12 @@ impl Connection {
NativeConnection
}

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
///
/// This is an alias for `Connection::create_hardware_adapter()`.
#[inline]
pub fn create_adapter(&self) -> Result<AppleAdapter, Error> {
self.create_hardware_adapter()
}

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
#[inline]
pub fn create_hardware_adapter(&self) -> Result<AppleAdapter, Error> {
Ok(AppleAdapter {
is_low_power: false,
})
}

/// Returns the "best" adapter on this system, preferring low-power hardware adapters.
#[inline]
pub fn create_low_power_adapter(&self) -> Result<AppleAdapter, Error> {
Ok(AppleAdapter { is_low_power: true })
}

/// Returns the "best" adapter on this system, preferring software adapters.
/// Returns an adapter on this system according to the provided preferences.
#[inline]
pub fn create_software_adapter(&self) -> Result<AppleAdapter, Error> {
self.create_low_power_adapter()
pub fn create_adapter(&self, preferences: AdapterPreferences) -> Result<AppleAdapter, Error> {
let is_low_power = matches!(preferences.power, PowerPreference::LowPower)
|| matches!(preferences.rendering, RenderingPreference::Software);
Ok(AppleAdapter { is_low_power })
}

/// Opens the hardware device corresponding to the given adapter.
Expand All @@ -109,7 +90,7 @@ impl Connection {
&self,
_: NativeDevice,
) -> Result<Device, Error> {
self.create_device(&self.create_adapter()?)
self.create_device(&self.create_adapter(Default::default())?)
}

/// Opens the display connection corresponding to the given `DisplayHandle`.
Expand Down
28 changes: 4 additions & 24 deletions src/cgl/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! global window server connection.

use super::device::Device;
use crate::adapter::Adapter;
use crate::adapter::{Adapter, AdapterPreferences};
use crate::base::io_surface::connection::Connection as SystemConnection;
use crate::base::io_surface::device::NativeDevice;
use crate::base::io_surface::surface::NativeWidget;
Expand Down Expand Up @@ -48,30 +48,10 @@ impl Connection {
GLApi::GL
}

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
///
/// This is an alias for `Connection::create_hardware_adapter()`.
#[inline]
pub fn create_adapter(&self) -> Result<Adapter, Error> {
self.0.create_adapter().map(Into::into)
}

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
#[inline]
pub fn create_hardware_adapter(&self) -> Result<Adapter, Error> {
self.0.create_hardware_adapter().map(Into::into)
}

/// Returns the "best" adapter on this system, preferring low-power hardware adapters.
#[inline]
pub fn create_low_power_adapter(&self) -> Result<Adapter, Error> {
self.0.create_low_power_adapter().map(Into::into)
}

/// Returns the "best" adapter on this system, preferring software adapters.
/// Returns an adapter on this system according to the provided preferences.
#[inline]
pub fn create_software_adapter(&self) -> Result<Adapter, Error> {
self.0.create_software_adapter().map(Into::into)
pub fn create_adapter(&self, preferences: AdapterPreferences) -> Result<Adapter, Error> {
self.0.create_adapter(preferences).map(Into::into)
}

/// Opens the hardware device corresponding to the given adapter.
Expand Down
16 changes: 3 additions & 13 deletions src/connection.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! The abstract interface that all connections conform to.

use crate::adapter::AdapterPreferences;
use crate::Adapter;
use crate::Error;
use crate::GLApi;
Expand All @@ -21,19 +22,8 @@ pub trait Connection: Sized {
/// Returns the OpenGL API flavor that this connection supports (OpenGL or OpenGL ES).
fn gl_api(&self) -> GLApi;

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
///
/// This is an alias for `Connection::create_hardware_adapter()`.
fn create_adapter(&self) -> Result<Adapter, Error>;

/// Returns the "best" adapter on this system, preferring high-performance hardware adapters.
fn create_hardware_adapter(&self) -> Result<Adapter, Error>;

/// Returns the "best" adapter on this system, preferring low-power hardware adapters.
fn create_low_power_adapter(&self) -> Result<Adapter, Error>;

/// Returns the "best" adapter on this system, preferring software adapters.
fn create_software_adapter(&self) -> Result<Adapter, Error>;
/// Returns an adapter on this system according to the provided preferences.
fn create_adapter(&self, preferences: AdapterPreferences) -> Result<Adapter, Error>;

/// Opens a device.
fn create_device(&self, adapter: &Adapter) -> Result<Self::Device, Error>;
Expand Down
49 changes: 12 additions & 37 deletions src/free_unix/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,31 @@

//! A hardware display adapter on Wayland / X11 systems.

use crate::{AdapterPreferences, PowerPreference, RenderingPreference};
use std::env;

static MESA_SOFTWARE_RENDERING_ENV_VAR: &str = "LIBGL_ALWAYS_SOFTWARE";
static MESA_DRI_PRIME_ENV_VAR: &str = "DRI_PRIME";

/// An implementation of [`crate::Adapter`] for Wayland / X11 platforms.
#[derive(Clone, Debug)]
pub enum FreeUnixAdapter {
#[doc(hidden)]
Hardware,
#[doc(hidden)]
HardwarePrime,
#[doc(hidden)]
Software,
}
pub struct FreeUnixAdapter(AdapterPreferences);

impl FreeUnixAdapter {
#[inline]
pub(crate) fn hardware() -> Self {
Self::HardwarePrime
}

#[inline]
pub(crate) fn low_power() -> Self {
Self::Hardware
}

#[inline]
pub(crate) fn software() -> Self {
Self::Software
pub(crate) fn new(preferences: AdapterPreferences) -> Self {
Self(preferences)
}

pub(crate) fn set_environment_variables(&self) {
match *self {
Self::Hardware | Self::HardwarePrime => {
env::remove_var(MESA_SOFTWARE_RENDERING_ENV_VAR);
}
Self::Software => {
env::set_var(MESA_SOFTWARE_RENDERING_ENV_VAR, "1");
}
}

match *self {
Self::Software => {}
Self::Hardware => {
env::remove_var(MESA_DRI_PRIME_ENV_VAR);
}
Self::HardwarePrime => {
env::set_var(MESA_DRI_PRIME_ENV_VAR, "1");
}
env::remove_var(MESA_SOFTWARE_RENDERING_ENV_VAR);
env::remove_var(MESA_DRI_PRIME_ENV_VAR);
match self.0.rendering {
RenderingPreference::Hardware => match self.0.power {
PowerPreference::HighPerformance => env::set_var(MESA_DRI_PRIME_ENV_VAR, "1"),
PowerPreference::LowPower => {}
},
RenderingPreference::Software => env::set_var(MESA_SOFTWARE_RENDERING_ENV_VAR, "1"),
}
}
}
Loading
Loading