mpv/video/out/opengl/ra.h

225 lines
10 KiB
C
Raw Normal View History

#pragma once
#include "common/common.h"
// Handle for a rendering API backend.
struct ra {
struct ra_fns *fns;
void *priv;
struct mp_log *log;
// RA_CAP_* bit field. The RA backend must set supported features at init
// time.
uint64_t caps;
// Maximum supported width and height of a 2D texture. Set by the RA backend
// at init time.
int max_texture_wh;
// Set of supported texture formats. Must be added by RA backend at init time.
struct ra_format **formats;
int num_formats;
};
enum {
RA_CAP_TEX_1D = 1 << 0, // supports 1D textures (as shader source textures)
RA_CAP_TEX_3D = 1 << 1, // supports 3D textures (as shader source textures)
RA_CAP_BLIT = 1 << 2, // supports ra_fns.blit
};
enum ra_ctype {
RA_CTYPE_UNKNOWN = 0, // also used for inconsistent multi-component formats
RA_CTYPE_UNORM, // unsigned normalized integer (fixed point) formats
RA_CTYPE_UINT, // full integer formats
RA_CTYPE_FLOAT, // float formats (signed, any bit size)
};
// All formats must be useable as texture formats. All formats must be byte
// aligned (all pixels start and end on a byte boundary), at least as far CPU
// transfers are concerned.
struct ra_format {
// All fields are read-only after creation.
const char *name; // symbolic name for user interaction/debugging
void *priv;
enum ra_ctype ctype; // data type of each component
int num_components; // component count, 0 if not applicable, max. 4
int component_size[4]; // in bits, all entries 0 if not applicable
int component_depth[4]; // bits in use for each component, 0 if not applicable
// (_must_ be set if component_size[] includes padding,
// and the real procession as seen by shader is lower)
int pixel_size; // in bytes, total pixel size (0 if opaque)
bool luminance_alpha; // pre-GL_ARB_texture_rg hack for 2 component textures
// if this is set, shader must use .ra instead of .rg
// only applies to 2-component textures
bool linear_filter; // linear filtering available from shader
bool renderable; // can be used for render targets
// If not 0, the format represents some sort of packed fringe format, whose
// shader representation is given by the special_imgfmt_desc pointer.
int special_imgfmt;
const struct ra_imgfmt_desc *special_imgfmt_desc;
};
struct ra_tex_params {
int dimensions; // 1-3 for 1D-3D textures
// Size of the texture. 1D textures require h=d=1, 2D textures require d=1.
int w, h, d;
const struct ra_format *format;
bool render_src; // must be useable as source texture in a shader
bool render_dst; // must be useable as target texture in a shader
// this requires creation of a FBO
// When used as render source texture.
bool src_linear; // if false, use nearest sampling (whether this can
// be true depends on ra_format.linear_filter)
bool src_repeat; // if false, clamp texture coordinates to edge
// if true, repeat texture coordinates
bool non_normalized; // hack for GL_TEXTURE_RECTANGLE OSX idiocy
// always set to false, except in OSX code
// If non-NULL, the texture will be created with these contents, and is
// considered immutable afterwards (no upload, mapping, or rendering to it).
void *initial_data;
};
// Conflates the following typical GPU API concepts:
// - texture itself
// - sampler state
// - staging buffers for texture upload
// - framebuffer objects
// - wrappers for swapchain framebuffers
// - synchronization needed for upload/rendering/etc.
struct ra_tex {
// All fields are read-only after creation.
struct ra_tex_params params;
void *priv;
// Set by user, GL only: attempt to accelerate upload with PBOs.
bool use_pbo;
};
// A persistent mapping, which can be used for texture upload.
struct ra_mapped_buffer {
// All fields are read-only after creation. The data is read/write, but
// requires explicit fence usage.
void *priv;
void *data; // pointer to first usable byte
size_t size; // total size of the mapping, starting at data
};
enum {
// Flags for the texture_upload flags parameter.
RA_TEX_UPLOAD_DISCARD = 1 << 0, // discard pre-existing data not in the region
};
// Rendering API entrypoints. (Note: there are some additional hidden features
// you need to take care of. For example, hwdec mapping will be provided
// separately from ra, but might need to call into ra private code.)
struct ra_fns {
void (*destroy)(struct ra *ra);
// Create a texture (with undefined contents). Return NULL on failure.
// This is a rare operation, and normally textures and even FBOs for
// temporary rendering intermediate data are cached.
struct ra_tex *(*tex_create)(struct ra *ra,
const struct ra_tex_params *params);
void (*tex_destroy)(struct ra *ra, struct ra_tex *tex);
// Copy from CPU RAM to the texture. The image dimensions are as specified
// in tex->params.
// This is an extremely common operation.
// Unlike with OpenGL, the src data has to have exactly the same format as
// the texture, and no conversion is supported.
// region can be NULL - if it's not NULL, then the provided pointer only
// contains data for the given region. Only part of the texture data is
// updated, and ptr points to the first pixel in the region. If
// RA_TEX_UPLOAD_DISCARD is set, data outside of the region can return to
// an uninitialized state. The region is always strictly within the texture
// and has a size >0 in both dimensions. 2D textures only.
// For 1D textures, stride is ignored, and region must be NULL.
// For 3D textures, stride is not supported. All data is fully packed with
// no padding, and stride is ignored, and region must be NULL.
// If buf is not NULL, then src must be within the provided buffer. The
// operation is implied to have dramatically better performance, but
// requires correct flushing and fencing operations by the caller to deal
// with asynchronous host/GPU behavior. If any of these conditions are not
// met, undefined behavior will result.
void (*tex_upload)(struct ra *ra, struct ra_tex *tex,
const void *src, ptrdiff_t stride,
struct mp_rect *region, uint64_t flags,
struct ra_mapped_buffer *buf);
// Create a persistently mapped buffer for tex_upload.
// Optional, can be NULL or return NULL if unavailable.
struct ra_mapped_buffer *(*create_mapped_buffer)(struct ra *ra, size_t size);
void (*destroy_mapped_buffer)(struct ra *ra, struct ra_mapped_buffer *buf);
// Essentially a fence: once the GPU uses the mapping for read-access (e.g.
// by starting a texture upload), the host must not write to the mapped
// data until an internal object has been signalled. This call returns
// whether it was signalled yet. If true, write accesses are allowed again.
// Optional, only available if flush_mapping is.
bool (*poll_mapped_buffer)(struct ra *ra, struct ra_mapped_buffer *buf);
// Clear the dst with the given color (rgba) and within the given scissor.
// dst must have dst->params.render_dst==true. Content outside of the
// scissor is preserved.
void (*clear)(struct ra *ra, struct ra_tex *dst, float color[4],
struct mp_rect *scissor);
// Copy a sub-rectangle from one texture to another. The source/dest region
// is always within the texture bounds. Areas outside the dest region are
// preserved. The formats of the textures will be losely compatible (this
// probably has to be defined strictly). The dst texture can be a swapchain
// framebuffer, but src can not. Only 2D textures are supported.
// Both textures must have tex->params.render_dst==true (even src, which is
// an odd GL requirement).
// A rectangle with negative width or height means a flipped copy should be
// done. Coordinates are always in pixels.
// Optional. Only available if RA_CAP_BLIT is set (if it's not set, the must
// not be called, even if it's non-NULL).
void (*blit)(struct ra *ra, struct ra_tex *dst, struct ra_tex *src,
int dst_x, int dst_y, struct mp_rect *src_rc);
};
struct ra_tex *ra_tex_create(struct ra *ra, const struct ra_tex_params *params);
void ra_tex_free(struct ra *ra, struct ra_tex **tex);
const struct ra_format *ra_find_unorm_format(struct ra *ra,
int bytes_per_component,
int n_components);
const struct ra_format *ra_find_uint_format(struct ra *ra,
int bytes_per_component,
int n_components);
const struct ra_format *ra_find_float16_format(struct ra *ra, int n_components);
const struct ra_format *ra_find_named_format(struct ra *ra, const char *name);
struct ra_imgfmt_desc {
int num_planes;
const struct ra_format *planes[4];
// Chroma pixel size (1x1 is 4:4:4)
uint8_t chroma_w, chroma_h;
// Component storage size in bits (possibly padded). For formats with
// different sizes per component, this is arbitrary. For padded formats
// like P010 or YUV420P10, padding is included.
int component_bits;
// Like mp_regular_imgfmt.component_pad.
int component_pad;
// For each texture and each texture output (rgba order) describe what
// component it returns.
// The values are like the values in mp_regular_imgfmt_plane.components[].
// Access as components[plane_nr][component_index]. Set unused items to 0.
// For ra_format.luminance_alpha, this returns 1/2 ("rg") instead of 1/4
// ("ra"). the logic is that the texture format has 2 channels, thus the
// data must be returned in the first two components. The renderer fixes
// this later.
uint8_t components[4][4];
};
bool ra_get_imgfmt_desc(struct ra *ra, int imgfmt, struct ra_imgfmt_desc *out);
void ra_dump_tex_formats(struct ra *ra, int msgl);
void ra_dump_imgfmt_desc(struct ra *ra, const struct ra_imgfmt_desc *desc,
int msgl);
void ra_dump_img_formats(struct ra *ra, int msgl);