diff options
Diffstat (limited to 'src/include/libplacebo/swapchain.h')
-rw-r--r-- | src/include/libplacebo/swapchain.h | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/include/libplacebo/swapchain.h b/src/include/libplacebo/swapchain.h new file mode 100644 index 0000000..b53aa5c --- /dev/null +++ b/src/include/libplacebo/swapchain.h @@ -0,0 +1,171 @@ +/* + * This file is part of libplacebo. + * + * libplacebo is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libplacebo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBPLACEBO_SWAPCHAIN_H_ +#define LIBPLACEBO_SWAPCHAIN_H_ + +#include <libplacebo/common.h> +#include <libplacebo/colorspace.h> +#include <libplacebo/gpu.h> + +PL_API_BEGIN + +// This abstraction represents a low-level interface to visible surfaces +// exposed by a graphics API (and accompanying GPU instance), allowing users to +// directly present frames to the screen (or window, typically). This is a +// sister API to gpu.h and follows the same convention w.r.t undefined behavior. +// +// Thread-safety: Safe +typedef const struct pl_swapchain_t { + pl_log log; + pl_gpu gpu; +} *pl_swapchain; + +// Destroys this swapchain. May be used at any time, and may block until the +// completion of all outstanding rendering commands. The swapchain and any +// resources retrieved from it must not be used afterwards. +PL_API void pl_swapchain_destroy(pl_swapchain *sw); + +// Returns the approximate current swapchain latency in vsyncs, or 0 if +// unknown. A latency of 1 means that `submit_frame` followed by `swap_buffers` +// will block until the just-submitted frame has finished rendering. Typical +// values are 2 or 3, which enable better pipelining by allowing the GPU to be +// processing one or two frames at the same time as the user is preparing the +// next for submission. +PL_API int pl_swapchain_latency(pl_swapchain sw); + +// Update/query the swapchain size. This function performs both roles: it tries +// setting the swapchain size to the values requested by the user, and returns +// in the same variables what width/height the swapchain was actually set to - +// which may be (substantially) different from the values requested by the +// user. A value of 0 means "unknown/none" (in which case, libplacebo won't try +// updating the size - it will simply return the current state of the +// swapchain). It's also possible for libplacebo to return values of 0, such as +// in the case that the swapchain doesn't exist yet. +// +// Returns false on significant errors (e.g. dead surface). This function can +// effectively be used to probe if creating a swapchain works. +PL_API bool pl_swapchain_resize(pl_swapchain sw, int *width, int *height); + +// Backwards compatibility +#define pl_swapchain_colors pl_color_space + +// Inform the swapchain about the input color space. This API deliberately +// provides no feedback, because the swapchain can internally decide what to do +// with this information, including ignoring it entirely, or applying it +// asynchronously. Users must still base their rendering on the value of +// `pl_swapchain_frame.color_space`. +// +// Note: Calling this function a second time completely overrides any +// previously specified hint. So calling this on {0} or NULL resets the +// swapchain back to its initial/preferred colorspace. +// +// Note: If `csp->transfer` is a HDR transfer curve but HDR metadata is left +// unspecified, the HDR metadata defaults to `pl_hdr_metadata_hdr10`. +// Conversely, if the HDR metadata is non-empty but `csp->transfer` is left as +// PL_COLOR_TRC_UNKNOWN, then it instead defaults to PL_COLOR_TRC_PQ. +PL_API void pl_swapchain_colorspace_hint(pl_swapchain sw, const struct pl_color_space *csp); + +// The struct used to hold the results of `pl_swapchain_start_frame` +struct pl_swapchain_frame { + // A texture representing the framebuffer users should use for rendering. + // It's guaranteed that `fbo->params.renderable` and `fbo->params.blit_dst` + // will be true, but no other guarantees are made - not even that + // `fbo->params.format` is a real format. + pl_tex fbo; + + // If true, the user should assume that this framebuffer will be flipped + // as a result of presenting it on-screen. If false, nothing special needs + // to be done - but if true, users should flip the coordinate system of + // the `pl_pass` that is rendering to this framebuffer. + // + // Note: Normally, libplacebo follows the convention that (0,0) represents + // the top left of the image/screen. So when flipped is true, this means + // (0,0) on this framebuffer gets displayed as the bottom left of the image. + bool flipped; + + // Indicates the color representation this framebuffer will be interpreted + // as by the host system / compositor / display, including the bit depth + // and alpha handling (where available). + struct pl_color_repr color_repr; + struct pl_color_space color_space; +}; + +// Retrieve a new frame from the swapchain. Returns whether successful. It's +// worth noting that this function can fail sporadically for benign reasons, +// for example the window being invisible or inaccessible. This function may +// block until an image is available, which may be the case if the GPU is +// rendering frames significantly faster than the display can output them. It +// may also be non-blocking, so users shouldn't rely on this call alone in +// order to meter rendering speed. (Specifics depend on the underlying graphics +// API) +PL_API bool pl_swapchain_start_frame(pl_swapchain sw, struct pl_swapchain_frame *out_frame); + +// Submits the previously started frame. Non-blocking. This must be issued in +// lockstep with pl_swapchain_start_frame - there is no way to start multiple +// frames and submit them out-of-order. The frames submitted this way will +// generally be made visible in a first-in first-out fashion, although +// specifics depend on the mechanism used to create the pl_swapchain. (See the +// platform-specific APIs for more info). +// +// Returns whether successful. This should normally never fail, unless the +// GPU/surface has been lost or some other critical error has occurred. The +// "started" frame is consumed even in the event of failure. +// +// Note that `start_frame` and `submit_frame` form a lock pair, i.e. trying to +// call e.g. `pl_swapchain_resize` from another thread will block until +// `pl_swapchain_submit_frame` is finished. +PL_API bool pl_swapchain_submit_frame(pl_swapchain sw); + +// Performs a "buffer swap", or some generalization of the concept. In layman's +// terms, this blocks until the execution of the Nth previously submitted frame +// has been "made complete" in some sense. (The N derives from the swapchain's +// built-in latency. See `pl_swapchain_latency` for more information). +// +// Users should include this call in their rendering loops in order to make +// sure they aren't submitting rendering commands faster than the GPU can +// process them, which would potentially lead to a queue overrun or exhaust +// memory. +// +// An example loop might look like this: +// +// while (rendering) { +// struct pl_swapchain_frame frame; +// bool ok = pl_swapchain_start_frame(swapchain, &frame); +// if (!ok) { +// /* wait some time, or decide to stop rendering */ +// continue; +// } +// +// /* do some rendering with frame.fbo */ +// +// ok = pl_swapchain_submit_frame(swapchain); +// if (!ok) +// break; +// +// pl_swapchain_swap_buffers(swapchain); +// } +// +// The duration this function blocks for, if at all, may be very inconsistent +// and should not be used as an authoritative source of vsync timing +// information without sufficient smoothing/filtering (and if so, the time that +// `start_frame` blocked for should also be included). +PL_API void pl_swapchain_swap_buffers(pl_swapchain sw); + +PL_API_END + +#endif // LIBPLACEBO_SWAPCHAIN_H_ |