@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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_CACHE_H_
|
||||
#define LIBPLACEBO_CACHE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libplacebo/config.h>
|
||||
#include <libplacebo/common.h>
|
||||
#include <libplacebo/log.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
typedef struct pl_cache_obj {
|
||||
// Cache object key. This will uniquely identify this cached object.
|
||||
uint64_t key;
|
||||
|
||||
// Cache data pointer and length. 0-length cached objects are invalid
|
||||
// and will be silently dropped. You can explicitly remove a cached
|
||||
// object by overwriting it with a length 0 object.
|
||||
void *data;
|
||||
size_t size;
|
||||
|
||||
// Free callback, to free memory associated with `data`. (Optional)
|
||||
// Will be called when the object is either explicitly deleted, culled
|
||||
// due to hitting size limits, or on pl_cache_destroy().
|
||||
void (*free)(void *data);
|
||||
} pl_cache_obj;
|
||||
|
||||
struct pl_cache_params {
|
||||
// Optional `pl_log` that is used for logging internal events related
|
||||
// to the cache, such as insertions, saving and loading.
|
||||
pl_log log;
|
||||
|
||||
// Size limits. If 0, no limit is imposed.
|
||||
//
|
||||
// Note: libplacebo will never detect or invalidate stale cache entries, so
|
||||
// setting an upper size limit is strongly recommended
|
||||
size_t max_object_size;
|
||||
size_t max_total_size;
|
||||
|
||||
// Optional external callback to call after a cached object is modified
|
||||
// (including deletion and (re-)insertion). Note that this is not called on
|
||||
// objects which are merely pruned from the cache due to `max_total_size`,
|
||||
// so users must rely on some external mechanism to prune stale entries or
|
||||
// enforce size limits.
|
||||
//
|
||||
// Note: `pl_cache_load` does not trigger this callback.
|
||||
// Note: Ownership of `obj` does *not* pass to the caller.
|
||||
// Note: This function must be thread safe.
|
||||
void (*set)(void *priv, pl_cache_obj obj);
|
||||
|
||||
// Optional external callback to call on a cache miss. Ownership of the
|
||||
// returned object passes to the `pl_cache`. Objects returned by this
|
||||
// callback *should* have a valid `free` callback, unless lifetime can be
|
||||
// externally managed and guaranteed to outlive the `pl_cache`.
|
||||
//
|
||||
// Note: This function must be thread safe.
|
||||
pl_cache_obj (*get)(void *priv, uint64_t key);
|
||||
|
||||
// External context for insert/lookup.
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#define pl_cache_params(...) (&(struct pl_cache_params) { __VA_ARGS__ })
|
||||
PL_API extern const struct pl_cache_params pl_cache_default_params;
|
||||
|
||||
// Thread-safety: Safe
|
||||
//
|
||||
// Note: In any context in which `pl_cache` is used, users may also pass NULL
|
||||
// to disable caching. In other words, NULL is a valid `pl_cache`.
|
||||
typedef const struct pl_cache_t {
|
||||
struct pl_cache_params params;
|
||||
} *pl_cache;
|
||||
|
||||
// Create a new cache. This function will never fail.
|
||||
PL_API pl_cache pl_cache_create(const struct pl_cache_params *params);
|
||||
|
||||
// Destroy a `pl_cache` object, including all underlying objects.
|
||||
PL_API void pl_cache_destroy(pl_cache *cache);
|
||||
|
||||
// Explicitly clear all objects in the cache without destroying it. This is
|
||||
// similar to `pl_cache_destroy`, but the cache remains valid afterwards.
|
||||
//
|
||||
// Note: Objects destroyed in this way *not* propagated to the `set` callback.
|
||||
PL_API void pl_cache_reset(pl_cache cache);
|
||||
|
||||
// Return the current internal number of objects and total size (bytes)
|
||||
PL_API int pl_cache_objects(pl_cache cache);
|
||||
PL_API size_t pl_cache_size(pl_cache cache);
|
||||
|
||||
// --- Cache saving and loading APIs
|
||||
|
||||
// Serialize the internal state of a `pl_cache` into an abstract cache
|
||||
// object that can be e.g. saved to disk and loaded again later. Returns the
|
||||
// number of objects saved.
|
||||
//
|
||||
// Note: Using `save/load` is largely redundant with using `insert/lookup`
|
||||
// callbacks, and the user should decide whether to use the explicit API or the
|
||||
// callback-based API.
|
||||
PL_API int pl_cache_save_ex(pl_cache cache,
|
||||
void (*write)(void *priv, size_t size, const void *ptr),
|
||||
void *priv);
|
||||
|
||||
// Load the result of a previous `pl_cache_save` call. Any duplicate entries in
|
||||
// the `pl_cache` will be overwritten. Returns the number of objects loaded, or
|
||||
// a negative number on serious error (e.g. corrupt header)
|
||||
//
|
||||
// Note: This does not trigger the `update` callback.
|
||||
PL_API int pl_cache_load_ex(pl_cache cache,
|
||||
bool (*read)(void *priv, size_t size, void *ptr),
|
||||
void *priv);
|
||||
|
||||
// --- Convenience wrappers around pl_cache_save/load_ex
|
||||
|
||||
// Writes data directly to a pointer. Returns the number of bytes that *would*
|
||||
// have been written, so this can be used on a size 0 buffer to get the required
|
||||
// total size.
|
||||
PL_API size_t pl_cache_save(pl_cache cache, uint8_t *data, size_t size);
|
||||
|
||||
// Reads data directly from a pointer. This still reads from `data`, so it does
|
||||
// not avoid a copy.
|
||||
PL_API int pl_cache_load(pl_cache cache, const uint8_t *data, size_t size);
|
||||
|
||||
// Writes/loads data to/from a FILE stream at the current position.
|
||||
#define pl_cache_save_file(c, file) pl_cache_save_ex(c, pl_write_file_cb, file)
|
||||
#define pl_cache_load_file(c, file) pl_cache_load_ex(c, pl_read_file_cb, file)
|
||||
|
||||
static inline void pl_write_file_cb(void *priv, size_t size, const void *ptr)
|
||||
{
|
||||
(void) fwrite(ptr, 1, size, (FILE *) priv);
|
||||
}
|
||||
|
||||
static inline bool pl_read_file_cb(void *priv, size_t size, void *ptr)
|
||||
{
|
||||
return fread(ptr, 1, size, (FILE *) priv) == size;
|
||||
}
|
||||
|
||||
// --- Object modification API. Mostly intended for internal use.
|
||||
|
||||
// Insert a new cached object into a `pl_cache`. Returns whether successful.
|
||||
// Overwrites any existing cached object with that signature, so this can be
|
||||
// used to e.g. delete objects as well (set their size to 0). On success,
|
||||
// ownership of `obj` passes to the `pl_cache`.
|
||||
//
|
||||
// Note: If `object.free` is NULL, this will perform an internal memdup. To
|
||||
// bypass this (e.g. when directly adding externally managed memory), you can
|
||||
// set the `free` callback to an explicit noop function.
|
||||
//
|
||||
// Note: `obj->data/free` will be reset to NULL on successful insertion.
|
||||
PL_API bool pl_cache_try_set(pl_cache cache, pl_cache_obj *obj);
|
||||
|
||||
// Variant of `pl_cache_try_set` that simply frees `obj` on failure.
|
||||
PL_API void pl_cache_set(pl_cache cache, pl_cache_obj *obj);
|
||||
|
||||
// Looks up `obj->key` in the object cache. If successful, `obj->data` is
|
||||
// set to memory owned by the caller, which must be either explicitly
|
||||
// re-inserted, or explicitly freed (using obj->free).
|
||||
//
|
||||
// Note: On failure, `obj->data/size/free` are reset to NULL.
|
||||
PL_API bool pl_cache_get(pl_cache cache, pl_cache_obj *obj);
|
||||
|
||||
// Run a callback on every object currently stored in `cache`.
|
||||
//
|
||||
// Note: Running any `pl_cache_*` function on `cache` from this callback is
|
||||
// undefined behavior.
|
||||
PL_API void pl_cache_iterate(pl_cache cache,
|
||||
void (*cb)(void *priv, pl_cache_obj obj),
|
||||
void *priv);
|
||||
|
||||
// Utility wrapper to free a `pl_cache_obj` if necessary (and sanitize it)
|
||||
static inline void pl_cache_obj_free(pl_cache_obj *obj)
|
||||
{
|
||||
if (obj->free)
|
||||
obj->free(obj->data);
|
||||
obj->data = NULL;
|
||||
obj->free = NULL;
|
||||
obj->size = 0;
|
||||
}
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_CACHE_H_
|
||||
@ -0,0 +1,719 @@
|
||||
/*
|
||||
* 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_COLORSPACE_H_
|
||||
#define LIBPLACEBO_COLORSPACE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libplacebo/common.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// The underlying color representation (e.g. RGB, XYZ or YCbCr)
|
||||
enum pl_color_system {
|
||||
PL_COLOR_SYSTEM_UNKNOWN = 0,
|
||||
// YCbCr-like color systems:
|
||||
PL_COLOR_SYSTEM_BT_601, // ITU-R Rec. BT.601 (SD)
|
||||
PL_COLOR_SYSTEM_BT_709, // ITU-R Rec. BT.709 (HD)
|
||||
PL_COLOR_SYSTEM_SMPTE_240M, // SMPTE-240M
|
||||
PL_COLOR_SYSTEM_BT_2020_NC, // ITU-R Rec. BT.2020 (non-constant luminance)
|
||||
PL_COLOR_SYSTEM_BT_2020_C, // ITU-R Rec. BT.2020 (constant luminance)
|
||||
PL_COLOR_SYSTEM_BT_2100_PQ, // ITU-R Rec. BT.2100 ICtCp PQ variant
|
||||
PL_COLOR_SYSTEM_BT_2100_HLG, // ITU-R Rec. BT.2100 ICtCp HLG variant
|
||||
PL_COLOR_SYSTEM_DOLBYVISION, // Dolby Vision (see pl_dovi_metadata)
|
||||
PL_COLOR_SYSTEM_YCGCO, // YCgCo (derived from RGB)
|
||||
// Other color systems:
|
||||
PL_COLOR_SYSTEM_RGB, // Red, Green and Blue
|
||||
PL_COLOR_SYSTEM_XYZ, // Digital Cinema Distribution Master (XYZ)
|
||||
PL_COLOR_SYSTEM_COUNT
|
||||
};
|
||||
|
||||
PL_API bool pl_color_system_is_ycbcr_like(enum pl_color_system sys);
|
||||
|
||||
// Returns true for color systems that are linear transformations of the RGB
|
||||
// equivalent, i.e. are simple matrix multiplications. For color systems with
|
||||
// this property, `pl_color_repr_decode` is sufficient for conversion to RGB.
|
||||
PL_API bool pl_color_system_is_linear(enum pl_color_system sys);
|
||||
|
||||
// Guesses the best YCbCr-like colorspace based on a image given resolution.
|
||||
// This only picks conservative values. (In particular, BT.2020 is never
|
||||
// auto-guessed, even for 4K resolution content)
|
||||
PL_API enum pl_color_system pl_color_system_guess_ycbcr(int width, int height);
|
||||
|
||||
// Friendly names for the canonical channel names and order.
|
||||
enum pl_channel {
|
||||
PL_CHANNEL_NONE = -1,
|
||||
PL_CHANNEL_A = 3, // alpha
|
||||
// RGB system
|
||||
PL_CHANNEL_R = 0,
|
||||
PL_CHANNEL_G = 1,
|
||||
PL_CHANNEL_B = 2,
|
||||
// YCbCr-like systems
|
||||
PL_CHANNEL_Y = 0,
|
||||
PL_CHANNEL_CB = 1,
|
||||
PL_CHANNEL_CR = 2,
|
||||
// Aliases for Cb/Cr
|
||||
PL_CHANNEL_U = 1,
|
||||
PL_CHANNEL_V = 2
|
||||
// There are deliberately no names for the XYZ system to avoid
|
||||
// confusion due to PL_CHANNEL_Y.
|
||||
};
|
||||
|
||||
// The numerical range of the representation (where applicable).
|
||||
enum pl_color_levels {
|
||||
PL_COLOR_LEVELS_UNKNOWN = 0,
|
||||
PL_COLOR_LEVELS_LIMITED, // Limited/TV range, e.g. 16-235
|
||||
PL_COLOR_LEVELS_FULL, // Full/PC range, e.g. 0-255
|
||||
PL_COLOR_LEVELS_COUNT,
|
||||
|
||||
// Compatibility aliases
|
||||
PL_COLOR_LEVELS_TV = PL_COLOR_LEVELS_LIMITED,
|
||||
PL_COLOR_LEVELS_PC = PL_COLOR_LEVELS_FULL,
|
||||
};
|
||||
|
||||
// The alpha representation mode.
|
||||
enum pl_alpha_mode {
|
||||
PL_ALPHA_UNKNOWN = 0, // or no alpha channel present
|
||||
PL_ALPHA_INDEPENDENT, // alpha channel is separate from the video
|
||||
PL_ALPHA_PREMULTIPLIED, // alpha channel is multiplied into the colors
|
||||
PL_ALPHA_MODE_COUNT,
|
||||
};
|
||||
|
||||
// The underlying bit-wise representation of a color sample. For example,
|
||||
// a 10-bit TV-range YCbCr value uploaded to a 16 bit texture would have
|
||||
// sample_depth=16 color_depth=10 bit_shift=0.
|
||||
//
|
||||
// For another example, a 12-bit XYZ full range sample shifted to 16-bits with
|
||||
// the lower 4 bits all set to 0 would have sample_depth=16 color_depth=12
|
||||
// bit_shift=4. (libavcodec likes outputting this type of `xyz12`)
|
||||
//
|
||||
// To explain the meaning of `sample_depth` further; the consideration factor
|
||||
// here is the fact that GPU sampling will normalized the sampled color to the
|
||||
// range 0.0 - 1.0 in a manner dependent on the number of bits in the texture
|
||||
// format. So if you upload a 10-bit YCbCr value unpadded as 16-bit color
|
||||
// samples, all of the sampled values will be extremely close to 0.0. In such a
|
||||
// case, `pl_color_repr_normalize` would return a high scaling factor, which
|
||||
// would pull the color up to their 16-bit range.
|
||||
struct pl_bit_encoding {
|
||||
int sample_depth; // the number of bits the color is stored/sampled as
|
||||
int color_depth; // the effective number of bits of the color information
|
||||
int bit_shift; // a representational bit shift applied to the color
|
||||
};
|
||||
|
||||
// Returns whether two bit encodings are exactly identical.
|
||||
PL_API bool pl_bit_encoding_equal(const struct pl_bit_encoding *b1,
|
||||
const struct pl_bit_encoding *b2);
|
||||
|
||||
// Parsed metadata from the Dolby Vision RPU
|
||||
struct pl_dovi_metadata {
|
||||
// Colorspace transformation metadata
|
||||
float nonlinear_offset[3]; // input offset ("ycc_to_rgb_offset")
|
||||
pl_matrix3x3 nonlinear; // before PQ, also called "ycc_to_rgb"
|
||||
pl_matrix3x3 linear; // after PQ, also called "rgb_to_lms"
|
||||
|
||||
// Reshape data, grouped by component
|
||||
struct pl_reshape_data {
|
||||
uint8_t num_pivots;
|
||||
float pivots[9]; // normalized to [0.0, 1.0] based on BL bit depth
|
||||
uint8_t method[8]; // 0 = polynomial, 1 = MMR
|
||||
// Note: these must be normalized (divide by coefficient_log2_denom)
|
||||
float poly_coeffs[8][3]; // x^0, x^1, x^2, unused must be 0
|
||||
uint8_t mmr_order[8]; // 1, 2 or 3
|
||||
float mmr_constant[8];
|
||||
float mmr_coeffs[8][3 /* order */][7];
|
||||
} comp[3];
|
||||
};
|
||||
|
||||
// Struct describing the underlying color system and representation. This
|
||||
// information is needed to convert an encoded color to a normalized RGB triple
|
||||
// in the range 0-1.
|
||||
struct pl_color_repr {
|
||||
enum pl_color_system sys;
|
||||
enum pl_color_levels levels;
|
||||
enum pl_alpha_mode alpha;
|
||||
struct pl_bit_encoding bits; // or {0} if unknown
|
||||
|
||||
// Metadata for PL_COLOR_SYSTEM_DOLBYVISION. Note that, for the sake of
|
||||
// efficiency, this is treated purely as an opaque reference - functions
|
||||
// like pl_color_repr_equal will merely do a pointer equality test.
|
||||
//
|
||||
// The only functions that actually dereference it in any way are
|
||||
// pl_color_repr_decode, pl_shader_decode_color and pl_render_image(_mix).
|
||||
const struct pl_dovi_metadata *dovi;
|
||||
};
|
||||
|
||||
// Some common color representations. It's worth pointing out that all of these
|
||||
// presets leave `alpha` and `bits` as unknown - that is, only the system and
|
||||
// levels are predefined
|
||||
PL_API extern const struct pl_color_repr pl_color_repr_unknown;
|
||||
PL_API extern const struct pl_color_repr pl_color_repr_rgb;
|
||||
PL_API extern const struct pl_color_repr pl_color_repr_sdtv;
|
||||
PL_API extern const struct pl_color_repr pl_color_repr_hdtv; // also Blu-ray
|
||||
PL_API extern const struct pl_color_repr pl_color_repr_uhdtv; // SDR, NCL system
|
||||
PL_API extern const struct pl_color_repr pl_color_repr_jpeg;
|
||||
|
||||
// Returns whether two colorspace representations are exactly identical.
|
||||
PL_API bool pl_color_repr_equal(const struct pl_color_repr *c1,
|
||||
const struct pl_color_repr *c2);
|
||||
|
||||
// Replaces unknown values in the first struct by those of the second struct.
|
||||
PL_API void pl_color_repr_merge(struct pl_color_repr *orig,
|
||||
const struct pl_color_repr *update);
|
||||
|
||||
// This function normalizes the color representation such that
|
||||
// color_depth=sample_depth and bit_shift=0; and returns the scaling factor
|
||||
// that must be multiplied into the color value to accomplish this, assuming
|
||||
// it has already been sampled by the GPU. If unknown, the color and sample
|
||||
// depth will both be inferred as 8 bits for the purposes of this conversion.
|
||||
PL_API float pl_color_repr_normalize(struct pl_color_repr *repr);
|
||||
|
||||
// Guesses the best color levels based on the specified color levels and
|
||||
// falling back to using the color system instead. YCbCr-like systems are
|
||||
// assumed to be TV range, otherwise this defaults to PC range.
|
||||
PL_API enum pl_color_levels pl_color_levels_guess(const struct pl_color_repr *repr);
|
||||
|
||||
// The colorspace's primaries (gamut)
|
||||
enum pl_color_primaries {
|
||||
PL_COLOR_PRIM_UNKNOWN = 0,
|
||||
// Standard gamut:
|
||||
PL_COLOR_PRIM_BT_601_525, // ITU-R Rec. BT.601 (525-line = NTSC, SMPTE-C)
|
||||
PL_COLOR_PRIM_BT_601_625, // ITU-R Rec. BT.601 (625-line = PAL, SECAM)
|
||||
PL_COLOR_PRIM_BT_709, // ITU-R Rec. BT.709 (HD), also sRGB
|
||||
PL_COLOR_PRIM_BT_470M, // ITU-R Rec. BT.470 M
|
||||
PL_COLOR_PRIM_EBU_3213, // EBU Tech. 3213-E / JEDEC P22 phosphors
|
||||
// Wide gamut:
|
||||
PL_COLOR_PRIM_BT_2020, // ITU-R Rec. BT.2020 (UltraHD)
|
||||
PL_COLOR_PRIM_APPLE, // Apple RGB
|
||||
PL_COLOR_PRIM_ADOBE, // Adobe RGB (1998)
|
||||
PL_COLOR_PRIM_PRO_PHOTO, // ProPhoto RGB (ROMM)
|
||||
PL_COLOR_PRIM_CIE_1931, // CIE 1931 RGB primaries
|
||||
PL_COLOR_PRIM_DCI_P3, // DCI-P3 (Digital Cinema)
|
||||
PL_COLOR_PRIM_DISPLAY_P3, // DCI-P3 (Digital Cinema) with D65 white point
|
||||
PL_COLOR_PRIM_V_GAMUT, // Panasonic V-Gamut (VARICAM)
|
||||
PL_COLOR_PRIM_S_GAMUT, // Sony S-Gamut
|
||||
PL_COLOR_PRIM_FILM_C, // Traditional film primaries with Illuminant C
|
||||
PL_COLOR_PRIM_ACES_AP0, // ACES Primaries #0 (ultra wide)
|
||||
PL_COLOR_PRIM_ACES_AP1, // ACES Primaries #1
|
||||
PL_COLOR_PRIM_COUNT
|
||||
};
|
||||
|
||||
PL_API bool pl_color_primaries_is_wide_gamut(enum pl_color_primaries prim);
|
||||
|
||||
// Guesses the best primaries based on a resolution. This always guesses
|
||||
// conservatively, i.e. it will never return a wide gamut color space even if
|
||||
// the resolution is 4K.
|
||||
PL_API enum pl_color_primaries pl_color_primaries_guess(int width, int height);
|
||||
|
||||
// The colorspace's transfer function (gamma / EOTF)
|
||||
enum pl_color_transfer {
|
||||
PL_COLOR_TRC_UNKNOWN = 0,
|
||||
// Standard dynamic range:
|
||||
PL_COLOR_TRC_BT_1886, // ITU-R Rec. BT.1886 (CRT emulation + OOTF)
|
||||
PL_COLOR_TRC_SRGB, // IEC 61966-2-4 sRGB (CRT emulation)
|
||||
PL_COLOR_TRC_LINEAR, // Linear light content
|
||||
PL_COLOR_TRC_GAMMA18, // Pure power gamma 1.8
|
||||
PL_COLOR_TRC_GAMMA20, // Pure power gamma 2.0
|
||||
PL_COLOR_TRC_GAMMA22, // Pure power gamma 2.2
|
||||
PL_COLOR_TRC_GAMMA24, // Pure power gamma 2.4
|
||||
PL_COLOR_TRC_GAMMA26, // Pure power gamma 2.6
|
||||
PL_COLOR_TRC_GAMMA28, // Pure power gamma 2.8
|
||||
PL_COLOR_TRC_PRO_PHOTO, // ProPhoto RGB (ROMM)
|
||||
PL_COLOR_TRC_ST428, // Digital Cinema Distribution Master (XYZ)
|
||||
// High dynamic range:
|
||||
PL_COLOR_TRC_PQ, // ITU-R BT.2100 PQ (perceptual quantizer), aka SMPTE ST2048
|
||||
PL_COLOR_TRC_HLG, // ITU-R BT.2100 HLG (hybrid log-gamma), aka ARIB STD-B67
|
||||
PL_COLOR_TRC_V_LOG, // Panasonic V-Log (VARICAM)
|
||||
PL_COLOR_TRC_S_LOG1, // Sony S-Log1
|
||||
PL_COLOR_TRC_S_LOG2, // Sony S-Log2
|
||||
PL_COLOR_TRC_COUNT
|
||||
};
|
||||
|
||||
// Returns the nominal peak of a given transfer function, relative to the
|
||||
// reference white. This refers to the highest encodable signal level.
|
||||
// Always equal to 1.0 for SDR curves.
|
||||
//
|
||||
// Note: For HLG in particular, which is scene-referred, this returns the
|
||||
// highest nominal peak in scene-referred space (3.77), which may be different
|
||||
// from the actual peak in display space after application of the HLG OOTF.
|
||||
PL_API float pl_color_transfer_nominal_peak(enum pl_color_transfer trc);
|
||||
|
||||
static inline bool pl_color_transfer_is_hdr(enum pl_color_transfer trc)
|
||||
{
|
||||
return pl_color_transfer_nominal_peak(trc) > 1.0;
|
||||
}
|
||||
|
||||
// This defines the display-space standard reference white level (in cd/m^2)
|
||||
// that is assumed for SDR content, for use when mapping between HDR and SDR in
|
||||
// display space. See ITU-R Report BT.2408 for more information.
|
||||
#define PL_COLOR_SDR_WHITE 203.0f
|
||||
|
||||
// This defines the assumed contrast level of an unknown SDR display. This
|
||||
// will be used to determine the black point in the absence of any tagged
|
||||
// minimum luminance, relative to the tagged maximum luminance (or
|
||||
// PL_COLOR_SDR_WHITE in the absence of all tagging)
|
||||
#define PL_COLOR_SDR_CONTRAST 1000.0f
|
||||
|
||||
// This defines the default black point assumed for "infinite contrast" HDR
|
||||
// displays. This is not exactly 0.0 because a value of 0.0 is interpreted
|
||||
// as "unknown / missing metadata" inside struct pl_hdr_metadata, and also
|
||||
// to avoid numerical issues in a variety of tone mapping functions.
|
||||
// Essentially, a black level below this number is functionally meaningless
|
||||
// inside libplacebo, and will be clamped to this value regardless.
|
||||
//
|
||||
// The value used here (1e-6) is about one 13-bit PQ step above absolute zero,
|
||||
// which is a small fraction of the human JND at this brightness level, and also
|
||||
// about 3 bits above the floating point machine epsilon.
|
||||
#define PL_COLOR_HDR_BLACK 1e-6f
|
||||
|
||||
// This defines the assumed peak brightness of a HLG display with no HDR10
|
||||
// metadata. This is set to the brightness of a "nominal" HLG reference display.
|
||||
#define PL_COLOR_HLG_PEAK 1000.0f
|
||||
|
||||
// Represents a single CIE xy coordinate (e.g. CIE Yxy with Y = 1.0)
|
||||
struct pl_cie_xy {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
// Creates a pl_cie_xyz from raw XYZ values
|
||||
static inline struct pl_cie_xy pl_cie_from_XYZ(float X, float Y, float Z)
|
||||
{
|
||||
float k = 1.0f / (X + Y + Z);
|
||||
struct pl_cie_xy xy = { k * X, k * Y };
|
||||
return xy;
|
||||
}
|
||||
|
||||
// Recovers (X / Y) from a CIE xy value.
|
||||
static inline float pl_cie_X(struct pl_cie_xy xy)
|
||||
{
|
||||
return xy.x / xy.y;
|
||||
}
|
||||
|
||||
// Recovers (Z / Y) from a CIE xy value.
|
||||
static inline float pl_cie_Z(struct pl_cie_xy xy)
|
||||
{
|
||||
return (1 - xy.x - xy.y) / xy.y;
|
||||
}
|
||||
|
||||
static inline bool pl_cie_xy_equal(const struct pl_cie_xy *a,
|
||||
const struct pl_cie_xy *b)
|
||||
{
|
||||
return a->x == b->x && a->y == b->y;
|
||||
}
|
||||
|
||||
// Computes the CIE xy chromaticity coordinates of a CIE D-series illuminant
|
||||
// with the given correlated color temperature.
|
||||
//
|
||||
// `temperature` must be between 2500 K and 25000 K, inclusive.
|
||||
PL_API struct pl_cie_xy pl_white_from_temp(float temperature);
|
||||
|
||||
// Represents the raw physical primaries corresponding to a color space.
|
||||
struct pl_raw_primaries {
|
||||
struct pl_cie_xy red, green, blue, white;
|
||||
};
|
||||
|
||||
// Returns whether two raw primaries are exactly identical.
|
||||
PL_API bool pl_raw_primaries_equal(const struct pl_raw_primaries *a,
|
||||
const struct pl_raw_primaries *b);
|
||||
|
||||
// Returns whether two raw primaries are approximately equal
|
||||
PL_API bool pl_raw_primaries_similar(const struct pl_raw_primaries *a,
|
||||
const struct pl_raw_primaries *b);
|
||||
|
||||
// Replaces unknown values in the first struct by those of the second struct.
|
||||
PL_API void pl_raw_primaries_merge(struct pl_raw_primaries *orig,
|
||||
const struct pl_raw_primaries *update);
|
||||
|
||||
// Returns the raw primaries for a given color space.
|
||||
PL_API const struct pl_raw_primaries *pl_raw_primaries_get(enum pl_color_primaries prim);
|
||||
|
||||
enum pl_hdr_scaling {
|
||||
PL_HDR_NORM = 0, // 0.0 is absolute black, 1.0 is PL_COLOR_SDR_WHITE
|
||||
PL_HDR_SQRT, // sqrt() of PL_HDR_NORM values
|
||||
PL_HDR_NITS, // absolute brightness in raw cd/m²
|
||||
PL_HDR_PQ, // absolute brightness in PQ (0.0 to 1.0)
|
||||
PL_HDR_SCALING_COUNT,
|
||||
};
|
||||
|
||||
// Generic helper for performing HDR scale conversions.
|
||||
PL_API float pl_hdr_rescale(enum pl_hdr_scaling from, enum pl_hdr_scaling to, float x);
|
||||
|
||||
enum pl_hdr_metadata_type {
|
||||
PL_HDR_METADATA_ANY = 0,
|
||||
PL_HDR_METADATA_NONE,
|
||||
PL_HDR_METADATA_HDR10, // HDR10 static mastering display metadata
|
||||
PL_HDR_METADATA_HDR10PLUS, // HDR10+ dynamic metadata
|
||||
PL_HDR_METADATA_CIE_Y, // CIE Y derived dynamic luminance metadata
|
||||
PL_HDR_METADATA_TYPE_COUNT,
|
||||
};
|
||||
|
||||
// Bezier curve for HDR metadata
|
||||
struct pl_hdr_bezier {
|
||||
float target_luma; // target luminance (cd/m²) for this OOTF
|
||||
float knee_x, knee_y; // cross-over knee point (0-1)
|
||||
float anchors[15]; // intermediate bezier curve control points (0-1)
|
||||
uint8_t num_anchors;
|
||||
};
|
||||
|
||||
// Represents raw HDR metadata as defined by SMPTE 2086 / CTA 861.3, which is
|
||||
// often attached to HDR sources and can be forwarded to HDR-capable displays,
|
||||
// or used to guide the libplacebo built-in tone mapping. Values left as 0
|
||||
// are treated as unknown by libplacebo.
|
||||
//
|
||||
// Note: This means that a value of `min_luma == 0.0` gets treated as "minimum
|
||||
// luminance not known", which in practice may end up inferring a default
|
||||
// contrast of 1000:1 for SDR transfer functions. To avoid this, the user should
|
||||
// set these fields to a low positive value, e.g. PL_COLOR_HDR_BLACK, to signal
|
||||
// a "zero" black point (i.e. infinite contrast display).
|
||||
struct pl_hdr_metadata {
|
||||
// --- PL_HDR_METADATA_HDR10
|
||||
// Mastering display metadata.
|
||||
struct pl_raw_primaries prim; // mastering display primaries
|
||||
float min_luma, max_luma; // min/max luminance (in cd/m²)
|
||||
|
||||
// Content light level. (Note: this is ignored by libplacebo itself)
|
||||
float max_cll; // max content light level (in cd/m²)
|
||||
float max_fall; // max frame average light level (in cd/m²)
|
||||
|
||||
// --- PL_HDR_METADATA_HDR10PLUS
|
||||
float scene_max[3]; // maxSCL in cd/m² per component (RGB)
|
||||
float scene_avg; // average of maxRGB in cd/m²
|
||||
struct pl_hdr_bezier ootf; // reference OOTF (optional)
|
||||
|
||||
// --- PL_HDR_METADATA_CIE_Y
|
||||
float max_pq_y; // maximum PQ luminance (in PQ, 0-1)
|
||||
float avg_pq_y; // averaged PQ luminance (in PQ, 0-1)
|
||||
};
|
||||
|
||||
PL_API extern const struct pl_hdr_metadata pl_hdr_metadata_empty; // equal to {0}
|
||||
PL_API extern const struct pl_hdr_metadata pl_hdr_metadata_hdr10; // generic HDR10 display
|
||||
|
||||
// Returns whether two sets of HDR metadata are exactly identical.
|
||||
PL_API bool pl_hdr_metadata_equal(const struct pl_hdr_metadata *a,
|
||||
const struct pl_hdr_metadata *b);
|
||||
|
||||
// Replaces unknown values in the first struct by those of the second struct.
|
||||
PL_API void pl_hdr_metadata_merge(struct pl_hdr_metadata *orig,
|
||||
const struct pl_hdr_metadata *update);
|
||||
|
||||
// Returns `true` if `data` contains a complete set of a given metadata type.
|
||||
// Note: for PL_HDR_METADATA_HDR10, only `min_luma` and `max_luma` are
|
||||
// considered - CLL/FALL and primaries are irrelevant for HDR tone-mapping.
|
||||
PL_API bool pl_hdr_metadata_contains(const struct pl_hdr_metadata *data,
|
||||
enum pl_hdr_metadata_type type);
|
||||
|
||||
// Rendering intent for colorspace transformations. These constants match the
|
||||
// ICC specification (Table 23)
|
||||
enum pl_rendering_intent {
|
||||
PL_INTENT_AUTO = -1, // not a valid ICC intent, but used to auto-infer
|
||||
PL_INTENT_PERCEPTUAL = 0,
|
||||
PL_INTENT_RELATIVE_COLORIMETRIC = 1,
|
||||
PL_INTENT_SATURATION = 2,
|
||||
PL_INTENT_ABSOLUTE_COLORIMETRIC = 3
|
||||
};
|
||||
|
||||
// Struct describing a physical color space. This information is needed to
|
||||
// turn a normalized RGB triple into its physical meaning, as well as to convert
|
||||
// between color spaces.
|
||||
struct pl_color_space {
|
||||
enum pl_color_primaries primaries;
|
||||
enum pl_color_transfer transfer;
|
||||
|
||||
// HDR metadata for this color space, if present. (Optional)
|
||||
struct pl_hdr_metadata hdr;
|
||||
};
|
||||
|
||||
#define pl_color_space(...) (&(struct pl_color_space) { __VA_ARGS__ })
|
||||
|
||||
// Returns whether or not a color space is considered as effectively HDR.
|
||||
// This is true when the effective signal peak is greater than the SDR
|
||||
// reference white (1.0), taking into account `csp->hdr`.
|
||||
PL_API bool pl_color_space_is_hdr(const struct pl_color_space *csp);
|
||||
|
||||
// Returns whether or not a color space is "black scaled", in which case 0.0 is
|
||||
// the true black point. This is true for SDR signals other than BT.1886, as
|
||||
// well as for HLG.
|
||||
PL_API bool pl_color_space_is_black_scaled(const struct pl_color_space *csp);
|
||||
|
||||
struct pl_nominal_luma_params {
|
||||
// The color space to infer luminance from
|
||||
const struct pl_color_space *color;
|
||||
|
||||
// Which type of metadata to draw values from
|
||||
enum pl_hdr_metadata_type metadata;
|
||||
|
||||
// This field controls the scaling of `out_*`
|
||||
enum pl_hdr_scaling scaling;
|
||||
|
||||
// Fields to write the detected nominal luminance to. (Optional)
|
||||
//
|
||||
// For SDR displays, this will default to a contrast level of 1000:1 unless
|
||||
// indicated otherwise in the `min/max_luma` static HDR10 metadata fields.
|
||||
float *out_min;
|
||||
float *out_max;
|
||||
|
||||
// Field to write the detected average luminance to, or 0.0 in the absence
|
||||
// of dynamic metadata. (Optional)
|
||||
float *out_avg;
|
||||
};
|
||||
|
||||
#define pl_nominal_luma_params(...) \
|
||||
(&(struct pl_nominal_luma_params) { __VA_ARGS__ })
|
||||
|
||||
// Returns the effective luminance described by a pl_color_space.
|
||||
PL_API void pl_color_space_nominal_luma_ex(const struct pl_nominal_luma_params *params);
|
||||
|
||||
// Backwards compatibility wrapper for `pl_color_space_nominal_luma_ex`
|
||||
PL_DEPRECATED PL_API void pl_color_space_nominal_luma(const struct pl_color_space *csp,
|
||||
float *out_min, float *out_max);
|
||||
|
||||
// Replaces unknown values in the first struct by those of the second struct.
|
||||
PL_API void pl_color_space_merge(struct pl_color_space *orig,
|
||||
const struct pl_color_space *update);
|
||||
|
||||
// Returns whether two colorspaces are exactly identical.
|
||||
PL_API bool pl_color_space_equal(const struct pl_color_space *c1,
|
||||
const struct pl_color_space *c2);
|
||||
|
||||
// Go through a color-space and explicitly default all unknown fields to
|
||||
// reasonable values. After this function is called, none of the values will be
|
||||
// PL_COLOR_*_UNKNOWN or 0.0, except for the dynamic HDR metadata fields.
|
||||
PL_API void pl_color_space_infer(struct pl_color_space *space);
|
||||
|
||||
// Like `pl_color_space_infer`, but takes default values from the reference
|
||||
// color space (excluding certain special cases like HDR or wide gamut).
|
||||
PL_API void pl_color_space_infer_ref(struct pl_color_space *space,
|
||||
const struct pl_color_space *ref);
|
||||
|
||||
// Infer both the source and destination gamut simultaneously, and also adjust
|
||||
// values for optimal display. This is mostly the same as
|
||||
// `pl_color_space_infer(src)` followed by `pl_color_space_infer_ref`, but also
|
||||
// takes into account the SDR contrast levels and PQ black points. This is
|
||||
// basically the logic used by `pl_shader_color_map` and `pl_renderer` to
|
||||
// decide the output color space in a conservative way and compute the final
|
||||
// end-to-end color transformation that needs to be done.
|
||||
PL_API void pl_color_space_infer_map(struct pl_color_space *src,
|
||||
struct pl_color_space *dst);
|
||||
|
||||
// Some common color spaces. Note: These don't necessarily have all fields
|
||||
// filled, in particular `hdr` is left unset.
|
||||
PL_API extern const struct pl_color_space pl_color_space_unknown;
|
||||
PL_API extern const struct pl_color_space pl_color_space_srgb;
|
||||
PL_API extern const struct pl_color_space pl_color_space_bt709;
|
||||
PL_API extern const struct pl_color_space pl_color_space_hdr10;
|
||||
PL_API extern const struct pl_color_space pl_color_space_bt2020_hlg;
|
||||
PL_API extern const struct pl_color_space pl_color_space_monitor; // typical display
|
||||
|
||||
// This represents metadata about extra operations to perform during colorspace
|
||||
// conversion, which correspond to artistic adjustments of the color.
|
||||
struct pl_color_adjustment {
|
||||
// Brightness boost. 0.0 = neutral, 1.0 = solid white, -1.0 = solid black
|
||||
float brightness;
|
||||
// Contrast boost. 1.0 = neutral, 0.0 = solid black
|
||||
float contrast;
|
||||
// Saturation gain. 1.0 = neutral, 0.0 = grayscale
|
||||
float saturation;
|
||||
// Hue shift, corresponding to a rotation around the [U, V] subvector, in
|
||||
// radians. 0.0 = neutral
|
||||
float hue;
|
||||
// Gamma adjustment. 1.0 = neutral, 0.0 = solid black
|
||||
float gamma;
|
||||
// Color temperature shift. 0.0 = 6500 K, -1.0 = 3000 K, 1.0 = 10000 K
|
||||
float temperature;
|
||||
};
|
||||
|
||||
#define PL_COLOR_ADJUSTMENT_NEUTRAL \
|
||||
.contrast = 1.0, \
|
||||
.saturation = 1.0, \
|
||||
.gamma = 1.0,
|
||||
|
||||
#define pl_color_adjustment(...) (&(struct pl_color_adjustment) { PL_COLOR_ADJUSTMENT_NEUTRAL __VA_ARGS__ })
|
||||
PL_API extern const struct pl_color_adjustment pl_color_adjustment_neutral;
|
||||
|
||||
// Represents the chroma placement with respect to the luma samples. This is
|
||||
// only relevant for YCbCr-like colorspaces with chroma subsampling.
|
||||
enum pl_chroma_location {
|
||||
PL_CHROMA_UNKNOWN = 0,
|
||||
PL_CHROMA_LEFT, // MPEG2/4, H.264
|
||||
PL_CHROMA_CENTER, // MPEG1, JPEG
|
||||
PL_CHROMA_TOP_LEFT,
|
||||
PL_CHROMA_TOP_CENTER,
|
||||
PL_CHROMA_BOTTOM_LEFT,
|
||||
PL_CHROMA_BOTTOM_CENTER,
|
||||
PL_CHROMA_COUNT,
|
||||
};
|
||||
|
||||
// Fills *x and *y with the offset in luma pixels corresponding to a given
|
||||
// chroma location.
|
||||
//
|
||||
// Note: PL_CHROMA_UNKNOWN defaults to PL_CHROMA_LEFT
|
||||
PL_API void pl_chroma_location_offset(enum pl_chroma_location loc, float *x, float *y);
|
||||
|
||||
// Returns an RGB->XYZ conversion matrix for a given set of primaries.
|
||||
// Multiplying this into the RGB color transforms it to CIE XYZ, centered
|
||||
// around the color space's white point.
|
||||
PL_API pl_matrix3x3 pl_get_rgb2xyz_matrix(const struct pl_raw_primaries *prim);
|
||||
|
||||
// Similar to pl_get_rgb2xyz_matrix, but gives the inverse transformation.
|
||||
PL_API pl_matrix3x3 pl_get_xyz2rgb_matrix(const struct pl_raw_primaries *prim);
|
||||
|
||||
// Returns a primary adaptation matrix, which converts from one set of
|
||||
// primaries to another. This is an RGB->RGB transformation. For rendering
|
||||
// intents other than PL_INTENT_ABSOLUTE_COLORIMETRIC, the white point is
|
||||
// adapted using the Bradford matrix.
|
||||
PL_API pl_matrix3x3 pl_get_color_mapping_matrix(const struct pl_raw_primaries *src,
|
||||
const struct pl_raw_primaries *dst,
|
||||
enum pl_rendering_intent intent);
|
||||
|
||||
// Return a chromatic adaptation matrix, which converts from one white point to
|
||||
// another, using the Bradford matrix. This is an RGB->RGB transformation.
|
||||
PL_API pl_matrix3x3 pl_get_adaptation_matrix(struct pl_cie_xy src, struct pl_cie_xy dst);
|
||||
|
||||
// Returns true if 'b' is entirely contained in 'a'. Useful for figuring out if
|
||||
// colorimetric clipping will occur or not.
|
||||
PL_API bool pl_primaries_superset(const struct pl_raw_primaries *a,
|
||||
const struct pl_raw_primaries *b);
|
||||
|
||||
// Returns true if `prim` forms a nominally valid set of primaries. This does
|
||||
// not check whether or not these primaries are actually physically realisable,
|
||||
// merely that they satisfy the requirements for colorspace math (to avoid NaN).
|
||||
PL_API bool pl_primaries_valid(const struct pl_raw_primaries *prim);
|
||||
|
||||
// Returns true if two primaries are 'compatible', which is the case if
|
||||
// they preserve the relationship between primaries (red=red, green=green,
|
||||
// blue=blue). In other words, this is false for synthetic primaries that have
|
||||
// channels misordered from the convention (e.g. for some test ICC profiles).
|
||||
PL_API bool pl_primaries_compatible(const struct pl_raw_primaries *a,
|
||||
const struct pl_raw_primaries *b);
|
||||
|
||||
// Clip points in the first gamut (src) to be fully contained inside the second
|
||||
// gamut (dst). Only works on compatible primaries (pl_primaries_compatible).
|
||||
PL_API struct pl_raw_primaries
|
||||
pl_primaries_clip(const struct pl_raw_primaries *src,
|
||||
const struct pl_raw_primaries *dst);
|
||||
|
||||
// Primary-dependent RGB->LMS matrix for the IPTPQc4 color system. This is
|
||||
// derived from the HPE XYZ->LMS matrix with 4% crosstalk added.
|
||||
PL_API pl_matrix3x3 pl_ipt_rgb2lms(const struct pl_raw_primaries *prim);
|
||||
PL_API pl_matrix3x3 pl_ipt_lms2rgb(const struct pl_raw_primaries *prim);
|
||||
|
||||
// Primary-independent L'M'S' -> IPT matrix for the IPTPQc4 color system, and
|
||||
// its inverse. This is identical to the Ebner & Fairchild (1998) IPT matrix.
|
||||
PL_API extern const pl_matrix3x3 pl_ipt_lms2ipt;
|
||||
PL_API extern const pl_matrix3x3 pl_ipt_ipt2lms;
|
||||
|
||||
// Cone types involved in human vision
|
||||
enum pl_cone {
|
||||
PL_CONE_L = 1 << 0,
|
||||
PL_CONE_M = 1 << 1,
|
||||
PL_CONE_S = 1 << 2,
|
||||
|
||||
// Convenience aliases
|
||||
PL_CONE_NONE = 0,
|
||||
PL_CONE_LM = PL_CONE_L | PL_CONE_M,
|
||||
PL_CONE_MS = PL_CONE_M | PL_CONE_S,
|
||||
PL_CONE_LS = PL_CONE_L | PL_CONE_S,
|
||||
PL_CONE_LMS = PL_CONE_L | PL_CONE_M | PL_CONE_S,
|
||||
};
|
||||
|
||||
// Structure describing parameters for simulating color blindness
|
||||
struct pl_cone_params {
|
||||
enum pl_cone cones; // Which cones are *affected* by the vision model
|
||||
float strength; // Coefficient for how strong the defect is
|
||||
// (1.0 = Unaffected, 0.0 = Full blindness)
|
||||
};
|
||||
|
||||
#define pl_cone_params(...) (&(struct pl_cone_params) { __VA_ARGS__ })
|
||||
|
||||
// Built-in color blindness models
|
||||
PL_API extern const struct pl_cone_params pl_vision_normal; // No distortion (92%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_protanomaly; // Red deficiency (0.66%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_protanopia; // Red absence (0.59%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_deuteranomaly; // Green deficiency (2.7%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_deuteranopia; // Green absence (0.56%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_tritanomaly; // Blue deficiency (0.01%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_tritanopia; // Blue absence (0.016%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_monochromacy; // Blue cones only (<0.001%)
|
||||
PL_API extern const struct pl_cone_params pl_vision_achromatopsia; // Rods only (<0.0001%)
|
||||
|
||||
// Returns a cone adaptation matrix. Applying this to an RGB color in the given
|
||||
// color space will apply the given cone adaptation coefficients for simulating
|
||||
// a type of color blindness.
|
||||
//
|
||||
// For the color blindness models which don't entail complete loss of a cone,
|
||||
// you can partially counteract the effect by using a similar model with the
|
||||
// `strength` set to its inverse. For example, to partially counteract
|
||||
// deuteranomaly, you could generate a cone matrix for PL_CONE_M with the
|
||||
// strength 2.0 (or some other number above 1.0).
|
||||
PL_API pl_matrix3x3 pl_get_cone_matrix(const struct pl_cone_params *params,
|
||||
const struct pl_raw_primaries *prim);
|
||||
|
||||
// Returns a color decoding matrix for a given combination of source color
|
||||
// representation and adjustment parameters. This mutates `repr` to reflect the
|
||||
// change. If `params` is NULL, it defaults to &pl_color_adjustment_neutral.
|
||||
//
|
||||
// This function always performs a conversion to RGB. To convert to other
|
||||
// colorspaces (e.g. between YUV systems), obtain a second YUV->RGB matrix
|
||||
// and invert it using `pl_transform3x3_invert`.
|
||||
//
|
||||
// Note: For BT.2020 constant-luminance, this outputs chroma information in the
|
||||
// range [-0.5, 0.5]. Since the CL system conversion is non-linear, further
|
||||
// processing must be done by the caller. The channel order is CrYCb.
|
||||
//
|
||||
// Note: For BT.2100 ICtCp, this outputs in the color space L'M'S'. Further
|
||||
// non-linear processing must be done by the caller.
|
||||
//
|
||||
// Note: XYZ system is expected to be in DCDM X'Y'Z' encoding (ST 428-1), in
|
||||
// practice this means normalizing by (48.0 / 52.37) factor and applying 2.6 gamma
|
||||
PL_API pl_transform3x3 pl_color_repr_decode(struct pl_color_repr *repr,
|
||||
const struct pl_color_adjustment *params);
|
||||
|
||||
// Common struct to describe an ICC profile
|
||||
struct pl_icc_profile {
|
||||
// Points to the in-memory representation of the ICC profile. This is
|
||||
// allowed to be NULL, in which case the `pl_icc_profile` represents "no
|
||||
// profile”.
|
||||
const void *data;
|
||||
size_t len;
|
||||
|
||||
// If a profile is set, this signature must uniquely identify it (including
|
||||
// across restarts, for caching), ideally using a checksum of the profile
|
||||
// contents. The user is free to choose the method of determining this
|
||||
// signature, but note the existence of the
|
||||
// `pl_icc_profile_compute_signature` helper.
|
||||
uint64_t signature;
|
||||
};
|
||||
|
||||
#define pl_icc_profile(...) &(struct pl_icc_profile) { __VA_ARGS__ }
|
||||
|
||||
// This doesn't do a comparison of the actual contents, only of the signature.
|
||||
PL_API bool pl_icc_profile_equal(const struct pl_icc_profile *p1,
|
||||
const struct pl_icc_profile *p2);
|
||||
|
||||
// Sets `signature` to a hash of `profile->data`, if non-NULL. Provided as a
|
||||
// convenience function for the sake of users ingesting arbitrary ICC profiles
|
||||
// from sources where they can't reliably detect profile changes.
|
||||
//
|
||||
// Note: This is based on a very fast hash, and will compute a signature for
|
||||
// even large (10 MB) ICC profiles in, typically, a fraction of a millisecond.
|
||||
PL_API void pl_icc_profile_compute_signature(struct pl_icc_profile *profile);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_COLORSPACE_H_
|
||||
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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_COMMON_H_
|
||||
#define LIBPLACEBO_COMMON_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libplacebo/config.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Some common utility types. These are overloaded to support 2D, 3D and
|
||||
// integer/float variants.
|
||||
typedef struct pl_rect2d {
|
||||
int x0, y0;
|
||||
int x1, y1;
|
||||
} pl_rect2d;
|
||||
|
||||
typedef struct pl_rect3d {
|
||||
int x0, y0, z0;
|
||||
int x1, y1, z1;
|
||||
} pl_rect3d;
|
||||
|
||||
typedef struct pl_rect2df {
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} pl_rect2df;
|
||||
|
||||
typedef struct pl_rect3df {
|
||||
float x0, y0, z0;
|
||||
float x1, y1, z1;
|
||||
} pl_rect3df;
|
||||
|
||||
// These macros will work for any of the above pl_rect variants (with enough
|
||||
// dimensions). Careful: double-evaluation hazard
|
||||
#define pl_rect_w(r) ((r).x1 - (r).x0)
|
||||
#define pl_rect_h(r) ((r).y1 - (r).y0)
|
||||
#define pl_rect_d(r) ((r).z1 - (r).z0)
|
||||
|
||||
#define pl_rect2d_eq(a, b) \
|
||||
((a).x0 == (b).x0 && (a).x1 == (b).x1 && \
|
||||
(a).y0 == (b).y0 && (a).y1 == (b).y1)
|
||||
|
||||
#define pl_rect3d_eq(a, b) \
|
||||
((a).x0 == (b).x0 && (a).x1 == (b).x1 && \
|
||||
(a).y0 == (b).y0 && (a).y1 == (b).y1 && \
|
||||
(a).z0 == (b).z0 && (a).z1 == (b).z1)
|
||||
|
||||
// "Normalize" a rectangle: This ensures d1 >= d0 for all dimensions.
|
||||
PL_API void pl_rect2d_normalize(pl_rect2d *rc);
|
||||
PL_API void pl_rect3d_normalize(pl_rect3d *rc);
|
||||
|
||||
PL_API void pl_rect2df_normalize(pl_rect2df *rc);
|
||||
PL_API void pl_rect3df_normalize(pl_rect3df *rc);
|
||||
|
||||
// Return the rounded form of a rect.
|
||||
PL_API pl_rect2d pl_rect2df_round(const pl_rect2df *rc);
|
||||
PL_API pl_rect3d pl_rect3df_round(const pl_rect3df *rc);
|
||||
|
||||
// Represents a row-major matrix, i.e. the following matrix
|
||||
// [ a11 a12 a13 ]
|
||||
// [ a21 a22 a23 ]
|
||||
// [ a31 a32 a33 ]
|
||||
// is represented in C like this:
|
||||
// { { a11, a12, a13 },
|
||||
// { a21, a22, a23 },
|
||||
// { a31, a32, a33 } };
|
||||
typedef struct pl_matrix3x3 {
|
||||
float m[3][3];
|
||||
} pl_matrix3x3;
|
||||
|
||||
PL_API extern const pl_matrix3x3 pl_matrix3x3_identity;
|
||||
|
||||
// Applies a matrix to a float vector in-place.
|
||||
PL_API void pl_matrix3x3_apply(const pl_matrix3x3 *mat, float vec[3]);
|
||||
|
||||
// Applies a matrix to a pl_rect3df
|
||||
PL_API void pl_matrix3x3_apply_rc(const pl_matrix3x3 *mat, pl_rect3df *rc);
|
||||
|
||||
// Scales a color matrix by a linear factor.
|
||||
PL_API void pl_matrix3x3_scale(pl_matrix3x3 *mat, float scale);
|
||||
|
||||
// Inverts a matrix. Only use where precision is not that important.
|
||||
PL_API void pl_matrix3x3_invert(pl_matrix3x3 *mat);
|
||||
|
||||
// Composes/multiplies two matrices. Multiples B into A, i.e.
|
||||
// A := A * B
|
||||
PL_API void pl_matrix3x3_mul(pl_matrix3x3 *a, const pl_matrix3x3 *b);
|
||||
|
||||
// Flipped version of `pl_matrix3x3_mul`.
|
||||
// B := A * B
|
||||
PL_API void pl_matrix3x3_rmul(const pl_matrix3x3 *a, pl_matrix3x3 *b);
|
||||
|
||||
// Represents an affine transformation, which is basically a 3x3 matrix
|
||||
// together with a column vector to add onto the output.
|
||||
typedef struct pl_transform3x3 {
|
||||
pl_matrix3x3 mat;
|
||||
float c[3];
|
||||
} pl_transform3x3;
|
||||
|
||||
PL_API extern const pl_transform3x3 pl_transform3x3_identity;
|
||||
|
||||
// Applies a transform to a float vector in-place.
|
||||
PL_API void pl_transform3x3_apply(const pl_transform3x3 *t, float vec[3]);
|
||||
|
||||
// Applies a transform to a pl_rect3df
|
||||
PL_API void pl_transform3x3_apply_rc(const pl_transform3x3 *t, pl_rect3df *rc);
|
||||
|
||||
// Scales the output of a transform by a linear factor. Since an affine
|
||||
// transformation is non-linear, this does not commute. If you want to scale
|
||||
// the *input* of a transform, use pl_matrix3x3_scale on `t.mat`.
|
||||
PL_API void pl_transform3x3_scale(pl_transform3x3 *t, float scale);
|
||||
|
||||
// Inverts a transform. Only use where precision is not that important.
|
||||
PL_API void pl_transform3x3_invert(pl_transform3x3 *t);
|
||||
|
||||
// 2D analog of the above structs. Since these are featured less prominently,
|
||||
// we omit some of the other helper functions.
|
||||
typedef struct pl_matrix2x2 {
|
||||
float m[2][2];
|
||||
} pl_matrix2x2;
|
||||
|
||||
PL_API extern const pl_matrix2x2 pl_matrix2x2_identity;
|
||||
PL_API pl_matrix2x2 pl_matrix2x2_rotation(float angle);
|
||||
|
||||
PL_API void pl_matrix2x2_apply(const pl_matrix2x2 *mat, float vec[2]);
|
||||
PL_API void pl_matrix2x2_apply_rc(const pl_matrix2x2 *mat, pl_rect2df *rc);
|
||||
|
||||
PL_API void pl_matrix2x2_mul(pl_matrix2x2 *a, const pl_matrix2x2 *b);
|
||||
PL_API void pl_matrix2x2_rmul(const pl_matrix2x2 *a, pl_matrix2x2 *b);
|
||||
|
||||
PL_API void pl_matrix2x2_scale(pl_matrix2x2 *mat, float scale);
|
||||
PL_API void pl_matrix2x2_invert(pl_matrix2x2 *mat);
|
||||
|
||||
typedef struct pl_transform2x2 {
|
||||
pl_matrix2x2 mat;
|
||||
float c[2];
|
||||
} pl_transform2x2;
|
||||
|
||||
PL_API extern const pl_transform2x2 pl_transform2x2_identity;
|
||||
|
||||
PL_API void pl_transform2x2_apply(const pl_transform2x2 *t, float vec[2]);
|
||||
PL_API void pl_transform2x2_apply_rc(const pl_transform2x2 *t, pl_rect2df *rc);
|
||||
|
||||
PL_API void pl_transform2x2_mul(pl_transform2x2 *a, const pl_transform2x2 *b);
|
||||
PL_API void pl_transform2x2_rmul(const pl_transform2x2 *a, pl_transform2x2 *b);
|
||||
|
||||
PL_API void pl_transform2x2_scale(pl_transform2x2 *t, float scale);
|
||||
PL_API void pl_transform2x2_invert(pl_transform2x2 *t);
|
||||
|
||||
// Compute new bounding box of a transformation (as applied to a given rect).
|
||||
PL_API pl_rect2df pl_transform2x2_bounds(const pl_transform2x2 *t,
|
||||
const pl_rect2df *rc);
|
||||
|
||||
// Helper functions for dealing with aspect ratios and stretched/scaled rects.
|
||||
|
||||
// Return the (absolute) aspect ratio (width/height) of a given pl_rect2df.
|
||||
// This will always be a positive number, even if `rc` is flipped.
|
||||
PL_API float pl_rect2df_aspect(const pl_rect2df *rc);
|
||||
|
||||
// Set the aspect of a `rc` to a given aspect ratio with an extra 'panscan'
|
||||
// factor choosing the balance between shrinking and growing the `rc` to meet
|
||||
// this aspect ratio.
|
||||
//
|
||||
// Notes:
|
||||
// - If `panscan` is 0.0, this function will only ever shrink the `rc`.
|
||||
// - If `panscan` is 1.0, this function will only ever grow the `rc`.
|
||||
// - If `panscan` is 0.5, this function is area-preserving.
|
||||
PL_API void pl_rect2df_aspect_set(pl_rect2df *rc, float aspect, float panscan);
|
||||
|
||||
// Set one rect's aspect to that of another
|
||||
#define pl_rect2df_aspect_copy(rc, src, panscan) \
|
||||
pl_rect2df_aspect_set((rc), pl_rect2df_aspect(src), (panscan))
|
||||
|
||||
// 'Fit' one rect inside another. `rc` will be set to the same size and aspect
|
||||
// ratio as `src`, but with the size limited to fit inside the original `rc`.
|
||||
// Like `pl_rect2df_aspect_set`, `panscan` controls the pan&scan factor.
|
||||
PL_API void pl_rect2df_aspect_fit(pl_rect2df *rc, const pl_rect2df *src, float panscan);
|
||||
|
||||
// Scale rect in each direction while keeping it centered.
|
||||
PL_API void pl_rect2df_stretch(pl_rect2df *rc, float stretch_x, float stretch_y);
|
||||
|
||||
// Offset rect by an arbitrary offset factor. If the corresponding dimension
|
||||
// of a rect is flipped, so too is the applied offset.
|
||||
PL_API void pl_rect2df_offset(pl_rect2df *rc, float offset_x, float offset_y);
|
||||
|
||||
// Scale a rect uniformly in both dimensions.
|
||||
#define pl_rect2df_zoom(rc, zoom) pl_rect2df_stretch((rc), (zoom), (zoom))
|
||||
|
||||
// Rotation in degrees clockwise
|
||||
typedef int pl_rotation;
|
||||
enum {
|
||||
PL_ROTATION_0 = 0,
|
||||
PL_ROTATION_90 = 1,
|
||||
PL_ROTATION_180 = 2,
|
||||
PL_ROTATION_270 = 3,
|
||||
PL_ROTATION_360 = 4, // equivalent to PL_ROTATION_0
|
||||
|
||||
// Note: Values outside the range [0,4) are legal, including negatives.
|
||||
};
|
||||
|
||||
// Constrains to the interval [PL_ROTATION_0, PL_ROTATION_360).
|
||||
static inline pl_rotation pl_rotation_normalize(pl_rotation rot)
|
||||
{
|
||||
return (rot % PL_ROTATION_360 + PL_ROTATION_360) % PL_ROTATION_360;
|
||||
}
|
||||
|
||||
// Rotates the coordinate system of a `pl_rect2d(f)` in a certain direction.
|
||||
// For example, calling this with PL_ROTATION_90 will correspond to rotating
|
||||
// the coordinate system 90° to the right (so the x axis becomes the y axis).
|
||||
//
|
||||
// The resulting rect is re-normalized in the same coordinate system.
|
||||
PL_API void pl_rect2df_rotate(pl_rect2df *rc, pl_rotation rot);
|
||||
|
||||
// Returns the aspect ratio in a rotated frame of reference.
|
||||
static inline float pl_aspect_rotate(float aspect, pl_rotation rot)
|
||||
{
|
||||
return (rot % PL_ROTATION_180) ? 1.0 / aspect : aspect;
|
||||
}
|
||||
|
||||
#define pl_rect2df_aspect_set_rot(rc, aspect, rot, panscan) \
|
||||
pl_rect2df_aspect_set((rc), pl_aspect_rotate((aspect), (rot)), (panscan))
|
||||
|
||||
#define pl_rect2df_aspect_copy_rot(rc, src, panscan, rot) \
|
||||
pl_rect2df_aspect_set_rot((rc), pl_rect2df_aspect(src), (rot), (panscan))
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_COMMON_H_
|
||||
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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_CONFIG_H_
|
||||
#define LIBPLACEBO_CONFIG_H_
|
||||
|
||||
// Increased any time the library changes in a fundamental/major way.
|
||||
#define PL_MAJOR_VER 6
|
||||
|
||||
// Increased any time the API changes. (Note: Does not reset when PL_MAJOR_VER
|
||||
// is increased)
|
||||
#define PL_API_VER 338
|
||||
|
||||
// Increased any time a fix is made to a given API version.
|
||||
#define PL_FIX_VER (pl_fix_ver())
|
||||
|
||||
// Friendly name (`git describe`) for the overall version of the library
|
||||
#define PL_VERSION (pl_version())
|
||||
|
||||
// Feature tests. These aren't described in further detail, but may be useful
|
||||
// for programmers wanting to programmatically check for feature support
|
||||
// in their compiled libplacebo versions.
|
||||
#undef PL_HAVE_D3D11
|
||||
#define PL_HAVE_DOVI 1
|
||||
#define PL_HAVE_GL_PROC_ADDR 1
|
||||
#undef PL_HAVE_GLSLANG
|
||||
#define PL_HAVE_LCMS 1
|
||||
#undef PL_HAVE_LIBDOVI
|
||||
#undef PL_HAVE_OPENGL
|
||||
#define PL_HAVE_SHADERC 1
|
||||
#define PL_HAVE_VK_PROC_ADDR 1
|
||||
#define PL_HAVE_VULKAN 1
|
||||
#undef PL_HAVE_XXHASH
|
||||
|
||||
|
||||
// Extra compiler-specific stuff
|
||||
#ifndef PL_DEPRECATED
|
||||
# if defined(_MSC_VER)
|
||||
# define PL_DEPRECATED
|
||||
# else
|
||||
# define PL_DEPRECATED __attribute__((deprecated))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef PL_DEPRECATED_ENUMERATOR
|
||||
# if (defined(__GNUC__) && (__GNUC__ >= 6)) || __has_feature(enumerator_attributes)
|
||||
# define PL_DEPRECATED_ENUMERATOR PL_DEPRECATED
|
||||
# else
|
||||
# define PL_DEPRECATED_ENUMERATOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# ifdef PL_EXPORT
|
||||
# define PL_API __declspec(dllexport)
|
||||
# else
|
||||
# ifndef PL_STATIC
|
||||
# define PL_API __declspec(dllimport)
|
||||
# else
|
||||
# define PL_API
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define PL_API __attribute__ ((visibility ("default")))
|
||||
#endif
|
||||
|
||||
// C++ compatibility
|
||||
#ifdef __cplusplus
|
||||
# define PL_API_BEGIN extern "C" {
|
||||
# define PL_API_END }
|
||||
#else
|
||||
# define PL_API_BEGIN
|
||||
# define PL_API_END
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
// Disable this warning because libplacebo's params macros override fields
|
||||
# pragma GCC diagnostic ignored "-Woverride-init"
|
||||
#endif
|
||||
|
||||
// Extra helper macros
|
||||
#define PL_TOSTRING_INNER(x) #x
|
||||
#define PL_TOSTRING(x) PL_TOSTRING_INNER(x)
|
||||
|
||||
// Deprecated macro for back-compatibility
|
||||
#define PL_STRUCT(name) struct name##_t
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
PL_API int pl_fix_ver(void);
|
||||
PL_API const char *pl_version(void);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_CONFIG_H_
|
||||
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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_D3D11_H_
|
||||
#define LIBPLACEBO_D3D11_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d11.h>
|
||||
#include <dxgi1_2.h>
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/swapchain.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Structure representing the actual D3D11 device and associated GPU instance
|
||||
typedef const struct pl_d3d11_t {
|
||||
pl_gpu gpu;
|
||||
|
||||
// The D3D11 device in use. The user is free to use this for their own
|
||||
// purposes, including taking a reference to the device (with AddRef) and
|
||||
// using it beyond the lifetime of the pl_d3d11 that created it (though if
|
||||
// this is done with debug enabled, it will confuse the leak checker.)
|
||||
ID3D11Device *device;
|
||||
|
||||
// True if the device is using a software (WARP) adapter
|
||||
bool software;
|
||||
} *pl_d3d11;
|
||||
|
||||
struct pl_d3d11_params {
|
||||
// The Direct3D 11 device to use. Optional, if NULL then libplacebo will
|
||||
// create its own ID3D11Device using the options below. If set, all the
|
||||
// options below will be ignored.
|
||||
ID3D11Device *device;
|
||||
|
||||
// --- Adapter selection options
|
||||
|
||||
// The adapter to use. This overrides adapter_luid.
|
||||
IDXGIAdapter *adapter;
|
||||
|
||||
// The LUID of the adapter to use. If adapter and adapter_luid are unset,
|
||||
// the default adapter will be used instead.
|
||||
LUID adapter_luid;
|
||||
|
||||
// Allow a software (WARP) adapter when selecting the adapter automatically.
|
||||
// Note that sometimes the default adapter will be a software adapter. This
|
||||
// is because, on Windows 8 and up, if there are no hardware adapters,
|
||||
// Windows will pretend the WARP adapter is the default hardware adapter.
|
||||
bool allow_software;
|
||||
|
||||
// Always use a software adapter. This is mainly for testing purposes.
|
||||
bool force_software;
|
||||
|
||||
// --- Device creation options
|
||||
|
||||
// Enable the debug layer (D3D11_CREATE_DEVICE_DEBUG)
|
||||
// Also logs IDXGIInfoQueue messages
|
||||
bool debug;
|
||||
|
||||
// Extra flags to pass to D3D11CreateDevice (D3D11_CREATE_DEVICE_FLAG).
|
||||
// libplacebo should be compatible with any flags passed here.
|
||||
UINT flags;
|
||||
|
||||
// The minimum and maximum allowable feature levels for the created device.
|
||||
// libplacebo will attempt to create a device with the highest feature level
|
||||
// between min_feature_level and max_feature_level (inclusive.) If there are
|
||||
// no supported feature levels in this range, `pl_d3d11_create` will either
|
||||
// return NULL or fall back to the software adapter, depending on whether
|
||||
// `allow_software` is set.
|
||||
//
|
||||
// Normally there is no reason to set `max_feature_level` other than to test
|
||||
// if a program works at lower feature levels.
|
||||
//
|
||||
// Note that D3D_FEATURE_LEVEL_9_3 and below (known as 10level9) are highly
|
||||
// restrictive. These feature levels are supported on a best-effort basis.
|
||||
// They represent very old DirectX 9 compatible PC and laptop hardware
|
||||
// (2001-2007, GeForce FX, 6, 7, ATI R300-R500, GMA 950-X3000) and some
|
||||
// less-old mobile devices (Surface RT, Surface 2.) Basic video rendering
|
||||
// should work, but the full pl_gpu API will not be available and advanced
|
||||
// shaders will probably fail. The hardware is probably too slow for these
|
||||
// anyway.
|
||||
//
|
||||
// Known restrictions of 10level9 devices include:
|
||||
// D3D_FEATURE_LEVEL_9_3 and below:
|
||||
// - `pl_pass_run_params->index_buf` will not work (but `index_data` will)
|
||||
// - Dimensions of 3D textures must be powers of two
|
||||
// - Shaders cannot use gl_FragCoord
|
||||
// - Shaders cannot use texelFetch
|
||||
// D3D_FEATURE_LEVEL_9_2 and below:
|
||||
// - Fragment shaders have no dynamic flow control and very strict limits
|
||||
// on the number of constants, temporary registers and instructions.
|
||||
// Whether a shader meets the requirements will depend on how it's
|
||||
// compiled and optimized, but it's likely that only simple shaders will
|
||||
// work.
|
||||
// D3D_FEATURE_LEVEL_9_1:
|
||||
// - No high-bit-depth formats with PL_FMT_CAP_RENDERABLE or
|
||||
// PL_FMT_CAP_LINEAR
|
||||
//
|
||||
// If these restrictions are undesirable and you don't need to support
|
||||
// ancient hardware, set `min_feature_level` to D3D_FEATURE_LEVEL_10_0.
|
||||
int min_feature_level; // Defaults to D3D_FEATURE_LEVEL_9_1 if unset
|
||||
int max_feature_level; // Defaults to D3D_FEATURE_LEVEL_12_1 if unset
|
||||
|
||||
// Allow up to N in-flight frames. Similar to swapchain_depth for Vulkan and
|
||||
// OpenGL, though with DXGI this is a device-wide setting that affects all
|
||||
// swapchains (except for waitable swapchains.) See the documentation for
|
||||
// `pl_swapchain_latency` for more information.
|
||||
int max_frame_latency;
|
||||
};
|
||||
|
||||
// Default/recommended parameters. Should generally be safe and efficient.
|
||||
#define PL_D3D11_DEFAULTS \
|
||||
.allow_software = true,
|
||||
|
||||
#define pl_d3d11_params(...) (&(struct pl_d3d11_params) { PL_D3D11_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_d3d11_params pl_d3d11_default_params;
|
||||
|
||||
// Creates a new Direct3D 11 device based on the given parameters, or wraps an
|
||||
// existing device, and initializes a new GPU instance. If params is left as
|
||||
// NULL, it defaults to &pl_d3d11_default_params. If an existing device is
|
||||
// provided in params->device, `pl_d3d11_create` will take a reference to it
|
||||
// that will be released in `pl_d3d11_destroy`.
|
||||
PL_API pl_d3d11 pl_d3d11_create(pl_log log, const struct pl_d3d11_params *params);
|
||||
|
||||
// Release the D3D11 device.
|
||||
//
|
||||
// Note that all libplacebo objects allocated from this pl_d3d11 object (e.g.
|
||||
// via `d3d11->gpu` or using `pl_d3d11_create_swapchain`) *must* be explicitly
|
||||
// destroyed by the user before calling this.
|
||||
PL_API void pl_d3d11_destroy(pl_d3d11 *d3d11);
|
||||
|
||||
// For a `pl_gpu` backed by `pl_d3d11`, this function can be used to retrieve
|
||||
// the underlying `pl_d3d11`. Returns NULL for any other type of `gpu`.
|
||||
PL_API pl_d3d11 pl_d3d11_get(pl_gpu gpu);
|
||||
|
||||
struct pl_d3d11_swapchain_params {
|
||||
// The Direct3D 11 swapchain to wrap. Optional. If NULL, libplacebo will
|
||||
// create its own swapchain using the options below. If set, all the
|
||||
// swapchain creation options will be ignored.
|
||||
//
|
||||
// The provided swapchain must have been created by the same device used
|
||||
// by `gpu` and must not have multisampled backbuffers.
|
||||
IDXGISwapChain *swapchain;
|
||||
|
||||
// --- Swapchain creation options
|
||||
|
||||
// Initial framebuffer width and height. If both width and height are set to
|
||||
// 0 and window is non-NULL, the client area of the window is used instead.
|
||||
// For convenience, if either component would be 0, it is set to 1 instead.
|
||||
// This is because Windows can have 0-sized windows, but not 0-sized
|
||||
// swapchains.
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// The handle of the output window. In Windows 8 and up this is optional
|
||||
// because you can output to a CoreWindow or create a composition swapchain
|
||||
// instead.
|
||||
HWND window;
|
||||
|
||||
// A pointer to the CoreWindow to output to. If both this and `window` are
|
||||
// NULL, CreateSwapChainForComposition will be used to create the swapchain.
|
||||
IUnknown *core_window;
|
||||
|
||||
// If set, libplacebo will create a swapchain that uses the legacy bitblt
|
||||
// presentation model (with the DXGI_SWAP_EFFECT_DISCARD swap effect.) This
|
||||
// tends to give worse performance and frame pacing in windowed mode and it
|
||||
// prevents borderless fullscreen optimizations, but it might be necessary
|
||||
// to work around buggy drivers, especially with DXGI 1.2 in the Platform
|
||||
// Update for Windows 7. When unset, libplacebo will try to use the flip
|
||||
// presentation model and only fall back to bitblt if flip is unavailable.
|
||||
bool blit;
|
||||
|
||||
// additional swapchain flags
|
||||
// No validation on these flags is being performed, and swapchain creation
|
||||
// may fail if an unsupported combination is requested.
|
||||
UINT flags;
|
||||
|
||||
// --- Swapchain usage behavior options
|
||||
|
||||
// Disable using a 10-bit swapchain format for SDR output
|
||||
bool disable_10bit_sdr;
|
||||
};
|
||||
|
||||
#define pl_d3d11_swapchain_params(...) (&(struct pl_d3d11_swapchain_params) { __VA_ARGS__ })
|
||||
|
||||
// Creates a new Direct3D 11 swapchain, or wraps an existing one. If an existing
|
||||
// swapchain is provided in params->swapchain, `pl_d3d11_create_swapchain` will
|
||||
// take a reference to it that will be released in `pl_swapchain_destroy`.
|
||||
PL_API pl_swapchain pl_d3d11_create_swapchain(pl_d3d11 d3d11,
|
||||
const struct pl_d3d11_swapchain_params *params);
|
||||
|
||||
// Takes a `pl_swapchain` created by pl_d3d11_create_swapchain and returns a
|
||||
// reference to the underlying IDXGISwapChain. This increments the refcount, so
|
||||
// call IDXGISwapChain::Release when finished with it.
|
||||
PL_API IDXGISwapChain *pl_d3d11_swapchain_unwrap(pl_swapchain sw);
|
||||
|
||||
struct pl_d3d11_wrap_params {
|
||||
// The D3D11 texture to wrap, or a texture array containing the texture to
|
||||
// wrap. Must be a ID3D11Texture1D, ID3D11Texture2D or ID3D11Texture3D
|
||||
// created by the same device used by `gpu`, must have D3D11_USAGE_DEFAULT,
|
||||
// and must not be mipmapped or multisampled.
|
||||
ID3D11Resource *tex;
|
||||
|
||||
// If tex is a texture array, this is the array member to use as the pl_tex.
|
||||
int array_slice;
|
||||
|
||||
// If tex is a video resource (eg. DXGI_FORMAT_AYUV, DXGI_FORMAT_NV12,
|
||||
// DXGI_FORMAT_P010, etc.,) it can be wrapped as a pl_tex by specifying the
|
||||
// type and size of the shader view. For planar video formats, the plane
|
||||
// that is wrapped depends on the chosen format.
|
||||
//
|
||||
// If tex is not a video resource, these fields are unnecessary. The correct
|
||||
// format will be determined automatically. If tex is not 2D, these fields
|
||||
// are ignored.
|
||||
//
|
||||
// For a list of supported video formats and their corresponding view
|
||||
// formats and sizes, see:
|
||||
// https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#VideoViews
|
||||
DXGI_FORMAT fmt;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
#define pl_d3d11_wrap_params(...) (&(struct pl_d3d11_wrap_params) { __VA_ARGS__ })
|
||||
|
||||
// Wraps an external texture into a pl_tex abstraction. `pl_d3d11_wrap` takes a
|
||||
// reference to the texture, which is released when `pl_tex_destroy` is called.
|
||||
//
|
||||
// This function may fail due to incompatible formats, incompatible flags or
|
||||
// other reasons, in which case it will return NULL.
|
||||
PL_API pl_tex pl_d3d11_wrap(pl_gpu gpu, const struct pl_d3d11_wrap_params *params);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_D3D11_H_
|
||||
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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_DISPATCH_H_
|
||||
#define LIBPLACEBO_DISPATCH_H_
|
||||
|
||||
#include <libplacebo/shaders.h>
|
||||
#include <libplacebo/gpu.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Thread-safety: Safe
|
||||
typedef struct pl_dispatch_t *pl_dispatch;
|
||||
|
||||
// Creates a new shader dispatch object. This object provides a translation
|
||||
// layer between generated shaders (pl_shader) and the ra context such that it
|
||||
// can be used to execute shaders. This dispatch object will also provide
|
||||
// shader caching (for efficient re-use).
|
||||
PL_API pl_dispatch pl_dispatch_create(pl_log log, pl_gpu gpu);
|
||||
PL_API void pl_dispatch_destroy(pl_dispatch *dp);
|
||||
|
||||
// Reset/increments the internal counters of the pl_dispatch. This must be
|
||||
// called whenever the user is going to begin with a new frame, in order to
|
||||
// perform garbage collection and advance the state of the internal PRNG.
|
||||
//
|
||||
// Note that shaders generated by `pl_dispatch` are therefore entirely
|
||||
// deterministic, as long as the sequence of calls (and inputs to the shader)
|
||||
// are the same.
|
||||
PL_API void pl_dispatch_reset_frame(pl_dispatch dp);
|
||||
|
||||
// Returns a blank pl_shader object, suitable for recording rendering commands.
|
||||
// For more information, see the header documentation in `shaders/*.h`.
|
||||
PL_API pl_shader pl_dispatch_begin(pl_dispatch dp);
|
||||
|
||||
// Struct passed to `info_callback`. Only valid until that function returns.
|
||||
struct pl_dispatch_info {
|
||||
// Information about the shader for this shader execution, as well as a
|
||||
// 64-bit signature uniquely identifying it.
|
||||
pl_shader_info shader;
|
||||
uint64_t signature;
|
||||
|
||||
// A list of execution times for this pass, in nanoseconds. May be empty.
|
||||
uint64_t samples[256];
|
||||
int num_samples;
|
||||
|
||||
// As a convenience, this contains the last, average and peak of the above
|
||||
// list of samples. If `num_samples` is 0, these values are also 0.
|
||||
uint64_t last;
|
||||
uint64_t peak;
|
||||
uint64_t average;
|
||||
};
|
||||
|
||||
// Helper function to make a copy of `pl_dispatch_info`, while overriding
|
||||
// (and dereferencing) whatever was previously stored there.
|
||||
static inline void pl_dispatch_info_move(struct pl_dispatch_info *dst,
|
||||
const struct pl_dispatch_info *src)
|
||||
{
|
||||
pl_shader_info_deref(&dst->shader);
|
||||
*dst = *src;
|
||||
dst->shader = pl_shader_info_ref(src->shader);
|
||||
}
|
||||
|
||||
// Set up a dispatch callback for this `pl_dispatch` object. The given callback
|
||||
// will be run for every successfully dispatched shader. Call this again with
|
||||
// `cb == NULL` to disable.
|
||||
PL_API void pl_dispatch_callback(pl_dispatch dp, void *priv,
|
||||
void (*cb)(void *priv,
|
||||
const struct pl_dispatch_info *));
|
||||
|
||||
struct pl_dispatch_params {
|
||||
// The shader to execute. The pl_dispatch will take over ownership
|
||||
// of this shader, and return it back to the internal pool.
|
||||
//
|
||||
// This shader must have a compatible signature, i.e. inputs
|
||||
// `PL_SHADER_SIG_NONE` and outputs `PL_SHADER_SIG_COLOR`.
|
||||
pl_shader *shader;
|
||||
|
||||
// The texture to render to. This must have params compatible with the
|
||||
// shader, i.e. `target->params.renderable` for fragment shaders and
|
||||
// `target->params.storable` for compute shaders.
|
||||
//
|
||||
// Note: Even when not using compute shaders, users are advised to always
|
||||
// set `target->params.storable` if permitted by the `pl_fmt`, since this
|
||||
// allows the use of compute shaders instead of full-screen quads, which is
|
||||
// faster on some platforms.
|
||||
pl_tex target;
|
||||
|
||||
// The target rect to render to. Optional, if left as {0}, then the
|
||||
// entire texture will be rendered to.
|
||||
pl_rect2d rect;
|
||||
|
||||
// If set, enables and controls the blending for this pass. Optional. When
|
||||
// using this with fragment shaders, `target->params.fmt->caps` must
|
||||
// include `PL_FMT_CAP_BLENDABLE`.
|
||||
const struct pl_blend_params *blend_params;
|
||||
|
||||
// If set, records the execution time of this dispatch into the given
|
||||
// timer object. Optional.
|
||||
//
|
||||
// Note: If this is set, `pl_dispatch` cannot internally measure the
|
||||
// execution time of the shader, which means `pl_dispatch_info.samples` may
|
||||
// be empty as a result.
|
||||
pl_timer timer;
|
||||
};
|
||||
|
||||
#define pl_dispatch_params(...) (&(struct pl_dispatch_params) { __VA_ARGS__ })
|
||||
|
||||
// Dispatch a generated shader (via the pl_shader mechanism). Returns whether
|
||||
// or not the dispatch was successful.
|
||||
PL_API bool pl_dispatch_finish(pl_dispatch dp, const struct pl_dispatch_params *params);
|
||||
|
||||
struct pl_dispatch_compute_params {
|
||||
// The shader to execute. This must be a compute shader with the input
|
||||
// set to PL_SHADER_SIG_NONE. The output, if it has any, is ignored.
|
||||
pl_shader *shader;
|
||||
|
||||
// The number of work groups to dispatch in each dimension. If this is left
|
||||
// as [0} and `width/height` are both set, the number of work groups will
|
||||
// be inferred from the shader's `compute_group_sizes`.
|
||||
int dispatch_size[3];
|
||||
|
||||
// If set, simulate vertex attributes (similar to `pl_dispatch_finish`)
|
||||
// according to the given dimensions. The first two components of the
|
||||
// thread's global ID will be interpreted as the X and Y locations.
|
||||
//
|
||||
// Optional, ignored if either component is left as 0.
|
||||
int width, height;
|
||||
|
||||
// If set, records the execution time of this dispatch into the given
|
||||
// timer object. Optional.
|
||||
//
|
||||
// Note: If this is set, `pl_dispatch` cannot internally measure the
|
||||
// execution time of the shader, which means `pl_dispatch_info.samples` may
|
||||
// be empty as a result.
|
||||
pl_timer timer;
|
||||
};
|
||||
|
||||
#define pl_dispatch_compute_params(...) (&(struct pl_dispatch_compute_params) { __VA_ARGS__ })
|
||||
|
||||
// A variant of `pl_dispatch_finish`, this one only dispatches a compute shader
|
||||
// while ignoring its output (if it has one). It's only useful for shaders
|
||||
// which have otherwise observable side effects (such as updating state
|
||||
// objects).
|
||||
PL_API bool pl_dispatch_compute(pl_dispatch dp, const struct pl_dispatch_compute_params *params);
|
||||
|
||||
enum pl_vertex_coords {
|
||||
PL_COORDS_ABSOLUTE, // Absolute/integer `target` coordinates
|
||||
PL_COORDS_RELATIVE, // Relative `target` coordinates in range [0, 1]
|
||||
PL_COORDS_NORMALIZED, // GL-normalized coordinates in range [-1, 1]
|
||||
};
|
||||
|
||||
struct pl_dispatch_vertex_params {
|
||||
// The shader to execute. This must be a raster shader with the input set
|
||||
// to `PL_SHADER_SIG_NONE` and the output set to `PL_SHADER_SIG_COLOR`.
|
||||
//
|
||||
// Additionally, the shader must not have any attached vertex attributes.
|
||||
pl_shader *shader;
|
||||
|
||||
// The texture to render to. Requires `target->params.renderable`.
|
||||
pl_tex target;
|
||||
|
||||
// The target rect to clip the rendering to. (Optional)
|
||||
pl_rect2d scissors;
|
||||
|
||||
// If set, enables and controls the blending for this pass. Optional. When
|
||||
// enabled, `target->params.fmt->caps` must include `PL_FMT_CAP_BLENDABLE`.
|
||||
const struct pl_blend_params *blend_params;
|
||||
|
||||
// The description of the vertex format, including offsets.
|
||||
//
|
||||
// Note: `location` is ignored and can safely be left unset.
|
||||
const struct pl_vertex_attrib *vertex_attribs;
|
||||
int num_vertex_attribs;
|
||||
size_t vertex_stride;
|
||||
|
||||
// The index of the vertex position in `vertex_attribs`, as well as the
|
||||
// interpretation of its contents.
|
||||
int vertex_position_idx;
|
||||
enum pl_vertex_coords vertex_coords;
|
||||
bool vertex_flipped; // flip all vertex y coordinates
|
||||
|
||||
// Type and number of vertices to render.
|
||||
enum pl_prim_type vertex_type;
|
||||
int vertex_count;
|
||||
|
||||
// Vertex data. See `pl_pass_run_params.vertex_data`.
|
||||
const void *vertex_data;
|
||||
pl_buf vertex_buf;
|
||||
size_t buf_offset;
|
||||
|
||||
// Index data. See `pl_pass_run_params.index_data`. Optional.
|
||||
const void *index_data;
|
||||
enum pl_index_format index_fmt;
|
||||
pl_buf index_buf;
|
||||
size_t index_offset;
|
||||
|
||||
// If set, records the execution time of this dispatch into the given
|
||||
// timer object. Optional.
|
||||
//
|
||||
// Note: If this is set, `pl_dispatch` cannot internally measure the
|
||||
// execution time of the shader, which means `pl_dispatch_info.samples` may
|
||||
// be empty as a result.
|
||||
pl_timer timer;
|
||||
};
|
||||
|
||||
#define pl_dispatch_vertex_params(...) (&(struct pl_dispatch_vertex_params) { __VA_ARGS__ })
|
||||
|
||||
// Dispatch a generated shader using custom vertices, rather than using a quad
|
||||
// generated by the dispatch. This allows the use of e.g. custom fragment
|
||||
// shaders for things like rendering custom UI elements, or possibly doing
|
||||
// advanced things like sampling from a cube map or spherical video.
|
||||
PL_API bool pl_dispatch_vertex(pl_dispatch dp, const struct pl_dispatch_vertex_params *params);
|
||||
|
||||
// Cancel an active shader without submitting anything. Useful, for example,
|
||||
// if the shader was instead merged into a different shader.
|
||||
PL_API void pl_dispatch_abort(pl_dispatch dp, pl_shader *sh);
|
||||
|
||||
// Deprecated in favor of `pl_cache_save/pl_cache_load` on the `pl_cache`
|
||||
// associated with the `pl_gpu` this dispatch is using.
|
||||
PL_DEPRECATED PL_API size_t pl_dispatch_save(pl_dispatch dp, uint8_t *out_cache);
|
||||
PL_DEPRECATED PL_API void pl_dispatch_load(pl_dispatch dp, const uint8_t *cache);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_DISPATCH_H
|
||||
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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_DITHER_H_
|
||||
#define LIBPLACEBO_DITHER_H_
|
||||
|
||||
#include <libplacebo/common.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Generates a deterministic NxN bayer (ordered) dither matrix, storing the
|
||||
// result in `data`. `size` must be a power of two. The resulting matrix will
|
||||
// be roughly uniformly distributed within the range [0,1).
|
||||
PL_API void pl_generate_bayer_matrix(float *data, int size);
|
||||
|
||||
// Generates a random NxN blue noise texture. storing the result in `data`.
|
||||
// `size` must be a positive power of two no larger than 256. The resulting
|
||||
// texture will be roughly uniformly distributed within the range [0,1).
|
||||
//
|
||||
// Note: This function is very, *very* slow for large sizes. Generating a
|
||||
// dither matrix with size 256 can take several seconds on a modern processor.
|
||||
PL_API void pl_generate_blue_noise(float *data, int size);
|
||||
|
||||
// Defines the border of all error diffusion kernels
|
||||
#define PL_EDF_MIN_DX (-2)
|
||||
#define PL_EDF_MAX_DX (2)
|
||||
#define PL_EDF_MAX_DY (2)
|
||||
|
||||
struct pl_error_diffusion_kernel {
|
||||
const char *name; // Short and concise identifier
|
||||
const char *description; // Longer / friendly name
|
||||
|
||||
// The minimum value such that a (y, x) -> (y, x + y * shift) mapping will
|
||||
// make all error pushing operations affect next column (and after it)
|
||||
// only.
|
||||
//
|
||||
// Higher shift values are significantly more computationally intensive.
|
||||
int shift;
|
||||
|
||||
// The diffusion factor for (y, x) is pattern[y][x - PL_EDF_MIN_DX] / divisor.
|
||||
int pattern[PL_EDF_MAX_DY + 1][PL_EDF_MAX_DX - PL_EDF_MIN_DX + 1];
|
||||
int divisor;
|
||||
};
|
||||
|
||||
// Algorithms with shift=1:
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_simple;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_false_fs;
|
||||
// Algorithms with shift=2:
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_sierra_lite;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_floyd_steinberg;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_atkinson;
|
||||
// Algorithms with shift=3, probably too heavy for low end GPUs:
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_jarvis_judice_ninke;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_stucki;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_burkes;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_sierra2;
|
||||
PL_API extern const struct pl_error_diffusion_kernel pl_error_diffusion_sierra3;
|
||||
|
||||
// A list of built-in error diffusion kernels, terminated by NULL
|
||||
PL_API extern const struct pl_error_diffusion_kernel * const pl_error_diffusion_kernels[];
|
||||
PL_API extern const int pl_num_error_diffusion_kernels; // excluding trailing NULL
|
||||
|
||||
// Find the error diffusion kernel with the given name, or NULL on failure.
|
||||
PL_API const struct pl_error_diffusion_kernel *pl_find_error_diffusion_kernel(const char *name);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_DITHER_H_
|
||||
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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_DUMMY_H_
|
||||
#define LIBPLACEBO_DUMMY_H_
|
||||
|
||||
#include <libplacebo/gpu.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// The functions in this file allow creating and manipulating "dummy" contexts.
|
||||
// A dummy context isn't actually mapped by the GPU, all data exists purely on
|
||||
// the CPU. It also isn't capable of compiling or executing any shaders, any
|
||||
// attempts to do so will simply fail.
|
||||
//
|
||||
// The main use case for this dummy context is for users who want to generate
|
||||
// advanced shaders that depend on specific GLSL features or support for
|
||||
// certain types of GPU resources (e.g. LUTs). This dummy context allows such
|
||||
// shaders to be generated, with all of the referenced shader objects and
|
||||
// textures simply containing their data in a host-accessible way.
|
||||
|
||||
struct pl_gpu_dummy_params {
|
||||
// These GPU parameters correspond to their equivalents in `pl_gpu`, and
|
||||
// must obey the same rules as documented there. The values from
|
||||
// `pl_gpu_dummy_default_params` are set to support pretty much everything
|
||||
// and are set for GLSL version 450.
|
||||
//
|
||||
// Individual fields such as `glsl.compute` or `glsl.version` description
|
||||
// can and should be overridden by the user based on their requirements.
|
||||
// Individual limits should ideally be set based on the corresponding
|
||||
// `glGet` queries etc.
|
||||
struct pl_glsl_version glsl;
|
||||
struct pl_gpu_limits limits;
|
||||
};
|
||||
|
||||
#define PL_GPU_DUMMY_DEFAULTS \
|
||||
.glsl = { \
|
||||
.version = 450, \
|
||||
.gles = false, \
|
||||
.vulkan = false, \
|
||||
.compute = true, \
|
||||
.max_shmem_size = SIZE_MAX, \
|
||||
.max_group_threads = 1024, \
|
||||
.max_group_size = { 1024, 1024, 1024 }, \
|
||||
.subgroup_size = 32, \
|
||||
.min_gather_offset = INT16_MIN, \
|
||||
.max_gather_offset = INT16_MAX, \
|
||||
}, \
|
||||
.limits = { \
|
||||
/* pl_gpu */ \
|
||||
.callbacks = false, \
|
||||
.thread_safe = true, \
|
||||
/* pl_buf */ \
|
||||
.max_buf_size = SIZE_MAX, \
|
||||
.max_ubo_size = SIZE_MAX, \
|
||||
.max_ssbo_size = SIZE_MAX, \
|
||||
.max_vbo_size = SIZE_MAX, \
|
||||
.max_mapped_size = SIZE_MAX, \
|
||||
.max_buffer_texels = UINT64_MAX, \
|
||||
/* pl_tex */ \
|
||||
.max_tex_1d_dim = UINT32_MAX, \
|
||||
.max_tex_2d_dim = UINT32_MAX, \
|
||||
.max_tex_3d_dim = UINT32_MAX, \
|
||||
.buf_transfer = true, \
|
||||
.align_tex_xfer_pitch = 1, \
|
||||
.align_tex_xfer_offset = 1, \
|
||||
/* pl_pass */ \
|
||||
.max_variable_comps = SIZE_MAX, \
|
||||
.max_constants = SIZE_MAX, \
|
||||
.max_pushc_size = SIZE_MAX, \
|
||||
.max_dispatch = { UINT32_MAX, UINT32_MAX, UINT32_MAX }, \
|
||||
.fragment_queues = 0, \
|
||||
.compute_queues = 0, \
|
||||
},
|
||||
|
||||
#define pl_gpu_dummy_params(...) (&(struct pl_gpu_dummy_params) { PL_GPU_DUMMY_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_gpu_dummy_params pl_gpu_dummy_default_params;
|
||||
|
||||
// Create a dummy GPU context based on the given parameters. This GPU will have
|
||||
// a format for each host-representable type (i.e. intN_t, floats and doubles),
|
||||
// in the canonical channel order RGBA. These formats will have every possible
|
||||
// capability activated, respectively.
|
||||
//
|
||||
// If `params` is left as NULL, it defaults to `&pl_gpu_dummy_params`.
|
||||
PL_API pl_gpu pl_gpu_dummy_create(pl_log log, const struct pl_gpu_dummy_params *params);
|
||||
PL_API void pl_gpu_dummy_destroy(pl_gpu *gpu);
|
||||
|
||||
// Back-doors into the `pl_tex` and `pl_buf` representations. These allow you
|
||||
// to access the raw data backing this object. Textures are always laid out in
|
||||
// a tightly packed manner.
|
||||
//
|
||||
// For "placeholder" dummy textures, this always returns NULL.
|
||||
PL_API uint8_t *pl_buf_dummy_data(pl_buf buf);
|
||||
PL_API uint8_t *pl_tex_dummy_data(pl_tex tex);
|
||||
|
||||
// Skeleton of `pl_tex_params` containing only the fields relevant to
|
||||
// `pl_tex_dummy_create`, plus the extra `sampler_type` field.
|
||||
struct pl_tex_dummy_params {
|
||||
int w, h, d;
|
||||
pl_fmt format;
|
||||
enum pl_sampler_type sampler_type;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#define pl_tex_dummy_params(...) (&(struct pl_tex_dummy_params) { __VA_ARGS__ })
|
||||
|
||||
// Allows creating a "placeholder" dummy texture. This is basically a texture
|
||||
// that isn't even backed by anything. All `pl_tex_*` operations (other than
|
||||
// `pl_tex_destroy`) performed on it will simply fail.
|
||||
//
|
||||
// All of the permissions will be set to `false`, except `sampleable`, which is
|
||||
// set to `true`. (So you can use it as an input to shader sampling functions)
|
||||
PL_API pl_tex pl_tex_dummy_create(pl_gpu gpu, const struct pl_tex_dummy_params *params);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_DUMMY_H_
|
||||
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* 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_FILTER_KERNELS_H_
|
||||
#define LIBPLACEBO_FILTER_KERNELS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <libplacebo/log.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
#define PL_FILTER_MAX_PARAMS 2
|
||||
|
||||
// Invocation parameters for a given kernel
|
||||
struct pl_filter_ctx {
|
||||
float radius;
|
||||
float params[PL_FILTER_MAX_PARAMS];
|
||||
};
|
||||
|
||||
// Represents a single filter function, i.e. kernel or windowing function.
|
||||
struct pl_filter_function {
|
||||
// The cosmetic name associated with this filter function.
|
||||
const char *name;
|
||||
|
||||
// The radius of the filter function. For resizable filters, this gives
|
||||
// the radius needed to represent a single filter lobe (tap).
|
||||
float radius;
|
||||
|
||||
// If true, the filter function is resizable (see pl_filter_config.radius)
|
||||
bool resizable;
|
||||
|
||||
// If true, the filter function is tunable (see pl_filter_config.params)
|
||||
bool tunable[PL_FILTER_MAX_PARAMS];
|
||||
|
||||
// If the relevant parameter is tunable, this contains the default values.
|
||||
float params[PL_FILTER_MAX_PARAMS];
|
||||
|
||||
// The underlying filter function itself: Computes the weight as a function
|
||||
// of the offset. All filter functions must be normalized such that x=0 is
|
||||
// the center point, and in particular weight(0) = 1.0. The functions may
|
||||
// be undefined for values of x outside [0, radius].
|
||||
double (*weight)(const struct pl_filter_ctx *f, double x);
|
||||
|
||||
// If true, this filter represents an opaque placeholder for a more
|
||||
// sophisticated filter function which does not fit into the pl_filter
|
||||
// framework. `weight()` will always return 0.0.
|
||||
bool opaque;
|
||||
};
|
||||
|
||||
// Deprecated function, merely checks a->weight == b->weight
|
||||
PL_DEPRECATED PL_API bool
|
||||
pl_filter_function_eq(const struct pl_filter_function *a,
|
||||
const struct pl_filter_function *b);
|
||||
|
||||
// Box filter: Entirely 1.0 within the radius, entirely 0.0 outside of it.
|
||||
// This is also sometimes called a Dirichlet window
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_box;
|
||||
|
||||
// Triangle filter: Linear transitions from 1.0 at x=0 to 0.0 at x=radius.
|
||||
// This is also sometimes called a Bartlett window.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_triangle;
|
||||
|
||||
// Cosine filter: Ordinary cosine function, single lobe.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_cosine;
|
||||
|
||||
// Hann function: Cosine filter named after Julius von Hann. Also commonly
|
||||
// mislabeled as a "Hanning" function, due to its similarly to the Hamming
|
||||
// function.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_hann;
|
||||
|
||||
// Hamming function: Cosine filter named after Richard Hamming.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_hamming;
|
||||
|
||||
// Welch filter: Polynomial function consisting of a single parabolic section.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_welch;
|
||||
|
||||
// Kaiser filter: Approximation of the DPSS window using Bessel functions.
|
||||
// Also sometimes called a Kaiser-Bessel window.
|
||||
// Parameter [0]: Shape (alpha). Determines the trade-off between the main lobe
|
||||
// and the side lobes.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_kaiser;
|
||||
|
||||
// Blackman filter: Cosine filter named after Ralph Beebe Blackman.
|
||||
// Parameter [0]: Scale (alpha). Influences the shape. The defaults result in
|
||||
// zeros at the third and fourth sidelobes.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_blackman;
|
||||
|
||||
// Bohman filter: 2nd order Cosine filter.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_bohman;
|
||||
|
||||
// Gaussian function: Similar to the Gaussian distribution, this defines a
|
||||
// bell curve function.
|
||||
// Parameter [0]: Scale (t), increasing makes the result blurrier.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_gaussian;
|
||||
|
||||
// Quadratic function: 2nd order approximation of the gaussian function. Also
|
||||
// sometimes called a "quadric" window.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_quadratic;
|
||||
|
||||
// Sinc function: Widely used for both kernels and windows, sinc(x) = sin(x)/x.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_sinc;
|
||||
|
||||
// Jinc function: Similar to sinc, but extended to the 2D domain. Widely
|
||||
// used as the kernel of polar (EWA) filters. Also sometimes called a Sombrero
|
||||
// function.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_jinc;
|
||||
|
||||
// Sphinx function: Similar to sinc and jinx, but extended to the 3D domain.
|
||||
// The name is derived from "spherical" sinc. Can be used to filter 3D signals
|
||||
// in theory.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_sphinx;
|
||||
|
||||
// B/C-tunable Spline function: This is a family of commonly used spline
|
||||
// functions with two tunable parameters. Does not need to be windowed.
|
||||
// Parameter [0]: "B"
|
||||
// Parameter [1]: "C"
|
||||
// Some popular variants of this function are:
|
||||
// B = 1.0, C = 0.0: "base" Cubic (blurry)
|
||||
// B = 0.0, C = 0.0: Hermite filter (blocky)
|
||||
// B = 0.0, C = 0.5: Catmull-Rom filter (sharp)
|
||||
// B = 1/3, C = 1/3: Mitchell-Netravali filter (soft, doesn't ring)
|
||||
// B ≈ 0.37, C ≈ 0.31: Robidoux filter (used by ImageMagick)
|
||||
// B ≈ 0.26, C ≈ 0.37: RobidouxSharp filter (sharper variant of Robidoux)
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_cubic;
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_hermite;
|
||||
#define pl_filter_function_bicubic pl_filter_function_cubic
|
||||
#define pl_filter_function_bcspline pl_filter_function_cubic
|
||||
|
||||
// Cubic splines with 2/3/4 taps. Referred to as "spline16", "spline36", and
|
||||
// "spline64" mainly for historical reasons, based on the number of pixels in
|
||||
// their window when using them as 2D orthogonal filters. Do not need to be
|
||||
// windowed.
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_spline16;
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_spline36;
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_spline64;
|
||||
|
||||
// Special filter function for the built-in oversampling algorithm. This is an
|
||||
// opaque filter with no meaningful representation. though it has one tunable
|
||||
// parameter controlling the threshold at which to switch back to ordinary
|
||||
// nearest neighbour sampling. (See `pl_shader_sample_oversample`)
|
||||
PL_API extern const struct pl_filter_function pl_filter_function_oversample;
|
||||
|
||||
// A list of built-in filter functions, terminated by NULL
|
||||
//
|
||||
// Note: May contain extra aliases for the above functions.
|
||||
PL_API extern const struct pl_filter_function * const pl_filter_functions[];
|
||||
PL_API extern const int pl_num_filter_functions; // excluding trailing NULL
|
||||
|
||||
// Find the filter function with the given name, or NULL on failure.
|
||||
PL_API const struct pl_filter_function *pl_find_filter_function(const char *name);
|
||||
|
||||
// Backwards compatibility with the older configuration API. Redundant with
|
||||
// `pl_filter_function.name`. May be formally deprecated in the future.
|
||||
|
||||
struct pl_filter_function_preset {
|
||||
const char *name;
|
||||
const struct pl_filter_function *function;
|
||||
};
|
||||
|
||||
// A list of built-in filter function presets, terminated by {0}
|
||||
PL_API extern const struct pl_filter_function_preset pl_filter_function_presets[];
|
||||
PL_API extern const int pl_num_filter_function_presets; // excluding trailing {0}
|
||||
|
||||
// Find the filter function preset with the given name, or NULL on failure.
|
||||
PL_API const struct pl_filter_function_preset *pl_find_filter_function_preset(const char *name);
|
||||
|
||||
// Different usage domains for a filter
|
||||
enum pl_filter_usage {
|
||||
PL_FILTER_UPSCALING = (1 << 0),
|
||||
PL_FILTER_DOWNSCALING = (1 << 1),
|
||||
PL_FILTER_FRAME_MIXING = (1 << 2),
|
||||
|
||||
PL_FILTER_SCALING = PL_FILTER_UPSCALING | PL_FILTER_DOWNSCALING,
|
||||
PL_FILTER_ALL = PL_FILTER_SCALING | PL_FILTER_FRAME_MIXING,
|
||||
};
|
||||
|
||||
// Represents a tuned combination of filter functions, plus parameters
|
||||
struct pl_filter_config {
|
||||
// The cosmetic name associated with this filter config. Optional for
|
||||
// user-provided configs, but always set by built-in configurations.
|
||||
const char *name;
|
||||
|
||||
// Longer / friendly name. Always set for built-in configurations,
|
||||
// except for names which are merely aliases of other filters.
|
||||
const char *description;
|
||||
|
||||
// Allowed and recommended usage domains (respectively)
|
||||
//
|
||||
// When it is desired to maintain a simpler user interface, it may be
|
||||
// recommended to include only scalers whose recommended usage domains
|
||||
// includes the relevant context in which it will be used.
|
||||
enum pl_filter_usage allowed;
|
||||
enum pl_filter_usage recommended;
|
||||
|
||||
// The kernel function and (optionally) windowing function.
|
||||
const struct pl_filter_function *kernel;
|
||||
const struct pl_filter_function *window;
|
||||
|
||||
// The radius. Ignored if !kernel->resizable. Optional, defaults to
|
||||
// kernel->radius if unset.
|
||||
float radius;
|
||||
|
||||
// Parameters for the respective filter function. Ignored if not tunable.
|
||||
float params[PL_FILTER_MAX_PARAMS];
|
||||
float wparams[PL_FILTER_MAX_PARAMS];
|
||||
|
||||
// Represents a clamping coefficient for negative weights. A value of 0.0
|
||||
// (the default) represents no clamping. A value of 1.0 represents full
|
||||
// clamping, i.e. all negative weights will be clamped to 0. Values in
|
||||
// between will be linearly scaled.
|
||||
float clamp;
|
||||
|
||||
// Additional blur coefficient. This effectively stretches the kernel,
|
||||
// without changing the effective radius of the filter radius. Setting this
|
||||
// to a value of 0.0 is equivalent to disabling it. Values significantly
|
||||
// below 1.0 may seriously degrade the visual output, and should be used
|
||||
// with care.
|
||||
float blur;
|
||||
|
||||
// Additional taper coefficient. This essentially flattens the function's
|
||||
// center. The values within [-taper, taper] will return 1.0, with the
|
||||
// actual function being squished into the remainder of [taper, radius].
|
||||
// Defaults to 0.0.
|
||||
float taper;
|
||||
|
||||
// If true, this filter is intended to be used as a polar/2D filter (EWA)
|
||||
// instead of a separable/1D filter. Does not affect the actual sampling,
|
||||
// but provides information about how the results are to be interpreted.
|
||||
bool polar;
|
||||
|
||||
// Antiringing strength. A value of 0.0 disables antiringing, and a value
|
||||
// of 1.0 enables full-strength antiringing. Defaults to 0.0 if
|
||||
// unspecified.
|
||||
//
|
||||
// Note: This is only included in `pl_filter_config` for convenience. Does
|
||||
// not affect the actual filter sampling, but provides information to the
|
||||
// downstream consumer of the `pl_filter`.
|
||||
float antiring;
|
||||
};
|
||||
|
||||
PL_API bool pl_filter_config_eq(const struct pl_filter_config *a,
|
||||
const struct pl_filter_config *b);
|
||||
|
||||
// Samples a given filter configuration at a given x coordinate, while
|
||||
// respecting all parameters of the configuration.
|
||||
PL_API double pl_filter_sample(const struct pl_filter_config *c, double x);
|
||||
|
||||
// A list of built-in filter configurations. Since they are just combinations
|
||||
// of the above filter functions, they are not described in much further
|
||||
// detail.
|
||||
PL_API extern const struct pl_filter_config pl_filter_spline16; // 2 taps
|
||||
PL_API extern const struct pl_filter_config pl_filter_spline36; // 3 taps
|
||||
PL_API extern const struct pl_filter_config pl_filter_spline64; // 4 taps
|
||||
PL_API extern const struct pl_filter_config pl_filter_nearest;
|
||||
PL_API extern const struct pl_filter_config pl_filter_box;
|
||||
PL_API extern const struct pl_filter_config pl_filter_bilinear;
|
||||
PL_API extern const struct pl_filter_config pl_filter_gaussian;
|
||||
// Sinc family (all configured to 3 taps):
|
||||
PL_API extern const struct pl_filter_config pl_filter_sinc; // unwindowed
|
||||
PL_API extern const struct pl_filter_config pl_filter_lanczos; // sinc-sinc
|
||||
PL_API extern const struct pl_filter_config pl_filter_ginseng; // sinc-jinc
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_jinc; // unwindowed
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_lanczos; // jinc-jinc
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_lanczossharp;
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_lanczos4sharpest;
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_ginseng; // jinc-sinc
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_hann; // jinc-hann
|
||||
// Spline family
|
||||
PL_API extern const struct pl_filter_config pl_filter_bicubic;
|
||||
PL_API extern const struct pl_filter_config pl_filter_hermite;
|
||||
PL_API extern const struct pl_filter_config pl_filter_catmull_rom;
|
||||
PL_API extern const struct pl_filter_config pl_filter_mitchell;
|
||||
PL_API extern const struct pl_filter_config pl_filter_mitchell_clamp; // clamp = 1.0
|
||||
PL_API extern const struct pl_filter_config pl_filter_robidoux;
|
||||
PL_API extern const struct pl_filter_config pl_filter_robidouxsharp;
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_robidoux;
|
||||
PL_API extern const struct pl_filter_config pl_filter_ewa_robidouxsharp;
|
||||
// Special/opaque filters
|
||||
PL_API extern const struct pl_filter_config pl_filter_oversample;
|
||||
|
||||
// Backwards compatibility
|
||||
#define pl_filter_triangle pl_filter_bilinear
|
||||
#define pl_oversample_frame_mixer pl_filter_oversample
|
||||
|
||||
// A list of built-in filter configs, terminated by NULL
|
||||
PL_API extern const struct pl_filter_config * const pl_filter_configs[];
|
||||
PL_API extern const int pl_num_filter_configs; // excluding trailing NULL
|
||||
|
||||
// Find the filter config with the given name, or NULL on failure.
|
||||
// `usage` restricts the valid usage (based on `pl_filter_config.allowed`).
|
||||
PL_API const struct pl_filter_config *
|
||||
pl_find_filter_config(const char *name, enum pl_filter_usage usage);
|
||||
|
||||
// Backward compatibility with the previous filter configuration API. Redundant
|
||||
// with pl_filter_config.name/description. May be deprecated in the future.
|
||||
struct pl_filter_preset {
|
||||
const char *name;
|
||||
const struct pl_filter_config *filter;
|
||||
|
||||
// Longer / friendly name, or NULL for aliases
|
||||
const char *description;
|
||||
};
|
||||
|
||||
// A list of built-in filter presets, terminated by {0}
|
||||
PL_API extern const struct pl_filter_preset pl_filter_presets[];
|
||||
PL_API extern const int pl_num_filter_presets; // excluding trailing {0}
|
||||
|
||||
// Find the filter preset with the given name, or NULL on failure.
|
||||
PL_API const struct pl_filter_preset *pl_find_filter_preset(const char *name);
|
||||
|
||||
// Parameters for filter generation.
|
||||
struct pl_filter_params {
|
||||
// The particular filter configuration to be sampled. config.kernel must
|
||||
// be set to a valid pl_filter_function.
|
||||
struct pl_filter_config config;
|
||||
|
||||
// The precision of the resulting LUT. A value of 64 should be fine for
|
||||
// most practical purposes, but higher or lower values may be justified
|
||||
// depending on the use case. This value must be set to something > 0.
|
||||
int lut_entries;
|
||||
|
||||
// --- Polar filers only (config.polar)
|
||||
|
||||
// As a micro-optimization, all samples below this cutoff value will be
|
||||
// ignored when updating the cutoff radius. Setting it to a value of 0.0
|
||||
// disables this optimization.
|
||||
float cutoff;
|
||||
|
||||
// --- Separable filters only (!config.polar)
|
||||
|
||||
// Indicates the maximum row size that is supported by the calling code, or
|
||||
// 0 for no limit.
|
||||
int max_row_size;
|
||||
|
||||
// Indicates the row stride alignment. For some use cases (e.g. uploading
|
||||
// the weights as a texture), there are certain alignment requirements for
|
||||
// each row. The chosen row_size will always be a multiple of this value.
|
||||
// Specifying 0 indicates no alignment requirements.
|
||||
int row_stride_align;
|
||||
|
||||
// --- Deprecated options
|
||||
float filter_scale PL_DEPRECATED; // no effect, use `config.blur` instead
|
||||
};
|
||||
|
||||
#define pl_filter_params(...) (&(struct pl_filter_params) { __VA_ARGS__ })
|
||||
|
||||
// Represents an initialized instance of a particular filter, with a
|
||||
// precomputed LUT. The interpretation of the LUT depends on the type of the
|
||||
// filter (polar or separable).
|
||||
typedef const struct pl_filter_t {
|
||||
// Deep copy of the parameters, for convenience.
|
||||
struct pl_filter_params params;
|
||||
|
||||
// Contains the true radius of the computed filter. This may be
|
||||
// smaller than the configured radius depending on the exact filter
|
||||
// parameters used. Mainly relevant for polar filters, since
|
||||
// it affects the value range of *weights.
|
||||
float radius;
|
||||
|
||||
// Radius of the first zero crossing (main lobe size).
|
||||
float radius_zero;
|
||||
|
||||
// The computed look-up table (LUT). For polar filters, this is interpreted
|
||||
// as a 1D array with dimensions [lut_entries] containing the raw filter
|
||||
// samples on the scale [0, radius]. For separable (non-polar) filters,
|
||||
// this is interpreted as a 2D array with dimensions
|
||||
// [lut_entries][row_stride]. The inner rows contain the `row_size` samples
|
||||
// to convolve with the corresponding input pixels. The outer coordinate is
|
||||
// used to very the fractional offset (phase). So for example, if the
|
||||
// sample position to reconstruct is directly aligned with the source
|
||||
// texels, you would use the values from weights[0]. If the sample position
|
||||
// to reconstruct is exactly half-way between two source texels (180° out
|
||||
// of phase), you would use the values from weights[lut_entries/2].
|
||||
const float *weights;
|
||||
|
||||
// --- separable filters only (!params.config.polar)
|
||||
|
||||
// The number of source texels to convolve over for each row. This value
|
||||
// will never exceed the given `max_row_size`. If the filter ends up
|
||||
// cut off because of this, the bool `insufficient` will be set to true.
|
||||
int row_size;
|
||||
bool insufficient;
|
||||
|
||||
// The separation (in *weights) between each row of the filter. Always
|
||||
// a multiple of params.row_stride_align.
|
||||
int row_stride;
|
||||
|
||||
// --- deprecated / removed fields
|
||||
float radius_cutoff PL_DEPRECATED; // identical to `radius`
|
||||
} *pl_filter;
|
||||
|
||||
// Generate (compute) a filter instance based on a given filter configuration.
|
||||
// The resulting pl_filter must be freed with `pl_filter_free` when no longer
|
||||
// needed. Returns NULL if filter generation fails due to invalid parameters
|
||||
// (i.e. missing a required parameter).
|
||||
PL_API pl_filter pl_filter_generate(pl_log log, const struct pl_filter_params *params);
|
||||
PL_API void pl_filter_free(pl_filter *filter);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_FILTER_KERNELS_H_
|
||||
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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_GAMUT_MAPPING_H_
|
||||
#define LIBPLACEBO_GAMUT_MAPPING_H_
|
||||
|
||||
#include <libplacebo/common.h>
|
||||
#include <libplacebo/colorspace.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
struct pl_gamut_map_params;
|
||||
struct pl_gamut_map_function {
|
||||
const char *name; // Identifier
|
||||
const char *description; // Friendly / longer name
|
||||
|
||||
// The gamut-mapping function itself. Iterates over all values in `lut`,
|
||||
// and adapts them as needed.
|
||||
void (*map)(float *lut, const struct pl_gamut_map_params *params);
|
||||
|
||||
// Returns true if `map` supports both stretching and contracting the
|
||||
// gamut. In this case, `map` is always executed, even if the output gamut
|
||||
// is larger than the input gamut.
|
||||
bool bidirectional;
|
||||
|
||||
// Private data. Unused by libplacebo, but may be accessed by `map`.
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct pl_gamut_map_constants {
|
||||
// (Relative) chromaticity protection zone for perceptual mapping [0,1]
|
||||
float perceptual_deadzone;
|
||||
|
||||
// Strength of the perceptual saturation mapping component [0,1]
|
||||
float perceptual_strength;
|
||||
|
||||
// I vs C curve gamma to use for colorimetric clipping [0,10]
|
||||
float colorimetric_gamma;
|
||||
|
||||
// Knee point to use for softclipping methods (perceptual, softclip) [0,1]
|
||||
float softclip_knee;
|
||||
|
||||
// Desaturation strength (for softclip only) [0,1]
|
||||
float softclip_desat;
|
||||
};
|
||||
|
||||
#define PL_GAMUT_MAP_CONSTANTS \
|
||||
.colorimetric_gamma = 1.80f, \
|
||||
.softclip_knee = 0.70f, \
|
||||
.softclip_desat = 0.35f, \
|
||||
.perceptual_deadzone = 0.30f, \
|
||||
.perceptual_strength = 0.80f,
|
||||
|
||||
struct pl_gamut_map_params {
|
||||
// If `function` is NULL, defaults to `pl_gamut_map_clip`.
|
||||
const struct pl_gamut_map_function *function;
|
||||
|
||||
// The desired input/output primaries. This affects the subjective color
|
||||
// volume in which the desired mapping shall take place.
|
||||
struct pl_raw_primaries input_gamut;
|
||||
struct pl_raw_primaries output_gamut;
|
||||
|
||||
// Minimum/maximum luminance (PQ) of the target display. Note that the same
|
||||
// value applies to both the input and output, since it's assumed that tone
|
||||
// mapping has already happened by this stage. This effectively defines the
|
||||
// legal gamut boundary in RGB space.
|
||||
//
|
||||
// This also defines the I channel value range, for `pl_gamut_map_generate`
|
||||
float min_luma;
|
||||
float max_luma;
|
||||
|
||||
// Common constants, should be initialized to PL_GAMUT_MAP_CONSTANTS if
|
||||
// not intending to override them further.
|
||||
struct pl_gamut_map_constants constants;
|
||||
|
||||
// -- LUT generation options (for `pl_gamut_map_generate` only)
|
||||
|
||||
// The size of the resulting LUT, per channel.
|
||||
//
|
||||
// Note: For quality, it's generally best to increase h > I > C
|
||||
int lut_size_I;
|
||||
int lut_size_C;
|
||||
int lut_size_h;
|
||||
|
||||
// The stride (in number of floats) between elements in the resulting LUT.
|
||||
int lut_stride;
|
||||
|
||||
// -- Removed parameters
|
||||
float chroma_margin PL_DEPRECATED; // non-functional
|
||||
};
|
||||
|
||||
#define pl_gamut_map_params(...) (&(struct pl_gamut_map_params) { \
|
||||
.constants = { PL_GAMUT_MAP_CONSTANTS }, \
|
||||
__VA_ARGS__ \
|
||||
})
|
||||
|
||||
// Note: Only does pointer equality testing on `function`
|
||||
PL_API bool pl_gamut_map_params_equal(const struct pl_gamut_map_params *a,
|
||||
const struct pl_gamut_map_params *b);
|
||||
|
||||
// Returns true if the given gamut mapping configuration effectively represents
|
||||
// a no-op configuration. Gamut mapping can be skipped in this case.
|
||||
PL_API bool pl_gamut_map_params_noop(const struct pl_gamut_map_params *params);
|
||||
|
||||
// Generate a gamut-mapping LUT for a given configuration. LUT samples are
|
||||
// stored as IPTPQc4 values, but the LUT itself is indexed by IChPQc4,spanning
|
||||
// the effective range [min_luma, max_luma] × [0, 0.5] × [-pi,pi].
|
||||
//
|
||||
// This ordering is designed to keep frequently co-occurring values close in
|
||||
// memory, while permitting simple wrapping of the 'h' component.
|
||||
PL_API void pl_gamut_map_generate(float *out, const struct pl_gamut_map_params *params);
|
||||
|
||||
// Samples a gamut mapping function for a single IPTPQc4 value. The input
|
||||
// values are updated in-place.
|
||||
PL_API void pl_gamut_map_sample(float x[3], const struct pl_gamut_map_params *params);
|
||||
|
||||
// Performs no gamut-mapping, just hard clips out-of-range colors per-channel.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_clip;
|
||||
|
||||
// Performs a perceptually balanced (saturation) gamut mapping, using a soft
|
||||
// knee function to preserve in-gamut colors, followed by a final softclip
|
||||
// operation. This works bidirectionally, meaning it can both compress and
|
||||
// expand the gamut. Behaves similar to a blend of `saturation` and `softclip`.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_perceptual;
|
||||
|
||||
// Performs a perceptually balanced gamut mapping using a soft knee function to
|
||||
// roll-off clipped regions, and a hue shifting function to preserve saturation.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_softclip;
|
||||
|
||||
// Performs relative colorimetric clipping, while maintaining an exponential
|
||||
// relationship between brightness and chromaticity.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_relative;
|
||||
|
||||
// Performs simple RGB->RGB saturation mapping. The input R/G/B channels are
|
||||
// mapped directly onto the output R/G/B channels. Will never clip, but will
|
||||
// distort all hues and/or result in a faded look.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_saturation;
|
||||
|
||||
// Performs absolute colorimetric clipping. Like pl_gamut_map_relative, but
|
||||
// does not adapt the white point.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_absolute;
|
||||
|
||||
// Performs constant-luminance colorimetric clipping, desaturing colors
|
||||
// towards white until they're in-range.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_desaturate;
|
||||
|
||||
// Uniformly darkens the input slightly to prevent clipping on blown-out
|
||||
// highlights, then clamps colorimetrically to the input gamut boundary,
|
||||
// biased slightly to preserve chromaticity over luminance.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_darken;
|
||||
|
||||
// Performs no gamut mapping, but simply highlights out-of-gamut pixels.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_highlight;
|
||||
|
||||
// Linearly/uniformly desaturates the image in order to bring the entire
|
||||
// image into the target gamut.
|
||||
PL_API extern const struct pl_gamut_map_function pl_gamut_map_linear;
|
||||
|
||||
// A list of built-in gamut mapping functions, terminated by NULL
|
||||
PL_API extern const struct pl_gamut_map_function * const pl_gamut_map_functions[];
|
||||
PL_API extern const int pl_num_gamut_map_functions; // excluding trailing NULL
|
||||
|
||||
// Find the gamut mapping function with the given name, or NULL on failure.
|
||||
PL_API const struct pl_gamut_map_function *pl_find_gamut_map_function(const char *name);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_GAMUT_MAPPING_H_
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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_LOG_H_
|
||||
#define LIBPLACEBO_LOG_H_
|
||||
|
||||
#include <libplacebo/config.h>
|
||||
#include <libplacebo/common.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// The log level associated with a given log message.
|
||||
enum pl_log_level {
|
||||
PL_LOG_NONE = 0,
|
||||
PL_LOG_FATAL, // results in total loss of function of a major component
|
||||
PL_LOG_ERR, // serious error; may result in degraded function
|
||||
PL_LOG_WARN, // warning; potentially bad, probably user-relevant
|
||||
PL_LOG_INFO, // informational message, also potentially harmless errors
|
||||
PL_LOG_DEBUG, // verbose debug message, informational
|
||||
PL_LOG_TRACE, // very noisy trace of activity,, usually benign
|
||||
PL_LOG_ALL = PL_LOG_TRACE,
|
||||
};
|
||||
|
||||
struct pl_log_params {
|
||||
// Logging callback. All messages, informational or otherwise, will get
|
||||
// redirected to this callback. The logged messages do not include trailing
|
||||
// newlines. Optional.
|
||||
void (*log_cb)(void *log_priv, enum pl_log_level level, const char *msg);
|
||||
void *log_priv;
|
||||
|
||||
// The current log level. Controls the level of message that will be
|
||||
// redirected to the log callback. Setting this to PL_LOG_ALL means all
|
||||
// messages will be forwarded, but doing so indiscriminately can result
|
||||
// in increased CPU usage as it may enable extra debug paths based on the
|
||||
// configured log level.
|
||||
enum pl_log_level log_level;
|
||||
};
|
||||
|
||||
#define pl_log_params(...) (&(struct pl_log_params) { __VA_ARGS__ })
|
||||
PL_API extern const struct pl_log_params pl_log_default_params;
|
||||
|
||||
// Thread-safety: Safe
|
||||
//
|
||||
// Note: In any context in which `pl_log` is used, users may also pass NULL
|
||||
// to disable logging. In other words, NULL is a valid `pl_log`.
|
||||
typedef const struct pl_log_t {
|
||||
struct pl_log_params params;
|
||||
} *pl_log;
|
||||
|
||||
#define pl_log_glue1(x, y) x##y
|
||||
#define pl_log_glue2(x, y) pl_log_glue1(x, y)
|
||||
// Force a link error in the case of linking against an incompatible API
|
||||
// version.
|
||||
#define pl_log_create pl_log_glue2(pl_log_create_, PL_API_VER)
|
||||
// Creates a pl_log. `api_ver` is for historical reasons and ignored currently.
|
||||
// `params` defaults to `&pl_log_default_params` if left as NULL.
|
||||
//
|
||||
// Note: As a general rule, any `params` struct used as an argument to a
|
||||
// function need only live until the corresponding function returns.
|
||||
PL_API pl_log pl_log_create(int api_ver, const struct pl_log_params *params);
|
||||
|
||||
// Destroy a `pl_log` object.
|
||||
//
|
||||
// Note: As a general rule, all `_destroy` functions take the pointer to the
|
||||
// object to free as their parameter. This pointer is overwritten by NULL
|
||||
// afterwards. Calling a _destroy function on &{NULL} is valid, but calling it
|
||||
// on NULL itself is invalid.
|
||||
PL_API void pl_log_destroy(pl_log *log);
|
||||
|
||||
// Update the parameters of a `pl_log` without destroying it. This can be
|
||||
// used to change the log function, log context or log level retroactively.
|
||||
// `params` defaults to `&pl_log_default_params` if left as NULL.
|
||||
//
|
||||
// Returns the previous params, atomically.
|
||||
PL_API struct pl_log_params pl_log_update(pl_log log, const struct pl_log_params *params);
|
||||
|
||||
// Like `pl_log_update` but only updates the log level, leaving the log
|
||||
// callback intact.
|
||||
//
|
||||
// Returns the previous log level, atomically.
|
||||
PL_API enum pl_log_level pl_log_level_update(pl_log log, enum pl_log_level level);
|
||||
|
||||
// Two simple, stream-based loggers. You can use these as the log_cb. If you
|
||||
// also set log_priv to a FILE* (e.g. stdout or stderr) it will be printed
|
||||
// there; otherwise, it will be printed to stdout or stderr depending on the
|
||||
// log level.
|
||||
//
|
||||
// The version with colors will use ANSI escape sequences to indicate the log
|
||||
// level. The version without will use explicit prefixes.
|
||||
PL_API void pl_log_simple(void *stream, enum pl_log_level level, const char *msg);
|
||||
PL_API void pl_log_color(void *stream, enum pl_log_level level, const char *msg);
|
||||
|
||||
// Backwards compatibility with older versions of libplacebo
|
||||
#define pl_context pl_log
|
||||
#define pl_context_params pl_log_params
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_LOG_H_
|
||||
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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_OPENGL_H_
|
||||
#define LIBPLACEBO_OPENGL_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/swapchain.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Note on thread safety: The thread safety of `pl_opengl` and any associated
|
||||
// GPU objects follows the same thread safety rules as the underlying OpenGL
|
||||
// context. In other words, they must only be called from the thread the OpenGL
|
||||
// context is current on.
|
||||
|
||||
typedef const struct pl_opengl_t {
|
||||
pl_gpu gpu;
|
||||
|
||||
// Detected GL version
|
||||
int major, minor;
|
||||
|
||||
// List of GL/EGL extensions, provided for convenience
|
||||
const char * const *extensions;
|
||||
int num_extensions;
|
||||
} *pl_opengl;
|
||||
|
||||
static inline bool pl_opengl_has_ext(pl_opengl gl, const char *ext)
|
||||
{
|
||||
for (int i = 0; i < gl->num_extensions; i++)
|
||||
if (!strcmp(ext, gl->extensions[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef void (*pl_voidfunc_t)(void);
|
||||
|
||||
struct pl_opengl_params {
|
||||
// Main gl*GetProcAddr function. This will be used to load all GL/EGL
|
||||
// functions. Optional - if unspecified, libplacebo will default to an
|
||||
// internal loading logic which should work on most platforms.
|
||||
pl_voidfunc_t (*get_proc_addr_ex)(void *proc_ctx, const char *procname);
|
||||
void *proc_ctx;
|
||||
|
||||
// Simpler API for backwards compatibility / convenience. (This one
|
||||
// directly matches the signature of most gl*GetProcAddr library functions)
|
||||
pl_voidfunc_t (*get_proc_addr)(const char *procname);
|
||||
|
||||
// Enable OpenGL debug report callbacks. May have little effect depending
|
||||
// on whether or not the GL context was initialized with appropriate
|
||||
// debugging enabled.
|
||||
bool debug;
|
||||
|
||||
// Allow the use of (suspected) software rasterizers and renderers. These
|
||||
// can be useful for debugging purposes, but normally, their use is
|
||||
// undesirable when GPU-accelerated processing is expected.
|
||||
bool allow_software;
|
||||
|
||||
// Restrict the maximum allowed GLSL version. (Mainly for testing)
|
||||
int max_glsl_version;
|
||||
|
||||
// Optional. Required when importing/exporting dmabufs as textures.
|
||||
void *egl_display;
|
||||
void *egl_context;
|
||||
|
||||
// Optional callbacks to bind/release the OpenGL context on the current
|
||||
// thread. If these are specified, then the resulting `pl_gpu` will have
|
||||
// `pl_gpu_limits.thread_safe` enabled, and may therefore be used from any
|
||||
// thread without first needing to bind the OpenGL context.
|
||||
//
|
||||
// If the user is re-using the same OpenGL context in non-libplacebo code,
|
||||
// then these callbacks should include whatever synchronization is
|
||||
// necessary to prevent simultaneous use between libplacebo and the user.
|
||||
bool (*make_current)(void *priv);
|
||||
void (*release_current)(void *priv);
|
||||
void *priv;
|
||||
};
|
||||
|
||||
// Default/recommended parameters
|
||||
#define pl_opengl_params(...) (&(struct pl_opengl_params) { __VA_ARGS__ })
|
||||
PL_API extern const struct pl_opengl_params pl_opengl_default_params;
|
||||
|
||||
// Creates a new OpenGL renderer based on the given parameters. This will
|
||||
// internally use whatever platform-defined mechanism (WGL, X11, EGL) is
|
||||
// appropriate for loading the OpenGL function calls, so the user doesn't need
|
||||
// to pass in a `getProcAddress` callback. If `params` is left as NULL, it
|
||||
// defaults to `&pl_opengl_default_params`. The context must be active when
|
||||
// calling this function, and must remain active whenever calling any
|
||||
// libplacebo function on the resulting `pl_opengl` or `pl_gpu`.
|
||||
//
|
||||
// Note that creating multiple `pl_opengl` instances from the same OpenGL
|
||||
// context is undefined behavior.
|
||||
PL_API pl_opengl pl_opengl_create(pl_log log, const struct pl_opengl_params *params);
|
||||
|
||||
// All resources allocated from the `pl_gpu` contained by this `pl_opengl` must
|
||||
// be explicitly destroyed by the user before calling `pl_opengl_destroy`.
|
||||
PL_API void pl_opengl_destroy(pl_opengl *gl);
|
||||
|
||||
// For a `pl_gpu` backed by `pl_opengl`, this function can be used to retrieve
|
||||
// the underlying `pl_opengl`. Returns NULL for any other type of `gpu`.
|
||||
PL_API pl_opengl pl_opengl_get(pl_gpu gpu);
|
||||
|
||||
struct pl_opengl_framebuffer {
|
||||
// ID of the framebuffer, or 0 to use the context's default framebuffer.
|
||||
int id;
|
||||
|
||||
// If true, then the framebuffer is assumed to be "flipped" relative to
|
||||
// normal GL semantics, i.e. set this to `true` if the first pixel is the
|
||||
// top left corner.
|
||||
bool flipped;
|
||||
};
|
||||
|
||||
struct pl_opengl_swapchain_params {
|
||||
// Set this to the platform-specific function to swap buffers, e.g.
|
||||
// glXSwapBuffers, eglSwapBuffers etc. This will be called internally by
|
||||
// `pl_swapchain_swap_buffers`. Required, unless you never call that
|
||||
// function.
|
||||
void (*swap_buffers)(void *priv);
|
||||
|
||||
// Initial framebuffer description. This can be changed later on using
|
||||
// `pl_opengl_swapchain_update_fb`.
|
||||
struct pl_opengl_framebuffer framebuffer;
|
||||
|
||||
// Attempt forcing a specific latency. If this is nonzero, then
|
||||
// `pl_swapchain_swap_buffers` will wait until fewer than N frames are "in
|
||||
// flight" before returning. Setting this to a high number generally
|
||||
// accomplished nothing, because the OpenGL driver typically limits the
|
||||
// number of buffers on its own. But setting it to a low number like 2 or
|
||||
// even 1 can reduce latency (at the cost of throughput).
|
||||
int max_swapchain_depth;
|
||||
|
||||
// Arbitrary user pointer that gets passed to `swap_buffers` etc.
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#define pl_opengl_swapchain_params(...) (&(struct pl_opengl_swapchain_params) { __VA_ARGS__ })
|
||||
|
||||
// Creates an instance of `pl_swapchain` tied to the active context.
|
||||
// Note: Due to OpenGL semantics, users *must* call `pl_swapchain_resize`
|
||||
// before attempting to use this swapchain, otherwise calls to
|
||||
// `pl_swapchain_start_frame` will fail.
|
||||
PL_API pl_swapchain pl_opengl_create_swapchain(pl_opengl gl,
|
||||
const struct pl_opengl_swapchain_params *params);
|
||||
|
||||
// Update the framebuffer description. After calling this function, users
|
||||
// *must* call `pl_swapchain_resize` before attempting to use the swapchain
|
||||
// again, otherwise calls to `pl_swapchain_start_frame` will fail.
|
||||
PL_API void pl_opengl_swapchain_update_fb(pl_swapchain sw,
|
||||
const struct pl_opengl_framebuffer *fb);
|
||||
|
||||
struct pl_opengl_wrap_params {
|
||||
// The GLuint texture object itself. Optional. If no texture is provided,
|
||||
// then only the opaque framebuffer `fbo` will be wrapped, leaving the
|
||||
// resulting `pl_tex` object with some operations (such as sampling) being
|
||||
// unsupported.
|
||||
unsigned int texture;
|
||||
|
||||
// The GLuint associated framebuffer. Optional. If this is not specified,
|
||||
// then libplacebo will attempt creating a framebuffer from the provided
|
||||
// texture object (if possible).
|
||||
//
|
||||
// Note: As a special case, if neither a texture nor an FBO are provided,
|
||||
// this is equivalent to wrapping the OpenGL default framebuffer (id 0).
|
||||
unsigned int framebuffer;
|
||||
|
||||
// The image's dimensions (unused dimensions must be 0)
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
|
||||
// Texture-specific fields:
|
||||
//
|
||||
// Note: These are only relevant if `texture` is provided.
|
||||
|
||||
// The GLenum for the texture target to use, e.g. GL_TEXTURE_2D. Optional.
|
||||
// If this is left as 0, the target is inferred from the number of
|
||||
// dimensions. Users may want to set this to something specific like
|
||||
// GL_TEXTURE_EXTERNAL_OES depending on the nature of the texture.
|
||||
unsigned int target;
|
||||
|
||||
// The texture's GLint sized internal format (e.g. GL_RGBA16F). Required.
|
||||
int iformat;
|
||||
};
|
||||
|
||||
#define pl_opengl_wrap_params(...) (&(struct pl_opengl_wrap_params) { __VA_ARGS__ })
|
||||
|
||||
// Wraps an external OpenGL object into a `pl_tex` abstraction. Due to the
|
||||
// internally synchronized nature of OpenGL, no explicit synchronization
|
||||
// is needed between libplacebo `pl_tex_` operations, and host accesses to
|
||||
// the texture. Wrapping the same OpenGL texture multiple times is permitted.
|
||||
// Note that this function transfers no ownership.
|
||||
//
|
||||
// This wrapper can be destroyed by simply calling `pl_tex_destroy` on it,
|
||||
// which will *not* destroy the user-provided OpenGL texture or framebuffer.
|
||||
//
|
||||
// This function may fail, in which case it returns NULL.
|
||||
PL_API pl_tex pl_opengl_wrap(pl_gpu gpu, const struct pl_opengl_wrap_params *params);
|
||||
|
||||
// Analogous to `pl_opengl_wrap`, this function takes any `pl_tex` (including
|
||||
// ones created by `pl_tex_create`) and unwraps it to expose the underlying
|
||||
// OpenGL texture to the user. Note that this function transfers no ownership,
|
||||
// i.e. the texture object and framebuffer shall not be destroyed by the user.
|
||||
//
|
||||
// Returns the OpenGL texture. `out_target` and `out_iformat` will be updated
|
||||
// to hold the target type and internal format, respectively. (Optional)
|
||||
//
|
||||
// For renderable/blittable textures, `out_fbo` will be updated to the ID of
|
||||
// the framebuffer attached to this texture, or 0 if there is none. (Optional)
|
||||
PL_API unsigned int pl_opengl_unwrap(pl_gpu gpu, pl_tex tex, unsigned int *out_target,
|
||||
int *out_iformat, unsigned int *out_fbo);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_OPENGL_H_
|
||||
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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_OPTIONS_H_
|
||||
#define LIBPLACEBO_OPTIONS_H_
|
||||
|
||||
#include <libplacebo/renderer.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// High-level heap-managed struct containing storage for all options implied by
|
||||
// pl_render_params, including a high-level interface for serializing,
|
||||
// deserializing and interfacing with them in a programmatic way.
|
||||
|
||||
typedef const struct pl_opt_t *pl_opt;
|
||||
typedef struct pl_options_t {
|
||||
// Non-NULL `params.*_params` pointers must always point into this struct
|
||||
struct pl_render_params params;
|
||||
|
||||
// Backing storage for all of the various rendering parameters. Whether
|
||||
// or not these params are active is determined by whether or not
|
||||
// `params.*_params` is set to this address or NULL.
|
||||
struct pl_deband_params deband_params;
|
||||
struct pl_sigmoid_params sigmoid_params;
|
||||
struct pl_color_adjustment color_adjustment;
|
||||
struct pl_peak_detect_params peak_detect_params;
|
||||
struct pl_color_map_params color_map_params;
|
||||
struct pl_dither_params dither_params;
|
||||
struct pl_icc_params icc_params PL_DEPRECATED;
|
||||
struct pl_cone_params cone_params;
|
||||
struct pl_blend_params blend_params;
|
||||
struct pl_deinterlace_params deinterlace_params;
|
||||
struct pl_distort_params distort_params;
|
||||
|
||||
// Backing storage for "custom" scalers. `params.upscaler` etc. will
|
||||
// always be a pointer either to a built-in pl_filter_config, or one of
|
||||
// these structs. `name`, `description` and `allowed` will always be
|
||||
// valid for the respective type of filter config.
|
||||
struct pl_filter_config upscaler;
|
||||
struct pl_filter_config downscaler;
|
||||
struct pl_filter_config plane_upscaler;
|
||||
struct pl_filter_config plane_downscaler;
|
||||
struct pl_filter_config frame_mixer;
|
||||
} *pl_options;
|
||||
|
||||
// Allocate a new set of render params, with internally backed storage for
|
||||
// all parameters. Initialized to an "empty" config (PL_RENDER_DEFAULTS),
|
||||
// equivalent to `&pl_render_fast_params`. To initialize the struct instead to
|
||||
// the recommended default parameters, use `pl_options_reset` with
|
||||
// `pl_render_default_params`.
|
||||
//
|
||||
// If `log` is provided, errors related to parsing etc. will be logged there.
|
||||
PL_API pl_options pl_options_alloc(pl_log log);
|
||||
PL_API void pl_options_free(pl_options *opts);
|
||||
|
||||
// Resets all options to their default values from a given struct. If `preset`
|
||||
// is NULL, `opts` is instead reset back to the initial "empty" configuration,
|
||||
// with all options disabled, as if it was freshly allocated.
|
||||
//
|
||||
// Note: This function will also reset structs which were not included in
|
||||
// `preset`, such as any custom upscalers.
|
||||
PL_API void pl_options_reset(pl_options opts, const struct pl_render_params *preset);
|
||||
|
||||
typedef const struct pl_opt_data_t {
|
||||
// Original options struct.
|
||||
pl_options opts;
|
||||
|
||||
// Triggering option for this callback invocation.
|
||||
pl_opt opt;
|
||||
|
||||
// The raw data associated with this option. Always some pointer into
|
||||
// `opts`. Note that only PL_OPT_BOOL, PL_OPT_INT and PL_OPT_FLOAT have
|
||||
// a fixed representation, for other fields its usefulness is dubious.
|
||||
const void *value;
|
||||
|
||||
// The underlying data, as a formatted, locale-invariant string. Lifetime
|
||||
// is limited until the return of this callback.
|
||||
const char *text;
|
||||
} *pl_opt_data;
|
||||
|
||||
// Query a single option from `opts` by key, or NULL if none was found.
|
||||
// The resulting pointer is only valid until the next pl_options_* call.
|
||||
PL_API pl_opt_data pl_options_get(pl_options opts, const char *key);
|
||||
|
||||
// Update an option from a formatted value string (see `pl_opt_data.text`).
|
||||
// This can be used for all type of options, even non-string ones. In this case,
|
||||
// `value` will be parsed according to the option type.
|
||||
//
|
||||
// Returns whether successful.
|
||||
PL_API bool pl_options_set_str(pl_options opts, const char *key, const char *value);
|
||||
|
||||
// Programmatically iterate over options set in a `pl_options`, running the
|
||||
// provided callback on each entry.
|
||||
PL_API void pl_options_iterate(pl_options opts,
|
||||
void (*cb)(void *priv, pl_opt_data data),
|
||||
void *priv);
|
||||
|
||||
// Serialize a `pl_options` structs to a comma-separated key/value string. The
|
||||
// returned string has a lifetime valid until either the next call to
|
||||
// `pl_options_save`, or until the `pl_options` is freed.
|
||||
PL_API const char *pl_options_save(pl_options opts);
|
||||
|
||||
// Parse a `pl_options` struct from a key/value string, in standard syntax
|
||||
// "key1=value1,key2=value2,...", and updates `opts` with the new values.
|
||||
// Valid separators include whitespace, commas (,) and (semi)colons (:;).
|
||||
//
|
||||
// Returns true if no errors occurred.
|
||||
PL_API bool pl_options_load(pl_options opts, const char *str);
|
||||
|
||||
// Helpers for interfacing with `opts->params.hooks`. Note that using any of
|
||||
// these helpers will overwrite the array by an internally managed pointer,
|
||||
// so care must be taken when combining them with external management of
|
||||
// this memory. Negative indices are possible and are counted relative to the
|
||||
// end of the list.
|
||||
//
|
||||
// Note: These hooks are *not* included in pl_options_save() and related.
|
||||
PL_API void pl_options_add_hook(pl_options opts, const struct pl_hook *hook);
|
||||
PL_API void pl_options_insert_hook(pl_options opts, const struct pl_hook *hook, int idx);
|
||||
PL_API void pl_options_remove_hook_at(pl_options opts, int idx);
|
||||
|
||||
// Underlying options system and list
|
||||
//
|
||||
// Note: By necessity, this option list does not cover every single field
|
||||
// present in `pl_render_params`. In particular, fields like `info_callback`,
|
||||
// `lut` and `hooks` cannot be configured through the options system, as doing
|
||||
// so would require interop with C code or I/O. (However, see
|
||||
// `pl_options_add_hook` and related)
|
||||
|
||||
enum pl_option_type {
|
||||
// Accepts `yes/no`, `on/off`, `true/false` and variants
|
||||
PL_OPT_BOOL,
|
||||
|
||||
// Parsed as human-readable locale-invariant (C) numbers, scientific
|
||||
// notation accepted for floats
|
||||
PL_OPT_INT,
|
||||
PL_OPT_FLOAT,
|
||||
|
||||
// Parsed as a short string containing only alphanumerics and _-,
|
||||
// corresponding to some name/identifier. Catch-all bucket for several
|
||||
// other types of options, such as presets, struct pointers, and functions
|
||||
//
|
||||
// Note: These options do not correspond to actual strings in C, the
|
||||
// underlying type of option will determine the values of `size` and
|
||||
// corresponding interpretation of pointers.
|
||||
PL_OPT_STRING,
|
||||
|
||||
PL_OPT_TYPE_COUNT,
|
||||
};
|
||||
|
||||
struct pl_opt_t {
|
||||
// Programmatic key uniquely identifying this option.
|
||||
const char *key;
|
||||
|
||||
// Longer, human readable friendly name
|
||||
const char *name;
|
||||
|
||||
// Data type of option, affects how it is parsed. This field is purely
|
||||
// informative for the user, the actual implementation may vary.
|
||||
enum pl_option_type type;
|
||||
|
||||
// Minimum/maximum value ranges for numeric options (int / float)
|
||||
// If both are 0.0, these limits are disabled/ignored.
|
||||
float min, max;
|
||||
|
||||
// If true, this option is considered deprecated and may be removed
|
||||
// in the future.
|
||||
bool deprecated;
|
||||
|
||||
// If true, this option is considered a 'preset' (read-only), which can
|
||||
// be loaded but not saved. (The equivalent underlying options this preset
|
||||
// corresponds to will be saved instead)
|
||||
bool preset;
|
||||
|
||||
// Internal implementation details (for parsing/saving), opaque to user
|
||||
const void *priv;
|
||||
};
|
||||
|
||||
// A list of options, terminated by {0} for convenience
|
||||
PL_API extern const struct pl_opt_t pl_option_list[];
|
||||
PL_API extern const int pl_option_count; // excluding terminating {0}
|
||||
|
||||
// Returns the `pl_option` associated with a given key, or NULL
|
||||
PL_API pl_opt pl_find_option(const char *key);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_OPTIONS_H_
|
||||
@ -0,0 +1,847 @@
|
||||
/*
|
||||
* 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_RENDERER_H_
|
||||
#define LIBPLACEBO_RENDERER_H_
|
||||
|
||||
#include <libplacebo/config.h>
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/filters.h>
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/shaders/colorspace.h>
|
||||
#include <libplacebo/shaders/deinterlacing.h>
|
||||
#include <libplacebo/shaders/dithering.h>
|
||||
#include <libplacebo/shaders/film_grain.h>
|
||||
#include <libplacebo/shaders/icc.h>
|
||||
#include <libplacebo/shaders/lut.h>
|
||||
#include <libplacebo/shaders/sampling.h>
|
||||
#include <libplacebo/shaders/custom.h>
|
||||
#include <libplacebo/swapchain.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Thread-safety: Unsafe
|
||||
typedef struct pl_renderer_t *pl_renderer;
|
||||
|
||||
// Enum values used in pl_renderer_errors_t as a bit positions for error flags
|
||||
enum pl_render_error {
|
||||
PL_RENDER_ERR_NONE = 0,
|
||||
PL_RENDER_ERR_FBO = 1 << 0,
|
||||
PL_RENDER_ERR_SAMPLING = 1 << 1,
|
||||
PL_RENDER_ERR_DEBANDING = 1 << 2,
|
||||
PL_RENDER_ERR_BLENDING = 1 << 3,
|
||||
PL_RENDER_ERR_OVERLAY = 1 << 4,
|
||||
PL_RENDER_ERR_PEAK_DETECT = 1 << 5,
|
||||
PL_RENDER_ERR_FILM_GRAIN = 1 << 6,
|
||||
PL_RENDER_ERR_FRAME_MIXING = 1 << 7,
|
||||
PL_RENDER_ERR_DEINTERLACING = 1 << 8,
|
||||
PL_RENDER_ERR_ERROR_DIFFUSION = 1 << 9,
|
||||
PL_RENDER_ERR_HOOKS = 1 << 10,
|
||||
PL_RENDER_ERR_CONTRAST_RECOVERY = 1 << 11,
|
||||
};
|
||||
|
||||
// Struct describing current renderer state, including internal processing errors,
|
||||
// as well as list of signatures of disabled hooks.
|
||||
struct pl_render_errors {
|
||||
enum pl_render_error errors;
|
||||
// List containing signatures of disabled hooks
|
||||
const uint64_t *disabled_hooks;
|
||||
int num_disabled_hooks;
|
||||
};
|
||||
|
||||
// Creates a new renderer object, which is backed by a GPU context. This is a
|
||||
// high-level object that takes care of the rendering chain as a whole, from
|
||||
// the source textures to the finished frame.
|
||||
PL_API pl_renderer pl_renderer_create(pl_log log, pl_gpu gpu);
|
||||
PL_API void pl_renderer_destroy(pl_renderer *rr);
|
||||
|
||||
// Returns current renderer state, see pl_render_errors.
|
||||
PL_API struct pl_render_errors pl_renderer_get_errors(pl_renderer rr);
|
||||
|
||||
// Clears errors state of renderer. If `errors` is NULL, all render errors will
|
||||
// be cleared. Otherwise only selected errors/hooks will be cleared.
|
||||
// If `PL_RENDER_ERR_HOOKS` is set and `num_disabled_hooks` is 0, clear all hooks.
|
||||
// Otherwise only selected hooks will be cleard based on `disabled_hooks` array.
|
||||
PL_API void pl_renderer_reset_errors(pl_renderer rr,
|
||||
const struct pl_render_errors *errors);
|
||||
|
||||
enum pl_lut_type {
|
||||
PL_LUT_UNKNOWN = 0,
|
||||
PL_LUT_NATIVE, // applied to raw image contents (after fixing bit depth)
|
||||
PL_LUT_NORMALIZED, // applied to normalized (HDR) RGB values
|
||||
PL_LUT_CONVERSION, // LUT fully replaces color conversion
|
||||
|
||||
// Note: When using a PL_LUT_CONVERSION to replace the YUV->RGB conversion,
|
||||
// `pl_render_params.color_adjustment` is no longer applied. Similarly,
|
||||
// when using a PL_LUT_CONVERSION to replace the image->target color space
|
||||
// conversion, `pl_render_params.color_map_params` are ignored.
|
||||
//
|
||||
// Note: For LUTs attached to the output frame, PL_LUT_CONVERSION should
|
||||
// instead perform the inverse (RGB->native) conversion.
|
||||
//
|
||||
// Note: PL_LUT_UNKNOWN tries inferring the meaning of the LUT from the
|
||||
// LUT's tagged metadata, and otherwise falls back to PL_LUT_NATIVE.
|
||||
};
|
||||
|
||||
enum pl_render_stage {
|
||||
PL_RENDER_STAGE_FRAME, // full frame redraws, for fresh/uncached frames
|
||||
PL_RENDER_STAGE_BLEND, // the output blend pass (only for pl_render_image_mix)
|
||||
PL_RENDER_STAGE_COUNT,
|
||||
};
|
||||
|
||||
struct pl_render_info {
|
||||
const struct pl_dispatch_info *pass; // information about the shader
|
||||
enum pl_render_stage stage; // the associated render stage
|
||||
|
||||
// This specifies the chronological index of this pass within the frame and
|
||||
// stage (starting at `index == 0`).
|
||||
int index;
|
||||
|
||||
// For PL_RENDER_STAGE_BLEND, this specifies the number of frames
|
||||
// being blended (since that results in a different shader).
|
||||
int count;
|
||||
};
|
||||
|
||||
// Represents the options used for rendering. These affect the quality of
|
||||
// the result.
|
||||
struct pl_render_params {
|
||||
// Configures the algorithms used for upscaling and downscaling,
|
||||
// respectively. If left as NULL, then libplacebo will only use inexpensive
|
||||
// sampling (bilinear or nearest neighbour depending on the capabilities
|
||||
// of the hardware / texture).
|
||||
//
|
||||
// Note: Setting `downscaler` to NULL also implies `skip_anti_aliasing`,
|
||||
// since the built-in GPU sampling algorithms can't anti-alias.
|
||||
//
|
||||
// Note: If set to the same address as the built-in `pl_filter_bicubic`,
|
||||
// `pl_filter_nearest` etc.; libplacebo will also use the more efficient
|
||||
// direct sampling algorithm where possible without quality loss.
|
||||
const struct pl_filter_config *upscaler;
|
||||
const struct pl_filter_config *downscaler;
|
||||
|
||||
// If set, this overrides the value of `upscaler`/`downscaling` for
|
||||
// subsampled (chroma) planes. These scalers are used whenever the size of
|
||||
// multiple different `pl_plane`s in a single `pl_frame` differ, requiring
|
||||
// adaptation when converting to/from RGB. Note that a value of NULL simply
|
||||
// means "no override". To force built-in scaling explicitly, set this to
|
||||
// `&pl_filter_bilinear`.
|
||||
const struct pl_filter_config *plane_upscaler;
|
||||
const struct pl_filter_config *plane_downscaler;
|
||||
|
||||
// The anti-ringing strength to apply to filters. See the equivalent option
|
||||
// in `pl_sample_filter_params` for more information.
|
||||
float antiringing_strength;
|
||||
|
||||
// Configures the algorithm used for frame mixing (when using
|
||||
// `pl_render_image_mix`). Ignored otherwise. As a special requirement,
|
||||
// this must be a filter config with `polar` set to false, since it's only
|
||||
// used for 1D mixing and thus only 1D filters are compatible.
|
||||
//
|
||||
// If set to NULL, frame mixing is disabled, in which case
|
||||
// `pl_render_image_mix` will use nearest-neighbour semantics. (Note that
|
||||
// this still goes through the redraw cache, unless you also enable
|
||||
// `skip_caching_single_frame`)
|
||||
const struct pl_filter_config *frame_mixer;
|
||||
|
||||
// Configures the settings used to deband source textures. Leaving this as
|
||||
// NULL disables debanding.
|
||||
//
|
||||
// Note: The `deband_params.grain` setting is automatically adjusted to
|
||||
// prevent blowing up on HDR sources. The user need not account for this.
|
||||
const struct pl_deband_params *deband_params;
|
||||
|
||||
// Configures the settings used to sigmoidize the image before upscaling.
|
||||
// This is not always used. If NULL, disables sigmoidization.
|
||||
const struct pl_sigmoid_params *sigmoid_params;
|
||||
|
||||
// Configures the color adjustment parameters used to decode the color.
|
||||
// This can be used to apply additional artistic settings such as
|
||||
// desaturation, etc. If NULL, defaults to &pl_color_adjustment_neutral.
|
||||
const struct pl_color_adjustment *color_adjustment;
|
||||
|
||||
// Configures the settings used to detect the peak of the source content,
|
||||
// for HDR sources. Has no effect on SDR content. If NULL, peak detection
|
||||
// is disabled.
|
||||
const struct pl_peak_detect_params *peak_detect_params;
|
||||
|
||||
// Configures the settings used to tone map from HDR to SDR, or from higher
|
||||
// gamut to standard gamut content. If NULL, defaults to
|
||||
// `&pl_color_map_default_params`.
|
||||
const struct pl_color_map_params *color_map_params;
|
||||
|
||||
// Configures the settings used to dither to the output depth. Leaving this
|
||||
// as NULL disables dithering.
|
||||
const struct pl_dither_params *dither_params;
|
||||
|
||||
// Configures the error diffusion kernel to use for error diffusion
|
||||
// dithering. If set, this will be used instead of `dither_params` whenever
|
||||
// possible. Leaving this as NULL disables error diffusion.
|
||||
const struct pl_error_diffusion_kernel *error_diffusion;
|
||||
|
||||
// Configures the settings used to simulate color blindness, if desired.
|
||||
// If NULL, this feature is disabled.
|
||||
const struct pl_cone_params *cone_params;
|
||||
|
||||
// Configures output blending. When rendering to the final target, the
|
||||
// framebuffer contents will be blended using this blend mode. Requires
|
||||
// that the target format has PL_FMT_CAP_BLENDABLE. NULL disables blending.
|
||||
const struct pl_blend_params *blend_params;
|
||||
|
||||
// Configures the settings used to deinterlace frames (see
|
||||
// `pl_frame.field`), if required.. If NULL, deinterlacing is "disabled",
|
||||
// meaning interlaced frames are rendered as weaved frames instead.
|
||||
//
|
||||
// Note: As a consequence of how `pl_frame` represents individual fields,
|
||||
// and especially when using the `pl_queue`, this will still result in
|
||||
// frames being redundantly rendered twice. As such, it's highly
|
||||
// recommended to, instead, fully disable deinterlacing by not marking
|
||||
// source frames as interlaced in the first place.
|
||||
const struct pl_deinterlace_params *deinterlace_params;
|
||||
|
||||
// If set, applies an extra distortion matrix to the image, after
|
||||
// scaling and before presenting it to the screen. Can be used for e.g.
|
||||
// fractional rotation.
|
||||
//
|
||||
// Note: The distortion canvas will be set to the size of `target->crop`,
|
||||
// so this cannot effectively draw outside the specified target area,
|
||||
// nor change the aspect ratio of the image.
|
||||
const struct pl_distort_params *distort_params;
|
||||
|
||||
// List of custom user shaders / hooks.
|
||||
// See <libplacebo/shaders/custom.h> for more information.
|
||||
const struct pl_hook * const *hooks;
|
||||
int num_hooks;
|
||||
|
||||
// Color mapping LUT. If present, this will be applied as part of the
|
||||
// image being rendered, in normalized RGB space.
|
||||
//
|
||||
// Note: In this context, PL_LUT_NATIVE means "gamma light" and
|
||||
// PL_LUT_NORMALIZED means "linear light". For HDR signals, normalized LUTs
|
||||
// are scaled so 1.0 corresponds to the `pl_color_transfer_nominal_peak`.
|
||||
//
|
||||
// Note: A PL_LUT_CONVERSION fully replaces the color adaptation from
|
||||
// `image` to `target`, including any tone-mapping (if necessary) and ICC
|
||||
// profiles. It has the same representation as PL_LUT_NATIVE, so in this
|
||||
// case the input and output are (respectively) non-linear light RGB.
|
||||
const struct pl_custom_lut *lut;
|
||||
enum pl_lut_type lut_type;
|
||||
|
||||
// If the image being rendered does not span the entire size of the target,
|
||||
// it will be cleared explicitly using this background color (RGB). To
|
||||
// disable this logic, set `skip_target_clearing`.
|
||||
float background_color[3];
|
||||
float background_transparency; // 0.0 for opaque, 1.0 for fully transparent
|
||||
bool skip_target_clearing;
|
||||
|
||||
// If set to a value above 0.0, the output will be rendered with rounded
|
||||
// corners, as if an alpha transparency mask had been applied. The value
|
||||
// indicates the relative fraction of the side length to round - a value
|
||||
// of 1.0 rounds the corners as much as possible.
|
||||
float corner_rounding;
|
||||
|
||||
// If true, then transparent images will made opaque by painting them
|
||||
// against a checkerboard pattern consisting of alternating colors. If both
|
||||
// colors are left as {0}, they default respectively to 93% and 87% gray.
|
||||
bool blend_against_tiles;
|
||||
float tile_colors[2][3];
|
||||
int tile_size;
|
||||
|
||||
// --- Performance / quality trade-off options:
|
||||
// These should generally be left off where quality is desired, as they can
|
||||
// degrade the result quite noticeably; but may be useful for older or
|
||||
// slower hardware. Note that libplacebo will automatically disable
|
||||
// advanced features on hardware where they are unsupported, regardless of
|
||||
// these settings. So only enable them if you need a performance bump.
|
||||
|
||||
// Disables anti-aliasing on downscaling. This will result in moiré
|
||||
// artifacts and nasty, jagged pixels when downscaling, except for some
|
||||
// very limited special cases (e.g. bilinear downsampling to exactly 0.5x).
|
||||
//
|
||||
// Significantly speeds up downscaling with high downscaling ratios.
|
||||
bool skip_anti_aliasing;
|
||||
|
||||
// Normally, when the size of the `target` used with `pl_render_image_mix`
|
||||
// changes, or the render parameters are updated, the internal cache of
|
||||
// mixed frames must be discarded in order to re-render all required
|
||||
// frames. Setting this option to `true` will skip the cache invalidation
|
||||
// and instead re-use the existing frames (with bilinear scaling to the new
|
||||
// size if necessary), which comes at a quality loss shortly after a
|
||||
// resize, but should make it much more smooth.
|
||||
bool preserve_mixing_cache;
|
||||
|
||||
// --- Performance tuning / debugging options
|
||||
// These may affect performance or may make debugging problems easier,
|
||||
// but shouldn't have any effect on the quality.
|
||||
|
||||
// Normally, `pl_render_image_mix` will also push single frames through the
|
||||
// mixer cache, in order to speed up re-draws. Enabling this option
|
||||
// disables that logic, causing single frames to bypass the cache. (Though
|
||||
// it will still read from, if they happen to already be cached)
|
||||
bool skip_caching_single_frame;
|
||||
|
||||
// Disables linearization / sigmoidization before scaling. This might be
|
||||
// useful when tracking down unexpected image artifacts or excessing
|
||||
// ringing, but it shouldn't normally be necessary.
|
||||
bool disable_linear_scaling;
|
||||
|
||||
// Forces the use of the "general" scaling algorithms even when using the
|
||||
// special-cased built-in presets like `pl_filter_bicubic`. Basically, this
|
||||
// disables the more efficient implementations in favor of the slower,
|
||||
// general-purpose ones.
|
||||
bool disable_builtin_scalers;
|
||||
|
||||
// Forces correction of subpixel offsets (using the configured `upscaler`).
|
||||
bool correct_subpixel_offsets;
|
||||
|
||||
// Forces the use of dithering, even when rendering to 16-bit FBOs. This is
|
||||
// generally pretty pointless because most 16-bit FBOs have high enough
|
||||
// depth that rounding errors are below the human perception threshold,
|
||||
// but this can be used to test the dither code.
|
||||
bool force_dither;
|
||||
|
||||
// Disables the gamma-correct dithering logic which normally applies when
|
||||
// dithering to low bit depths. No real use, outside of testing.
|
||||
bool disable_dither_gamma_correction;
|
||||
|
||||
// Completely overrides the use of FBOs, as if there were no renderable
|
||||
// texture format available. This disables most features.
|
||||
bool disable_fbos;
|
||||
|
||||
// Use only low-bit-depth FBOs (8 bits). Note that this also implies
|
||||
// disabling linear scaling and sigmoidization.
|
||||
bool force_low_bit_depth_fbos;
|
||||
|
||||
// If this is true, all shaders will be generated as "dynamic" shaders,
|
||||
// with any compile-time constants being replaced by runtime-adjustable
|
||||
// values. This is generally a performance loss, but has the advantage of
|
||||
// being able to freely change parameters without triggering shader
|
||||
// recompilations.
|
||||
//
|
||||
// It's a good idea to enable while presenting configurable settings to the
|
||||
// user, but it should be set to false once those values are "dialed in".
|
||||
bool dynamic_constants;
|
||||
|
||||
// This callback is invoked for every pass successfully executed in the
|
||||
// process of rendering a frame. Optional.
|
||||
//
|
||||
// Note: `info` is only valid until this function returns.
|
||||
void (*info_callback)(void *priv, const struct pl_render_info *info);
|
||||
void *info_priv;
|
||||
|
||||
// --- Deprecated/removed fields
|
||||
bool allow_delayed_peak_detect PL_DEPRECATED; // moved to pl_peak_detect_params
|
||||
const struct pl_icc_params *icc_params PL_DEPRECATED; // use pl_frame.icc
|
||||
bool ignore_icc_profiles PL_DEPRECATED; // non-functional, just set pl_frame.icc to NULL
|
||||
int lut_entries PL_DEPRECATED; // hard-coded as 256
|
||||
float polar_cutoff PL_DEPRECATED; // hard-coded as 1e-3
|
||||
};
|
||||
|
||||
// Bare minimum parameters, with no features enabled. This is the fastest
|
||||
// possible configuration, and should therefore be fine on any system.
|
||||
#define PL_RENDER_DEFAULTS \
|
||||
.color_map_params = &pl_color_map_default_params, \
|
||||
.color_adjustment = &pl_color_adjustment_neutral, \
|
||||
.tile_colors = {{0.93, 0.93, 0.93}, \
|
||||
{0.87, 0.87, 0.87}}, \
|
||||
.tile_size = 32,
|
||||
|
||||
#define pl_render_params(...) (&(struct pl_render_params) { PL_RENDER_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_render_params pl_render_fast_params;
|
||||
|
||||
// This contains the default/recommended options for reasonable image quality,
|
||||
// while also not being too terribly slow. All of the *_params structs are
|
||||
// defaulted to the corresponding *_default_params, except for deband_params,
|
||||
// which is disabled by default.
|
||||
//
|
||||
// This should be fine on most integrated GPUs, but if it's too slow,
|
||||
// consider using `pl_render_fast_params` instead.
|
||||
PL_API extern const struct pl_render_params pl_render_default_params;
|
||||
|
||||
// This contains a higher quality preset for better image quality at the cost
|
||||
// of quite a bit of performance. In addition to the settings implied by
|
||||
// `pl_render_default_params`, it enables debanding, sets the upscaler to
|
||||
// `pl_filter_ewa_lanczossharp`, and uses pl_*_high_quality_params structs where
|
||||
// available. This should only really be used with a discrete GPU and where
|
||||
// maximum image quality is desired.
|
||||
PL_API extern const struct pl_render_params pl_render_high_quality_params;
|
||||
|
||||
#define PL_MAX_PLANES 4
|
||||
|
||||
// High level description of a single slice of an image. This basically
|
||||
// represents a single 2D plane, with any number of components
|
||||
struct pl_plane {
|
||||
// The texture underlying this plane. The texture must be 2D, and must
|
||||
// have specific parameters set depending on what the plane is being used
|
||||
// for (see `pl_render_image`).
|
||||
pl_tex texture;
|
||||
|
||||
// The preferred behaviour when sampling outside of this texture. Optional,
|
||||
// since the default (PL_TEX_ADDRESS_CLAMP) is very reasonable.
|
||||
enum pl_tex_address_mode address_mode;
|
||||
|
||||
// Controls whether or not the `texture` will be considered flipped
|
||||
// vertically with respect to the overall image dimensions. It's generally
|
||||
// preferable to flip planes using this setting instead of the crop in
|
||||
// cases where the flipping is the result of e.g. negative plane strides or
|
||||
// flipped framebuffers (OpenGL).
|
||||
//
|
||||
// Note that any planar padding (due to e.g. size mismatch or misalignment
|
||||
// of subsampled planes) is always at the physical end of the texture
|
||||
// (highest y coordinate) - even if this bool is true. However, any
|
||||
// subsampling shift (`shift_y`) is applied with respect to the flipped
|
||||
// direction. This ensures the correct interpretation when e.g. vertically
|
||||
// flipping 4:2:0 sources by flipping all planes.
|
||||
bool flipped;
|
||||
|
||||
// Describes the number and interpretation of the components in this plane.
|
||||
// This defines the mapping from component index to the canonical component
|
||||
// order (RGBA, YCbCrA or XYZA). It's worth pointing out that this is
|
||||
// completely separate from `texture->format.sample_order`. The latter is
|
||||
// essentially irrelevant/transparent for the API user, since it just
|
||||
// determines which order the texture data shows up as inside the GLSL
|
||||
// shader; whereas this field controls the actual meaning of the component.
|
||||
//
|
||||
// Example; if the user has a plane with just {Y} and a plane with just
|
||||
// {Cb Cr}, and a GPU that only supports bgra formats, you would still
|
||||
// specify the component mapping as {0} and {1 2} respectively, even though
|
||||
// the GPU is sampling the data in the order BGRA. Use -1 for "ignored"
|
||||
// components.
|
||||
int components; // number of relevant components
|
||||
int component_mapping[4]; // semantic index of each component
|
||||
|
||||
// Controls the sample offset, relative to the "reference" dimensions. For
|
||||
// an example of what to set here, see `pl_chroma_location_offset`. Note
|
||||
// that this is given in unit of reference pixels. For a graphical example,
|
||||
// imagine you have a 2x2 image with a 1x1 (subsampled) plane. Without any
|
||||
// shift (0.0), the situation looks like this:
|
||||
//
|
||||
// X-------X X = reference pixel
|
||||
// | | P = plane pixel
|
||||
// | P |
|
||||
// | |
|
||||
// X-------X
|
||||
//
|
||||
// For 4:2:0 subsampling, this corresponds to PL_CHROMA_CENTER. If the
|
||||
// shift_x was instead set to -0.5, the `P` pixel would be offset to the
|
||||
// left by half the separation between the reference (`X` pixels), resulting
|
||||
// in the following:
|
||||
//
|
||||
// X-------X X = reference pixel
|
||||
// | | P = plane pixel
|
||||
// P |
|
||||
// | |
|
||||
// X-------X
|
||||
//
|
||||
// For 4:2:0 subsampling, this corresponds to PL_CHROMA_LEFT.
|
||||
//
|
||||
// Note: It's recommended to fill this using `pl_chroma_location_offset` on
|
||||
// the chroma planes.
|
||||
float shift_x, shift_y;
|
||||
};
|
||||
|
||||
enum pl_overlay_mode {
|
||||
PL_OVERLAY_NORMAL = 0, // treat the texture as a normal, full-color texture
|
||||
PL_OVERLAY_MONOCHROME, // treat the texture as a single-component alpha map
|
||||
PL_OVERLAY_MODE_COUNT,
|
||||
};
|
||||
|
||||
enum pl_overlay_coords {
|
||||
PL_OVERLAY_COORDS_AUTO = 0, // equal to SRC/DST_FRAME, respectively
|
||||
PL_OVERLAY_COORDS_SRC_FRAME, // relative to the raw src frame
|
||||
PL_OVERLAY_COORDS_SRC_CROP, // relative to the src frame crop
|
||||
PL_OVERLAY_COORDS_DST_FRAME, // relative to the raw dst frame
|
||||
PL_OVERLAY_COORDS_DST_CROP, // relative to the dst frame crop
|
||||
PL_OVERLAY_COORDS_COUNT,
|
||||
|
||||
// Note on rotations: If there is an end-to-end rotation between `src` and
|
||||
// `dst`, then any overlays relative to SRC_FRAME or SRC_CROP will be
|
||||
// rotated alongside the image, while overlays relative to DST_FRAME or
|
||||
// DST_CROP will not.
|
||||
};
|
||||
|
||||
struct pl_overlay_part {
|
||||
pl_rect2df src; // source coordinate with respect to `pl_overlay.tex`
|
||||
pl_rect2df dst; // target coordinates with respect to `pl_overlay.coords`
|
||||
|
||||
// If `mode` is PL_OVERLAY_MONOCHROME, then this specifies the color of
|
||||
// this overlay part. The color is multiplied into the sampled texture's
|
||||
// first channel.
|
||||
float color[4];
|
||||
};
|
||||
|
||||
// A struct representing an image overlay (e.g. for subtitles or on-screen
|
||||
// status messages, controls, ...)
|
||||
struct pl_overlay {
|
||||
// The texture containing the backing data for overlay parts. Must have
|
||||
// `params.sampleable` set.
|
||||
pl_tex tex;
|
||||
|
||||
// This controls the coloring mode of this overlay.
|
||||
enum pl_overlay_mode mode;
|
||||
|
||||
// Controls which coordinates this overlay is addressed relative to.
|
||||
enum pl_overlay_coords coords;
|
||||
|
||||
// This controls the colorspace information for this overlay. The contents
|
||||
// of the texture / the value of `color` are interpreted according to this.
|
||||
struct pl_color_repr repr;
|
||||
struct pl_color_space color;
|
||||
|
||||
// The number of parts for this overlay.
|
||||
const struct pl_overlay_part *parts;
|
||||
int num_parts;
|
||||
};
|
||||
|
||||
// High-level description of a complete frame, including metadata and planes
|
||||
struct pl_frame {
|
||||
// Each frame is split up into some number of planes, each of which may
|
||||
// carry several components and be of any size / offset.
|
||||
int num_planes;
|
||||
struct pl_plane planes[PL_MAX_PLANES];
|
||||
|
||||
// For interlaced frames. If set, this `pl_frame` corresponds to a single
|
||||
// field of the underlying source textures. `first_field` indicates which
|
||||
// of these fields is ordered first in time. `prev` and `next` should point
|
||||
// to the previous/next frames in the file, or NULL if there are none.
|
||||
//
|
||||
// Note: Setting these fields on the render target has no meaning and will
|
||||
// be ignored.
|
||||
enum pl_field field;
|
||||
enum pl_field first_field;
|
||||
const struct pl_frame *prev, *next;
|
||||
|
||||
// If set, will be called immediately before GPU access to this frame. This
|
||||
// function *may* be used to, for example, perform synchronization with
|
||||
// external APIs (e.g. `pl_vulkan_hold/release`). If your mapping requires
|
||||
// a memcpy of some sort (e.g. pl_tex_transfer), users *should* instead do
|
||||
// the memcpy up-front and avoid the use of these callbacks - because they
|
||||
// might be called multiple times on the same frame.
|
||||
//
|
||||
// This function *may* arbitrarily mutate the `pl_frame`, but it *should*
|
||||
// ideally only update `planes` - in particular, color metadata and so
|
||||
// forth should be provided up-front as best as possible. Note that changes
|
||||
// here will not be reflected back to the structs provided in the original
|
||||
// `pl_render_*` call (e.g. via `pl_frame_mix`).
|
||||
//
|
||||
// Note: Unless dealing with interlaced frames, only one frame will ever be
|
||||
// acquired at a time per `pl_render_*` call. So users *can* safely use
|
||||
// this with, for example, hwdec mappers that can only map a single frame
|
||||
// at a time. When using this with, for example, `pl_render_image_mix`,
|
||||
// each frame to be blended is acquired and release in succession, before
|
||||
// moving on to the next frame. For interlaced frames, the previous and
|
||||
// next frames must also be acquired simultaneously.
|
||||
bool (*acquire)(pl_gpu gpu, struct pl_frame *frame);
|
||||
|
||||
// If set, will be called after a plane is done being used by the GPU,
|
||||
// *including* after any errors (e.g. `acquire` returning false).
|
||||
void (*release)(pl_gpu gpu, struct pl_frame *frame);
|
||||
|
||||
// Color representation / encoding / semantics of this frame.
|
||||
struct pl_color_repr repr;
|
||||
struct pl_color_space color;
|
||||
|
||||
// Optional ICC profile associated with this frame.
|
||||
pl_icc_object icc;
|
||||
|
||||
// Alternative to `icc`, this can be used in cases where allocating and
|
||||
// tracking an pl_icc_object externally may be inconvenient. The resulting
|
||||
// profile will be managed internally by the pl_renderer.
|
||||
struct pl_icc_profile profile;
|
||||
|
||||
// Optional LUT associated with this frame.
|
||||
const struct pl_custom_lut *lut;
|
||||
enum pl_lut_type lut_type;
|
||||
|
||||
// The logical crop / rectangle containing the valid information, relative
|
||||
// to the reference plane's dimensions (e.g. luma). Pixels outside of this
|
||||
// rectangle will ostensibly be ignored, but note that this is not a hard
|
||||
// guarantee. In particular, scaler filters may end up sampling outside of
|
||||
// this crop. This rect may be flipped, and may be partially or wholly
|
||||
// outside the bounds of the underlying textures. (Optional)
|
||||
//
|
||||
// Note that `pl_render_image` will map the input crop directly to the
|
||||
// output crop, stretching and scaling as needed. If you wish to preserve
|
||||
// the aspect ratio, use a dedicated function like pl_rect2df_aspect_copy.
|
||||
pl_rect2df crop;
|
||||
|
||||
// Logical rotation of the image, with respect to the underlying planes.
|
||||
// For example, if this is PL_ROTATION_90, then the image will be rotated
|
||||
// to the right by 90° when mapping to `crop`. The actual position on-screen
|
||||
// is unaffected, so users should ensure that the (rotated) aspect ratio
|
||||
// matches the source. (Or use a helper like `pl_rect2df_aspect_set_rot`)
|
||||
//
|
||||
// Note: For `target` frames, this corresponds to a rotation of the
|
||||
// display, for `image` frames, this corresponds to a rotation of the
|
||||
// camera.
|
||||
//
|
||||
// So, as an example, target->rotation = PL_ROTATE_90 means the end user
|
||||
// has rotated the display to the right by 90° (meaning rendering will be
|
||||
// rotated 90° to the *left* to compensate), and image->rotation =
|
||||
// PL_ROTATE_90 means the video provider has rotated the camera to the
|
||||
// right by 90° (so rendering will be rotated 90° to the *right* to
|
||||
// compensate).
|
||||
pl_rotation rotation;
|
||||
|
||||
// A list of additional overlays associated with this frame. Note that will
|
||||
// be rendered directly onto intermediate/cache frames, so changing any of
|
||||
// these overlays may require flushing the renderer cache.
|
||||
const struct pl_overlay *overlays;
|
||||
int num_overlays;
|
||||
|
||||
// Note on subsampling and plane correspondence: All planes belonging to
|
||||
// the same frame will only be stretched by an integer multiple (or inverse
|
||||
// thereof) in order to match the reference dimensions of this image. For
|
||||
// example, suppose you have an 8x4 image. A valid plane scaling would be
|
||||
// 4x2 -> 8x4 or 4x4 -> 4x4, but not 6x4 -> 8x4. So if a 6x4 plane is
|
||||
// given, then it would be treated like a cropped 8x4 plane (since 1.0 is
|
||||
// the closest scaling ratio to the actual ratio of 1.3).
|
||||
//
|
||||
// For an explanation of why this makes sense, consider the relatively
|
||||
// common example of a subsampled, oddly sized (e.g. jpeg) image. In such
|
||||
// cases, for example a 35x23 image, the 4:2:0 subsampled chroma plane
|
||||
// would have to end up as 17.5x11.5, which gets rounded up to 18x12 by
|
||||
// implementations. So in this example, the 18x12 chroma plane would get
|
||||
// treated by libplacebo as an oversized chroma plane - i.e. the plane
|
||||
// would get sampled as if it was 17.5 pixels wide and 11.5 pixels large.
|
||||
|
||||
// Associated film grain data (see <libplacebo/shaders/film_grain.h>).
|
||||
//
|
||||
// Note: This is ignored for the `target` of `pl_render_image`, since
|
||||
// un-applying grain makes little sense.
|
||||
struct pl_film_grain_data film_grain;
|
||||
|
||||
// Ignored by libplacebo. May be useful for users.
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
// Helper function to infer the chroma location offset for each plane in a
|
||||
// frame. This is equivalent to calling `pl_chroma_location_offset` on all
|
||||
// subsampled planes' shift_x/shift_y variables.
|
||||
PL_API void pl_frame_set_chroma_location(struct pl_frame *frame,
|
||||
enum pl_chroma_location chroma_loc);
|
||||
|
||||
// Fills in a `pl_frame` based on a swapchain frame's FBO and metadata.
|
||||
PL_API void pl_frame_from_swapchain(struct pl_frame *out_frame,
|
||||
const struct pl_swapchain_frame *frame);
|
||||
|
||||
// Helper function to determine if a frame is logically cropped or not. In
|
||||
// particular, this is useful in determining whether or not an output frame
|
||||
// needs to be cleared before rendering or not.
|
||||
PL_API bool pl_frame_is_cropped(const struct pl_frame *frame);
|
||||
|
||||
// Helper function to reset a frame to a given RGB color. If the frame's
|
||||
// color representation is something other than RGB, the clear color will
|
||||
// be adjusted accordingly. `clear_color` should be non-premultiplied.
|
||||
PL_API void pl_frame_clear_rgba(pl_gpu gpu, const struct pl_frame *frame,
|
||||
const float clear_color[4]);
|
||||
|
||||
// Like `pl_frame_clear_rgba` but without an alpha channel.
|
||||
static inline void pl_frame_clear(pl_gpu gpu, const struct pl_frame *frame,
|
||||
const float clear_color[3])
|
||||
{
|
||||
const float clear_color_rgba[4] = { clear_color[0], clear_color[1], clear_color[2], 1.0 };
|
||||
pl_frame_clear_rgba(gpu, frame, clear_color_rgba);
|
||||
}
|
||||
|
||||
// Helper functions to return the fixed/inferred pl_frame parameters used
|
||||
// for rendering internally. Mutates `image` and `target` in-place to hold
|
||||
// the modified values, which are what will actually be used for rendering.
|
||||
//
|
||||
// This currently includes:
|
||||
// - Defaulting all missing pl_color_space/repr parameters
|
||||
// - Coalescing all rotation to the target
|
||||
// - Rounding and clamping the target crop to pixel boundaries and adjusting the
|
||||
// image crop correspondingly
|
||||
//
|
||||
// Note: This is idempotent and does not generally alter the effects of a
|
||||
// subsequent `pl_render_image` on the same pl_frame pair. (But see the
|
||||
// following warning)
|
||||
//
|
||||
// Warning: This does *not* call pl_frame.acquire/release, and so the returned
|
||||
// metadata *may* be incorrect if the acquire callback mutates the pl_frame in
|
||||
// nontrivial ways, in particular the crop and color space fields.
|
||||
PL_API void pl_frames_infer(pl_renderer rr, struct pl_frame *image,
|
||||
struct pl_frame *target);
|
||||
|
||||
|
||||
// Render a single image to a target using the given parameters. This is
|
||||
// fully dynamic, i.e. the params can change at any time. libplacebo will
|
||||
// internally detect and flush whatever caches are invalidated as a result of
|
||||
// changing colorspace, size etc.
|
||||
//
|
||||
// Required plane capabilities:
|
||||
// - Planes in `image` must be `sampleable`
|
||||
// - Planes in `target` must be `renderable`
|
||||
//
|
||||
// Recommended plane capabilities: (Optional, but good for performance)
|
||||
// - Planes in `image` should have `sample_mode` PL_TEX_SAMPLE_LINEAR
|
||||
// - Planes in `target` should be `storable`
|
||||
// - Planes in `target` should have `blit_dst`
|
||||
//
|
||||
// Note on lifetime: Once this call returns, the passed structures may be
|
||||
// freely overwritten or discarded by the caller, even the referenced
|
||||
// `pl_tex` objects may be freely reused.
|
||||
//
|
||||
// Note: `image` may be NULL, in which case `target.overlays` will still be
|
||||
// rendered, but nothing else.
|
||||
PL_API bool pl_render_image(pl_renderer rr, const struct pl_frame *image,
|
||||
const struct pl_frame *target,
|
||||
const struct pl_render_params *params);
|
||||
|
||||
// Flushes the internal state of this renderer. This is normally not needed,
|
||||
// even if the image parameters, colorspace or target configuration change,
|
||||
// since libplacebo will internally detect such circumstances and recreate
|
||||
// outdated resources automatically. Doing this explicitly *may* be useful to
|
||||
// purge some state related to things like HDR peak detection or frame mixing,
|
||||
// so calling it is a good idea if the content source is expected to change
|
||||
// dramatically (e.g. when switching to a different file).
|
||||
PL_API void pl_renderer_flush_cache(pl_renderer rr);
|
||||
|
||||
// Mirrors `pl_get_detected_hdr_metadata`, giving you the current internal peak
|
||||
// detection HDR metadata (when peak detection is active). Returns false if no
|
||||
// information is available (e.g. not HDR source, peak detection disabled).
|
||||
PL_API bool pl_renderer_get_hdr_metadata(pl_renderer rr,
|
||||
struct pl_hdr_metadata *metadata);
|
||||
|
||||
// Represents a mixture of input frames, distributed temporally.
|
||||
//
|
||||
// NOTE: Frames must be sorted by timestamp, i.e. `timestamps` must be
|
||||
// monotonically increasing.
|
||||
struct pl_frame_mix {
|
||||
// The number of frames in this mixture. The number of frames should be
|
||||
// sufficient to meet the needs of the configured frame mixer. See the
|
||||
// section below for more information.
|
||||
//
|
||||
// If the number of frames is 0, this call will be equivalent to
|
||||
// `pl_render_image` with `image == NULL`.
|
||||
int num_frames;
|
||||
|
||||
// A list of the frames themselves. The frames can have different
|
||||
// colorspaces, configurations of planes, or even sizes.
|
||||
//
|
||||
// Note: This is a list of pointers, to avoid users having to copy
|
||||
// around `pl_frame` structs when re-organizing this array.
|
||||
const struct pl_frame **frames;
|
||||
|
||||
// A list of unique signatures, one for each frame. These are used to
|
||||
// identify frames across calls to this function, so it's crucial that they
|
||||
// be both unique per-frame but also stable across invocations of
|
||||
// `pl_render_frame_mix`.
|
||||
const uint64_t *signatures;
|
||||
|
||||
// A list of relative timestamps for each frame. These are relative to the
|
||||
// time of the vsync being drawn, i.e. this function will render the frame
|
||||
// that will be made visible at timestamp 0.0. The values are expected to
|
||||
// be normalized such that a separation of 1.0 corresponds to roughly one
|
||||
// nominal source frame duration. So a constant framerate video file will
|
||||
// always have timestamps like e.g. {-2.3, -1.3, -0.3, 0.7, 1.7, 2.7},
|
||||
// using an example radius of 3.
|
||||
//
|
||||
// In cases where the framerate is variable (e.g. VFR video), the choice of
|
||||
// what to scale to use can be difficult to answer. A typical choice would
|
||||
// be either to use the canonical (container-tagged) framerate, or the
|
||||
// highest momentary framerate, as a reference. If all else fails, you
|
||||
// could also use the display's framerate.
|
||||
//
|
||||
// Note: This function assumes zero-order-hold semantics, i.e. the frame at
|
||||
// timestamp 0.7 is intended to remain visible until timestamp 1.7, when
|
||||
// the next frame replaces it.
|
||||
const float *timestamps;
|
||||
|
||||
// The duration for which the vsync being drawn will be held, using the
|
||||
// same scale as `timestamps`. If the display has an unknown or variable
|
||||
// frame-rate (e.g. Adaptive Sync), then you're probably better off not
|
||||
// using this function and instead just painting the frames directly using
|
||||
// `pl_render_frame` at the correct PTS.
|
||||
//
|
||||
// As an example, if `vsync_duration` is 0.4, then it's assumed that the
|
||||
// vsync being painted is visible for the period [0.0, 0.4].
|
||||
float vsync_duration;
|
||||
|
||||
// Explanation of the frame mixing radius: The algorithm chosen in
|
||||
// `pl_render_params.frame_mixer` has a canonical radius equal to
|
||||
// `pl_filter_config.kernel->radius`. This means that the frame mixing
|
||||
// algorithm will (only) need to consult all of the frames that have a
|
||||
// distance within the interval [-radius, radius]. As such, the user should
|
||||
// include all such frames in `frames`, but may prune or omit frames that
|
||||
// lie outside it.
|
||||
//
|
||||
// The built-in frame mixing (`pl_render_params.frame_mixer == NULL`) has
|
||||
// no concept of radius, it just always needs access to the "current" and
|
||||
// "next" frames.
|
||||
};
|
||||
|
||||
// Helper function to calculate the base frame mixing radius.
|
||||
//
|
||||
// Note: When the source FPS exceeds the display FPS, this radius must be
|
||||
// increased by the corresponding ratio.
|
||||
static inline float pl_frame_mix_radius(const struct pl_render_params *params)
|
||||
{
|
||||
// For backwards compatibility, allow !frame_mixer->kernel
|
||||
if (!params->frame_mixer || !params->frame_mixer->kernel)
|
||||
return 0.0;
|
||||
|
||||
return params->frame_mixer->kernel->radius;
|
||||
}
|
||||
|
||||
// Find closest frame to current PTS by zero-order hold semantics, or NULL.
|
||||
PL_API const struct pl_frame *pl_frame_mix_current(const struct pl_frame_mix *mix);
|
||||
|
||||
// Find closest frame to current PTS by nearest neighbour semantics, or NULL.
|
||||
PL_API const struct pl_frame *pl_frame_mix_nearest(const struct pl_frame_mix *mix);
|
||||
|
||||
// Render a mixture of images to the target using the given parameters. This
|
||||
// functions much like a generalization of `pl_render_image`, for when the API
|
||||
// user has more control over the frame queue / vsync loop, and can provide a
|
||||
// few frames from the past and future + timestamp information.
|
||||
//
|
||||
// This allows libplacebo to perform rudimentary frame mixing / interpolation,
|
||||
// in order to eliminate judder artifacts typically associated with
|
||||
// source/display frame rate mismatch.
|
||||
PL_API bool pl_render_image_mix(pl_renderer rr, const struct pl_frame_mix *images,
|
||||
const struct pl_frame *target,
|
||||
const struct pl_render_params *params);
|
||||
|
||||
// Analog of `pl_frame_infer` corresponding to `pl_render_image_mix`. This
|
||||
// function will *not* mutate the frames contained in `mix`, and instead
|
||||
// return an adjusted copy of the "reference" frame for that image mix in
|
||||
// `out_refimage`, or {0} if the mix is empty.
|
||||
PL_API void pl_frames_infer_mix(pl_renderer rr, const struct pl_frame_mix *mix,
|
||||
struct pl_frame *target, struct pl_frame *out_ref);
|
||||
|
||||
// Backwards compatibility with old filters API, may be deprecated.
|
||||
// Redundant with pl_filter_configs and masking `allowed` for
|
||||
// PL_FILTER_SCALING and PL_FILTER_FRAME_MIXING respectively.
|
||||
|
||||
// A list of recommended frame mixer presets, terminated by {0}
|
||||
PL_API extern const struct pl_filter_preset pl_frame_mixers[];
|
||||
PL_API extern const int pl_num_frame_mixers; // excluding trailing {0}
|
||||
|
||||
// A list of recommended scaler presets, terminated by {0}. This is almost
|
||||
// equivalent to `pl_filter_presets` with the exception of including extra
|
||||
// built-in filters that don't map to the `pl_filter` architecture.
|
||||
PL_API extern const struct pl_filter_preset pl_scale_filters[];
|
||||
PL_API extern const int pl_num_scale_filters; // excluding trailing {0}
|
||||
|
||||
// Deprecated in favor of `pl_cache_save/pl_cache_load` on the `pl_cache`
|
||||
// associated with the `pl_gpu` this renderer is using.
|
||||
PL_DEPRECATED PL_API size_t pl_renderer_save(pl_renderer rr, uint8_t *out_cache);
|
||||
PL_DEPRECATED PL_API void pl_renderer_load(pl_renderer rr, const uint8_t *cache);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_RENDERER_H_
|
||||
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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_SHADERS_H_
|
||||
#define LIBPLACEBO_SHADERS_H_
|
||||
|
||||
// This function defines the "direct" interface to libplacebo's GLSL shaders,
|
||||
// suitable for use in contexts where the user controls GLSL shader compilation
|
||||
// but wishes to include functions generated by libplacebo as part of their
|
||||
// own rendering process. This API is normally not used for operation with
|
||||
// libplacebo's higher-level constructs such as `pl_dispatch` or `pl_renderer`.
|
||||
|
||||
#include <libplacebo/gpu.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Thread-safety: Unsafe
|
||||
typedef struct pl_shader_t *pl_shader;
|
||||
|
||||
struct pl_shader_params {
|
||||
// The `id` represents an abstract identifier for the shader, to avoid
|
||||
// collisions with other shaders being used as part of the same larger,
|
||||
// overarching shader. This is relevant for users which want to combine
|
||||
// multiple `pl_shader` objects together, in which case all `pl_shader`
|
||||
// objects should have a unique `id`.
|
||||
uint8_t id;
|
||||
|
||||
// If `gpu` is non-NULL, then this `gpu` will be used to create objects
|
||||
// such as textures and buffers, or check for required capabilities, for
|
||||
// operations which depend on either of those. This is fully optional, i.e.
|
||||
// these GLSL primitives are designed to be used without a dependency on
|
||||
// `gpu` wherever possible - however, some features may not work, and will
|
||||
// be disabled even if requested.
|
||||
pl_gpu gpu;
|
||||
|
||||
// The `index` represents an abstract frame index, which shaders may use
|
||||
// internally to do things like temporal dithering or seeding PRNGs. If the
|
||||
// user does not care about temporal dithering/debanding, or wants
|
||||
// deterministic rendering, this may safely be left as 0. Otherwise, it
|
||||
// should be incremented by 1 on successive frames.
|
||||
uint8_t index;
|
||||
|
||||
// If `glsl.version` is nonzero, then this structure will be used to
|
||||
// determine the effective GLSL mode and capabilities. If `gpu` is also
|
||||
// set, then this overrides `gpu->glsl`.
|
||||
struct pl_glsl_version glsl;
|
||||
|
||||
// If this is true, all constants in the shader will be replaced by
|
||||
// dynamic variables. This is mainly useful to avoid recompilation for
|
||||
// shaders which expect to have their values change constantly.
|
||||
bool dynamic_constants;
|
||||
};
|
||||
|
||||
#define pl_shader_params(...) (&(struct pl_shader_params) { __VA_ARGS__ })
|
||||
|
||||
// Creates a new, blank, mutable pl_shader object.
|
||||
//
|
||||
// Note: Rather than allocating and destroying many shaders, users are
|
||||
// encouraged to reuse them (using `pl_shader_reset`) for efficiency.
|
||||
PL_API pl_shader pl_shader_alloc(pl_log log, const struct pl_shader_params *params);
|
||||
|
||||
// Frees a pl_shader and all resources associated with it.
|
||||
PL_API void pl_shader_free(pl_shader *sh);
|
||||
|
||||
// Resets a pl_shader to a blank slate, without releasing internal memory.
|
||||
// If you're going to be re-generating shaders often, this function will let
|
||||
// you skip the re-allocation overhead.
|
||||
PL_API void pl_shader_reset(pl_shader sh, const struct pl_shader_params *params);
|
||||
|
||||
// Returns whether or not a shader is in a "failed" state. Trying to modify a
|
||||
// shader in illegal ways (e.g. signature mismatch) will result in the shader
|
||||
// being marked as "failed". Since most pl_shader_ operations have a void
|
||||
// return type, the user can use this function to figure out whether a specific
|
||||
// shader operation has failed or not. This function is somewhat redundant
|
||||
// since `pl_shader_finalize` will also return NULL in this case.
|
||||
PL_API bool pl_shader_is_failed(const pl_shader sh);
|
||||
|
||||
// Returns whether or not a pl_shader needs to be run as a compute shader. This
|
||||
// will never be the case unless the `pl_glsl_version` this `pl_shader` was
|
||||
// created using has `compute` support enabled.
|
||||
PL_API bool pl_shader_is_compute(const pl_shader sh);
|
||||
|
||||
// Returns whether or not the shader has any particular output size
|
||||
// requirements. Some shaders, in particular those that sample from other
|
||||
// textures, have specific output size requirements which need to be respected
|
||||
// by the caller. If this is false, then the shader is compatible with every
|
||||
// output size. If true, the size requirements are stored into *w and *h.
|
||||
PL_API bool pl_shader_output_size(const pl_shader sh, int *w, int *h);
|
||||
|
||||
// Indicates the type of signature that is associated with a shader result.
|
||||
// Every shader result defines a function that may be called by the user, and
|
||||
// this enum indicates the type of value that this function takes and/or
|
||||
// returns.
|
||||
//
|
||||
// Which signature a shader ends up with depends on the type of operation being
|
||||
// performed by a shader fragment, as determined by the user's calls. See below
|
||||
// for more information.
|
||||
enum pl_shader_sig {
|
||||
PL_SHADER_SIG_NONE = 0, // no input / void output
|
||||
PL_SHADER_SIG_COLOR, // vec4 color (normalized so that 1.0 is the ref white)
|
||||
|
||||
// The following are only valid as input signatures:
|
||||
PL_SHADER_SIG_SAMPLER, // (gsampler* src_tex, vecN tex_coord) pair,
|
||||
// specifics depend on how the shader was generated
|
||||
};
|
||||
|
||||
// Structure encapsulating information about a shader. This is internally
|
||||
// refcounted, to allow moving it around without having to create deep copies.
|
||||
typedef const struct pl_shader_info_t {
|
||||
// A copy of the parameters used to create the shader.
|
||||
struct pl_shader_params params;
|
||||
|
||||
// A list of friendly names for the semantic operations being performed by
|
||||
// this shader, e.g. "color decoding" or "debanding".
|
||||
const char **steps;
|
||||
int num_steps;
|
||||
|
||||
// As a convenience, this contains a pretty-printed version of the
|
||||
// above list, with entries tallied and separated by commas
|
||||
const char *description;
|
||||
} *pl_shader_info;
|
||||
|
||||
PL_API pl_shader_info pl_shader_info_ref(pl_shader_info info);
|
||||
PL_API void pl_shader_info_deref(pl_shader_info *info);
|
||||
|
||||
// Represents a finalized shader fragment. This is not a complete shader, but a
|
||||
// collection of raw shader text together with description of the input
|
||||
// attributes, variables and vertices it expects to be available.
|
||||
struct pl_shader_res {
|
||||
// Descriptive information about the shader. Note that this reference is
|
||||
// attached to the shader itself - the user does not need to manually ref
|
||||
// or deref `info` unless they wish to move it elsewhere.
|
||||
pl_shader_info info;
|
||||
|
||||
// The shader text, as literal GLSL. This will always be a function
|
||||
// definition, such that the the function with the indicated name and
|
||||
// signature may be called by the user.
|
||||
const char *glsl;
|
||||
const char *name;
|
||||
enum pl_shader_sig input; // what the function expects
|
||||
enum pl_shader_sig output; // what the function returns
|
||||
|
||||
// For compute shaders (pl_shader_is_compute), this indicates the requested
|
||||
// work group size. Otherwise, both fields are 0. The interpretation of
|
||||
// these work groups is that they're tiled across the output image.
|
||||
int compute_group_size[2];
|
||||
|
||||
// If this pass is a compute shader, this field indicates the shared memory
|
||||
// size requirements for this shader pass.
|
||||
size_t compute_shmem;
|
||||
|
||||
// A set of input vertex attributes needed by this shader fragment.
|
||||
const struct pl_shader_va *vertex_attribs;
|
||||
int num_vertex_attribs;
|
||||
|
||||
// A set of input variables needed by this shader fragment.
|
||||
const struct pl_shader_var *variables;
|
||||
int num_variables;
|
||||
|
||||
// A list of input descriptors needed by this shader fragment,
|
||||
const struct pl_shader_desc *descriptors;
|
||||
int num_descriptors;
|
||||
|
||||
// A list of compile-time constants used by this shader fragment.
|
||||
const struct pl_shader_const *constants;
|
||||
int num_constants;
|
||||
|
||||
// --- Deprecated fields (see `info`)
|
||||
struct pl_shader_params params PL_DEPRECATED;
|
||||
const char **steps PL_DEPRECATED;
|
||||
int num_steps PL_DEPRECATED;
|
||||
const char *description PL_DEPRECATED;
|
||||
};
|
||||
|
||||
// Represents a vertex attribute. The four values will be bound to the four
|
||||
// corner vertices respectively, in row-wise order starting from the top left:
|
||||
// data[0] data[1]
|
||||
// data[2] data[3]
|
||||
struct pl_shader_va {
|
||||
struct pl_vertex_attrib attr; // VA type, excluding `offset` and `location`
|
||||
const void *data[4];
|
||||
};
|
||||
|
||||
// Represents a bound shared variable / descriptor
|
||||
struct pl_shader_var {
|
||||
struct pl_var var; // the underlying variable description
|
||||
const void *data; // the raw data (as per `pl_var_host_layout`)
|
||||
bool dynamic; // if true, the value is expected to change frequently
|
||||
};
|
||||
|
||||
struct pl_buffer_var {
|
||||
struct pl_var var;
|
||||
struct pl_var_layout layout;
|
||||
};
|
||||
|
||||
typedef uint16_t pl_memory_qualifiers;
|
||||
enum {
|
||||
PL_MEMORY_COHERENT = 1 << 0, // supports synchronization across shader invocations
|
||||
PL_MEMORY_VOLATILE = 1 << 1, // all writes are synchronized automatically
|
||||
|
||||
// Note: All descriptors are also implicitly assumed to have the 'restrict'
|
||||
// memory qualifier. There is currently no way to override this behavior.
|
||||
};
|
||||
|
||||
struct pl_shader_desc {
|
||||
struct pl_desc desc; // descriptor type, excluding `int binding`
|
||||
struct pl_desc_binding binding; // contents of the descriptor binding
|
||||
|
||||
// For PL_DESC_BUF_UNIFORM/STORAGE, this specifies the layout of the
|
||||
// variables contained by a buffer. Ignored for the other descriptor types
|
||||
struct pl_buffer_var *buffer_vars;
|
||||
int num_buffer_vars;
|
||||
|
||||
// For storage images and buffers, this specifies additional memory
|
||||
// qualifiers on the descriptor. It's highly recommended to always use
|
||||
// at least PL_MEMORY_RESTRICT. Ignored for other descriptor types.
|
||||
pl_memory_qualifiers memory;
|
||||
};
|
||||
|
||||
// Represents a compile-time constant. This can be lowered to a specialization
|
||||
// constant to support cheaper recompilations.
|
||||
struct pl_shader_const {
|
||||
enum pl_var_type type;
|
||||
const char *name;
|
||||
const void *data;
|
||||
|
||||
// If true, this constant *must* be a compile-time constant, which
|
||||
// basically just overrides `pl_shader_params.dynamic_constants`. Useful
|
||||
// for constants which will serve as inputs to e.g. array sizes.
|
||||
bool compile_time;
|
||||
};
|
||||
|
||||
// Finalize a pl_shader. It is no longer mutable at this point, and any further
|
||||
// attempts to modify it result in an error. (Functions which take a `const
|
||||
// pl_shader` argument do not modify the shader and may be freely
|
||||
// called on an already-finalized shader)
|
||||
//
|
||||
// The returned pl_shader_res is bound to the lifetime of the pl_shader - and
|
||||
// will only remain valid until the pl_shader is freed or reset. This function
|
||||
// may be called multiple times, and will produce the same result each time.
|
||||
//
|
||||
// This function will return NULL if the shader is considered to be in a
|
||||
// "failed" state (see pl_shader_is_failed).
|
||||
PL_API const struct pl_shader_res *pl_shader_finalize(pl_shader sh);
|
||||
|
||||
// Shader objects represent abstract resources that shaders need to manage in
|
||||
// order to ensure their operation. This could include shader storage buffers,
|
||||
// generated lookup textures, or other sorts of configured state. The body
|
||||
// of a shader object is fully opaque; but the user is in charge of cleaning up
|
||||
// after them and passing them to the right shader passes.
|
||||
//
|
||||
// Note: pl_shader_obj objects must be initialized to NULL by the caller.
|
||||
typedef struct pl_shader_obj_t *pl_shader_obj;
|
||||
|
||||
PL_API void pl_shader_obj_destroy(pl_shader_obj *obj);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_H_
|
||||
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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_SHADERS_COLORSPACE_H_
|
||||
#define LIBPLACEBO_SHADERS_COLORSPACE_H_
|
||||
|
||||
// Color space transformation shaders. These all input and output a color
|
||||
// value (PL_SHADER_SIG_COLOR).
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/gamut_mapping.h>
|
||||
#include <libplacebo/tone_mapping.h>
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
// For backwards compatibility
|
||||
#include <libplacebo/shaders/dithering.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Transform the input color, in its given representation, to ensure
|
||||
// compatibility with the indicated alpha mode. Mutates `repr` to reflect the
|
||||
// change. Note that this is a no-op if the input is PL_ALPHA_UNKNOWN.
|
||||
PL_API void pl_shader_set_alpha(pl_shader sh, struct pl_color_repr *repr,
|
||||
enum pl_alpha_mode mode);
|
||||
|
||||
// Colorspace reshaping for PL_COLOR_SYSTEM_DOLBYVISION. Note that this is done
|
||||
// automatically by `pl_shader_decode_color` for PL_COLOR_SYSTEM_DOLBYVISION.
|
||||
PL_API void pl_shader_dovi_reshape(pl_shader sh, const struct pl_dovi_metadata *data);
|
||||
|
||||
// Decode the color into normalized RGB, given a specified color_repr. This
|
||||
// also takes care of additional pre- and post-conversions requires for the
|
||||
// "special" color systems (XYZ, BT.2020-C, etc.). If `params` is left as NULL,
|
||||
// it defaults to &pl_color_adjustment_neutral.
|
||||
//
|
||||
// Note: This function always returns PC-range RGB with independent alpha.
|
||||
// It mutates the pl_color_repr to reflect the change.
|
||||
//
|
||||
// Note: For DCDM XYZ decoding output is linear
|
||||
PL_API void pl_shader_decode_color(pl_shader sh, struct pl_color_repr *repr,
|
||||
const struct pl_color_adjustment *params);
|
||||
|
||||
// Encodes a color from normalized, PC-range, independent alpha RGB into a
|
||||
// given representation. That is, this performs the inverse operation of
|
||||
// `pl_shader_decode_color` (sans color adjustments).
|
||||
//
|
||||
// Note: For DCDM XYZ encoding input is expected to be linear
|
||||
PL_API void pl_shader_encode_color(pl_shader sh, const struct pl_color_repr *repr);
|
||||
|
||||
// Linearize (expand) `vec4 color`, given a specified color space. In essence,
|
||||
// this corresponds to the ITU-R EOTF.
|
||||
//
|
||||
// Note: Unlike the ITU-R EOTF, it never includes the OOTF - even for systems
|
||||
// where the EOTF includes the OOTF (such as HLG).
|
||||
PL_API void pl_shader_linearize(pl_shader sh, const struct pl_color_space *csp);
|
||||
|
||||
// Delinearize (compress), given a color space as output. This loosely
|
||||
// corresponds to the inverse EOTF (not the OETF) in ITU-R terminology, again
|
||||
// assuming a reference monitor.
|
||||
PL_API void pl_shader_delinearize(pl_shader sh, const struct pl_color_space *csp);
|
||||
|
||||
struct pl_sigmoid_params {
|
||||
// The center (bias) of the sigmoid curve. Must be between 0.0 and 1.0.
|
||||
// If left as NULL, defaults to 0.75
|
||||
float center;
|
||||
|
||||
// The slope (steepness) of the sigmoid curve. Must be between 1.0 and 20.0.
|
||||
// If left as NULL, defaults to 6.5.
|
||||
float slope;
|
||||
};
|
||||
|
||||
#define PL_SIGMOID_DEFAULTS \
|
||||
.center = 0.75, \
|
||||
.slope = 6.50,
|
||||
|
||||
#define pl_sigmoid_params(...) (&(struct pl_sigmoid_params) { PL_SIGMOID_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_sigmoid_params pl_sigmoid_default_params;
|
||||
|
||||
// Applies a sigmoidal color transform to all channels. This helps avoid
|
||||
// ringing artifacts during upscaling by bringing the color information closer
|
||||
// to neutral and away from the extremes. If `params` is NULL, it defaults to
|
||||
// &pl_sigmoid_default_params.
|
||||
//
|
||||
// Warning: This function clamps the input to the interval [0,1]; and as such
|
||||
// it should *NOT* be used on already-decoded high-dynamic range content.
|
||||
PL_API void pl_shader_sigmoidize(pl_shader sh, const struct pl_sigmoid_params *params);
|
||||
|
||||
// This performs the inverse operation to `pl_shader_sigmoidize`.
|
||||
PL_API void pl_shader_unsigmoidize(pl_shader sh, const struct pl_sigmoid_params *params);
|
||||
|
||||
struct pl_peak_detect_params {
|
||||
// Smoothing coefficient for the detected values. This controls the time
|
||||
// parameter (tau) of an IIR low pass filter. In other words, it represent
|
||||
// the cutoff period (= 1 / cutoff frequency) in frames. Frequencies below
|
||||
// this length will be suppressed. This helps block out annoying
|
||||
// "sparkling" or "flickering" due to small variations in frame-to-frame
|
||||
// brightness. If left as 0.0, this smoothing is completely disabled.
|
||||
float smoothing_period;
|
||||
|
||||
// In order to avoid reacting sluggishly on scene changes as a result of
|
||||
// the low-pass filter, we disable it when the difference between the
|
||||
// current frame brightness and the average frame brightness exceeds a
|
||||
// given threshold difference. But rather than a single hard cutoff, which
|
||||
// would lead to weird discontinuities on fades, we gradually disable it
|
||||
// over a small window of brightness ranges. These parameters control the
|
||||
// lower and upper bounds of this window, in units of 1% PQ.
|
||||
//
|
||||
// Setting either one of these to 0.0 disables this logic.
|
||||
float scene_threshold_low;
|
||||
float scene_threshold_high;
|
||||
|
||||
// Which percentile of the input image brightness histogram to consider as
|
||||
// the true peak of the scene. If this is set to 100 (or 0), the brightest
|
||||
// pixel is measured. Otherwise, the top of the frequency distribution is
|
||||
// progressively cut off. Setting this too low will cause clipping of very
|
||||
// bright details, but can improve the dynamic brightness range of scenes
|
||||
// with very bright isolated highlights.
|
||||
//
|
||||
// A recommended value is 99.995%, which is very conservative and should
|
||||
// cause no major issues in typical content.
|
||||
float percentile;
|
||||
|
||||
// Allows the peak detection result to be delayed by up to a single frame,
|
||||
// which can sometimes improve thoughput, at the cost of introducing the
|
||||
// possibility of 1-frame flickers on transitions. Disabled by default.
|
||||
bool allow_delayed;
|
||||
|
||||
// --- Deprecated / removed fields
|
||||
float overshoot_margin PL_DEPRECATED;
|
||||
float minimum_peak PL_DEPRECATED;
|
||||
};
|
||||
|
||||
#define PL_PEAK_DETECT_DEFAULTS \
|
||||
.smoothing_period = 20.0f, \
|
||||
.scene_threshold_low = 1.0f, \
|
||||
.scene_threshold_high = 3.0f, \
|
||||
.percentile = 100.0f,
|
||||
|
||||
#define PL_PEAK_DETECT_HQ_DEFAULTS \
|
||||
PL_PEAK_DETECT_DEFAULTS \
|
||||
.percentile = 99.995f,
|
||||
|
||||
#define pl_peak_detect_params(...) (&(struct pl_peak_detect_params) { PL_PEAK_DETECT_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_peak_detect_params pl_peak_detect_default_params;
|
||||
PL_API extern const struct pl_peak_detect_params pl_peak_detect_high_quality_params;
|
||||
|
||||
// This function can be used to measure the CLL and FALL of a video
|
||||
// source automatically, using a compute shader. The measured values are
|
||||
// smoothed automatically (depending on the parameters), so to keep track of
|
||||
// the measured results over time, a tone mapping shader state object is used
|
||||
// to hold the state. Returns false on failure initializing the tone mapping
|
||||
// object, or if compute shaders are not supported.
|
||||
//
|
||||
// It's important that the same shader object is used for successive frames
|
||||
// belonging to the same source. If the source changes (e.g. due to a file
|
||||
// change or seek), the user should reset it with `pl_reset_detected_peak` (or
|
||||
// destroy it and use a new state object).
|
||||
//
|
||||
// The parameter `csp` holds the representation of the color values that are
|
||||
// the input to this function. (They must already be in decoded RGB form, i.e.
|
||||
// alternate color representations are not supported)
|
||||
PL_API bool pl_shader_detect_peak(pl_shader sh, struct pl_color_space csp,
|
||||
pl_shader_obj *state,
|
||||
const struct pl_peak_detect_params *params);
|
||||
|
||||
// After dispatching the above shader, this function can be used to retrieve
|
||||
// the detected dynamic HDR10+ metadata parameters. The other fields of
|
||||
// `metadata` are not written to. Returns whether or not any values were
|
||||
// written. If not, the values are left untouched, so this can be used to
|
||||
// safely update `pl_hdr_metadata` values in-place. This function may or may
|
||||
// not block, depending on the previous setting of `allow_delayed`.
|
||||
PL_API bool pl_get_detected_hdr_metadata(const pl_shader_obj state,
|
||||
struct pl_hdr_metadata *metadata);
|
||||
|
||||
// After dispatching the above shader, this function *may* be used to read out
|
||||
// the detected CLL and FALL directly (in PL_HDR_NORM units). If the shader
|
||||
// has never been dispatched yet, i.e. no information is available, this will
|
||||
// return false.
|
||||
//
|
||||
// Deprecated in favor of `pl_get_detected_hdr_metadata`
|
||||
PL_DEPRECATED PL_API bool pl_get_detected_peak(const pl_shader_obj state,
|
||||
float *out_cll, float *out_fall);
|
||||
|
||||
// Resets the peak detection state in a given tone mapping state object. This
|
||||
// is not equal to `pl_shader_obj_destroy`, because it does not destroy any
|
||||
// state used by `pl_shader_tone_map`.
|
||||
PL_API void pl_reset_detected_peak(pl_shader_obj state);
|
||||
|
||||
// Feature map extraction (for pl_color_map_args.feature_map). The result
|
||||
// of this shader should be downscaled / low-passed to the indicated kernel
|
||||
// size before use. (This does not happen automatically)
|
||||
PL_API void pl_shader_extract_features(pl_shader sh, struct pl_color_space csp);
|
||||
|
||||
// Deprecated and unused. Libplacebo now always performs a variant of the old
|
||||
// hybrid tone-mapping, mixing together the intensity (I) and per-channel (LMS)
|
||||
// results.
|
||||
enum pl_tone_map_mode {
|
||||
PL_TONE_MAP_AUTO PL_DEPRECATED_ENUMERATOR,
|
||||
PL_TONE_MAP_RGB PL_DEPRECATED_ENUMERATOR,
|
||||
PL_TONE_MAP_MAX PL_DEPRECATED_ENUMERATOR,
|
||||
PL_TONE_MAP_HYBRID PL_DEPRECATED_ENUMERATOR,
|
||||
PL_TONE_MAP_LUMA PL_DEPRECATED_ENUMERATOR,
|
||||
PL_TONE_MAP_MODE_COUNT,
|
||||
};
|
||||
|
||||
// Deprecated by <libplacebo/gamut_mapping.h>
|
||||
enum pl_gamut_mode {
|
||||
PL_GAMUT_CLIP PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_clip
|
||||
PL_GAMUT_WARN PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_highlight
|
||||
PL_GAMUT_DARKEN PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_darken
|
||||
PL_GAMUT_DESATURATE PL_DEPRECATED_ENUMERATOR, // pl_gamut_map_desaturate
|
||||
PL_GAMUT_MODE_COUNT,
|
||||
};
|
||||
|
||||
struct pl_color_map_params {
|
||||
// --- Gamut mapping options
|
||||
|
||||
// Gamut mapping function to use to handle out-of-gamut colors, including
|
||||
// colors which are out-of-gamut as a consequence of tone mapping.
|
||||
const struct pl_gamut_map_function *gamut_mapping;
|
||||
|
||||
// Gamut mapping constants, for expert tuning. Leave as default otherwise.
|
||||
struct pl_gamut_map_constants gamut_constants;
|
||||
|
||||
// Gamut mapping 3DLUT size, for channels ICh. Defaults to {48, 32, 256}
|
||||
int lut3d_size[3];
|
||||
|
||||
// Use higher quality, but slower, tricubic interpolation for gamut mapping
|
||||
// 3DLUTs. May substantially improve the 3DLUT gamut mapping accuracy, in
|
||||
// particular at smaller 3DLUT sizes. Shouldn't have much effect at the
|
||||
// default size.
|
||||
bool lut3d_tricubic;
|
||||
|
||||
// If true, allows the gamut mapping function to expand the gamut, in
|
||||
// cases where the target gamut exceeds that of the source. If false,
|
||||
// the source gamut will never be enlarged, even when using a gamut
|
||||
// mapping function capable of bidirectional mapping.
|
||||
bool gamut_expansion;
|
||||
|
||||
// --- Tone mapping options
|
||||
|
||||
// Tone mapping function to use to handle out-of-range colors.
|
||||
const struct pl_tone_map_function *tone_mapping_function;
|
||||
|
||||
// Tone mapping constants, for expert tuning. Leave as default otherwise.
|
||||
struct pl_tone_map_constants tone_constants;
|
||||
|
||||
// If true, and supported by the given tone mapping function, libplacebo
|
||||
// will perform inverse tone mapping to expand the dynamic range of a
|
||||
// signal. libplacebo is not liable for any HDR-induced eye damage.
|
||||
bool inverse_tone_mapping;
|
||||
|
||||
// Data source to use when tone-mapping. Setting this to a specific
|
||||
// value allows overriding the default metadata preference logic.
|
||||
enum pl_hdr_metadata_type metadata;
|
||||
|
||||
// Tone mapping LUT size. Defaults to 256.
|
||||
int lut_size;
|
||||
|
||||
// HDR contrast recovery strength. If set to a value above 0.0, the source
|
||||
// image will be divided into high-frequency and low-frequency components,
|
||||
// and a portion of the high-frequency image is added back onto the
|
||||
// tone-mapped output. May cause excessive ringing artifacts for some HDR
|
||||
// sources, but can improve the subjective sharpness and detail left over
|
||||
// in the image after tone-mapping.
|
||||
float contrast_recovery;
|
||||
|
||||
// Contrast recovery lowpass kernel size. Defaults to 3.5. Increasing
|
||||
// or decreasing this will affect the visual appearance substantially.
|
||||
float contrast_smoothness;
|
||||
|
||||
// --- Debugging options
|
||||
|
||||
// Force the use of a full tone-mapping LUT even for functions that have
|
||||
// faster pure GLSL replacements (e.g. clip, linear, saturation).
|
||||
bool force_tone_mapping_lut;
|
||||
|
||||
// Visualize the tone-mapping LUT and gamut mapping 3DLUT, in IPT space.
|
||||
bool visualize_lut;
|
||||
|
||||
// Controls where to draw the visualization, relative to the rendered
|
||||
// video (dimensions 0-1). Optional, defaults to the full picture.
|
||||
pl_rect2df visualize_rect;
|
||||
|
||||
// Controls the rotation of the 3DLUT visualization.
|
||||
float visualize_hue; // useful range [-pi, pi]
|
||||
float visualize_theta; // useful range [0, pi/2]
|
||||
|
||||
// Graphically highlight hard-clipped pixels during tone-mapping (i.e.
|
||||
// pixels that exceed the claimed source luminance range).
|
||||
bool show_clipping;
|
||||
|
||||
// --- Deprecated fields
|
||||
enum pl_tone_map_mode tone_mapping_mode PL_DEPRECATED; // removed
|
||||
float tone_mapping_param PL_DEPRECATED; // see `tone_constants`
|
||||
float tone_mapping_crosstalk PL_DEPRECATED; // now hard-coded as 0.04
|
||||
enum pl_rendering_intent intent PL_DEPRECATED; // see `gamut_mapping`
|
||||
enum pl_gamut_mode gamut_mode PL_DEPRECATED; // see `gamut_mapping`
|
||||
float hybrid_mix PL_DEPRECATED; // removed
|
||||
};
|
||||
|
||||
#define PL_COLOR_MAP_DEFAULTS \
|
||||
.gamut_mapping = &pl_gamut_map_perceptual, \
|
||||
.tone_mapping_function = &pl_tone_map_spline, \
|
||||
.gamut_constants = { PL_GAMUT_MAP_CONSTANTS }, \
|
||||
.tone_constants = { PL_TONE_MAP_CONSTANTS }, \
|
||||
.metadata = PL_HDR_METADATA_ANY, \
|
||||
.lut3d_size = {48, 32, 256}, \
|
||||
.lut_size = 256, \
|
||||
.visualize_rect = {0, 0, 1, 1}, \
|
||||
.contrast_smoothness = 3.5f,
|
||||
|
||||
#define PL_COLOR_MAP_HQ_DEFAULTS \
|
||||
PL_COLOR_MAP_DEFAULTS \
|
||||
.contrast_recovery = 0.30f,
|
||||
|
||||
#define pl_color_map_params(...) (&(struct pl_color_map_params) { PL_COLOR_MAP_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_color_map_params pl_color_map_default_params;
|
||||
PL_API extern const struct pl_color_map_params pl_color_map_high_quality_params;
|
||||
|
||||
// Execution arguments for the `pl_shader_color_map_ex` call. Distinct from
|
||||
// `pl_color_map_params` because it is filled by internally-provided execution
|
||||
// metadata, instead of user-tunable aesthetic parameters.
|
||||
struct pl_color_map_args {
|
||||
// Input/output color space for the mapping.
|
||||
struct pl_color_space src;
|
||||
struct pl_color_space dst;
|
||||
|
||||
// If true, the logic will assume the input has already been linearized by
|
||||
// the caller (e.g. as part of a previous linear light scaling operation).
|
||||
bool prelinearized;
|
||||
|
||||
// Object to be used to store generated LUTs. Note that this is the same
|
||||
// state object used by `pl_shader_detect_peak`, and if that function has
|
||||
// been called on `state` prior to `pl_shader_color_map`, the detected
|
||||
// values will be used to guide the tone mapping algorithm. If this is not
|
||||
// provided, tone/gamut mapping are disabled.
|
||||
pl_shader_obj *state;
|
||||
|
||||
// Low-resolution intensity feature map, as generated by
|
||||
// `pl_shader_extract_features`. Optional. No effect if
|
||||
// `params->contrast_recovery` is disabled.
|
||||
pl_tex feature_map;
|
||||
};
|
||||
|
||||
#define pl_color_map_args(...) (&(struct pl_color_map_args) { __VA_ARGS__ })
|
||||
|
||||
// Maps `vec4 color` from one color space to another color space according
|
||||
// to the parameters (described in greater depth above). If `params` is left
|
||||
// as NULL, it defaults to `&pl_color_map_default_params`
|
||||
PL_API void pl_shader_color_map_ex(pl_shader sh,
|
||||
const struct pl_color_map_params *params,
|
||||
const struct pl_color_map_args *args);
|
||||
|
||||
// Backwards compatibility wrapper around `pl_shader_color_map_ex`
|
||||
PL_API void pl_shader_color_map(pl_shader sh, const struct pl_color_map_params *params,
|
||||
struct pl_color_space src, struct pl_color_space dst,
|
||||
pl_shader_obj *state, bool prelinearized);
|
||||
|
||||
// Applies a set of cone distortion parameters to `vec4 color` in a given color
|
||||
// space. This can be used to simulate color blindness. See `pl_cone_params`
|
||||
// for more information.
|
||||
PL_API void pl_shader_cone_distort(pl_shader sh, struct pl_color_space csp,
|
||||
const struct pl_cone_params *params);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_COLORSPACE_H_
|
||||
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* 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_SHADERS_CUSTOM_H_
|
||||
#define LIBPLACEBO_SHADERS_CUSTOM_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Functions for writing custom shaders and hooking them into the `pl_renderer`
|
||||
// pipeline, as well as compatibility functions for parsing shaders in mpv
|
||||
// format.
|
||||
|
||||
#include <libplacebo/shaders.h>
|
||||
#include <libplacebo/dispatch.h>
|
||||
#include <libplacebo/colorspace.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Parameters describing custom shader text to be embedded into a `pl_shader`
|
||||
// object. All of the strings are optional and can be left as NULL, but without
|
||||
// a `body` in particular, the shader will do nothing useful on its own.
|
||||
struct pl_custom_shader {
|
||||
// The prelude contains text such as extra #defines, #extension pragmas,
|
||||
// or other parts of the shader that must be placed at the very
|
||||
// beginning (before input layout declarations etc.)
|
||||
//
|
||||
// Note: #extension pragmas do not need to be emitted to enable support for
|
||||
// resource types already attached to the shader (e.g. SSBOs), compute
|
||||
// shaders, or GPU capabilities known to libplacebo (e.g. subgroups).
|
||||
const char *prelude;
|
||||
|
||||
// The header contains text such as helper function definitions, extra
|
||||
// uniforms, shared memory variables or buffer descriptions.
|
||||
const char *header;
|
||||
|
||||
// A friendly name for the shader. (Optional)
|
||||
const char *description;
|
||||
|
||||
// The "primary" GLSL code. This will be effectively appended to the "main"
|
||||
// function. It lives in an environment given by the `input` signature, and
|
||||
// is expected to return results in a way given by the `output` signature.
|
||||
//
|
||||
// Note: In the case of PL_SHADER_SIG_COLOR, the output `vec4 color` is
|
||||
// allocated by `pl_shader_custom`, the user merely needs to assign to it.
|
||||
//
|
||||
// Note: For ease of development it can be useful to have the main logic
|
||||
// live inside a helper function defined as part of `header`, and specify
|
||||
// the `body` as a single line that simply calls the helper function.
|
||||
const char *body;
|
||||
enum pl_shader_sig input;
|
||||
enum pl_shader_sig output;
|
||||
|
||||
// Extra descriptors, variables and vertex attributes to attach to the
|
||||
// resulting `pl_shader_res`.
|
||||
//
|
||||
// Note: The names inside these will possibly be replaced by fresh
|
||||
// identifiers internally, so users should avoid looking for exact string
|
||||
// matches for the given names inside the `pl_shader_res`.
|
||||
const struct pl_shader_desc *descriptors;
|
||||
int num_descriptors;
|
||||
const struct pl_shader_var *variables;
|
||||
int num_variables;
|
||||
const struct pl_shader_va *vertex_attribs;
|
||||
int num_vertex_attribs;
|
||||
const struct pl_shader_const *constants;
|
||||
int num_constants;
|
||||
|
||||
// If true, this shader must be a compute shader. The desired workgroup
|
||||
// size and shared memory usage can be optionally specified, or 0 if no
|
||||
// specific work group size or shared memory size restrictions apply.
|
||||
//
|
||||
// See also: `pl_shader_res.compute_group_size`
|
||||
bool compute;
|
||||
size_t compute_shmem;
|
||||
int compute_group_size[2];
|
||||
|
||||
// Fixes the output size requirements of the shader to exact dimensions.
|
||||
// Optional, if left as 0, means the shader can be dispatched at any size.
|
||||
int output_w;
|
||||
int output_h;
|
||||
};
|
||||
|
||||
// Append custom shader code, including extra descriptors and variables, to an
|
||||
// existing `pl_shader` object. Returns whether successful. This function may
|
||||
// fail in the event that e.g. the custom shader requires compute shaders on
|
||||
// an unsupported GPU, or exceeds the GPU's shared memory capabilities.
|
||||
PL_API bool pl_shader_custom(pl_shader sh, const struct pl_custom_shader *params);
|
||||
|
||||
// Which "rendering stages" are available for user shader hooking purposes.
|
||||
// Except where otherwise noted, all stages are "non-resizable", i.e. the
|
||||
// shaders already have specific output size requirements.
|
||||
enum pl_hook_stage {
|
||||
// Hook stages for the untouched planes, as made available by the source.
|
||||
// These are all resizable, i.e. there are no specific output stage
|
||||
// requirements.
|
||||
PL_HOOK_RGB_INPUT = 1 << 0,
|
||||
PL_HOOK_LUMA_INPUT = 1 << 1,
|
||||
PL_HOOK_CHROMA_INPUT = 1 << 2,
|
||||
PL_HOOK_ALPHA_INPUT = 1 << 3,
|
||||
PL_HOOK_XYZ_INPUT = 1 << 4,
|
||||
|
||||
// Hook stages for the scaled/aligned planes
|
||||
PL_HOOK_CHROMA_SCALED = 1 << 5,
|
||||
PL_HOOK_ALPHA_SCALED = 1 << 6,
|
||||
|
||||
PL_HOOK_NATIVE = 1 << 7, // Combined image in its native color space
|
||||
PL_HOOK_RGB = 1 << 8, // After conversion to RGB (resizable)
|
||||
PL_HOOK_LINEAR = 1 << 9, // After linearization but before scaling
|
||||
PL_HOOK_SIGMOID = 1 << 10, // After sigmoidization
|
||||
PL_HOOK_PRE_KERNEL = 1 << 11, // Immediately before the main scaler kernel
|
||||
PL_HOOK_POST_KERNEL = 1 << 12, // Immediately after the main scaler kernel
|
||||
PL_HOOK_SCALED = 1 << 13, // After scaling, before color management
|
||||
PL_HOOK_PRE_OUTPUT = 1 << 14, // After color management, before blending/rotation
|
||||
PL_HOOK_OUTPUT = 1 << 15, // After blending/rotation, before dithering
|
||||
};
|
||||
|
||||
// Returns true if a given hook stage is resizable
|
||||
static inline bool pl_hook_stage_resizable(enum pl_hook_stage stage) {
|
||||
switch (stage) {
|
||||
case PL_HOOK_RGB_INPUT:
|
||||
case PL_HOOK_LUMA_INPUT:
|
||||
case PL_HOOK_CHROMA_INPUT:
|
||||
case PL_HOOK_ALPHA_INPUT:
|
||||
case PL_HOOK_XYZ_INPUT:
|
||||
case PL_HOOK_NATIVE:
|
||||
case PL_HOOK_RGB:
|
||||
return true;
|
||||
|
||||
case PL_HOOK_CHROMA_SCALED:
|
||||
case PL_HOOK_ALPHA_SCALED:
|
||||
case PL_HOOK_LINEAR:
|
||||
case PL_HOOK_SIGMOID:
|
||||
case PL_HOOK_PRE_KERNEL:
|
||||
case PL_HOOK_POST_KERNEL:
|
||||
case PL_HOOK_SCALED:
|
||||
case PL_HOOK_PRE_OUTPUT:
|
||||
case PL_HOOK_OUTPUT:
|
||||
return false;
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
// The different forms of communicating image data between the renderer and
|
||||
// the hooks
|
||||
enum pl_hook_sig {
|
||||
PL_HOOK_SIG_NONE, // No data is passed, no data is received/returned
|
||||
PL_HOOK_SIG_COLOR, // `vec4 color` already pre-sampled in a `pl_shader`
|
||||
PL_HOOK_SIG_TEX, // `pl_tex` containing the image data
|
||||
PL_HOOK_SIG_COUNT,
|
||||
};
|
||||
|
||||
struct pl_hook_params {
|
||||
// GPU objects associated with the `pl_renderer`, which the user may
|
||||
// use for their own purposes.
|
||||
pl_gpu gpu;
|
||||
pl_dispatch dispatch;
|
||||
|
||||
// Helper function to fetch a new temporary texture, using renderer-backed
|
||||
// storage. This is guaranteed to have sane image usage requirements and a
|
||||
// 16-bit or floating point format. The user does not need to free/destroy
|
||||
// this texture in any way. May return NULL.
|
||||
pl_tex (*get_tex)(void *priv, int width, int height);
|
||||
void *priv;
|
||||
|
||||
// Which stage triggered the hook to run.
|
||||
enum pl_hook_stage stage;
|
||||
|
||||
// For `PL_HOOK_SIG_COLOR`, this contains the existing shader object with
|
||||
// the color already pre-sampled into `vec4 color`. The user may modify
|
||||
// this as much as they want, as long as they don't dispatch/finalize/reset
|
||||
// it.
|
||||
//
|
||||
// Note that this shader might have specific output size requirements,
|
||||
// depending on the exact shader stage hooked by the user, and may already
|
||||
// be a compute shader.
|
||||
pl_shader sh;
|
||||
|
||||
// For `PL_HOOK_SIG_TEX`, this contains the texture that the user should
|
||||
// sample from.
|
||||
//
|
||||
// Note: This texture object is owned by the renderer, and users must not
|
||||
// modify its contents. It will not be touched for the duration of a frame,
|
||||
// but the contents are lost in between frames.
|
||||
pl_tex tex;
|
||||
|
||||
// The effective current rectangle of the image we're rendering in this
|
||||
// shader, i.e. the effective rect of the content we're interested in,
|
||||
// as a crop of either `sh` or `tex` (depending on the signature).
|
||||
//
|
||||
// Note: This is still set even for `PL_HOOK_SIG_NONE`!
|
||||
pl_rect2df rect;
|
||||
|
||||
// The current effective colorspace and representation, of either the
|
||||
// pre-sampled color (in `sh`), or the contents of `tex`, respectively.
|
||||
//
|
||||
// Note: This is still set even for `PL_HOOK_SIG_NONE`!
|
||||
struct pl_color_repr repr;
|
||||
struct pl_color_space color;
|
||||
int components;
|
||||
|
||||
// The representation and colorspace of the original image, for reference.
|
||||
const struct pl_color_repr *orig_repr;
|
||||
const struct pl_color_space *orig_color;
|
||||
|
||||
// The (cropped) source and destination rectangles of the overall
|
||||
// rendering. These are functionallty equivalent to `image.crop` and
|
||||
// `target.crop`, respectively, but `src_rect` in particular may change as
|
||||
// a result of previous hooks being executed. (e.g. prescalers)
|
||||
pl_rect2df src_rect;
|
||||
pl_rect2d dst_rect;
|
||||
};
|
||||
|
||||
struct pl_hook_res {
|
||||
// If true, the hook is assumed to have "failed" or errored in some way,
|
||||
// and all other fields are ignored.
|
||||
bool failed;
|
||||
|
||||
// What type of output this hook is returning.
|
||||
// Note: If this is `PL_HOOK_SIG_NONE`, all other fields are ignored.
|
||||
enum pl_hook_sig output;
|
||||
|
||||
// For `PL_HOOK_SIG_COLOR`, this *must* be set to a valid `pl_shader`
|
||||
// object containing the sampled color value (i.e. with an output signature
|
||||
// of `PL_SHADER_SIG_COLOR`), and *should* be allocated from the given
|
||||
// `pl_dispatch` object. Ignored otherwise.
|
||||
pl_shader sh;
|
||||
|
||||
// For `PL_HOOK_SIG_TEX`, this *must* contain the texture object containing
|
||||
// the result of rendering the hook. This *should* be a texture allocated
|
||||
// using the given `get_tex` callback, to ensure the format and texture
|
||||
// usage flags are compatible with what the renderer expects.
|
||||
pl_tex tex;
|
||||
|
||||
// For shaders that return some sort of output, this contains the
|
||||
// new/altered versions of the existing "current texture" metadata.
|
||||
struct pl_color_repr repr;
|
||||
struct pl_color_space color;
|
||||
int components;
|
||||
|
||||
// This contains the new effective rect of the contents. This may be
|
||||
// different from the original `rect` for resizable passes. Ignored for
|
||||
// non-resizable passes.
|
||||
pl_rect2df rect;
|
||||
};
|
||||
|
||||
enum pl_hook_par_mode {
|
||||
PL_HOOK_PAR_VARIABLE, // normal shader variable
|
||||
PL_HOOK_PAR_DYNAMIC, // dynamic shader variable, e.g. per-frame changing
|
||||
PL_HOOK_PAR_CONSTANT, // fixed at compile time (e.g. for array sizes),
|
||||
// must be scalar (non-vector/matrix)
|
||||
PL_HOOK_PAR_DEFINE, // defined in the preprocessor, must be `int`
|
||||
PL_HOOK_PAR_MODE_COUNT,
|
||||
};
|
||||
|
||||
typedef union pl_var_data {
|
||||
int i;
|
||||
unsigned u;
|
||||
float f;
|
||||
} pl_var_data;
|
||||
|
||||
struct pl_hook_par {
|
||||
// Name as used in the shader.
|
||||
const char *name;
|
||||
|
||||
// Type of this shader parameter, and how it's manifested in the shader.
|
||||
enum pl_var_type type;
|
||||
enum pl_hook_par_mode mode;
|
||||
|
||||
// Human-readable explanation of this parameter. (Optional)
|
||||
const char *description;
|
||||
|
||||
// Mutable data pointer to current value of variable.
|
||||
pl_var_data *data;
|
||||
|
||||
// Default/initial value, and lower/upper bounds.
|
||||
pl_var_data initial;
|
||||
pl_var_data minimum;
|
||||
pl_var_data maximum;
|
||||
|
||||
// Human-readable names for the variants of an integer option. This array
|
||||
// can be indexed directly by integer values, ranging from `minimum.i` to
|
||||
// `maximum.i`. May be NULL, in which case options are unnamed.
|
||||
const char * const *names;
|
||||
};
|
||||
|
||||
// Struct describing a hook.
|
||||
//
|
||||
// Note: Users may freely create their own instances of this struct, there is
|
||||
// nothing particularly special about `pl_mpv_user_shader_parse`.
|
||||
struct pl_hook {
|
||||
enum pl_hook_stage stages; // Which stages to hook on
|
||||
enum pl_hook_sig input; // Which input signature this hook expects
|
||||
void *priv; // Arbitrary user context
|
||||
|
||||
// Custom tunable shader parameters exported by this hook. These may be
|
||||
// updated at any time by the user, to influence the behavior of the hook.
|
||||
// Contents are arbitrary and subject to the method of hook construction.
|
||||
const struct pl_hook_par *parameters;
|
||||
int num_parameters;
|
||||
|
||||
// Called at the beginning of passes, to reset/initialize the hook. (Optional)
|
||||
void (*reset)(void *priv);
|
||||
|
||||
// The hook function itself. Called by the renderer at any of the indicated
|
||||
// hook stages. See `pl_hook_res` for more info on the return values.
|
||||
struct pl_hook_res (*hook)(void *priv, const struct pl_hook_params *params);
|
||||
|
||||
// Unique signature identifying this hook, used to disable misbehaving hooks.
|
||||
// All hooks with the same signature will be disabled, should they fail to
|
||||
// execute during run-time.
|
||||
uint64_t signature;
|
||||
};
|
||||
|
||||
// Compatibility layer with `mpv` user shaders. See the mpv man page for more
|
||||
// information on the format. Will return `NULL` if the shader fails parsing.
|
||||
//
|
||||
// The resulting `pl_hook` objects should be destroyed with the corresponding
|
||||
// destructor when no longer needed.
|
||||
PL_API const struct pl_hook *
|
||||
pl_mpv_user_shader_parse(pl_gpu gpu, const char *shader_text, size_t shader_len);
|
||||
|
||||
PL_API void pl_mpv_user_shader_destroy(const struct pl_hook **hook);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_CUSTOM_H_
|
||||
@ -0,0 +1,137 @@
|
||||
|
||||
/*
|
||||
* This file is part of libplacebo, which is normally licensed under the terms
|
||||
* of the LGPL v2.1+. However, this file (film_grain.h) is also available under
|
||||
* the terms of the more permissive MIT license:
|
||||
*
|
||||
* Copyright (c) 2018-2019 Niklas Haas
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBPLACEBO_SHADERS_DEINTERLACING_H_
|
||||
#define LIBPLACEBO_SHADERS_DEINTERLACING_H_
|
||||
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
enum pl_field {
|
||||
PL_FIELD_NONE = 0, // no deinterlacing
|
||||
PL_FIELD_EVEN, // "top" fields, with even y coordinates
|
||||
PL_FIELD_ODD, // "bottom" fields, with odd y coordinates
|
||||
|
||||
// Convenience aliases
|
||||
PL_FIELD_TOP = PL_FIELD_EVEN,
|
||||
PL_FIELD_BOTTOM = PL_FIELD_ODD,
|
||||
};
|
||||
|
||||
static inline enum pl_field pl_field_other(enum pl_field field)
|
||||
{
|
||||
switch (field) {
|
||||
case PL_FIELD_EVEN: return PL_FIELD_ODD;
|
||||
case PL_FIELD_ODD: return PL_FIELD_EVEN;
|
||||
default: return field;
|
||||
}
|
||||
}
|
||||
|
||||
struct pl_field_pair {
|
||||
// Top texture. If only this is specified, it's assumed to contain both
|
||||
// fields in an interleaved fashion (MBAFF).
|
||||
//
|
||||
// Note: Support for separate fields (PAFF), is currently pending, so this
|
||||
// is the only way to provide interlaced frames at the moment.
|
||||
pl_tex top;
|
||||
};
|
||||
|
||||
#define pl_field_pair(...) ((struct pl_field_pair) { __VA_ARGS__ })
|
||||
|
||||
struct pl_deinterlace_source {
|
||||
// Previous, current and next source (interlaced) frames. `prev` and `next`
|
||||
// may be NULL, but `cur` is required. If present, they must all have the
|
||||
// exact same texture dimensions.
|
||||
//
|
||||
// Note: `prev` and `next` are only required for PL_DEINTERLACE_YADIF.
|
||||
struct pl_field_pair prev, cur, next;
|
||||
|
||||
// The parity of the current field to output. This field will be unmodified
|
||||
// from `cur`, with the corresponding other field interpolated.
|
||||
//
|
||||
// If this is `PL_FIELD_NONE`, no deinterlacing is performed, and the
|
||||
// texture is merely sampled as-is.
|
||||
enum pl_field field;
|
||||
|
||||
// The parity of the first frame in a stream. Set this the field that is
|
||||
// (conceptually) ordered first in time.
|
||||
//
|
||||
// If this is `PL_FIELD_NONE`, it will instead default to `PL_FIELD_TOP`.
|
||||
enum pl_field first_field;
|
||||
|
||||
// Components to deinterlace. Components not specified will be ignored.
|
||||
// Optional, if left as 0, all components will be deinterlaced.
|
||||
uint8_t component_mask;
|
||||
};
|
||||
|
||||
#define pl_deinterlace_source(...) (&(struct pl_deinterlace_source) { __VA_ARGS__ })
|
||||
|
||||
enum pl_deinterlace_algorithm {
|
||||
// No-op deinterlacing, just sample the weaved frame un-touched.
|
||||
PL_DEINTERLACE_WEAVE = 0,
|
||||
|
||||
// Naive bob deinterlacing. Doubles the field lines vertically.
|
||||
PL_DEINTERLACE_BOB,
|
||||
|
||||
// "Yet another deinterlacing filter". Deinterlacer with temporal and
|
||||
// spatial information. Based on FFmpeg's Yadif filter algorithm, but
|
||||
// adapted slightly for the GPU.
|
||||
PL_DEINTERLACE_YADIF,
|
||||
|
||||
PL_DEINTERLACE_ALGORITHM_COUNT,
|
||||
};
|
||||
|
||||
// Returns whether or not an algorithm requires `prev`/`next` refs to be set.
|
||||
static inline bool pl_deinterlace_needs_refs(enum pl_deinterlace_algorithm algo)
|
||||
{
|
||||
return algo == PL_DEINTERLACE_YADIF;
|
||||
}
|
||||
|
||||
struct pl_deinterlace_params {
|
||||
// Algorithm to use. The recommended default is PL_DEINTERLACE_YADIF, which
|
||||
// provides a good trade-off of quality and speed.
|
||||
enum pl_deinterlace_algorithm algo;
|
||||
|
||||
// Skip the spatial interlacing check. (PL_DEINTERLACE_YADIF only)
|
||||
bool skip_spatial_check;
|
||||
};
|
||||
|
||||
#define PL_DEINTERLACE_DEFAULTS \
|
||||
.algo = PL_DEINTERLACE_YADIF,
|
||||
|
||||
#define pl_deinterlace_params(...) (&(struct pl_deinterlace_params) { PL_DEINTERLACE_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_deinterlace_params pl_deinterlace_default_params;
|
||||
|
||||
// Deinterlaces a set of interleaved source frames and outputs the result into
|
||||
// `vec4 color`. If `params` is left as NULL, it defaults to
|
||||
// `&pl_deinterlace_default_params`.
|
||||
PL_API void pl_shader_deinterlace(pl_shader sh, const struct pl_deinterlace_source *src,
|
||||
const struct pl_deinterlace_params *params);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_DEINTERLACING_H_
|
||||
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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_SHADERS_DITHERING_H_
|
||||
#define LIBPLACEBO_SHADERS_DITHERING_H_
|
||||
|
||||
// Dithering shaders
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/dither.h>
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
enum pl_dither_method {
|
||||
// Dither with blue noise. Very high quality, but requires the use of a
|
||||
// LUT. Warning: Computing a blue noise texture with a large size can be
|
||||
// very slow, however this only needs to be performed once. Even so, using
|
||||
// this with a `lut_size` greater than 6 is generally ill-advised. This is
|
||||
// the preferred/default dither method.
|
||||
PL_DITHER_BLUE_NOISE,
|
||||
|
||||
// Dither with an ordered (bayer) dither matrix, using a LUT. Low quality,
|
||||
// and since this also uses a LUT, there's generally no advantage to picking
|
||||
// this instead of `PL_DITHER_BLUE_NOISE`. It's mainly there for testing.
|
||||
PL_DITHER_ORDERED_LUT,
|
||||
|
||||
// The same as `PL_DITHER_ORDERED_LUT`, but uses fixed function math instead
|
||||
// of a LUT. This is faster, but only supports a fixed dither matrix size
|
||||
// of 16x16 (equal to a `lut_size` of 4).
|
||||
PL_DITHER_ORDERED_FIXED,
|
||||
|
||||
// Dither with white noise. This does not require a LUT and is fairly cheap
|
||||
// to compute. Unlike the other modes it doesn't show any repeating
|
||||
// patterns either spatially or temporally, but the downside is that this
|
||||
// is visually fairly jarring due to the presence of low frequencies in the
|
||||
// noise spectrum.
|
||||
PL_DITHER_WHITE_NOISE,
|
||||
|
||||
PL_DITHER_METHOD_COUNT,
|
||||
};
|
||||
|
||||
struct pl_dither_params {
|
||||
// The source of the dither noise to use.
|
||||
enum pl_dither_method method;
|
||||
|
||||
// For the dither methods which require the use of a LUT, this controls
|
||||
// the size of the LUT (base 2). If left as NULL, this defaults to 6, which
|
||||
// is equivalent to a 64x64 dither matrix. Must not be larger than 8.
|
||||
int lut_size;
|
||||
|
||||
// Enables temporal dithering. This reduces the persistence of dithering
|
||||
// artifacts by perturbing the dithering matrix per frame.
|
||||
// Warning: This can cause nasty aliasing artifacts on some LCD screens.
|
||||
bool temporal;
|
||||
|
||||
// Gamma function to use for dither gamma correction. This will only have
|
||||
// an effect when dithering to low bit depths (<= 4).
|
||||
enum pl_color_transfer transfer;
|
||||
};
|
||||
|
||||
#define PL_DITHER_DEFAULTS \
|
||||
.method = PL_DITHER_BLUE_NOISE, \
|
||||
.lut_size = 6, \
|
||||
/* temporal dithering commonly flickers on LCDs */ \
|
||||
.temporal = false,
|
||||
|
||||
#define pl_dither_params(...) (&(struct pl_dither_params) { PL_DITHER_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_dither_params pl_dither_default_params;
|
||||
|
||||
// Dither the colors to a lower depth, given in bits. This can be used on input
|
||||
// colors of any precision. Basically, this rounds the colors to only linear
|
||||
// multiples of the stated bit depth. The average intensity of the result
|
||||
// will not change (i.e., the dither noise is balanced in both directions).
|
||||
// If `params` is NULL, it defaults to &pl_dither_default_params.
|
||||
//
|
||||
// For the dither methods which require the use of a LUT, `dither_state` must
|
||||
// be set to a valid pointer. To avoid thrashing the resource, users should
|
||||
// avoid trying to re-use the same LUT for different dither configurations. If
|
||||
// passed as NULL, libplacebo will automatically fall back to dither algorithms
|
||||
// that don't require the use of a LUT.
|
||||
//
|
||||
// Warning: This dithering algorithm is not gamma-invariant; so using it for
|
||||
// very low bit depths (below 4 or so) will noticeably increase the brightness
|
||||
// of the resulting image. When doing low bit depth dithering for aesthetic
|
||||
// purposes, it's recommended that the user explicitly (de)linearize the colors
|
||||
// before and after this algorithm.
|
||||
PL_API void pl_shader_dither(pl_shader sh, int new_depth,
|
||||
pl_shader_obj *dither_state,
|
||||
const struct pl_dither_params *params);
|
||||
|
||||
struct pl_error_diffusion_params {
|
||||
// Both the input and output texture must be provided up-front, with the
|
||||
// same size. The output texture must be storable, and the input texture
|
||||
// must be sampleable.
|
||||
pl_tex input_tex;
|
||||
pl_tex output_tex;
|
||||
|
||||
// Depth to dither to. Required.
|
||||
int new_depth;
|
||||
|
||||
// Error diffusion kernel to use. Optional. If unspecified, defaults to
|
||||
// `&pl_error_diffusion_sierra_lite`.
|
||||
const struct pl_error_diffusion_kernel *kernel;
|
||||
};
|
||||
|
||||
#define pl_error_diffusion_params(...) (&(struct pl_error_diffusion_params) { __VA_ARGS__ })
|
||||
|
||||
// Computes the shared memory requirements for a given error diffusion kernel.
|
||||
// This can be used to test up-front whether or not error diffusion would be
|
||||
// supported or not, before having to initialize textures.
|
||||
PL_API size_t pl_error_diffusion_shmem_req(const struct pl_error_diffusion_kernel *kernel,
|
||||
int height);
|
||||
|
||||
// Apply an error diffusion dithering kernel. This is a much more expensive and
|
||||
// heavy dithering method, and is not generally recommended for realtime usage
|
||||
// where performance is critical.
|
||||
//
|
||||
// Requires compute shader support. Returns false if dithering fail e.g. as a
|
||||
// result of shader memory limits being exceeded. The resulting shader must be
|
||||
// dispatched with a work group count of exactly 1.
|
||||
PL_API bool pl_shader_error_diffusion(pl_shader sh, const struct pl_error_diffusion_params *params);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_DITHERING_H_
|
||||
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of libplacebo, which is normally licensed under the terms
|
||||
* of the LGPL v2.1+. However, this file (film_grain.h) is also available under
|
||||
* the terms of the more permissive MIT license:
|
||||
*
|
||||
* Copyright (c) 2018-2019 Niklas Haas
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBPLACEBO_SHADERS_FILM_GRAIN_H_
|
||||
#define LIBPLACEBO_SHADERS_FILM_GRAIN_H_
|
||||
|
||||
// Film grain synthesis shaders for AV1 / H.274.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
enum pl_film_grain_type {
|
||||
PL_FILM_GRAIN_NONE = 0,
|
||||
PL_FILM_GRAIN_AV1,
|
||||
PL_FILM_GRAIN_H274,
|
||||
PL_FILM_GRAIN_COUNT,
|
||||
};
|
||||
|
||||
// AV1 film grain parameters. For the exact meaning of these, see the AV1
|
||||
// specification (section 6.8.20).
|
||||
struct pl_av1_grain_data {
|
||||
int num_points_y;
|
||||
uint8_t points_y[14][2]; // [n][0] = value, [n][1] = scaling
|
||||
bool chroma_scaling_from_luma;
|
||||
int num_points_uv[2]; // should be {0} for grayscale images
|
||||
uint8_t points_uv[2][10][2]; // like points_y for points_uv[0, 1] = u, v
|
||||
int scaling_shift;
|
||||
int ar_coeff_lag;
|
||||
int8_t ar_coeffs_y[24];
|
||||
int8_t ar_coeffs_uv[2][25];
|
||||
int ar_coeff_shift;
|
||||
int grain_scale_shift;
|
||||
int8_t uv_mult[2];
|
||||
int8_t uv_mult_luma[2];
|
||||
int16_t uv_offset[2]; // 9-bit value, range [-256, 255]
|
||||
bool overlap;
|
||||
};
|
||||
|
||||
// H.274 film grain parameters. For the exact meaning of these, see the H.274
|
||||
// specification (section 8.5).
|
||||
struct pl_h274_grain_data {
|
||||
int model_id;
|
||||
int blending_mode_id;
|
||||
int log2_scale_factor;
|
||||
bool component_model_present[3];
|
||||
uint16_t num_intensity_intervals[3];
|
||||
uint8_t num_model_values[3];
|
||||
const uint8_t *intensity_interval_lower_bound[3];
|
||||
const uint8_t *intensity_interval_upper_bound[3];
|
||||
const int16_t (*comp_model_value[3])[6];
|
||||
};
|
||||
|
||||
// Tagged union for film grain data
|
||||
struct pl_film_grain_data {
|
||||
enum pl_film_grain_type type; // film grain type
|
||||
uint64_t seed; // shared seed value
|
||||
|
||||
union {
|
||||
// Warning: These values are not sanity-checked at all, Invalid grain
|
||||
// data results in undefined behavior!
|
||||
struct pl_av1_grain_data av1;
|
||||
struct pl_h274_grain_data h274;
|
||||
} params;
|
||||
};
|
||||
|
||||
// Options for the `pl_shader_film_grain` call.
|
||||
struct pl_film_grain_params {
|
||||
// Required for all film grain types:
|
||||
struct pl_film_grain_data data; // film grain data
|
||||
pl_tex tex; // texture to sample from
|
||||
struct pl_color_repr *repr; // underlying color representation (see notes)
|
||||
int components;
|
||||
int component_mapping[4]; // same as `struct pl_plane`
|
||||
|
||||
// Notes for `repr`:
|
||||
// - repr->bits affects the rounding for grain generation
|
||||
// - repr->levels affects whether or not we clip to full range or not
|
||||
// - repr->sys affects the interpretation of channels
|
||||
// - *repr gets normalized by this shader, which is why it's a pointer
|
||||
|
||||
// Required for PL_FILM_GRAIN_AV1 only:
|
||||
pl_tex luma_tex; // "luma" texture (see notes)
|
||||
int luma_comp; // index of luma in `luma_tex`
|
||||
|
||||
// Notes for `luma_tex`:
|
||||
// - `luma_tex` must be specified if the `tex` does not itself contain the
|
||||
// "luma-like" component. For XYZ systems, the Y channel is the luma
|
||||
// component. For RGB systems, the G channel is.
|
||||
};
|
||||
|
||||
#define pl_film_grain_params(...) (&(struct pl_film_grain_params) { __VA_ARGS__ })
|
||||
|
||||
// Test if film grain needs to be applied. This is a helper function that users
|
||||
// can use to decide whether or not `pl_shader_film_grain` needs to be called,
|
||||
// based on the given grain metadata.
|
||||
PL_API bool pl_needs_film_grain(const struct pl_film_grain_params *params);
|
||||
|
||||
// Sample from a texture while applying film grain at the same time.
|
||||
// `grain_state` must be unique for every plane configuration, as it may
|
||||
// contain plane-dependent state.
|
||||
//
|
||||
// Returns false on any error, or if film grain generation is not supported
|
||||
// due to GLSL limitations.
|
||||
PL_API bool pl_shader_film_grain(pl_shader sh, pl_shader_obj *grain_state,
|
||||
const struct pl_film_grain_params *params);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_FILM_GRAIN_H_
|
||||
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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_SHADERS_ICC_H_
|
||||
#define LIBPLACEBO_SHADERS_ICC_H_
|
||||
|
||||
// Functions for generating and applying ICC-derived (3D)LUTs
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
struct pl_icc_params {
|
||||
// The rendering intent to use, for profiles with multiple intents. A
|
||||
// recommended value is PL_INTENT_RELATIVE_COLORIMETRIC for color-accurate
|
||||
// video reproduction, or PL_INTENT_PERCEPTUAL for profiles containing
|
||||
// meaningful perceptual mapping tables for some more suitable color space
|
||||
// like BT.709.
|
||||
//
|
||||
// If this is set to the special value PL_INTENT_AUTO, will use the
|
||||
// preferred intent provided by the profile header.
|
||||
enum pl_rendering_intent intent;
|
||||
|
||||
// The size of the 3DLUT to generate. If left as NULL, these individually
|
||||
// default to values appropriate for the profile. (Based on internal
|
||||
// precision heuristics)
|
||||
//
|
||||
// Note: Setting this manually is strongly discouraged, as it can result
|
||||
// in excessively high 3DLUT sizes where a much smaller LUT would have
|
||||
// sufficed.
|
||||
int size_r, size_g, size_b;
|
||||
|
||||
// This field can be used to override the detected brightness level of the
|
||||
// ICC profile. If you set this to the special value 0 (or a negative
|
||||
// number), libplacebo will attempt reading the brightness value from the
|
||||
// ICC profile's tagging (if available), falling back to PL_COLOR_SDR_WHITE
|
||||
// if unavailable.
|
||||
float max_luma;
|
||||
|
||||
// Force black point compensation. May help avoid crushed or raised black
|
||||
// points on "improper" profiles containing e.g. colorimetric tables that
|
||||
// do not round-trip. Should not be required on well-behaved profiles,
|
||||
// or when using PL_INTENT_PERCEPTUAL, but YMMV.
|
||||
bool force_bpc;
|
||||
|
||||
// If provided, this pl_cache instance will be used, instead of the
|
||||
// GPU-internal cache, to cache the generated 3DLUTs. Note that these can
|
||||
// get large, especially for large values of size_{r,g,b}, so the user may
|
||||
// wish to split this cache off from the main shader cache. (Optional)
|
||||
pl_cache cache;
|
||||
|
||||
// Deprecated legacy caching API. Replaced by `cache`.
|
||||
PL_DEPRECATED void *cache_priv;
|
||||
PL_DEPRECATED void (*cache_save)(void *priv, uint64_t sig, const uint8_t *cache, size_t size);
|
||||
PL_DEPRECATED bool (*cache_load)(void *priv, uint64_t sig, uint8_t *cache, size_t size);
|
||||
};
|
||||
|
||||
#define PL_ICC_DEFAULTS \
|
||||
.intent = PL_INTENT_RELATIVE_COLORIMETRIC, \
|
||||
.max_luma = PL_COLOR_SDR_WHITE,
|
||||
|
||||
#define pl_icc_params(...) (&(struct pl_icc_params) { PL_ICC_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_icc_params pl_icc_default_params;
|
||||
|
||||
// This object represents a "parsed" ICC profile.
|
||||
typedef const struct pl_icc_object_t {
|
||||
// Provided params, with the `intent` and `size` fields set (as described)
|
||||
struct pl_icc_params params;
|
||||
|
||||
// Signature of the corresponding ICC profile.
|
||||
uint64_t signature;
|
||||
|
||||
// Detected color space (or UNKNOWN for profiles which don't contain an
|
||||
// exact match), with HDR metedata set to the detected gamut and
|
||||
// white/black value ranges.
|
||||
struct pl_color_space csp;
|
||||
|
||||
// Best estimate of profile gamma. This only serves as a rough guideline.
|
||||
float gamma;
|
||||
|
||||
// Smallest containing primary set, always set.
|
||||
enum pl_color_primaries containing_primaries;
|
||||
} *pl_icc_object;
|
||||
|
||||
// Attempts opening/parsing the contents of an ICC profile. The resulting
|
||||
// object is memory managed and may outlive the original profile - access
|
||||
// to the underlying profile is no longer needed once this returns.
|
||||
PL_API pl_icc_object pl_icc_open(pl_log log, const struct pl_icc_profile *profile,
|
||||
const struct pl_icc_params *params);
|
||||
PL_API void pl_icc_close(pl_icc_object *icc);
|
||||
|
||||
// Update an existing pl_icc_object, which may be NULL, replacing it by the
|
||||
// new profile and parameters (if incompatible).
|
||||
//
|
||||
// Returns success. `obj` is set to the created profile, or NULL on error.
|
||||
//
|
||||
// Note: If `profile->signature` matches `(*obj)->signature`, or if `profile` is
|
||||
// NULL, then the existing profile is directly reused, with only the effective
|
||||
// parameters changing. In this case, `profile->data` is also *not* read from,
|
||||
// and may safely be NULL.
|
||||
PL_API bool pl_icc_update(pl_log log, pl_icc_object *obj,
|
||||
const struct pl_icc_profile *profile,
|
||||
const struct pl_icc_params *params);
|
||||
|
||||
// Decode the input from the colorspace determined by the attached ICC profile
|
||||
// to linear light RGB (in the profile's containing primary set). `lut` must be
|
||||
// set to a shader object that will store the GPU resources associated with the
|
||||
// generated LUT. The resulting color space will be written to `out_csp`.
|
||||
PL_API void pl_icc_decode(pl_shader sh, pl_icc_object profile, pl_shader_obj *lut,
|
||||
struct pl_color_space *out_csp);
|
||||
|
||||
// Encode the input from linear light RGB (in the profile's containing primary
|
||||
// set) into the colorspace determined by the attached ICC profile. `lut` must
|
||||
// be set to a shader object that will store the GPU resources associated with
|
||||
// the generated LUT.
|
||||
PL_API void pl_icc_encode(pl_shader sh, pl_icc_object profile, pl_shader_obj *lut);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_ICC_H_
|
||||
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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_SHADERS_LUT_H_
|
||||
#define LIBPLACEBO_SHADERS_LUT_H_
|
||||
|
||||
// Shaders for loading and applying arbitrary custom 1D/3DLUTs
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Struct defining custom LUTs
|
||||
//
|
||||
// Note: Users may freely create their own instances of this struct, there is
|
||||
// nothing particularly special about `pl_lut_parse_cube`.
|
||||
struct pl_custom_lut {
|
||||
// Some unique signature identifying this LUT, needed to detect state
|
||||
// changes (for cache invalidation). This should ideally be a hash of the
|
||||
// file contents. (Which is what `pl_lut_parse_*` will set it to.)
|
||||
uint64_t signature;
|
||||
|
||||
// Size of each dimension, in the order R, G, B. For 1D LUTs, only the R
|
||||
// dimension should be specified (the others left as 0).
|
||||
int size[3];
|
||||
|
||||
// Raw LUT data itself, in properly scaled floating point format. For 3D
|
||||
// LUTs, the innermost dimension is the first dimension (R), and the
|
||||
// outermost dimension is the last dimension (B). Individual color samples
|
||||
// are in the order R, G, B.
|
||||
const float *data;
|
||||
|
||||
// Extra input/output shaper matrices. Ignored if equal to {0}. This is
|
||||
// mostly useful for 1D LUTs, since 3D LUTs can bake the shaper matrix into
|
||||
// the LUT itself - but it can still help optimize LUT precision.
|
||||
pl_matrix3x3 shaper_in, shaper_out;
|
||||
|
||||
// Nominal metadata for the input/output of a LUT. Left as {0} if unknown.
|
||||
// Note: This is purely informative, `pl_shader_custom_lut` ignores it.
|
||||
struct pl_color_repr repr_in, repr_out;
|
||||
struct pl_color_space color_in, color_out;
|
||||
};
|
||||
|
||||
// Parse a 3DLUT in .cube format. Returns NULL if the file fails parsing.
|
||||
PL_API struct pl_custom_lut *pl_lut_parse_cube(pl_log log, const char *str, size_t str_len);
|
||||
|
||||
// Frees a LUT created by `pl_lut_parse_*`.
|
||||
PL_API void pl_lut_free(struct pl_custom_lut **lut);
|
||||
|
||||
// Apply a `pl_custom_lut`. The user is responsible for ensuring colors going
|
||||
// into the LUT are in the expected format as informed by the LUT metadata.
|
||||
//
|
||||
// `lut_state` must be a pointer to a NULL-initialized shader state object that
|
||||
// will be used to encapsulate any required GPU state.
|
||||
//
|
||||
// Note: `lut` does not have to be allocated by `pl_lut_parse_*`. It can be a
|
||||
// struct filled out by the user.
|
||||
PL_API void pl_shader_custom_lut(pl_shader sh, const struct pl_custom_lut *lut,
|
||||
pl_shader_obj *lut_state);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_LUT_H_
|
||||
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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_SHADERS_SAMPLING_H_
|
||||
#define LIBPLACEBO_SHADERS_SAMPLING_H_
|
||||
|
||||
// Sampling operations. These shaders perform some form of sampling operation
|
||||
// from a given pl_tex. In order to use these, the pl_shader *must* have been
|
||||
// created using the same `gpu` as the originating `pl_tex`. Otherwise, this
|
||||
// is undefined behavior. They require nothing (PL_SHADER_SIG_NONE) and return
|
||||
// a color (PL_SHADER_SIG_COLOR).
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
#include <libplacebo/filters.h>
|
||||
#include <libplacebo/shaders.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Common parameters for sampling operations
|
||||
struct pl_sample_src {
|
||||
// There are two mutually exclusive ways of providing the source to sample
|
||||
// from:
|
||||
//
|
||||
// 1. Provide the texture and sampled region directly. This generates
|
||||
// a shader with input signature `PL_SHADER_SIG_NONE`, which binds the
|
||||
// texture as a descriptor (and the coordinates as a vertex attribute)
|
||||
pl_tex tex; // texture to sample
|
||||
pl_rect2df rect; // sub-rect to sample from (optional)
|
||||
enum pl_tex_address_mode address_mode; // preferred texture address mode
|
||||
|
||||
// 2. Have the shader take it as an argument. Doing this requires
|
||||
// specifying the missing metadata of the texture backing the sampler, so
|
||||
// that the shader generation can generate the correct code.
|
||||
int tex_w, tex_h; // dimensions of the actual texture
|
||||
enum pl_fmt_type format; // format of the sampler being accepted
|
||||
enum pl_sampler_type sampler; // type of the sampler being accepted
|
||||
enum pl_tex_sample_mode mode; // sample mode of the sampler being accepted
|
||||
float sampled_w, sampled_h; // dimensions of the sampled region (optional)
|
||||
|
||||
// Common metadata for both sampler input types:
|
||||
int components; // number of components to sample (optional)
|
||||
uint8_t component_mask; // bitmask of components to sample (optional)
|
||||
int new_w, new_h; // dimensions of the resulting output (optional)
|
||||
float scale; // factor to multiply into sampled signal (optional)
|
||||
|
||||
// Note: `component_mask` and `components` are mutually exclusive, the
|
||||
// former is preferred if both are specified.
|
||||
};
|
||||
|
||||
#define pl_sample_src(...) (&(struct pl_sample_src) { __VA_ARGS__ })
|
||||
|
||||
struct pl_deband_params {
|
||||
// The number of debanding steps to perform per sample. Each step reduces a
|
||||
// bit more banding, but takes time to compute. Note that the strength of
|
||||
// each step falls off very quickly, so high numbers (>4) are practically
|
||||
// useless. Defaults to 1.
|
||||
int iterations;
|
||||
|
||||
// The debanding filter's cut-off threshold. Higher numbers increase the
|
||||
// debanding strength dramatically, but progressively diminish image
|
||||
// details. Defaults to 3.0.
|
||||
float threshold;
|
||||
|
||||
// The debanding filter's initial radius. The radius increases linearly
|
||||
// for each iteration. A higher radius will find more gradients, but a
|
||||
// lower radius will smooth more aggressively. Defaults to 16.0.
|
||||
float radius;
|
||||
|
||||
// Add some extra noise to the image. This significantly helps cover up
|
||||
// remaining quantization artifacts. Higher numbers add more noise.
|
||||
// Note: When debanding HDR sources, even a small amount of grain can
|
||||
// result in a very big change to the brightness level. It's recommended to
|
||||
// either scale this value down or disable it entirely for HDR.
|
||||
//
|
||||
// Defaults to 4.0, which is very mild.
|
||||
float grain;
|
||||
|
||||
// 'Neutral' grain value for each channel being debanded (sorted in order
|
||||
// from low to high index). Grain application will be modulated to avoid
|
||||
// disturbing colors close to this value. Set this to a value corresponding
|
||||
// to black in the relevant colorspace.
|
||||
float grain_neutral[3];
|
||||
};
|
||||
|
||||
#define PL_DEBAND_DEFAULTS \
|
||||
.iterations = 1, \
|
||||
.threshold = 3.0, \
|
||||
.radius = 16.0, \
|
||||
.grain = 4.0,
|
||||
|
||||
#define pl_deband_params(...) (&(struct pl_deband_params) {PL_DEBAND_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_deband_params pl_deband_default_params;
|
||||
|
||||
// Debands a given texture and returns the sampled color in `vec4 color`. If
|
||||
// `params` is left as NULL, it defaults to &pl_deband_default_params. Note
|
||||
// that `tex->params.format` must have PL_FMT_CAP_LINEAR. When the given
|
||||
// `pl_sample_src` implies scaling, this effectively performs bilinear
|
||||
// sampling on the input (but not the output).
|
||||
//
|
||||
// Note: This can also be used as a pure grain function, by setting the number
|
||||
// of iterations to 0.
|
||||
PL_API void pl_shader_deband(pl_shader sh, const struct pl_sample_src *src,
|
||||
const struct pl_deband_params *params);
|
||||
|
||||
// Performs direct / native texture sampling, using whatever texture filter is
|
||||
// available (linear for linearly sampleable sources, nearest otherwise).
|
||||
//
|
||||
// Note: This is generally very low quality and should be avoided if possible,
|
||||
// for both upscaling and downscaling.
|
||||
PL_API bool pl_shader_sample_direct(pl_shader sh, const struct pl_sample_src *src);
|
||||
|
||||
// Performs hardware-accelerated nearest neighbour sampling. This is similar to
|
||||
// `pl_shader_sample_direct`, but forces nearest neighbour interpolation.
|
||||
PL_API bool pl_shader_sample_nearest(pl_shader sh, const struct pl_sample_src *src);
|
||||
|
||||
// Performs hardware-accelerated bilinear sampling. This is similar to
|
||||
// `pl_shader_sample_direct`, but forces bilinear interpolation.
|
||||
PL_API bool pl_shader_sample_bilinear(pl_shader sh, const struct pl_sample_src *src);
|
||||
|
||||
// Optimized versions of specific, strictly positive scaler kernels that take
|
||||
// adantage of linear texture sampling to reduce the number of fetches needed
|
||||
// by a factor of four. This family of functions performs radius-2 scaling
|
||||
// with only four texture fetches, which is far more efficient than using
|
||||
// the generalized 1D scaling method. Only works well for upscaling.
|
||||
PL_API bool pl_shader_sample_bicubic(pl_shader sh, const struct pl_sample_src *src);
|
||||
PL_API bool pl_shader_sample_hermite(pl_shader sh, const struct pl_sample_src *src);
|
||||
PL_API bool pl_shader_sample_gaussian(pl_shader sh, const struct pl_sample_src *src);
|
||||
|
||||
// A sampler that is similar to nearest neighbour sampling, but tries to
|
||||
// preserve pixel aspect ratios. This is mathematically equivalent to taking an
|
||||
// idealized image with square pixels, sampling it at an infinite resolution,
|
||||
// and then downscaling that to the desired resolution. (Hence it being called
|
||||
// "oversample"). Good for pixel art.
|
||||
//
|
||||
// The threshold provides a cutoff threshold below which the contribution of
|
||||
// pixels should be ignored, trading some amount of aspect ratio distortion for
|
||||
// a slightly crisper image. A value of `threshold == 0.5` makes this filter
|
||||
// equivalent to regular nearest neighbour sampling.
|
||||
PL_API bool pl_shader_sample_oversample(pl_shader sh, const struct pl_sample_src *src,
|
||||
float threshold);
|
||||
|
||||
struct pl_sample_filter_params {
|
||||
// The filter to use for sampling.
|
||||
struct pl_filter_config filter;
|
||||
|
||||
// Antiringing strength. A value of 0.0 disables antiringing, and a value
|
||||
// of 1.0 enables full-strength antiringing. Defaults to 0.0 if
|
||||
// unspecified.
|
||||
//
|
||||
// Note: Ignored if `filter.antiring` is already set to something nonzero.
|
||||
float antiring;
|
||||
|
||||
// Disable the use of compute shaders (e.g. if rendering to non-storable tex)
|
||||
bool no_compute;
|
||||
// Disable the use of filter widening / anti-aliasing (for downscaling)
|
||||
bool no_widening;
|
||||
|
||||
// This shader object is used to store the LUT, and will be recreated
|
||||
// if necessary. To avoid thrashing the resource, users should avoid trying
|
||||
// to re-use the same LUT for different filter configurations or scaling
|
||||
// ratios. Must be set to a valid pointer, and the target NULL-initialized.
|
||||
pl_shader_obj *lut;
|
||||
|
||||
// Deprecated / removed fields
|
||||
int lut_entries PL_DEPRECATED; // hard-coded as 256
|
||||
float cutoff PL_DEPRECATED; // hard-coded as 1e-3
|
||||
};
|
||||
|
||||
#define pl_sample_filter_params(...) (&(struct pl_sample_filter_params) { __VA_ARGS__ })
|
||||
|
||||
// Performs polar sampling. This internally chooses between an optimized compute
|
||||
// shader, and various fragment shaders, depending on the supported GLSL version
|
||||
// and GPU features. Returns whether or not it was successful.
|
||||
//
|
||||
// Note: `params->filter.polar` must be true to use this function.
|
||||
PL_API bool pl_shader_sample_polar(pl_shader sh, const struct pl_sample_src *src,
|
||||
const struct pl_sample_filter_params *params);
|
||||
|
||||
// Performs orthogonal (1D) sampling. Using this twice in a row (once vertical
|
||||
// and once horizontal) effectively performs a 2D upscale. This is lower
|
||||
// quality than polar sampling, but significantly faster, and therefore the
|
||||
// recommended default. Returns whether or not it was successful.
|
||||
//
|
||||
// `src` must represent a scaling operation that only scales in one direction,
|
||||
// i.e. either only X or only Y. The other direction must be left unscaled.
|
||||
//
|
||||
// Note: Due to internal limitations, this may currently only be used on 2D
|
||||
// textures - even though the basic principle would work for 1D and 3D textures
|
||||
// as well.
|
||||
PL_API bool pl_shader_sample_ortho2(pl_shader sh, const struct pl_sample_src *src,
|
||||
const struct pl_sample_filter_params *params);
|
||||
|
||||
struct pl_distort_params {
|
||||
// An arbitrary 2x2 affine transformation to apply to the input image.
|
||||
// For simplicity, the input image is explicitly centered and scaled such
|
||||
// that the longer dimension is in [-1,1], before applying this.
|
||||
pl_transform2x2 transform;
|
||||
|
||||
// If true, the texture is placed inside the center of the canvas without
|
||||
// scaling. If false, it is effectively stretched to the canvas size.
|
||||
bool unscaled;
|
||||
|
||||
// If true, the transformation is automatically scaled down and shifted to
|
||||
// ensure that the resulting image fits inside the output canvas.
|
||||
bool constrain;
|
||||
|
||||
// If true, use bicubic interpolation rather than faster bilinear
|
||||
// interpolation. Higher quality but slower.
|
||||
bool bicubic;
|
||||
|
||||
// Specifies the texture address mode to use when sampling out of bounds.
|
||||
enum pl_tex_address_mode address_mode;
|
||||
|
||||
// If set, all out-of-bounds accesses will instead be treated as
|
||||
// transparent, according to the given alpha mode. (Which should match the
|
||||
// alpha mode of the texture)
|
||||
//
|
||||
// Note: `address_mode` has no effect when this is specified.
|
||||
enum pl_alpha_mode alpha_mode;
|
||||
};
|
||||
|
||||
#define PL_DISTORT_DEFAULTS \
|
||||
.transform.mat.m = {{ 1, 0 }, {0, 1}},
|
||||
|
||||
#define pl_distort_params(...) (&(struct pl_distort_params) {PL_DISTORT_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_distort_params pl_distort_default_params;
|
||||
|
||||
// Distorts the input image using a given set of transformation parameters.
|
||||
// `out_w` and `out_h` determine the size of the effective canvas inside which
|
||||
// the distorted result may be rendered. Areas outside of this canvas will
|
||||
// be implicitly cut off.
|
||||
PL_API void pl_shader_distort(pl_shader sh, pl_tex tex, int out_w, int out_h,
|
||||
const struct pl_distort_params *params);
|
||||
|
||||
enum PL_DEPRECATED { // for `int pass`
|
||||
PL_SEP_VERT = 0,
|
||||
PL_SEP_HORIZ,
|
||||
PL_SEP_PASSES
|
||||
};
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_SHADERS_SAMPLING_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_
|
||||
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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_TONE_MAPPING_H_
|
||||
#define LIBPLACEBO_TONE_MAPPING_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libplacebo/common.h>
|
||||
#include <libplacebo/colorspace.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
struct pl_tone_map_params;
|
||||
struct pl_tone_map_function {
|
||||
const char *name; // Identifier
|
||||
const char *description; // Friendly / longer name
|
||||
|
||||
// This controls the type of values input/output to/from `map`
|
||||
enum pl_hdr_scaling scaling;
|
||||
|
||||
// The tone-mapping function itself. Iterates over all values in `lut`, and
|
||||
// adapts them as needed.
|
||||
//
|
||||
// Note that the `params` struct fed into this function is guaranteed to
|
||||
// satisfy `params->input_scaling == params->output_scaling == scaling`,
|
||||
// and also obeys `params->input_max >= params->output_max`.
|
||||
void (*map)(float *lut, const struct pl_tone_map_params *params);
|
||||
|
||||
// Inverse tone mapping function. Optional. If absent, this tone mapping
|
||||
// curve only works in the forwards direction.
|
||||
//
|
||||
// For this function, `params->input_max <= params->output_max`.
|
||||
void (*map_inverse)(float *lut, const struct pl_tone_map_params *params);
|
||||
|
||||
// Private data. Unused by libplacebo, but may be accessed by `map`.
|
||||
void *priv;
|
||||
|
||||
// --- Deprecated fields
|
||||
const char *param_desc PL_DEPRECATED;
|
||||
float param_min PL_DEPRECATED;
|
||||
float param_def PL_DEPRECATED;
|
||||
float param_max PL_DEPRECATED;
|
||||
};
|
||||
|
||||
struct pl_tone_map_constants {
|
||||
// Configures the knee point, as a ratio between the source average and
|
||||
// target average (in PQ space). An adaptation of 1.0 always adapts the
|
||||
// source scene average brightness to the (scaled) target average,
|
||||
// while a value of 0.0 never modifies scene brightness. [0,1]
|
||||
//
|
||||
// Affects all methods that use the ST2094 knee point determination
|
||||
// (currently ST2094-40, ST2094-10 and spline)
|
||||
float knee_adaptation;
|
||||
|
||||
// Configures the knee point minimum and maximum, respectively, as
|
||||
// a percentage of the PQ luminance range. Provides a hard limit on the
|
||||
// knee point chosen by `knee_adaptation`.
|
||||
float knee_minimum; // (0, 0.5)
|
||||
float knee_maximum; // (0.5, 1.0)
|
||||
|
||||
// Default knee point to use in the absence of source scene average
|
||||
// metadata. Normally, this is ignored in favor of picking the knee
|
||||
// point as the (relative) source scene average brightness level.
|
||||
float knee_default; // [knee_minimum, knee_maximum]
|
||||
|
||||
// Knee point offset (for BT.2390 only). Note that a value of 0.5 is
|
||||
// the spec-defined default behavior, which differs from the libplacebo
|
||||
// default of 1.0. [0.5, 2]
|
||||
float knee_offset;
|
||||
|
||||
// For the single-pivot polynomial (spline) function, this controls the
|
||||
// coefficients used to tune the slope of the curve. This tuning is designed
|
||||
// to make the slope closer to 1.0 when the difference in peaks is low,
|
||||
// and closer to linear when the difference between peaks is high.
|
||||
float slope_tuning; // [0,10]
|
||||
float slope_offset; // [0,1]
|
||||
|
||||
// Contrast setting for the spline function. Higher values make the curve
|
||||
// steeper (closer to `clip`), preserving midtones at the cost of losing
|
||||
// shadow/highlight details, while lower values make the curve shallowed
|
||||
// (closer to `linear`), preserving highlights at the cost of losing midtone
|
||||
// contrast. Values above 1.0 are possible, resulting in an output with more
|
||||
// contrast than the input.
|
||||
float spline_contrast; // [0,1.5]
|
||||
|
||||
// For the reinhard function, this specifies the local contrast coefficient
|
||||
// at the display peak. Essentially, a value of 0.5 implies that the
|
||||
// reference white will be about half as bright as when clipping. (0,1)
|
||||
float reinhard_contrast;
|
||||
|
||||
// For legacy functions (mobius, gamma) which operate on linear light, this
|
||||
// directly sets the corresponding knee point. (0,1)
|
||||
float linear_knee;
|
||||
|
||||
// For linear methods (linear, linearlight), this controls the linear
|
||||
// exposure/gain applied to the image. (0,10]
|
||||
float exposure;
|
||||
};
|
||||
|
||||
#define PL_TONE_MAP_CONSTANTS \
|
||||
.knee_adaptation = 0.4f, \
|
||||
.knee_minimum = 0.1f, \
|
||||
.knee_maximum = 0.8f, \
|
||||
.knee_default = 0.4f, \
|
||||
.knee_offset = 1.0f, \
|
||||
.slope_tuning = 1.5f, \
|
||||
.slope_offset = 0.2f, \
|
||||
.spline_contrast = 0.5f, \
|
||||
.reinhard_contrast = 0.5f, \
|
||||
.linear_knee = 0.3f, \
|
||||
.exposure = 1.0f,
|
||||
|
||||
struct pl_tone_map_params {
|
||||
// If `function` is NULL, defaults to `pl_tone_map_clip`.
|
||||
const struct pl_tone_map_function *function;
|
||||
|
||||
// Common constants, should be initialized to PL_TONE_MAP_CONSTANTS if
|
||||
// not intending to override them further.
|
||||
struct pl_tone_map_constants constants;
|
||||
|
||||
// The desired input/output scaling of the tone map. If this differs from
|
||||
// `function->scaling`, any required conversion will be performed.
|
||||
//
|
||||
// Note that to maximize LUT efficiency, it's *highly* recommended to use
|
||||
// either PL_HDR_PQ or PL_HDR_SQRT as the input scaling, except when
|
||||
// using `pl_tone_map_sample`.
|
||||
enum pl_hdr_scaling input_scaling;
|
||||
enum pl_hdr_scaling output_scaling;
|
||||
|
||||
// The size of the resulting LUT. (For `pl_tone_map_generate` only)
|
||||
size_t lut_size;
|
||||
|
||||
// The characteristics of the input, in `input_scaling` units.
|
||||
float input_min;
|
||||
float input_max;
|
||||
float input_avg; // or 0 if unknown
|
||||
|
||||
// The desired characteristics of the output, in `output_scaling` units.
|
||||
float output_min;
|
||||
float output_max;
|
||||
|
||||
// The input HDR metadata. Only used by a select few tone-mapping
|
||||
// functions, currently only SMPTE ST2094. (Optional)
|
||||
struct pl_hdr_metadata hdr;
|
||||
|
||||
// --- Deprecated fields
|
||||
float param PL_DEPRECATED; // see `constants`
|
||||
};
|
||||
|
||||
#define pl_tone_map_params(...) (&(struct pl_tone_map_params) { __VA_ARGS__ });
|
||||
|
||||
// Note: Only does pointer equality testing on `function`
|
||||
PL_API bool pl_tone_map_params_equal(const struct pl_tone_map_params *a,
|
||||
const struct pl_tone_map_params *b);
|
||||
|
||||
// Clamps/defaults the parameters, including input/output maximum.
|
||||
PL_API void pl_tone_map_params_infer(struct pl_tone_map_params *params);
|
||||
|
||||
// Returns true if the given tone mapping configuration effectively represents
|
||||
// a no-op configuration. Tone mapping can be skipped in this case (although
|
||||
// strictly speaking, the LUT would still clip illegal input values)
|
||||
PL_API bool pl_tone_map_params_noop(const struct pl_tone_map_params *params);
|
||||
|
||||
// Generate a tone-mapping LUT for a given configuration. This will always
|
||||
// span the entire input range, as given by `input_min` and `input_max`.
|
||||
PL_API void pl_tone_map_generate(float *out, const struct pl_tone_map_params *params);
|
||||
|
||||
// Samples a tone mapping function at a single position. Note that this is less
|
||||
// efficient than `pl_tone_map_generate` for generating multiple values.
|
||||
//
|
||||
// Ignores `params->lut_size`.
|
||||
PL_API float pl_tone_map_sample(float x, const struct pl_tone_map_params *params);
|
||||
|
||||
// Performs no tone-mapping, just clips out-of-range colors. Retains perfect
|
||||
// color accuracy for in-range colors but completely destroys out-of-range
|
||||
// information. Does not perform any black point adaptation.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_clip;
|
||||
|
||||
// EETF from SMPTE ST 2094-40 Annex B, which uses the provided OOTF based on
|
||||
// Bezier curves to perform tone-mapping. The OOTF used is adjusted based on
|
||||
// the ratio between the targeted and actual display peak luminances. In the
|
||||
// absence of HDR10+ metadata, falls back to a simple constant bezier curve.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_st2094_40;
|
||||
|
||||
// EETF from SMPTE ST 2094-10 Annex B.2, which takes into account the input
|
||||
// signal average luminance in addition to the maximum/minimum.
|
||||
//
|
||||
// Note: This does *not* currently include the subjective gain/offset/gamma
|
||||
// controls defined in Annex B.3. (Open an issue with a valid sample file if
|
||||
// you want such parameters to be respected.)
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_st2094_10;
|
||||
|
||||
// EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear
|
||||
// segment.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_bt2390;
|
||||
|
||||
// EETF from ITU-R Report BT.2446, method A. Can be used for both forward
|
||||
// and inverse tone mapping.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_bt2446a;
|
||||
|
||||
// Simple spline consisting of two polynomials, joined by a single pivot point,
|
||||
// which is tuned based on the source scene average brightness (taking into
|
||||
// account dynamic metadata if available). This function can be used
|
||||
// for both forward and inverse tone mapping.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_spline;
|
||||
|
||||
// Very simple non-linear curve. Named after Erik Reinhard.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_reinhard;
|
||||
|
||||
// Generalization of the reinhard tone mapping algorithm to support an
|
||||
// additional linear slope near black. The name is derived from its function
|
||||
// shape (ax+b)/(cx+d), which is known as a Möbius transformation.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_mobius;
|
||||
|
||||
// Piece-wise, filmic tone-mapping algorithm developed by John Hable for use in
|
||||
// Uncharted 2, inspired by a similar tone-mapping algorithm used by Kodak.
|
||||
// Popularized by its use in video games with HDR rendering. Preserves both
|
||||
// dark and bright details very well, but comes with the drawback of changing
|
||||
// the average brightness quite significantly. This is sort of similar to
|
||||
// pl_tone_map_reinhard with `reinhard_contrast=0.24`.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_hable;
|
||||
|
||||
// Fits a gamma (power) function to transfer between the source and target
|
||||
// color spaces, effectively resulting in a perceptual hard-knee joining two
|
||||
// roughly linear sections. This preserves details at all scales, but can result
|
||||
// in an image with a muted or dull appearance.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_gamma;
|
||||
|
||||
// Linearly stretches the input range to the output range, in PQ space. This
|
||||
// will preserve all details accurately, but results in a significantly
|
||||
// different average brightness. Can be used for inverse tone-mapping in
|
||||
// addition to regular tone-mapping.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_linear;
|
||||
|
||||
// Like `pl_tone_map_linear`, but in linear light (instead of PQ). Works well
|
||||
// for small range adjustments but may cause severe darkening when
|
||||
// downconverting from e.g. 10k nits to SDR.
|
||||
PL_API extern const struct pl_tone_map_function pl_tone_map_linear_light;
|
||||
|
||||
// A list of built-in tone mapping functions, terminated by NULL
|
||||
PL_API extern const struct pl_tone_map_function * const pl_tone_map_functions[];
|
||||
PL_API extern const int pl_num_tone_map_functions; // excluding trailing NULL
|
||||
|
||||
// Find the tone mapping function with the given name, or NULL on failure.
|
||||
PL_API const struct pl_tone_map_function *pl_find_tone_map_function(const char *name);
|
||||
|
||||
// Deprecated alias, do not use
|
||||
#define pl_tone_map_auto pl_tone_map_spline
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_TONE_MAPPING_H_
|
||||
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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_DAV1D_H_
|
||||
#define LIBPLACEBO_DAV1D_H_
|
||||
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/utils/upload.h>
|
||||
#include <dav1d/dav1d.h>
|
||||
|
||||
#if defined(__cplusplus) && !defined(PL_DAV1D_IMPLEMENTATION)
|
||||
# define PL_DAV1D_API
|
||||
# define PL_DAV1D_IMPLEMENTATION 0
|
||||
# warning Remember to include this file with a PL_DAV1D_IMPLEMENTATION set to 1 in \
|
||||
C translation unit to provide implementation. Suppress this warning by \
|
||||
defining PL_DAV1D_IMPLEMENTATION to 0 in C++ files.
|
||||
#elif !defined(PL_DAV1D_IMPLEMENTATION)
|
||||
# define PL_DAV1D_API static inline
|
||||
# define PL_DAV1D_IMPLEMENTATION 1
|
||||
#else
|
||||
# define PL_DAV1D_API
|
||||
#endif
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Fill in the details of a `pl_frame` from a Dav1dPicture. This function will
|
||||
// explicitly clear `out_frame`, setting all extra fields to 0. After this
|
||||
// function returns, the only missing data is information related to the plane
|
||||
// texture itself (`planes[N].texture`).
|
||||
//
|
||||
// Note: This will include all possible metadata, including HDR metadata and
|
||||
// AV1 film grain data. Users should explicitly clear this out if undesired.
|
||||
PL_DAV1D_API void pl_frame_from_dav1dpicture(struct pl_frame *out_frame,
|
||||
const Dav1dPicture *picture);
|
||||
|
||||
// Helper function to generate a `pl_color_space` struct from a Dav1dPicture.
|
||||
// Useful to update the swapchain colorspace mode dynamically (e.g. for HDR).
|
||||
PL_DAV1D_API void pl_swapchain_colors_from_dav1dpicture(struct pl_color_space *out_colors,
|
||||
const Dav1dPicture *picture);
|
||||
|
||||
struct pl_dav1d_upload_params {
|
||||
// The picture to upload. Not modified unless `asynchronous` is true.
|
||||
Dav1dPicture *picture;
|
||||
|
||||
// If true, film grain present in `picture` will be exported to the
|
||||
// `pl_frame` as well. This should be set to false unless the user has
|
||||
// disabled `Dav1dSettings.apply_grain`.
|
||||
bool film_grain;
|
||||
|
||||
// If true, libplacebo will probe for the allocation metadata set by
|
||||
// `pl_allocate_dav1dpicture`, and directly import the attached buffers
|
||||
// (saving a memcpy in some cases). Has no effect if the Dav1dPicture was
|
||||
// not allocated using `pl_allocate_dav1dpicture`.
|
||||
//
|
||||
// Note: When this is the case, `asynchronous` has no further effect -
|
||||
// uploads from attached buffers are already asynchronous.
|
||||
bool gpu_allocated;
|
||||
|
||||
// If true, `picture` will be asynchronously uploaded and unref'd
|
||||
// internally by libplacebo, and the struct passed by the user cleared to
|
||||
// {0}. This is needed to avoid `memcpy` in some cases, so setting it to
|
||||
// true is highly recommended wherever possible.
|
||||
//
|
||||
// Note: If `pl_upload_dav1dpicture` returns false, `picture` does not get
|
||||
// unref'd.
|
||||
bool asynchronous;
|
||||
};
|
||||
|
||||
#define pl_dav1d_upload_params(...) (&(struct pl_dav1d_upload_params) { __VA_ARGS__ })
|
||||
|
||||
// Very high level helper function to take a `Dav1dPicture` and upload it to
|
||||
// the GPU. Similar in spirit to `pl_upload_plane`, and the same notes apply.
|
||||
// `tex` must be an array of 3 pointers of type `pl_tex`, each
|
||||
// either pointing to a valid texture, or NULL. Returns whether successful.
|
||||
PL_DAV1D_API bool pl_upload_dav1dpicture(pl_gpu gpu,
|
||||
struct pl_frame *out_frame, pl_tex tex[3],
|
||||
const struct pl_dav1d_upload_params *params);
|
||||
|
||||
// Allocate a Dav1dPicture from persistently mapped buffers. This can be more
|
||||
// efficient than regular Dav1dPictures, especially when using the synchronous
|
||||
// `pl_upload_dav1dpicture`, or on platforms that don't support importing
|
||||
// PL_HANDLE_HOST_PTR as buffers. Returns 0 or a negative DAV1D_ERR value.
|
||||
//
|
||||
// Note: These may only be used directly as a Dav1dPicAllocator if the `gpu`
|
||||
// passed as the value of `cookie` is `pl_gpu.limits.thread_safe`. Otherwise,
|
||||
// the user must manually synchronize this to ensure it runs on the correct
|
||||
// thread.
|
||||
PL_DAV1D_API int pl_allocate_dav1dpicture(Dav1dPicture *picture, void *gpu);
|
||||
PL_DAV1D_API void pl_release_dav1dpicture(Dav1dPicture *picture, void *gpu);
|
||||
|
||||
// Mapping functions for the various Dav1dColor* enums. Note that these are not
|
||||
// quite 1:1, and even for values that exist in both, the semantics sometimes
|
||||
// differ. Some special cases (e.g. ICtCp, or XYZ) are handled differently in
|
||||
// libplacebo and libdav1d, respectively.
|
||||
PL_DAV1D_API enum pl_color_system pl_system_from_dav1d(enum Dav1dMatrixCoefficients mc);
|
||||
PL_DAV1D_API enum Dav1dMatrixCoefficients pl_system_to_dav1d(enum pl_color_system sys);
|
||||
PL_DAV1D_API enum pl_color_levels pl_levels_from_dav1d(int color_range);
|
||||
PL_DAV1D_API int pl_levels_to_dav1d(enum pl_color_levels levels);
|
||||
PL_DAV1D_API enum pl_color_primaries pl_primaries_from_dav1d(enum Dav1dColorPrimaries prim);
|
||||
PL_DAV1D_API enum Dav1dColorPrimaries pl_primaries_to_dav1d(enum pl_color_primaries prim);
|
||||
PL_DAV1D_API enum pl_color_transfer pl_transfer_from_dav1d(enum Dav1dTransferCharacteristics trc);
|
||||
PL_DAV1D_API enum Dav1dTransferCharacteristics pl_transfer_to_dav1d(enum pl_color_transfer trc);
|
||||
PL_DAV1D_API enum pl_chroma_location pl_chroma_from_dav1d(enum Dav1dChromaSamplePosition loc);
|
||||
PL_DAV1D_API enum Dav1dChromaSamplePosition pl_chroma_to_dav1d(enum pl_chroma_location loc);
|
||||
|
||||
|
||||
// Actual implementation, included as part of this header to avoid having
|
||||
// a compile-time dependency on libdav1d.
|
||||
#if PL_DAV1D_IMPLEMENTATION
|
||||
# include <libplacebo/utils/dav1d_internal.h>
|
||||
#endif
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_DAV1D_H_
|
||||
@ -0,0 +1,613 @@
|
||||
/*
|
||||
* 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_DAV1D_H_
|
||||
#error This header should be included as part of <libplacebo/utils/dav1d.h>
|
||||
#elif defined(__cplusplus)
|
||||
#error This header cannot be included from C++ define PL_DAV1D_IMPLEMENTATION appropriately
|
||||
#else
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
PL_DAV1D_API enum pl_color_system pl_system_from_dav1d(enum Dav1dMatrixCoefficients mc)
|
||||
{
|
||||
switch (mc) {
|
||||
case DAV1D_MC_IDENTITY: return PL_COLOR_SYSTEM_RGB; // or XYZ (unlikely)
|
||||
case DAV1D_MC_BT709: return PL_COLOR_SYSTEM_BT_709;
|
||||
case DAV1D_MC_UNKNOWN: return PL_COLOR_SYSTEM_UNKNOWN;
|
||||
case DAV1D_MC_FCC: return PL_COLOR_SYSTEM_UNKNOWN; // missing
|
||||
case DAV1D_MC_BT470BG: return PL_COLOR_SYSTEM_BT_601;
|
||||
case DAV1D_MC_BT601: return PL_COLOR_SYSTEM_BT_601;
|
||||
case DAV1D_MC_SMPTE240: return PL_COLOR_SYSTEM_SMPTE_240M;
|
||||
case DAV1D_MC_SMPTE_YCGCO: return PL_COLOR_SYSTEM_YCGCO;
|
||||
case DAV1D_MC_BT2020_NCL: return PL_COLOR_SYSTEM_BT_2020_NC;
|
||||
case DAV1D_MC_BT2020_CL: return PL_COLOR_SYSTEM_BT_2020_C;
|
||||
case DAV1D_MC_SMPTE2085: return PL_COLOR_SYSTEM_UNKNOWN; // missing
|
||||
case DAV1D_MC_CHROMAT_NCL: return PL_COLOR_SYSTEM_UNKNOWN; // missing
|
||||
case DAV1D_MC_CHROMAT_CL: return PL_COLOR_SYSTEM_UNKNOWN; // missing
|
||||
// Note: this colorspace is confused between PQ and HLG, which dav1d
|
||||
// requires inferring from other sources, but libplacebo makes
|
||||
// explicit. Default to PQ as it's the more common scenario.
|
||||
case DAV1D_MC_ICTCP: return PL_COLOR_SYSTEM_BT_2100_PQ;
|
||||
case DAV1D_MC_RESERVED: abort();
|
||||
}
|
||||
|
||||
return PL_COLOR_SYSTEM_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum Dav1dMatrixCoefficients pl_system_to_dav1d(enum pl_color_system sys)
|
||||
{
|
||||
switch (sys) {
|
||||
case PL_COLOR_SYSTEM_UNKNOWN: return DAV1D_MC_UNKNOWN;
|
||||
case PL_COLOR_SYSTEM_BT_601: return DAV1D_MC_BT601;
|
||||
case PL_COLOR_SYSTEM_BT_709: return DAV1D_MC_BT709;
|
||||
case PL_COLOR_SYSTEM_SMPTE_240M: return DAV1D_MC_SMPTE240;
|
||||
case PL_COLOR_SYSTEM_BT_2020_NC: return DAV1D_MC_BT2020_NCL;
|
||||
case PL_COLOR_SYSTEM_BT_2020_C: return DAV1D_MC_BT2020_CL;
|
||||
case PL_COLOR_SYSTEM_BT_2100_PQ: return DAV1D_MC_ICTCP;
|
||||
case PL_COLOR_SYSTEM_BT_2100_HLG: return DAV1D_MC_ICTCP;
|
||||
case PL_COLOR_SYSTEM_DOLBYVISION: return DAV1D_MC_UNKNOWN; // missing
|
||||
case PL_COLOR_SYSTEM_YCGCO: return DAV1D_MC_SMPTE_YCGCO;
|
||||
case PL_COLOR_SYSTEM_RGB: return DAV1D_MC_IDENTITY;
|
||||
case PL_COLOR_SYSTEM_XYZ: return DAV1D_MC_IDENTITY;
|
||||
case PL_COLOR_SYSTEM_COUNT: abort();
|
||||
}
|
||||
|
||||
return DAV1D_MC_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum pl_color_levels pl_levels_from_dav1d(int color_range)
|
||||
{
|
||||
return color_range ? PL_COLOR_LEVELS_FULL : PL_COLOR_LEVELS_LIMITED;
|
||||
}
|
||||
|
||||
PL_DAV1D_API int pl_levels_to_dav1d(enum pl_color_levels levels)
|
||||
{
|
||||
return levels == PL_COLOR_LEVELS_FULL;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum pl_color_primaries pl_primaries_from_dav1d(enum Dav1dColorPrimaries prim)
|
||||
{
|
||||
switch (prim) {
|
||||
case DAV1D_COLOR_PRI_BT709: return PL_COLOR_PRIM_BT_709;
|
||||
case DAV1D_COLOR_PRI_UNKNOWN: return PL_COLOR_PRIM_UNKNOWN;
|
||||
case DAV1D_COLOR_PRI_RESERVED: return PL_COLOR_PRIM_UNKNOWN;
|
||||
case DAV1D_COLOR_PRI_BT470M: return PL_COLOR_PRIM_BT_470M;
|
||||
case DAV1D_COLOR_PRI_BT470BG: return PL_COLOR_PRIM_BT_601_625;
|
||||
case DAV1D_COLOR_PRI_BT601: return PL_COLOR_PRIM_BT_601_525;
|
||||
case DAV1D_COLOR_PRI_SMPTE240: return PL_COLOR_PRIM_BT_601_525;
|
||||
case DAV1D_COLOR_PRI_FILM: return PL_COLOR_PRIM_FILM_C;
|
||||
case DAV1D_COLOR_PRI_BT2020: return PL_COLOR_PRIM_BT_2020;
|
||||
case DAV1D_COLOR_PRI_XYZ: return PL_COLOR_PRIM_UNKNOWN;
|
||||
case DAV1D_COLOR_PRI_SMPTE431: return PL_COLOR_PRIM_DCI_P3;
|
||||
case DAV1D_COLOR_PRI_SMPTE432: return PL_COLOR_PRIM_DISPLAY_P3;
|
||||
case DAV1D_COLOR_PRI_EBU3213: return PL_COLOR_PRIM_EBU_3213;
|
||||
}
|
||||
|
||||
return PL_COLOR_PRIM_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum Dav1dColorPrimaries pl_primaries_to_dav1d(enum pl_color_primaries prim)
|
||||
{
|
||||
switch (prim) {
|
||||
case PL_COLOR_PRIM_UNKNOWN: return DAV1D_COLOR_PRI_UNKNOWN;
|
||||
case PL_COLOR_PRIM_BT_601_525: return DAV1D_COLOR_PRI_BT601;
|
||||
case PL_COLOR_PRIM_BT_601_625: return DAV1D_COLOR_PRI_BT470BG;
|
||||
case PL_COLOR_PRIM_BT_709: return DAV1D_COLOR_PRI_BT709;
|
||||
case PL_COLOR_PRIM_BT_470M: return DAV1D_COLOR_PRI_BT470M;
|
||||
case PL_COLOR_PRIM_EBU_3213: return DAV1D_COLOR_PRI_EBU3213;
|
||||
case PL_COLOR_PRIM_BT_2020: return DAV1D_COLOR_PRI_BT2020;
|
||||
case PL_COLOR_PRIM_APPLE: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_ADOBE: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_PRO_PHOTO: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_CIE_1931: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_DCI_P3: return DAV1D_COLOR_PRI_SMPTE431;
|
||||
case PL_COLOR_PRIM_DISPLAY_P3: return DAV1D_COLOR_PRI_SMPTE432;
|
||||
case PL_COLOR_PRIM_V_GAMUT: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_S_GAMUT: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_FILM_C: return DAV1D_COLOR_PRI_FILM;
|
||||
case PL_COLOR_PRIM_ACES_AP0: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_ACES_AP1: return DAV1D_COLOR_PRI_UNKNOWN; // missing
|
||||
case PL_COLOR_PRIM_COUNT: abort();
|
||||
}
|
||||
|
||||
return DAV1D_COLOR_PRI_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum pl_color_transfer pl_transfer_from_dav1d(enum Dav1dTransferCharacteristics trc)
|
||||
{
|
||||
switch (trc) {
|
||||
case DAV1D_TRC_BT709: return PL_COLOR_TRC_BT_1886; // EOTF != OETF
|
||||
case DAV1D_TRC_UNKNOWN: return PL_COLOR_TRC_UNKNOWN;
|
||||
case DAV1D_TRC_BT470M: return PL_COLOR_TRC_GAMMA22;
|
||||
case DAV1D_TRC_BT470BG: return PL_COLOR_TRC_GAMMA28;
|
||||
case DAV1D_TRC_BT601: return PL_COLOR_TRC_BT_1886; // EOTF != OETF
|
||||
case DAV1D_TRC_SMPTE240: return PL_COLOR_TRC_BT_1886; // EOTF != OETF
|
||||
case DAV1D_TRC_LINEAR: return PL_COLOR_TRC_LINEAR;
|
||||
case DAV1D_TRC_LOG100: return PL_COLOR_TRC_UNKNOWN; // missing
|
||||
case DAV1D_TRC_LOG100_SQRT10: return PL_COLOR_TRC_UNKNOWN; // missing
|
||||
case DAV1D_TRC_IEC61966: return PL_COLOR_TRC_BT_1886; // EOTF != OETF
|
||||
case DAV1D_TRC_BT1361: return PL_COLOR_TRC_BT_1886; // ETOF != OETF
|
||||
case DAV1D_TRC_SRGB: return PL_COLOR_TRC_SRGB;
|
||||
case DAV1D_TRC_BT2020_10BIT: return PL_COLOR_TRC_BT_1886; // EOTF != OETF
|
||||
case DAV1D_TRC_BT2020_12BIT: return PL_COLOR_TRC_BT_1886; // EOTF != OETF
|
||||
case DAV1D_TRC_SMPTE2084: return PL_COLOR_TRC_PQ;
|
||||
case DAV1D_TRC_SMPTE428: return PL_COLOR_TRC_ST428;
|
||||
case DAV1D_TRC_HLG: return PL_COLOR_TRC_HLG;
|
||||
case DAV1D_TRC_RESERVED: abort();
|
||||
}
|
||||
|
||||
return PL_COLOR_TRC_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum Dav1dTransferCharacteristics pl_transfer_to_dav1d(enum pl_color_transfer trc)
|
||||
{
|
||||
switch (trc) {
|
||||
case PL_COLOR_TRC_UNKNOWN: return DAV1D_TRC_UNKNOWN;
|
||||
case PL_COLOR_TRC_BT_1886: return DAV1D_TRC_BT709; // EOTF != OETF
|
||||
case PL_COLOR_TRC_SRGB: return DAV1D_TRC_SRGB;
|
||||
case PL_COLOR_TRC_LINEAR: return DAV1D_TRC_LINEAR;
|
||||
case PL_COLOR_TRC_GAMMA18: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_GAMMA20: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_GAMMA22: return DAV1D_TRC_BT470M;
|
||||
case PL_COLOR_TRC_GAMMA24: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_GAMMA26: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_GAMMA28: return DAV1D_TRC_BT470BG;
|
||||
case PL_COLOR_TRC_ST428: return DAV1D_TRC_SMPTE428;
|
||||
case PL_COLOR_TRC_PRO_PHOTO: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_PQ: return DAV1D_TRC_SMPTE2084;
|
||||
case PL_COLOR_TRC_HLG: return DAV1D_TRC_HLG;
|
||||
case PL_COLOR_TRC_V_LOG: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_S_LOG1: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_S_LOG2: return DAV1D_TRC_UNKNOWN; // missing
|
||||
case PL_COLOR_TRC_COUNT: abort();
|
||||
}
|
||||
|
||||
return DAV1D_TRC_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum pl_chroma_location pl_chroma_from_dav1d(enum Dav1dChromaSamplePosition loc)
|
||||
{
|
||||
switch (loc) {
|
||||
case DAV1D_CHR_UNKNOWN: return PL_CHROMA_UNKNOWN;
|
||||
case DAV1D_CHR_VERTICAL: return PL_CHROMA_LEFT;
|
||||
case DAV1D_CHR_COLOCATED: return PL_CHROMA_TOP_LEFT;
|
||||
}
|
||||
|
||||
return PL_CHROMA_UNKNOWN;
|
||||
}
|
||||
|
||||
PL_DAV1D_API enum Dav1dChromaSamplePosition pl_chroma_to_dav1d(enum pl_chroma_location loc)
|
||||
{
|
||||
switch (loc) {
|
||||
case PL_CHROMA_UNKNOWN: return DAV1D_CHR_UNKNOWN;
|
||||
case PL_CHROMA_LEFT: return DAV1D_CHR_VERTICAL;
|
||||
case PL_CHROMA_CENTER: return DAV1D_CHR_UNKNOWN; // missing
|
||||
case PL_CHROMA_TOP_LEFT: return DAV1D_CHR_COLOCATED;
|
||||
case PL_CHROMA_TOP_CENTER: return DAV1D_CHR_UNKNOWN; // missing
|
||||
case PL_CHROMA_BOTTOM_LEFT: return DAV1D_CHR_UNKNOWN; // missing
|
||||
case PL_CHROMA_BOTTOM_CENTER: return DAV1D_CHR_UNKNOWN; // missing
|
||||
case PL_CHROMA_COUNT: abort();
|
||||
}
|
||||
|
||||
return DAV1D_CHR_UNKNOWN;
|
||||
}
|
||||
|
||||
static inline float pl_fixed24_8(uint32_t n)
|
||||
{
|
||||
return (float) n / (1 << 8);
|
||||
}
|
||||
|
||||
static inline float pl_fixed18_14(uint32_t n)
|
||||
{
|
||||
return (float) n / (1 << 14);
|
||||
}
|
||||
|
||||
static inline float pl_fixed0_16(uint16_t n)
|
||||
{
|
||||
return (float) n / (1 << 16);
|
||||
}
|
||||
|
||||
// Align to a power of 2
|
||||
#define PL_ALIGN2(x, align) (((x) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
PL_DAV1D_API void pl_frame_from_dav1dpicture(struct pl_frame *out,
|
||||
const Dav1dPicture *picture)
|
||||
{
|
||||
const Dav1dSequenceHeader *seq_hdr = picture->seq_hdr;
|
||||
int num_planes;
|
||||
switch (picture->p.layout) {
|
||||
case DAV1D_PIXEL_LAYOUT_I400:
|
||||
num_planes = 1;
|
||||
break;
|
||||
case DAV1D_PIXEL_LAYOUT_I420:
|
||||
case DAV1D_PIXEL_LAYOUT_I422:
|
||||
case DAV1D_PIXEL_LAYOUT_I444:
|
||||
num_planes = 3;
|
||||
break;
|
||||
default: abort();
|
||||
}
|
||||
|
||||
*out = (struct pl_frame) {
|
||||
.num_planes = num_planes,
|
||||
.planes = {
|
||||
// Components are always in order, which makes things easy
|
||||
{
|
||||
.components = 1,
|
||||
.component_mapping = {0},
|
||||
}, {
|
||||
.components = 1,
|
||||
.component_mapping = {1},
|
||||
}, {
|
||||
.components = 1,
|
||||
.component_mapping = {2},
|
||||
},
|
||||
},
|
||||
.crop = {
|
||||
0, 0, picture->p.w, picture->p.h,
|
||||
},
|
||||
.color = {
|
||||
.primaries = pl_primaries_from_dav1d(seq_hdr->pri),
|
||||
.transfer = pl_transfer_from_dav1d(seq_hdr->trc),
|
||||
},
|
||||
.repr = {
|
||||
.sys = pl_system_from_dav1d(seq_hdr->mtrx),
|
||||
.levels = pl_levels_from_dav1d(seq_hdr->color_range),
|
||||
.bits = {
|
||||
.sample_depth = PL_ALIGN2(picture->p.bpc, 8),
|
||||
.color_depth = picture->p.bpc,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (seq_hdr->mtrx == DAV1D_MC_ICTCP && seq_hdr->trc == DAV1D_TRC_HLG) {
|
||||
|
||||
// dav1d makes no distinction between PQ and HLG ICtCp, so we need
|
||||
// to manually fix it in the case that we have HLG ICtCp data.
|
||||
out->repr.sys = PL_COLOR_SYSTEM_BT_2100_HLG;
|
||||
|
||||
} else if (seq_hdr->mtrx == DAV1D_MC_IDENTITY &&
|
||||
seq_hdr->pri == DAV1D_COLOR_PRI_XYZ)
|
||||
{
|
||||
|
||||
// dav1d handles this as a special case, but doesn't provide an
|
||||
// explicit flag for it either, so we have to resort to this ugly hack,
|
||||
// even though CIE 1931 RGB *is* a valid thing in principle!
|
||||
out->repr.sys= PL_COLOR_SYSTEM_XYZ;
|
||||
|
||||
} else if (!out->repr.sys) {
|
||||
|
||||
// PL_COLOR_SYSTEM_UNKNOWN maps to RGB, so hard-code this one
|
||||
out->repr.sys = pl_color_system_guess_ycbcr(picture->p.w, picture->p.h);
|
||||
}
|
||||
|
||||
const Dav1dContentLightLevel *cll = picture->content_light;
|
||||
if (cll) {
|
||||
out->color.hdr.max_cll = cll->max_content_light_level;
|
||||
out->color.hdr.max_fall = cll->max_frame_average_light_level;
|
||||
}
|
||||
|
||||
// This overrides the CLL values above, if both are present
|
||||
const Dav1dMasteringDisplay *md = picture->mastering_display;
|
||||
if (md) {
|
||||
out->color.hdr.max_luma = pl_fixed24_8(md->max_luminance);
|
||||
out->color.hdr.min_luma = pl_fixed18_14(md->min_luminance);
|
||||
out->color.hdr.prim = (struct pl_raw_primaries) {
|
||||
.red.x = pl_fixed0_16(md->primaries[0][0]),
|
||||
.red.y = pl_fixed0_16(md->primaries[0][1]),
|
||||
.green.x = pl_fixed0_16(md->primaries[1][0]),
|
||||
.green.y = pl_fixed0_16(md->primaries[1][1]),
|
||||
.blue.x = pl_fixed0_16(md->primaries[2][0]),
|
||||
.blue.y = pl_fixed0_16(md->primaries[2][1]),
|
||||
.white.x = pl_fixed0_16(md->white_point[0]),
|
||||
.white.y = pl_fixed0_16(md->white_point[1]),
|
||||
};
|
||||
}
|
||||
|
||||
if (picture->frame_hdr->film_grain.present) {
|
||||
const Dav1dFilmGrainData *fg = &picture->frame_hdr->film_grain.data;
|
||||
out->film_grain = (struct pl_film_grain_data) {
|
||||
.type = PL_FILM_GRAIN_AV1,
|
||||
.seed = fg->seed,
|
||||
.params.av1 = {
|
||||
.num_points_y = fg->num_y_points,
|
||||
.chroma_scaling_from_luma = fg->chroma_scaling_from_luma,
|
||||
.num_points_uv = { fg->num_uv_points[0], fg->num_uv_points[1] },
|
||||
.scaling_shift = fg->scaling_shift,
|
||||
.ar_coeff_lag = fg->ar_coeff_lag,
|
||||
.ar_coeff_shift = (int) fg->ar_coeff_shift,
|
||||
.grain_scale_shift = fg->grain_scale_shift,
|
||||
.uv_mult = { fg->uv_mult[0], fg->uv_mult[1] },
|
||||
.uv_mult_luma = { fg->uv_luma_mult[0], fg->uv_luma_mult[1] },
|
||||
.uv_offset = { fg->uv_offset[0], fg->uv_offset[1] },
|
||||
.overlap = fg->overlap_flag,
|
||||
},
|
||||
};
|
||||
|
||||
struct pl_av1_grain_data *av1 = &out->film_grain.params.av1;
|
||||
memcpy(av1->points_y, fg->y_points, sizeof(av1->points_y));
|
||||
memcpy(av1->points_uv, fg->uv_points, sizeof(av1->points_uv));
|
||||
memcpy(av1->ar_coeffs_y, fg->ar_coeffs_y, sizeof(av1->ar_coeffs_y));
|
||||
memcpy(av1->ar_coeffs_uv[0], fg->ar_coeffs_uv[0], sizeof(av1->ar_coeffs_uv[0]));
|
||||
memcpy(av1->ar_coeffs_uv[1], fg->ar_coeffs_uv[1], sizeof(av1->ar_coeffs_uv[1]));
|
||||
}
|
||||
|
||||
switch (picture->p.layout) {
|
||||
case DAV1D_PIXEL_LAYOUT_I400:
|
||||
case DAV1D_PIXEL_LAYOUT_I444:
|
||||
break;
|
||||
case DAV1D_PIXEL_LAYOUT_I420:
|
||||
case DAV1D_PIXEL_LAYOUT_I422:
|
||||
// Only set the chroma location for definitely subsampled images
|
||||
pl_frame_set_chroma_location(out, pl_chroma_from_dav1d(seq_hdr->chr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PL_DAV1D_API void pl_swapchain_colors_from_dav1dpicture(struct pl_swapchain_colors *out_colors,
|
||||
const Dav1dPicture *picture)
|
||||
{
|
||||
struct pl_frame frame;
|
||||
pl_frame_from_dav1dpicture(&frame, picture);
|
||||
|
||||
*out_colors = (struct pl_swapchain_colors) {
|
||||
.primaries = frame.color.primaries,
|
||||
.transfer = frame.color.transfer,
|
||||
};
|
||||
|
||||
const Dav1dContentLightLevel *cll = picture->content_light;
|
||||
if (cll) {
|
||||
out_colors->hdr.max_cll = cll->max_content_light_level;
|
||||
out_colors->hdr.max_fall = cll->max_frame_average_light_level;
|
||||
}
|
||||
|
||||
const Dav1dMasteringDisplay *md = picture->mastering_display;
|
||||
if (md) {
|
||||
out_colors->hdr.min_luma = pl_fixed18_14(md->min_luminance);
|
||||
out_colors->hdr.max_luma = pl_fixed24_8(md->max_luminance);
|
||||
out_colors->hdr.prim.red.x = pl_fixed0_16(md->primaries[0][0]);
|
||||
out_colors->hdr.prim.red.y = pl_fixed0_16(md->primaries[0][1]);
|
||||
out_colors->hdr.prim.green.x = pl_fixed0_16(md->primaries[1][0]);
|
||||
out_colors->hdr.prim.green.y = pl_fixed0_16(md->primaries[1][1]);
|
||||
out_colors->hdr.prim.blue.x = pl_fixed0_16(md->primaries[2][0]);
|
||||
out_colors->hdr.prim.blue.y = pl_fixed0_16(md->primaries[2][1]);
|
||||
out_colors->hdr.prim.white.x = pl_fixed0_16(md->white_point[0]);
|
||||
out_colors->hdr.prim.white.y = pl_fixed0_16(md->white_point[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#define PL_MAGIC0 0x2c2a1269
|
||||
#define PL_MAGIC1 0xc6d02577
|
||||
|
||||
struct pl_dav1dalloc {
|
||||
uint32_t magic[2];
|
||||
pl_gpu gpu;
|
||||
pl_buf buf;
|
||||
};
|
||||
|
||||
struct pl_dav1dref {
|
||||
Dav1dPicture pic;
|
||||
uint8_t count;
|
||||
};
|
||||
|
||||
static void pl_dav1dpicture_unref(void *priv)
|
||||
{
|
||||
struct pl_dav1dref *ref = priv;
|
||||
if (--ref->count == 0) {
|
||||
dav1d_picture_unref(&ref->pic);
|
||||
free(ref);
|
||||
}
|
||||
}
|
||||
|
||||
PL_DAV1D_API bool pl_upload_dav1dpicture(pl_gpu gpu,
|
||||
struct pl_frame *out,
|
||||
pl_tex tex[3],
|
||||
const struct pl_dav1d_upload_params *params)
|
||||
{
|
||||
Dav1dPicture *pic = params->picture;
|
||||
pl_frame_from_dav1dpicture(out, pic);
|
||||
if (!params->film_grain)
|
||||
out->film_grain.type = PL_FILM_GRAIN_NONE;
|
||||
|
||||
const int bytes = (pic->p.bpc + 7) / 8; // rounded up
|
||||
int sub_x = 0, sub_y = 0;
|
||||
switch (pic->p.layout) {
|
||||
case DAV1D_PIXEL_LAYOUT_I400:
|
||||
case DAV1D_PIXEL_LAYOUT_I444:
|
||||
break;
|
||||
case DAV1D_PIXEL_LAYOUT_I420:
|
||||
sub_x = sub_y = 1;
|
||||
break;
|
||||
case DAV1D_PIXEL_LAYOUT_I422:
|
||||
sub_x = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
struct pl_plane_data data[3] = {
|
||||
{
|
||||
// Y plane
|
||||
.type = PL_FMT_UNORM,
|
||||
.width = pic->p.w,
|
||||
.height = pic->p.h,
|
||||
.pixel_stride = bytes,
|
||||
.component_size = {bytes * 8},
|
||||
.component_map = {0},
|
||||
}, {
|
||||
// U plane
|
||||
.type = PL_FMT_UNORM,
|
||||
.width = pic->p.w >> sub_x,
|
||||
.height = pic->p.h >> sub_y,
|
||||
.pixel_stride = bytes,
|
||||
.component_size = {bytes * 8},
|
||||
.component_map = {1},
|
||||
}, {
|
||||
// V plane
|
||||
.type = PL_FMT_UNORM,
|
||||
.width = pic->p.w >> sub_x,
|
||||
.height = pic->p.h >> sub_y,
|
||||
.pixel_stride = bytes,
|
||||
.component_size = {bytes * 8},
|
||||
.component_map = {2},
|
||||
},
|
||||
};
|
||||
|
||||
pl_buf buf = NULL;
|
||||
struct pl_dav1dalloc *alloc = params->gpu_allocated ? pic->allocator_data : NULL;
|
||||
struct pl_dav1dref *ref = NULL;
|
||||
|
||||
if (alloc && alloc->magic[0] == PL_MAGIC0 && alloc->magic[1] == PL_MAGIC1) {
|
||||
// Re-use pre-allocated buffers directly
|
||||
assert(alloc->gpu == gpu);
|
||||
buf = alloc->buf;
|
||||
} else if (params->asynchronous && gpu->limits.callbacks) {
|
||||
ref = malloc(sizeof(*ref));
|
||||
if (!ref)
|
||||
return false;
|
||||
memcpy(&ref->pic, pic, sizeof(Dav1dPicture));
|
||||
ref->count = out->num_planes;
|
||||
}
|
||||
|
||||
for (int p = 0; p < out->num_planes; p++) {
|
||||
ptrdiff_t stride = p > 0 ? pic->stride[1] : pic->stride[0];
|
||||
if (stride < 0) {
|
||||
data[p].pixels = (uint8_t *) pic->data[p] + stride * (data[p].height - 1);
|
||||
data[p].row_stride = -stride;
|
||||
out->planes[p].flipped = true;
|
||||
} else {
|
||||
data[p].pixels = pic->data[p];
|
||||
data[p].row_stride = stride;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
data[p].buf = buf;
|
||||
data[p].buf_offset = (uintptr_t) data[p].pixels - (uintptr_t) buf->data;
|
||||
data[p].pixels = NULL;
|
||||
} else if (ref) {
|
||||
data[p].priv = ref;
|
||||
data[p].callback = pl_dav1dpicture_unref;
|
||||
}
|
||||
|
||||
if (!pl_upload_plane(gpu, &out->planes[p], &tex[p], &data[p])) {
|
||||
free(ref);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->asynchronous) {
|
||||
if (ref) {
|
||||
*pic = (Dav1dPicture) {0};
|
||||
} else {
|
||||
dav1d_picture_unref(pic);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PL_DAV1D_API int pl_allocate_dav1dpicture(Dav1dPicture *p, void *cookie)
|
||||
{
|
||||
pl_gpu gpu = cookie;
|
||||
if (!gpu->limits.max_mapped_size || !gpu->limits.host_cached ||
|
||||
!gpu->limits.buf_transfer)
|
||||
{
|
||||
return DAV1D_ERR(ENOTSUP);
|
||||
}
|
||||
|
||||
// Copied from dav1d_default_picture_alloc
|
||||
const int hbd = p->p.bpc > 8;
|
||||
const int aligned_w = PL_ALIGN2(p->p.w, 128);
|
||||
const int aligned_h = PL_ALIGN2(p->p.h, 128);
|
||||
const int has_chroma = p->p.layout != DAV1D_PIXEL_LAYOUT_I400;
|
||||
const int ss_ver = p->p.layout == DAV1D_PIXEL_LAYOUT_I420;
|
||||
const int ss_hor = p->p.layout != DAV1D_PIXEL_LAYOUT_I444;
|
||||
p->stride[0] = aligned_w << hbd;
|
||||
p->stride[1] = has_chroma ? (aligned_w >> ss_hor) << hbd : 0;
|
||||
|
||||
// Align strides up to multiples of the GPU performance hints
|
||||
p->stride[0] = PL_ALIGN2(p->stride[0], gpu->limits.align_tex_xfer_pitch);
|
||||
p->stride[1] = PL_ALIGN2(p->stride[1], gpu->limits.align_tex_xfer_pitch);
|
||||
|
||||
// Aligning offsets to 4 also implicitly aligns to the texel alignment (1 or 2)
|
||||
size_t off_align = PL_ALIGN2(gpu->limits.align_tex_xfer_offset, 4);
|
||||
const size_t y_sz = PL_ALIGN2(p->stride[0] * aligned_h, off_align);
|
||||
const size_t uv_sz = PL_ALIGN2(p->stride[1] * (aligned_h >> ss_ver), off_align);
|
||||
|
||||
// The extra DAV1D_PICTURE_ALIGNMENTs are to brute force plane alignment,
|
||||
// even in the case that the driver gives us insane alignments
|
||||
const size_t pic_size = y_sz + 2 * uv_sz;
|
||||
const size_t total_size = pic_size + DAV1D_PICTURE_ALIGNMENT * 4;
|
||||
|
||||
// Validate size limitations
|
||||
if (total_size > gpu->limits.max_mapped_size)
|
||||
return DAV1D_ERR(ENOMEM);
|
||||
|
||||
pl_buf buf = pl_buf_create(gpu, pl_buf_params(
|
||||
.size = total_size,
|
||||
.host_mapped = true,
|
||||
.memory_type = PL_BUF_MEM_HOST,
|
||||
));
|
||||
|
||||
if (!buf)
|
||||
return DAV1D_ERR(ENOMEM);
|
||||
|
||||
struct pl_dav1dalloc *alloc = malloc(sizeof(struct pl_dav1dalloc));
|
||||
if (!alloc) {
|
||||
pl_buf_destroy(gpu, &buf);
|
||||
return DAV1D_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
*alloc = (struct pl_dav1dalloc) {
|
||||
.magic = { PL_MAGIC0, PL_MAGIC1 },
|
||||
.gpu = gpu,
|
||||
.buf = buf,
|
||||
};
|
||||
|
||||
assert(buf->data);
|
||||
uintptr_t base = (uintptr_t) buf->data, data[3];
|
||||
data[0] = PL_ALIGN2(base, DAV1D_PICTURE_ALIGNMENT);
|
||||
data[1] = PL_ALIGN2(data[0] + y_sz, DAV1D_PICTURE_ALIGNMENT);
|
||||
data[2] = PL_ALIGN2(data[1] + uv_sz, DAV1D_PICTURE_ALIGNMENT);
|
||||
|
||||
p->allocator_data = alloc;
|
||||
p->data[0] = (void *) data[0];
|
||||
p->data[1] = (void *) data[1];
|
||||
p->data[2] = (void *) data[2];
|
||||
return 0;
|
||||
}
|
||||
|
||||
PL_DAV1D_API void pl_release_dav1dpicture(Dav1dPicture *p, void *cookie)
|
||||
{
|
||||
struct pl_dav1dalloc *alloc = p->allocator_data;
|
||||
if (!alloc)
|
||||
return;
|
||||
|
||||
assert(alloc->magic[0] == PL_MAGIC0);
|
||||
assert(alloc->magic[1] == PL_MAGIC1);
|
||||
assert(alloc->gpu == cookie);
|
||||
pl_buf_destroy(alloc->gpu, &alloc->buf);
|
||||
free(alloc);
|
||||
|
||||
p->data[0] = p->data[1] = p->data[2] = p->allocator_data = NULL;
|
||||
}
|
||||
|
||||
#undef PL_ALIGN2
|
||||
#undef PL_MAGIC0
|
||||
#undef PL_MAGIC1
|
||||
|
||||
#endif // LIBPLACEBO_DAV1D_H_
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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_DOLBYVISION_H_
|
||||
#define LIBPLACEBO_DOLBYVISION_H_
|
||||
|
||||
#include <libplacebo/colorspace.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// Parses the Dolby Vision RPU, and sets the `pl_hdr_metadata` dynamic
|
||||
// brightness metadata fields accordingly.
|
||||
//
|
||||
// Note: requires `PL_HAVE_LIBDOVI` to be defined, no-op otherwise.
|
||||
PL_API void pl_hdr_metadata_from_dovi_rpu(struct pl_hdr_metadata *out,
|
||||
const uint8_t *buf, size_t size);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_DOLBYVISION_H_
|
||||
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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_FRAME_QUEUE_H
|
||||
#define LIBPLACEBO_FRAME_QUEUE_H
|
||||
|
||||
#include <libplacebo/renderer.h>
|
||||
#include <libplacebo/shaders/deinterlacing.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// An abstraction layer for automatically turning a conceptual stream of
|
||||
// (frame, pts) pairs, as emitted by a decoder or filter graph, into a
|
||||
// `pl_frame_mix` suitable for `pl_render_image_mix`.
|
||||
//
|
||||
// This API ensures that minimal work is performed (e.g. only mapping frames
|
||||
// that are actually required), while also satisfying the requirements
|
||||
// of any configured frame mixer.
|
||||
//
|
||||
// Thread-safety: Safe
|
||||
typedef struct pl_queue_t *pl_queue;
|
||||
|
||||
enum pl_queue_status {
|
||||
PL_QUEUE_OK, // success
|
||||
PL_QUEUE_EOF, // no more frames are available
|
||||
PL_QUEUE_MORE, // more frames needed, but not (yet) available
|
||||
PL_QUEUE_ERR = -1, // some unknown error occurred while retrieving frames
|
||||
};
|
||||
|
||||
struct pl_source_frame {
|
||||
// The frame's presentation timestamp, in seconds relative to the first
|
||||
// frame. These must be monotonically increasing for subsequent frames.
|
||||
// To implement a discontinuous jump, users must explicitly reset the
|
||||
// frame queue with `pl_queue_reset` and restart from PTS 0.0.
|
||||
double pts;
|
||||
|
||||
// The frame's duration. This is not needed in normal scenarios, as the
|
||||
// FPS can be inferred from the `pts` values themselves. Providing it
|
||||
// only helps initialize the value for initial frames, which can smooth
|
||||
// out the interpolation weights. Its use is also highly recommended
|
||||
// when displaying interlaced frames. (Optional)
|
||||
float duration;
|
||||
|
||||
// If set to something other than PL_FIELD_NONE, this source frame is
|
||||
// marked as interlaced. It will be split up into two separate frames
|
||||
// internally, and exported to the resulting `pl_frame_mix` as a pair of
|
||||
// fields, referencing the corresponding previous and next frames. The
|
||||
// first field will have the same PTS as `pts`, and the second field will
|
||||
// be inserted at the timestamp `pts + duration/2`.
|
||||
//
|
||||
// Note: As a result of FPS estimates being unreliable around streams with
|
||||
// mixed FPS (or when mixing interlaced and progressive frames), it's
|
||||
// highly recommended to always specify a valid `duration` for interlaced
|
||||
// frames.
|
||||
enum pl_field first_field;
|
||||
|
||||
// Abstract frame data itself. To allow mapping frames only when they're
|
||||
// actually needed, frames use a lazy representation. The provided
|
||||
// callbacks will be invoked to interface with it.
|
||||
void *frame_data;
|
||||
|
||||
// This will be called to map the frame to the GPU, only if needed.
|
||||
//
|
||||
// `tex` is a pointer to an array of 4 texture objects (or NULL), which
|
||||
// *may* serve as backing storage for the texture being mapped. These are
|
||||
// intended to be recreated by `map`, e.g. using `pl_tex_recreate` or
|
||||
// `pl_upload_plane` as appropriate. They will be managed internally by
|
||||
// `pl_queue` and destroyed at some unspecified future point in time.
|
||||
//
|
||||
// Note: If `map` fails, it will not be retried, nor will `discard` be run.
|
||||
// The user should clean up state in this case.
|
||||
bool (*map)(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src,
|
||||
struct pl_frame *out_frame);
|
||||
|
||||
// If present, this will be called on frames that are done being used by
|
||||
// `pl_queue`. This may be useful to e.g. unmap textures backed by external
|
||||
// APIs such as hardware decoders. (Optional)
|
||||
void (*unmap)(pl_gpu gpu, struct pl_frame *frame, const struct pl_source_frame *src);
|
||||
|
||||
// This function will be called for frames that are deemed unnecessary
|
||||
// (e.g. never became visible) and should instead be cleanly freed.
|
||||
// (Optional)
|
||||
void (*discard)(const struct pl_source_frame *src);
|
||||
};
|
||||
|
||||
// Create a new, empty frame queue.
|
||||
//
|
||||
// It's highly recommended to fully render a single frame with `pts == 0.0`,
|
||||
// and flush the GPU pipeline with `pl_gpu_finish`, prior to starting the timed
|
||||
// playback loop.
|
||||
PL_API pl_queue pl_queue_create(pl_gpu gpu);
|
||||
PL_API void pl_queue_destroy(pl_queue *queue);
|
||||
|
||||
// Explicitly clear the queue. This is essentially equivalent to destroying
|
||||
// and recreating the queue, but preserves any internal memory allocations.
|
||||
//
|
||||
// Note: Calling `pl_queue_reset` may block, if another thread is currently
|
||||
// blocked on a different `pl_queue_*` call.
|
||||
PL_API void pl_queue_reset(pl_queue queue);
|
||||
|
||||
// Explicitly push a frame. This is an alternative way to feed the frame queue
|
||||
// with incoming frames, the other method being the asynchronous callback
|
||||
// specified as `pl_queue_params.get_frame`. Both methods may be used
|
||||
// simultaneously, although providing `get_frame` is recommended since it
|
||||
// avoids the risk of the queue underrunning.
|
||||
//
|
||||
// When no more frames are available, call this function with `frame == NULL`
|
||||
// to indicate EOF and begin draining the frame queue.
|
||||
PL_API void pl_queue_push(pl_queue queue, const struct pl_source_frame *frame);
|
||||
|
||||
// Variant of `pl_queue_push` that blocks while the queue is judged
|
||||
// (internally) to be "too full". This is useful for asynchronous decoder loops
|
||||
// in order to prevent the queue from exhausting available RAM if frames are
|
||||
// decoded significantly faster than they're displayed.
|
||||
//
|
||||
// The given `timeout` parameter specifies how long to wait before giving up,
|
||||
// in nanoseconds. Returns false if this timeout was reached.
|
||||
PL_API bool pl_queue_push_block(pl_queue queue, uint64_t timeout,
|
||||
const struct pl_source_frame *frame);
|
||||
|
||||
struct pl_queue_params {
|
||||
// The PTS of the frame that will be rendered. This should be set to the
|
||||
// timestamp (in seconds) of the next vsync, relative to the initial frame.
|
||||
//
|
||||
// These must be monotonically increasing. To implement a discontinuous
|
||||
// jump, users must explicitly reset the frame queue with `pl_queue_reset`
|
||||
// and restart from PTS 0.0.
|
||||
double pts;
|
||||
|
||||
// The radius of the configured mixer. This should be set to the value
|
||||
// as returned by `pl_frame_mix_radius`.
|
||||
float radius;
|
||||
|
||||
// The estimated duration of a vsync, in seconds. This will only be used as
|
||||
// a hint, the true value will be estimated by comparing `pts` timestamps
|
||||
// between calls to `pl_queue_update`. (Optional)
|
||||
float vsync_duration;
|
||||
|
||||
// If the difference between the (estimated) vsync duration and the
|
||||
// (measured) frame duration is smaller than this threshold, silently
|
||||
// disable interpolation and switch to ZOH semantics instead.
|
||||
//
|
||||
// For example, a value of 0.01 allows the FPS to differ by up to 1%
|
||||
// without being interpolated. Note that this will result in a continuous
|
||||
// phase drift unless also compensated for by the user, which will
|
||||
// eventually resulted in a dropped or duplicated frame. (Though this can
|
||||
// be preferable to seeing that same phase drift result in a temporally
|
||||
// smeared image)
|
||||
float interpolation_threshold;
|
||||
|
||||
// Specifies how long `pl_queue_update` will wait for frames to become
|
||||
// available, in nanoseconds, before giving up and returning with
|
||||
// QUEUE_MORE.
|
||||
//
|
||||
// If `get_frame` is provided, this value is ignored by `pl_queue` and
|
||||
// should instead be interpreted by the provided callback.
|
||||
uint64_t timeout;
|
||||
|
||||
// This callback will be used to pull new frames from the decoder. It may
|
||||
// block if needed. The user is responsible for setting appropriate time
|
||||
// limits and/or returning and interpreting QUEUE_MORE as sensible.
|
||||
//
|
||||
// Providing this callback is entirely optional. Users can instead choose
|
||||
// to manually feed the frame queue with new frames using `pl_queue_push`.
|
||||
enum pl_queue_status (*get_frame)(struct pl_source_frame *out_frame,
|
||||
const struct pl_queue_params *params);
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#define pl_queue_params(...) (&(struct pl_queue_params) { __VA_ARGS__ })
|
||||
|
||||
// Advance the frame queue's internal state to the target timestamp. Any frames
|
||||
// which are no longer needed (i.e. too far in the past) are automatically
|
||||
// unmapped and evicted. Any future frames which are needed to fill the queue
|
||||
// must either have been pushed in advance, or will be requested using the
|
||||
// provided `get_frame` callback. If you call this on `out_mix == NULL`, the
|
||||
// queue state will advance, but no frames will be mapped.
|
||||
//
|
||||
// This function may return with PL_QUEUE_MORE, in which case the user may wish
|
||||
// to ensure more frames are available and then re-run this function with the
|
||||
// same parameters. In this case, `out_mix` is still written to, but it may be
|
||||
// incomplete (or even contain no frames at all). Additionally, when the source
|
||||
// contains interlaced frames (see `pl_source_frame.first_field`), this
|
||||
// function may return with PL_QUEUE_MORE if a frame is missing references to
|
||||
// a future frame.
|
||||
//
|
||||
// The resulting mix of frames in `out_mix` will represent the neighbourhood of
|
||||
// the target timestamp, and can be passed to `pl_render_image_mix` as-is.
|
||||
//
|
||||
// Note: `out_mix` will only remain valid until the next call to
|
||||
// `pl_queue_update` or `pl_queue_reset`.
|
||||
PL_API enum pl_queue_status pl_queue_update(pl_queue queue, struct pl_frame_mix *out_mix,
|
||||
const struct pl_queue_params *params);
|
||||
|
||||
// Returns a pl_queue's internal estimates for FPS and VPS (vsyncs per second).
|
||||
// Returns 0.0 if no estimate is available.
|
||||
PL_API float pl_queue_estimate_fps(pl_queue queue);
|
||||
PL_API float pl_queue_estimate_vps(pl_queue queue);
|
||||
|
||||
// Returns the number of frames currently contained in a pl_queue.
|
||||
PL_API int pl_queue_num_frames(pl_queue queue);
|
||||
|
||||
// Inspect the contents of the Nth queued frame. Returns false if `idx` is
|
||||
// out of range.
|
||||
//
|
||||
// Warning: No guarantee is made to ensure validity of `out->frame_data`
|
||||
// after this call. In particular, pl_queue_* calls made from another thread
|
||||
// may call `discard()` on the frame in question. The user bears responsibility
|
||||
// to avoid accessing `out->frame_data` in a multi-threaded scenario unless
|
||||
// an external guarantee can be made that the frame won't be dequeued until
|
||||
// it is done being used by the user.
|
||||
PL_API bool pl_queue_peek(pl_queue queue, int idx, struct pl_source_frame *out);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_FRAME_QUEUE_H
|
||||
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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_LIBAV_H_
|
||||
#define LIBPLACEBO_LIBAV_H_
|
||||
|
||||
#include <libplacebo/config.h>
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/shaders/deinterlacing.h>
|
||||
#include <libplacebo/utils/upload.h>
|
||||
|
||||
#if defined(__cplusplus) && !defined(PL_LIBAV_IMPLEMENTATION)
|
||||
# define PL_LIBAV_API
|
||||
# define PL_LIBAV_IMPLEMENTATION 0
|
||||
# warning Remember to include this file with a PL_LIBAV_IMPLEMENTATION set to 1 in \
|
||||
C translation unit to provide implementation. Suppress this warning by \
|
||||
defining PL_LIBAV_IMPLEMENTATION to 0 in C++ files.
|
||||
#elif !defined(PL_LIBAV_IMPLEMENTATION)
|
||||
# define PL_LIBAV_API static inline
|
||||
# define PL_LIBAV_IMPLEMENTATION 1
|
||||
#else
|
||||
# define PL_LIBAV_API
|
||||
#endif
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/frame.h>
|
||||
#include <libavutil/version.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 16, 100) && defined(PL_HAVE_DOVI)
|
||||
# define PL_HAVE_LAV_DOLBY_VISION
|
||||
# include <libavutil/dovi_meta.h>
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 61, 100)
|
||||
# define PL_HAVE_LAV_FILM_GRAIN
|
||||
# include <libavutil/film_grain_params.h>
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 25, 100)
|
||||
# define PL_HAVE_LAV_HDR
|
||||
# include <libavutil/hdr_dynamic_metadata.h>
|
||||
# include <libavutil/mastering_display_metadata.h>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Important note: For support for AVVkFrame, which depends on <vulkan.h>,
|
||||
// users *SHOULD* include <vulkan/vulkan.h> manually before this header.
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Fill in the details of a `pl_frame` from an AVFrame. This function will
|
||||
// explicitly clear `out_frame`, setting all extra fields to 0. After this
|
||||
// function returns, the only missing data is information related to the plane
|
||||
// texture itself (`planes[N].texture`), as well as any overlays (e.g.
|
||||
// subtitles).
|
||||
//
|
||||
// Note: If the AVFrame contains an embedded ICC profile or H.274 film grain
|
||||
// metadata, the resulting `out_image->profile` will reference this pointer,
|
||||
// meaning that in general, the `pl_frame` is only guaranteed to be valid as
|
||||
// long as the AVFrame is not freed.
|
||||
//
|
||||
// Note: This will ignore Dolby Vision metadata by default (to avoid leaking
|
||||
// memory), either switch to pl_map_avframe_ex or do it manually using
|
||||
// pl_map_dovi_metadata.
|
||||
PL_LIBAV_API void pl_frame_from_avframe(struct pl_frame *out_frame, const AVFrame *frame);
|
||||
|
||||
// Deprecated aliases for backwards compatibility
|
||||
#define pl_image_from_avframe pl_frame_from_avframe
|
||||
#define pl_target_from_avframe pl_frame_from_avframe
|
||||
|
||||
// Copy extra metadata from an AVStream to a pl_frame. This should be called
|
||||
// after `pl_frame_from_avframe` or `pl_map_avframe` (respectively), and sets
|
||||
// metadata associated with stream-level side data. This is needed because
|
||||
// FFmpeg rather annoyingly does not propagate stream-level metadata to frames.
|
||||
PL_LIBAV_API void pl_frame_copy_stream_props(struct pl_frame *out_frame,
|
||||
const AVStream *stream);
|
||||
|
||||
#ifdef PL_HAVE_LAV_HDR
|
||||
struct pl_av_hdr_metadata {
|
||||
// All fields are optional and may be passed as `NULL`.
|
||||
const AVMasteringDisplayMetadata *mdm;
|
||||
const AVContentLightMetadata *clm;
|
||||
const AVDynamicHDRPlus *dhp;
|
||||
};
|
||||
|
||||
// Helper function to update a `pl_hdr_metadata` struct from HDR10/HDR10+
|
||||
// metadata in the FFmpeg format. Unspecified/invalid elements will be left
|
||||
// uninitialized in `out`.
|
||||
PL_LIBAV_API void pl_map_hdr_metadata(struct pl_hdr_metadata *out,
|
||||
const struct pl_av_hdr_metadata *metadata);
|
||||
#endif
|
||||
|
||||
#ifdef PL_HAVE_LAV_DOLBY_VISION
|
||||
// Helper function to map Dolby Vision metadata from the FFmpeg format.
|
||||
PL_LIBAV_API void pl_map_dovi_metadata(struct pl_dovi_metadata *out,
|
||||
const AVDOVIMetadata *metadata);
|
||||
|
||||
// Helper function to map Dolby Vision metadata from the FFmpeg format
|
||||
// to `pl_dovi_metadata`, and adds it to the `pl_frame`.
|
||||
// The `pl_frame` colorspace fields and HDR struct are also updated with
|
||||
// values from the `AVDOVIMetadata`.
|
||||
//
|
||||
// Note: The `pl_dovi_metadata` must be allocated externally.
|
||||
// Also, currently the metadata is only used if the `AVDOVIRpuDataHeader`
|
||||
// `disable_residual_flag` field is not zero and can be checked before allocating.
|
||||
PL_LIBAV_API void pl_frame_map_avdovi_metadata(struct pl_frame *out_frame,
|
||||
struct pl_dovi_metadata *dovi,
|
||||
const AVDOVIMetadata *metadata);
|
||||
#endif
|
||||
|
||||
// Helper function to test if a pixfmt would be supported by the GPU.
|
||||
// Essentially, this can be used to check if `pl_map_avframe` would work for a
|
||||
// given AVPixelFormat, without actually uploading or allocating anything.
|
||||
PL_LIBAV_API bool pl_test_pixfmt(pl_gpu gpu, enum AVPixelFormat pixfmt);
|
||||
|
||||
// Variant of `pl_test_pixfmt` that also tests for the given capabilities
|
||||
// being present. Note that in the presence of hardware accelerated frames,
|
||||
// this cannot be tested without frame-specific information (i.e. swformat),
|
||||
// but in practice this should be a non-issue as GPU-native hwformats will
|
||||
// probably be fully supported.
|
||||
PL_LIBAV_API bool pl_test_pixfmt_caps(pl_gpu gpu, enum AVPixelFormat pixfmt,
|
||||
enum pl_fmt_caps caps);
|
||||
|
||||
// Like `pl_frame_from_avframe`, but the texture pointers are also initialized
|
||||
// to ensure they have the correct size and format to match the AVframe.
|
||||
// Similar in spirit to `pl_recreate_plane`, and the same notes apply. `tex`
|
||||
// must be an array of 4 pointers of type `pl_tex`, each either
|
||||
// pointing to a valid texture, or NULL. Returns whether successful.
|
||||
PL_LIBAV_API bool pl_frame_recreate_from_avframe(pl_gpu gpu, struct pl_frame *out_frame,
|
||||
pl_tex tex[4], const AVFrame *frame);
|
||||
|
||||
struct pl_avframe_params {
|
||||
// The AVFrame to map. Required.
|
||||
const AVFrame *frame;
|
||||
|
||||
// Backing textures for frame data. Required for all non-hwdec formats.
|
||||
// This must point to an array of four valid textures (or NULL entries).
|
||||
//
|
||||
// Note: Not cleaned up by `pl_unmap_avframe`. The intent is for users to
|
||||
// re-use this texture array for subsequent frames, to avoid texture
|
||||
// creation/destruction overhead.
|
||||
pl_tex *tex;
|
||||
|
||||
// Also map Dolby Vision metadata (if supported). Note that this also
|
||||
// overrides the colorimetry metadata (forces BT.2020+PQ).
|
||||
bool map_dovi;
|
||||
};
|
||||
|
||||
#define PL_AVFRAME_DEFAULTS \
|
||||
.map_dovi = true,
|
||||
|
||||
#define pl_avframe_params(...) (&(struct pl_avframe_params) { PL_AVFRAME_DEFAULTS __VA_ARGS__ })
|
||||
|
||||
// Very high level helper function to take an `AVFrame` and map it to the GPU.
|
||||
// The resulting `pl_frame` remains valid until `pl_unmap_avframe` is called,
|
||||
// which must be called at some point to clean up state. The `AVFrame` is
|
||||
// automatically ref'd and unref'd if needed. Returns whether successful.
|
||||
//
|
||||
// Note: `out_frame->user_data` points to a privately managed opaque struct
|
||||
// and must not be touched by the user.
|
||||
PL_LIBAV_API bool pl_map_avframe_ex(pl_gpu gpu, struct pl_frame *out_frame,
|
||||
const struct pl_avframe_params *params);
|
||||
PL_LIBAV_API void pl_unmap_avframe(pl_gpu gpu, struct pl_frame *frame);
|
||||
|
||||
// Backwards compatibility with previous versions of this API.
|
||||
PL_LIBAV_API bool pl_map_avframe(pl_gpu gpu, struct pl_frame *out_frame,
|
||||
pl_tex tex[4], const AVFrame *avframe);
|
||||
|
||||
// Return the AVFrame* that a pl_frame was mapped from (via pl_map_avframe_ex)
|
||||
// Note: This reference is attached to the `pl_frame` and will get freed by
|
||||
// pl_unmap_avframe.
|
||||
PL_LIBAV_API AVFrame *pl_get_mapped_avframe(const struct pl_frame *frame);
|
||||
|
||||
// Download the texture contents of a `pl_frame` back to a corresponding
|
||||
// AVFrame. Blocks until completion.
|
||||
//
|
||||
// Note: This function performs minimal verification, so incorrect usage will
|
||||
// likely result in broken frames. Use `pl_frame_recreate_from_avframe` to
|
||||
// ensure matching formats.
|
||||
PL_LIBAV_API bool pl_download_avframe(pl_gpu gpu,
|
||||
const struct pl_frame *frame,
|
||||
AVFrame *out_frame);
|
||||
|
||||
// Helper functions to update the colorimetry data in an AVFrame based on
|
||||
// the values specified in the given color space / color repr / profile.
|
||||
//
|
||||
// Note: These functions can and will allocate AVFrame side data if needed,
|
||||
// in particular to encode HDR metadata in `space.hdr`.
|
||||
PL_LIBAV_API void pl_avframe_set_color(AVFrame *frame, struct pl_color_space space);
|
||||
PL_LIBAV_API void pl_avframe_set_repr(AVFrame *frame, struct pl_color_repr repr);
|
||||
PL_LIBAV_API void pl_avframe_set_profile(AVFrame *frame, struct pl_icc_profile profile);
|
||||
|
||||
// Map an AVPixelFormat to an array of pl_plane_data structs. The array must
|
||||
// have at least `av_pix_fmt_count_planes(fmt)` elements, but never more than
|
||||
// 4. This function leaves `width`, `height` and `row_stride`, as well as the
|
||||
// data pointers, uninitialized.
|
||||
//
|
||||
// If `bits` is non-NULL, this function will attempt aligning the resulting
|
||||
// `pl_plane_data` struct for optimal compatibility, placing the resulting
|
||||
// `pl_bit_depth` metadata into `bits`.
|
||||
//
|
||||
// Returns the number of plane structs written to, or 0 on error.
|
||||
//
|
||||
// Note: This function is usually clumsier to use than the higher-level
|
||||
// functions above, but it might have some fringe use cases, for example if
|
||||
// the user wants to replace the data buffers by `pl_buf` references in the
|
||||
// `pl_plane_data` before uploading it to the GPU.
|
||||
PL_LIBAV_API int pl_plane_data_from_pixfmt(struct pl_plane_data data[4],
|
||||
struct pl_bit_encoding *bits,
|
||||
enum AVPixelFormat pix_fmt);
|
||||
|
||||
// Callback for AVCodecContext.get_buffer2 that allocates memory from
|
||||
// persistently mapped buffers. This can be more efficient than regular
|
||||
// system memory, especially on platforms that don't support importing
|
||||
// PL_HANDLE_HOST_PTR as buffers.
|
||||
//
|
||||
// Note: `avctx->opaque` must be a pointer that *points* to the GPU instance.
|
||||
// That is, it should have type `pl_gpu *`.
|
||||
PL_LIBAV_API int pl_get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags);
|
||||
|
||||
// Mapping functions for the various libavutil enums. Note that these are not
|
||||
// quite 1:1, and even for values that exist in both, the semantics sometimes
|
||||
// differ. Some special cases (e.g. ICtCp, or XYZ) are handled differently in
|
||||
// libplacebo and libavutil, respectively.
|
||||
//
|
||||
// Because of this, it's generally recommended to avoid these and instead use
|
||||
// helpers like `pl_frame_from_avframe`, which contain extra logic to patch
|
||||
// through all of the special cases.
|
||||
PL_LIBAV_API enum pl_color_system pl_system_from_av(enum AVColorSpace spc);
|
||||
PL_LIBAV_API enum AVColorSpace pl_system_to_av(enum pl_color_system sys);
|
||||
PL_LIBAV_API enum pl_color_levels pl_levels_from_av(enum AVColorRange range);
|
||||
PL_LIBAV_API enum AVColorRange pl_levels_to_av(enum pl_color_levels levels);
|
||||
PL_LIBAV_API enum pl_color_primaries pl_primaries_from_av(enum AVColorPrimaries prim);
|
||||
PL_LIBAV_API enum AVColorPrimaries pl_primaries_to_av(enum pl_color_primaries prim);
|
||||
PL_LIBAV_API enum pl_color_transfer pl_transfer_from_av(enum AVColorTransferCharacteristic trc);
|
||||
PL_LIBAV_API enum AVColorTransferCharacteristic pl_transfer_to_av(enum pl_color_transfer trc);
|
||||
PL_LIBAV_API enum pl_chroma_location pl_chroma_from_av(enum AVChromaLocation loc);
|
||||
PL_LIBAV_API enum AVChromaLocation pl_chroma_to_av(enum pl_chroma_location loc);
|
||||
|
||||
// Helper function to generate a `pl_color_space` struct from an AVFrame.
|
||||
PL_LIBAV_API void pl_color_space_from_avframe(struct pl_color_space *out_csp,
|
||||
const AVFrame *frame);
|
||||
|
||||
// Helper function to pick the right `pl_field` value for an AVFrame.
|
||||
PL_LIBAV_API enum pl_field pl_field_from_avframe(const AVFrame *frame);
|
||||
|
||||
#ifdef PL_HAVE_LAV_FILM_GRAIN
|
||||
// Fill in film grain parameters from an AVFilmGrainParams.
|
||||
//
|
||||
// Note: The resulting struct will only remain valid as long as the
|
||||
// `AVFilmGrainParams` remains valid.
|
||||
PL_LIBAV_API void pl_film_grain_from_av(struct pl_film_grain_data *out_data,
|
||||
const AVFilmGrainParams *fgp);
|
||||
#endif
|
||||
|
||||
// Deprecated alias for backwards compatibility
|
||||
#define pl_swapchain_colors_from_avframe pl_color_space_from_avframe
|
||||
|
||||
// Actual implementation, included as part of this header to avoid having
|
||||
// a compile-time dependency on libavutil.
|
||||
#if PL_LIBAV_IMPLEMENTATION
|
||||
# include <libplacebo/utils/libav_internal.h>
|
||||
#endif
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_LIBAV_H_
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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_UPLOAD_H_
|
||||
#define LIBPLACEBO_UPLOAD_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/renderer.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
// This file contains a utility function to assist in uploading data from host
|
||||
// memory to a texture. In particular, the texture will be suitable for use as
|
||||
// a `pl_plane`.
|
||||
|
||||
// Description of the host representation of an image plane
|
||||
struct pl_plane_data {
|
||||
enum pl_fmt_type type; // meaning of the data (must not be UINT or SINT)
|
||||
int width, height; // dimensions of the plane
|
||||
int component_size[4]; // size in bits of each coordinate
|
||||
int component_pad[4]; // ignored bits preceding each component
|
||||
int component_map[4]; // semantic meaning of each component (pixel order)
|
||||
size_t pixel_stride; // offset in bytes between pixels (required)
|
||||
size_t row_stride; // offset in bytes between rows (optional)
|
||||
bool swapped; // pixel data is endian-swapped (non-native)
|
||||
|
||||
// Similar to `pl_tex_transfer_params`, you can either upload from a raw
|
||||
// pointer address, or a buffer + offset. Again, the use of these two
|
||||
// mechanisms is mutually exclusive.
|
||||
//
|
||||
// 1. Uploading from host memory
|
||||
const void *pixels; // the actual data underlying this plane
|
||||
|
||||
// 2. Uploading from a buffer (requires `pl_gpu_limits.buf_transfer`)
|
||||
pl_buf buf; // the buffer to use
|
||||
size_t buf_offset; // offset of data within buffer, must be a
|
||||
// multiple of `pixel_stride` as well as of 4
|
||||
|
||||
// Similar to `pl_tex_transfer_params.callback`, this allows turning the
|
||||
// upload of a plane into an asynchronous upload. The same notes apply.
|
||||
void (*callback)(void *priv);
|
||||
void *priv;
|
||||
|
||||
// Note: When using this together with `pl_frame`, there is some amount of
|
||||
// overlap between `component_pad` and `pl_color_repr.bits`. Some key
|
||||
// differences between the two:
|
||||
//
|
||||
// - the bits from `component_pad` are ignored; whereas the superfluous bits
|
||||
// in a `pl_color_repr` must be 0.
|
||||
// - the `component_pad` exists to align the component size and placement
|
||||
// with the capabilities of GPUs; the `pl_color_repr` exists to control
|
||||
// the semantics of the color samples on a finer granularity.
|
||||
// - the `pl_color_repr` applies to the color sample as a whole, and
|
||||
// therefore applies to all planes; the `component_pad` can be different
|
||||
// for each plane.
|
||||
// - `component_pad` interacts with float textures by moving the actual
|
||||
// float in memory. `pl_color_repr` interacts with float data as if
|
||||
// the float was converted from an integer under full range semantics.
|
||||
//
|
||||
// To help establish the motivating difference, a typical example of a use
|
||||
// case would be yuv420p10. Since 10-bit GPU texture support is limited,
|
||||
// and working with non-byte-aligned pixels is awkward in general, the
|
||||
// convention is to represent yuv420p10 as 16-bit samples with either the
|
||||
// high or low bits set to 0. In this scenario, the `component_size` of the
|
||||
// `pl_plane_data` and `pl_bit_encoding.sample_depth` would be 16, while
|
||||
// the `pl_bit_encoding.color_depth` would be 10 (and additionally, the
|
||||
// `pl_bit_encoding.bit_shift` would be either 0 or 6, depending on
|
||||
// whether the low or the high bits are used).
|
||||
//
|
||||
// On the contrary, something like a packed, 8-bit XBGR format (where the
|
||||
// X bits are ignored and may contain garbage) would set `component_pad[0]`
|
||||
// to 8, and the component_size[0:2] (respectively) to 8 as well.
|
||||
//
|
||||
// As a general rule of thumb, for maximum compatibility, you should try
|
||||
// and align component_size/component_pad to multiples of 8 and explicitly
|
||||
// clear any remaining superfluous bits (+ use `pl_color_repr.bits` to
|
||||
// ensure they're decoded correctly). You should also try to align the
|
||||
// `pixel_stride` to a power of two.
|
||||
};
|
||||
|
||||
// Fills in the `component_size`, `component_pad` and `component_map` fields
|
||||
// based on the supplied mask for each component (in semantic order, i.e.
|
||||
// RGBA). Each element of `mask` must have a contiguous range of set bits.
|
||||
PL_API void pl_plane_data_from_mask(struct pl_plane_data *data, uint64_t mask[4]);
|
||||
|
||||
// Fills in the `component_size`, `component_pad` and `component_map` fields
|
||||
// based on the supplied sizes (in bits) and shift of each component (in
|
||||
// semantic order).
|
||||
//
|
||||
// Similar to `pl_plane_data_from_mask` but not limited to 64-bit pixels.
|
||||
PL_API void pl_plane_data_from_comps(struct pl_plane_data *data, int size[4],
|
||||
int shift[4]);
|
||||
|
||||
// Helper function to take a `pl_plane_data` struct and try and improve its
|
||||
// alignment to make it more likely to correspond to a real `pl_fmt`. It does
|
||||
// this by attempting to round each component up to the nearest byte boundary.
|
||||
// This relies on the assumption (true in practice) that superfluous bits of
|
||||
// byte-misaligned formats are explicitly set to 0.
|
||||
//
|
||||
// The resulting shift must be consistent across all components, in which case
|
||||
// it's returned in `out_bits`. If no alignment was possible, `out_bits` is set
|
||||
// to {0}, and this function returns false.
|
||||
PL_API bool pl_plane_data_align(struct pl_plane_data *data, struct pl_bit_encoding *out_bits);
|
||||
|
||||
// Helper function to find a suitable `pl_fmt` based on a pl_plane_data's
|
||||
// requirements. This is called internally by `pl_upload_plane`, but it's
|
||||
// exposed to users both as a convenience and so they may pre-emptively check
|
||||
// if a format would be supported without actually having to attempt the upload.
|
||||
PL_API pl_fmt pl_plane_find_fmt(pl_gpu gpu, int out_map[4], const struct pl_plane_data *data);
|
||||
|
||||
// Upload an image plane to a texture, and output the resulting `pl_plane`
|
||||
// struct to `out_plane` (optional). `tex` must be a valid pointer to a texture
|
||||
// (or NULL), which will be destroyed and reinitialized if it does not already
|
||||
// exist or is incompatible. Returns whether successful.
|
||||
//
|
||||
// The resulting texture is guaranteed to be `sampleable`, and it will also try
|
||||
// and maximize compatibility with the other `pl_renderer` requirements
|
||||
// (blittable, linear filterable, etc.).
|
||||
//
|
||||
// Note: `out_plane->shift_x/y` and `out_plane->flipped` are left
|
||||
// uninitialized, and should be set explicitly by the user.
|
||||
PL_API bool pl_upload_plane(pl_gpu gpu, struct pl_plane *out_plane,
|
||||
pl_tex *tex, const struct pl_plane_data *data);
|
||||
|
||||
// Like `pl_upload_plane`, but only creates an uninitialized texture object
|
||||
// rather than actually performing an upload. This can be useful to, for
|
||||
// example, prepare textures to be used as the target of rendering.
|
||||
//
|
||||
// The resulting texture is guaranteed to be `renderable`, and it will also try
|
||||
// to maximize compatibility with the other `pl_renderer` requirements
|
||||
// (blittable, storable, etc.).
|
||||
PL_API bool pl_recreate_plane(pl_gpu gpu, struct pl_plane *out_plane,
|
||||
pl_tex *tex, const struct pl_plane_data *data);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_UPLOAD_H_
|
||||
@ -0,0 +1,638 @@
|
||||
/*
|
||||
* 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_VULKAN_H_
|
||||
#define LIBPLACEBO_VULKAN_H_
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <libplacebo/gpu.h>
|
||||
#include <libplacebo/swapchain.h>
|
||||
|
||||
PL_API_BEGIN
|
||||
|
||||
#define PL_VK_MIN_VERSION VK_API_VERSION_1_2
|
||||
|
||||
// Structure representing a VkInstance. Using this is not required.
|
||||
typedef const struct pl_vk_inst_t {
|
||||
VkInstance instance;
|
||||
|
||||
// The Vulkan API version supported by this VkInstance.
|
||||
uint32_t api_version;
|
||||
|
||||
// The associated vkGetInstanceProcAddr pointer.
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
|
||||
// The instance extensions that were successfully enabled, including
|
||||
// extensions enabled by libplacebo internally. May contain duplicates.
|
||||
const char * const *extensions;
|
||||
int num_extensions;
|
||||
|
||||
// The instance layers that were successfully enabled, including
|
||||
// layers enabled by libplacebo internally. May contain duplicates.
|
||||
const char * const *layers;
|
||||
int num_layers;
|
||||
} *pl_vk_inst;
|
||||
|
||||
struct pl_vk_inst_params {
|
||||
// If set, enable the debugging and validation layers. These should
|
||||
// generally be lightweight and relatively harmless to enable.
|
||||
bool debug;
|
||||
|
||||
// If set, also enable GPU-assisted verification and best practices
|
||||
// layers. (Note: May cause substantial slowdown and/or result in lots of
|
||||
// false positive spam)
|
||||
bool debug_extra;
|
||||
|
||||
// If nonzero, restricts the Vulkan API version to be at most this. This
|
||||
// is only really useful for explicitly testing backwards compatibility.
|
||||
uint32_t max_api_version;
|
||||
|
||||
// Pointer to a user-provided `vkGetInstanceProcAddr`. If this is NULL,
|
||||
// libplacebo will use the directly linked version (if available).
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
|
||||
// Enables extra instance extensions. Instance creation will fail if these
|
||||
// extensions are not all supported. The user may use this to enable e.g.
|
||||
// windowing system integration.
|
||||
const char * const *extensions;
|
||||
int num_extensions;
|
||||
|
||||
// Enables extra optional instance extensions. These are opportunistically
|
||||
// enabled if supported by the device, but otherwise skipped.
|
||||
const char * const *opt_extensions;
|
||||
int num_opt_extensions;
|
||||
|
||||
// Enables extra layers. Instance creation will fail if these layers are
|
||||
// not all supported.
|
||||
//
|
||||
// NOTE: Layers needed for required/optional extensions are automatically
|
||||
// enabled. The user does not specifically need to enable layers related
|
||||
// to extension support.
|
||||
const char * const *layers;
|
||||
int num_layers;
|
||||
|
||||
// Enables extra optional layers. These are opportunistically enabled if
|
||||
// supported by the platform, but otherwise skipped.
|
||||
const char * const *opt_layers;
|
||||
int num_opt_layers;
|
||||
};
|
||||
|
||||
#define pl_vk_inst_params(...) (&(struct pl_vk_inst_params) { __VA_ARGS__ })
|
||||
PL_API extern const struct pl_vk_inst_params pl_vk_inst_default_params;
|
||||
|
||||
// Helper function to simplify instance creation. The user could also bypass
|
||||
// these helpers and do it manually, but this function is provided as a
|
||||
// convenience. It also sets up a debug callback which forwards all vulkan
|
||||
// messages to the `pl_log` callback.
|
||||
PL_API pl_vk_inst pl_vk_inst_create(pl_log log, const struct pl_vk_inst_params *params);
|
||||
PL_API void pl_vk_inst_destroy(pl_vk_inst *inst);
|
||||
|
||||
struct pl_vulkan_queue {
|
||||
uint32_t index; // Queue family index
|
||||
uint32_t count; // Queue family count
|
||||
};
|
||||
|
||||
// Structure representing the actual vulkan device and associated GPU instance
|
||||
typedef const struct pl_vulkan_t *pl_vulkan;
|
||||
struct pl_vulkan_t {
|
||||
pl_gpu gpu;
|
||||
|
||||
// The vulkan objects in use. The user may use this for their own purposes,
|
||||
// but please note that the lifetime is tied to the lifetime of the
|
||||
// pl_vulkan object, and must not be destroyed by the user. Note that the
|
||||
// created vulkan device may have any number of queues and queue family
|
||||
// assignments; so using it for queue submission commands is ill-advised.
|
||||
VkInstance instance;
|
||||
VkPhysicalDevice phys_device;
|
||||
VkDevice device;
|
||||
|
||||
// The associated vkGetInstanceProcAddr pointer.
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
|
||||
// The Vulkan API version supported by this VkPhysicalDevice.
|
||||
uint32_t api_version;
|
||||
|
||||
// The device extensions that were successfully enabled, including
|
||||
// extensions enabled by libplacebo internally. May contain duplicates.
|
||||
const char * const *extensions;
|
||||
int num_extensions;
|
||||
|
||||
// The device features that were enabled at device creation time.
|
||||
//
|
||||
// Note: Whenever a feature flag is ambiguious between several alternative
|
||||
// locations, for completeness' sake, we include both.
|
||||
const VkPhysicalDeviceFeatures2 *features;
|
||||
|
||||
// The explicit queue families we are using to provide a given capability.
|
||||
struct pl_vulkan_queue queue_graphics; // provides VK_QUEUE_GRAPHICS_BIT
|
||||
struct pl_vulkan_queue queue_compute; // provides VK_QUEUE_COMPUTE_BIT
|
||||
struct pl_vulkan_queue queue_transfer; // provides VK_QUEUE_TRANSFER_BIT
|
||||
|
||||
// Functions for locking a queue. These must be used to lock VkQueues for
|
||||
// submission or other related operations when sharing the VkDevice between
|
||||
// multiple threads, Using this on queue families or indices not contained
|
||||
// in `queues` is undefined behavior.
|
||||
void (*lock_queue)(pl_vulkan vk, uint32_t qf, uint32_t qidx);
|
||||
void (*unlock_queue)(pl_vulkan vk, uint32_t qf, uint32_t qidx);
|
||||
|
||||
// --- Deprecated fields
|
||||
|
||||
// These are the same active queue families and their queue counts in list
|
||||
// form. This list does not contain duplicates, nor any extra queues
|
||||
// enabled at device creation time. Deprecated in favor of querying
|
||||
// `vkGetPhysicalDeviceQueueFamilyProperties` directly.
|
||||
const struct pl_vulkan_queue *queues PL_DEPRECATED;
|
||||
int num_queues PL_DEPRECATED;
|
||||
};
|
||||
|
||||
struct pl_vulkan_params {
|
||||
// The vulkan instance. Optional, if NULL then libplacebo will internally
|
||||
// create a VkInstance with the settings from `instance_params`.
|
||||
//
|
||||
// Note: The VkInstance provided by the user *MUST* be created with a
|
||||
// VkApplicationInfo.apiVersion of PL_VK_MIN_VERSION or higher.
|
||||
VkInstance instance;
|
||||
|
||||
// Pointer to `vkGetInstanceProcAddr`. If this is NULL, libplacebo will
|
||||
// use the directly linked version (if available).
|
||||
//
|
||||
// Note: This overwrites the same value from `instance_params`.
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
|
||||
// Configures the settings used for creating an internal vulkan instance.
|
||||
// May be NULL. Ignored if `instance` is set.
|
||||
const struct pl_vk_inst_params *instance_params;
|
||||
|
||||
// When choosing the device, rule out all devices that don't support
|
||||
// presenting to this surface. When creating a device, enable all extensions
|
||||
// needed to ensure we can present to this surface. Optional. Only legal
|
||||
// when specifying an existing VkInstance to use.
|
||||
VkSurfaceKHR surface;
|
||||
|
||||
// --- Physical device selection options
|
||||
|
||||
// The vulkan physical device. May be set by the caller to indicate the
|
||||
// physical device to use. Otherwise, libplacebo will pick the "best"
|
||||
// available GPU, based on the advertised device type. (i.e., it will
|
||||
// prefer discrete GPUs over integrated GPUs). Only legal when specifying
|
||||
// an existing VkInstance to use.
|
||||
VkPhysicalDevice device;
|
||||
|
||||
// When choosing the device, only choose a device with this exact name.
|
||||
// This overrides `allow_software`. No effect if `device` is set. Note: A
|
||||
// list of devices and their names are logged at level PL_LOG_INFO.
|
||||
const char *device_name;
|
||||
|
||||
// When choosing the device, only choose a device with this exact UUID.
|
||||
// This overrides `allow_software` and `device_name`. No effect if `device`
|
||||
// is set.
|
||||
uint8_t device_uuid[16];
|
||||
|
||||
// When choosing the device, controls whether or not to also allow software
|
||||
// GPUs. No effect if `device` or `device_name` are set.
|
||||
bool allow_software;
|
||||
|
||||
// --- Logical device creation options
|
||||
|
||||
// Controls whether or not to allow asynchronous transfers, using transfer
|
||||
// queue families, if supported by the device. This can be significantly
|
||||
// faster and more power efficient, and also allows streaming uploads in
|
||||
// parallel with rendering commands. Enabled by default.
|
||||
bool async_transfer;
|
||||
|
||||
// Controls whether or not to allow asynchronous compute, using dedicated
|
||||
// compute queue families, if supported by the device. On some devices,
|
||||
// these can allow the GPU to schedule compute shaders in parallel with
|
||||
// fragment shaders. Enabled by default.
|
||||
bool async_compute;
|
||||
|
||||
// Limits the number of queues to use. If left as 0, libplacebo will use as
|
||||
// many queues as the device supports. Multiple queues can result in
|
||||
// improved efficiency when submitting multiple commands that can entirely
|
||||
// or partially execute in parallel. Defaults to 1, since using more queues
|
||||
// can actually decrease performance.
|
||||
//
|
||||
// Note: libplacebo will always *create* logical devices with all available
|
||||
// queues for a given QF enabled, regardless of this setting.
|
||||
int queue_count;
|
||||
|
||||
// Bitmask of extra queue families to enable. If set, then *all* queue
|
||||
// families matching *any* of these flags will be enabled at device
|
||||
// creation time. Setting this to VK_QUEUE_FLAG_BITS_MAX_ENUM effectively
|
||||
// enables all queue families supported by the device.
|
||||
VkQueueFlags extra_queues;
|
||||
|
||||
// Enables extra device extensions. Device creation will fail if these
|
||||
// extensions are not all supported. The user may use this to enable e.g.
|
||||
// interop extensions.
|
||||
const char * const *extensions;
|
||||
int num_extensions;
|
||||
|
||||
// Enables extra optional device extensions. These are opportunistically
|
||||
// enabled if supported by the device, but otherwise skipped.
|
||||
const char * const *opt_extensions;
|
||||
int num_opt_extensions;
|
||||
|
||||
// Optional extra features to enable at device creation time. These are
|
||||
// opportunistically enabled if supported by the physical device, but
|
||||
// otherwise kept disabled.
|
||||
const VkPhysicalDeviceFeatures2 *features;
|
||||
|
||||
// --- Misc/debugging options
|
||||
|
||||
// Restrict specific features to e.g. work around driver bugs, or simply
|
||||
// for testing purposes
|
||||
int max_glsl_version; // limit the maximum GLSL version
|
||||
uint32_t max_api_version; // limit the maximum vulkan API version
|
||||
};
|
||||
|
||||
// Default/recommended parameters. Should generally be safe and efficient.
|
||||
#define PL_VULKAN_DEFAULTS \
|
||||
.async_transfer = true, \
|
||||
.async_compute = true, \
|
||||
/* enabling multiple queues often decreases perf */ \
|
||||
.queue_count = 1,
|
||||
|
||||
#define pl_vulkan_params(...) (&(struct pl_vulkan_params) { PL_VULKAN_DEFAULTS __VA_ARGS__ })
|
||||
PL_API extern const struct pl_vulkan_params pl_vulkan_default_params;
|
||||
|
||||
// Creates a new vulkan device based on the given parameters and initializes
|
||||
// a new GPU. If `params` is left as NULL, it defaults to
|
||||
// &pl_vulkan_default_params.
|
||||
//
|
||||
// Thread-safety: Safe
|
||||
PL_API pl_vulkan pl_vulkan_create(pl_log log, const struct pl_vulkan_params *params);
|
||||
|
||||
// Destroys the vulkan device and all associated objects, except for the
|
||||
// VkInstance provided by the user.
|
||||
//
|
||||
// Note that all resources allocated from this vulkan object (e.g. via the
|
||||
// `vk->ra` or using `pl_vulkan_create_swapchain`) *must* be explicitly
|
||||
// destroyed by the user before calling this.
|
||||
//
|
||||
// Also note that this function will block until all in-flight GPU commands are
|
||||
// finished processing. You can avoid this by manually calling `pl_gpu_finish`
|
||||
// before `pl_vulkan_destroy`.
|
||||
PL_API void pl_vulkan_destroy(pl_vulkan *vk);
|
||||
|
||||
// For a `pl_gpu` backed by `pl_vulkan`, this function can be used to retrieve
|
||||
// the underlying `pl_vulkan`. Returns NULL for any other type of `gpu`.
|
||||
PL_API pl_vulkan pl_vulkan_get(pl_gpu gpu);
|
||||
|
||||
struct pl_vulkan_device_params {
|
||||
// The instance to use. Required!
|
||||
//
|
||||
// Note: The VkInstance provided by the user *must* be created with a
|
||||
// VkApplicationInfo.apiVersion of PL_VK_MIN_VERSION or higher.
|
||||
VkInstance instance;
|
||||
|
||||
// Mirrored from `pl_vulkan_params`. All of these fields are optional.
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
VkSurfaceKHR surface;
|
||||
const char *device_name;
|
||||
uint8_t device_uuid[16];
|
||||
bool allow_software;
|
||||
};
|
||||
|
||||
#define pl_vulkan_device_params(...) (&(struct pl_vulkan_device_params) { __VA_ARGS__ })
|
||||
|
||||
// Helper function to choose the best VkPhysicalDevice, given a VkInstance.
|
||||
// This uses the same logic as `pl_vulkan_create` uses internally. If no
|
||||
// matching device was found, this returns VK_NULL_HANDLE.
|
||||
PL_API VkPhysicalDevice pl_vulkan_choose_device(pl_log log,
|
||||
const struct pl_vulkan_device_params *params);
|
||||
|
||||
struct pl_vulkan_swapchain_params {
|
||||
// The surface to use for rendering. Required, the user is in charge of
|
||||
// creating this. Must belong to the same VkInstance as `vk->instance`.
|
||||
VkSurfaceKHR surface;
|
||||
|
||||
// The preferred presentation mode. See the vulkan documentation for more
|
||||
// information about these. If the device/surface combination does not
|
||||
// support this mode, libplacebo will fall back to VK_PRESENT_MODE_FIFO_KHR.
|
||||
//
|
||||
// Warning: Leaving this zero-initialized is the same as having specified
|
||||
// VK_PRESENT_MODE_IMMEDIATE_KHR, which is probably not what the user
|
||||
// wants!
|
||||
VkPresentModeKHR present_mode;
|
||||
|
||||
// Allow up to N in-flight frames. This essentially controls how many
|
||||
// rendering commands may be queued up at the same time. See the
|
||||
// documentation for `pl_swapchain_get_latency` for more information. For
|
||||
// vulkan specifically, we are only able to wait until the GPU has finished
|
||||
// rendering a frame - we are unable to wait until the display has actually
|
||||
// finished displaying it. So this only provides a rough guideline.
|
||||
// Optional, defaults to 3.
|
||||
int swapchain_depth;
|
||||
|
||||
// This suppresses automatic recreation of the swapchain when any call
|
||||
// returns VK_SUBOPTIMAL_KHR. Normally, libplacebo will recreate the
|
||||
// swapchain internally on the next `pl_swapchain_start_frame`. If enabled,
|
||||
// clients are assumed to take care of swapchain recreations themselves, by
|
||||
// calling `pl_swapchain_resize` as appropriate. libplacebo will tolerate
|
||||
// the "suboptimal" status indefinitely.
|
||||
bool allow_suboptimal;
|
||||
|
||||
// Disable high-bit (10 or more) SDR formats. May help work around buggy
|
||||
// drivers which don't dither properly when outputting high bit depth
|
||||
// SDR backbuffers to 8-bit screens.
|
||||
bool disable_10bit_sdr;
|
||||
};
|
||||
|
||||
#define pl_vulkan_swapchain_params(...) (&(struct pl_vulkan_swapchain_params) { __VA_ARGS__ })
|
||||
|
||||
// Creates a new vulkan swapchain based on an existing VkSurfaceKHR. Using this
|
||||
// function requires that the vulkan device was created with the
|
||||
// VK_KHR_swapchain extension. The easiest way of accomplishing this is to set
|
||||
// the `pl_vulkan_params.surface` explicitly at creation time.
|
||||
PL_API pl_swapchain pl_vulkan_create_swapchain(pl_vulkan vk,
|
||||
const struct pl_vulkan_swapchain_params *params);
|
||||
|
||||
// This will return true if the vulkan swapchain is internally detected
|
||||
// as being suboptimal (VK_SUBOPTIMAL_KHR). This might be of use to clients
|
||||
// who have `params->allow_suboptimal` enabled.
|
||||
PL_API bool pl_vulkan_swapchain_suboptimal(pl_swapchain sw);
|
||||
|
||||
// Vulkan interop API, for sharing a single VkDevice (and associated vulkan
|
||||
// resources) directly with the API user. The use of this API is a bit sketchy
|
||||
// and requires careful communication of Vulkan API state.
|
||||
|
||||
struct pl_vulkan_import_params {
|
||||
// The vulkan instance. Required.
|
||||
//
|
||||
// Note: The VkInstance provided by the user *must* be created with a
|
||||
// VkApplicationInfo.apiVersion of PL_VK_MIN_VERSION or higher.
|
||||
VkInstance instance;
|
||||
|
||||
// Pointer to `vkGetInstanceProcAddr`. If this is NULL, libplacebo will
|
||||
// use the directly linked version (if available).
|
||||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
|
||||
// The physical device selected by the user. Required.
|
||||
VkPhysicalDevice phys_device;
|
||||
|
||||
// The logical device created by the user. Required.
|
||||
VkDevice device;
|
||||
|
||||
// --- Logical device parameters
|
||||
|
||||
// List of all device-level extensions that were enabled. (Instance-level
|
||||
// extensions need not be re-specified here, since it's guaranteed that any
|
||||
// instance-level extensions that device-level extensions depend on were
|
||||
// enabled at the instance level)
|
||||
const char * const *extensions;
|
||||
int num_extensions;
|
||||
|
||||
// Enabled queue families. At least `queue_graphics` is required.
|
||||
//
|
||||
// It's okay for multiple queue families to be specified with the same
|
||||
// index, e.g. in the event that a dedicated compute queue also happens to
|
||||
// be the dedicated transfer queue.
|
||||
//
|
||||
// It's also okay to leave the queue struct as {0} in the event that no
|
||||
// dedicated queue exists for a given operation type. libplacebo will
|
||||
// automatically fall back to using e.g. the graphics queue instead.
|
||||
struct pl_vulkan_queue queue_graphics; // must support VK_QUEUE_GRAPHICS_BIT
|
||||
struct pl_vulkan_queue queue_compute; // must support VK_QUEUE_COMPUTE_BIT
|
||||
struct pl_vulkan_queue queue_transfer; // must support VK_QUEUE_TRANSFER_BIT
|
||||
|
||||
// Enabled VkPhysicalDeviceFeatures. The device *must* be created with
|
||||
// all of the features in `pl_vulkan_required_features` enabled.
|
||||
const VkPhysicalDeviceFeatures2 *features;
|
||||
|
||||
// Functions for locking a queue. If set, these will be used instead of
|
||||
// libplacebo's internal functions for `pl_vulkan.(un)lock_queue`.
|
||||
void (*lock_queue)(void *ctx, uint32_t qf, uint32_t qidx);
|
||||
void (*unlock_queue)(void *ctx, uint32_t qf, uint32_t qidx);
|
||||
void *queue_ctx;
|
||||
|
||||
// --- Misc/debugging options
|
||||
|
||||
// Restrict specific features to e.g. work around driver bugs, or simply
|
||||
// for testing purposes. See `pl_vulkan_params` for a description of these.
|
||||
int max_glsl_version;
|
||||
uint32_t max_api_version;
|
||||
};
|
||||
|
||||
#define pl_vulkan_import_params(...) (&(struct pl_vulkan_import_params) { __VA_ARGS__ })
|
||||
|
||||
// For purely informative reasons, this contains a list of extensions and
|
||||
// device features that libplacebo *can* make use of. These are all strictly
|
||||
// optional, but provide a hint to the API user as to what might be worth
|
||||
// enabling at device creation time.
|
||||
//
|
||||
// Note: This also includes physical device features provided by extensions.
|
||||
// They are all provided using extension-specific features structs, rather
|
||||
// than the more general purpose VkPhysicalDeviceVulkan11Features etc.
|
||||
PL_API extern const char * const pl_vulkan_recommended_extensions[];
|
||||
PL_API extern const int pl_vulkan_num_recommended_extensions;
|
||||
PL_API extern const VkPhysicalDeviceFeatures2 pl_vulkan_recommended_features;
|
||||
|
||||
// A list of device features that are required by libplacebo. These
|
||||
// *must* be provided by imported Vulkan devices.
|
||||
//
|
||||
// Note: `pl_vulkan_recommended_features` does not include this list.
|
||||
PL_API extern const VkPhysicalDeviceFeatures2 pl_vulkan_required_features;
|
||||
|
||||
// Import an existing VkDevice instead of creating a new one, and wrap it into
|
||||
// a `pl_vulkan` abstraction. It's safe to `pl_vulkan_destroy` this, which will
|
||||
// destroy application state related to libplacebo but leave the underlying
|
||||
// VkDevice intact.
|
||||
PL_API pl_vulkan pl_vulkan_import(pl_log log, const struct pl_vulkan_import_params *params);
|
||||
|
||||
struct pl_vulkan_wrap_params {
|
||||
// The image itself. It *must* be usable concurrently by all of the queue
|
||||
// family indices listed in `pl_vulkan->queues`. Note that this requires
|
||||
// the use of VK_SHARING_MODE_CONCURRENT if `pl_vulkan->num_queues` is
|
||||
// greater than 1. If this is difficult to achieve for the user, then
|
||||
// `async_transfer` / `async_compute` should be turned off, which
|
||||
// guarantees the use of only one queue family.
|
||||
VkImage image;
|
||||
|
||||
// Which aspect of `image` to wrap. Only useful for wrapping individual
|
||||
// sub-planes of planar images. If left as 0, it defaults to the entire
|
||||
// image (i.e. the union of VK_IMAGE_ASPECT_PLANE_N_BIT for planar formats,
|
||||
// and VK_IMAGE_ASPECT_COLOR_BIT otherwise).
|
||||
VkImageAspectFlags aspect;
|
||||
|
||||
// The image's dimensions (unused dimensions must be 0)
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
|
||||
// The image's format. libplacebo will try to map this to an equivalent
|
||||
// pl_fmt. If no compatible pl_fmt is found, wrapping will fail.
|
||||
VkFormat format;
|
||||
|
||||
// The usage flags the image was created with. libplacebo will set the
|
||||
// pl_tex capabilities to include whatever it can, as determined by the set
|
||||
// of enabled usage flags.
|
||||
VkImageUsageFlags usage;
|
||||
|
||||
// See `pl_tex_params`
|
||||
void *user_data;
|
||||
pl_debug_tag debug_tag;
|
||||
};
|
||||
|
||||
#define pl_vulkan_wrap_params(...) (&(struct pl_vulkan_wrap_params) { \
|
||||
.debug_tag = PL_DEBUG_TAG, \
|
||||
__VA_ARGS__ \
|
||||
})
|
||||
|
||||
// Wraps an external VkImage into a pl_tex abstraction. By default, the image
|
||||
// is considered "held" by the user and must be released before calling any
|
||||
// pl_tex_* API calls on it (see `pl_vulkan_release`).
|
||||
//
|
||||
// This wrapper can be destroyed by simply calling `pl_tex_destroy` on it,
|
||||
// which will not destroy the underlying VkImage. If a pl_tex wrapper is
|
||||
// destroyed while an image is not currently being held by the user, that
|
||||
// image is left in an undefined state.
|
||||
//
|
||||
// Wrapping the same VkImage multiple times is undefined behavior, as is trying
|
||||
// to wrap an image belonging to a different VkDevice than the one in use by
|
||||
// `gpu`.
|
||||
//
|
||||
// This function may fail, in which case it returns NULL.
|
||||
PL_API pl_tex pl_vulkan_wrap(pl_gpu gpu, const struct pl_vulkan_wrap_params *params);
|
||||
|
||||
// Analogous to `pl_vulkan_wrap`, this function takes any `pl_tex` (including
|
||||
// ones created by `pl_tex_create`) and unwraps it to expose the underlying
|
||||
// VkImage to the user. Unlike `pl_vulkan_wrap`, this `pl_tex` is *not*
|
||||
// considered held after calling this function - the user must explicitly
|
||||
// `pl_vulkan_hold` before accessing the VkImage.
|
||||
//
|
||||
// `out_format` and `out_flags` will be updated to hold the VkImage's
|
||||
// format and usage flags. (Optional)
|
||||
PL_API VkImage pl_vulkan_unwrap(pl_gpu gpu, pl_tex tex,
|
||||
VkFormat *out_format, VkImageUsageFlags *out_flags);
|
||||
|
||||
// Represents a vulkan semaphore/value pair (for compatibility with timeline
|
||||
// semaphores). When using normal, binary semaphores, `value` may be ignored.
|
||||
typedef struct pl_vulkan_sem {
|
||||
VkSemaphore sem;
|
||||
uint64_t value;
|
||||
} pl_vulkan_sem;
|
||||
|
||||
struct pl_vulkan_hold_params {
|
||||
// The Vulkan image to hold. It will be marked as held. Attempting to
|
||||
// perform any pl_tex_* operation (except pl_tex_destroy) on a held image
|
||||
// is undefined behavior.
|
||||
pl_tex tex;
|
||||
|
||||
// The layout to transition the image to when holding. Alternatively, a
|
||||
// pointer to receive the current image layout. If `out_layout` is
|
||||
// provided, `layout` is ignored.
|
||||
VkImageLayout layout;
|
||||
VkImageLayout *out_layout;
|
||||
|
||||
// The queue family index to transition the image to. This can be used with
|
||||
// VK_QUEUE_FAMILY_EXTERNAL to transition the image to an external API. As
|
||||
// a special case, if set to VK_QUEUE_FAMILY_IGNORED, libplacebo will not
|
||||
// transition the image, even if this image was not set up for concurrent
|
||||
// usage. Ignored for concurrent images.
|
||||
uint32_t qf;
|
||||
|
||||
// The semaphore to fire when the image is available for use. (Required)
|
||||
pl_vulkan_sem semaphore;
|
||||
};
|
||||
|
||||
#define pl_vulkan_hold_params(...) (&(struct pl_vulkan_hold_params) { __VA_ARGS__ })
|
||||
|
||||
// "Hold" a shared image, transferring control over the image to the user.
|
||||
// Returns whether successful.
|
||||
PL_API bool pl_vulkan_hold_ex(pl_gpu gpu, const struct pl_vulkan_hold_params *params);
|
||||
|
||||
struct pl_vulkan_release_params {
|
||||
// The image to be released. It must be marked as "held". Performing any
|
||||
// operation on the VkImage underlying this `pl_tex` while it is not being
|
||||
// held by the user is undefined behavior.
|
||||
pl_tex tex;
|
||||
|
||||
// The current layout of the image at the point in time when `semaphore`
|
||||
// fires, or if no semaphore is specified, at the time of call.
|
||||
VkImageLayout layout;
|
||||
|
||||
// The queue family index to transition the image to. This can be used with
|
||||
// VK_QUEUE_FAMILY_EXTERNAL to transition the image rom an external API. As
|
||||
// a special case, if set to VK_QUEUE_FAMILY_IGNORED, libplacebo will not
|
||||
// transition the image, even if this image was not set up for concurrent
|
||||
// usage. Ignored for concurrent images.
|
||||
uint32_t qf;
|
||||
|
||||
// The semaphore to wait on before libplacebo will actually use or modify
|
||||
// the image. (Optional)
|
||||
//
|
||||
// Note: the lifetime of `semaphore` is indeterminate, and destroying it
|
||||
// while the texture is still depending on that semaphore is undefined
|
||||
// behavior.
|
||||
//
|
||||
// Technically, the only way to be sure that it's safe to free is to use
|
||||
// `pl_gpu_finish()` or similar (e.g. `pl_vulkan_destroy` or
|
||||
// `vkDeviceWaitIdle`) after another operation involving `tex` has been
|
||||
// emitted (or the texture has been destroyed).
|
||||
//
|
||||
//
|
||||
// Warning: If `tex` is a planar image (`pl_fmt.num_planes > 0`), and
|
||||
// `semaphore` is specified, it *must* be a timeline semaphore! Failure to
|
||||
// respect this will result in undefined behavior. This warning does not
|
||||
// apply to individual planes (as exposed by `pl_tex.planes`).
|
||||
pl_vulkan_sem semaphore;
|
||||
};
|
||||
|
||||
#define pl_vulkan_release_params(...) (&(struct pl_vulkan_release_params) { __VA_ARGS__ })
|
||||
|
||||
// "Release" a shared image, transferring control to libplacebo.
|
||||
PL_API void pl_vulkan_release_ex(pl_gpu gpu, const struct pl_vulkan_release_params *params);
|
||||
|
||||
struct pl_vulkan_sem_params {
|
||||
// The type of semaphore to create.
|
||||
VkSemaphoreType type;
|
||||
|
||||
// For VK_SEMAPHORE_TYPE_TIMELINE, sets the initial timeline value.
|
||||
uint64_t initial_value;
|
||||
|
||||
// If set, exports this VkSemaphore to the handle given in `out_handle`.
|
||||
// The user takes over ownership, and should manually close it before
|
||||
// destroying this VkSemaphore (via `pl_vulkan_sem_destroy`).
|
||||
enum pl_handle_type export_handle;
|
||||
union pl_handle *out_handle;
|
||||
|
||||
// Optional debug tag to identify this semaphore.
|
||||
pl_debug_tag debug_tag;
|
||||
};
|
||||
|
||||
#define pl_vulkan_sem_params(...) (&(struct pl_vulkan_sem_params) { \
|
||||
.debug_tag = PL_DEBUG_TAG, \
|
||||
__VA_ARGS__ \
|
||||
})
|
||||
|
||||
// Helper functions to create and destroy vulkan semaphores. Returns
|
||||
// VK_NULL_HANDLE on failure.
|
||||
PL_API VkSemaphore pl_vulkan_sem_create(pl_gpu gpu, const struct pl_vulkan_sem_params *params);
|
||||
PL_API void pl_vulkan_sem_destroy(pl_gpu gpu, VkSemaphore *semaphore);
|
||||
|
||||
// Backwards-compatibility wrappers for older versions of the API.
|
||||
PL_DEPRECATED PL_API bool pl_vulkan_hold(pl_gpu gpu, pl_tex tex, VkImageLayout layout,
|
||||
pl_vulkan_sem sem_out);
|
||||
PL_DEPRECATED PL_API bool pl_vulkan_hold_raw(pl_gpu gpu, pl_tex tex, VkImageLayout *out_layout,
|
||||
pl_vulkan_sem sem_out);
|
||||
PL_DEPRECATED PL_API void pl_vulkan_release(pl_gpu gpu, pl_tex tex, VkImageLayout layout,
|
||||
pl_vulkan_sem sem_in);
|
||||
|
||||
PL_API_END
|
||||
|
||||
#endif // LIBPLACEBO_VULKAN_H_
|
||||
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>libplacebo</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.kintan.ksplayer.libplacebo</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>libplacebo</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>87.88.520</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>87.88.520</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>AppleTVOS</string>
|
||||
</array>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,4 @@
|
||||
framework module libplacebo [system] {
|
||||
umbrella "."
|
||||
export *
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user