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