1 /* 2 * This file is part of libplacebo. 3 * 4 * libplacebo is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * libplacebo is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef LIBPLACEBO_UPLOAD_H_ 19 #define LIBPLACEBO_UPLOAD_H_ 20 21 #include <stdint.h> 22 23 #include <libplacebo/gpu.h> 24 #include <libplacebo/renderer.h> 25 26 PL_API_BEGIN 27 28 // This file contains a utility function to assist in uploading data from host 29 // memory to a texture. In particular, the texture will be suitable for use as 30 // a `pl_plane`. 31 32 // Description of the host representation of an image plane 33 struct pl_plane_data { 34 enum pl_fmt_type type; // meaning of the data (must not be UINT or SINT) 35 int width, height; // dimensions of the plane 36 int component_size[4]; // size in bits of each coordinate 37 int component_pad[4]; // ignored bits preceding each component 38 int component_map[4]; // semantic meaning of each component (pixel order) 39 size_t pixel_stride; // offset in bytes between pixels (required) 40 size_t row_stride; // offset in bytes between rows (optional) 41 42 // Similar to `pl_tex_transfer_params`, you can either upload from a raw 43 // pointer address, or a buffer + offset. Again, the use of these two 44 // mechanisms is mutually exclusive. 45 // 46 // 1. Uploading from host memory 47 const void *pixels; // the actual data underlying this plane 48 49 // 2. Uploading from a buffer (requires `pl_gpu_limits.buf_transfer`) 50 pl_buf buf; // the buffer to use 51 size_t buf_offset; // offset of data within buffer, must be a 52 // multiple of `pixel_stride` as well as of 4 53 54 // Similar to `pl_tex_transfer_params.callback`, this allows turning the 55 // upload of a plane into an asynchronous upload. The same notes apply. 56 void (*callback)(void *priv); 57 void *priv; 58 59 // Note: When using this together with `pl_frame`, there is some amount of 60 // overlap between `component_pad` and `pl_color_repr.bits`. Some key 61 // differences between the two: 62 // 63 // - the bits from `component_pad` are ignored; whereas the superfluous bits 64 // in a `pl_color_repr` must be 0. 65 // - the `component_pad` exists to align the component size and placement 66 // with the capabilities of GPUs; the `pl_color_repr` exists to control 67 // the semantics of the color samples on a finer granularity. 68 // - the `pl_color_repr` applies to the color sample as a whole, and 69 // therefore applies to all planes; the `component_pad` can be different 70 // for each plane. 71 // - `component_pad` interacts with float textures by moving the actual 72 // float in memory. `pl_color_repr` interacts with float data as if 73 // the float was converted from an integer under full range semantics. 74 // 75 // To help establish the motivating difference, a typical example of a use 76 // case would be yuv420p10. Since 10-bit GPU texture support is limited, 77 // and working with non-byte-aligned pixels is awkward in general, the 78 // convention is to represent yuv420p10 as 16-bit samples with either the 79 // high or low bits set to 0. In this scenario, the `component_size` of the 80 // `pl_plane_repr` and `pl_bit_encoding.sample_depth` would be 16, while 81 // the `pl_bit_encoding.color_depth` would be 10 (and additionally, the 82 // `pl_bit_encoding.bit_shift` would be either 0 or 6, depending on 83 // whether the low or the high bits are used). 84 // 85 // On the contrary, something like a packed, 8-bit XBGR format (where the 86 // X bits are ignored and may contain garbage) would set `component_pad[0]` 87 // to 8, and the component_size[0:2] (respectively) to 8 as well. 88 // 89 // As a general rule of thumb, for maximum compatibility, you should try 90 // and align component_size/component_pad to multiples of 8 and explicitly 91 // clear any remaining superfluous bits (+ use `pl_color_repr.bits` to 92 // ensure they're decoded correctly). You should also try to align the 93 // `pixel_stride` to a power of two. 94 }; 95 96 // Fills in the `component_size`, `component_pad` and `component_map` fields 97 // based on the supplied mask for each component (in semantic order, i.e. 98 // RGBA). Each element of `mask` must have a contiguous range of set bits. 99 void pl_plane_data_from_mask(struct pl_plane_data *data, uint64_t mask[4]); 100 101 // Helper function to take a `pl_plane_data` struct and try and improve its 102 // alignment to make it more likely to correspond to a real `pl_fmt`. It does 103 // this by attempting to round each component up to the nearest byte boundary. 104 // This relies on the assumption (true in practice) that superfluous bits of 105 // byte-misaligned formats are explicitly set to 0. 106 // 107 // The resulting shift must be consistent across all components, in which case 108 // it's returned in `out_bits`. If no alignment was possible, `out_bits` is set 109 // to {0}, and this function returns false. 110 bool pl_plane_data_align(struct pl_plane_data *data, struct pl_bit_encoding *out_bits); 111 112 // Helper function to find a suitable `pl_fmt` based on a pl_plane_data's 113 // requirements. This is called internally by `pl_upload_plane`, but it's 114 // exposed to users both as a convenience and so they may pre-emptively check 115 // if a format would be supported without actually having to attempt the upload. 116 pl_fmt pl_plane_find_fmt(pl_gpu gpu, int out_map[4], const struct pl_plane_data *data); 117 118 // Upload an image plane to a texture, and output the resulting `pl_plane` 119 // struct to `out_plane` (optional). `tex` must be a valid pointer to a texture 120 // (or NULL), which will be destroyed and reinitialized if it does not already 121 // exist or is incompatible. Returns whether successful. 122 // 123 // The resulting texture is guaranteed to be `sampleable`, and it will also try 124 // and maximize compatibility with the other `pl_renderer` requirements 125 // (blittable, linear filterable, etc.). 126 // 127 // Note: `out_plane->shift_x/y` are left uninitialized, and should be set 128 // explicitly by the user. 129 bool pl_upload_plane(pl_gpu gpu, struct pl_plane *out_plane, 130 pl_tex *tex, const struct pl_plane_data *data); 131 132 // Like `pl_upload_plane`, but only creates an uninitialized texture object 133 // rather than actually performing an upload. This can be useful to, for 134 // example, prepare textures to be used as the target of rendering. 135 // 136 // The resulting texture is guaranteed to be `renderable`, and it will also try 137 // to maximize compatibility with the other `pl_renderer` reequirements 138 // (blittable, storable, etc.). 139 bool pl_recreate_plane(pl_gpu gpu, struct pl_plane *out_plane, 140 pl_tex *tex, const struct pl_plane_data *data); 141 142 PL_API_END 143 144 #endif // LIBPLACEBO_UPLOAD_H_ 145