summaryrefslogtreecommitdiffstats
path: root/src/include/libplacebo/utils/upload.h
blob: 9e8d4363d9e7c4487eeb90f7a9c602307577a8cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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_