surfman/surface.rs
1//! Information related to hardware surfaces.
2
3use crate::context::ContextID;
4
5use euclid::default::Size2D;
6use std::fmt::{self, Display, Formatter};
7
8/// Various data about the surface.
9pub struct SystemSurfaceInfo {
10 /// The surface's size, in device pixels.
11 pub size: Size2D<i32>,
12 /// The ID of the surface. This should be globally unique for each currently-allocated surface.
13 pub id: SurfaceID,
14}
15
16/// Various data about the surface.
17pub struct SurfaceInfo {
18 /// The surface's size, in device pixels.
19 pub size: Size2D<i32>,
20 /// The ID of the surface. This should be globally unique for each currently-allocated surface.
21 pub id: SurfaceID,
22 /// The ID of the context that this surface belongs to.
23 pub context_id: ContextID,
24 /// The OpenGL framebuffer object that can be used to render to this surface.
25 ///
26 /// This is only valid when the surface is actually attached to a context.
27 pub framebuffer_object: Option<glow::Framebuffer>,
28}
29
30// The default framebuffer for a context.
31#[allow(dead_code)]
32pub(crate) enum Framebuffer<S, E> {
33 // No framebuffer has been attached to the context.
34 None,
35 // The context is externally-managed.
36 External(E),
37 // The context renders to a surface.
38 Surface(S),
39}
40
41/// A unique ID per allocated surface.
42///
43/// If you destroy a surface and then create a new one, the ID may be reused.
44#[derive(Clone, Copy, Debug, PartialEq)]
45pub struct SurfaceID(pub usize);
46
47impl Display for SurfaceID {
48 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
49 write!(f, "{:?}", *self)
50 }
51}
52
53/// Specifies how and if the CPU has direct access to the surface data.
54///
55/// No matter what value you choose here, the CPU can always indirectly upload data to the surface
56/// by, for example, drawing a full-screen quad. This enumeration simply describes whether the CPU
57/// has *direct* memory access to the surface, via a slice of pixel data.
58///
59/// You can achieve better performance by limiting surfaces to `GPUOnly` unless you need to access
60/// the data on the CPU. For surfaces marked as GPU-only, the GPU can use texture swizzling to
61/// improve memory locality.
62#[derive(Clone, Copy, PartialEq, Debug)]
63pub enum SurfaceAccess {
64 /// The surface data is accessible by the GPU only.
65 ///
66 /// The `lock_surface_data()` method will return the `SurfaceDataInaccessible` error when
67 /// called on this surface.
68 ///
69 /// This is typically the flag you will want to use.
70 GPUOnly,
71
72 /// The surface data is accessible by the GPU and CPU.
73 GPUCPU,
74
75 /// The surface data is accessible by the GPU and CPU, and the CPU will send surface data over
76 /// the bus to the GPU using write-combining if available.
77 ///
78 /// Specifically, what this means is that data transfer will be optimized for the following
79 /// patterns:
80 ///
81 /// 1. Writing, not reading.
82 ///
83 /// 2. Writing sequentially, filling every byte in a range.
84 ///
85 /// This flag has no effect on correctness (at least on x86), but not following the rules
86 /// above may result in severe performance consequences.
87 ///
88 /// The driver is free to treat this as identical to `GPUCPU`.
89 GPUCPUWriteCombined,
90}
91
92/// Information specific to the type of surface: generic or widget.
93#[derive(Clone)]
94pub enum SurfaceType<NativeWidget> {
95 /// An off-screen surface that has a pixel size. Generic surfaces can sometimes be shown on
96 /// screen using platform-specific APIs, but `surfman` itself provides no way to draw their
97 /// contents on screen. Only generic surfaces can be bound to textures.
98 Generic {
99 /// The size of the surface.
100 ///
101 /// For HiDPI screens, this is a physical size, not a logical size.
102 size: Size2D<i32>,
103 },
104 /// A surface displayed inside a native widget (window or view). The size of a widget surface
105 /// is automatically determined based on the size of the widget. (For example, if the widget is
106 /// a window, the size of the surface will be the physical size of the window.) Widget surfaces
107 /// cannot be bound to textures.
108 Widget {
109 /// A native widget type specific to the backend.
110 ///
111 /// For example, on Windows this wraps an `HWND`.
112 native_widget: NativeWidget,
113 },
114}
115
116impl SurfaceAccess {
117 #[allow(dead_code)]
118 #[inline]
119 pub(crate) fn cpu_access_allowed(self) -> bool {
120 match self {
121 SurfaceAccess::GPUOnly => false,
122 SurfaceAccess::GPUCPU | SurfaceAccess::GPUCPUWriteCombined => true,
123 }
124 }
125}