1 /// Presentation module 2 module gfx.graal.presentation; 3 4 import core.time : Duration; 5 6 import gfx.core.rc; 7 import gfx.graal.format; 8 import gfx.graal.image; 9 import gfx.graal.sync; 10 11 import std.typecons : Tuple; 12 13 /// Surface capabilities 14 /// See_Also: PhysicalDevice.surfaceCaps 15 struct SurfaceCaps 16 { 17 // TODO: currentSize 18 /// Minimum number of images necessary in a swapchain created for the 19 /// surface these caps where queried for. 20 uint minImages; 21 /// Maximum number of images supported by swapchains created for the surface 22 /// these caps where queried for. 23 uint maxImages; 24 /// Minimum size of the surface 25 uint[2] minSize; 26 /// Maximum size of the surface 27 uint[2] maxSize; 28 /// Maximum number of array layers for this surface. At least one. 29 uint maxLayers; 30 /// Possible usages bits of the images of swapchains created for this image. 31 /// At least `ImageUsage.colorAttachment` is included. 32 ImageUsage usage; 33 /// Supported composition mode for the surface. 34 /// At least one bit is always included. Opaque composition is always 35 /// feasible by having no alpha channel or with alpha channel equals to 1.0. 36 CompositeAlpha supportedAlpha; 37 } 38 39 /// Composition mode for a presentation engine 40 enum CompositeAlpha { 41 /// The alpha channel of presented surface is discarded and no composition 42 /// is performed. 43 opaque = 0x01, 44 /// Composition is enabled and the color channels of presented surface are 45 /// treated as pre-multiplied by the alpha channel. 46 preMultiplied = 0x02, 47 /// Composition is enabled and the color channels of presented surface must 48 /// multiplied by the alpha channel by the presentation engine. 49 postMultiplied = 0x04, 50 /// The Graal implementation has no clue on how the compositor will 51 /// treat the alpha channel. 52 inherit = 0x08, 53 } 54 55 /// PresentMode is the algorithm driving a swapchain 56 enum PresentMode 57 { 58 /// Image is presented immediately, without waiting for V-blank. 59 /// This mode may cause tearing. 60 immediate, 61 /// First-in, first-out. The presentation engine waits for the next V-blank 62 /// to present image, such as tearing cannot be observed. Images are 63 /// appended at the end of an internal queue and the images are retrieved at 64 /// the beginning of the queue at each V-Blank. This mode is always 65 /// available, and should be used for steady throughput of presentation. 66 fifo, 67 /// This is similar to fifo, with the exception that the internal queue 68 /// has only one entry, such as if an image is waiting to be presented, 69 /// and another comes before V-blank, the new image replaces the previous 70 /// one, such as only the latest image is presented. Tearing cannot be 71 /// observed. This mode can increase reactivity of application. 72 mailbox, 73 } 74 75 /// Handle to a native surface 76 interface Surface : IAtomicRefCounted 77 {} 78 79 /// Result of Image acquisition from a Swapchain. 80 /// See_Also: Swapchain.acquireNextImage 81 struct ImageAcquisition 82 { 83 /// An Image Acquisition can have one of the 4 following states. 84 enum State : uint 85 { 86 /// The image could be acquired in optimal condition 87 ok = 0x00000000, 88 /// An image could be acquired but its use is suboptimal. 89 /// This is an indication that the swapchain should be re-generated when 90 /// practicable. This can happen e.g. if the window is being resized but 91 /// the presentation engine is able to scale the image to the surface. 92 suboptimal = 0x01000000, 93 /// The swapchain could is out of date and MUST be re-generated. 94 /// This can happen for example during resize of the window behind 95 /// the swapchain's surface, or if the window properties have changed 96 /// in some way. 97 outOfDate = 0x02000000, 98 /// Swapchain.acquireNextImage timed-out, or was called with null 99 /// timeout and no image was ready. 100 notReady = 0x03000000, 101 102 /// Value used to mask out the index from the state. 103 mask = 0xff000000, 104 } 105 106 /// Make an ImageAcquisition in OK state with the given image index. 107 static ImageAcquisition makeOk(uint index) 108 { 109 assert(indexValid(index)); 110 return ImageAcquisition(index); 111 } 112 113 /// Make an ImageAcquisition in Suboptimal state with the given image index. 114 static ImageAcquisition makeSuboptimal(uint index) 115 { 116 assert(indexValid(index)); 117 return ImageAcquisition(cast(uint)State.suboptimal | index); 118 } 119 120 /// Make an ImageAcquisition in out-of-date state. 121 static ImageAcquisition makeOutOfDate() 122 { 123 return ImageAcquisition(cast(uint)State.outOfDate); 124 } 125 126 /// Make an ImageAcquisition in notReady state. 127 static ImageAcquisition makeNotReady() 128 { 129 return ImageAcquisition(cast(uint)State.notReady); 130 } 131 132 /// Get the state of the acquisition 133 @property State state() const 134 { 135 return cast(State)(rep & State.mask); 136 } 137 138 /// Get the index of the acquired image 139 @property uint index() const 140 in (!outOfDate) 141 { 142 return rep & ~State.mask; 143 } 144 145 /// Whether the acquisition is in OK state 146 @property bool ok() const 147 { 148 return state == State.ok; 149 } 150 151 /// Whether the acquisition is in suboptimal state 152 @property bool suboptimal() const 153 { 154 return state == State.suboptimal; 155 } 156 157 /// Whether the acquisition is in out-of-date state 158 @property bool outOfDate() const 159 { 160 return state == State.outOfDate; 161 } 162 163 /// Whether the acquisition is in not-ready state 164 @property bool notReady() const 165 { 166 return state == State.notReady; 167 } 168 169 /// Whether an image could be acquired 170 @property bool hasIndex() const 171 { 172 return ok || suboptimal; 173 } 174 175 /// Whether the Swapchain should be reconstructed 176 @property bool swapchainNeedsRebuild() const 177 { 178 return suboptimal || outOfDate; 179 } 180 181 private uint rep; 182 183 private this (uint rep) { this.rep = rep; } 184 185 private static bool indexValid(in uint index) 186 { 187 return (index & cast(uint)State.mask) == 0; 188 } 189 } 190 191 /// Handle to a swapchain engine 192 interface Swapchain : IAtomicRefCounted 193 { 194 import gfx.graal.device : Device; 195 import core.time : dur; 196 197 /// Get the parent device 198 @property Device device(); 199 200 /// Get the Surface that this swapchain is bound to. 201 @property Surface surface(); 202 203 /// The image format of this swapchain 204 @property Format format(); 205 206 /// Get the list of images owned by this swapchain. 207 /// The index of each image is meaningful and is often used to reference 208 /// the image (such as the index returned by acquireNextImage) 209 @property ImageBase[] images(); 210 211 /// Acquire the next image in the swapchain. This function may block until 212 /// the next image is available. 213 /// Params: 214 /// semaphore = A semaphore that is signaled when the image is 215 /// ready to be written to. Use it to synchronize with 216 /// the first submission that will write to the image. 217 /// timeout = The maximum time to wait until the call returns. 218 /// Use negative timeout to specify infinite waiting time. 219 /// Use null timeout to specify no wait at all. 220 /// Returns: ImageAcquisition representing the result of the operation. 221 /// See_Also: ImageAcquisition 222 ImageAcquisition acquireNextImage(Semaphore semaphore, 223 Duration timeout=dur!"seconds"(-1)); 224 }